blob: bbf2cc4fff95f72de2d59058eb717574fc5e0615 [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/*
17 * Garbage-collecting memory allocator.
18 */
19#include "Dalvik.h"
Barry Hayes962adba2010-03-17 12:12:39 -070020#include "alloc/HeapBitmap.h"
21#include "alloc/Verify.h"
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080022#include "alloc/HeapTable.h"
23#include "alloc/Heap.h"
24#include "alloc/HeapInternal.h"
25#include "alloc/DdmHeap.h"
26#include "alloc/HeapSource.h"
27#include "alloc/MarkSweep.h"
28
29#include "utils/threads.h" // need Android thread priorities
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080030
San Mehat5a2056c2009-09-12 10:10:13 -070031#include <cutils/sched_policy.h>
32
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080033#include <sys/time.h>
34#include <sys/resource.h>
35#include <limits.h>
36#include <errno.h>
37
Carl Shapirocc6f5112011-01-26 17:25:27 -080038static const GcSpec kGcForMallocSpec = {
Carl Shapiro9b6881c2011-01-26 18:41:03 -080039 true, /* isPartial */
40 false, /* isConcurrent */
Carl Shapirocc6f5112011-01-26 17:25:27 -080041 PRESERVE,
42 "GC_FOR_ALLOC"
Barry Hayes1b9b4e42010-01-04 10:33:46 -080043};
44
Carl Shapirocc6f5112011-01-26 17:25:27 -080045const GcSpec *GC_FOR_MALLOC = &kGcForMallocSpec;
46
47static const GcSpec kGcConcurrentSpec = {
Carl Shapiro9b6881c2011-01-26 18:41:03 -080048 true, /* isPartial */
49 true, /* isConcurrent */
Carl Shapirocc6f5112011-01-26 17:25:27 -080050 PRESERVE,
51 "GC_CONCURRENT"
52};
53
54const GcSpec *GC_CONCURRENT = &kGcConcurrentSpec;
55
56static const GcSpec kGcExplicitSpec = {
Carl Shapiro9b6881c2011-01-26 18:41:03 -080057 false, /* isPartial */
58 true, /* isConcurrent */
Carl Shapirocc6f5112011-01-26 17:25:27 -080059 PRESERVE,
60 "GC_EXPLICIT"
61};
62
63const GcSpec *GC_EXPLICIT = &kGcExplicitSpec;
64
65static const GcSpec kGcBeforeOomSpec = {
Carl Shapiro9b6881c2011-01-26 18:41:03 -080066 false, /* isPartial */
67 false, /* isConcurrent */
Carl Shapirocc6f5112011-01-26 17:25:27 -080068 CLEAR,
69 "GC_BEFORE_OOM"
70};
71
72const GcSpec *GC_BEFORE_OOM = &kGcBeforeOomSpec;
73
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080074/*
75 * Initialize the GC heap.
76 *
77 * Returns true if successful, false otherwise.
78 */
79bool dvmHeapStartup()
80{
81 GcHeap *gcHeap;
82
Carl Shapirodf9f08b2011-01-18 17:59:30 -080083 if (gDvm.heapGrowthLimit == 0) {
84 gDvm.heapGrowthLimit = gDvm.heapMaximumSize;
85 }
86
87 gcHeap = dvmHeapSourceStartup(gDvm.heapStartingSize,
88 gDvm.heapMaximumSize,
89 gDvm.heapGrowthLimit);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080090 if (gcHeap == NULL) {
91 return false;
92 }
93 gcHeap->heapWorkerCurrentObject = NULL;
94 gcHeap->heapWorkerCurrentMethod = NULL;
95 gcHeap->heapWorkerInterpStartTime = 0LL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080096 gcHeap->ddmHpifWhen = 0;
97 gcHeap->ddmHpsgWhen = 0;
98 gcHeap->ddmHpsgWhat = 0;
99 gcHeap->ddmNhsgWhen = 0;
100 gcHeap->ddmNhsgWhat = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800101 gDvm.gcHeap = gcHeap;
102
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800103 /* Set up the lists and lock we'll use for finalizable
104 * and reference objects.
105 */
106 dvmInitMutex(&gDvm.heapWorkerListLock);
107 gcHeap->finalizableRefs = NULL;
108 gcHeap->pendingFinalizationRefs = NULL;
109 gcHeap->referenceOperations = NULL;
110
Carl Shapirodf9f08b2011-01-18 17:59:30 -0800111 if (!dvmCardTableStartup(gDvm.heapMaximumSize)) {
Barry Hayesb874ab92010-07-14 08:13:18 -0700112 LOGE_HEAP("card table startup failed.");
113 return false;
114 }
115
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800116 /* Initialize the HeapWorker locks and other state
117 * that the GC uses.
118 */
119 dvmInitializeHeapWorkerState();
120
121 return true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800122}
123
Carl Shapiroec805ea2010-06-28 16:28:26 -0700124bool dvmHeapStartupAfterZygote(void)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800125{
Carl Shapiroec805ea2010-06-28 16:28:26 -0700126 return dvmHeapSourceStartupAfterZygote();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800127}
128
129void dvmHeapShutdown()
130{
131//TODO: make sure we're locked
132 if (gDvm.gcHeap != NULL) {
Barry Hayesb874ab92010-07-14 08:13:18 -0700133 dvmCardTableShutdown();
134 /* Tables are allocated on the native heap; they need to be
135 * cleaned up explicitly. The process may stick around, so we
136 * don't want to leak any native memory.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800137 */
Carl Shapiroa199eb72010-02-09 16:26:30 -0800138 dvmHeapFreeLargeTable(gDvm.gcHeap->finalizableRefs);
139 gDvm.gcHeap->finalizableRefs = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800140
Carl Shapiroa199eb72010-02-09 16:26:30 -0800141 dvmHeapFreeLargeTable(gDvm.gcHeap->pendingFinalizationRefs);
142 gDvm.gcHeap->pendingFinalizationRefs = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800143
Carl Shapiroa199eb72010-02-09 16:26:30 -0800144 dvmHeapFreeLargeTable(gDvm.gcHeap->referenceOperations);
145 gDvm.gcHeap->referenceOperations = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800146
Barry Hayesb874ab92010-07-14 08:13:18 -0700147 /* Destroy the heap. Any outstanding pointers will point to
148 * unmapped memory (unless/until someone else maps it). This
149 * frees gDvm.gcHeap as a side-effect.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800150 */
Carl Shapiroa199eb72010-02-09 16:26:30 -0800151 dvmHeapSourceShutdown(&gDvm.gcHeap);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800152 }
153}
154
155/*
Carl Shapiroec805ea2010-06-28 16:28:26 -0700156 * Shutdown any threads internal to the heap.
157 */
158void dvmHeapThreadShutdown(void)
159{
160 dvmHeapSourceThreadShutdown();
161}
162
163/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800164 * We've been asked to allocate something we can't, e.g. an array so
Andy McFadden6da743b2009-07-15 16:56:00 -0700165 * large that (length * elementWidth) is larger than 2^31.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800166 *
Andy McFadden6da743b2009-07-15 16:56:00 -0700167 * _The Java Programming Language_, 4th edition, says, "you can be sure
168 * that all SoftReferences to softly reachable objects will be cleared
169 * before an OutOfMemoryError is thrown."
170 *
171 * It's unclear whether that holds for all situations where an OOM can
172 * be thrown, or just in the context of an allocation that fails due
173 * to lack of heap space. For simplicity we just throw the exception.
174 *
175 * (OOM due to actually running out of space is handled elsewhere.)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800176 */
177void dvmThrowBadAllocException(const char* msg)
178{
Andy McFadden6da743b2009-07-15 16:56:00 -0700179 dvmThrowException("Ljava/lang/OutOfMemoryError;", msg);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800180}
181
182/*
183 * Grab the lock, but put ourselves into THREAD_VMWAIT if it looks like
184 * we're going to have to wait on the mutex.
185 */
186bool dvmLockHeap()
187{
Carl Shapiro980ffb02010-03-13 22:34:01 -0800188 if (dvmTryLockMutex(&gDvm.gcHeapLock) != 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800189 Thread *self;
190 ThreadStatus oldStatus;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800191
192 self = dvmThreadSelf();
Carl Shapiro5617ad32010-07-02 10:50:57 -0700193 oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
Carl Shapiro980ffb02010-03-13 22:34:01 -0800194 dvmLockMutex(&gDvm.gcHeapLock);
Carl Shapiro5617ad32010-07-02 10:50:57 -0700195 dvmChangeStatus(self, oldStatus);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800196 }
197
198 return true;
199}
200
201void dvmUnlockHeap()
202{
203 dvmUnlockMutex(&gDvm.gcHeapLock);
204}
205
206/* Pop an object from the list of pending finalizations and
207 * reference clears/enqueues, and return the object.
208 * The caller must call dvmReleaseTrackedAlloc()
209 * on the object when finished.
210 *
211 * Typically only called by the heap worker thread.
212 */
213Object *dvmGetNextHeapWorkerObject(HeapWorkerOperation *op)
214{
215 Object *obj;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800216 GcHeap *gcHeap = gDvm.gcHeap;
217
218 assert(op != NULL);
219
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800220 dvmLockMutex(&gDvm.heapWorkerListLock);
221
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800222 obj = dvmHeapGetNextObjectFromLargeTable(&gcHeap->referenceOperations);
223 if (obj != NULL) {
Carl Shapiro646ba092010-06-10 15:17:00 -0700224 *op = WORKER_ENQUEUE;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800225 } else {
226 obj = dvmHeapGetNextObjectFromLargeTable(
227 &gcHeap->pendingFinalizationRefs);
228 if (obj != NULL) {
229 *op = WORKER_FINALIZE;
230 }
231 }
232
233 if (obj != NULL) {
234 /* Don't let the GC collect the object until the
235 * worker thread is done with it.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800236 */
237 dvmAddTrackedAlloc(obj, NULL);
238 }
239
240 dvmUnlockMutex(&gDvm.heapWorkerListLock);
241
242 return obj;
243}
244
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800245/* Do a full garbage collection, which may grow the
246 * heap as a side-effect if the live set is large.
247 */
Carl Shapiroa371fad2011-01-23 15:58:31 -0800248static void gcForMalloc(bool clearSoftReferences)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800249{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800250 if (gDvm.allocProf.enabled) {
251 Thread* self = dvmThreadSelf();
252 gDvm.allocProf.gcCount++;
253 if (self != NULL) {
254 self->allocProf.gcCount++;
255 }
256 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800257 /* This may adjust the soft limit as a side-effect.
258 */
Carl Shapirocc6f5112011-01-26 17:25:27 -0800259 const GcSpec *spec = clearSoftReferences ? GC_BEFORE_OOM : GC_FOR_MALLOC;
260 dvmCollectGarbageInternal(spec);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800261}
262
263/* Try as hard as possible to allocate some memory.
264 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800265static void *tryMalloc(size_t size)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800266{
Carl Shapiro6343bd02010-02-16 17:40:19 -0800267 void *ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800268
269 /* Don't try too hard if there's no way the allocation is
270 * going to succeed. We have to collect SoftReferences before
271 * throwing an OOME, though.
272 */
Carl Shapirodf9f08b2011-01-18 17:59:30 -0800273 if (size >= gDvm.heapGrowthLimit) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800274 LOGW_HEAP("dvmMalloc(%zu/0x%08zx): "
275 "someone's allocating a huge buffer\n", size, size);
Carl Shapiro6343bd02010-02-16 17:40:19 -0800276 ptr = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800277 goto collect_soft_refs;
278 }
279
280//TODO: figure out better heuristics
281// There will be a lot of churn if someone allocates a bunch of
282// big objects in a row, and we hit the frag case each time.
283// A full GC for each.
284// Maybe we grow the heap in bigger leaps
285// Maybe we skip the GC if the size is large and we did one recently
286// (number of allocations ago) (watch for thread effects)
287// DeflateTest allocs a bunch of ~128k buffers w/in 0-5 allocs of each other
288// (or, at least, there are only 0-5 objects swept each time)
289
Carl Shapiro6343bd02010-02-16 17:40:19 -0800290 ptr = dvmHeapSourceAlloc(size);
291 if (ptr != NULL) {
292 return ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800293 }
294
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700295 /*
296 * The allocation failed. If the GC is running, block until it
297 * completes and retry.
298 */
299 if (gDvm.gcHeap->gcRunning) {
300 /*
301 * The GC is concurrently tracing the heap. Release the heap
302 * lock, wait for the GC to complete, and retrying allocating.
303 */
304 dvmWaitForConcurrentGcToComplete();
305 ptr = dvmHeapSourceAlloc(size);
306 if (ptr != NULL) {
307 return ptr;
308 }
309 }
310 /*
311 * Another failure. Our thread was starved or there may be too
312 * many live objects. Try a foreground GC. This will have no
313 * effect if the concurrent GC is already running.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800314 */
315 gcForMalloc(false);
Carl Shapiro6343bd02010-02-16 17:40:19 -0800316 ptr = dvmHeapSourceAlloc(size);
317 if (ptr != NULL) {
318 return ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800319 }
320
321 /* Even that didn't work; this is an exceptional state.
322 * Try harder, growing the heap if necessary.
323 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800324 ptr = dvmHeapSourceAllocAndGrow(size);
Carl Shapiro6343bd02010-02-16 17:40:19 -0800325 if (ptr != NULL) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800326 size_t newHeapSize;
327
328 newHeapSize = dvmHeapSourceGetIdealFootprint();
329//TODO: may want to grow a little bit more so that the amount of free
330// space is equal to the old free space + the utilization slop for
331// the new allocation.
332 LOGI_HEAP("Grow heap (frag case) to "
333 "%zu.%03zuMB for %zu-byte allocation\n",
334 FRACTIONAL_MB(newHeapSize), size);
Carl Shapiro6343bd02010-02-16 17:40:19 -0800335 return ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800336 }
337
338 /* Most allocations should have succeeded by now, so the heap
339 * is really full, really fragmented, or the requested size is
340 * really big. Do another GC, collecting SoftReferences this
341 * time. The VM spec requires that all SoftReferences have
342 * been collected and cleared before throwing an OOME.
343 */
344//TODO: wait for the finalizers from the previous GC to finish
345collect_soft_refs:
346 LOGI_HEAP("Forcing collection of SoftReferences for %zu-byte allocation\n",
347 size);
348 gcForMalloc(true);
Carl Shapiro6343bd02010-02-16 17:40:19 -0800349 ptr = dvmHeapSourceAllocAndGrow(size);
Carl Shapiro6343bd02010-02-16 17:40:19 -0800350 if (ptr != NULL) {
351 return ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800352 }
353//TODO: maybe wait for finalizers and try one last time
354
355 LOGE_HEAP("Out of memory on a %zd-byte allocation.\n", size);
356//TODO: tell the HeapSource to dump its state
357 dvmDumpThread(dvmThreadSelf(), false);
358
359 return NULL;
360}
361
362/* Throw an OutOfMemoryError if there's a thread to attach it to.
363 * Avoid recursing.
364 *
365 * The caller must not be holding the heap lock, or else the allocations
366 * in dvmThrowException() will deadlock.
367 */
368static void throwOOME()
369{
370 Thread *self;
371
372 if ((self = dvmThreadSelf()) != NULL) {
373 /* If the current (failing) dvmMalloc() happened as part of thread
374 * creation/attachment before the thread became part of the root set,
375 * we can't rely on the thread-local trackedAlloc table, so
376 * we can't keep track of a real allocated OOME object. But, since
377 * the thread is in the process of being created, it won't have
378 * a useful stack anyway, so we may as well make things easier
379 * by throwing the (stackless) pre-built OOME.
380 */
381 if (dvmIsOnThreadList(self) && !self->throwingOOME) {
382 /* Let ourselves know that we tried to throw an OOM
383 * error in the normal way in case we run out of
384 * memory trying to allocate it inside dvmThrowException().
385 */
386 self->throwingOOME = true;
387
388 /* Don't include a description string;
389 * one fewer allocation.
390 */
391 dvmThrowException("Ljava/lang/OutOfMemoryError;", NULL);
392 } else {
393 /*
394 * This thread has already tried to throw an OutOfMemoryError,
395 * which probably means that we're running out of memory
396 * while recursively trying to throw.
397 *
398 * To avoid any more allocation attempts, "throw" a pre-built
399 * OutOfMemoryError object (which won't have a useful stack trace).
400 *
401 * Note that since this call can't possibly allocate anything,
402 * we don't care about the state of self->throwingOOME
403 * (which will usually already be set).
404 */
405 dvmSetException(self, gDvm.outOfMemoryObj);
406 }
407 /* We're done with the possible recursion.
408 */
409 self->throwingOOME = false;
410 }
411}
412
413/*
414 * Allocate storage on the GC heap. We guarantee 8-byte alignment.
415 *
416 * The new storage is zeroed out.
417 *
418 * Note that, in rare cases, this could get called while a GC is in
419 * progress. If a non-VM thread tries to attach itself through JNI,
420 * it will need to allocate some objects. If this becomes annoying to
421 * deal with, we can block it at the source, but holding the allocation
422 * mutex should be enough.
423 *
424 * In rare circumstances (JNI AttachCurrentThread) we can be called
425 * from a non-VM thread.
426 *
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800427 * Use ALLOC_DONT_TRACK when we either don't want to track an allocation
428 * (because it's being done for the interpreter "new" operation and will
429 * be part of the root set immediately) or we can't (because this allocation
430 * is for a brand new thread).
431 *
432 * Returns NULL and throws an exception on failure.
433 *
434 * TODO: don't do a GC if the debugger thinks all threads are suspended
435 */
436void* dvmMalloc(size_t size, int flags)
437{
438 GcHeap *gcHeap = gDvm.gcHeap;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800439 void *ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800440
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800441 dvmLockHeap();
442
443 /* Try as hard as possible to allocate some memory.
444 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800445 ptr = tryMalloc(size);
446 if (ptr != NULL) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800447 /* We've got the memory.
448 */
449 if ((flags & ALLOC_FINALIZABLE) != 0) {
450 /* This object is an instance of a class that
451 * overrides finalize(). Add it to the finalizable list.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800452 */
453 if (!dvmHeapAddRefToLargeTable(&gcHeap->finalizableRefs,
Carl Shapiro6343bd02010-02-16 17:40:19 -0800454 (Object *)ptr))
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800455 {
456 LOGE_HEAP("dvmMalloc(): no room for any more "
457 "finalizable objects\n");
458 dvmAbort();
459 }
460 }
461
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800462 if (gDvm.allocProf.enabled) {
463 Thread* self = dvmThreadSelf();
464 gDvm.allocProf.allocCount++;
465 gDvm.allocProf.allocSize += size;
466 if (self != NULL) {
467 self->allocProf.allocCount++;
468 self->allocProf.allocSize += size;
469 }
470 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800471 } else {
472 /* The allocation failed.
473 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800474
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800475 if (gDvm.allocProf.enabled) {
476 Thread* self = dvmThreadSelf();
477 gDvm.allocProf.failedAllocCount++;
478 gDvm.allocProf.failedAllocSize += size;
479 if (self != NULL) {
480 self->allocProf.failedAllocCount++;
481 self->allocProf.failedAllocSize += size;
482 }
483 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800484 }
485
486 dvmUnlockHeap();
487
488 if (ptr != NULL) {
489 /*
Barry Hayesd4f78d32010-06-08 09:34:42 -0700490 * If caller hasn't asked us not to track it, add it to the
491 * internal tracking list.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800492 */
Barry Hayesd4f78d32010-06-08 09:34:42 -0700493 if ((flags & ALLOC_DONT_TRACK) == 0) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800494 dvmAddTrackedAlloc((Object*)ptr, NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800495 }
496 } else {
Ben Chengc3b92b22010-01-26 16:46:15 -0800497 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800498 * The allocation failed; throw an OutOfMemoryError.
499 */
500 throwOOME();
501 }
502
503 return ptr;
504}
505
506/*
507 * Returns true iff <obj> points to a valid allocated object.
508 */
509bool dvmIsValidObject(const Object* obj)
510{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800511 /* Don't bother if it's NULL or not 8-byte aligned.
512 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800513 if (obj != NULL && ((uintptr_t)obj & (8-1)) == 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800514 /* Even if the heap isn't locked, this shouldn't return
515 * any false negatives. The only mutation that could
516 * be happening is allocation, which means that another
517 * thread could be in the middle of a read-modify-write
518 * to add a new bit for a new object. However, that
519 * RMW will have completed by the time any other thread
520 * could possibly see the new pointer, so there is no
521 * danger of dvmIsValidObject() being called on a valid
522 * pointer whose bit isn't set.
523 *
524 * Freeing will only happen during the sweep phase, which
525 * only happens while the heap is locked.
526 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800527 return dvmHeapSourceContains(obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800528 }
529 return false;
530}
531
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800532size_t dvmObjectSizeInHeap(const Object *obj)
533{
Carl Shapiro6343bd02010-02-16 17:40:19 -0800534 return dvmHeapSourceChunkSize(obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800535}
536
Carl Shapiro6c5dd932010-08-05 21:49:07 -0700537static void verifyRootsAndHeap(void)
Barry Hayes962adba2010-03-17 12:12:39 -0700538{
Carl Shapiro106c5fd2010-07-28 14:12:27 -0700539 dvmVerifyRoots();
540 dvmVerifyBitmap(dvmHeapSourceGetLiveBits());
Barry Hayes962adba2010-03-17 12:12:39 -0700541}
542
543/*
Carl Shapirocc6f5112011-01-26 17:25:27 -0800544 * Raises the scheduling priority of the current thread. Returns the
545 * original priority if successful. Otherwise, returns INT_MAX on
546 * failure.
547 */
548static int raiseThreadPriority(void)
549{
550 /* Get the priority (the "nice" value) of the current thread. The
551 * getpriority() call can legitimately return -1, so we have to
552 * explicitly test errno.
553 */
554 errno = 0;
555 int oldThreadPriority = getpriority(PRIO_PROCESS, 0);
556 if (errno != 0) {
557 LOGI_HEAP("getpriority(self) failed: %s", strerror(errno));
558 } else if (oldThreadPriority > ANDROID_PRIORITY_NORMAL) {
559 /* Current value is numerically greater than "normal", which
560 * in backward UNIX terms means lower priority.
561 */
562 if (oldThreadPriority >= ANDROID_PRIORITY_BACKGROUND) {
563 set_sched_policy(dvmGetSysThreadId(), SP_FOREGROUND);
564 }
565 if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL) != 0) {
566 LOGI_HEAP("Unable to elevate priority from %d to %d",
567 oldThreadPriority, ANDROID_PRIORITY_NORMAL);
568 } else {
569 /*
570 * The priority has been elevated. Return the old value
571 * so the caller can restore it later.
572 */
573 LOGD_HEAP("Elevating priority from %d to %d",
574 oldThreadPriority, ANDROID_PRIORITY_NORMAL);
575 return oldThreadPriority;
576 }
577 }
578 return INT_MAX;
579}
580
581/*
582 * Sets the current thread scheduling priority.
583 */
584static void setThreadPriority(int newThreadPriority)
585{
586 if (setpriority(PRIO_PROCESS, 0, newThreadPriority) != 0) {
587 LOGW_HEAP("Unable to reset priority to %d: %s",
588 newThreadPriority, strerror(errno));
589 } else {
590 LOGD_HEAP("Reset priority to %d", oldThreadPriority);
591 }
592 if (newThreadPriority >= ANDROID_PRIORITY_BACKGROUND) {
593 set_sched_policy(dvmGetSysThreadId(), SP_BACKGROUND);
594 }
595}
596
597/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800598 * Initiate garbage collection.
599 *
600 * NOTES:
601 * - If we don't hold gDvm.threadListLock, it's possible for a thread to
602 * be added to the thread list while we work. The thread should NOT
603 * start executing, so this is only interesting when we start chasing
604 * thread stacks. (Before we do so, grab the lock.)
605 *
606 * We are not allowed to GC when the debugger has suspended the VM, which
607 * is awkward because debugger requests can cause allocations. The easiest
608 * way to enforce this is to refuse to GC on an allocation made by the
609 * JDWP thread -- we have to expand the heap or fail.
610 */
Carl Shapirocc6f5112011-01-26 17:25:27 -0800611void dvmCollectGarbageInternal(const GcSpec* spec)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800612{
613 GcHeap *gcHeap = gDvm.gcHeap;
Carl Shapirocc6f5112011-01-26 17:25:27 -0800614 u4 rootSuspend, rootSuspendTime, rootStart = 0 , rootEnd = 0;
615 u4 dirtySuspend, dirtyStart = 0, dirtyEnd = 0;
Carl Shapiro8881a802010-08-10 15:55:45 -0700616 u4 totalTime;
Carl Shapiro570942c2010-09-17 15:53:16 -0700617 size_t numObjectsFreed, numBytesFreed;
618 size_t currAllocated, currFootprint;
Carl Shapiro570942c2010-09-17 15:53:16 -0700619 size_t percentFree;
Carl Shapirocc6f5112011-01-26 17:25:27 -0800620 int oldThreadPriority = INT_MAX;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800621
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800622 /* The heap lock must be held.
623 */
624
625 if (gcHeap->gcRunning) {
626 LOGW_HEAP("Attempted recursive GC\n");
627 return;
628 }
Carl Shapiro03f3b132010-07-27 17:25:31 -0700629
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800630 gcHeap->gcRunning = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800631
Andy McFadden58aa6112011-01-19 14:48:52 -0800632 /*
633 * Grab the heapWorkerLock to prevent the HeapWorker thread from
634 * doing work. If it's executing a finalizer or an enqueue operation
635 * it won't be holding the lock, so this should return quickly.
636 */
637 dvmLockMutex(&gDvm.heapWorkerLock);
638
Carl Shapiro8881a802010-08-10 15:55:45 -0700639 rootSuspend = dvmGetRelativeTimeMsec();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800640 dvmSuspendAllThreads(SUSPEND_FOR_GC);
Carl Shapiro03f3b132010-07-27 17:25:31 -0700641 rootStart = dvmGetRelativeTimeMsec();
Carl Shapiro8881a802010-08-10 15:55:45 -0700642 rootSuspendTime = rootStart - rootSuspend;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800643
Carl Shapiroec805ea2010-06-28 16:28:26 -0700644 /*
645 * If we are not marking concurrently raise the priority of the
646 * thread performing the garbage collection.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800647 */
Carl Shapirocc6f5112011-01-26 17:25:27 -0800648 if (!spec->isConcurrent) {
649 oldThreadPriority = raiseThreadPriority();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800650 }
651
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800652 /* Make sure that the HeapWorker thread hasn't become
653 * wedged inside interp code. If it has, this call will
654 * print a message and abort the VM.
655 */
656 dvmAssertHeapWorkerThreadRunning();
657
658 /* Lock the pendingFinalizationRefs list.
659 *
660 * Acquire the lock after suspending so the finalizer
661 * thread can't block in the RUNNING state while
662 * we try to suspend.
663 */
664 dvmLockMutex(&gDvm.heapWorkerListLock);
665
Barry Hayes962adba2010-03-17 12:12:39 -0700666 if (gDvm.preVerify) {
Carl Shapiro6c5dd932010-08-05 21:49:07 -0700667 LOGV_HEAP("Verifying roots and heap before GC");
668 verifyRootsAndHeap();
Barry Hayes962adba2010-03-17 12:12:39 -0700669 }
670
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800671 dvmMethodTraceGCBegin();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800672
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800673 /* Set up the marking context.
674 */
Carl Shapirocc6f5112011-01-26 17:25:27 -0800675 if (!dvmHeapBeginMarkStep(spec->isPartial)) {
The Android Open Source Project99409882009-03-18 22:20:24 -0700676 LOGE_HEAP("dvmHeapBeginMarkStep failed; aborting\n");
677 dvmAbort();
678 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800679
680 /* Mark the set of objects that are strongly reachable from the roots.
681 */
682 LOGD_HEAP("Marking...");
683 dvmHeapMarkRootSet();
684
685 /* dvmHeapScanMarkedObjects() will build the lists of known
686 * instances of the Reference classes.
687 */
688 gcHeap->softReferences = NULL;
689 gcHeap->weakReferences = NULL;
690 gcHeap->phantomReferences = NULL;
691
Carl Shapirocc6f5112011-01-26 17:25:27 -0800692 if (spec->isConcurrent) {
Carl Shapiroec805ea2010-06-28 16:28:26 -0700693 /*
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700694 * Resume threads while tracing from the roots. We unlock the
695 * heap to allow mutator threads to allocate from free space.
Carl Shapiroec805ea2010-06-28 16:28:26 -0700696 */
Carl Shapiro03f3b132010-07-27 17:25:31 -0700697 rootEnd = dvmGetRelativeTimeMsec();
Carl Shapiro106c5fd2010-07-28 14:12:27 -0700698 dvmClearCardTable();
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700699 dvmUnlockHeap();
Carl Shapiroec805ea2010-06-28 16:28:26 -0700700 dvmResumeAllThreads(SUSPEND_FOR_GC);
701 }
702
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800703 /* Recursively mark any objects that marked objects point to strongly.
704 * If we're not collecting soft references, soft-reachable
705 * objects will also be marked.
706 */
707 LOGD_HEAP("Recursing...");
708 dvmHeapScanMarkedObjects();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800709
Carl Shapirocc6f5112011-01-26 17:25:27 -0800710 if (spec->isConcurrent) {
Carl Shapiroec805ea2010-06-28 16:28:26 -0700711 /*
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700712 * Re-acquire the heap lock and perform the final thread
713 * suspension.
Carl Shapiroec805ea2010-06-28 16:28:26 -0700714 */
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700715 dvmLockHeap();
Carl Shapiro8881a802010-08-10 15:55:45 -0700716 dirtySuspend = dvmGetRelativeTimeMsec();
Carl Shapiroec805ea2010-06-28 16:28:26 -0700717 dvmSuspendAllThreads(SUSPEND_FOR_GC);
Carl Shapiro03f3b132010-07-27 17:25:31 -0700718 dirtyStart = dvmGetRelativeTimeMsec();
Carl Shapiroec805ea2010-06-28 16:28:26 -0700719 /*
720 * As no barrier intercepts root updates, we conservatively
721 * assume all roots may be gray and re-mark them.
722 */
Carl Shapiro106c5fd2010-07-28 14:12:27 -0700723 dvmHeapReMarkRootSet();
Carl Shapiroec805ea2010-06-28 16:28:26 -0700724 /*
Carl Shapiro5ba39372010-08-06 17:07:53 -0700725 * With the exception of reference objects and weak interned
726 * strings, all gray objects should now be on dirty cards.
727 */
728 if (gDvm.verifyCardTable) {
729 dvmVerifyCardTable();
730 }
731 /*
Carl Shapiroec805ea2010-06-28 16:28:26 -0700732 * Recursively mark gray objects pointed to by the roots or by
733 * heap objects dirtied during the concurrent mark.
734 */
Carl Shapiro106c5fd2010-07-28 14:12:27 -0700735 dvmHeapReScanMarkedObjects();
Carl Shapiroec805ea2010-06-28 16:28:26 -0700736 }
737
Carl Shapiroe8ef2b52010-12-01 19:32:05 -0800738 /*
739 * All strongly-reachable objects have now been marked. Process
740 * weakly-reachable objects discovered while tracing.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800741 */
Carl Shapirocc6f5112011-01-26 17:25:27 -0800742 dvmHeapProcessReferences(&gcHeap->softReferences,
743 spec->softReferencePolicy == CLEAR,
Carl Shapiroe8ef2b52010-12-01 19:32:05 -0800744 &gcHeap->weakReferences,
745 &gcHeap->phantomReferences);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800746
Carl Shapiro8881a802010-08-10 15:55:45 -0700747#if defined(WITH_JIT)
748 /*
749 * Patching a chaining cell is very cheap as it only updates 4 words. It's
750 * the overhead of stopping all threads and synchronizing the I/D cache
751 * that makes it expensive.
752 *
753 * Therefore we batch those work orders in a queue and go through them
754 * when threads are suspended for GC.
755 */
756 dvmCompilerPerformSafePointChecks();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800757#endif
758
Carl Shapiro8881a802010-08-10 15:55:45 -0700759 LOGD_HEAP("Sweeping...");
760
761 dvmHeapSweepSystemWeaks();
762
763 /*
764 * Live objects have a bit set in the mark bitmap, swap the mark
765 * and live bitmaps. The sweep can proceed concurrently viewing
766 * the new live bitmap as the old mark bitmap, and vice versa.
767 */
768 dvmHeapSourceSwapBitmaps();
769
770 if (gDvm.postVerify) {
771 LOGV_HEAP("Verifying roots and heap after GC");
772 verifyRootsAndHeap();
773 }
774
Carl Shapirocc6f5112011-01-26 17:25:27 -0800775 if (spec->isConcurrent) {
Carl Shapiro8881a802010-08-10 15:55:45 -0700776 dirtyEnd = dvmGetRelativeTimeMsec();
777 dvmUnlockHeap();
778 dvmResumeAllThreads(SUSPEND_FOR_GC);
779 }
Carl Shapirocc6f5112011-01-26 17:25:27 -0800780 dvmHeapSweepUnmarkedObjects(spec->isPartial, spec->isConcurrent,
Carl Shapiro570942c2010-09-17 15:53:16 -0700781 &numObjectsFreed, &numBytesFreed);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800782 LOGD_HEAP("Cleaning up...");
783 dvmHeapFinishMarkStep();
Carl Shapirocc6f5112011-01-26 17:25:27 -0800784 if (spec->isConcurrent) {
Carl Shapiro8881a802010-08-10 15:55:45 -0700785 dvmLockHeap();
786 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800787
788 LOGD_HEAP("Done.");
789
790 /* Now's a good time to adjust the heap size, since
791 * we know what our utilization is.
792 *
793 * This doesn't actually resize any memory;
794 * it just lets the heap grow more when necessary.
795 */
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -0800796 dvmHeapSourceGrowForUtilization();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800797
Carl Shapiro570942c2010-09-17 15:53:16 -0700798 currAllocated = dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);
799 currFootprint = dvmHeapSourceGetValue(HS_FOOTPRINT, NULL, 0);
800
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800801 /* Now that we've freed up the GC heap, return any large
802 * free chunks back to the system. They'll get paged back
803 * in the next time they're used. Don't do it immediately,
804 * though; if the process is still allocating a bunch of
805 * memory, we'll be taking a ton of page faults that we don't
806 * necessarily need to.
807 *
808 * Cancel any old scheduled trims, and schedule a new one.
809 */
810 dvmScheduleHeapSourceTrim(5); // in seconds
811
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800812 dvmMethodTraceGCEnd();
Barry Hayes962adba2010-03-17 12:12:39 -0700813 LOGV_HEAP("GC finished");
814
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800815 gcHeap->gcRunning = false;
816
Barry Hayes962adba2010-03-17 12:12:39 -0700817 LOGV_HEAP("Resuming threads");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800818 dvmUnlockMutex(&gDvm.heapWorkerListLock);
819 dvmUnlockMutex(&gDvm.heapWorkerLock);
820
Carl Shapirocc6f5112011-01-26 17:25:27 -0800821 if (spec->isConcurrent) {
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700822 /*
823 * Wake-up any threads that blocked after a failed allocation
824 * request.
825 */
826 dvmBroadcastCond(&gDvm.gcHeapCond);
827 }
828
Carl Shapirocc6f5112011-01-26 17:25:27 -0800829 if (!spec->isConcurrent) {
Carl Shapiro8881a802010-08-10 15:55:45 -0700830 dirtyEnd = dvmGetRelativeTimeMsec();
831 dvmResumeAllThreads(SUSPEND_FOR_GC);
Carl Shapirocc6f5112011-01-26 17:25:27 -0800832 /*
833 * Restore the original thread scheduling priority if it was
834 * changed at the start of the current garbage collection.
835 */
836 if (oldThreadPriority != INT_MAX) {
837 setThreadPriority(oldThreadPriority);
San Mehat256fc152009-04-21 14:03:06 -0700838 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800839 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800840
Carl Shapiro570942c2010-09-17 15:53:16 -0700841 percentFree = 100 - (size_t)(100.0f * (float)currAllocated / currFootprint);
Carl Shapirocc6f5112011-01-26 17:25:27 -0800842 if (!spec->isConcurrent) {
Carl Shapiro03f3b132010-07-27 17:25:31 -0700843 u4 markSweepTime = dirtyEnd - rootStart;
Carl Shapiro570942c2010-09-17 15:53:16 -0700844 bool isSmall = numBytesFreed > 0 && numBytesFreed < 1024;
Carl Shapiro8881a802010-08-10 15:55:45 -0700845 totalTime = rootSuspendTime + markSweepTime;
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -0800846 LOGD("%s freed %s%zdK, %d%% free %zdK/%zdK, paused %ums",
Carl Shapirocc6f5112011-01-26 17:25:27 -0800847 spec->reason,
Carl Shapiro570942c2010-09-17 15:53:16 -0700848 isSmall ? "<" : "",
849 numBytesFreed ? MAX(numBytesFreed / 1024, 1) : 0,
850 percentFree,
851 currAllocated / 1024, currFootprint / 1024,
Carl Shapiro570942c2010-09-17 15:53:16 -0700852 markSweepTime);
Carl Shapiro03f3b132010-07-27 17:25:31 -0700853 } else {
Carl Shapiro8881a802010-08-10 15:55:45 -0700854 u4 rootTime = rootEnd - rootStart;
855 u4 dirtySuspendTime = dirtyStart - dirtySuspend;
856 u4 dirtyTime = dirtyEnd - dirtyStart;
Carl Shapiro570942c2010-09-17 15:53:16 -0700857 bool isSmall = numBytesFreed > 0 && numBytesFreed < 1024;
Carl Shapiro03f3b132010-07-27 17:25:31 -0700858 totalTime = rootSuspendTime + rootTime + dirtySuspendTime + dirtyTime;
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -0800859 LOGD("%s freed %s%zdK, %d%% free %zdK/%zdK, paused %ums+%ums",
Carl Shapirocc6f5112011-01-26 17:25:27 -0800860 spec->reason,
Carl Shapiro570942c2010-09-17 15:53:16 -0700861 isSmall ? "<" : "",
862 numBytesFreed ? MAX(numBytesFreed / 1024, 1) : 0,
863 percentFree,
864 currAllocated / 1024, currFootprint / 1024,
Carl Shapiro570942c2010-09-17 15:53:16 -0700865 rootTime, dirtyTime);
Carl Shapiro03f3b132010-07-27 17:25:31 -0700866 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800867 if (gcHeap->ddmHpifWhen != 0) {
868 LOGD_HEAP("Sending VM heap info to DDM\n");
869 dvmDdmSendHeapInfo(gcHeap->ddmHpifWhen, false);
870 }
871 if (gcHeap->ddmHpsgWhen != 0) {
872 LOGD_HEAP("Dumping VM heap to DDM\n");
873 dvmDdmSendHeapSegments(false, false);
874 }
875 if (gcHeap->ddmNhsgWhen != 0) {
876 LOGD_HEAP("Dumping native heap to DDM\n");
877 dvmDdmSendHeapSegments(false, true);
878 }
879}
880
Andy McFadden58aa6112011-01-19 14:48:52 -0800881/*
882 * If the concurrent GC is running, wait for it to finish. The caller
883 * must hold the heap lock.
884 *
885 * Note: the second dvmChangeStatus() could stall if we were in RUNNING
886 * on entry, and some other thread has asked us to suspend. In that
887 * case we will be suspended with the heap lock held, which can lead to
888 * deadlock if the other thread tries to do something with the managed heap.
889 * For example, the debugger might suspend us and then execute a method that
890 * allocates memory. We can avoid this situation by releasing the lock
891 * before self-suspending. (The developer can work around this specific
892 * situation by single-stepping the VM. Alternatively, we could disable
893 * concurrent GC when the debugger is attached, but that might change
894 * behavior more than is desirable.)
895 *
896 * This should not be a problem in production, because any GC-related
897 * activity will grab the lock before issuing a suspend-all. (We may briefly
898 * suspend when the GC thread calls dvmUnlockHeap before dvmResumeAllThreads,
899 * but there's no risk of deadlock.)
900 */
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700901void dvmWaitForConcurrentGcToComplete(void)
902{
903 Thread *self = dvmThreadSelf();
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700904 assert(self != NULL);
Carl Shapiro039167e2010-12-20 18:33:24 -0800905 while (gDvm.gcHeap->gcRunning) {
906 ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
907 dvmWaitCond(&gDvm.gcHeapCond, &gDvm.gcHeapLock);
908 dvmChangeStatus(self, oldStatus);
909 }
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700910}