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/Heap.h" 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapInternal.h" 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/DdmHeap.h" 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapSource.h" 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/MarkSweep.h" 27e6c0ef210ee6c62cf4c63d50c04f451d5fa505f5Elliott Hughes#include "os/os.h" 285a2056ca8c7e7c0ed9f51d68cedbee59cc936685San Mehat 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/time.h> 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/resource.h> 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <limits.h> 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h> 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 34cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapirostatic const GcSpec kGcForMallocSpec = { 359b6881c26d58a46e6478294d83554fb9e3a85625Carl Shapiro true, /* isPartial */ 369b6881c26d58a46e6478294d83554fb9e3a85625Carl Shapiro false, /* isConcurrent */ 37ae188c676c681e47a93ade7fdf0144099b470e03Carl Shapiro true, /* doPreserve */ 38cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro "GC_FOR_ALLOC" 391b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes}; 401b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes 41cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiroconst GcSpec *GC_FOR_MALLOC = &kGcForMallocSpec; 42cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro 43cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapirostatic const GcSpec kGcConcurrentSpec = { 449b6881c26d58a46e6478294d83554fb9e3a85625Carl Shapiro true, /* isPartial */ 459b6881c26d58a46e6478294d83554fb9e3a85625Carl Shapiro true, /* isConcurrent */ 46ae188c676c681e47a93ade7fdf0144099b470e03Carl Shapiro true, /* doPreserve */ 47cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro "GC_CONCURRENT" 48cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro}; 49cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro 50cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiroconst GcSpec *GC_CONCURRENT = &kGcConcurrentSpec; 51cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro 52cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapirostatic const GcSpec kGcExplicitSpec = { 539b6881c26d58a46e6478294d83554fb9e3a85625Carl Shapiro false, /* isPartial */ 549b6881c26d58a46e6478294d83554fb9e3a85625Carl Shapiro true, /* isConcurrent */ 55ae188c676c681e47a93ade7fdf0144099b470e03Carl Shapiro true, /* doPreserve */ 56cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro "GC_EXPLICIT" 57cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro}; 58cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro 59cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiroconst GcSpec *GC_EXPLICIT = &kGcExplicitSpec; 60cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro 61cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapirostatic const GcSpec kGcBeforeOomSpec = { 629b6881c26d58a46e6478294d83554fb9e3a85625Carl Shapiro false, /* isPartial */ 639b6881c26d58a46e6478294d83554fb9e3a85625Carl Shapiro false, /* isConcurrent */ 64ae188c676c681e47a93ade7fdf0144099b470e03Carl Shapiro false, /* doPreserve */ 65cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro "GC_BEFORE_OOM" 66cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro}; 67cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro 68cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiroconst GcSpec *GC_BEFORE_OOM = &kGcBeforeOomSpec; 69cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the GC heap. 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if successful, false otherwise. 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmHeapStartup() 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GcHeap *gcHeap; 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 79df9f08b877ecfd8ebadea822bb9e066ee7d30433Carl Shapiro if (gDvm.heapGrowthLimit == 0) { 80df9f08b877ecfd8ebadea822bb9e066ee7d30433Carl Shapiro gDvm.heapGrowthLimit = gDvm.heapMaximumSize; 81df9f08b877ecfd8ebadea822bb9e066ee7d30433Carl Shapiro } 82df9f08b877ecfd8ebadea822bb9e066ee7d30433Carl Shapiro 83df9f08b877ecfd8ebadea822bb9e066ee7d30433Carl Shapiro gcHeap = dvmHeapSourceStartup(gDvm.heapStartingSize, 84df9f08b877ecfd8ebadea822bb9e066ee7d30433Carl Shapiro gDvm.heapMaximumSize, 85df9f08b877ecfd8ebadea822bb9e066ee7d30433Carl Shapiro gDvm.heapGrowthLimit); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap == NULL) { 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->ddmHpifWhen = 0; 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->ddmHpsgWhen = 0; 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->ddmHpsgWhat = 0; 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->ddmNhsgWhen = 0; 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->ddmNhsgWhat = 0; 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.gcHeap = gcHeap; 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 96ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro /* Set up the lists we'll use for cleared reference objects. 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 98ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro gcHeap->clearedReferences = NULL; 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 100af6cf54652d1b27885b99e216bee29b955052630Andy McFadden if (!dvmCardTableStartup(gDvm.heapMaximumSize, gDvm.heapGrowthLimit)) { 101b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes LOGE_HEAP("card table startup failed."); 102b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes return false; 103b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes } 104b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1081e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmHeapStartupAfterZygote() 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 110ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro return dvmHeapSourceStartupAfterZygote(); 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmHeapShutdown() 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: make sure we're locked 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.gcHeap != NULL) { 117b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes dvmCardTableShutdown(); 118b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes /* Destroy the heap. Any outstanding pointers will point to 119b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes * unmapped memory (unless/until someone else maps it). This 120b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes * frees gDvm.gcHeap as a side-effect. 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 122a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro dvmHeapSourceShutdown(&gDvm.gcHeap); 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 127ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * Shutdown any threads internal to the heap. 128ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro */ 1291e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmHeapThreadShutdown() 130ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro{ 131ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmHeapSourceThreadShutdown(); 132ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro} 133ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 134ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro/* 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Grab the lock, but put ourselves into THREAD_VMWAIT if it looks like 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we're going to have to wait on the mutex. 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmLockHeap() 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 140980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro if (dvmTryLockMutex(&gDvm.gcHeapLock) != 0) { 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread *self; 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ThreadStatus oldStatus; 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self = dvmThreadSelf(); 1455617ad30c611f373e16bf10c0feec114faef54efCarl Shapiro oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); 146980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro dvmLockMutex(&gDvm.gcHeapLock); 1475617ad30c611f373e16bf10c0feec114faef54efCarl Shapiro dvmChangeStatus(self, oldStatus); 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmUnlockHeap() 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockMutex(&gDvm.gcHeapLock); 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Do a full garbage collection, which may grow the 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * heap as a side-effect if the live set is large. 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 161a371fad368c4d697b2906079bfbe8059269ed362Carl Shapirostatic void gcForMalloc(bool clearSoftReferences) 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.allocProf.enabled) { 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.gcCount++; 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.gcCount++; 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* This may adjust the soft limit as a side-effect. 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 172cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro const GcSpec *spec = clearSoftReferences ? GC_BEFORE_OOM : GC_FOR_MALLOC; 173cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro dvmCollectGarbageInternal(spec); 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Try as hard as possible to allocate some memory. 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1786343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapirostatic void *tryMalloc(size_t size) 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1806343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro void *ptr; 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't try too hard if there's no way the allocation is 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * going to succeed. We have to collect SoftReferences before 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * throwing an OOME, though. 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 186df9f08b877ecfd8ebadea822bb9e066ee7d30433Carl Shapiro if (size >= gDvm.heapGrowthLimit) { 187e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("%zd byte allocation exceeds the %zd byte maximum heap size", 1882384bdf512d0609c747af03256654fde03093844Carl Shapiro size, gDvm.heapGrowthLimit); 1896343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = NULL; 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto collect_soft_refs; 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: figure out better heuristics 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// There will be a lot of churn if someone allocates a bunch of 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// big objects in a row, and we hit the frag case each time. 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// A full GC for each. 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// Maybe we grow the heap in bigger leaps 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// Maybe we skip the GC if the size is large and we did one recently 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// (number of allocations ago) (watch for thread effects) 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// DeflateTest allocs a bunch of ~128k buffers w/in 0-5 allocs of each other 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// (or, at least, there are only 0-5 objects swept each time) 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2036343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = dvmHeapSourceAlloc(size); 2046343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (ptr != NULL) { 2056343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return ptr; 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 208ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro /* 209ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * The allocation failed. If the GC is running, block until it 210ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * completes and retry. 211ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro */ 212ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro if (gDvm.gcHeap->gcRunning) { 213ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro /* 214ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * The GC is concurrently tracing the heap. Release the heap 215ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * lock, wait for the GC to complete, and retrying allocating. 216ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro */ 217ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro dvmWaitForConcurrentGcToComplete(); 218ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro ptr = dvmHeapSourceAlloc(size); 219ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro if (ptr != NULL) { 220ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro return ptr; 221ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro } 222ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro } 223ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro /* 224ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * Another failure. Our thread was starved or there may be too 225ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * many live objects. Try a foreground GC. This will have no 226ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * effect if the concurrent GC is already running. 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcForMalloc(false); 2296343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = dvmHeapSourceAlloc(size); 2306343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (ptr != NULL) { 2316343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return ptr; 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Even that didn't work; this is an exceptional state. 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try harder, growing the heap if necessary. 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 2376343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = dvmHeapSourceAllocAndGrow(size); 2386343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (ptr != NULL) { 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t newHeapSize; 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newHeapSize = dvmHeapSourceGetIdealFootprint(); 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: may want to grow a little bit more so that the amount of free 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// space is equal to the old free space + the utilization slop for 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// the new allocation. 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI_HEAP("Grow heap (frag case) to " 2466f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein "%zu.%03zuMB for %zu-byte allocation", 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(newHeapSize), size); 2486343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return ptr; 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Most allocations should have succeeded by now, so the heap 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is really full, really fragmented, or the requested size is 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * really big. Do another GC, collecting SoftReferences this 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * time. The VM spec requires that all SoftReferences have 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * been collected and cleared before throwing an OOME. 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: wait for the finalizers from the previous GC to finish 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectcollect_soft_refs: 25960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGI_HEAP("Forcing collection of SoftReferences for %zu-byte allocation", 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size); 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcForMalloc(true); 2626343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = dvmHeapSourceAllocAndGrow(size); 2636343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (ptr != NULL) { 2646343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return ptr; 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: maybe wait for finalizers and try one last time 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 26860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE_HEAP("Out of memory on a %zd-byte allocation.", size); 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: tell the HeapSource to dump its state 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(dvmThreadSelf(), false); 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Throw an OutOfMemoryError if there's a thread to attach it to. 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Avoid recursing. 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must not be holding the heap lock, or else the allocations 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in dvmThrowException() will deadlock. 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void throwOOME() 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread *self; 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((self = dvmThreadSelf()) != NULL) { 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* If the current (failing) dvmMalloc() happened as part of thread 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * creation/attachment before the thread became part of the root set, 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we can't rely on the thread-local trackedAlloc table, so 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we can't keep track of a real allocated OOME object. But, since 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the thread is in the process of being created, it won't have 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a useful stack anyway, so we may as well make things easier 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by throwing the (stackless) pre-built OOME. 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsOnThreadList(self) && !self->throwingOOME) { 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Let ourselves know that we tried to throw an OOM 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * error in the normal way in case we run out of 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * memory trying to allocate it inside dvmThrowException(). 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->throwingOOME = true; 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't include a description string; 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one fewer allocation. 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 304d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowOutOfMemoryError(NULL); 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This thread has already tried to throw an OutOfMemoryError, 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which probably means that we're running out of memory 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * while recursively trying to throw. 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * To avoid any more allocation attempts, "throw" a pre-built 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * OutOfMemoryError object (which won't have a useful stack trace). 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that since this call can't possibly allocate anything, 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't care about the state of self->throwingOOME 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (which will usually already be set). 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmSetException(self, gDvm.outOfMemoryObj); 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* We're done with the possible recursion. 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->throwingOOME = false; 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Allocate storage on the GC heap. We guarantee 8-byte alignment. 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The new storage is zeroed out. 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that, in rare cases, this could get called while a GC is in 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * progress. If a non-VM thread tries to attach itself through JNI, 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it will need to allocate some objects. If this becomes annoying to 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * deal with, we can block it at the source, but holding the allocation 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * mutex should be enough. 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In rare circumstances (JNI AttachCurrentThread) we can be called 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from a non-VM thread. 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Use ALLOC_DONT_TRACK when we either don't want to track an allocation 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (because it's being done for the interpreter "new" operation and will 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be part of the root set immediately) or we can't (because this allocation 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is for a brand new thread). 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL and throws an exception on failure. 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: don't do a GC if the debugger thinks all threads are suspended 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmMalloc(size_t size, int flags) 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void *ptr; 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockHeap(); 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Try as hard as possible to allocate some memory. 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 3576343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro ptr = tryMalloc(size); 3586343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (ptr != NULL) { 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* We've got the memory. 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.allocProf.enabled) { 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.allocCount++; 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.allocSize += size; 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.allocCount++; 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.allocSize += size; 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The allocation failed. 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.allocProf.enabled) { 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.failedAllocCount++; 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.failedAllocSize += size; 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.failedAllocCount++; 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.failedAllocSize += size; 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockHeap(); 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ptr != NULL) { 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 389d4f78d3a764e6aa8f7174c78f537c016dac7f7ecBarry Hayes * If caller hasn't asked us not to track it, add it to the 390d4f78d3a764e6aa8f7174c78f537c016dac7f7ecBarry Hayes * internal tracking list. 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 392d4f78d3a764e6aa8f7174c78f537c016dac7f7ecBarry Hayes if ((flags & ALLOC_DONT_TRACK) == 0) { 393fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro dvmAddTrackedAlloc((Object*)ptr, NULL); 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 396c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng /* 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The allocation failed; throw an OutOfMemoryError. 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwOOME(); 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ptr; 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true iff <obj> points to a valid allocated object. 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmIsValidObject(const Object* obj) 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't bother if it's NULL or not 8-byte aligned. 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 4126343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro if (obj != NULL && ((uintptr_t)obj & (8-1)) == 0) { 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Even if the heap isn't locked, this shouldn't return 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * any false negatives. The only mutation that could 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be happening is allocation, which means that another 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thread could be in the middle of a read-modify-write 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to add a new bit for a new object. However, that 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * RMW will have completed by the time any other thread 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * could possibly see the new pointer, so there is no 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * danger of dvmIsValidObject() being called on a valid 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pointer whose bit isn't set. 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Freeing will only happen during the sweep phase, which 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * only happens while the heap is locked. 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 4266343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return dvmHeapSourceContains(obj); 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsize_t dvmObjectSizeInHeap(const Object *obj) 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 4336343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro return dvmHeapSourceChunkSize(obj); 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 4361e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void verifyRootsAndHeap() 437962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes{ 438106c5fd9745a47d663e28217f3dd5ac48f606f81Carl Shapiro dvmVerifyRoots(); 439106c5fd9745a47d663e28217f3dd5ac48f606f81Carl Shapiro dvmVerifyBitmap(dvmHeapSourceGetLiveBits()); 440962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes} 441962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes 442962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes/* 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initiate garbage collection. 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTES: 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - If we don't hold gDvm.threadListLock, it's possible for a thread to 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be added to the thread list while we work. The thread should NOT 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * start executing, so this is only interesting when we start chasing 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thread stacks. (Before we do so, grab the lock.) 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We are not allowed to GC when the debugger has suspended the VM, which 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is awkward because debugger requests can cause allocations. The easiest 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * way to enforce this is to refuse to GC on an allocation made by the 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * JDWP thread -- we have to expand the heap or fail. 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 456cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapirovoid dvmCollectGarbageInternal(const GcSpec* spec) 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GcHeap *gcHeap = gDvm.gcHeap; 45989cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown u4 gcEnd = 0; 4607aa9563279627b2ff5413bc895381fc170df9f12Doug Kwan u4 rootStart = 0 , rootEnd = 0; 4617aa9563279627b2ff5413bc895381fc170df9f12Doug Kwan u4 dirtyStart = 0, dirtyEnd = 0; 462570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro size_t numObjectsFreed, numBytesFreed; 463570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro size_t currAllocated, currFootprint; 464570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro size_t percentFree; 465cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro int oldThreadPriority = INT_MAX; 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The heap lock must be held. 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->gcRunning) { 47160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGW_HEAP("Attempted recursive GC"); 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 47403f3b1394cc8421d125fd00455858944f0e9808dCarl Shapiro 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->gcRunning = true; 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 47703f3b1394cc8421d125fd00455858944f0e9808dCarl Shapiro rootStart = dvmGetRelativeTimeMsec(); 47889cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown dvmSuspendAllThreads(SUSPEND_FOR_GC); 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 480ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro /* 481ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * If we are not marking concurrently raise the priority of the 482ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * thread performing the garbage collection. 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 484cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro if (!spec->isConcurrent) { 485e6c0ef210ee6c62cf4c63d50c04f451d5fa505f5Elliott Hughes oldThreadPriority = os_raiseThreadPriority(); 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 487962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes if (gDvm.preVerify) { 4886c5dd93d6b41d85f54c45816120081654ed2cbd8Carl Shapiro LOGV_HEAP("Verifying roots and heap before GC"); 4896c5dd93d6b41d85f54c45816120081654ed2cbd8Carl Shapiro verifyRootsAndHeap(); 490962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes } 491962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmMethodTraceGCBegin(); 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Set up the marking context. 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 496cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro if (!dvmHeapBeginMarkStep(spec->isPartial)) { 49760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE_HEAP("dvmHeapBeginMarkStep failed; aborting"); 49899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project dvmAbort(); 49999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project } 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Mark the set of objects that are strongly reachable from the roots. 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Marking..."); 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapMarkRootSet(); 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* dvmHeapScanMarkedObjects() will build the lists of known 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instances of the Reference classes. 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 509ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro assert(gcHeap->softReferences == NULL); 510ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro assert(gcHeap->weakReferences == NULL); 511ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro assert(gcHeap->finalizerReferences == NULL); 512ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro assert(gcHeap->phantomReferences == NULL); 513ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro assert(gcHeap->clearedReferences == NULL); 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 515cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro if (spec->isConcurrent) { 516ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro /* 517ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * Resume threads while tracing from the roots. We unlock the 518ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * heap to allow mutator threads to allocate from free space. 519ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro */ 520b2714082bad44fde247920b9280c1b40c4979c3aBen Cheng dvmClearCardTable(); 521ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro dvmUnlockHeap(); 522ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmResumeAllThreads(SUSPEND_FOR_GC); 52389cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown rootEnd = dvmGetRelativeTimeMsec(); 524ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro } 525ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Recursively mark any objects that marked objects point to strongly. 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we're not collecting soft references, soft-reachable 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * objects will also be marked. 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Recursing..."); 531b2714082bad44fde247920b9280c1b40c4979c3aBen Cheng dvmHeapScanMarkedObjects(); 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 533cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro if (spec->isConcurrent) { 534ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro /* 535ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * Re-acquire the heap lock and perform the final thread 536ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * suspension. 537ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro */ 53889cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown dirtyStart = dvmGetRelativeTimeMsec(); 539ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro dvmLockHeap(); 540ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmSuspendAllThreads(SUSPEND_FOR_GC); 541ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro /* 542ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * As no barrier intercepts root updates, we conservatively 543ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * assume all roots may be gray and re-mark them. 544ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro */ 545106c5fd9745a47d663e28217f3dd5ac48f606f81Carl Shapiro dvmHeapReMarkRootSet(); 546ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro /* 5475ba39376c5b7a5878f234a689a51c74783583b4bCarl Shapiro * With the exception of reference objects and weak interned 5485ba39376c5b7a5878f234a689a51c74783583b4bCarl Shapiro * strings, all gray objects should now be on dirty cards. 5495ba39376c5b7a5878f234a689a51c74783583b4bCarl Shapiro */ 5505ba39376c5b7a5878f234a689a51c74783583b4bCarl Shapiro if (gDvm.verifyCardTable) { 5515ba39376c5b7a5878f234a689a51c74783583b4bCarl Shapiro dvmVerifyCardTable(); 5525ba39376c5b7a5878f234a689a51c74783583b4bCarl Shapiro } 5535ba39376c5b7a5878f234a689a51c74783583b4bCarl Shapiro /* 554ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * Recursively mark gray objects pointed to by the roots or by 555ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * heap objects dirtied during the concurrent mark. 556ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro */ 557106c5fd9745a47d663e28217f3dd5ac48f606f81Carl Shapiro dvmHeapReScanMarkedObjects(); 558ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro } 559ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 560e8ef2b53866b01fb5a8e73ea867c934777aec57eCarl Shapiro /* 561e8ef2b53866b01fb5a8e73ea867c934777aec57eCarl Shapiro * All strongly-reachable objects have now been marked. Process 562e8ef2b53866b01fb5a8e73ea867c934777aec57eCarl Shapiro * weakly-reachable objects discovered while tracing. 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 564cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro dvmHeapProcessReferences(&gcHeap->softReferences, 565ae188c676c681e47a93ade7fdf0144099b470e03Carl Shapiro spec->doPreserve == false, 566e8ef2b53866b01fb5a8e73ea867c934777aec57eCarl Shapiro &gcHeap->weakReferences, 5673475f9cdb47a6d6f8ad2ce49bbc3af46bca92f09Carl Shapiro &gcHeap->finalizerReferences, 568e8ef2b53866b01fb5a8e73ea867c934777aec57eCarl Shapiro &gcHeap->phantomReferences); 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 5708881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro#if defined(WITH_JIT) 5718881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro /* 5728881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * Patching a chaining cell is very cheap as it only updates 4 words. It's 5738881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * the overhead of stopping all threads and synchronizing the I/D cache 5748881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * that makes it expensive. 5758881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * 5768881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * Therefore we batch those work orders in a queue and go through them 5778881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * when threads are suspended for GC. 5788881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro */ 5798881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro dvmCompilerPerformSafePointChecks(); 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 5818881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Sweeping..."); 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 5848881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro dvmHeapSweepSystemWeaks(); 5858881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro 5868881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro /* 5878881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * Live objects have a bit set in the mark bitmap, swap the mark 5888881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * and live bitmaps. The sweep can proceed concurrently viewing 5898881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * the new live bitmap as the old mark bitmap, and vice versa. 5908881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro */ 5918881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro dvmHeapSourceSwapBitmaps(); 5928881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro 5938881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro if (gDvm.postVerify) { 5948881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro LOGV_HEAP("Verifying roots and heap after GC"); 5958881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro verifyRootsAndHeap(); 5968881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro } 5978881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro 598cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro if (spec->isConcurrent) { 5998881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro dvmUnlockHeap(); 6008881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro dvmResumeAllThreads(SUSPEND_FOR_GC); 60189cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown dirtyEnd = dvmGetRelativeTimeMsec(); 6028881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro } 603cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro dvmHeapSweepUnmarkedObjects(spec->isPartial, spec->isConcurrent, 604570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro &numObjectsFreed, &numBytesFreed); 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Cleaning up..."); 606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHeapFinishMarkStep(); 607cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro if (spec->isConcurrent) { 6088881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro dvmLockHeap(); 6098881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro } 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("Done."); 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Now's a good time to adjust the heap size, since 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we know what our utilization is. 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This doesn't actually resize any memory; 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it just lets the heap grow more when necessary. 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 619e7bdd8b8c6f3aae552b333d0bd9664ef5e63f0a0Carl Shapiro dvmHeapSourceGrowForUtilization(); 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 621570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro currAllocated = dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0); 622570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro currFootprint = dvmHeapSourceGetValue(HS_FOOTPRINT, NULL, 0); 623570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmMethodTraceGCEnd(); 625962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes LOGV_HEAP("GC finished"); 626962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->gcRunning = false; 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 629962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes LOGV_HEAP("Resuming threads"); 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 631cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro if (spec->isConcurrent) { 632ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro /* 633ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * Wake-up any threads that blocked after a failed allocation 634ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * request. 635ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro */ 636ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro dvmBroadcastCond(&gDvm.gcHeapCond); 637ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro } 638ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro 639cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro if (!spec->isConcurrent) { 6408881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro dvmResumeAllThreads(SUSPEND_FOR_GC); 64189cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown dirtyEnd = dvmGetRelativeTimeMsec(); 642cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro /* 643cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro * Restore the original thread scheduling priority if it was 644cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro * changed at the start of the current garbage collection. 645cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro */ 646cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro if (oldThreadPriority != INT_MAX) { 647e6c0ef210ee6c62cf4c63d50c04f451d5fa505f5Elliott Hughes os_lowerThreadPriority(oldThreadPriority); 648256fc159a267859c18e11e1d15fd7d97a59757c6San Mehat } 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 651ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro /* 652ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro * Move queue of pending references back into Java. 653ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro */ 654ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro dvmEnqueueClearedReferences(&gDvm.gcHeap->clearedReferences); 655ce87bfed41bbe4248b2770fb1a90f34b2518f6faCarl Shapiro 65689cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown gcEnd = dvmGetRelativeTimeMsec(); 657570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro percentFree = 100 - (size_t)(100.0f * (float)currAllocated / currFootprint); 658cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro if (!spec->isConcurrent) { 65903f3b1394cc8421d125fd00455858944f0e9808dCarl Shapiro u4 markSweepTime = dirtyEnd - rootStart; 66089cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown u4 gcTime = gcEnd - rootStart; 661570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro bool isSmall = numBytesFreed > 0 && numBytesFreed < 1024; 66289cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown ALOGD("%s freed %s%zdK, %d%% free %zdK/%zdK, paused %ums, total %ums", 663cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro spec->reason, 664570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro isSmall ? "<" : "", 665570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro numBytesFreed ? MAX(numBytesFreed / 1024, 1) : 0, 666570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro percentFree, 667570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro currAllocated / 1024, currFootprint / 1024, 66889cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown markSweepTime, gcTime); 66903f3b1394cc8421d125fd00455858944f0e9808dCarl Shapiro } else { 6708881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro u4 rootTime = rootEnd - rootStart; 6718881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro u4 dirtyTime = dirtyEnd - dirtyStart; 67289cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown u4 gcTime = gcEnd - rootStart; 673570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro bool isSmall = numBytesFreed > 0 && numBytesFreed < 1024; 67489cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown ALOGD("%s freed %s%zdK, %d%% free %zdK/%zdK, paused %ums+%ums, total %ums", 675cc6f5118d19bae06cb80841386a0c95f24616a65Carl Shapiro spec->reason, 676570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro isSmall ? "<" : "", 677570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro numBytesFreed ? MAX(numBytesFreed / 1024, 1) : 0, 678570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro percentFree, 679570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro currAllocated / 1024, currFootprint / 1024, 68089cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown rootTime, dirtyTime, gcTime); 681570942c26061692dc30e3c8ac1dc28d50170ef6aCarl Shapiro } 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->ddmHpifWhen != 0) { 68360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD_HEAP("Sending VM heap info to DDM"); 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDdmSendHeapInfo(gcHeap->ddmHpifWhen, false); 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->ddmHpsgWhen != 0) { 68760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD_HEAP("Dumping VM heap to DDM"); 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDdmSendHeapSegments(false, false); 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap->ddmNhsgWhen != 0) { 69160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD_HEAP("Dumping native heap to DDM"); 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDdmSendHeapSegments(false, true); 693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 69658aa611bb6f45eab669644b97e77165eb417458aAndy McFadden/* 69758aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * If the concurrent GC is running, wait for it to finish. The caller 69858aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * must hold the heap lock. 69958aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * 70058aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * Note: the second dvmChangeStatus() could stall if we were in RUNNING 70158aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * on entry, and some other thread has asked us to suspend. In that 70258aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * case we will be suspended with the heap lock held, which can lead to 70358aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * deadlock if the other thread tries to do something with the managed heap. 70458aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * For example, the debugger might suspend us and then execute a method that 70558aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * allocates memory. We can avoid this situation by releasing the lock 70658aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * before self-suspending. (The developer can work around this specific 70758aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * situation by single-stepping the VM. Alternatively, we could disable 70858aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * concurrent GC when the debugger is attached, but that might change 70958aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * behavior more than is desirable.) 71058aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * 71158aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * This should not be a problem in production, because any GC-related 71258aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * activity will grab the lock before issuing a suspend-all. (We may briefly 71358aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * suspend when the GC thread calls dvmUnlockHeap before dvmResumeAllThreads, 71458aa611bb6f45eab669644b97e77165eb417458aAndy McFadden * but there's no risk of deadlock.) 71558aa611bb6f45eab669644b97e77165eb417458aAndy McFadden */ 7161e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmWaitForConcurrentGcToComplete() 717ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro{ 718ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro Thread *self = dvmThreadSelf(); 719ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro assert(self != NULL); 72089cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown u4 start = dvmGetRelativeTimeMsec(); 721039167e7894ae16880f51fa0b4d44316318aae1eCarl Shapiro while (gDvm.gcHeap->gcRunning) { 722039167e7894ae16880f51fa0b4d44316318aae1eCarl Shapiro ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); 723039167e7894ae16880f51fa0b4d44316318aae1eCarl Shapiro dvmWaitCond(&gDvm.gcHeapCond, &gDvm.gcHeapLock); 724039167e7894ae16880f51fa0b4d44316318aae1eCarl Shapiro dvmChangeStatus(self, oldStatus); 725039167e7894ae16880f51fa0b4d44316318aae1eCarl Shapiro } 72689cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown u4 end = dvmGetRelativeTimeMsec(); 72789cf125cd95a7df3a713cb3d3d39a033304e474cJeff Brown ALOGD("WAIT_FOR_CONCURRENT_GC blocked %ums", end - start); 728ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro} 729