Alloc.cpp revision c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2ef
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);
33c7ecb9b57d4f7eaeeaedbd7955c6782f8b48ec6fCarl Shapiro    pthread_cond_init(&gDvm.gcHeapCond, NULL);
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
71e58a9b5d443cd3fcc22abc887cf0739a4b6bc145Jesse Wilsonbool dvmGcStartupClasses()
72ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro{
73e58a9b5d443cd3fcc22abc887cf0739a4b6bc145Jesse Wilson    ClassObject *klass = dvmFindSystemClass("Ljava/lang/Daemons;");
7471ae36cdf140e2dc06dd5b7727fdc625e4e94e08Carl Shapiro    if (klass == NULL) {
7571ae36cdf140e2dc06dd5b7727fdc625e4e94e08Carl Shapiro        return false;
76ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro    }
77e58a9b5d443cd3fcc22abc887cf0739a4b6bc145Jesse Wilson    Method *method = dvmFindDirectMethodByDescriptor(klass, "start", "()V");
7871ae36cdf140e2dc06dd5b7727fdc625e4e94e08Carl Shapiro    if (method == NULL) {
7971ae36cdf140e2dc06dd5b7727fdc625e4e94e08Carl Shapiro        return false;
80ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro    }
8171ae36cdf140e2dc06dd5b7727fdc625e4e94e08Carl Shapiro    Thread *self = dvmThreadSelf();
8271ae36cdf140e2dc06dd5b7727fdc625e4e94e08Carl Shapiro    assert(self != NULL);
8371ae36cdf140e2dc06dd5b7727fdc625e4e94e08Carl Shapiro    JValue unusedResult;
8471ae36cdf140e2dc06dd5b7727fdc625e4e94e08Carl Shapiro    dvmCallMethod(self, method, NULL, &unusedResult);
85ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro    return true;
86ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro}
87ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
897fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * Create a "stock instance" of an exception class.
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
917fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFaddenstatic Object* createStockException(const char* descriptor, const char* msg)
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
937fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    Thread* self = dvmThreadSelf();
947fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    StringObject* msgStr = NULL;
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* init;
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* obj;
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
997fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    /* find class, initialize if necessary */
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmFindSystemClass(descriptor);
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL) {
102c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Unable to find %s", descriptor);
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1067fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    init = dvmFindDirectMethodByDescriptor(clazz, "<init>",
1077fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            "(Ljava/lang/String;)V");
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (init == NULL) {
109c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Unable to find String-arg constructor for %s", descriptor);
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    obj = dvmAllocObject(clazz, ALLOC_DEFAULT);
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj == NULL)
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1177fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    if (msg == NULL) {
1187fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        msgStr = NULL;
1197fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    } else {
12081f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes        msgStr = dvmCreateStringFromCstr(msg);
1217fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        if (msgStr == NULL) {
122e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Could not allocate message string \"%s\"", msg);
1237fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            dvmReleaseTrackedAlloc(obj, self);
1247fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            return NULL;
1257fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        }
1267fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    }
1277fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue unused;
1297fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    dvmCallMethod(self, init, obj, &unused, msgStr);
1307fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    if (dvmCheckException(self)) {
1317fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        dvmReleaseTrackedAlloc((Object*) msgStr, self);
1327fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        dvmReleaseTrackedAlloc(obj, self);
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
1347fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    }
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1367fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    dvmReleaseTrackedAlloc((Object*) msgStr, self);     // okay if msgStr NULL
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return obj;
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1417fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * Create some "stock" exceptions.  These can be thrown when the system is
1427fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * too screwed up to allocate and initialize anything, or when we don't
1437fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * need a meaningful stack trace.
1447fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden *
1457fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * We can't do this during the initial startup because we need to execute
1467fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * the constructors.
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1481e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmCreateStockExceptions()
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Pre-allocate some throwables.  These need to be explicitly added
1527fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden     * to the GC's root set (see dvmHeapMarkRootSet()).
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1547fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    gDvm.outOfMemoryObj = createStockException("Ljava/lang/OutOfMemoryError;",
1557fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        "[memory exhausted]");
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(gDvm.outOfMemoryObj, NULL);
1577fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    gDvm.internalErrorObj = createStockException("Ljava/lang/InternalError;",
1587fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        "[pre-allocated]");
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(gDvm.internalErrorObj, NULL);
1607fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    gDvm.noClassDefFoundErrorObj =
1614c691d1a66c4c721dbc156b5e765edb49c7c67e4Andy McFadden        createStockException("Ljava/lang/NoClassDefFoundError;",
1624c691d1a66c4c721dbc156b5e765edb49c7c67e4Andy McFadden            "[generic]");
1637fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    dvmReleaseTrackedAlloc(gDvm.noClassDefFoundErrorObj, NULL);
1647fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden
1657fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    if (gDvm.outOfMemoryObj == NULL || gDvm.internalErrorObj == NULL ||
1667fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden        gDvm.noClassDefFoundErrorObj == NULL)
1677fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden    {
168e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Unable to create stock exceptions");
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create an instance of the specified class.
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL and throws an exception on failure.
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmAllocObject(ClassObject* clazz, int flags)
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* newObj;
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1853475f9cdb47a6d6f8ad2ce49bbc3af46bca92f09Carl Shapiro    assert(clazz != NULL);
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsClassInitialized(clazz) || dvmIsClassInitializing(clazz));
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* allocate on GC heap; memory is zeroed out */
189fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    newObj = (Object*)dvmMalloc(clazz->objectSize, flags);
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (newObj != NULL) {
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DVM_OBJECT_INIT(newObj, clazz);
1926af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden        dvmTrackAllocation(clazz, clazz->objectSize);   /* notify DDMS */
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return newObj;
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a copy of an object, for Object.clone().
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We use the size actually allocated, rather than obj->clazz->objectSize,
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because the latter doesn't work for array objects.
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2040f27ad70ce7a8e739cdf5870346af837e2b9b6c0Andy McFaddenObject* dvmCloneObject(Object* obj, int flags)
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsValidObject(obj));
207122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    ClassObject* clazz = obj->clazz;
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Class.java shouldn't let us get here (java.lang.Class is final
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and does not implement Clonable), but make extra sure.
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * A memcpy() clone will wreak havoc on a ClassObject's "innards".
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
213c6d2470eec726ae0ad95e4fd2d9d7da7cb2cdcbaDan Bornstein    assert(!dvmIsTheClassClass(clazz));
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
215122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    size_t size;
2166af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden    if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
217bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro        size = dvmArrayObjectSize((ArrayObject *)obj);
218bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro    } else {
2196af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden        size = clazz->objectSize;
220bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro    }
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
222122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    Object* copy = (Object*)dvmMalloc(size, flags);
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (copy == NULL)
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
226122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    DVM_OBJECT_INIT(copy, clazz);
227122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    size_t offset = sizeof(Object);
228122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    /* Copy instance data.  We assume memcpy copies by words. */
229122dac5b92c649b5d3182b163d7fce35e8c69d76Carl Shapiro    memcpy((char*)copy + offset, (char*)obj + offset, size - offset);
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23139721ef72fab792b97ec88aa068bb22d1426db23Carl Shapiro    /* Mark the clone as finalizable if appropriate. */
2326af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden    if (IS_CLASS_FLAG_SET(clazz, CLASS_ISFINALIZABLE)) {
2336af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden        dvmSetFinalizable(copy);
2346af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden    }
2356af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden
2366af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden    dvmTrackAllocation(clazz, size);    /* notify DDMS */
2376af2ddd107842c3737c04c37343cac9be17f4209Andy McFadden
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return copy;
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Track an object that was allocated internally and isn't yet part of the
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM root set.
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We could do this per-thread or globally.  If it's global we don't have
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to do the thread lookup but we do have to synchronize access to the list.
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
249bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden * "obj" must not be NULL.
250bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden *
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: "obj" is not a fully-formed object; in particular, obj->clazz will
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * usually be NULL since we're being called from dvmMalloc().
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmAddTrackedAlloc(Object* obj, Thread* self)
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self == NULL)
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self = dvmThreadSelf();
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
259bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden    assert(obj != NULL);
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self != NULL);
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmAddToReferenceTable(&self->internalLocalRefTable, obj)) {
262c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("threadid=%d: unable to add %p to internal ref table",
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->threadId, obj);
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDumpThread(self, false);
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Stop tracking an object.
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We allow attempts to delete NULL "obj" so that callers don't have to wrap
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calls with "if != NULL".
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmReleaseTrackedAlloc(Object* obj, Thread* self)
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj == NULL)
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self == NULL)
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self = dvmThreadSelf();
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self != NULL);
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmRemoveFromReferenceTable(&self->internalLocalRefTable,
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->internalLocalRefTable.table, obj))
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
287c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("threadid=%d: failed to remove %p from internal ref table",
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->threadId, obj);
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Explicitly initiate garbage collection.
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2971e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmCollectGarbage()
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
299821fd06d4dc53f23e82074fcc8d8ffdc32ea3a51Carl Shapiro    if (gDvm.disableExplicitGc) {
300821fd06d4dc53f23e82074fcc8d8ffdc32ea3a51Carl Shapiro        return;
301821fd06d4dc53f23e82074fcc8d8ffdc32ea3a51Carl Shapiro    }
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockHeap();
303039167e7894ae16880f51fa0b4d44316318aae1eCarl Shapiro    dvmWaitForConcurrentGcToComplete();
304cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro    dvmCollectGarbageInternal(GC_EXPLICIT);
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockHeap();
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
30741eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro
30850e5fd5984c9b0a6f0927ed5ddf13bde40e338c7Carl Shapirostruct CountContext {
30941eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    const ClassObject *clazz;
31041eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    size_t count;
31150e5fd5984c9b0a6f0927ed5ddf13bde40e338c7Carl Shapiro};
31241eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro
3130d92a4072c00434e95a03642a4944acf81a81cc3Carl Shapirostatic void countInstancesOfClassCallback(Object *obj, void *arg)
31441eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro{
315fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    CountContext *ctx = (CountContext *)arg;
31641eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    assert(ctx != NULL);
31757ee270b755271166b2349321e5b8b5457731dd7Carl Shapiro    if (obj->clazz == ctx->clazz) {
31857ee270b755271166b2349321e5b8b5457731dd7Carl Shapiro        ctx->count += 1;
31941eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    }
32041eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro}
32141eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro
32241eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapirosize_t dvmCountInstancesOfClass(const ClassObject *clazz)
32341eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro{
324f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    CountContext ctx = { clazz, 0 };
32541eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    dvmLockHeap();
326a4313feb23dd454905a3297bdc9ba745e6066a16Carl Shapiro    HeapBitmap *bitmap = dvmHeapSourceGetLiveBits();
32741eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    dvmHeapBitmapWalk(bitmap, countInstancesOfClassCallback, &ctx);
32841eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    dvmUnlockHeap();
32941eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro    return ctx.count;
33041eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro}
331f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro
3320d92a4072c00434e95a03642a4944acf81a81cc3Carl Shapirostatic void countAssignableInstancesOfClassCallback(Object *obj, void *arg)
333f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro{
334fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    CountContext *ctx = (CountContext *)arg;
335f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    assert(ctx != NULL);
3362efc12622b0a98cde09447f2bfeb47667c5dd192Carl Shapiro    if (obj->clazz != NULL && dvmInstanceof(obj->clazz, ctx->clazz)) {
337f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro        ctx->count += 1;
338f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    }
339f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro}
340f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro
341f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapirosize_t dvmCountAssignableInstancesOfClass(const ClassObject *clazz)
342f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro{
343f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    CountContext ctx = { clazz, 0 };
344f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    dvmLockHeap();
345a4313feb23dd454905a3297bdc9ba745e6066a16Carl Shapiro    HeapBitmap *bitmap = dvmHeapSourceGetLiveBits();
346f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    dvmHeapBitmapWalk(bitmap, countAssignableInstancesOfClassCallback, &ctx);
347f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    dvmUnlockHeap();
348f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro    return ctx.count;
349f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro}
3502494c5038e668add68c74dea83aca05187a89e7cCarl Shapiro
3512494c5038e668add68c74dea83aca05187a89e7cCarl Shapirobool dvmIsHeapAddress(void *address)
3522494c5038e668add68c74dea83aca05187a89e7cCarl Shapiro{
35321fefbaa3874c42f8a017c4794add2d7c337643aElliott Hughes    return address != NULL && (((uintptr_t) address & (8-1)) == 0);
3542494c5038e668add68c74dea83aca05187a89e7cCarl Shapiro}
355dc9e44cc0af797679822484d88ef76bff15ffc98Carl Shapiro
356dc9e44cc0af797679822484d88ef76bff15ffc98Carl Shapirobool dvmIsNonMovingObject(const Object* object)
357dc9e44cc0af797679822484d88ef76bff15ffc98Carl Shapiro{
358dc9e44cc0af797679822484d88ef76bff15ffc98Carl Shapiro    return true;
359dc9e44cc0af797679822484d88ef76bff15ffc98Carl Shapiro}
360