blob: 1f366013974578f11dbdb966124aeae6bfdd400d [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
30#define kInvalidPriority 10000
31
San Mehat5a2056c2009-09-12 10:10:13 -070032#include <cutils/sched_policy.h>
33
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080034#include <sys/time.h>
35#include <sys/resource.h>
36#include <limits.h>
37#include <errno.h>
38
Barry Hayes1b9b4e42010-01-04 10:33:46 -080039static const char* GcReasonStr[] = {
40 [GC_FOR_MALLOC] = "GC_FOR_MALLOC",
Carl Shapiroec805ea2010-06-28 16:28:26 -070041 [GC_CONCURRENT] = "GC_CONCURRENT",
Barry Hayes1b9b4e42010-01-04 10:33:46 -080042 [GC_EXPLICIT] = "GC_EXPLICIT",
43 [GC_EXTERNAL_ALLOC] = "GC_EXTERNAL_ALLOC",
44 [GC_HPROF_DUMP_HEAP] = "GC_HPROF_DUMP_HEAP"
45};
46
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080047/*
48 * Initialize the GC heap.
49 *
50 * Returns true if successful, false otherwise.
51 */
52bool dvmHeapStartup()
53{
54 GcHeap *gcHeap;
55
56#if defined(WITH_ALLOC_LIMITS)
57 gDvm.checkAllocLimits = false;
58 gDvm.allocationLimit = -1;
59#endif
60
61 gcHeap = dvmHeapSourceStartup(gDvm.heapSizeStart, gDvm.heapSizeMax);
62 if (gcHeap == NULL) {
63 return false;
64 }
65 gcHeap->heapWorkerCurrentObject = NULL;
66 gcHeap->heapWorkerCurrentMethod = NULL;
67 gcHeap->heapWorkerInterpStartTime = 0LL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080068 gcHeap->ddmHpifWhen = 0;
69 gcHeap->ddmHpsgWhen = 0;
70 gcHeap->ddmHpsgWhat = 0;
71 gcHeap->ddmNhsgWhen = 0;
72 gcHeap->ddmNhsgWhat = 0;
73#if WITH_HPROF
74 gcHeap->hprofDumpOnGc = false;
75 gcHeap->hprofContext = NULL;
76#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080077 gDvm.gcHeap = gcHeap;
78
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080079 /* Set up the lists and lock we'll use for finalizable
80 * and reference objects.
81 */
82 dvmInitMutex(&gDvm.heapWorkerListLock);
83 gcHeap->finalizableRefs = NULL;
84 gcHeap->pendingFinalizationRefs = NULL;
85 gcHeap->referenceOperations = NULL;
86
87 /* Initialize the HeapWorker locks and other state
88 * that the GC uses.
89 */
90 dvmInitializeHeapWorkerState();
91
92 return true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080093}
94
Carl Shapiroec805ea2010-06-28 16:28:26 -070095bool dvmHeapStartupAfterZygote(void)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080096{
97 /* Update our idea of the last GC start time so that we
98 * don't use the last time that Zygote happened to GC.
99 */
100 gDvm.gcHeap->gcStartTime = dvmGetRelativeTimeUsec();
Carl Shapiroec805ea2010-06-28 16:28:26 -0700101 return dvmHeapSourceStartupAfterZygote();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800102}
103
104void dvmHeapShutdown()
105{
106//TODO: make sure we're locked
107 if (gDvm.gcHeap != NULL) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800108 /* Tables are allocated on the native heap;
109 * they need to be cleaned up explicitly.
110 * The process may stick around, so we don't
111 * want to leak any native memory.
112 */
Carl Shapiroa199eb72010-02-09 16:26:30 -0800113 dvmHeapFreeLargeTable(gDvm.gcHeap->finalizableRefs);
114 gDvm.gcHeap->finalizableRefs = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800115
Carl Shapiroa199eb72010-02-09 16:26:30 -0800116 dvmHeapFreeLargeTable(gDvm.gcHeap->pendingFinalizationRefs);
117 gDvm.gcHeap->pendingFinalizationRefs = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800118
Carl Shapiroa199eb72010-02-09 16:26:30 -0800119 dvmHeapFreeLargeTable(gDvm.gcHeap->referenceOperations);
120 gDvm.gcHeap->referenceOperations = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800121
122 /* Destroy the heap. Any outstanding pointers
123 * will point to unmapped memory (unless/until
Carl Shapiroa199eb72010-02-09 16:26:30 -0800124 * someone else maps it). This frees gDvm.gcHeap
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800125 * as a side-effect.
126 */
Carl Shapiroa199eb72010-02-09 16:26:30 -0800127 dvmHeapSourceShutdown(&gDvm.gcHeap);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800128 }
129}
130
131/*
Carl Shapiroec805ea2010-06-28 16:28:26 -0700132 * Shutdown any threads internal to the heap.
133 */
134void dvmHeapThreadShutdown(void)
135{
136 dvmHeapSourceThreadShutdown();
137}
138
139/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800140 * We've been asked to allocate something we can't, e.g. an array so
Andy McFadden6da743b2009-07-15 16:56:00 -0700141 * large that (length * elementWidth) is larger than 2^31.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800142 *
Andy McFadden6da743b2009-07-15 16:56:00 -0700143 * _The Java Programming Language_, 4th edition, says, "you can be sure
144 * that all SoftReferences to softly reachable objects will be cleared
145 * before an OutOfMemoryError is thrown."
146 *
147 * It's unclear whether that holds for all situations where an OOM can
148 * be thrown, or just in the context of an allocation that fails due
149 * to lack of heap space. For simplicity we just throw the exception.
150 *
151 * (OOM due to actually running out of space is handled elsewhere.)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800152 */
153void dvmThrowBadAllocException(const char* msg)
154{
Andy McFadden6da743b2009-07-15 16:56:00 -0700155 dvmThrowException("Ljava/lang/OutOfMemoryError;", msg);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800156}
157
158/*
159 * Grab the lock, but put ourselves into THREAD_VMWAIT if it looks like
160 * we're going to have to wait on the mutex.
161 */
162bool dvmLockHeap()
163{
Carl Shapiro980ffb02010-03-13 22:34:01 -0800164 if (dvmTryLockMutex(&gDvm.gcHeapLock) != 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800165 Thread *self;
166 ThreadStatus oldStatus;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800167
168 self = dvmThreadSelf();
Carl Shapiro5617ad32010-07-02 10:50:57 -0700169 oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
Carl Shapiro980ffb02010-03-13 22:34:01 -0800170 dvmLockMutex(&gDvm.gcHeapLock);
Carl Shapiro5617ad32010-07-02 10:50:57 -0700171 dvmChangeStatus(self, oldStatus);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800172 }
173
174 return true;
175}
176
177void dvmUnlockHeap()
178{
179 dvmUnlockMutex(&gDvm.gcHeapLock);
180}
181
182/* Pop an object from the list of pending finalizations and
183 * reference clears/enqueues, and return the object.
184 * The caller must call dvmReleaseTrackedAlloc()
185 * on the object when finished.
186 *
187 * Typically only called by the heap worker thread.
188 */
189Object *dvmGetNextHeapWorkerObject(HeapWorkerOperation *op)
190{
191 Object *obj;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800192 GcHeap *gcHeap = gDvm.gcHeap;
193
194 assert(op != NULL);
195
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800196 dvmLockMutex(&gDvm.heapWorkerListLock);
197
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800198 obj = dvmHeapGetNextObjectFromLargeTable(&gcHeap->referenceOperations);
199 if (obj != NULL) {
Carl Shapiro646ba092010-06-10 15:17:00 -0700200 *op = WORKER_ENQUEUE;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800201 } else {
202 obj = dvmHeapGetNextObjectFromLargeTable(
203 &gcHeap->pendingFinalizationRefs);
204 if (obj != NULL) {
205 *op = WORKER_FINALIZE;
206 }
207 }
208
209 if (obj != NULL) {
210 /* Don't let the GC collect the object until the
211 * worker thread is done with it.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800212 */
213 dvmAddTrackedAlloc(obj, NULL);
214 }
215
216 dvmUnlockMutex(&gDvm.heapWorkerListLock);
217
218 return obj;
219}
220
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800221/* Whenever the effective heap size may have changed,
222 * this function must be called.
223 */
224void dvmHeapSizeChanged()
225{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800226}
227
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800228/* Do a full garbage collection, which may grow the
229 * heap as a side-effect if the live set is large.
230 */
231static void gcForMalloc(bool collectSoftReferences)
232{
233#ifdef WITH_PROFILER
234 if (gDvm.allocProf.enabled) {
235 Thread* self = dvmThreadSelf();
236 gDvm.allocProf.gcCount++;
237 if (self != NULL) {
238 self->allocProf.gcCount++;
239 }
240 }
241#endif
242 /* This may adjust the soft limit as a side-effect.
243 */
244 LOGD_HEAP("dvmMalloc initiating GC%s\n",
245 collectSoftReferences ? "(collect SoftReferences)" : "");
Barry Hayes1b9b4e42010-01-04 10:33:46 -0800246 dvmCollectGarbageInternal(collectSoftReferences, GC_FOR_MALLOC);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800247}
248
249/* Try as hard as possible to allocate some memory.
250 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800251static void *tryMalloc(size_t size)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800252{
Carl Shapiro6343bd02010-02-16 17:40:19 -0800253 void *ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800254
255 /* Don't try too hard if there's no way the allocation is
256 * going to succeed. We have to collect SoftReferences before
257 * throwing an OOME, though.
258 */
259 if (size >= gDvm.heapSizeMax) {
260 LOGW_HEAP("dvmMalloc(%zu/0x%08zx): "
261 "someone's allocating a huge buffer\n", size, size);
Carl Shapiro6343bd02010-02-16 17:40:19 -0800262 ptr = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800263 goto collect_soft_refs;
264 }
265
266//TODO: figure out better heuristics
267// There will be a lot of churn if someone allocates a bunch of
268// big objects in a row, and we hit the frag case each time.
269// A full GC for each.
270// Maybe we grow the heap in bigger leaps
271// Maybe we skip the GC if the size is large and we did one recently
272// (number of allocations ago) (watch for thread effects)
273// DeflateTest allocs a bunch of ~128k buffers w/in 0-5 allocs of each other
274// (or, at least, there are only 0-5 objects swept each time)
275
Carl Shapiro6343bd02010-02-16 17:40:19 -0800276 ptr = dvmHeapSourceAlloc(size);
277 if (ptr != NULL) {
278 return ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800279 }
280
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700281 /*
282 * The allocation failed. If the GC is running, block until it
283 * completes and retry.
284 */
285 if (gDvm.gcHeap->gcRunning) {
286 /*
287 * The GC is concurrently tracing the heap. Release the heap
288 * lock, wait for the GC to complete, and retrying allocating.
289 */
290 dvmWaitForConcurrentGcToComplete();
291 ptr = dvmHeapSourceAlloc(size);
292 if (ptr != NULL) {
293 return ptr;
294 }
295 }
296 /*
297 * Another failure. Our thread was starved or there may be too
298 * many live objects. Try a foreground GC. This will have no
299 * effect if the concurrent GC is already running.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800300 */
301 gcForMalloc(false);
Carl Shapiro6343bd02010-02-16 17:40:19 -0800302 ptr = dvmHeapSourceAlloc(size);
303 if (ptr != NULL) {
304 return ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800305 }
306
307 /* Even that didn't work; this is an exceptional state.
308 * Try harder, growing the heap if necessary.
309 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800310 ptr = dvmHeapSourceAllocAndGrow(size);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800311 dvmHeapSizeChanged();
Carl Shapiro6343bd02010-02-16 17:40:19 -0800312 if (ptr != NULL) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800313 size_t newHeapSize;
314
315 newHeapSize = dvmHeapSourceGetIdealFootprint();
316//TODO: may want to grow a little bit more so that the amount of free
317// space is equal to the old free space + the utilization slop for
318// the new allocation.
319 LOGI_HEAP("Grow heap (frag case) to "
320 "%zu.%03zuMB for %zu-byte allocation\n",
321 FRACTIONAL_MB(newHeapSize), size);
Carl Shapiro6343bd02010-02-16 17:40:19 -0800322 return ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800323 }
324
325 /* Most allocations should have succeeded by now, so the heap
326 * is really full, really fragmented, or the requested size is
327 * really big. Do another GC, collecting SoftReferences this
328 * time. The VM spec requires that all SoftReferences have
329 * been collected and cleared before throwing an OOME.
330 */
331//TODO: wait for the finalizers from the previous GC to finish
332collect_soft_refs:
333 LOGI_HEAP("Forcing collection of SoftReferences for %zu-byte allocation\n",
334 size);
335 gcForMalloc(true);
Carl Shapiro6343bd02010-02-16 17:40:19 -0800336 ptr = dvmHeapSourceAllocAndGrow(size);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800337 dvmHeapSizeChanged();
Carl Shapiro6343bd02010-02-16 17:40:19 -0800338 if (ptr != NULL) {
339 return ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800340 }
341//TODO: maybe wait for finalizers and try one last time
342
343 LOGE_HEAP("Out of memory on a %zd-byte allocation.\n", size);
344//TODO: tell the HeapSource to dump its state
345 dvmDumpThread(dvmThreadSelf(), false);
346
347 return NULL;
348}
349
350/* Throw an OutOfMemoryError if there's a thread to attach it to.
351 * Avoid recursing.
352 *
353 * The caller must not be holding the heap lock, or else the allocations
354 * in dvmThrowException() will deadlock.
355 */
356static void throwOOME()
357{
358 Thread *self;
359
360 if ((self = dvmThreadSelf()) != NULL) {
361 /* If the current (failing) dvmMalloc() happened as part of thread
362 * creation/attachment before the thread became part of the root set,
363 * we can't rely on the thread-local trackedAlloc table, so
364 * we can't keep track of a real allocated OOME object. But, since
365 * the thread is in the process of being created, it won't have
366 * a useful stack anyway, so we may as well make things easier
367 * by throwing the (stackless) pre-built OOME.
368 */
369 if (dvmIsOnThreadList(self) && !self->throwingOOME) {
370 /* Let ourselves know that we tried to throw an OOM
371 * error in the normal way in case we run out of
372 * memory trying to allocate it inside dvmThrowException().
373 */
374 self->throwingOOME = true;
375
376 /* Don't include a description string;
377 * one fewer allocation.
378 */
379 dvmThrowException("Ljava/lang/OutOfMemoryError;", NULL);
380 } else {
381 /*
382 * This thread has already tried to throw an OutOfMemoryError,
383 * which probably means that we're running out of memory
384 * while recursively trying to throw.
385 *
386 * To avoid any more allocation attempts, "throw" a pre-built
387 * OutOfMemoryError object (which won't have a useful stack trace).
388 *
389 * Note that since this call can't possibly allocate anything,
390 * we don't care about the state of self->throwingOOME
391 * (which will usually already be set).
392 */
393 dvmSetException(self, gDvm.outOfMemoryObj);
394 }
395 /* We're done with the possible recursion.
396 */
397 self->throwingOOME = false;
398 }
399}
400
401/*
402 * Allocate storage on the GC heap. We guarantee 8-byte alignment.
403 *
404 * The new storage is zeroed out.
405 *
406 * Note that, in rare cases, this could get called while a GC is in
407 * progress. If a non-VM thread tries to attach itself through JNI,
408 * it will need to allocate some objects. If this becomes annoying to
409 * deal with, we can block it at the source, but holding the allocation
410 * mutex should be enough.
411 *
412 * In rare circumstances (JNI AttachCurrentThread) we can be called
413 * from a non-VM thread.
414 *
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800415 * Use ALLOC_DONT_TRACK when we either don't want to track an allocation
416 * (because it's being done for the interpreter "new" operation and will
417 * be part of the root set immediately) or we can't (because this allocation
418 * is for a brand new thread).
419 *
420 * Returns NULL and throws an exception on failure.
421 *
422 * TODO: don't do a GC if the debugger thinks all threads are suspended
423 */
424void* dvmMalloc(size_t size, int flags)
425{
426 GcHeap *gcHeap = gDvm.gcHeap;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800427 void *ptr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800428
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800429#if defined(WITH_ALLOC_LIMITS)
430 /*
431 * See if they've exceeded the allocation limit for this thread.
432 *
433 * A limit value of -1 means "no limit".
434 *
435 * This is enabled at compile time because it requires us to do a
436 * TLS lookup for the Thread pointer. This has enough of a performance
437 * impact that we don't want to do it if we don't have to. (Now that
438 * we're using gDvm.checkAllocLimits we may want to reconsider this,
439 * but it's probably still best to just compile the check out of
440 * production code -- one less thing to hit on every allocation.)
441 */
442 if (gDvm.checkAllocLimits) {
443 Thread* self = dvmThreadSelf();
444 if (self != NULL) {
445 int count = self->allocLimit;
446 if (count > 0) {
447 self->allocLimit--;
448 } else if (count == 0) {
449 /* fail! */
450 assert(!gDvm.initializing);
451 self->allocLimit = -1;
452 dvmThrowException("Ldalvik/system/AllocationLimitError;",
453 "thread allocation limit exceeded");
454 return NULL;
455 }
456 }
457 }
458
459 if (gDvm.allocationLimit >= 0) {
460 assert(!gDvm.initializing);
461 gDvm.allocationLimit = -1;
462 dvmThrowException("Ldalvik/system/AllocationLimitError;",
463 "global allocation limit exceeded");
464 return NULL;
465 }
466#endif
467
468 dvmLockHeap();
469
470 /* Try as hard as possible to allocate some memory.
471 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800472 ptr = tryMalloc(size);
473 if (ptr != NULL) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800474 /* We've got the memory.
475 */
476 if ((flags & ALLOC_FINALIZABLE) != 0) {
477 /* This object is an instance of a class that
478 * overrides finalize(). Add it to the finalizable list.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800479 */
480 if (!dvmHeapAddRefToLargeTable(&gcHeap->finalizableRefs,
Carl Shapiro6343bd02010-02-16 17:40:19 -0800481 (Object *)ptr))
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800482 {
483 LOGE_HEAP("dvmMalloc(): no room for any more "
484 "finalizable objects\n");
485 dvmAbort();
486 }
487 }
488
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800489#ifdef WITH_PROFILER
490 if (gDvm.allocProf.enabled) {
491 Thread* self = dvmThreadSelf();
492 gDvm.allocProf.allocCount++;
493 gDvm.allocProf.allocSize += size;
494 if (self != NULL) {
495 self->allocProf.allocCount++;
496 self->allocProf.allocSize += size;
497 }
498 }
499#endif
500 } else {
501 /* The allocation failed.
502 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800503
504#ifdef WITH_PROFILER
505 if (gDvm.allocProf.enabled) {
506 Thread* self = dvmThreadSelf();
507 gDvm.allocProf.failedAllocCount++;
508 gDvm.allocProf.failedAllocSize += size;
509 if (self != NULL) {
510 self->allocProf.failedAllocCount++;
511 self->allocProf.failedAllocSize += size;
512 }
513 }
514#endif
515 }
516
517 dvmUnlockHeap();
518
519 if (ptr != NULL) {
520 /*
Barry Hayesd4f78d32010-06-08 09:34:42 -0700521 * If caller hasn't asked us not to track it, add it to the
522 * internal tracking list.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800523 */
Barry Hayesd4f78d32010-06-08 09:34:42 -0700524 if ((flags & ALLOC_DONT_TRACK) == 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800525 dvmAddTrackedAlloc(ptr, NULL);
526 }
527 } else {
Ben Chengc3b92b22010-01-26 16:46:15 -0800528 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800529 * The allocation failed; throw an OutOfMemoryError.
530 */
531 throwOOME();
532 }
533
534 return ptr;
535}
536
537/*
538 * Returns true iff <obj> points to a valid allocated object.
539 */
540bool dvmIsValidObject(const Object* obj)
541{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800542 /* Don't bother if it's NULL or not 8-byte aligned.
543 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800544 if (obj != NULL && ((uintptr_t)obj & (8-1)) == 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800545 /* Even if the heap isn't locked, this shouldn't return
546 * any false negatives. The only mutation that could
547 * be happening is allocation, which means that another
548 * thread could be in the middle of a read-modify-write
549 * to add a new bit for a new object. However, that
550 * RMW will have completed by the time any other thread
551 * could possibly see the new pointer, so there is no
552 * danger of dvmIsValidObject() being called on a valid
553 * pointer whose bit isn't set.
554 *
555 * Freeing will only happen during the sweep phase, which
556 * only happens while the heap is locked.
557 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800558 return dvmHeapSourceContains(obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800559 }
560 return false;
561}
562
Barry Hayes364f9d92010-06-11 16:12:47 -0700563/*
564 * Returns true iff <obj> points to a word-aligned address within Heap
565 * address space.
566 */
567bool dvmIsValidObjectAddress(const void* ptr)
568{
569 /* Don't bother if it's not 4-byte aligned.
570 */
571 if (((uintptr_t)ptr & (4-1)) == 0) {
572 return dvmHeapSourceContainsAddress(ptr);
573 }
574 return false;
575}
576
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800577size_t dvmObjectSizeInHeap(const Object *obj)
578{
Carl Shapiro6343bd02010-02-16 17:40:19 -0800579 return dvmHeapSourceChunkSize(obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800580}
581
582/*
Barry Hayes962adba2010-03-17 12:12:39 -0700583 * Scan every live object in the heap, holding the locks.
584 */
585static void verifyHeap()
586{
587 // TODO: check the locks.
588 HeapBitmap *liveBits = dvmHeapSourceGetLiveBits();
589 dvmVerifyBitmap(liveBits);
590}
591
592/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800593 * Initiate garbage collection.
594 *
595 * NOTES:
596 * - If we don't hold gDvm.threadListLock, it's possible for a thread to
597 * be added to the thread list while we work. The thread should NOT
598 * start executing, so this is only interesting when we start chasing
599 * thread stacks. (Before we do so, grab the lock.)
600 *
601 * We are not allowed to GC when the debugger has suspended the VM, which
602 * is awkward because debugger requests can cause allocations. The easiest
603 * way to enforce this is to refuse to GC on an allocation made by the
604 * JDWP thread -- we have to expand the heap or fail.
605 */
Carl Shapiro29540742010-03-26 15:34:39 -0700606void dvmCollectGarbageInternal(bool clearSoftRefs, GcReason reason)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800607{
608 GcHeap *gcHeap = gDvm.gcHeap;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800609 u8 now;
610 s8 timeSinceLastGc;
611 s8 gcElapsedTime;
612 int numFreed;
613 size_t sizeFreed;
Carl Shapirod25566d2010-03-11 20:39:47 -0800614 GcMode gcMode;
Carl Shapiroec805ea2010-06-28 16:28:26 -0700615 int oldThreadPriority = kInvalidPriority;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800616
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800617 /* The heap lock must be held.
618 */
619
620 if (gcHeap->gcRunning) {
621 LOGW_HEAP("Attempted recursive GC\n");
622 return;
623 }
Carl Shapirod25566d2010-03-11 20:39:47 -0800624 gcMode = (reason == GC_FOR_MALLOC) ? GC_PARTIAL : GC_FULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800625 gcHeap->gcRunning = true;
626 now = dvmGetRelativeTimeUsec();
627 if (gcHeap->gcStartTime != 0) {
628 timeSinceLastGc = (now - gcHeap->gcStartTime) / 1000;
629 } else {
630 timeSinceLastGc = 0;
631 }
632 gcHeap->gcStartTime = now;
633
Barry Hayes1b9b4e42010-01-04 10:33:46 -0800634 LOGV_HEAP("%s starting -- suspending threads\n", GcReasonStr[reason]);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800635
636 dvmSuspendAllThreads(SUSPEND_FOR_GC);
637
Carl Shapiroec805ea2010-06-28 16:28:26 -0700638 /*
639 * If we are not marking concurrently raise the priority of the
640 * thread performing the garbage collection.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800641 */
Carl Shapiroec805ea2010-06-28 16:28:26 -0700642 if (reason != GC_CONCURRENT) {
643 /* Get the priority (the "nice" value) of the current thread. The
644 * getpriority() call can legitimately return -1, so we have to
645 * explicitly test errno.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800646 */
Carl Shapiroec805ea2010-06-28 16:28:26 -0700647 errno = 0;
648 int priorityResult = getpriority(PRIO_PROCESS, 0);
649 if (errno != 0) {
650 LOGI_HEAP("getpriority(self) failed: %s\n", strerror(errno));
651 } else if (priorityResult > ANDROID_PRIORITY_NORMAL) {
652 /* Current value is numerically greater than "normal", which
653 * in backward UNIX terms means lower priority.
654 */
San Mehat256fc152009-04-21 14:03:06 -0700655
Carl Shapiroec805ea2010-06-28 16:28:26 -0700656 if (priorityResult >= ANDROID_PRIORITY_BACKGROUND) {
657 set_sched_policy(dvmGetSysThreadId(), SP_FOREGROUND);
658 }
San Mehat256fc152009-04-21 14:03:06 -0700659
Carl Shapiroec805ea2010-06-28 16:28:26 -0700660 if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL) != 0) {
661 LOGI_HEAP("Unable to elevate priority from %d to %d\n",
662 priorityResult, ANDROID_PRIORITY_NORMAL);
663 } else {
664 /* priority elevated; save value so we can restore it later */
665 LOGD_HEAP("Elevating priority from %d to %d\n",
666 priorityResult, ANDROID_PRIORITY_NORMAL);
667 oldThreadPriority = priorityResult;
668 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800669 }
670 }
671
672 /* Wait for the HeapWorker thread to block.
673 * (It may also already be suspended in interp code,
674 * in which case it's not holding heapWorkerLock.)
675 */
676 dvmLockMutex(&gDvm.heapWorkerLock);
677
678 /* Make sure that the HeapWorker thread hasn't become
679 * wedged inside interp code. If it has, this call will
680 * print a message and abort the VM.
681 */
682 dvmAssertHeapWorkerThreadRunning();
683
684 /* Lock the pendingFinalizationRefs list.
685 *
686 * Acquire the lock after suspending so the finalizer
687 * thread can't block in the RUNNING state while
688 * we try to suspend.
689 */
690 dvmLockMutex(&gDvm.heapWorkerListLock);
691
Barry Hayes962adba2010-03-17 12:12:39 -0700692 if (gDvm.preVerify) {
693 LOGV_HEAP("Verifying heap before GC");
694 verifyHeap();
695 }
696
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800697#ifdef WITH_PROFILER
698 dvmMethodTraceGCBegin();
699#endif
700
701#if WITH_HPROF
702
703/* Set DUMP_HEAP_ON_DDMS_UPDATE to 1 to enable heap dumps
704 * whenever DDMS requests a heap update (HPIF chunk).
705 * The output files will appear in /data/misc, which must
706 * already exist.
707 * You must define "WITH_HPROF := true" in your buildspec.mk
708 * and recompile libdvm for this to work.
709 *
710 * To enable stack traces for each allocation, define
711 * "WITH_HPROF_STACK := true" in buildspec.mk. This option slows down
712 * allocations and also requires 8 additional bytes per object on the
713 * GC heap.
714 */
715#define DUMP_HEAP_ON_DDMS_UPDATE 0
716#if DUMP_HEAP_ON_DDMS_UPDATE
717 gcHeap->hprofDumpOnGc |= (gcHeap->ddmHpifWhen != 0);
718#endif
719
720 if (gcHeap->hprofDumpOnGc) {
721 char nameBuf[128];
722
The Android Open Source Project99409882009-03-18 22:20:24 -0700723 gcHeap->hprofResult = -1;
724
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800725 if (gcHeap->hprofFileName == NULL) {
726 /* no filename was provided; invent one */
727 sprintf(nameBuf, "/data/misc/heap-dump-tm%d-pid%d.hprof",
728 (int) time(NULL), (int) getpid());
729 gcHeap->hprofFileName = nameBuf;
730 }
Andy McFadden6bf992c2010-01-28 17:01:39 -0800731 gcHeap->hprofContext = hprofStartup(gcHeap->hprofFileName,
732 gcHeap->hprofDirectToDdms);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800733 if (gcHeap->hprofContext != NULL) {
734 hprofStartHeapDump(gcHeap->hprofContext);
735 }
736 gcHeap->hprofDumpOnGc = false;
737 gcHeap->hprofFileName = NULL;
738 }
739#endif
740
741 if (timeSinceLastGc < 10000) {
742 LOGD_HEAP("GC! (%dms since last GC)\n",
743 (int)timeSinceLastGc);
744 } else {
745 LOGD_HEAP("GC! (%d sec since last GC)\n",
746 (int)(timeSinceLastGc / 1000));
747 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800748
749 /* Set up the marking context.
750 */
Carl Shapirod25566d2010-03-11 20:39:47 -0800751 if (!dvmHeapBeginMarkStep(gcMode)) {
The Android Open Source Project99409882009-03-18 22:20:24 -0700752 LOGE_HEAP("dvmHeapBeginMarkStep failed; aborting\n");
753 dvmAbort();
754 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800755
756 /* Mark the set of objects that are strongly reachable from the roots.
757 */
758 LOGD_HEAP("Marking...");
759 dvmHeapMarkRootSet();
760
761 /* dvmHeapScanMarkedObjects() will build the lists of known
762 * instances of the Reference classes.
763 */
764 gcHeap->softReferences = NULL;
765 gcHeap->weakReferences = NULL;
766 gcHeap->phantomReferences = NULL;
767
Carl Shapiroec805ea2010-06-28 16:28:26 -0700768 if (reason == GC_CONCURRENT) {
769 /*
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700770 * Resume threads while tracing from the roots. We unlock the
771 * heap to allow mutator threads to allocate from free space.
Carl Shapiroec805ea2010-06-28 16:28:26 -0700772 */
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700773 dvmUnlockHeap();
Carl Shapiroec805ea2010-06-28 16:28:26 -0700774 dvmResumeAllThreads(SUSPEND_FOR_GC);
775 }
776
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800777 /* Recursively mark any objects that marked objects point to strongly.
778 * If we're not collecting soft references, soft-reachable
779 * objects will also be marked.
780 */
781 LOGD_HEAP("Recursing...");
782 dvmHeapScanMarkedObjects();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800783
Carl Shapiroec805ea2010-06-28 16:28:26 -0700784 if (reason == GC_CONCURRENT) {
785 /*
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700786 * Re-acquire the heap lock and perform the final thread
787 * suspension.
Carl Shapiroec805ea2010-06-28 16:28:26 -0700788 */
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700789 dvmLockHeap();
Carl Shapiroec805ea2010-06-28 16:28:26 -0700790 dvmSuspendAllThreads(SUSPEND_FOR_GC);
791 /*
792 * As no barrier intercepts root updates, we conservatively
793 * assume all roots may be gray and re-mark them.
794 */
795 dvmHeapMarkRootSet();
796 /*
797 * Recursively mark gray objects pointed to by the roots or by
798 * heap objects dirtied during the concurrent mark.
799 */
800 dvmMarkDirtyObjects();
801 }
802
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800803 /* All strongly-reachable objects have now been marked.
804 */
Carl Shapiro29540742010-03-26 15:34:39 -0700805 LOGD_HEAP("Handling soft references...");
806 if (!clearSoftRefs) {
807 dvmHandleSoftRefs(&gcHeap->softReferences);
808 }
809 dvmClearWhiteRefs(&gcHeap->softReferences);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800810
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800811 LOGD_HEAP("Handling weak references...");
Carl Shapiro29540742010-03-26 15:34:39 -0700812 dvmClearWhiteRefs(&gcHeap->weakReferences);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800813
814 /* Once all weak-reachable objects have been taken
815 * care of, any remaining unmarked objects can be finalized.
816 */
817 LOGD_HEAP("Finding finalizations...");
818 dvmHeapScheduleFinalizations();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800819
Carl Shapiro29540742010-03-26 15:34:39 -0700820 LOGD_HEAP("Handling f-reachable soft references...");
821 dvmClearWhiteRefs(&gcHeap->softReferences);
822
823 LOGD_HEAP("Handling f-reachable weak references...");
824 dvmClearWhiteRefs(&gcHeap->weakReferences);
825
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800826 /* Any remaining objects that are not pending finalization
827 * could be phantom-reachable. This will mark any phantom-reachable
828 * objects, as well as enqueue their references.
829 */
830 LOGD_HEAP("Handling phantom references...");
Carl Shapiro29540742010-03-26 15:34:39 -0700831 dvmClearWhiteRefs(&gcHeap->phantomReferences);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800832
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800833#ifdef WITH_DEADLOCK_PREDICTION
834 dvmDumpMonitorInfo("before sweep");
835#endif
836 LOGD_HEAP("Sweeping...");
Carl Shapirod25566d2010-03-11 20:39:47 -0800837 dvmHeapSweepUnmarkedObjects(gcMode, &numFreed, &sizeFreed);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800838#ifdef WITH_DEADLOCK_PREDICTION
839 dvmDumpMonitorInfo("after sweep");
840#endif
841
842 LOGD_HEAP("Cleaning up...");
843 dvmHeapFinishMarkStep();
844
845 LOGD_HEAP("Done.");
846
847 /* Now's a good time to adjust the heap size, since
848 * we know what our utilization is.
849 *
850 * This doesn't actually resize any memory;
851 * it just lets the heap grow more when necessary.
852 */
853 dvmHeapSourceGrowForUtilization();
854 dvmHeapSizeChanged();
855
856#if WITH_HPROF
857 if (gcHeap->hprofContext != NULL) {
858 hprofFinishHeapDump(gcHeap->hprofContext);
859//TODO: write a HEAP_SUMMARY record
The Android Open Source Project99409882009-03-18 22:20:24 -0700860 if (hprofShutdown(gcHeap->hprofContext))
861 gcHeap->hprofResult = 0; /* indicate success */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800862 gcHeap->hprofContext = NULL;
863 }
864#endif
865
866 /* Now that we've freed up the GC heap, return any large
867 * free chunks back to the system. They'll get paged back
868 * in the next time they're used. Don't do it immediately,
869 * though; if the process is still allocating a bunch of
870 * memory, we'll be taking a ton of page faults that we don't
871 * necessarily need to.
872 *
873 * Cancel any old scheduled trims, and schedule a new one.
874 */
875 dvmScheduleHeapSourceTrim(5); // in seconds
876
877#ifdef WITH_PROFILER
878 dvmMethodTraceGCEnd();
879#endif
Barry Hayes962adba2010-03-17 12:12:39 -0700880 LOGV_HEAP("GC finished");
881
882 if (gDvm.postVerify) {
883 LOGV_HEAP("Verifying heap after GC");
884 verifyHeap();
885 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800886
887 gcHeap->gcRunning = false;
888
Barry Hayes962adba2010-03-17 12:12:39 -0700889 LOGV_HEAP("Resuming threads");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800890 dvmUnlockMutex(&gDvm.heapWorkerListLock);
891 dvmUnlockMutex(&gDvm.heapWorkerLock);
892
Ben Chengc3b92b22010-01-26 16:46:15 -0800893#if defined(WITH_JIT)
Ben Chengc3b92b22010-01-26 16:46:15 -0800894 /*
895 * Patching a chaining cell is very cheap as it only updates 4 words. It's
896 * the overhead of stopping all threads and synchronizing the I/D cache
897 * that makes it expensive.
898 *
899 * Therefore we batch those work orders in a queue and go through them
900 * when threads are suspended for GC.
901 */
902 dvmCompilerPerformSafePointChecks();
903#endif
904
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800905 dvmResumeAllThreads(SUSPEND_FOR_GC);
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700906
907 if (reason == GC_CONCURRENT) {
908 /*
909 * Wake-up any threads that blocked after a failed allocation
910 * request.
911 */
912 dvmBroadcastCond(&gDvm.gcHeapCond);
913 }
914
Carl Shapiroec805ea2010-06-28 16:28:26 -0700915 if (reason != GC_CONCURRENT) {
916 if (oldThreadPriority != kInvalidPriority) {
917 if (setpriority(PRIO_PROCESS, 0, oldThreadPriority) != 0) {
918 LOGW_HEAP("Unable to reset priority to %d: %s\n",
919 oldThreadPriority, strerror(errno));
920 } else {
921 LOGD_HEAP("Reset priority to %d\n", oldThreadPriority);
922 }
San Mehat256fc152009-04-21 14:03:06 -0700923
Carl Shapiroec805ea2010-06-28 16:28:26 -0700924 if (oldThreadPriority >= ANDROID_PRIORITY_BACKGROUND) {
925 set_sched_policy(dvmGetSysThreadId(), SP_BACKGROUND);
926 }
San Mehat256fc152009-04-21 14:03:06 -0700927 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800928 }
929 gcElapsedTime = (dvmGetRelativeTimeUsec() - gcHeap->gcStartTime) / 1000;
Barry Hayes31364132010-01-04 16:10:09 -0800930 LOGD("%s freed %d objects / %zd bytes in %dms\n",
931 GcReasonStr[reason], numFreed, sizeFreed, (int)gcElapsedTime);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800932 dvmLogGcStats(numFreed, sizeFreed, gcElapsedTime);
933
934 if (gcHeap->ddmHpifWhen != 0) {
935 LOGD_HEAP("Sending VM heap info to DDM\n");
936 dvmDdmSendHeapInfo(gcHeap->ddmHpifWhen, false);
937 }
938 if (gcHeap->ddmHpsgWhen != 0) {
939 LOGD_HEAP("Dumping VM heap to DDM\n");
940 dvmDdmSendHeapSegments(false, false);
941 }
942 if (gcHeap->ddmNhsgWhen != 0) {
943 LOGD_HEAP("Dumping native heap to DDM\n");
944 dvmDdmSendHeapSegments(false, true);
945 }
946}
947
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700948void dvmWaitForConcurrentGcToComplete(void)
949{
950 Thread *self = dvmThreadSelf();
951 ThreadStatus oldStatus;
952 assert(self != NULL);
953 oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
954 dvmWaitCond(&gDvm.gcHeapCond, &gDvm.gcHeapLock);
955 dvmChangeStatus(self, oldStatus);
956}
957
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800958#if WITH_HPROF
959/*
960 * Perform garbage collection, writing heap information to the specified file.
961 *
962 * If "fileName" is NULL, a suitable name will be generated automatically.
The Android Open Source Project99409882009-03-18 22:20:24 -0700963 *
964 * Returns 0 on success, or an error code on failure.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800965 */
Andy McFadden6bf992c2010-01-28 17:01:39 -0800966int hprofDumpHeap(const char* fileName, bool directToDdms)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800967{
The Android Open Source Project99409882009-03-18 22:20:24 -0700968 int result;
969
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800970 dvmLockMutex(&gDvm.gcHeapLock);
971
972 gDvm.gcHeap->hprofDumpOnGc = true;
973 gDvm.gcHeap->hprofFileName = fileName;
Andy McFadden6bf992c2010-01-28 17:01:39 -0800974 gDvm.gcHeap->hprofDirectToDdms = directToDdms;
Barry Hayes1b9b4e42010-01-04 10:33:46 -0800975 dvmCollectGarbageInternal(false, GC_HPROF_DUMP_HEAP);
The Android Open Source Project99409882009-03-18 22:20:24 -0700976 result = gDvm.gcHeap->hprofResult;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800977
978 dvmUnlockMutex(&gDvm.gcHeapLock);
The Android Open Source Project99409882009-03-18 22:20:24 -0700979
980 return result;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800981}
982
983void dvmHeapSetHprofGcScanState(hprof_heap_tag_t state, u4 threadSerialNumber)
984{
985 if (gDvm.gcHeap->hprofContext != NULL) {
986 hprofSetGcScanState(gDvm.gcHeap->hprofContext, state,
987 threadSerialNumber);
988 }
989}
990#endif