Heap.c revision d25566d9278e6424e521f4b7148ac31480e60c5c
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" 20962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes#include "alloc/HeapBitmap.h" 21962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes#include "alloc/Verify.h" 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapTable.h" 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/Heap.h" 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapInternal.h" 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/DdmHeap.h" 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapSource.h" 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/MarkSweep.h" 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "utils/threads.h" // need Android thread priorities 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kInvalidPriority 10000 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 325a2056ca8c7e7c0ed9f51d68cedbee59cc936685San Mehat#include <cutils/sched_policy.h> 335a2056ca8c7e7c0ed9f51d68cedbee59cc936685San Mehat 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/time.h> 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/resource.h> 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <limits.h> 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h> 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kNonCollectableRefDefault 16 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kFinalizableRefDefault 128 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 421b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayesstatic const char* GcReasonStr[] = { 431b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes [GC_FOR_MALLOC] = "GC_FOR_MALLOC", 441b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes [GC_EXPLICIT] = "GC_EXPLICIT", 451b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes [GC_EXTERNAL_ALLOC] = "GC_EXTERNAL_ALLOC", 461b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes [GC_HPROF_DUMP_HEAP] = "GC_HPROF_DUMP_HEAP" 471b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes}; 481b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the GC heap. 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if successful, false otherwise. 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmHeapStartup() 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GcHeap *gcHeap; 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if defined(WITH_ALLOC_LIMITS) 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.checkAllocLimits = false; 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocationLimit = -1; 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap = dvmHeapSourceStartup(gDvm.heapSizeStart, gDvm.heapSizeMax); 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap == NULL) { 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->heapWorkerCurrentObject = NULL; 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->heapWorkerCurrentMethod = NULL; 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->heapWorkerInterpStartTime = 0LL; 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->softReferenceCollectionState = SR_COLLECT_NONE; 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->softReferenceHeapSizeThreshold = gDvm.heapSizeStart; 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->ddmHpifWhen = 0; 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->ddmHpsgWhen = 0; 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->ddmHpsgWhat = 0; 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->ddmNhsgWhen = 0; 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->ddmNhsgWhat = 0; 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if WITH_HPROF 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->hprofDumpOnGc = false; 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->hprofContext = NULL; 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* This needs to be set before we call dvmHeapInitHeapRefTable(). 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.gcHeap = gcHeap; 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Set up the table we'll use for ALLOC_NO_GC. 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmHeapInitHeapRefTable(&gcHeap->nonCollectableRefs, 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kNonCollectableRefDefault)) 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE_HEAP("Can't allocate GC_NO_ALLOC table\n"); 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto fail; 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Set up the lists and lock we'll use for finalizable 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and reference objects. 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInitMutex(&gDvm.heapWorkerListLock); 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->finalizableRefs = NULL; 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->pendingFinalizationRefs = NULL; 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->referenceOperations = NULL; 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Initialize the HeapWorker locks and other state 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that the GC uses. 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInitializeHeapWorkerState(); 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfail: 111a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro dvmHeapSourceShutdown(&gcHeap); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 115c8e06c8dba30f01d3cf6506c553041c340b312afCarl Shapirovoid dvmHeapStartupAfterZygote() 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Update our idea of the last GC start time so that we 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * don't use the last time that Zygote happened to GC. 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.gcHeap->gcStartTime = dvmGetRelativeTimeUsec(); 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmHeapShutdown() 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: make sure we're locked 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.gcHeap != NULL) { 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Tables are allocated on the native heap; 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * they need to be cleaned up explicitly. 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The process may stick around, so we don't 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to leak any native memory. 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 132a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro dvmHeapFreeHeapRefTable(&gDvm.gcHeap->nonCollectableRefs); 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 134a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro dvmHeapFreeLargeTable(gDvm.gcHeap->finalizableRefs); 135a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro gDvm.gcHeap->finalizableRefs = NULL; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 137a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro dvmHeapFreeLargeTable(gDvm.gcHeap->pendingFinalizationRefs); 138a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro gDvm.gcHeap->pendingFinalizationRefs = NULL; 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 140a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro dvmHeapFreeLargeTable(gDvm.gcHeap->referenceOperations); 141a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro gDvm.gcHeap->referenceOperations = NULL; 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Destroy the heap. Any outstanding pointers 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will point to unmapped memory (unless/until 145a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro * someone else maps it). This frees gDvm.gcHeap 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * as a side-effect. 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 148a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro dvmHeapSourceShutdown(&gDvm.gcHeap); 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We've been asked to allocate something we can't, e.g. an array so 1546da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * large that (length * elementWidth) is larger than 2^31. 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1566da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * _The Java Programming Language_, 4th edition, says, "you can be sure 1576da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * that all SoftReferences to softly reachable objects will be cleared 1586da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * before an OutOfMemoryError is thrown." 1596da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * 1606da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * It's unclear whether that holds for all situations where an OOM can 1616da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * be thrown, or just in the context of an allocation that fails due 1626da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * to lack of heap space. For simplicity we just throw the exception. 1636da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * 1646da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * (OOM due to actually running out of space is handled elsewhere.) 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowBadAllocException(const char* msg) 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1686da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden dvmThrowException("Ljava/lang/OutOfMemoryError;", msg); 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Grab the lock, but put ourselves into THREAD_VMWAIT if it looks like 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we're going to have to wait on the mutex. 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmLockHeap() 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 177980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro if (dvmTryLockMutex(&gDvm.gcHeapLock) != 0) { 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread *self; 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ThreadStatus oldStatus; 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self = dvmThreadSelf(); 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 18599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project LOGI("ODD: waiting on heap lock, no self\n"); 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldStatus = -1; // shut up gcc 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 188980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro dvmLockMutex(&gDvm.gcHeapLock); 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmChangeStatus(self, oldStatus); 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmUnlockHeap() 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockMutex(&gDvm.gcHeapLock); 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Pop an object from the list of pending finalizations and 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reference clears/enqueues, and return the object. 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must call dvmReleaseTrackedAlloc() 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on the object when finished. 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Typically only called by the heap worker thread. 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject *dvmGetNextHeapWorkerObject(HeapWorkerOperation *op) 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object *obj; 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GcHeap *gcHeap = gDvm.gcHeap; 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(op != NULL); 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project obj = NULL; 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockMutex(&gDvm.heapWorkerListLock); 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* We must handle reference operations before finalizations. 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If: 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a) Someone subclasses WeakReference and overrides clear() 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * b) A reference of this type is the last reference to 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a finalizable object 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * then we need to guarantee that the overridden clear() is called 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on the reference before finalize() is called on the referent. 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Both of these operations will always be scheduled at the same 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * time, so handling reference operations first will guarantee 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the required order. 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project obj = dvmHeapGetNextObjectFromLargeTable(&gcHeap->referenceOperations); 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj != NULL) { 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project uintptr_t workBits; 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2356930a11fd75071fa2f04fcfe11c322e2518cf503Barry Hayes workBits = (uintptr_t)obj & WORKER_ENQUEUE; 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(workBits != 0); 2376930a11fd75071fa2f04fcfe11c322e2518cf503Barry Hayes obj = (Object *)((uintptr_t)obj & ~WORKER_ENQUEUE); 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *op = workBits; 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project obj = dvmHeapGetNextObjectFromLargeTable( 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project &gcHeap->pendingFinalizationRefs); 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj != NULL) { 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *op = WORKER_FINALIZE; 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj != NULL) { 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't let the GC collect the object until the 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * worker thread is done with it. 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This call is safe; it uses thread-local storage 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and doesn't acquire any locks. 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAddTrackedAlloc(obj, NULL); 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockMutex(&gDvm.heapWorkerListLock); 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return obj; 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Used for a heap size change hysteresis to avoid collecting 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * SoftReferences when the heap only grows by a small amount. 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define SOFT_REFERENCE_GROWTH_SLACK (128 * 1024) 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Whenever the effective heap size may have changed, 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this function must be called. 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmHeapSizeChanged() 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GcHeap *gcHeap = gDvm.gcHeap; 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t currentHeapSize; 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentHeapSize = dvmHeapSourceGetIdealFootprint(); 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* See if the heap size has changed enough that we should care 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * about it. 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (currentHeapSize <= gcHeap->softReferenceHeapSizeThreshold - 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 4 * SOFT_REFERENCE_GROWTH_SLACK) 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The heap has shrunk enough that we'll use this as a new 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * threshold. Since we're doing better on space, there's 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * no need to collect any SoftReferences. 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is 4x the growth hysteresis because we don't want 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to snap down so easily after a shrink. If we just cleared 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * up a bunch of SoftReferences, we don't want to disallow 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * any new ones from being created. 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: determine if the 4x is important, needed, or even good 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->softReferenceHeapSizeThreshold = currentHeapSize; 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->softReferenceCollectionState = SR_COLLECT_NONE; 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (currentHeapSize >= gcHeap->softReferenceHeapSizeThreshold + 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SOFT_REFERENCE_GROWTH_SLACK) 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The heap has grown enough to warrant collecting SoftReferences. 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->softReferenceHeapSizeThreshold = currentHeapSize; 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->softReferenceCollectionState = SR_COLLECT_SOME; 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Do a full garbage collection, which may grow the 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * heap as a side-effect if the live set is large. 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void gcForMalloc(bool collectSoftReferences) 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.allocProf.enabled) { 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.gcCount++; 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.gcCount++; 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* This may adjust the soft limit as a side-effect. 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("dvmMalloc initiating GC%s\n", 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project collectSoftReferences ? "(collect SoftReferences)" : ""); 3251b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes dvmCollectGarbageInternal(collectSoftReferences, GC_FOR_MALLOC); 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Try as hard as possible to allocate some memory. 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 3306343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapirostatic void *tryMalloc(size_t size) 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 3326343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro void *ptr; 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't try too hard if there's no way the allocation is 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * going to succeed. We have to collect SoftReferences before 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * throwing an OOME, though. 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (size >= gDvm.heapSizeMax) { 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW_HEAP("dvmMalloc(%zu/0x%08zx): " 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "someone's allocating a huge buffer\n", size, size); 3416343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = NULL; 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto collect_soft_refs; 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: figure out better heuristics 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// There will be a lot of churn if someone allocates a bunch of 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// big objects in a row, and we hit the frag case each time. 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// A full GC for each. 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// Maybe we grow the heap in bigger leaps 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// Maybe we skip the GC if the size is large and we did one recently 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// (number of allocations ago) (watch for thread effects) 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// DeflateTest allocs a bunch of ~128k buffers w/in 0-5 allocs of each other 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// (or, at least, there are only 0-5 objects swept each time) 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3556343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = dvmHeapSourceAlloc(size); 3566343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (ptr != NULL) { 3576343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return ptr; 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The allocation failed. Free up some space by doing 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a full garbage collection. This may grow the heap 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if the live set is sufficiently large. 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcForMalloc(false); 3656343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = dvmHeapSourceAlloc(size); 3666343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (ptr != NULL) { 3676343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return ptr; 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Even that didn't work; this is an exceptional state. 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try harder, growing the heap if necessary. 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 3736343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = dvmHeapSourceAllocAndGrow(size); 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapSizeChanged(); 3756343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (ptr != NULL) { 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t newHeapSize; 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newHeapSize = dvmHeapSourceGetIdealFootprint(); 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: may want to grow a little bit more so that the amount of free 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// space is equal to the old free space + the utilization slop for 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// the new allocation. 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI_HEAP("Grow heap (frag case) to " 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "%zu.%03zuMB for %zu-byte allocation\n", 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(newHeapSize), size); 3856343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return ptr; 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Most allocations should have succeeded by now, so the heap 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is really full, really fragmented, or the requested size is 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * really big. Do another GC, collecting SoftReferences this 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * time. The VM spec requires that all SoftReferences have 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * been collected and cleared before throwing an OOME. 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: wait for the finalizers from the previous GC to finish 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectcollect_soft_refs: 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI_HEAP("Forcing collection of SoftReferences for %zu-byte allocation\n", 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size); 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcForMalloc(true); 3996343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = dvmHeapSourceAllocAndGrow(size); 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapSizeChanged(); 4016343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (ptr != NULL) { 4026343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return ptr; 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: maybe wait for finalizers and try one last time 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE_HEAP("Out of memory on a %zd-byte allocation.\n", size); 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: tell the HeapSource to dump its state 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(dvmThreadSelf(), false); 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Throw an OutOfMemoryError if there's a thread to attach it to. 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Avoid recursing. 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must not be holding the heap lock, or else the allocations 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in dvmThrowException() will deadlock. 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void throwOOME() 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread *self; 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((self = dvmThreadSelf()) != NULL) { 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* If the current (failing) dvmMalloc() happened as part of thread 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * creation/attachment before the thread became part of the root set, 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we can't rely on the thread-local trackedAlloc table, so 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we can't keep track of a real allocated OOME object. But, since 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the thread is in the process of being created, it won't have 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a useful stack anyway, so we may as well make things easier 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by throwing the (stackless) pre-built OOME. 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsOnThreadList(self) && !self->throwingOOME) { 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Let ourselves know that we tried to throw an OOM 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * error in the normal way in case we run out of 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * memory trying to allocate it inside dvmThrowException(). 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->throwingOOME = true; 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't include a description string; 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one fewer allocation. 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/OutOfMemoryError;", NULL); 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This thread has already tried to throw an OutOfMemoryError, 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which probably means that we're running out of memory 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * while recursively trying to throw. 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * To avoid any more allocation attempts, "throw" a pre-built 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * OutOfMemoryError object (which won't have a useful stack trace). 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that since this call can't possibly allocate anything, 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't care about the state of self->throwingOOME 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (which will usually already be set). 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmSetException(self, gDvm.outOfMemoryObj); 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* We're done with the possible recursion. 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->throwingOOME = false; 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Allocate storage on the GC heap. We guarantee 8-byte alignment. 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The new storage is zeroed out. 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that, in rare cases, this could get called while a GC is in 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * progress. If a non-VM thread tries to attach itself through JNI, 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it will need to allocate some objects. If this becomes annoying to 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * deal with, we can block it at the source, but holding the allocation 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * mutex should be enough. 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In rare circumstances (JNI AttachCurrentThread) we can be called 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from a non-VM thread. 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We implement ALLOC_NO_GC by maintaining an internal list of objects 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that should not be collected. This requires no actual flag storage in 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the object itself, which is good, but makes flag queries expensive. 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Use ALLOC_DONT_TRACK when we either don't want to track an allocation 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (because it's being done for the interpreter "new" operation and will 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be part of the root set immediately) or we can't (because this allocation 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is for a brand new thread). 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL and throws an exception on failure. 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: don't do a GC if the debugger thinks all threads are suspended 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmMalloc(size_t size, int flags) 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GcHeap *gcHeap = gDvm.gcHeap; 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void *ptr; 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* handy for spotting large allocations */ 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (size >= 100000) { 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("dvmMalloc(%d):\n", size); 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(dvmThreadSelf(), false); 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if defined(WITH_ALLOC_LIMITS) 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See if they've exceeded the allocation limit for this thread. 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * A limit value of -1 means "no limit". 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is enabled at compile time because it requires us to do a 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TLS lookup for the Thread pointer. This has enough of a performance 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * impact that we don't want to do it if we don't have to. (Now that 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we're using gDvm.checkAllocLimits we may want to reconsider this, 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * but it's probably still best to just compile the check out of 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * production code -- one less thing to hit on every allocation.) 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.checkAllocLimits) { 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int count = self->allocLimit; 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (count > 0) { 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocLimit--; 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (count == 0) { 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* fail! */ 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!gDvm.initializing); 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocLimit = -1; 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ldalvik/system/AllocationLimitError;", 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "thread allocation limit exceeded"); 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.allocationLimit >= 0) { 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!gDvm.initializing); 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocationLimit = -1; 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ldalvik/system/AllocationLimitError;", 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "global allocation limit exceeded"); 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockHeap(); 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Try as hard as possible to allocate some memory. 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 5476343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = tryMalloc(size); 5486343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (ptr != NULL) { 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* We've got the memory. 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((flags & ALLOC_FINALIZABLE) != 0) { 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* This object is an instance of a class that 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * overrides finalize(). Add it to the finalizable list. 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that until DVM_OBJECT_INIT() is called on this 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * object, its clazz will be NULL. Since the object is 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in this table, it will be scanned as part of the root 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * set. scanObject() explicitly deals with the NULL clazz. 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmHeapAddRefToLargeTable(&gcHeap->finalizableRefs, 5616343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro (Object *)ptr)) 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE_HEAP("dvmMalloc(): no room for any more " 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "finalizable objects\n"); 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The caller may not want us to collect this object. 570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If not, throw it in the nonCollectableRefs table, which 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will be added to the root set when we GC. 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that until DVM_OBJECT_INIT() is called on this 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * object, its clazz will be NULL. Since the object is 575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in this table, it will be scanned as part of the root 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * set. scanObject() explicitly deals with the NULL clazz. 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((flags & ALLOC_NO_GC) != 0) { 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmHeapAddToHeapRefTable(&gcHeap->nonCollectableRefs, ptr)) { 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE_HEAP("dvmMalloc(): no room for any more " 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "ALLOC_NO_GC objects: %zd\n", 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapNumHeapRefTableEntries( 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project &gcHeap->nonCollectableRefs)); 584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER 589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.allocProf.enabled) { 590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.allocCount++; 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.allocSize += size; 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.allocCount++; 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.allocSize += size; 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The allocation failed. 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.allocProf.enabled) { 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.failedAllocCount++; 607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.failedAllocSize += size; 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.failedAllocCount++; 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.failedAllocSize += size; 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockHeap(); 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ptr != NULL) { 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If this block is immediately GCable, and they haven't asked us not 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to track it, add it to the internal tracking list. 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If there's no "self" yet, we can't track it. Calls made before 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the Thread exists should use ALLOC_NO_GC. 625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((flags & (ALLOC_DONT_TRACK | ALLOC_NO_GC)) == 0) { 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAddTrackedAlloc(ptr, NULL); 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 630c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng /* 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The allocation failed; throw an OutOfMemoryError. 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwOOME(); 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ptr; 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true iff <obj> points to a valid allocated object. 641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmIsValidObject(const Object* obj) 643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't bother if it's NULL or not 8-byte aligned. 645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 6466343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (obj != NULL && ((uintptr_t)obj & (8-1)) == 0) { 647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Even if the heap isn't locked, this shouldn't return 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * any false negatives. The only mutation that could 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be happening is allocation, which means that another 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thread could be in the middle of a read-modify-write 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to add a new bit for a new object. However, that 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * RMW will have completed by the time any other thread 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * could possibly see the new pointer, so there is no 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * danger of dvmIsValidObject() being called on a valid 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pointer whose bit isn't set. 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Freeing will only happen during the sweep phase, which 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * only happens while the heap is locked. 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 6606343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return dvmHeapSourceContains(obj); 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear flags that were passed into dvmMalloc() et al. 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * e.g., ALLOC_NO_GC, ALLOC_DONT_TRACK. 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmClearAllocFlags(Object *obj, int mask) 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((mask & ALLOC_NO_GC) != 0) { 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockHeap(); 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsValidObject(obj)) { 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmHeapRemoveFromHeapRefTable(&gDvm.gcHeap->nonCollectableRefs, 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project obj)) 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE_HEAP("dvmMalloc(): failed to remove ALLOC_NO_GC bit from " 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "object 0x%08x\n", (uintptr_t)obj); 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: shrink if the table is very empty 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockHeap(); 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((mask & ALLOC_DONT_TRACK) != 0) { 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(obj, NULL); 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsize_t dvmObjectSizeInHeap(const Object *obj) 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 6936343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return dvmHeapSourceChunkSize(obj); 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 697962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes * Scan every live object in the heap, holding the locks. 698962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes */ 699962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayesstatic void verifyHeap() 700962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes{ 701962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes // TODO: check the locks. 702962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes HeapBitmap *liveBits = dvmHeapSourceGetLiveBits(); 703962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes dvmVerifyBitmap(liveBits); 704962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes} 705962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes 706962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes/* 707962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes * Suspend the VM as for a GC, and assert-fail if any object has any 708962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes * corrupt references. 709962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes */ 710962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayesvoid dvmHeapSuspendAndVerify() 711962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes{ 712962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes /* Suspend the VM. */ 713962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes dvmSuspendAllThreads(SUSPEND_FOR_VERIFY); 714962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes dvmLockMutex(&gDvm.heapWorkerLock); 715962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes dvmAssertHeapWorkerThreadRunning(); 716962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes dvmLockMutex(&gDvm.heapWorkerListLock); 717962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes 718962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes verifyHeap(); 719962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes 720962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes /* Resume the VM. */ 721962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes dvmUnlockMutex(&gDvm.heapWorkerListLock); 722962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes dvmUnlockMutex(&gDvm.heapWorkerLock); 723962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes dvmResumeAllThreads(SUSPEND_FOR_VERIFY); 724962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes} 725962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes 726962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes/* 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initiate garbage collection. 728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTES: 730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - If we don't hold gDvm.threadListLock, it's possible for a thread to 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be added to the thread list while we work. The thread should NOT 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * start executing, so this is only interesting when we start chasing 733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thread stacks. (Before we do so, grab the lock.) 734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We are not allowed to GC when the debugger has suspended the VM, which 736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is awkward because debugger requests can cause allocations. The easiest 737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * way to enforce this is to refuse to GC on an allocation made by the 738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * JDWP thread -- we have to expand the heap or fail. 739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 740d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapirovoid dvmCollectGarbageInternal(bool collectSoftReferences, GcReason reason) 741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GcHeap *gcHeap = gDvm.gcHeap; 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object *softReferences; 744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object *weakReferences; 745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object *phantomReferences; 746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u8 now; 748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project s8 timeSinceLastGc; 749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project s8 gcElapsedTime; 750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int numFreed; 751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t sizeFreed; 752d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro GcMode gcMode; 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING 755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Since weak and soft references are always cleared, 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * they don't require any marking. 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Soft are lumped into strong when they aren't cleared.) 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t strongMarkCount = 0; 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t strongMarkSize = 0; 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t finalizeMarkCount = 0; 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t finalizeMarkSize = 0; 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t phantomMarkCount = 0; 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t phantomMarkSize = 0; 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The heap lock must be held. 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->gcRunning) { 771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW_HEAP("Attempted recursive GC\n"); 772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 774d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro gcMode = (reason == GC_FOR_MALLOC) ? GC_PARTIAL : GC_FULL; 775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->gcRunning = true; 776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project now = dvmGetRelativeTimeUsec(); 777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->gcStartTime != 0) { 778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project timeSinceLastGc = (now - gcHeap->gcStartTime) / 1000; 779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project timeSinceLastGc = 0; 781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->gcStartTime = now; 783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 7841b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes LOGV_HEAP("%s starting -- suspending threads\n", GcReasonStr[reason]); 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmSuspendAllThreads(SUSPEND_FOR_GC); 787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Get the priority (the "nice" value) of the current thread. The 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * getpriority() call can legitimately return -1, so we have to 790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * explicitly test errno. 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project errno = 0; 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int oldThreadPriority = kInvalidPriority; 794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int priorityResult = getpriority(PRIO_PROCESS, 0); 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (errno != 0) { 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI_HEAP("getpriority(self) failed: %s\n", strerror(errno)); 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (priorityResult > ANDROID_PRIORITY_NORMAL) { 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Current value is numerically greater than "normal", which 799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in backward UNIX terms means lower priority. 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 801256fc159a267859c18e11e1d15fd7d97a59757c6San Mehat 8023e371e2ebbeeefe176ba1357e6ff241bd13a711eSan Mehat if (priorityResult >= ANDROID_PRIORITY_BACKGROUND) { 8035a2056ca8c7e7c0ed9f51d68cedbee59cc936685San Mehat set_sched_policy(dvmGetSysThreadId(), SP_FOREGROUND); 804256fc159a267859c18e11e1d15fd7d97a59757c6San Mehat } 805256fc159a267859c18e11e1d15fd7d97a59757c6San Mehat 806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL) != 0) { 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI_HEAP("Unable to elevate priority from %d to %d\n", 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project priorityResult, ANDROID_PRIORITY_NORMAL); 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* priority elevated; save value so we can restore it later */ 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Elevating priority from %d to %d\n", 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project priorityResult, ANDROID_PRIORITY_NORMAL); 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldThreadPriority = priorityResult; 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Wait for the HeapWorker thread to block. 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (It may also already be suspended in interp code, 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in which case it's not holding heapWorkerLock.) 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockMutex(&gDvm.heapWorkerLock); 822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Make sure that the HeapWorker thread hasn't become 824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * wedged inside interp code. If it has, this call will 825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * print a message and abort the VM. 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAssertHeapWorkerThreadRunning(); 828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Lock the pendingFinalizationRefs list. 830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Acquire the lock after suspending so the finalizer 832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thread can't block in the RUNNING state while 833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we try to suspend. 834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockMutex(&gDvm.heapWorkerListLock); 836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 837962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes if (gDvm.preVerify) { 838962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes LOGV_HEAP("Verifying heap before GC"); 839962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes verifyHeap(); 840962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes } 841962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes 842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER 843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmMethodTraceGCBegin(); 844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if WITH_HPROF 847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Set DUMP_HEAP_ON_DDMS_UPDATE to 1 to enable heap dumps 849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * whenever DDMS requests a heap update (HPIF chunk). 850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The output files will appear in /data/misc, which must 851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * already exist. 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You must define "WITH_HPROF := true" in your buildspec.mk 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and recompile libdvm for this to work. 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * To enable stack traces for each allocation, define 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "WITH_HPROF_STACK := true" in buildspec.mk. This option slows down 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * allocations and also requires 8 additional bytes per object on the 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * GC heap. 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define DUMP_HEAP_ON_DDMS_UPDATE 0 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DUMP_HEAP_ON_DDMS_UPDATE 862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->hprofDumpOnGc |= (gcHeap->ddmHpifWhen != 0); 863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->hprofDumpOnGc) { 866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char nameBuf[128]; 867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 86899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project gcHeap->hprofResult = -1; 86999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->hprofFileName == NULL) { 871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* no filename was provided; invent one */ 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sprintf(nameBuf, "/data/misc/heap-dump-tm%d-pid%d.hprof", 873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (int) time(NULL), (int) getpid()); 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->hprofFileName = nameBuf; 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 8766bf992c9d51f1e12aa37fe4c791c156402a9b79bAndy McFadden gcHeap->hprofContext = hprofStartup(gcHeap->hprofFileName, 8776bf992c9d51f1e12aa37fe4c791c156402a9b79bAndy McFadden gcHeap->hprofDirectToDdms); 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->hprofContext != NULL) { 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hprofStartHeapDump(gcHeap->hprofContext); 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->hprofDumpOnGc = false; 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->hprofFileName = NULL; 883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (timeSinceLastGc < 10000) { 887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("GC! (%dms since last GC)\n", 888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (int)timeSinceLastGc); 889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("GC! (%d sec since last GC)\n", 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (int)(timeSinceLastGc / 1000)); 892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->markCount = 0; 895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->markSize = 0; 896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Set up the marking context. 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 900d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro if (!dvmHeapBeginMarkStep(gcMode)) { 90199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project LOGE_HEAP("dvmHeapBeginMarkStep failed; aborting\n"); 90299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project dvmAbort(); 90399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project } 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Mark the set of objects that are strongly reachable from the roots. 906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Marking..."); 908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapMarkRootSet(); 909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* dvmHeapScanMarkedObjects() will build the lists of known 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instances of the Reference classes. 912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->softReferences = NULL; 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->weakReferences = NULL; 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->phantomReferences = NULL; 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Make sure that we don't hard-mark the referents of Reference 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * objects by default. 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->markAllReferents = false; 921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't mark SoftReferences if our caller wants us to collect them. 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This has to be set before calling dvmHeapScanMarkedObjects(). 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (collectSoftReferences) { 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->softReferenceCollectionState = SR_COLLECT_ALL; 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Recursively mark any objects that marked objects point to strongly. 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we're not collecting soft references, soft-reachable 931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * objects will also be marked. 932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Recursing..."); 934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapScanMarkedObjects(); 935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING 936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project strongMarkCount = gcHeap->markCount; 937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project strongMarkSize = gcHeap->markSize; 938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->markCount = 0; 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->markSize = 0; 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Latch these so that the other calls to dvmHeapScanMarkedObjects() don't 943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * mess with them. 944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project softReferences = gcHeap->softReferences; 946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project weakReferences = gcHeap->weakReferences; 947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project phantomReferences = gcHeap->phantomReferences; 948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* All strongly-reachable objects have now been marked. 950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->softReferenceCollectionState != SR_COLLECT_NONE) { 952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Handling soft references..."); 953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapHandleReferences(softReferences, REF_SOFT); 954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // markCount always zero 955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Now that we've tried collecting SoftReferences, 957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fall back to not collecting them. If the heap 958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * grows, we will start collecting again. 959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->softReferenceCollectionState = SR_COLLECT_NONE; 961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } // else dvmHeapScanMarkedObjects() already marked the soft-reachable set 962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Handling weak references..."); 963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapHandleReferences(weakReferences, REF_WEAK); 964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // markCount always zero 965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Once all weak-reachable objects have been taken 967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * care of, any remaining unmarked objects can be finalized. 968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Finding finalizations..."); 970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapScheduleFinalizations(); 971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING 972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project finalizeMarkCount = gcHeap->markCount; 973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project finalizeMarkSize = gcHeap->markSize; 974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->markCount = 0; 975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->markSize = 0; 976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Any remaining objects that are not pending finalization 979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * could be phantom-reachable. This will mark any phantom-reachable 980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * objects, as well as enqueue their references. 981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Handling phantom references..."); 983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapHandleReferences(phantomReferences, REF_PHANTOM); 984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING 985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project phantomMarkCount = gcHeap->markCount; 986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project phantomMarkSize = gcHeap->markSize; 987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->markCount = 0; 988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->markSize = 0; 989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: take care of JNI weak global references 992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING 994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI_HEAP("Marked objects: %dB strong, %dB final, %dB phantom\n", 995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project strongMarkSize, finalizeMarkSize, phantomMarkSize); 996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION 999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpMonitorInfo("before sweep"); 1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Sweeping..."); 1002d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro dvmHeapSweepUnmarkedObjects(gcMode, &numFreed, &sizeFreed); 1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION 1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpMonitorInfo("after sweep"); 1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Cleaning up..."); 1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapFinishMarkStep(); 1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Done."); 1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Now's a good time to adjust the heap size, since 1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we know what our utilization is. 1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This doesn't actually resize any memory; 1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it just lets the heap grow more when necessary. 1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapSourceGrowForUtilization(); 1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapSizeChanged(); 1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if WITH_HPROF 1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->hprofContext != NULL) { 1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hprofFinishHeapDump(gcHeap->hprofContext); 1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: write a HEAP_SUMMARY record 102599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project if (hprofShutdown(gcHeap->hprofContext)) 102699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project gcHeap->hprofResult = 0; /* indicate success */ 1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->hprofContext = NULL; 1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Now that we've freed up the GC heap, return any large 1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * free chunks back to the system. They'll get paged back 1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in the next time they're used. Don't do it immediately, 1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * though; if the process is still allocating a bunch of 1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * memory, we'll be taking a ton of page faults that we don't 1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * necessarily need to. 1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Cancel any old scheduled trims, and schedule a new one. 1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmScheduleHeapSourceTrim(5); // in seconds 1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER 1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmMethodTraceGCEnd(); 1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1045962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes LOGV_HEAP("GC finished"); 1046962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes 1047962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes if (gDvm.postVerify) { 1048962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes LOGV_HEAP("Verifying heap after GC"); 1049962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes verifyHeap(); 1050962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes } 1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->gcRunning = false; 1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1054962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes LOGV_HEAP("Resuming threads"); 1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockMutex(&gDvm.heapWorkerListLock); 1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockMutex(&gDvm.heapWorkerLock); 1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1058c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng#if defined(WITH_JIT) 1059c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng /* 1060c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng * Patching a chaining cell is very cheap as it only updates 4 words. It's 1061c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng * the overhead of stopping all threads and synchronizing the I/D cache 1062c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng * that makes it expensive. 1063c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng * 1064c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng * Therefore we batch those work orders in a queue and go through them 1065c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng * when threads are suspended for GC. 1066c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng */ 1067c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng dvmCompilerPerformSafePointChecks(); 1068c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng#endif 1069c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng 1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmResumeAllThreads(SUSPEND_FOR_GC); 1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (oldThreadPriority != kInvalidPriority) { 1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (setpriority(PRIO_PROCESS, 0, oldThreadPriority) != 0) { 1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW_HEAP("Unable to reset priority to %d: %s\n", 1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldThreadPriority, strerror(errno)); 1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Reset priority to %d\n", oldThreadPriority); 1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1078256fc159a267859c18e11e1d15fd7d97a59757c6San Mehat 10793e371e2ebbeeefe176ba1357e6ff241bd13a711eSan Mehat if (oldThreadPriority >= ANDROID_PRIORITY_BACKGROUND) { 10805a2056ca8c7e7c0ed9f51d68cedbee59cc936685San Mehat set_sched_policy(dvmGetSysThreadId(), SP_BACKGROUND); 1081256fc159a267859c18e11e1d15fd7d97a59757c6San Mehat } 1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcElapsedTime = (dvmGetRelativeTimeUsec() - gcHeap->gcStartTime) / 1000; 10843136413fae48cee04095236a945e41782d6d10bcBarry Hayes LOGD("%s freed %d objects / %zd bytes in %dms\n", 10853136413fae48cee04095236a945e41782d6d10bcBarry Hayes GcReasonStr[reason], numFreed, sizeFreed, (int)gcElapsedTime); 1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLogGcStats(numFreed, sizeFreed, gcElapsedTime); 1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->ddmHpifWhen != 0) { 1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Sending VM heap info to DDM\n"); 1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDdmSendHeapInfo(gcHeap->ddmHpifWhen, false); 1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->ddmHpsgWhen != 0) { 1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Dumping VM heap to DDM\n"); 1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDdmSendHeapSegments(false, false); 1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->ddmNhsgWhen != 0) { 1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Dumping native heap to DDM\n"); 1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDdmSendHeapSegments(false, true); 1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if WITH_HPROF 1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Perform garbage collection, writing heap information to the specified file. 1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "fileName" is NULL, a suitable name will be generated automatically. 110799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * 110899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Returns 0 on success, or an error code on failure. 1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 11106bf992c9d51f1e12aa37fe4c791c156402a9b79bAndy McFaddenint hprofDumpHeap(const char* fileName, bool directToDdms) 1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 111299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project int result; 111399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockMutex(&gDvm.gcHeapLock); 1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.gcHeap->hprofDumpOnGc = true; 1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.gcHeap->hprofFileName = fileName; 11186bf992c9d51f1e12aa37fe4c791c156402a9b79bAndy McFadden gDvm.gcHeap->hprofDirectToDdms = directToDdms; 11191b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes dvmCollectGarbageInternal(false, GC_HPROF_DUMP_HEAP); 112099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project result = gDvm.gcHeap->hprofResult; 1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockMutex(&gDvm.gcHeapLock); 112399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 112499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project return result; 1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmHeapSetHprofGcScanState(hprof_heap_tag_t state, u4 threadSerialNumber) 1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.gcHeap->hprofContext != NULL) { 1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hprofSetGcScanState(gDvm.gcHeap->hprofContext, state, 1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project threadSerialNumber); 1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1135