Alloc.cpp revision 50e5fd5984c9b0a6f0927ed5ddf13bde40e338c7
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Garbage-collecting memory allocator.
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/Heap.h"
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapInternal.h"
2241eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro#include "alloc/HeapSource.h"
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the GC universe.
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're currently using a memory-mapped arena to keep things off of the
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * main heap.  This needs to be replaced with something real.
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
301e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmGcStartup()
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInitMutex(&gDvm.gcHeapLock);
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmHeapStartup();
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Post-zygote heap initialization, including starting
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the HeapWorker thread.
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
411e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmGcStartupAfterZygote()
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
43ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro    return dvmHeapStartupAfterZygote();
44ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro}
45ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro
46ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro/*
47ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * Shutdown the threads internal to the garbage collector.
48ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro */
491e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmGcThreadShutdown()
50ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro{
51ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro    dvmHeapThreadShutdown();
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shut the GC down.
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
571e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmGcShutdown()
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //TODO: grab and destroy the lock
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapShutdown();
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Do any last-minute preparation before we call fork() for the first time.
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
661e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmGcPreZygoteFork()
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmHeapSourceStartupBeforeFork();
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
711e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmGcStartupClasses()
72ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro{
73ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro    {
74ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        const char *klassName = "Ljava/lang/ref/ReferenceQueueThread;";
75ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        ClassObject *klass = dvmFindSystemClass(klassName);
76ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        if (klass == NULL) {
77ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro            return false;
78ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        }
79ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        const char *methodName = "startReferenceQueue";
80ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        Method *method = dvmFindDirectMethodByDescriptor(klass, methodName, "()V");
81ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        if (method == NULL) {
82ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro            return false;
83ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        }
84ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        Thread *self = dvmThreadSelf();
85ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        assert(self != NULL);
86ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        JValue unusedResult;
87ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        dvmCallMethod(self, method, NULL, &unusedResult);
88ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro    }
89ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro    {
90ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        const char *klassName = "Ljava/lang/FinalizerThread;";
91ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        ClassObject *klass = dvmFindSystemClass(klassName);
92ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        if (klass == NULL) {
93ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro            return false;
94ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        }
95ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        const char *methodName = "startFinalizer";
96ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        Method *method = dvmFindDirectMethodByDescriptor(klass, methodName, "()V");
97ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        if (method == NULL) {
98ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro            return false;
99ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        }
100ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        Thread *self = dvmThreadSelf();
101ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        assert(self != NULL);
102ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        JValue unusedResult;
103ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro        dvmCallMethod(self, method, NULL, &unusedResult);
104ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro    }
105ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro
106ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro    return true;
107ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro}
108ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1107fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * Create a "stock instance" of an exception class.
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1127fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFaddenstatic Object* createStockException(const char* descriptor, const char* msg)
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1147fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    Thread* self = dvmThreadSelf();
1157fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    StringObject* msgStr = NULL;
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* init;
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* obj;
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1207fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    /* find class, initialize if necessary */
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmFindSystemClass(descriptor);
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL) {
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to find %s\n", descriptor);
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1277fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    init = dvmFindDirectMethodByDescriptor(clazz, "<init>",
1287fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            "(Ljava/lang/String;)V");
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (init == NULL) {
1307fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        LOGE("Unable to find String-arg constructor for %s\n", descriptor);
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    obj = dvmAllocObject(clazz, ALLOC_DEFAULT);
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj == NULL)
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1387fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    if (msg == NULL) {
1397fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        msgStr = NULL;
1407fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    } else {
14181f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes        msgStr = dvmCreateStringFromCstr(msg);
1427fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        if (msgStr == NULL) {
1437fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            LOGW("Could not allocate message string \"%s\"\n", msg);
1447fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            dvmReleaseTrackedAlloc(obj, self);
1457fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            return NULL;
1467fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        }
1477fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    }
1487fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue unused;
1507fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    dvmCallMethod(self, init, obj, &unused, msgStr);
1517fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    if (dvmCheckException(self)) {
1527fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        dvmReleaseTrackedAlloc((Object*) msgStr, self);
1537fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        dvmReleaseTrackedAlloc(obj, self);
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
1557fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    }
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1577fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    dvmReleaseTrackedAlloc((Object*) msgStr, self);     // okay if msgStr NULL
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return obj;
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1627fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * Create some "stock" exceptions.  These can be thrown when the system is
1637fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * too screwed up to allocate and initialize anything, or when we don't
1647fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * need a meaningful stack trace.
1657fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden *
1667fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * We can't do this during the initial startup because we need to execute
1677fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * the constructors.
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1691e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmCreateStockExceptions()
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Pre-allocate some throwables.  These need to be explicitly added
1737fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden     * to the GC's root set (see dvmHeapMarkRootSet()).
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1757fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    gDvm.outOfMemoryObj = createStockException("Ljava/lang/OutOfMemoryError;",
1767fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        "[memory exhausted]");
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(gDvm.outOfMemoryObj, NULL);
1787fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    gDvm.internalErrorObj = createStockException("Ljava/lang/InternalError;",
1797fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        "[pre-allocated]");
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(gDvm.internalErrorObj, NULL);
1817fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    gDvm.noClassDefFoundErrorObj =
1824c691d1a66c4c721dbc156b5e765edb49c7c67e4Andy McFadden        createStockException("Ljava/lang/NoClassDefFoundError;",
1834c691d1a66c4c721dbc156b5e765edb49c7c67e4Andy McFadden            "[generic]");
1847fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    dvmReleaseTrackedAlloc(gDvm.noClassDefFoundErrorObj, NULL);
1857fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden
1867fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    if (gDvm.outOfMemoryObj == NULL || gDvm.internalErrorObj == NULL ||
1877fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        gDvm.noClassDefFoundErrorObj == NULL)
1887fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    {
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Unable to create stock exceptions\n");
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create an instance of the specified class.
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL and throws an exception on failure.
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmAllocObject(ClassObject* clazz, int flags)
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* newObj;
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2063475f9cdb47a6d6f8ad2ce49bbc3af46bca92f09Carl Shapiro    assert(clazz != NULL);
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsClassInitialized(clazz) || dvmIsClassInitializing(clazz));
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* allocate on GC heap; memory is zeroed out */
210fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    newObj = (Object*)dvmMalloc(clazz->objectSize, flags);
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (newObj != NULL) {
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DVM_OBJECT_INIT(newObj, clazz);
2136af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden        dvmTrackAllocation(clazz, clazz->objectSize);   /* notify DDMS */
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return newObj;
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a copy of an object, for Object.clone().
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We use the size actually allocated, rather than obj->clazz->objectSize,
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because the latter doesn't work for array objects.
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2250f27ad70ce7a8e739cdf5870346af837e2b9b6c0Andy McFaddenObject* dvmCloneObject(Object* obj, int flags)
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsValidObject(obj));
228122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    ClassObject* clazz = obj->clazz;
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Class.java shouldn't let us get here (java.lang.Class is final
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and does not implement Clonable), but make extra sure.
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * A memcpy() clone will wreak havoc on a ClassObject's "innards".
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
234c6d2470eec726ae0ad95e4fd2d9d7da7cb2cdcbaDan Bornstein    assert(!dvmIsTheClassClass(clazz));
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
236122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    size_t size;
2376af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden    if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
238bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro        size = dvmArrayObjectSize((ArrayObject *)obj);
239bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro    } else {
2406af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden        size = clazz->objectSize;
241bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro    }
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    Object* copy = (Object*)dvmMalloc(size, flags);
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (copy == NULL)
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
247122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    DVM_OBJECT_INIT(copy, clazz);
248122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    size_t offset = sizeof(Object);
249122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    /* Copy instance data.  We assume memcpy copies by words. */
250122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    memcpy((char*)copy + offset, (char*)obj + offset, size - offset);
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
25239721ef72fab792b97ec88aa068bb22d1426db23Carl Shapiro    /* Mark the clone as finalizable if appropriate. */
2536af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden    if (IS_CLASS_FLAG_SET(clazz, CLASS_ISFINALIZABLE)) {
2546af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden        dvmSetFinalizable(copy);
2556af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden    }
2566af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden
2576af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden    dvmTrackAllocation(clazz, size);    /* notify DDMS */
2586af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return copy;
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Track an object that was allocated internally and isn't yet part of the
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM root set.
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We could do this per-thread or globally.  If it's global we don't have
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to do the thread lookup but we do have to synchronize access to the list.
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
270bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden * "obj" must not be NULL.
271bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden *
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: "obj" is not a fully-formed object; in particular, obj->clazz will
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * usually be NULL since we're being called from dvmMalloc().
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmAddTrackedAlloc(Object* obj, Thread* self)
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self == NULL)
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self = dvmThreadSelf();
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden    assert(obj != NULL);
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self != NULL);
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmAddToReferenceTable(&self->internalLocalRefTable, obj)) {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("threadid=%d: unable to add %p to internal ref table\n",
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->threadId, obj);
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDumpThread(self, false);
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Stop tracking an object.
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We allow attempts to delete NULL "obj" so that callers don't have to wrap
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calls with "if != NULL".
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmReleaseTrackedAlloc(Object* obj, Thread* self)
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj == NULL)
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self == NULL)
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self = dvmThreadSelf();
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self != NULL);
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmRemoveFromReferenceTable(&self->internalLocalRefTable,
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->internalLocalRefTable.table, obj))
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("threadid=%d: failed to remove %p from internal ref table\n",
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->threadId, obj);
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Explicitly initiate garbage collection.
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3181e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmCollectGarbage()
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
320821fd06d4dc53f23e82074fcc8d8ffdc32ea3a51Carl Shapiro    if (gDvm.disableExplicitGc) {
321821fd06d4dc53f23e82074fcc8d8ffdc32ea3a51Carl Shapiro        return;
322821fd06d4dc53f23e82074fcc8d8ffdc32ea3a51Carl Shapiro    }
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockHeap();
324039167e7894ae16880f51fa0b4d44316318aae1eCarl Shapiro    dvmWaitForConcurrentGcToComplete();
325cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro    dvmCollectGarbageInternal(GC_EXPLICIT);
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockHeap();
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
32841eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro
32950e5fd5984c9b0a6f0927ed5ddf13bde40e338c7Carl Shapirostruct CountContext {
33041eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    const ClassObject *clazz;
33141eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    size_t count;
33250e5fd5984c9b0a6f0927ed5ddf13bde40e338c7Carl Shapiro};
33341eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro
33457ee270b755271166b2349321e5b8b5457731dd7Carl Shapirostatic void countInstancesOfClassCallback(void *ptr, void *arg)
33541eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro{
336fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    CountContext *ctx = (CountContext *)arg;
337fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    const Object *obj = (const Object *)ptr;
33841eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro
33941eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    assert(ctx != NULL);
34057ee270b755271166b2349321e5b8b5457731dd7Carl Shapiro    if (obj->clazz == ctx->clazz) {
34157ee270b755271166b2349321e5b8b5457731dd7Carl Shapiro        ctx->count += 1;
34241eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    }
34341eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro}
34441eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro
34541eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapirosize_t dvmCountInstancesOfClass(const ClassObject *clazz)
34641eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro{
347f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    CountContext ctx = { clazz, 0 };
34841eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    dvmLockHeap();
349a4313feb23dd454905a3297bdc9ba745e6066a16Carl Shapiro    HeapBitmap *bitmap = dvmHeapSourceGetLiveBits();
35041eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    dvmHeapBitmapWalk(bitmap, countInstancesOfClassCallback, &ctx);
35141eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    dvmUnlockHeap();
35241eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    return ctx.count;
35341eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro}
354f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro
355f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapirostatic void countAssignableInstancesOfClassCallback(void *ptr, void *arg)
356f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro{
357fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    CountContext *ctx = (CountContext *)arg;
358fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    const Object *obj = (const Object *)ptr;
359f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro
360f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    assert(ctx != NULL);
3612efc12622b0a98cde09447f2bfeb47667c5dd192Carl Shapiro    if (obj->clazz != NULL && dvmInstanceof(obj->clazz, ctx->clazz)) {
362f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro        ctx->count += 1;
363f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    }
364f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro}
365f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro
366f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapirosize_t dvmCountAssignableInstancesOfClass(const ClassObject *clazz)
367f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro{
368f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    CountContext ctx = { clazz, 0 };
369f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    dvmLockHeap();
370a4313feb23dd454905a3297bdc9ba745e6066a16Carl Shapiro    HeapBitmap *bitmap = dvmHeapSourceGetLiveBits();
371f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    dvmHeapBitmapWalk(bitmap, countAssignableInstancesOfClassCallback, &ctx);
372f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    dvmUnlockHeap();
373f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    return ctx.count;
374f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro}
3752494c5038e668add68c74dea83aca05187a89e7cCarl Shapiro
3762494c5038e668add68c74dea83aca05187a89e7cCarl Shapirobool dvmIsHeapAddress(void *address)
3772494c5038e668add68c74dea83aca05187a89e7cCarl Shapiro{
3782494c5038e668add68c74dea83aca05187a89e7cCarl Shapiro    return dvmHeapSourceContainsAddress(address);
3792494c5038e668add68c74dea83aca05187a89e7cCarl Shapiro}
380