blob: 459a23841d2d85ef29af46bc910310c8b791e07a [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
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800167 assert(dvmIsValidObject(obj));
168#endif
169
Carl Shapiro6343bd02010-02-16 17:40:19 -0800170 if (!setAndReturnMarkBit(ctx, obj)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800171 /* This object was not previously marked.
172 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800173 if (forceStack || (checkFinger && (void *)obj < ctx->finger)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800174 /* This object will need to go on the mark stack.
175 */
176 MARK_STACK_PUSH(ctx->stack, obj);
177 }
178
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800179#if WITH_HPROF
180 if (gDvm.gcHeap->hprofContext != NULL) {
181 hprofMarkRootObject(gDvm.gcHeap->hprofContext, obj, 0);
182 }
183#endif
184#if DVM_TRACK_HEAP_MARKING
185 gDvm.gcHeap->markCount++;
Carl Shapiro6343bd02010-02-16 17:40:19 -0800186 gDvm.gcHeap->markSize += dvmHeapSourceChunkSize((void *)obj) +
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800187 HEAP_SOURCE_CHUNK_OVERHEAD;
188#endif
189
190 /* obj->clazz can be NULL if we catch an object between
191 * dvmMalloc() and DVM_OBJECT_INIT(). This is ok.
192 */
193 LOGV_MARK("0x%08x %s\n", (uint)obj,
194 obj->clazz == NULL ? "<null class>" : obj->clazz->name);
195 }
196}
197
198/* Used to mark objects when recursing. Recursion is done by moving
199 * the finger across the bitmaps in address order and marking child
200 * objects. Any newly-marked objects whose addresses are lower than
201 * the finger won't be visited by the bitmap scan, so those objects
202 * need to be added to the mark stack.
203 */
204static void
205markObjectNonNull(const Object *obj, GcMarkContext *ctx)
206{
207 _markObjectNonNullCommon(obj, ctx, true, false);
208}
209
210#define markObject(obj, ctx) \
211 do { \
212 Object *MO_obj_ = (Object *)(obj); \
213 if (MO_obj_ != NULL) { \
214 markObjectNonNull(MO_obj_, (ctx)); \
215 } \
216 } while (false)
217
218/* If the object hasn't already been marked, mark it and
219 * schedule it to be scanned for references.
220 *
221 * obj may not be NULL. The macro dvmMarkObject() should
222 * be used in situations where a reference may be NULL.
223 *
224 * This function may only be called when marking the root
225 * set. When recursing, use the internal markObject[NonNull]().
226 */
227void
228dvmMarkObjectNonNull(const Object *obj)
229{
230 _markObjectNonNullCommon(obj, &gDvm.gcHeap->markContext, false, false);
231}
232
233/* Mark the set of root objects.
234 *
235 * Things we need to scan:
236 * - System classes defined by root classloader
237 * - For each thread:
238 * - Interpreted stack, from top to "curFrame"
239 * - Dalvik registers (args + local vars)
240 * - JNI local references
241 * - Automatic VM local references (TrackedAlloc)
242 * - Associated Thread/VMThread object
243 * - ThreadGroups (could track & start with these instead of working
244 * upward from Threads)
245 * - Exception currently being thrown, if present
246 * - JNI global references
247 * - Interned string table
248 * - Primitive classes
249 * - Special objects
250 * - gDvm.outOfMemoryObj
251 * - Objects allocated with ALLOC_NO_GC
252 * - Objects pending finalization (but not yet finalized)
253 * - Objects in debugger object registry
254 *
255 * Don't need:
256 * - Native stack (for in-progress stuff in the VM)
257 * - The TrackedAlloc stuff watches all native VM references.
258 */
259void dvmHeapMarkRootSet()
260{
261 HeapRefTable *refs;
262 GcHeap *gcHeap;
263 Object **op;
264
265 gcHeap = gDvm.gcHeap;
266
267 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_STICKY_CLASS, 0);
268
269 LOG_SCAN("root class loader\n");
270 dvmGcScanRootClassLoader();
271 LOG_SCAN("primitive classes\n");
272 dvmGcScanPrimitiveClasses();
273
274 /* dvmGcScanRootThreadGroups() sets a bunch of
275 * different scan states internally.
276 */
277 HPROF_CLEAR_GC_SCAN_STATE();
278
279 LOG_SCAN("root thread groups\n");
280 dvmGcScanRootThreadGroups();
281
282 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_INTERNED_STRING, 0);
283
284 LOG_SCAN("interned strings\n");
285 dvmGcScanInternedStrings();
286
287 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JNI_GLOBAL, 0);
288
289 LOG_SCAN("JNI global refs\n");
290 dvmGcMarkJniGlobalRefs();
291
292 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_REFERENCE_CLEANUP, 0);
293
294 LOG_SCAN("pending reference operations\n");
295 dvmHeapMarkLargeTableRefs(gcHeap->referenceOperations, true);
296
297 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_FINALIZING, 0);
298
299 LOG_SCAN("pending finalizations\n");
300 dvmHeapMarkLargeTableRefs(gcHeap->pendingFinalizationRefs, false);
301
302 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_DEBUGGER, 0);
303
304 LOG_SCAN("debugger refs\n");
305 dvmGcMarkDebuggerRefs();
306
307 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_VM_INTERNAL, 0);
308
309 /* Mark all ALLOC_NO_GC objects.
310 */
311 LOG_SCAN("ALLOC_NO_GC objects\n");
312 refs = &gcHeap->nonCollectableRefs;
313 op = refs->table;
314 while ((uintptr_t)op < (uintptr_t)refs->nextEntry) {
315 dvmMarkObjectNonNull(*(op++));
316 }
317
318 /* Mark any special objects we have sitting around.
319 */
320 LOG_SCAN("special objects\n");
321 dvmMarkObjectNonNull(gDvm.outOfMemoryObj);
322 dvmMarkObjectNonNull(gDvm.internalErrorObj);
Andy McFadden7fc3ce82009-07-14 15:57:23 -0700323 dvmMarkObjectNonNull(gDvm.noClassDefFoundErrorObj);
Andy McFaddenb18992f2009-09-25 10:42:15 -0700324 dvmMarkObject(gDvm.jniWeakGlobalRefQueue);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800325//TODO: scan object references sitting in gDvm; use pointer begin & end
326
327 HPROF_CLEAR_GC_SCAN_STATE();
328}
329
330/*
331 * Nothing past this point is allowed to use dvmMarkObject*().
332 * Scanning/recursion must use markObject*(), which takes the
333 * finger into account.
334 */
335#define dvmMarkObjectNonNull __dont_use_dvmMarkObjectNonNull__
336
337
338/* Mark all of a ClassObject's interfaces.
339 */
340static void markInterfaces(const ClassObject *clazz, GcMarkContext *ctx)
341{
342 ClassObject **interfaces;
343 int interfaceCount;
344 int i;
345
346 /* Mark all interfaces.
347 */
348 interfaces = clazz->interfaces;
349 interfaceCount = clazz->interfaceCount;
350 for (i = 0; i < interfaceCount; i++) {
351 markObjectNonNull((Object *)*interfaces, ctx);
352 interfaces++;
353 }
354}
355
356/* Mark all objects referred to by a ClassObject's static fields.
357 */
358static void scanStaticFields(const ClassObject *clazz, GcMarkContext *ctx)
359{
360 StaticField *f;
361 int i;
362
363 //TODO: Optimize this with a bit vector or something
Barry Hayes03aa70a2010-03-01 15:49:41 -0800364 f = &clazz->sfields[0];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800365 for (i = 0; i < clazz->sfieldCount; i++) {
366 char c = f->field.signature[0];
367 if (c == '[' || c == 'L') {
368 /* It's an array or class reference.
369 */
370 markObject((Object *)f->value.l, ctx);
371 }
372 f++;
373 }
374}
375
376/* Mark all objects referred to by a DataObject's instance fields.
377 */
378static void scanInstanceFields(const DataObject *obj, ClassObject *clazz,
379 GcMarkContext *ctx)
380{
Barry Hayesd1497482009-10-28 15:32:19 -0700381 if (clazz->refOffsets != CLASS_WALK_SUPER) {
Barry Hayeseac47ed2009-06-22 11:45:20 -0700382 unsigned int refOffsets = clazz->refOffsets;
383 while (refOffsets != 0) {
384 const int rshift = CLZ(refOffsets);
385 refOffsets &= ~(CLASS_HIGH_BIT >> rshift);
386 markObject(dvmGetFieldObject((Object*)obj,
387 CLASS_OFFSET_FROM_CLZ(rshift)), ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800388 }
Barry Hayeseac47ed2009-06-22 11:45:20 -0700389 } else {
390 while (clazz != NULL) {
391 InstField *f;
392 int i;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800393
Barry Hayeseac47ed2009-06-22 11:45:20 -0700394 /* All of the fields that contain object references
395 * are guaranteed to be at the beginning of the ifields list.
396 */
397 f = clazz->ifields;
398 for (i = 0; i < clazz->ifieldRefCount; i++) {
399 /* Mark the array or object reference.
400 * May be NULL.
401 *
402 * Note that, per the comment on struct InstField,
403 * f->byteOffset is the offset from the beginning of
404 * obj, not the offset into obj->instanceData.
405 */
406 markObject(dvmGetFieldObject((Object*)obj, f->byteOffset), ctx);
407 f++;
408 }
409
410 /* This will be NULL when we hit java.lang.Object
411 */
412 clazz = clazz->super;
413 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800414 }
415}
416
417/* Mark all objects referred to by the array's contents.
418 */
419static void scanObjectArray(const ArrayObject *array, GcMarkContext *ctx)
420{
421 Object **contents;
422 u4 length;
423 u4 i;
424
425 contents = (Object **)array->contents;
426 length = array->length;
427
428 for (i = 0; i < length; i++) {
429 markObject(*contents, ctx); // may be NULL
430 contents++;
431 }
432}
433
434/* Mark all objects referred to by the ClassObject.
435 */
436static void scanClassObject(const ClassObject *clazz, GcMarkContext *ctx)
437{
438 LOGV_SCAN("---------> %s\n", clazz->name);
439
440 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
441 /* We're an array; mark the class object of the contents
442 * of the array.
443 *
444 * Note that we won't necessarily reach the array's element
445 * class by scanning the array contents; the array may be
446 * zero-length, or may only contain null objects.
447 */
448 markObjectNonNull((Object *)clazz->elementClass, ctx);
449 }
450
451 /* We scan these explicitly in case the only remaining
452 * reference to a particular class object is via a data
453 * object; we may not be guaranteed to reach all
454 * live class objects via a classloader.
455 */
456 markObject((Object *)clazz->super, ctx); // may be NULL (java.lang.Object)
457 markObject(clazz->classLoader, ctx); // may be NULL
458
459 scanStaticFields(clazz, ctx);
460 markInterfaces(clazz, ctx);
461}
462
463/* Mark all objects that obj refers to.
464 *
465 * Called on every object in markList.
466 */
467static void scanObject(const Object *obj, GcMarkContext *ctx)
468{
469 ClassObject *clazz;
470
471 assert(dvmIsValidObject(obj));
Barry Hayes03aa70a2010-03-01 15:49:41 -0800472 LOGV_SCAN("0x%08x %s\n", (uint)obj, obj->clazz->descriptor);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800473
474#if WITH_HPROF
475 if (gDvm.gcHeap->hprofContext != NULL) {
476 hprofDumpHeapObject(gDvm.gcHeap->hprofContext, obj);
477 }
478#endif
479
480 /* Get and mark the class object for this particular instance.
481 */
482 clazz = obj->clazz;
483 if (clazz == NULL) {
Barry Hayesb36e6402010-03-05 09:51:12 -0800484 /* This can happen if we catch an object between dvmMalloc()
485 * and DVM_OBJECT_INIT(). The object won't contain any
486 * references yet, so we can just skip it. It can also mean
487 * that this object is unlinkedJavaLangClass, which has its
488 * clazz explicitly set to NULL.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800489 */
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.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800495 */
496 return;
497 }
Barry Hayes3592d622009-03-16 16:10:35 -0700498
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800499 assert(dvmIsValidObject((Object *)clazz));
500 markObjectNonNull((Object *)clazz, ctx);
501
502 /* Mark any references in this object.
503 */
504 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
505 /* It's an array object.
506 */
507 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOBJECTARRAY)) {
508 /* It's an array of object references.
509 */
510 scanObjectArray((ArrayObject *)obj, ctx);
511 }
512 // else there's nothing else to scan
513 } else {
514 /* It's a DataObject-compatible object.
515 */
516 scanInstanceFields((DataObject *)obj, clazz, ctx);
517
518 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISREFERENCE)) {
519 GcHeap *gcHeap = gDvm.gcHeap;
520 Object *referent;
521
522 /* It's a subclass of java/lang/ref/Reference.
523 * The fields in this class have been arranged
524 * such that scanInstanceFields() did not actually
525 * mark the "referent" field; we need to handle
526 * it specially.
527 *
528 * If the referent already has a strong mark (isMarked(referent)),
529 * we don't care about its reference status.
530 */
531 referent = dvmGetFieldObject(obj,
532 gDvm.offJavaLangRefReference_referent);
533 if (referent != NULL &&
Carl Shapiro6343bd02010-02-16 17:40:19 -0800534 !isMarked(referent, &gcHeap->markContext))
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800535 {
536 u4 refFlags;
537
538 if (gcHeap->markAllReferents) {
539 LOG_REF("Hard-marking a reference\n");
540
541 /* Don't bother with normal reference-following
542 * behavior, just mark the referent. This should
543 * only be used when following objects that just
544 * became scheduled for finalization.
545 */
546 markObjectNonNull(referent, ctx);
547 goto skip_reference;
548 }
549
550 /* See if this reference was handled by a previous GC.
551 */
552 if (dvmGetFieldObject(obj,
553 gDvm.offJavaLangRefReference_vmData) ==
554 SCHEDULED_REFERENCE_MAGIC)
555 {
556 LOG_REF("Skipping scheduled reference\n");
557
558 /* Don't reschedule it, but make sure that its
559 * referent doesn't get collected (in case it's
560 * a PhantomReference and wasn't cleared automatically).
561 */
562 //TODO: Mark these after handling all new refs of
563 // this strength, in case the new refs refer
564 // to the same referent. Not a very common
565 // case, though.
566 markObjectNonNull(referent, ctx);
567 goto skip_reference;
568 }
569
570 /* Find out what kind of reference is pointing
571 * to referent.
572 */
573 refFlags = GET_CLASS_FLAG_GROUP(clazz,
574 CLASS_ISREFERENCE |
575 CLASS_ISWEAKREFERENCE |
576 CLASS_ISPHANTOMREFERENCE);
577
578 /* We use the vmData field of Reference objects
579 * as a next pointer in a singly-linked list.
580 * That way, we don't need to allocate any memory
581 * while we're doing a GC.
582 */
583#define ADD_REF_TO_LIST(list, ref) \
584 do { \
585 Object *ARTL_ref_ = (/*de-const*/Object *)(ref); \
586 dvmSetFieldObject(ARTL_ref_, \
587 gDvm.offJavaLangRefReference_vmData, list); \
588 list = ARTL_ref_; \
589 } while (false)
590
591 /* At this stage, we just keep track of all of
592 * the live references that we've seen. Later,
593 * we'll walk through each of these lists and
594 * deal with the referents.
595 */
596 if (refFlags == CLASS_ISREFERENCE) {
597 /* It's a soft reference. Depending on the state,
598 * we'll attempt to collect all of them, some of
599 * them, or none of them.
600 */
601 if (gcHeap->softReferenceCollectionState ==
602 SR_COLLECT_NONE)
603 {
604 sr_collect_none:
605 markObjectNonNull(referent, ctx);
606 } else if (gcHeap->softReferenceCollectionState ==
607 SR_COLLECT_ALL)
608 {
609 sr_collect_all:
610 ADD_REF_TO_LIST(gcHeap->softReferences, obj);
611 } else {
612 /* We'll only try to collect half of the
613 * referents.
614 */
615 if (gcHeap->softReferenceColor++ & 1) {
616 goto sr_collect_none;
617 }
618 goto sr_collect_all;
619 }
620 } else {
621 /* It's a weak or phantom reference.
622 * Clearing CLASS_ISREFERENCE will reveal which.
623 */
624 refFlags &= ~CLASS_ISREFERENCE;
625 if (refFlags == CLASS_ISWEAKREFERENCE) {
626 ADD_REF_TO_LIST(gcHeap->weakReferences, obj);
627 } else if (refFlags == CLASS_ISPHANTOMREFERENCE) {
628 ADD_REF_TO_LIST(gcHeap->phantomReferences, obj);
629 } else {
630 assert(!"Unknown reference type");
631 }
632 }
633#undef ADD_REF_TO_LIST
634 }
635 }
636
637 skip_reference:
638 /* If this is a class object, mark various other things that
639 * its internals point to.
640 *
641 * All class objects are instances of java.lang.Class,
642 * including the java.lang.Class class object.
643 */
644 if (clazz == gDvm.classJavaLangClass) {
645 scanClassObject((ClassObject *)obj, ctx);
646 }
647 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800648}
649
650static void
651processMarkStack(GcMarkContext *ctx)
652{
653 const Object **const base = ctx->stack.base;
654
655 /* Scan anything that's on the mark stack.
656 * We can't use the bitmaps anymore, so use
657 * a finger that points past the end of them.
658 */
659 ctx->finger = (void *)ULONG_MAX;
660 while (ctx->stack.top != base) {
661 scanObject(*ctx->stack.top++, ctx);
662 }
663}
664
665#ifndef NDEBUG
666static uintptr_t gLastFinger = 0;
667#endif
668
669static bool
670scanBitmapCallback(size_t numPtrs, void **ptrs, const void *finger, void *arg)
671{
672 GcMarkContext *ctx = (GcMarkContext *)arg;
673 size_t i;
674
675#ifndef NDEBUG
676 assert((uintptr_t)finger >= gLastFinger);
677 gLastFinger = (uintptr_t)finger;
678#endif
679
680 ctx->finger = finger;
681 for (i = 0; i < numPtrs; i++) {
Carl Shapiro6343bd02010-02-16 17:40:19 -0800682 scanObject(*ptrs++, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800683 }
684
685 return true;
686}
687
688/* Given bitmaps with the root set marked, find and mark all
689 * reachable objects. When this returns, the entire set of
690 * live objects will be marked and the mark stack will be empty.
691 */
692void dvmHeapScanMarkedObjects()
693{
694 GcMarkContext *ctx = &gDvm.gcHeap->markContext;
695
696 assert(ctx->finger == NULL);
697
698 /* The bitmaps currently have bits set for the root set.
699 * Walk across the bitmaps and scan each object.
700 */
701#ifndef NDEBUG
702 gLastFinger = 0;
703#endif
Carl Shapirof373efd2010-02-19 00:46:33 -0800704 dvmHeapBitmapWalk(ctx->bitmap, scanBitmapCallback, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800705
706 /* We've walked the mark bitmaps. Scan anything that's
707 * left on the mark stack.
708 */
709 processMarkStack(ctx);
710
711 LOG_SCAN("done with marked objects\n");
712}
713
Barry Hayes6930a112009-12-22 11:01:38 -0800714/** Clear the referent field.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800715 */
Barry Hayes6930a112009-12-22 11:01:38 -0800716static void clearReference(Object *reference)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800717{
718 /* This is what the default implementation of Reference.clear()
719 * does. We're required to clear all references to a given
720 * referent atomically, so we can't pop in and out of interp
721 * code each time.
722 *
Barry Hayes6930a112009-12-22 11:01:38 -0800723 * We don't ever actaully call overriding implementations of
724 * Reference.clear().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800725 */
726 dvmSetFieldObject(reference,
727 gDvm.offJavaLangRefReference_referent, NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800728}
729
730/** @return true if we need to schedule a call to enqueue().
731 */
732static bool enqueueReference(Object *reference)
733{
Barry Hayes6930a112009-12-22 11:01:38 -0800734 Object *queue = dvmGetFieldObject(reference,
735 gDvm.offJavaLangRefReference_queue);
736 Object *queueNext = dvmGetFieldObject(reference,
737 gDvm.offJavaLangRefReference_queueNext);
738 if (queue == NULL || queueNext != NULL) {
739 /* There is no queue, or the reference has already
740 * been enqueued. The Reference.enqueue() method
741 * will do nothing even if we call it.
742 */
743 return false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800744 }
745
746 /* We need to call enqueue(), but if we called it from
747 * here we'd probably deadlock. Schedule a call.
748 */
749 return true;
750}
751
752/* All objects for stronger reference levels have been
753 * marked before this is called.
754 */
755void dvmHeapHandleReferences(Object *refListHead, enum RefType refType)
756{
757 Object *reference;
758 GcMarkContext *markContext = &gDvm.gcHeap->markContext;
759 const int offVmData = gDvm.offJavaLangRefReference_vmData;
760 const int offReferent = gDvm.offJavaLangRefReference_referent;
761 bool workRequired = false;
762
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800763 reference = refListHead;
764 while (reference != NULL) {
765 Object *next;
766 Object *referent;
767
768 /* Pull the interesting fields out of the Reference object.
769 */
770 next = dvmGetFieldObject(reference, offVmData);
771 referent = dvmGetFieldObject(reference, offReferent);
772
773 //TODO: when handling REF_PHANTOM, unlink any references
774 // that fail this initial if(). We need to re-walk
775 // the list, and it would be nice to avoid the extra
776 // work.
Carl Shapiro6343bd02010-02-16 17:40:19 -0800777 if (referent != NULL && !isMarked(referent, markContext)) {
Barry Hayes6930a112009-12-22 11:01:38 -0800778 bool schedEnqueue;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800779
780 /* This is the strongest reference that refers to referent.
781 * Do the right thing.
782 */
783 switch (refType) {
784 case REF_SOFT:
785 case REF_WEAK:
Barry Hayes6930a112009-12-22 11:01:38 -0800786 clearReference(reference);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800787 schedEnqueue = enqueueReference(reference);
788 break;
789 case REF_PHANTOM:
790 /* PhantomReferences are not cleared automatically.
791 * Until someone clears it (or the reference itself
792 * is collected), the referent must remain alive.
793 *
794 * It's necessary to fully mark the referent because
795 * it will still be present during the next GC, and
796 * all objects that it points to must be valid.
797 * (The referent will be marked outside of this loop,
798 * after handing all references of this strength, in
799 * case multiple references point to the same object.)
Andy McFaddenb18992f2009-09-25 10:42:15 -0700800 *
801 * One exception: JNI "weak global" references are handled
802 * as a special case. They're identified by the queue.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800803 */
Andy McFaddenb18992f2009-09-25 10:42:15 -0700804 if (gDvm.jniWeakGlobalRefQueue != NULL) {
805 Object* queue = dvmGetFieldObject(reference,
806 gDvm.offJavaLangRefReference_queue);
807 if (queue == gDvm.jniWeakGlobalRefQueue) {
808 LOGV("+++ WGR: clearing + not queueing %p:%p\n",
809 reference, referent);
Barry Hayes6930a112009-12-22 11:01:38 -0800810 clearReference(reference);
Andy McFaddenb18992f2009-09-25 10:42:15 -0700811 schedEnqueue = false;
812 break;
813 }
814 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800815
816 /* A PhantomReference is only useful with a
817 * queue, but since it's possible to create one
818 * without a queue, we need to check.
819 */
820 schedEnqueue = enqueueReference(reference);
821 break;
822 default:
823 assert(!"Bad reference type");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800824 schedEnqueue = false;
825 break;
826 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800827
Barry Hayes6930a112009-12-22 11:01:38 -0800828 if (schedEnqueue) {
Barry Hayes6930a112009-12-22 11:01:38 -0800829 /* Stuff the enqueue bit in the bottom of the pointer.
830 * Assumes that objects are 8-byte aligned.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800831 *
832 * Note that we are adding the *Reference* (which
833 * is by definition already marked at this point) to
834 * this list; we're not adding the referent (which
835 * has already been cleared).
836 */
837 assert(((intptr_t)reference & 3) == 0);
Barry Hayes6930a112009-12-22 11:01:38 -0800838 assert((WORKER_ENQUEUE & ~3) == 0);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800839 if (!dvmHeapAddRefToLargeTable(
840 &gDvm.gcHeap->referenceOperations,
Barry Hayes6930a112009-12-22 11:01:38 -0800841 (Object *)((uintptr_t)reference | WORKER_ENQUEUE)))
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800842 {
843 LOGE_HEAP("dvmMalloc(): no room for any more "
844 "reference operations\n");
845 dvmAbort();
846 }
847 workRequired = true;
848 }
849
850 if (refType != REF_PHANTOM) {
851 /* Let later GCs know not to reschedule this reference.
852 */
853 dvmSetFieldObject(reference, offVmData,
854 SCHEDULED_REFERENCE_MAGIC);
855 } // else this is handled later for REF_PHANTOM
856
857 } // else there was a stronger reference to the referent.
858
859 reference = next;
860 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800861
862 /* Walk though the reference list again, and mark any non-clear/marked
863 * referents. Only PhantomReferences can have non-clear referents
864 * at this point.
Andy McFaddenb18992f2009-09-25 10:42:15 -0700865 *
866 * (Could skip this for JNI weak globals, since we know they've been
867 * cleared.)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800868 */
869 if (refType == REF_PHANTOM) {
870 bool scanRequired = false;
871
872 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_REFERENCE_CLEANUP, 0);
873 reference = refListHead;
874 while (reference != NULL) {
875 Object *next;
876 Object *referent;
877
878 /* Pull the interesting fields out of the Reference object.
879 */
880 next = dvmGetFieldObject(reference, offVmData);
881 referent = dvmGetFieldObject(reference, offReferent);
882
Carl Shapiro6343bd02010-02-16 17:40:19 -0800883 if (referent != NULL && !isMarked(referent, markContext)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800884 markObjectNonNull(referent, markContext);
885 scanRequired = true;
886
887 /* Let later GCs know not to reschedule this reference.
888 */
889 dvmSetFieldObject(reference, offVmData,
890 SCHEDULED_REFERENCE_MAGIC);
891 }
892
893 reference = next;
894 }
895 HPROF_CLEAR_GC_SCAN_STATE();
896
897 if (scanRequired) {
898 processMarkStack(markContext);
899 }
900 }
901
902 if (workRequired) {
903 dvmSignalHeapWorker(false);
904 }
905}
906
907
908/* Find unreachable objects that need to be finalized,
909 * and schedule them for finalization.
910 */
911void dvmHeapScheduleFinalizations()
912{
913 HeapRefTable newPendingRefs;
914 LargeHeapRefTable *finRefs = gDvm.gcHeap->finalizableRefs;
915 Object **ref;
916 Object **lastRef;
917 size_t totalPendCount;
918 GcMarkContext *markContext = &gDvm.gcHeap->markContext;
919
920 /*
921 * All reachable objects have been marked.
922 * Any unmarked finalizable objects need to be finalized.
923 */
924
925 /* Create a table that the new pending refs will
926 * be added to.
927 */
928 if (!dvmHeapInitHeapRefTable(&newPendingRefs, 128)) {
929 //TODO: mark all finalizable refs and hope that
930 // we can schedule them next time. Watch out,
931 // because we may be expecting to free up space
932 // by calling finalizers.
933 LOGE_GC("dvmHeapScheduleFinalizations(): no room for "
934 "pending finalizations\n");
935 dvmAbort();
936 }
937
938 /* Walk through finalizableRefs and move any unmarked references
939 * to the list of new pending refs.
940 */
941 totalPendCount = 0;
942 while (finRefs != NULL) {
943 Object **gapRef;
944 size_t newPendCount = 0;
945
946 gapRef = ref = finRefs->refs.table;
947 lastRef = finRefs->refs.nextEntry;
948 while (ref < lastRef) {
Carl Shapiro6343bd02010-02-16 17:40:19 -0800949 if (!isMarked(*ref, markContext)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800950 if (!dvmHeapAddToHeapRefTable(&newPendingRefs, *ref)) {
951 //TODO: add the current table and allocate
952 // a new, smaller one.
953 LOGE_GC("dvmHeapScheduleFinalizations(): "
954 "no room for any more pending finalizations: %zd\n",
955 dvmHeapNumHeapRefTableEntries(&newPendingRefs));
956 dvmAbort();
957 }
958 newPendCount++;
959 } else {
960 /* This ref is marked, so will remain on finalizableRefs.
961 */
962 if (newPendCount > 0) {
963 /* Copy it up to fill the holes.
964 */
965 *gapRef++ = *ref;
966 } else {
967 /* No holes yet; don't bother copying.
968 */
969 gapRef++;
970 }
971 }
972 ref++;
973 }
974 finRefs->refs.nextEntry = gapRef;
975 //TODO: if the table is empty when we're done, free it.
976 totalPendCount += newPendCount;
977 finRefs = finRefs->next;
978 }
979 LOGD_GC("dvmHeapScheduleFinalizations(): %zd finalizers triggered.\n",
980 totalPendCount);
981 if (totalPendCount == 0) {
982 /* No objects required finalization.
983 * Free the empty temporary table.
984 */
985 dvmClearReferenceTable(&newPendingRefs);
986 return;
987 }
988
989 /* Add the new pending refs to the main list.
990 */
991 if (!dvmHeapAddTableToLargeTable(&gDvm.gcHeap->pendingFinalizationRefs,
992 &newPendingRefs))
993 {
994 LOGE_GC("dvmHeapScheduleFinalizations(): can't insert new "
995 "pending finalizations\n");
996 dvmAbort();
997 }
998
999 //TODO: try compacting the main list with a memcpy loop
1000
1001 /* Mark the refs we just moved; we don't want them or their
1002 * children to get swept yet.
1003 */
1004 ref = newPendingRefs.table;
1005 lastRef = newPendingRefs.nextEntry;
1006 assert(ref < lastRef);
1007 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_FINALIZING, 0);
1008 while (ref < lastRef) {
1009 markObjectNonNull(*ref, markContext);
1010 ref++;
1011 }
1012 HPROF_CLEAR_GC_SCAN_STATE();
1013
1014 /* Set markAllReferents so that we don't collect referents whose
1015 * only references are in final-reachable objects.
1016 * TODO: eventually provide normal reference behavior by properly
1017 * marking these references.
1018 */
1019 gDvm.gcHeap->markAllReferents = true;
1020 processMarkStack(markContext);
1021 gDvm.gcHeap->markAllReferents = false;
1022
1023 dvmSignalHeapWorker(false);
1024}
1025
1026void dvmHeapFinishMarkStep()
1027{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001028 GcMarkContext *markContext;
1029
1030 markContext = &gDvm.gcHeap->markContext;
1031
1032 /* The sweep step freed every object that appeared in the
1033 * HeapSource bitmaps that didn't appear in the mark bitmaps.
1034 * The new state of the HeapSource is exactly the final
1035 * mark bitmaps, so swap them in.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001036 */
Carl Shapirof373efd2010-02-19 00:46:33 -08001037 dvmHeapSourceSwapBitmaps();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001038
Carl Shapirof373efd2010-02-19 00:46:33 -08001039 /* Clean up everything else associated with the marking process.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001040 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001041 destroyMarkStack(&markContext->stack);
1042
Carl Shapirof373efd2010-02-19 00:46:33 -08001043 markContext->finger = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001044}
1045
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001046static bool
1047sweepBitmapCallback(size_t numPtrs, void **ptrs, const void *finger, void *arg)
1048{
1049 const ClassObject *const classJavaLangClass = gDvm.classJavaLangClass;
Barry Hayes5cbb2302010-02-02 14:07:37 -08001050 const bool overwriteFree = gDvm.overwriteFree;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001051 size_t i;
Barry Hayesdde8ab02009-05-20 12:10:36 -07001052 void **origPtrs = ptrs;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001053
1054 for (i = 0; i < numPtrs; i++) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001055 Object *obj;
1056
Carl Shapiro6343bd02010-02-16 17:40:19 -08001057 obj = (Object *)*ptrs++;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001058
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001059 /* NOTE: Dereferencing clazz is dangerous. If obj was the last
1060 * one to reference its class object, the class object could be
1061 * on the sweep list, and could already have been swept, leaving
1062 * us with a stale pointer.
1063 */
1064 LOGV_SWEEP("FREE: 0x%08x %s\n", (uint)obj, obj->clazz->name);
1065
1066 /* This assumes that java.lang.Class will never go away.
1067 * If it can, and we were the last reference to it, it
1068 * could have already been swept. However, even in that case,
1069 * gDvm.classJavaLangClass should still have a useful
1070 * value.
1071 */
1072 if (obj->clazz == classJavaLangClass) {
1073 LOGV_SWEEP("---------------> %s\n", ((ClassObject *)obj)->name);
1074 /* dvmFreeClassInnards() may have already been called,
1075 * but it's safe to call on the same ClassObject twice.
1076 */
1077 dvmFreeClassInnards((ClassObject *)obj);
1078 }
1079
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001080 /* Overwrite the to-be-freed object to make stale references
1081 * more obvious.
1082 */
Barry Hayes5cbb2302010-02-02 14:07:37 -08001083 if (overwriteFree) {
Barry Hayes2e3c3e12010-02-22 09:39:10 -08001084 int objlen;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001085 ClassObject *clazz = obj->clazz;
Barry Hayes2e3c3e12010-02-22 09:39:10 -08001086 objlen = dvmHeapSourceChunkSize(obj);
1087 memset(obj, 0xa5, objlen);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001088 obj->clazz = (ClassObject *)((uintptr_t)clazz ^ 0xffffffff);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001089 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001090 }
Barry Hayesdde8ab02009-05-20 12:10:36 -07001091 // TODO: dvmHeapSourceFreeList has a loop, just like the above
1092 // does. Consider collapsing the two loops to save overhead.
1093 dvmHeapSourceFreeList(numPtrs, origPtrs);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001094
1095 return true;
1096}
1097
Carl Shapiro5a6071b2010-01-07 21:35:50 -08001098/* Returns true if the given object is unmarked. Ignores the low bits
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001099 * of the pointer because the intern table may set them.
1100 */
1101static int isUnmarkedObject(void *object)
1102{
Carl Shapiro6343bd02010-02-16 17:40:19 -08001103 return !isMarked((void *)((uintptr_t)object & ~(HB_OBJECT_ALIGNMENT-1)),
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001104 &gDvm.gcHeap->markContext);
1105}
1106
1107/* Walk through the list of objects that haven't been
1108 * marked and free them.
1109 */
1110void
1111dvmHeapSweepUnmarkedObjects(int *numFreed, size_t *sizeFreed)
1112{
Carl Shapirof373efd2010-02-19 00:46:33 -08001113 HeapBitmap markBits[HEAP_SOURCE_MAX_HEAP_COUNT];
1114 HeapBitmap objBits[HEAP_SOURCE_MAX_HEAP_COUNT];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001115 size_t origObjectsAllocated;
1116 size_t origBytesAllocated;
1117 size_t numBitmaps;
1118
1119 /* All reachable objects have been marked.
1120 * Detach any unreachable interned strings before
1121 * we sweep.
1122 */
1123 dvmGcDetachDeadInternedStrings(isUnmarkedObject);
1124
1125 /* Free any known objects that are not marked.
1126 */
1127 origObjectsAllocated = dvmHeapSourceGetValue(HS_OBJECTS_ALLOCATED, NULL, 0);
1128 origBytesAllocated = dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);
1129
Carl Shapiro5a6071b2010-01-07 21:35:50 -08001130 dvmSweepMonitorList(&gDvm.monitorList, isUnmarkedObject);
1131
Carl Shapirof373efd2010-02-19 00:46:33 -08001132 numBitmaps = dvmHeapSourceGetNumHeaps();
1133 dvmHeapSourceGetObjectBitmaps(objBits, markBits, numBitmaps);
1134 dvmHeapBitmapXorWalkLists(markBits, objBits, numBitmaps,
1135 sweepBitmapCallback, NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001136
1137 *numFreed = origObjectsAllocated -
1138 dvmHeapSourceGetValue(HS_OBJECTS_ALLOCATED, NULL, 0);
1139 *sizeFreed = origBytesAllocated -
1140 dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);
1141
1142#ifdef WITH_PROFILER
1143 if (gDvm.allocProf.enabled) {
1144 gDvm.allocProf.freeCount += *numFreed;
1145 gDvm.allocProf.freeSize += *sizeFreed;
1146 }
1147#endif
1148}