Alloc.cpp revision 2494c5038e668add68c74dea83aca05187a89e7c
160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky/* 260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * Copyright (C) 2008 The Android Open Source Project 360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * 460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * Licensed under the Apache License, Version 2.0 (the "License"); 560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * you may not use this file except in compliance with the License. 660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * You may obtain a copy of the License at 760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * 860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * http://www.apache.org/licenses/LICENSE-2.0 960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * 1060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * Unless required by applicable law or agreed to in writing, software 1160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * distributed under the License is distributed on an "AS IS" BASIS, 1260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * See the License for the specific language governing permissions and 1460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * limitations under the License. 1560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky */ 1660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky/* 1760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * Garbage-collecting memory allocator. 1860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky */ 1960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky#include "Dalvik.h" 202e402d5b5f2fce8bfe29509cc771b9919946003bEli Bendersky#include "alloc/Heap.h" 212e402d5b5f2fce8bfe29509cc771b9919946003bEli Bendersky#include "alloc/HeapInternal.h" 2260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky#include "alloc/HeapSource.h" 2360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 2460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky/* 2560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * Initialize the GC universe. 26ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky * 2760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * We're currently using a memory-mapped arena to keep things off of the 288a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky * main heap. This needs to be replaced with something real. 298a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky */ 308a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Benderskybool dvmGcStartup(void) 3160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky{ 3260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmInitMutex(&gDvm.gcHeapLock); 3360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 34ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky return dvmHeapStartup(); 3560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky} 3660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 37ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky/* 38ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky * Post-zygote heap initialization, including starting 39ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky * the HeapWorker thread. 4060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky */ 41ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Benderskybool dvmGcStartupAfterZygote(void) 42ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky{ 4360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky if (!dvmHeapWorkerStartup()) { 44ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky return false; 45ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky } 4660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky return dvmHeapStartupAfterZygote(); 4760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky} 4860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 4974b3c8da4800c7e8ba8f019879db29738ecc5f74Benjamin Kramer/* 502e402d5b5f2fce8bfe29509cc771b9919946003bEli Bendersky * Shutdown the threads internal to the garbage collector. 5160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky */ 5260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskyvoid dvmGcThreadShutdown(void) 5360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky{ 5460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmHeapWorkerShutdown(); 5560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmHeapThreadShutdown(); 5660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky} 5760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 5860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky/* 5960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * Shut the GC down. 6060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky */ 61ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Benderskyvoid dvmGcShutdown(void) 6260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky{ 638a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky //TODO: grab and destroy the lock 648a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky dvmHeapShutdown(); 658a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky} 6660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 6790e01ac0ea5bdc6dd6bccd9c59c3acb04e339666NAKAMURA Takumi/* 6890e01ac0ea5bdc6dd6bccd9c59c3acb04e339666NAKAMURA Takumi * Do any last-minute preparation before we call fork() for the first time. 6990e01ac0ea5bdc6dd6bccd9c59c3acb04e339666NAKAMURA Takumi */ 7060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskybool dvmGcPreZygoteFork(void) 7160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky{ 720b821eff4c9c8d3b7ac872691bc453337ad3d03aDavid Tweed return dvmHeapSourceStartupBeforeFork(); 730b821eff4c9c8d3b7ac872691bc453337ad3d03aDavid Tweed} 740b821eff4c9c8d3b7ac872691bc453337ad3d03aDavid Tweed 7560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky/* 7660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * Create a "stock instance" of an exception class. 7760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky */ 7860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskystatic Object* createStockException(const char* descriptor, const char* msg) 7960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky{ 8060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky Thread* self = dvmThreadSelf(); 81ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky StringObject* msgStr = NULL; 8260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky ClassObject* clazz; 83ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky Method* init; 8460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky Object* obj; 8560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 8660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky /* find class, initialize if necessary */ 8760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky clazz = dvmFindSystemClass(descriptor); 8860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky if (clazz == NULL) { 8960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky LOGE("Unable to find %s\n", descriptor); 9060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky return NULL; 9160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky } 922e402d5b5f2fce8bfe29509cc771b9919946003bEli Bendersky 9360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky init = dvmFindDirectMethodByDescriptor(clazz, "<init>", 9460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky "(Ljava/lang/String;)V"); 9560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky if (init == NULL) { 9660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky LOGE("Unable to find String-arg constructor for %s\n", descriptor); 9760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky return NULL; 98ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky } 99ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky 10060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky obj = dvmAllocObject(clazz, ALLOC_DEFAULT); 10160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky if (obj == NULL) 102ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky return NULL; 10360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 1048a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky if (msg == NULL) { 1058a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky msgStr = NULL; 1068a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky } else { 10760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky msgStr = dvmCreateStringFromCstr(msg); 10890e01ac0ea5bdc6dd6bccd9c59c3acb04e339666NAKAMURA Takumi if (msgStr == NULL) { 109d9a8d43ed3e7c6c32f52ab5d0f627f7b1cdb6aacNAKAMURA Takumi LOGW("Could not allocate message string \"%s\"\n", msg); 11060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmReleaseTrackedAlloc(obj, self); 111d9a8d43ed3e7c6c32f52ab5d0f627f7b1cdb6aacNAKAMURA Takumi return NULL; 1128ff0631967c64d51b193b862aa0a6f1e8eb06f78NAKAMURA Takumi } 1138ff0631967c64d51b193b862aa0a6f1e8eb06f78NAKAMURA Takumi } 11460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 115b2ac7c09b17efadea2a9f90f45801d9d2ee687aaEli Bendersky JValue unused; 116b2ac7c09b17efadea2a9f90f45801d9d2ee687aaEli Bendersky dvmCallMethod(self, init, obj, &unused, msgStr); 117b2ac7c09b17efadea2a9f90f45801d9d2ee687aaEli Bendersky if (dvmCheckException(self)) { 11860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmReleaseTrackedAlloc((Object*) msgStr, self); 11960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmReleaseTrackedAlloc(obj, self); 12060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky return NULL; 12160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky } 12260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 12360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmReleaseTrackedAlloc((Object*) msgStr, self); // okay if msgStr NULL 124ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky return obj; 125ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky} 12660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 12760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky/* 12860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * Create some "stock" exceptions. These can be thrown when the system is 12960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * too screwed up to allocate and initialize anything, or when we don't 13060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * need a meaningful stack trace. 13174b3c8da4800c7e8ba8f019879db29738ecc5f74Benjamin Kramer * 13260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * We can't do this during the initial startup because we need to execute 13360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * the constructors. 134ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky */ 13560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskybool dvmCreateStockExceptions(void) 13660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky{ 13760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky /* 138ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky * Pre-allocate some throwables. These need to be explicitly added 13960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * to the GC's root set (see dvmHeapMarkRootSet()). 14060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky */ 14160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky gDvm.outOfMemoryObj = createStockException("Ljava/lang/OutOfMemoryError;", 14260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky "[memory exhausted]"); 14360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmReleaseTrackedAlloc(gDvm.outOfMemoryObj, NULL); 14460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky gDvm.internalErrorObj = createStockException("Ljava/lang/InternalError;", 14560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky "[pre-allocated]"); 14660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmReleaseTrackedAlloc(gDvm.internalErrorObj, NULL); 14760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky gDvm.noClassDefFoundErrorObj = 14860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky createStockException("Ljava/lang/NoClassDefFoundError;", 14960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky "[generic]"); 15060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmReleaseTrackedAlloc(gDvm.noClassDefFoundErrorObj, NULL); 15160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 15260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky if (gDvm.outOfMemoryObj == NULL || gDvm.internalErrorObj == NULL || 15360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky gDvm.noClassDefFoundErrorObj == NULL) 15460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky { 15560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky LOGW("Unable to create stock exceptions\n"); 15660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky return false; 15760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky } 15860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 15960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky return true; 16060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky} 16160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 16260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 16360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky/* 16460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * Create an instance of the specified class. 16560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * 16660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * Returns NULL and throws an exception on failure. 16760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky */ 16860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli BenderskyObject* dvmAllocObject(ClassObject* clazz, int flags) 16960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky{ 17060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky Object* newObj; 17160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 17260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky assert(dvmIsClassInitialized(clazz) || dvmIsClassInitializing(clazz)); 17360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 17460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky /* allocate on GC heap; memory is zeroed out */ 17560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky newObj = (Object*)dvmMalloc(clazz->objectSize, flags); 17660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky if (newObj != NULL) { 17760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky DVM_OBJECT_INIT(newObj, clazz); 17860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmTrackAllocation(clazz, clazz->objectSize); /* notify DDMS */ 17960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky } 18060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 18160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky return newObj; 18260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky} 18360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 18460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky/* 18560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * Create a copy of an object, for Object.clone(). 18660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * 18760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * We use the size actually allocated, rather than obj->clazz->objectSize, 18860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * because the latter doesn't work for array objects. 18960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky */ 19060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli BenderskyObject* dvmCloneObject(Object* obj, int flags) 19160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky{ 19260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky ClassObject* clazz; 19360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky Object* copy; 19460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky size_t size; 19560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 19660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky assert(dvmIsValidObject(obj)); 19760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky clazz = obj->clazz; 19860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 19960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky /* Class.java shouldn't let us get here (java.lang.Class is final 20060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * and does not implement Clonable), but make extra sure. 20160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky * A memcpy() clone will wreak havoc on a ClassObject's "innards". 20260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky */ 20360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky assert(clazz != gDvm.classJavaLangClass); 20460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 20560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) { 20660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky size = dvmArrayObjectSize((ArrayObject *)obj); 20760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky } else { 20860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky size = clazz->objectSize; 20960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky } 21060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 21160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky copy = (Object*)dvmMalloc(size, flags); 21260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky if (copy == NULL) 21360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky return NULL; 21460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 21560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky /* We assume that memcpy will copy obj by words. */ 21660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky memcpy(copy, obj, size); 21760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky DVM_LOCK_INIT(©->lock); 21860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmWriteBarrierObject(copy); 21960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky 22060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky /* Mark the clone as finalizable if appropriate. */ 22160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky if (IS_CLASS_FLAG_SET(clazz, CLASS_ISFINALIZABLE)) { 22260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky dvmSetFinalizable(copy); 22360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky } 224 225 dvmTrackAllocation(clazz, size); /* notify DDMS */ 226 227 return copy; 228} 229 230 231/* 232 * Track an object that was allocated internally and isn't yet part of the 233 * VM root set. 234 * 235 * We could do this per-thread or globally. If it's global we don't have 236 * to do the thread lookup but we do have to synchronize access to the list. 237 * 238 * "obj" must not be NULL. 239 * 240 * NOTE: "obj" is not a fully-formed object; in particular, obj->clazz will 241 * usually be NULL since we're being called from dvmMalloc(). 242 */ 243void dvmAddTrackedAlloc(Object* obj, Thread* self) 244{ 245 if (self == NULL) 246 self = dvmThreadSelf(); 247 248 assert(obj != NULL); 249 assert(self != NULL); 250 if (!dvmAddToReferenceTable(&self->internalLocalRefTable, obj)) { 251 LOGE("threadid=%d: unable to add %p to internal ref table\n", 252 self->threadId, obj); 253 dvmDumpThread(self, false); 254 dvmAbort(); 255 } 256} 257 258/* 259 * Stop tracking an object. 260 * 261 * We allow attempts to delete NULL "obj" so that callers don't have to wrap 262 * calls with "if != NULL". 263 */ 264void dvmReleaseTrackedAlloc(Object* obj, Thread* self) 265{ 266 if (obj == NULL) 267 return; 268 269 if (self == NULL) 270 self = dvmThreadSelf(); 271 assert(self != NULL); 272 273 if (!dvmRemoveFromReferenceTable(&self->internalLocalRefTable, 274 self->internalLocalRefTable.table, obj)) 275 { 276 LOGE("threadid=%d: failed to remove %p from internal ref table\n", 277 self->threadId, obj); 278 dvmAbort(); 279 } 280} 281 282 283/* 284 * Explicitly initiate garbage collection. 285 */ 286void dvmCollectGarbage(void) 287{ 288 if (gDvm.disableExplicitGc) { 289 return; 290 } 291 dvmLockHeap(); 292 dvmWaitForConcurrentGcToComplete(); 293 dvmCollectGarbageInternal(GC_EXPLICIT); 294 dvmUnlockHeap(); 295} 296 297typedef struct { 298 const ClassObject *clazz; 299 size_t count; 300} CountContext; 301 302static void countInstancesOfClassCallback(void *ptr, void *arg) 303{ 304 CountContext *ctx = (CountContext *)arg; 305 const Object *obj = (const Object *)ptr; 306 307 assert(ctx != NULL); 308 if (obj->clazz == ctx->clazz) { 309 ctx->count += 1; 310 } 311} 312 313size_t dvmCountInstancesOfClass(const ClassObject *clazz) 314{ 315 CountContext ctx = { clazz, 0 }; 316 dvmLockHeap(); 317 HeapBitmap *bitmap = dvmHeapSourceGetLiveBits(); 318 dvmHeapBitmapWalk(bitmap, countInstancesOfClassCallback, &ctx); 319 dvmUnlockHeap(); 320 return ctx.count; 321} 322 323static void countAssignableInstancesOfClassCallback(void *ptr, void *arg) 324{ 325 CountContext *ctx = (CountContext *)arg; 326 const Object *obj = (const Object *)ptr; 327 328 assert(ctx != NULL); 329 if (obj->clazz != NULL && dvmInstanceof(obj->clazz, ctx->clazz)) { 330 ctx->count += 1; 331 } 332} 333 334size_t dvmCountAssignableInstancesOfClass(const ClassObject *clazz) 335{ 336 CountContext ctx = { clazz, 0 }; 337 dvmLockHeap(); 338 HeapBitmap *bitmap = dvmHeapSourceGetLiveBits(); 339 dvmHeapBitmapWalk(bitmap, countAssignableInstancesOfClassCallback, &ctx); 340 dvmUnlockHeap(); 341 return ctx.count; 342} 343 344bool dvmIsHeapAddress(void *address) 345{ 346 return dvmHeapSourceContainsAddress(address); 347} 348