Alloc.cpp revision 039167e7894ae16880f51fa0b4d44316318aae1e
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 24a5a46928b486725ed624fa0ae6c469645a209e87Carl Shapiro#if WITH_HPROF_STACK 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "hprof/Hprof.h" 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the GC universe. 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're currently using a memory-mapped arena to keep things off of the 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * main heap. This needs to be replaced with something real. 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmGcStartup(void) 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInitMutex(&gDvm.gcHeapLock); 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return dvmHeapStartup(); 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Post-zygote heap initialization, including starting 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the HeapWorker thread. 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmGcStartupAfterZygote(void) 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmHeapWorkerStartup()) { 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 51ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro return dvmHeapStartupAfterZygote(); 52ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro} 53ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 54ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro/* 55ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * Shutdown the threads internal to the garbage collector. 56ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro */ 57ec805eaed940e40212e85b58b163c7649feaca56Carl Shapirovoid dvmGcThreadShutdown(void) 58ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro{ 59ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmHeapWorkerShutdown(); 60ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmHeapThreadShutdown(); 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shut the GC down. 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmGcShutdown(void) 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //TODO: grab and destroy the lock 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapShutdown(); 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Do any last-minute preparation before we call fork() for the first time. 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmGcPreZygoteFork(void) 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return dvmHeapSourceStartupBeforeFork(); 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 817fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * Create a "stock instance" of an exception class. 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 837fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFaddenstatic Object* createStockException(const char* descriptor, const char* msg) 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 857fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden Thread* self = dvmThreadSelf(); 867fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden StringObject* msgStr = NULL; 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method* init; 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* obj; 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 917fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden /* find class, initialize if necessary */ 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = dvmFindSystemClass(descriptor); 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) { 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Unable to find %s\n", descriptor); 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 987fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden init = dvmFindDirectMethodByDescriptor(clazz, "<init>", 997fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden "(Ljava/lang/String;)V"); 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (init == NULL) { 1017fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden LOGE("Unable to find String-arg constructor for %s\n", descriptor); 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project obj = dvmAllocObject(clazz, ALLOC_DEFAULT); 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj == NULL) 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1097fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden if (msg == NULL) { 1107fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden msgStr = NULL; 1117fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden } else { 11281f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes msgStr = dvmCreateStringFromCstr(msg); 1137fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden if (msgStr == NULL) { 1147fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden LOGW("Could not allocate message string \"%s\"\n", msg); 1157fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden dvmReleaseTrackedAlloc(obj, self); 1167fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden return NULL; 1177fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden } 1187fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden } 1197fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue unused; 1217fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden dvmCallMethod(self, init, obj, &unused, msgStr); 1227fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden if (dvmCheckException(self)) { 1237fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden dvmReleaseTrackedAlloc((Object*) msgStr, self); 1247fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden dvmReleaseTrackedAlloc(obj, self); 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 1267fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden } 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1287fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden dvmReleaseTrackedAlloc((Object*) msgStr, self); // okay if msgStr NULL 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return obj; 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1337fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * Create some "stock" exceptions. These can be thrown when the system is 1347fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * too screwed up to allocate and initialize anything, or when we don't 1357fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * need a meaningful stack trace. 1367fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * 1377fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * We can't do this during the initial startup because we need to execute 1387fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * the constructors. 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1407fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFaddenbool dvmCreateStockExceptions(void) 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pre-allocate some throwables. These need to be explicitly added 1447fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden * to the GC's root set (see dvmHeapMarkRootSet()). 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1467fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden gDvm.outOfMemoryObj = createStockException("Ljava/lang/OutOfMemoryError;", 1477fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden "[memory exhausted]"); 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(gDvm.outOfMemoryObj, NULL); 1497fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden gDvm.internalErrorObj = createStockException("Ljava/lang/InternalError;", 1507fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden "[pre-allocated]"); 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(gDvm.internalErrorObj, NULL); 1527fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden gDvm.noClassDefFoundErrorObj = 1534c691d1a66c4c721dbc156b5e765edb49c7c67e4Andy McFadden createStockException("Ljava/lang/NoClassDefFoundError;", 1544c691d1a66c4c721dbc156b5e765edb49c7c67e4Andy McFadden "[generic]"); 1557fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden dvmReleaseTrackedAlloc(gDvm.noClassDefFoundErrorObj, NULL); 1567fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden 1577fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden if (gDvm.outOfMemoryObj == NULL || gDvm.internalErrorObj == NULL || 1587fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden gDvm.noClassDefFoundErrorObj == NULL) 1597fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden { 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Unable to create stock exceptions\n"); 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create an instance of the specified class. 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL and throws an exception on failure. 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmAllocObject(ClassObject* clazz, int flags) 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* newObj; 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsClassInitialized(clazz) || dvmIsClassInitializing(clazz)); 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (IS_CLASS_FLAG_SET(clazz, CLASS_ISFINALIZABLE)) { 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project flags |= ALLOC_FINALIZABLE; 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* allocate on GC heap; memory is zeroed out */ 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newObj = dvmMalloc(clazz->objectSize, flags); 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (newObj != NULL) { 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DVM_OBJECT_INIT(newObj, clazz); 187a5a46928b486725ed624fa0ae6c469645a209e87Carl Shapiro#if WITH_HPROF_STACK 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hprofFillInStackTrace(newObj); 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmTrackAllocation(clazz, clazz->objectSize); 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return newObj; 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a copy of an object, for Object.clone(). 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We use the size actually allocated, rather than obj->clazz->objectSize, 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because the latter doesn't work for array objects. 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmCloneObject(Object* obj) 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* copy; 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int size; 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int flags; 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsValidObject(obj)); 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Class.java shouldn't let us get here (java.lang.Class is final 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and does not implement Clonable), but make extra sure. 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * A memcpy() clone will wreak havoc on a ClassObject's "innards". 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj->clazz != gDvm.classJavaLangClass); 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISFINALIZABLE)) 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project flags = ALLOC_DEFAULT | ALLOC_FINALIZABLE; 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project flags = ALLOC_DEFAULT; 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 221bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) { 222bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro size = dvmArrayObjectSize((ArrayObject *)obj); 223bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro } else { 224bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro size = obj->clazz->objectSize; 225bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro } 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project copy = dvmMalloc(size, flags); 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (copy == NULL) 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 230a5a46928b486725ed624fa0ae6c469645a209e87Carl Shapiro#if WITH_HPROF_STACK 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hprofFillInStackTrace(copy); 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmTrackAllocation(obj->clazz, size); 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(copy, obj, size); 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DVM_LOCK_INIT(©->lock); 237364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes dvmWriteBarrierObject(copy); 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return copy; 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Track an object that was allocated internally and isn't yet part of the 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM root set. 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We could do this per-thread or globally. If it's global we don't have 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to do the thread lookup but we do have to synchronize access to the list. 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 250bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden * "obj" must not be NULL. 251bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden * 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: "obj" is not a fully-formed object; in particular, obj->clazz will 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * usually be NULL since we're being called from dvmMalloc(). 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmAddTrackedAlloc(Object* obj, Thread* self) 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self == NULL) 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self = dvmThreadSelf(); 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 260bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden assert(obj != NULL); 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self != NULL); 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmAddToReferenceTable(&self->internalLocalRefTable, obj)) { 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("threadid=%d: unable to add %p to internal ref table\n", 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->threadId, obj); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Stop tracking an object. 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We allow attempts to delete NULL "obj" so that callers don't have to wrap 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calls with "if != NULL". 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmReleaseTrackedAlloc(Object* obj, Thread* self) 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj == NULL) 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self == NULL) 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self = dvmThreadSelf(); 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self != NULL); 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmRemoveFromReferenceTable(&self->internalLocalRefTable, 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->internalLocalRefTable.table, obj)) 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("threadid=%d: failed to remove %p from internal ref table\n", 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->threadId, obj); 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 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/* 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Explicitly initiate garbage collection. 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCollectGarbage(bool collectSoftReferences) 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockHeap(); 301039167e7894ae16880f51fa0b4d44316318aae1eCarl Shapiro dvmWaitForConcurrentGcToComplete(); 3021b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes dvmCollectGarbageInternal(collectSoftReferences, GC_EXPLICIT); 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockHeap(); 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 30541eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro 30641eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapirotypedef struct { 30741eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro const ClassObject *clazz; 30841eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro size_t count; 309f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro} CountContext; 31041eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro 31157ee270b755271166b2349321e5b8b5457731dd7Carl Shapirostatic void countInstancesOfClassCallback(void *ptr, void *arg) 31241eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro{ 313f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro CountContext *ctx = arg; 31457ee270b755271166b2349321e5b8b5457731dd7Carl Shapiro const Object *obj = ptr; 31541eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro 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 HeapBitmap *bitmap = dvmHeapSourceGetLiveBits(); 32641eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro dvmLockHeap(); 32741eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro dvmHeapBitmapWalk(bitmap, countInstancesOfClassCallback, &ctx); 32841eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro dvmUnlockHeap(); 32941eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro return ctx.count; 33041eb6e988193a1c6b331c7c208bf8dd74f96d773Carl Shapiro} 331f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro 332f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapirostatic void countAssignableInstancesOfClassCallback(void *ptr, void *arg) 333f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro{ 334f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro CountContext *ctx = arg; 335f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro const Object *obj = ptr; 336f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro 337f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro assert(ctx != NULL); 338f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro if (dvmInstanceof(obj->clazz, ctx->clazz)) { 339f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro ctx->count += 1; 340f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro } 341f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro} 342f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro 343f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapirosize_t dvmCountAssignableInstancesOfClass(const ClassObject *clazz) 344f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro{ 345f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro CountContext ctx = { clazz, 0 }; 346f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro HeapBitmap *bitmap = dvmHeapSourceGetLiveBits(); 347f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro dvmLockHeap(); 348f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro dvmHeapBitmapWalk(bitmap, countAssignableInstancesOfClassCallback, &ctx); 349f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro dvmUnlockHeap(); 350f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro return ctx.count; 351f331a60b2a7ad79c2ecb0ba638f66bae1f37eb6cCarl Shapiro} 352