blob: 0c8feca8eb5614a048d8531ff7e00bf854eddbbc [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#include "Dalvik.h"
Barry Hayeseac47ed2009-06-22 11:45:20 -070018#include "alloc/clz.h"
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080019#include "alloc/HeapBitmap.h"
20#include "alloc/HeapInternal.h"
21#include "alloc/HeapSource.h"
22#include "alloc/MarkSweep.h"
23#include <limits.h> // for ULONG_MAX
24#include <sys/mman.h> // for madvise(), mmap()
25#include <cutils/ashmem.h>
The Android Open Source Project99409882009-03-18 22:20:24 -070026#include <errno.h>
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080027
28#define GC_DEBUG_PARANOID 2
29#define GC_DEBUG_BASIC 1
30#define GC_DEBUG_OFF 0
31#define GC_DEBUG(l) (GC_DEBUG_LEVEL >= (l))
32
33#if 1
34#define GC_DEBUG_LEVEL GC_DEBUG_PARANOID
35#else
36#define GC_DEBUG_LEVEL GC_DEBUG_OFF
37#endif
38
39#define VERBOSE_GC 0
40
41#define GC_LOG_TAG LOG_TAG "-gc"
42
43#if LOG_NDEBUG
44#define LOGV_GC(...) ((void)0)
45#define LOGD_GC(...) ((void)0)
46#else
47#define LOGV_GC(...) LOG(LOG_VERBOSE, GC_LOG_TAG, __VA_ARGS__)
48#define LOGD_GC(...) LOG(LOG_DEBUG, GC_LOG_TAG, __VA_ARGS__)
49#endif
50
51#if VERBOSE_GC
52#define LOGVV_GC(...) LOGV_GC(__VA_ARGS__)
53#else
54#define LOGVV_GC(...) ((void)0)
55#endif
56
57#define LOGI_GC(...) LOG(LOG_INFO, GC_LOG_TAG, __VA_ARGS__)
58#define LOGW_GC(...) LOG(LOG_WARN, GC_LOG_TAG, __VA_ARGS__)
59#define LOGE_GC(...) LOG(LOG_ERROR, GC_LOG_TAG, __VA_ARGS__)
60
61#define LOG_SCAN(...) LOGV_GC("SCAN: " __VA_ARGS__)
62#define LOG_MARK(...) LOGV_GC("MARK: " __VA_ARGS__)
63#define LOG_SWEEP(...) LOGV_GC("SWEEP: " __VA_ARGS__)
64#define LOG_REF(...) LOGV_GC("REF: " __VA_ARGS__)
65
66#define LOGV_SCAN(...) LOGVV_GC("SCAN: " __VA_ARGS__)
67#define LOGV_MARK(...) LOGVV_GC("MARK: " __VA_ARGS__)
68#define LOGV_SWEEP(...) LOGVV_GC("SWEEP: " __VA_ARGS__)
69#define LOGV_REF(...) LOGVV_GC("REF: " __VA_ARGS__)
70
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080071#define ALIGN_UP_TO_PAGE_SIZE(p) \
Andy McFadden96516932009-10-28 17:39:02 -070072 (((size_t)(p) + (SYSTEM_PAGE_SIZE - 1)) & ~(SYSTEM_PAGE_SIZE - 1))
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080073
74/* Do not cast the result of this to a boolean; the only set bit
75 * may be > 1<<8.
76 */
Carl Shapiro6343bd02010-02-16 17:40:19 -080077static inline long isMarked(const void *obj, const GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080078 __attribute__((always_inline));
Carl Shapiro6343bd02010-02-16 17:40:19 -080079static inline long isMarked(const void *obj, const GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080080{
Carl Shapirof373efd2010-02-19 00:46:33 -080081 return dvmHeapBitmapIsObjectBitSet(ctx->bitmap, obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080082}
83
84static bool
85createMarkStack(GcMarkStack *stack)
86{
87 const Object **limit;
88 size_t size;
The Android Open Source Project99409882009-03-18 22:20:24 -070089 int fd, err;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080090
91 /* Create a stack big enough for the worst possible case,
92 * where the heap is perfectly full of the smallest object.
93 * TODO: be better about memory usage; use a smaller stack with
94 * overflow detection and recovery.
95 */
96 size = dvmHeapSourceGetIdealFootprint() * sizeof(Object*) /
97 (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD);
98 size = ALIGN_UP_TO_PAGE_SIZE(size);
99 fd = ashmem_create_region("dalvik-heap-markstack", size);
100 if (fd < 0) {
The Android Open Source Project99409882009-03-18 22:20:24 -0700101 LOGE_GC("Could not create %d-byte ashmem mark stack: %s\n",
102 size, strerror(errno));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800103 return false;
104 }
105 limit = (const Object **)mmap(NULL, size, PROT_READ | PROT_WRITE,
106 MAP_PRIVATE, fd, 0);
The Android Open Source Project99409882009-03-18 22:20:24 -0700107 err = errno;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800108 close(fd);
109 if (limit == MAP_FAILED) {
The Android Open Source Project99409882009-03-18 22:20:24 -0700110 LOGE_GC("Could not mmap %d-byte ashmem mark stack: %s\n",
111 size, strerror(err));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800112 return false;
113 }
114
115 memset(stack, 0, sizeof(*stack));
116 stack->limit = limit;
117 stack->base = (const Object **)((uintptr_t)limit + size);
118 stack->top = stack->base;
119
120 return true;
121}
122
123static void
124destroyMarkStack(GcMarkStack *stack)
125{
126 munmap((char *)stack->limit,
127 (uintptr_t)stack->base - (uintptr_t)stack->limit);
128 memset(stack, 0, sizeof(*stack));
129}
130
131#define MARK_STACK_PUSH(stack, obj) \
132 do { \
133 *--(stack).top = (obj); \
134 } while (false)
135
136bool
137dvmHeapBeginMarkStep()
138{
139 GcMarkContext *mc = &gDvm.gcHeap->markContext;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800140
141 if (!createMarkStack(&mc->stack)) {
142 return false;
143 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800144 mc->finger = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800145 return true;
146}
147
Carl Shapiro6343bd02010-02-16 17:40:19 -0800148static long setAndReturnMarkBit(GcMarkContext *ctx, const void *obj)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800149 __attribute__((always_inline));
150static long
Carl Shapiro6343bd02010-02-16 17:40:19 -0800151setAndReturnMarkBit(GcMarkContext *ctx, const void *obj)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800152{
Carl Shapirof373efd2010-02-19 00:46:33 -0800153 return dvmHeapBitmapSetAndReturnObjectBit(ctx->bitmap, obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800154}
155
156static void _markObjectNonNullCommon(const Object *obj, GcMarkContext *ctx,
157 bool checkFinger, bool forceStack)
158 __attribute__((always_inline));
159static void
160_markObjectNonNullCommon(const Object *obj, GcMarkContext *ctx,
161 bool checkFinger, bool forceStack)
162{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800163 assert(obj != NULL);
164
165#if GC_DEBUG(GC_DEBUG_PARANOID)
166//TODO: make sure we're locked
167 assert(obj != (Object *)gDvm.unlinkedJavaLangClass);
168 assert(dvmIsValidObject(obj));
169#endif
170
Carl Shapiro6343bd02010-02-16 17:40:19 -0800171 if (!setAndReturnMarkBit(ctx, obj)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800172 /* This object was not previously marked.
173 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800174 if (forceStack || (checkFinger && (void *)obj < ctx->finger)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800175 /* This object will need to go on the mark stack.
176 */
177 MARK_STACK_PUSH(ctx->stack, obj);
178 }
179
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800180#if WITH_HPROF
181 if (gDvm.gcHeap->hprofContext != NULL) {
182 hprofMarkRootObject(gDvm.gcHeap->hprofContext, obj, 0);
183 }
184#endif
185#if DVM_TRACK_HEAP_MARKING
186 gDvm.gcHeap->markCount++;
Carl Shapiro6343bd02010-02-16 17:40:19 -0800187 gDvm.gcHeap->markSize += dvmHeapSourceChunkSize((void *)obj) +
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800188 HEAP_SOURCE_CHUNK_OVERHEAD;
189#endif
190
191 /* obj->clazz can be NULL if we catch an object between
192 * dvmMalloc() and DVM_OBJECT_INIT(). This is ok.
193 */
194 LOGV_MARK("0x%08x %s\n", (uint)obj,
195 obj->clazz == NULL ? "<null class>" : obj->clazz->name);
196 }
197}
198
199/* Used to mark objects when recursing. Recursion is done by moving
200 * the finger across the bitmaps in address order and marking child
201 * objects. Any newly-marked objects whose addresses are lower than
202 * the finger won't be visited by the bitmap scan, so those objects
203 * need to be added to the mark stack.
204 */
205static void
206markObjectNonNull(const Object *obj, GcMarkContext *ctx)
207{
208 _markObjectNonNullCommon(obj, ctx, true, false);
209}
210
211#define markObject(obj, ctx) \
212 do { \
213 Object *MO_obj_ = (Object *)(obj); \
214 if (MO_obj_ != NULL) { \
215 markObjectNonNull(MO_obj_, (ctx)); \
216 } \
217 } while (false)
218
219/* If the object hasn't already been marked, mark it and
220 * schedule it to be scanned for references.
221 *
222 * obj may not be NULL. The macro dvmMarkObject() should
223 * be used in situations where a reference may be NULL.
224 *
225 * This function may only be called when marking the root
226 * set. When recursing, use the internal markObject[NonNull]().
227 */
228void
229dvmMarkObjectNonNull(const Object *obj)
230{
231 _markObjectNonNullCommon(obj, &gDvm.gcHeap->markContext, false, false);
232}
233
234/* Mark the set of root objects.
235 *
236 * Things we need to scan:
237 * - System classes defined by root classloader
238 * - For each thread:
239 * - Interpreted stack, from top to "curFrame"
240 * - Dalvik registers (args + local vars)
241 * - JNI local references
242 * - Automatic VM local references (TrackedAlloc)
243 * - Associated Thread/VMThread object
244 * - ThreadGroups (could track & start with these instead of working
245 * upward from Threads)
246 * - Exception currently being thrown, if present
247 * - JNI global references
248 * - Interned string table
249 * - Primitive classes
250 * - Special objects
251 * - gDvm.outOfMemoryObj
252 * - Objects allocated with ALLOC_NO_GC
253 * - Objects pending finalization (but not yet finalized)
254 * - Objects in debugger object registry
255 *
256 * Don't need:
257 * - Native stack (for in-progress stuff in the VM)
258 * - The TrackedAlloc stuff watches all native VM references.
259 */
260void dvmHeapMarkRootSet()
261{
262 HeapRefTable *refs;
263 GcHeap *gcHeap;
264 Object **op;
265
266 gcHeap = gDvm.gcHeap;
267
268 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_STICKY_CLASS, 0);
269
270 LOG_SCAN("root class loader\n");
271 dvmGcScanRootClassLoader();
272 LOG_SCAN("primitive classes\n");
273 dvmGcScanPrimitiveClasses();
274
275 /* dvmGcScanRootThreadGroups() sets a bunch of
276 * different scan states internally.
277 */
278 HPROF_CLEAR_GC_SCAN_STATE();
279
280 LOG_SCAN("root thread groups\n");
281 dvmGcScanRootThreadGroups();
282
283 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_INTERNED_STRING, 0);
284
285 LOG_SCAN("interned strings\n");
286 dvmGcScanInternedStrings();
287
288 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JNI_GLOBAL, 0);
289
290 LOG_SCAN("JNI global refs\n");
291 dvmGcMarkJniGlobalRefs();
292
293 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_REFERENCE_CLEANUP, 0);
294
295 LOG_SCAN("pending reference operations\n");
296 dvmHeapMarkLargeTableRefs(gcHeap->referenceOperations, true);
297
298 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_FINALIZING, 0);
299
300 LOG_SCAN("pending finalizations\n");
301 dvmHeapMarkLargeTableRefs(gcHeap->pendingFinalizationRefs, false);
302
303 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_DEBUGGER, 0);
304
305 LOG_SCAN("debugger refs\n");
306 dvmGcMarkDebuggerRefs();
307
308 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_VM_INTERNAL, 0);
309
310 /* Mark all ALLOC_NO_GC objects.
311 */
312 LOG_SCAN("ALLOC_NO_GC objects\n");
313 refs = &gcHeap->nonCollectableRefs;
314 op = refs->table;
315 while ((uintptr_t)op < (uintptr_t)refs->nextEntry) {
316 dvmMarkObjectNonNull(*(op++));
317 }
318
319 /* Mark any special objects we have sitting around.
320 */
321 LOG_SCAN("special objects\n");
322 dvmMarkObjectNonNull(gDvm.outOfMemoryObj);
323 dvmMarkObjectNonNull(gDvm.internalErrorObj);
Andy McFadden7fc3ce82009-07-14 15:57:23 -0700324 dvmMarkObjectNonNull(gDvm.noClassDefFoundErrorObj);
Andy McFaddenb18992f2009-09-25 10:42:15 -0700325 dvmMarkObject(gDvm.jniWeakGlobalRefQueue);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800326//TODO: scan object references sitting in gDvm; use pointer begin & end
327
328 HPROF_CLEAR_GC_SCAN_STATE();
329}
330
331/*
332 * Nothing past this point is allowed to use dvmMarkObject*().
333 * Scanning/recursion must use markObject*(), which takes the
334 * finger into account.
335 */
336#define dvmMarkObjectNonNull __dont_use_dvmMarkObjectNonNull__
337
338
339/* Mark all of a ClassObject's interfaces.
340 */
341static void markInterfaces(const ClassObject *clazz, GcMarkContext *ctx)
342{
343 ClassObject **interfaces;
344 int interfaceCount;
345 int i;
346
347 /* Mark all interfaces.
348 */
349 interfaces = clazz->interfaces;
350 interfaceCount = clazz->interfaceCount;
351 for (i = 0; i < interfaceCount; i++) {
352 markObjectNonNull((Object *)*interfaces, ctx);
353 interfaces++;
354 }
355}
356
357/* Mark all objects referred to by a ClassObject's static fields.
358 */
359static void scanStaticFields(const ClassObject *clazz, GcMarkContext *ctx)
360{
361 StaticField *f;
362 int i;
363
364 //TODO: Optimize this with a bit vector or something
365 f = clazz->sfields;
366 for (i = 0; i < clazz->sfieldCount; i++) {
367 char c = f->field.signature[0];
368 if (c == '[' || c == 'L') {
369 /* It's an array or class reference.
370 */
371 markObject((Object *)f->value.l, ctx);
372 }
373 f++;
374 }
375}
376
377/* Mark all objects referred to by a DataObject's instance fields.
378 */
379static void scanInstanceFields(const DataObject *obj, ClassObject *clazz,
380 GcMarkContext *ctx)
381{
Barry Hayesd1497482009-10-28 15:32:19 -0700382 if (clazz->refOffsets != CLASS_WALK_SUPER) {
Barry Hayeseac47ed2009-06-22 11:45:20 -0700383 unsigned int refOffsets = clazz->refOffsets;
384 while (refOffsets != 0) {
385 const int rshift = CLZ(refOffsets);
386 refOffsets &= ~(CLASS_HIGH_BIT >> rshift);
387 markObject(dvmGetFieldObject((Object*)obj,
388 CLASS_OFFSET_FROM_CLZ(rshift)), ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800389 }
Barry Hayeseac47ed2009-06-22 11:45:20 -0700390 } else {
391 while (clazz != NULL) {
392 InstField *f;
393 int i;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800394
Barry Hayeseac47ed2009-06-22 11:45:20 -0700395 /* All of the fields that contain object references
396 * are guaranteed to be at the beginning of the ifields list.
397 */
398 f = clazz->ifields;
399 for (i = 0; i < clazz->ifieldRefCount; i++) {
400 /* Mark the array or object reference.
401 * May be NULL.
402 *
403 * Note that, per the comment on struct InstField,
404 * f->byteOffset is the offset from the beginning of
405 * obj, not the offset into obj->instanceData.
406 */
407 markObject(dvmGetFieldObject((Object*)obj, f->byteOffset), ctx);
408 f++;
409 }
410
411 /* This will be NULL when we hit java.lang.Object
412 */
413 clazz = clazz->super;
414 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800415 }
416}
417
418/* Mark all objects referred to by the array's contents.
419 */
420static void scanObjectArray(const ArrayObject *array, GcMarkContext *ctx)
421{
422 Object **contents;
423 u4 length;
424 u4 i;
425
426 contents = (Object **)array->contents;
427 length = array->length;
428
429 for (i = 0; i < length; i++) {
430 markObject(*contents, ctx); // may be NULL
431 contents++;
432 }
433}
434
435/* Mark all objects referred to by the ClassObject.
436 */
437static void scanClassObject(const ClassObject *clazz, GcMarkContext *ctx)
438{
439 LOGV_SCAN("---------> %s\n", clazz->name);
440
441 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
442 /* We're an array; mark the class object of the contents
443 * of the array.
444 *
445 * Note that we won't necessarily reach the array's element
446 * class by scanning the array contents; the array may be
447 * zero-length, or may only contain null objects.
448 */
449 markObjectNonNull((Object *)clazz->elementClass, ctx);
450 }
451
452 /* We scan these explicitly in case the only remaining
453 * reference to a particular class object is via a data
454 * object; we may not be guaranteed to reach all
455 * live class objects via a classloader.
456 */
457 markObject((Object *)clazz->super, ctx); // may be NULL (java.lang.Object)
458 markObject(clazz->classLoader, ctx); // may be NULL
459
460 scanStaticFields(clazz, ctx);
461 markInterfaces(clazz, ctx);
462}
463
464/* Mark all objects that obj refers to.
465 *
466 * Called on every object in markList.
467 */
468static void scanObject(const Object *obj, GcMarkContext *ctx)
469{
470 ClassObject *clazz;
471
472 assert(dvmIsValidObject(obj));
473 LOGV_SCAN("0x%08x %s\n", (uint)obj, obj->clazz->name);
474
475#if WITH_HPROF
476 if (gDvm.gcHeap->hprofContext != NULL) {
477 hprofDumpHeapObject(gDvm.gcHeap->hprofContext, obj);
478 }
479#endif
480
481 /* Get and mark the class object for this particular instance.
482 */
483 clazz = obj->clazz;
484 if (clazz == NULL) {
485 /* This can happen if we catch an object between
486 * dvmMalloc() and DVM_OBJECT_INIT(). The object
487 * won't contain any references yet, so we can
488 * just skip it.
489 */
490 return;
491 } else if (clazz == gDvm.unlinkedJavaLangClass) {
492 /* This class hasn't been linked yet. We're guaranteed
493 * that the object doesn't contain any references that
494 * aren't already tracked, so we can skip scanning it.
495 *
496 * NOTE: unlinkedJavaLangClass is not on the heap, so
497 * it's very important that we don't try marking it.
498 */
499 return;
500 }
Barry Hayes3592d622009-03-16 16:10:35 -0700501
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800502 assert(dvmIsValidObject((Object *)clazz));
503 markObjectNonNull((Object *)clazz, ctx);
504
505 /* Mark any references in this object.
506 */
507 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
508 /* It's an array object.
509 */
510 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOBJECTARRAY)) {
511 /* It's an array of object references.
512 */
513 scanObjectArray((ArrayObject *)obj, ctx);
514 }
515 // else there's nothing else to scan
516 } else {
517 /* It's a DataObject-compatible object.
518 */
519 scanInstanceFields((DataObject *)obj, clazz, ctx);
520
521 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISREFERENCE)) {
522 GcHeap *gcHeap = gDvm.gcHeap;
523 Object *referent;
524
525 /* It's a subclass of java/lang/ref/Reference.
526 * The fields in this class have been arranged
527 * such that scanInstanceFields() did not actually
528 * mark the "referent" field; we need to handle
529 * it specially.
530 *
531 * If the referent already has a strong mark (isMarked(referent)),
532 * we don't care about its reference status.
533 */
534 referent = dvmGetFieldObject(obj,
535 gDvm.offJavaLangRefReference_referent);
536 if (referent != NULL &&
Carl Shapiro6343bd02010-02-16 17:40:19 -0800537 !isMarked(referent, &gcHeap->markContext))
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800538 {
539 u4 refFlags;
540
541 if (gcHeap->markAllReferents) {
542 LOG_REF("Hard-marking a reference\n");
543
544 /* Don't bother with normal reference-following
545 * behavior, just mark the referent. This should
546 * only be used when following objects that just
547 * became scheduled for finalization.
548 */
549 markObjectNonNull(referent, ctx);
550 goto skip_reference;
551 }
552
553 /* See if this reference was handled by a previous GC.
554 */
555 if (dvmGetFieldObject(obj,
556 gDvm.offJavaLangRefReference_vmData) ==
557 SCHEDULED_REFERENCE_MAGIC)
558 {
559 LOG_REF("Skipping scheduled reference\n");
560
561 /* Don't reschedule it, but make sure that its
562 * referent doesn't get collected (in case it's
563 * a PhantomReference and wasn't cleared automatically).
564 */
565 //TODO: Mark these after handling all new refs of
566 // this strength, in case the new refs refer
567 // to the same referent. Not a very common
568 // case, though.
569 markObjectNonNull(referent, ctx);
570 goto skip_reference;
571 }
572
573 /* Find out what kind of reference is pointing
574 * to referent.
575 */
576 refFlags = GET_CLASS_FLAG_GROUP(clazz,
577 CLASS_ISREFERENCE |
578 CLASS_ISWEAKREFERENCE |
579 CLASS_ISPHANTOMREFERENCE);
580
581 /* We use the vmData field of Reference objects
582 * as a next pointer in a singly-linked list.
583 * That way, we don't need to allocate any memory
584 * while we're doing a GC.
585 */
586#define ADD_REF_TO_LIST(list, ref) \
587 do { \
588 Object *ARTL_ref_ = (/*de-const*/Object *)(ref); \
589 dvmSetFieldObject(ARTL_ref_, \
590 gDvm.offJavaLangRefReference_vmData, list); \
591 list = ARTL_ref_; \
592 } while (false)
593
594 /* At this stage, we just keep track of all of
595 * the live references that we've seen. Later,
596 * we'll walk through each of these lists and
597 * deal with the referents.
598 */
599 if (refFlags == CLASS_ISREFERENCE) {
600 /* It's a soft reference. Depending on the state,
601 * we'll attempt to collect all of them, some of
602 * them, or none of them.
603 */
604 if (gcHeap->softReferenceCollectionState ==
605 SR_COLLECT_NONE)
606 {
607 sr_collect_none:
608 markObjectNonNull(referent, ctx);
609 } else if (gcHeap->softReferenceCollectionState ==
610 SR_COLLECT_ALL)
611 {
612 sr_collect_all:
613 ADD_REF_TO_LIST(gcHeap->softReferences, obj);
614 } else {
615 /* We'll only try to collect half of the
616 * referents.
617 */
618 if (gcHeap->softReferenceColor++ & 1) {
619 goto sr_collect_none;
620 }
621 goto sr_collect_all;
622 }
623 } else {
624 /* It's a weak or phantom reference.
625 * Clearing CLASS_ISREFERENCE will reveal which.
626 */
627 refFlags &= ~CLASS_ISREFERENCE;
628 if (refFlags == CLASS_ISWEAKREFERENCE) {
629 ADD_REF_TO_LIST(gcHeap->weakReferences, obj);
630 } else if (refFlags == CLASS_ISPHANTOMREFERENCE) {
631 ADD_REF_TO_LIST(gcHeap->phantomReferences, obj);
632 } else {
633 assert(!"Unknown reference type");
634 }
635 }
636#undef ADD_REF_TO_LIST
637 }
638 }
639
640 skip_reference:
641 /* If this is a class object, mark various other things that
642 * its internals point to.
643 *
644 * All class objects are instances of java.lang.Class,
645 * including the java.lang.Class class object.
646 */
647 if (clazz == gDvm.classJavaLangClass) {
648 scanClassObject((ClassObject *)obj, ctx);
649 }
650 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800651}
652
653static void
654processMarkStack(GcMarkContext *ctx)
655{
656 const Object **const base = ctx->stack.base;
657
658 /* Scan anything that's on the mark stack.
659 * We can't use the bitmaps anymore, so use
660 * a finger that points past the end of them.
661 */
662 ctx->finger = (void *)ULONG_MAX;
663 while (ctx->stack.top != base) {
664 scanObject(*ctx->stack.top++, ctx);
665 }
666}
667
668#ifndef NDEBUG
669static uintptr_t gLastFinger = 0;
670#endif
671
672static bool
673scanBitmapCallback(size_t numPtrs, void **ptrs, const void *finger, void *arg)
674{
675 GcMarkContext *ctx = (GcMarkContext *)arg;
676 size_t i;
677
678#ifndef NDEBUG
679 assert((uintptr_t)finger >= gLastFinger);
680 gLastFinger = (uintptr_t)finger;
681#endif
682
683 ctx->finger = finger;
684 for (i = 0; i < numPtrs; i++) {
Carl Shapiro6343bd02010-02-16 17:40:19 -0800685 scanObject(*ptrs++, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800686 }
687
688 return true;
689}
690
691/* Given bitmaps with the root set marked, find and mark all
692 * reachable objects. When this returns, the entire set of
693 * live objects will be marked and the mark stack will be empty.
694 */
695void dvmHeapScanMarkedObjects()
696{
697 GcMarkContext *ctx = &gDvm.gcHeap->markContext;
698
699 assert(ctx->finger == NULL);
700
701 /* The bitmaps currently have bits set for the root set.
702 * Walk across the bitmaps and scan each object.
703 */
704#ifndef NDEBUG
705 gLastFinger = 0;
706#endif
Carl Shapirof373efd2010-02-19 00:46:33 -0800707 dvmHeapBitmapWalk(ctx->bitmap, scanBitmapCallback, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800708
709 /* We've walked the mark bitmaps. Scan anything that's
710 * left on the mark stack.
711 */
712 processMarkStack(ctx);
713
714 LOG_SCAN("done with marked objects\n");
715}
716
Barry Hayes6930a112009-12-22 11:01:38 -0800717/** Clear the referent field.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800718 */
Barry Hayes6930a112009-12-22 11:01:38 -0800719static void clearReference(Object *reference)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800720{
721 /* This is what the default implementation of Reference.clear()
722 * does. We're required to clear all references to a given
723 * referent atomically, so we can't pop in and out of interp
724 * code each time.
725 *
Barry Hayes6930a112009-12-22 11:01:38 -0800726 * We don't ever actaully call overriding implementations of
727 * Reference.clear().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800728 */
729 dvmSetFieldObject(reference,
730 gDvm.offJavaLangRefReference_referent, NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800731}
732
733/** @return true if we need to schedule a call to enqueue().
734 */
735static bool enqueueReference(Object *reference)
736{
Barry Hayes6930a112009-12-22 11:01:38 -0800737 Object *queue = dvmGetFieldObject(reference,
738 gDvm.offJavaLangRefReference_queue);
739 Object *queueNext = dvmGetFieldObject(reference,
740 gDvm.offJavaLangRefReference_queueNext);
741 if (queue == NULL || queueNext != NULL) {
742 /* There is no queue, or the reference has already
743 * been enqueued. The Reference.enqueue() method
744 * will do nothing even if we call it.
745 */
746 return false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800747 }
748
749 /* We need to call enqueue(), but if we called it from
750 * here we'd probably deadlock. Schedule a call.
751 */
752 return true;
753}
754
755/* All objects for stronger reference levels have been
756 * marked before this is called.
757 */
758void dvmHeapHandleReferences(Object *refListHead, enum RefType refType)
759{
760 Object *reference;
761 GcMarkContext *markContext = &gDvm.gcHeap->markContext;
762 const int offVmData = gDvm.offJavaLangRefReference_vmData;
763 const int offReferent = gDvm.offJavaLangRefReference_referent;
764 bool workRequired = false;
765
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800766 reference = refListHead;
767 while (reference != NULL) {
768 Object *next;
769 Object *referent;
770
771 /* Pull the interesting fields out of the Reference object.
772 */
773 next = dvmGetFieldObject(reference, offVmData);
774 referent = dvmGetFieldObject(reference, offReferent);
775
776 //TODO: when handling REF_PHANTOM, unlink any references
777 // that fail this initial if(). We need to re-walk
778 // the list, and it would be nice to avoid the extra
779 // work.
Carl Shapiro6343bd02010-02-16 17:40:19 -0800780 if (referent != NULL && !isMarked(referent, markContext)) {
Barry Hayes6930a112009-12-22 11:01:38 -0800781 bool schedEnqueue;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800782
783 /* This is the strongest reference that refers to referent.
784 * Do the right thing.
785 */
786 switch (refType) {
787 case REF_SOFT:
788 case REF_WEAK:
Barry Hayes6930a112009-12-22 11:01:38 -0800789 clearReference(reference);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800790 schedEnqueue = enqueueReference(reference);
791 break;
792 case REF_PHANTOM:
793 /* PhantomReferences are not cleared automatically.
794 * Until someone clears it (or the reference itself
795 * is collected), the referent must remain alive.
796 *
797 * It's necessary to fully mark the referent because
798 * it will still be present during the next GC, and
799 * all objects that it points to must be valid.
800 * (The referent will be marked outside of this loop,
801 * after handing all references of this strength, in
802 * case multiple references point to the same object.)
Andy McFaddenb18992f2009-09-25 10:42:15 -0700803 *
804 * One exception: JNI "weak global" references are handled
805 * as a special case. They're identified by the queue.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800806 */
Andy McFaddenb18992f2009-09-25 10:42:15 -0700807 if (gDvm.jniWeakGlobalRefQueue != NULL) {
808 Object* queue = dvmGetFieldObject(reference,
809 gDvm.offJavaLangRefReference_queue);
810 if (queue == gDvm.jniWeakGlobalRefQueue) {
811 LOGV("+++ WGR: clearing + not queueing %p:%p\n",
812 reference, referent);
Barry Hayes6930a112009-12-22 11:01:38 -0800813 clearReference(reference);
Andy McFaddenb18992f2009-09-25 10:42:15 -0700814 schedEnqueue = false;
815 break;
816 }
817 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800818
819 /* A PhantomReference is only useful with a
820 * queue, but since it's possible to create one
821 * without a queue, we need to check.
822 */
823 schedEnqueue = enqueueReference(reference);
824 break;
825 default:
826 assert(!"Bad reference type");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800827 schedEnqueue = false;
828 break;
829 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800830
Barry Hayes6930a112009-12-22 11:01:38 -0800831 if (schedEnqueue) {
Barry Hayes6930a112009-12-22 11:01:38 -0800832 /* Stuff the enqueue bit in the bottom of the pointer.
833 * Assumes that objects are 8-byte aligned.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800834 *
835 * Note that we are adding the *Reference* (which
836 * is by definition already marked at this point) to
837 * this list; we're not adding the referent (which
838 * has already been cleared).
839 */
840 assert(((intptr_t)reference & 3) == 0);
Barry Hayes6930a112009-12-22 11:01:38 -0800841 assert((WORKER_ENQUEUE & ~3) == 0);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800842 if (!dvmHeapAddRefToLargeTable(
843 &gDvm.gcHeap->referenceOperations,
Barry Hayes6930a112009-12-22 11:01:38 -0800844 (Object *)((uintptr_t)reference | WORKER_ENQUEUE)))
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800845 {
846 LOGE_HEAP("dvmMalloc(): no room for any more "
847 "reference operations\n");
848 dvmAbort();
849 }
850 workRequired = true;
851 }
852
853 if (refType != REF_PHANTOM) {
854 /* Let later GCs know not to reschedule this reference.
855 */
856 dvmSetFieldObject(reference, offVmData,
857 SCHEDULED_REFERENCE_MAGIC);
858 } // else this is handled later for REF_PHANTOM
859
860 } // else there was a stronger reference to the referent.
861
862 reference = next;
863 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800864
865 /* Walk though the reference list again, and mark any non-clear/marked
866 * referents. Only PhantomReferences can have non-clear referents
867 * at this point.
Andy McFaddenb18992f2009-09-25 10:42:15 -0700868 *
869 * (Could skip this for JNI weak globals, since we know they've been
870 * cleared.)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800871 */
872 if (refType == REF_PHANTOM) {
873 bool scanRequired = false;
874
875 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_REFERENCE_CLEANUP, 0);
876 reference = refListHead;
877 while (reference != NULL) {
878 Object *next;
879 Object *referent;
880
881 /* Pull the interesting fields out of the Reference object.
882 */
883 next = dvmGetFieldObject(reference, offVmData);
884 referent = dvmGetFieldObject(reference, offReferent);
885
Carl Shapiro6343bd02010-02-16 17:40:19 -0800886 if (referent != NULL && !isMarked(referent, markContext)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800887 markObjectNonNull(referent, markContext);
888 scanRequired = true;
889
890 /* Let later GCs know not to reschedule this reference.
891 */
892 dvmSetFieldObject(reference, offVmData,
893 SCHEDULED_REFERENCE_MAGIC);
894 }
895
896 reference = next;
897 }
898 HPROF_CLEAR_GC_SCAN_STATE();
899
900 if (scanRequired) {
901 processMarkStack(markContext);
902 }
903 }
904
905 if (workRequired) {
906 dvmSignalHeapWorker(false);
907 }
908}
909
910
911/* Find unreachable objects that need to be finalized,
912 * and schedule them for finalization.
913 */
914void dvmHeapScheduleFinalizations()
915{
916 HeapRefTable newPendingRefs;
917 LargeHeapRefTable *finRefs = gDvm.gcHeap->finalizableRefs;
918 Object **ref;
919 Object **lastRef;
920 size_t totalPendCount;
921 GcMarkContext *markContext = &gDvm.gcHeap->markContext;
922
923 /*
924 * All reachable objects have been marked.
925 * Any unmarked finalizable objects need to be finalized.
926 */
927
928 /* Create a table that the new pending refs will
929 * be added to.
930 */
931 if (!dvmHeapInitHeapRefTable(&newPendingRefs, 128)) {
932 //TODO: mark all finalizable refs and hope that
933 // we can schedule them next time. Watch out,
934 // because we may be expecting to free up space
935 // by calling finalizers.
936 LOGE_GC("dvmHeapScheduleFinalizations(): no room for "
937 "pending finalizations\n");
938 dvmAbort();
939 }
940
941 /* Walk through finalizableRefs and move any unmarked references
942 * to the list of new pending refs.
943 */
944 totalPendCount = 0;
945 while (finRefs != NULL) {
946 Object **gapRef;
947 size_t newPendCount = 0;
948
949 gapRef = ref = finRefs->refs.table;
950 lastRef = finRefs->refs.nextEntry;
951 while (ref < lastRef) {
Carl Shapiro6343bd02010-02-16 17:40:19 -0800952 if (!isMarked(*ref, markContext)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800953 if (!dvmHeapAddToHeapRefTable(&newPendingRefs, *ref)) {
954 //TODO: add the current table and allocate
955 // a new, smaller one.
956 LOGE_GC("dvmHeapScheduleFinalizations(): "
957 "no room for any more pending finalizations: %zd\n",
958 dvmHeapNumHeapRefTableEntries(&newPendingRefs));
959 dvmAbort();
960 }
961 newPendCount++;
962 } else {
963 /* This ref is marked, so will remain on finalizableRefs.
964 */
965 if (newPendCount > 0) {
966 /* Copy it up to fill the holes.
967 */
968 *gapRef++ = *ref;
969 } else {
970 /* No holes yet; don't bother copying.
971 */
972 gapRef++;
973 }
974 }
975 ref++;
976 }
977 finRefs->refs.nextEntry = gapRef;
978 //TODO: if the table is empty when we're done, free it.
979 totalPendCount += newPendCount;
980 finRefs = finRefs->next;
981 }
982 LOGD_GC("dvmHeapScheduleFinalizations(): %zd finalizers triggered.\n",
983 totalPendCount);
984 if (totalPendCount == 0) {
985 /* No objects required finalization.
986 * Free the empty temporary table.
987 */
988 dvmClearReferenceTable(&newPendingRefs);
989 return;
990 }
991
992 /* Add the new pending refs to the main list.
993 */
994 if (!dvmHeapAddTableToLargeTable(&gDvm.gcHeap->pendingFinalizationRefs,
995 &newPendingRefs))
996 {
997 LOGE_GC("dvmHeapScheduleFinalizations(): can't insert new "
998 "pending finalizations\n");
999 dvmAbort();
1000 }
1001
1002 //TODO: try compacting the main list with a memcpy loop
1003
1004 /* Mark the refs we just moved; we don't want them or their
1005 * children to get swept yet.
1006 */
1007 ref = newPendingRefs.table;
1008 lastRef = newPendingRefs.nextEntry;
1009 assert(ref < lastRef);
1010 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_FINALIZING, 0);
1011 while (ref < lastRef) {
1012 markObjectNonNull(*ref, markContext);
1013 ref++;
1014 }
1015 HPROF_CLEAR_GC_SCAN_STATE();
1016
1017 /* Set markAllReferents so that we don't collect referents whose
1018 * only references are in final-reachable objects.
1019 * TODO: eventually provide normal reference behavior by properly
1020 * marking these references.
1021 */
1022 gDvm.gcHeap->markAllReferents = true;
1023 processMarkStack(markContext);
1024 gDvm.gcHeap->markAllReferents = false;
1025
1026 dvmSignalHeapWorker(false);
1027}
1028
1029void dvmHeapFinishMarkStep()
1030{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001031 GcMarkContext *markContext;
1032
1033 markContext = &gDvm.gcHeap->markContext;
1034
1035 /* The sweep step freed every object that appeared in the
1036 * HeapSource bitmaps that didn't appear in the mark bitmaps.
1037 * The new state of the HeapSource is exactly the final
1038 * mark bitmaps, so swap them in.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001039 */
Carl Shapirof373efd2010-02-19 00:46:33 -08001040 dvmHeapSourceSwapBitmaps();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001041
Carl Shapirof373efd2010-02-19 00:46:33 -08001042 /* Clean up everything else associated with the marking process.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001043 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001044 destroyMarkStack(&markContext->stack);
1045
Carl Shapirof373efd2010-02-19 00:46:33 -08001046 markContext->finger = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001047}
1048
1049#if WITH_HPROF && WITH_HPROF_UNREACHABLE
1050static bool
1051hprofUnreachableBitmapCallback(size_t numPtrs, void **ptrs,
1052 const void *finger, void *arg)
1053{
1054 hprof_context_t *hctx = (hprof_context_t *)arg;
1055 size_t i;
1056
1057 for (i = 0; i < numPtrs; i++) {
1058 Object *obj;
1059
Carl Shapiro6343bd02010-02-16 17:40:19 -08001060 obj = (Object *)*ptrs++;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001061
1062 hprofMarkRootObject(hctx, obj, 0);
1063 hprofDumpHeapObject(hctx, obj);
1064 }
1065
1066 return true;
1067}
1068
1069static void
1070hprofDumpUnmarkedObjects(const HeapBitmap markBitmaps[],
1071 const HeapBitmap objectBitmaps[], size_t numBitmaps)
1072{
1073 hprof_context_t *hctx = gDvm.gcHeap->hprofContext;
1074 if (hctx == NULL) {
1075 return;
1076 }
1077
1078 LOGI("hprof: dumping unreachable objects\n");
1079
1080 HPROF_SET_GC_SCAN_STATE(HPROF_UNREACHABLE, 0);
1081
1082 dvmHeapBitmapXorWalkLists(markBitmaps, objectBitmaps, numBitmaps,
1083 hprofUnreachableBitmapCallback, hctx);
1084
1085 HPROF_CLEAR_GC_SCAN_STATE();
1086}
1087#endif
1088
1089static bool
1090sweepBitmapCallback(size_t numPtrs, void **ptrs, const void *finger, void *arg)
1091{
1092 const ClassObject *const classJavaLangClass = gDvm.classJavaLangClass;
Barry Hayes5cbb2302010-02-02 14:07:37 -08001093 const bool overwriteFree = gDvm.overwriteFree;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001094 size_t i;
Barry Hayesdde8ab02009-05-20 12:10:36 -07001095 void **origPtrs = ptrs;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001096
1097 for (i = 0; i < numPtrs; i++) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001098 Object *obj;
1099
Carl Shapiro6343bd02010-02-16 17:40:19 -08001100 obj = (Object *)*ptrs++;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001101
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001102 /* NOTE: Dereferencing clazz is dangerous. If obj was the last
1103 * one to reference its class object, the class object could be
1104 * on the sweep list, and could already have been swept, leaving
1105 * us with a stale pointer.
1106 */
1107 LOGV_SWEEP("FREE: 0x%08x %s\n", (uint)obj, obj->clazz->name);
1108
1109 /* This assumes that java.lang.Class will never go away.
1110 * If it can, and we were the last reference to it, it
1111 * could have already been swept. However, even in that case,
1112 * gDvm.classJavaLangClass should still have a useful
1113 * value.
1114 */
1115 if (obj->clazz == classJavaLangClass) {
1116 LOGV_SWEEP("---------------> %s\n", ((ClassObject *)obj)->name);
1117 /* dvmFreeClassInnards() may have already been called,
1118 * but it's safe to call on the same ClassObject twice.
1119 */
1120 dvmFreeClassInnards((ClassObject *)obj);
1121 }
1122
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001123 /* Overwrite the to-be-freed object to make stale references
1124 * more obvious.
1125 */
Barry Hayes5cbb2302010-02-02 14:07:37 -08001126 if (overwriteFree) {
Barry Hayes2e3c3e12010-02-22 09:39:10 -08001127 int objlen;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001128 ClassObject *clazz = obj->clazz;
Barry Hayes2e3c3e12010-02-22 09:39:10 -08001129 objlen = dvmHeapSourceChunkSize(obj);
1130 memset(obj, 0xa5, objlen);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001131 obj->clazz = (ClassObject *)((uintptr_t)clazz ^ 0xffffffff);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001132 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001133 }
Barry Hayesdde8ab02009-05-20 12:10:36 -07001134 // TODO: dvmHeapSourceFreeList has a loop, just like the above
1135 // does. Consider collapsing the two loops to save overhead.
1136 dvmHeapSourceFreeList(numPtrs, origPtrs);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001137
1138 return true;
1139}
1140
Carl Shapiro5a6071b2010-01-07 21:35:50 -08001141/* Returns true if the given object is unmarked. Ignores the low bits
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001142 * of the pointer because the intern table may set them.
1143 */
1144static int isUnmarkedObject(void *object)
1145{
Carl Shapiro6343bd02010-02-16 17:40:19 -08001146 return !isMarked((void *)((uintptr_t)object & ~(HB_OBJECT_ALIGNMENT-1)),
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001147 &gDvm.gcHeap->markContext);
1148}
1149
1150/* Walk through the list of objects that haven't been
1151 * marked and free them.
1152 */
1153void
1154dvmHeapSweepUnmarkedObjects(int *numFreed, size_t *sizeFreed)
1155{
Carl Shapirof373efd2010-02-19 00:46:33 -08001156 HeapBitmap markBits[HEAP_SOURCE_MAX_HEAP_COUNT];
1157 HeapBitmap objBits[HEAP_SOURCE_MAX_HEAP_COUNT];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001158 size_t origObjectsAllocated;
1159 size_t origBytesAllocated;
1160 size_t numBitmaps;
1161
1162 /* All reachable objects have been marked.
1163 * Detach any unreachable interned strings before
1164 * we sweep.
1165 */
1166 dvmGcDetachDeadInternedStrings(isUnmarkedObject);
1167
1168 /* Free any known objects that are not marked.
1169 */
1170 origObjectsAllocated = dvmHeapSourceGetValue(HS_OBJECTS_ALLOCATED, NULL, 0);
1171 origBytesAllocated = dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);
1172
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001173#if WITH_HPROF && WITH_HPROF_UNREACHABLE
1174 hprofDumpUnmarkedObjects(markBitmaps, objectBitmaps, numBitmaps);
1175#endif
1176
Carl Shapiro5a6071b2010-01-07 21:35:50 -08001177 dvmSweepMonitorList(&gDvm.monitorList, isUnmarkedObject);
1178
Carl Shapirof373efd2010-02-19 00:46:33 -08001179 numBitmaps = dvmHeapSourceGetNumHeaps();
1180 dvmHeapSourceGetObjectBitmaps(objBits, markBits, numBitmaps);
1181 dvmHeapBitmapXorWalkLists(markBits, objBits, numBitmaps,
1182 sweepBitmapCallback, NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001183
1184 *numFreed = origObjectsAllocated -
1185 dvmHeapSourceGetValue(HS_OBJECTS_ALLOCATED, NULL, 0);
1186 *sizeFreed = origBytesAllocated -
1187 dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);
1188
1189#ifdef WITH_PROFILER
1190 if (gDvm.allocProf.enabled) {
1191 gDvm.allocProf.freeCount += *numFreed;
1192 gDvm.allocProf.freeSize += *sizeFreed;
1193 }
1194#endif
1195}