blob: 99ec2aa0e5045b7868d89445e0490c7a48e913ac [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
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080028#define VERBOSE_GC 0
29
30#define GC_LOG_TAG LOG_TAG "-gc"
31
32#if LOG_NDEBUG
33#define LOGV_GC(...) ((void)0)
34#define LOGD_GC(...) ((void)0)
35#else
36#define LOGV_GC(...) LOG(LOG_VERBOSE, GC_LOG_TAG, __VA_ARGS__)
37#define LOGD_GC(...) LOG(LOG_DEBUG, GC_LOG_TAG, __VA_ARGS__)
38#endif
39
40#if VERBOSE_GC
41#define LOGVV_GC(...) LOGV_GC(__VA_ARGS__)
42#else
43#define LOGVV_GC(...) ((void)0)
44#endif
45
46#define LOGI_GC(...) LOG(LOG_INFO, GC_LOG_TAG, __VA_ARGS__)
47#define LOGW_GC(...) LOG(LOG_WARN, GC_LOG_TAG, __VA_ARGS__)
48#define LOGE_GC(...) LOG(LOG_ERROR, GC_LOG_TAG, __VA_ARGS__)
49
50#define LOG_SCAN(...) LOGV_GC("SCAN: " __VA_ARGS__)
51#define LOG_MARK(...) LOGV_GC("MARK: " __VA_ARGS__)
52#define LOG_SWEEP(...) LOGV_GC("SWEEP: " __VA_ARGS__)
53#define LOG_REF(...) LOGV_GC("REF: " __VA_ARGS__)
54
55#define LOGV_SCAN(...) LOGVV_GC("SCAN: " __VA_ARGS__)
56#define LOGV_MARK(...) LOGVV_GC("MARK: " __VA_ARGS__)
57#define LOGV_SWEEP(...) LOGVV_GC("SWEEP: " __VA_ARGS__)
58#define LOGV_REF(...) LOGVV_GC("REF: " __VA_ARGS__)
59
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080060#define ALIGN_UP_TO_PAGE_SIZE(p) \
Andy McFadden96516932009-10-28 17:39:02 -070061 (((size_t)(p) + (SYSTEM_PAGE_SIZE - 1)) & ~(SYSTEM_PAGE_SIZE - 1))
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080062
63/* Do not cast the result of this to a boolean; the only set bit
64 * may be > 1<<8.
65 */
Carl Shapiro6343bd02010-02-16 17:40:19 -080066static inline long isMarked(const void *obj, const GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080067{
Carl Shapirof373efd2010-02-19 00:46:33 -080068 return dvmHeapBitmapIsObjectBitSet(ctx->bitmap, obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080069}
70
71static bool
72createMarkStack(GcMarkStack *stack)
73{
74 const Object **limit;
75 size_t size;
The Android Open Source Project99409882009-03-18 22:20:24 -070076 int fd, err;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080077
78 /* Create a stack big enough for the worst possible case,
79 * where the heap is perfectly full of the smallest object.
80 * TODO: be better about memory usage; use a smaller stack with
81 * overflow detection and recovery.
82 */
83 size = dvmHeapSourceGetIdealFootprint() * sizeof(Object*) /
84 (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD);
85 size = ALIGN_UP_TO_PAGE_SIZE(size);
86 fd = ashmem_create_region("dalvik-heap-markstack", size);
87 if (fd < 0) {
The Android Open Source Project99409882009-03-18 22:20:24 -070088 LOGE_GC("Could not create %d-byte ashmem mark stack: %s\n",
89 size, strerror(errno));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080090 return false;
91 }
92 limit = (const Object **)mmap(NULL, size, PROT_READ | PROT_WRITE,
93 MAP_PRIVATE, fd, 0);
The Android Open Source Project99409882009-03-18 22:20:24 -070094 err = errno;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080095 close(fd);
96 if (limit == MAP_FAILED) {
The Android Open Source Project99409882009-03-18 22:20:24 -070097 LOGE_GC("Could not mmap %d-byte ashmem mark stack: %s\n",
98 size, strerror(err));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080099 return false;
100 }
101
102 memset(stack, 0, sizeof(*stack));
103 stack->limit = limit;
104 stack->base = (const Object **)((uintptr_t)limit + size);
105 stack->top = stack->base;
106
107 return true;
108}
109
110static void
111destroyMarkStack(GcMarkStack *stack)
112{
113 munmap((char *)stack->limit,
114 (uintptr_t)stack->base - (uintptr_t)stack->limit);
115 memset(stack, 0, sizeof(*stack));
116}
117
118#define MARK_STACK_PUSH(stack, obj) \
119 do { \
120 *--(stack).top = (obj); \
121 } while (false)
122
123bool
Carl Shapirod25566d2010-03-11 20:39:47 -0800124dvmHeapBeginMarkStep(GcMode mode)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800125{
126 GcMarkContext *mc = &gDvm.gcHeap->markContext;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800127
128 if (!createMarkStack(&mc->stack)) {
129 return false;
130 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800131 mc->finger = NULL;
Carl Shapirod25566d2010-03-11 20:39:47 -0800132 mc->immuneLimit = dvmHeapSourceGetImmuneLimit(mode);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800133 return true;
134}
135
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800136static long
Carl Shapiro6343bd02010-02-16 17:40:19 -0800137setAndReturnMarkBit(GcMarkContext *ctx, const void *obj)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800138{
Carl Shapirof373efd2010-02-19 00:46:33 -0800139 return dvmHeapBitmapSetAndReturnObjectBit(ctx->bitmap, obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800140}
141
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800142static void
Barry Hayese1bccb92010-05-18 09:48:37 -0700143markObjectNonNull(const Object *obj, GcMarkContext *ctx,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800144 bool checkFinger, bool forceStack)
145{
Barry Hayese1bccb92010-05-18 09:48:37 -0700146 assert(ctx != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800147 assert(obj != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800148 assert(dvmIsValidObject(obj));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800149
Carl Shapirob31b3012010-05-25 18:35:37 -0700150 if (obj < (Object *)ctx->immuneLimit) {
Carl Shapirod25566d2010-03-11 20:39:47 -0800151 assert(isMarked(obj, ctx));
152 return;
153 }
Carl Shapiro6343bd02010-02-16 17:40:19 -0800154 if (!setAndReturnMarkBit(ctx, obj)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800155 /* This object was not previously marked.
156 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800157 if (forceStack || (checkFinger && (void *)obj < ctx->finger)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800158 /* This object will need to go on the mark stack.
159 */
160 MARK_STACK_PUSH(ctx->stack, obj);
161 }
162
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800163#if WITH_HPROF
164 if (gDvm.gcHeap->hprofContext != NULL) {
165 hprofMarkRootObject(gDvm.gcHeap->hprofContext, obj, 0);
166 }
167#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800168
169 /* obj->clazz can be NULL if we catch an object between
170 * dvmMalloc() and DVM_OBJECT_INIT(). This is ok.
171 */
172 LOGV_MARK("0x%08x %s\n", (uint)obj,
173 obj->clazz == NULL ? "<null class>" : obj->clazz->name);
174 }
175}
176
177/* Used to mark objects when recursing. Recursion is done by moving
178 * the finger across the bitmaps in address order and marking child
179 * objects. Any newly-marked objects whose addresses are lower than
180 * the finger won't be visited by the bitmap scan, so those objects
181 * need to be added to the mark stack.
182 */
Barry Hayese1bccb92010-05-18 09:48:37 -0700183static void markObject(const Object *obj, GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800184{
Barry Hayese1bccb92010-05-18 09:48:37 -0700185 if (obj != NULL) {
186 markObjectNonNull(obj, ctx, true, false);
187 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800188}
189
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800190/* If the object hasn't already been marked, mark it and
191 * schedule it to be scanned for references.
192 *
193 * obj may not be NULL. The macro dvmMarkObject() should
194 * be used in situations where a reference may be NULL.
195 *
196 * This function may only be called when marking the root
Barry Hayese1bccb92010-05-18 09:48:37 -0700197 * set. When recursing, use the internal markObject().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800198 */
199void
200dvmMarkObjectNonNull(const Object *obj)
201{
Barry Hayese1bccb92010-05-18 09:48:37 -0700202 assert(obj != NULL);
203 markObjectNonNull(obj, &gDvm.gcHeap->markContext, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800204}
205
206/* Mark the set of root objects.
207 *
208 * Things we need to scan:
209 * - System classes defined by root classloader
210 * - For each thread:
211 * - Interpreted stack, from top to "curFrame"
212 * - Dalvik registers (args + local vars)
213 * - JNI local references
214 * - Automatic VM local references (TrackedAlloc)
215 * - Associated Thread/VMThread object
216 * - ThreadGroups (could track & start with these instead of working
217 * upward from Threads)
218 * - Exception currently being thrown, if present
219 * - JNI global references
220 * - Interned string table
221 * - Primitive classes
222 * - Special objects
223 * - gDvm.outOfMemoryObj
224 * - Objects allocated with ALLOC_NO_GC
225 * - Objects pending finalization (but not yet finalized)
226 * - Objects in debugger object registry
227 *
228 * Don't need:
229 * - Native stack (for in-progress stuff in the VM)
230 * - The TrackedAlloc stuff watches all native VM references.
231 */
232void dvmHeapMarkRootSet()
233{
234 HeapRefTable *refs;
235 GcHeap *gcHeap;
236 Object **op;
237
238 gcHeap = gDvm.gcHeap;
239
240 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_STICKY_CLASS, 0);
241
Carl Shapirod25566d2010-03-11 20:39:47 -0800242 LOG_SCAN("immune objects");
Barry Hayes425848f2010-05-04 13:32:12 -0700243 dvmMarkImmuneObjects(gcHeap->markContext.immuneLimit);
Carl Shapirod25566d2010-03-11 20:39:47 -0800244
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800245 LOG_SCAN("root class loader\n");
246 dvmGcScanRootClassLoader();
247 LOG_SCAN("primitive classes\n");
248 dvmGcScanPrimitiveClasses();
249
250 /* dvmGcScanRootThreadGroups() sets a bunch of
251 * different scan states internally.
252 */
253 HPROF_CLEAR_GC_SCAN_STATE();
254
255 LOG_SCAN("root thread groups\n");
256 dvmGcScanRootThreadGroups();
257
258 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_INTERNED_STRING, 0);
259
260 LOG_SCAN("interned strings\n");
261 dvmGcScanInternedStrings();
262
263 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JNI_GLOBAL, 0);
264
265 LOG_SCAN("JNI global refs\n");
266 dvmGcMarkJniGlobalRefs();
267
268 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_REFERENCE_CLEANUP, 0);
269
270 LOG_SCAN("pending reference operations\n");
271 dvmHeapMarkLargeTableRefs(gcHeap->referenceOperations, true);
272
273 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_FINALIZING, 0);
274
275 LOG_SCAN("pending finalizations\n");
276 dvmHeapMarkLargeTableRefs(gcHeap->pendingFinalizationRefs, false);
277
278 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_DEBUGGER, 0);
279
280 LOG_SCAN("debugger refs\n");
281 dvmGcMarkDebuggerRefs();
282
283 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_VM_INTERNAL, 0);
284
285 /* Mark all ALLOC_NO_GC objects.
286 */
287 LOG_SCAN("ALLOC_NO_GC objects\n");
288 refs = &gcHeap->nonCollectableRefs;
289 op = refs->table;
290 while ((uintptr_t)op < (uintptr_t)refs->nextEntry) {
291 dvmMarkObjectNonNull(*(op++));
292 }
293
294 /* Mark any special objects we have sitting around.
295 */
296 LOG_SCAN("special objects\n");
297 dvmMarkObjectNonNull(gDvm.outOfMemoryObj);
298 dvmMarkObjectNonNull(gDvm.internalErrorObj);
Andy McFadden7fc3ce82009-07-14 15:57:23 -0700299 dvmMarkObjectNonNull(gDvm.noClassDefFoundErrorObj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800300//TODO: scan object references sitting in gDvm; use pointer begin & end
301
302 HPROF_CLEAR_GC_SCAN_STATE();
303}
304
305/*
Barry Hayese1bccb92010-05-18 09:48:37 -0700306 * Nothing past this point is allowed to use dvmMarkObject() or
307 * dvmMarkObjectNonNull(), which are for root-marking only.
308 * Scanning/recursion must use markObject(), which takes the finger
309 * into account.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800310 */
Barry Hayese1bccb92010-05-18 09:48:37 -0700311#undef dvmMarkObject
312#define dvmMarkObject __dont_use_dvmMarkObject__
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800313#define dvmMarkObjectNonNull __dont_use_dvmMarkObjectNonNull__
314
Barry Hayese1bccb92010-05-18 09:48:37 -0700315/*
316 * Scans instance fields.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800317 */
Barry Hayese1bccb92010-05-18 09:48:37 -0700318static void scanInstanceFields(const Object *obj, GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800319{
Barry Hayese1bccb92010-05-18 09:48:37 -0700320 assert(obj != NULL);
321 assert(obj->clazz != NULL);
322 assert(ctx != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800323
Barry Hayese1bccb92010-05-18 09:48:37 -0700324 if (obj->clazz->refOffsets != CLASS_WALK_SUPER) {
325 unsigned int refOffsets = obj->clazz->refOffsets;
Barry Hayeseac47ed2009-06-22 11:45:20 -0700326 while (refOffsets != 0) {
327 const int rshift = CLZ(refOffsets);
328 refOffsets &= ~(CLASS_HIGH_BIT >> rshift);
329 markObject(dvmGetFieldObject((Object*)obj,
Barry Hayese1bccb92010-05-18 09:48:37 -0700330 CLASS_OFFSET_FROM_CLZ(rshift)), ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800331 }
Barry Hayeseac47ed2009-06-22 11:45:20 -0700332 } else {
Barry Hayese1bccb92010-05-18 09:48:37 -0700333 ClassObject *clazz;
334 int i;
335 for (clazz = obj->clazz; clazz != NULL; clazz = clazz->super) {
336 InstField *field = clazz->ifields;
337 for (i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
338 void *addr = BYTE_OFFSET((Object *)obj, field->byteOffset);
339 markObject(((JValue *)addr)->l, ctx);
Barry Hayeseac47ed2009-06-22 11:45:20 -0700340 }
Barry Hayeseac47ed2009-06-22 11:45:20 -0700341 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800342 }
343}
344
Barry Hayese1bccb92010-05-18 09:48:37 -0700345/*
346 * Scans the header, static field references, and interface
347 * pointers of a class object.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800348 */
Barry Hayese1bccb92010-05-18 09:48:37 -0700349static void scanClassObject(const ClassObject *obj, GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800350{
Barry Hayese1bccb92010-05-18 09:48:37 -0700351 int i;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800352
Barry Hayese1bccb92010-05-18 09:48:37 -0700353 assert(obj != NULL);
354 assert(obj->obj.clazz == gDvm.classJavaLangClass);
355 assert(ctx != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800356
Barry Hayese1bccb92010-05-18 09:48:37 -0700357 markObject((Object *)obj->obj.clazz, ctx);
358 if (IS_CLASS_FLAG_SET(obj, CLASS_ISARRAY)) {
359 markObject((Object *)obj->elementClass, ctx);
360 }
Barry Hayesc49db852010-05-14 13:43:34 -0700361 /* Do super and the interfaces contain Objects and not dex idx values? */
362 if (obj->status > CLASS_IDX) {
363 markObject((Object *)obj->super, ctx);
364 }
Barry Hayese1bccb92010-05-18 09:48:37 -0700365 markObject(obj->classLoader, ctx);
366 /* Scan static field references. */
367 for (i = 0; i < obj->sfieldCount; ++i) {
368 char ch = obj->sfields[i].field.signature[0];
369 if (ch == '[' || ch == 'L') {
370 markObject(obj->sfields[i].value.l, ctx);
371 }
372 }
373 /* Scan the instance fields. */
374 scanInstanceFields((const Object *)obj, ctx);
375 /* Scan interface references. */
Barry Hayesc49db852010-05-14 13:43:34 -0700376 if (obj->status > CLASS_IDX) {
377 for (i = 0; i < obj->interfaceCount; ++i) {
378 markObject((Object *)obj->interfaces[i], ctx);
379 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800380 }
381}
382
Barry Hayese1bccb92010-05-18 09:48:37 -0700383/*
384 * Scans the header of all array objects. If the array object is
385 * specialized to a reference type, scans the array data as well.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800386 */
Barry Hayese1bccb92010-05-18 09:48:37 -0700387static void scanArrayObject(const ArrayObject *obj, GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800388{
Barry Hayese1bccb92010-05-18 09:48:37 -0700389 size_t i;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800390
Barry Hayese1bccb92010-05-18 09:48:37 -0700391 assert(obj != NULL);
392 assert(obj->obj.clazz != NULL);
393 assert(ctx != NULL);
394 /* Scan the class object reference. */
395 markObject((Object *)obj->obj.clazz, ctx);
396 if (IS_CLASS_FLAG_SET(obj->obj.clazz, CLASS_ISOBJECTARRAY)) {
397 /* Scan the array contents. */
398 Object **contents = (Object **)obj->contents;
399 for (i = 0; i < obj->length; ++i) {
400 markObject(contents[i], ctx);
401 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800402 }
Barry Hayese1bccb92010-05-18 09:48:37 -0700403}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800404
Barry Hayese1bccb92010-05-18 09:48:37 -0700405/*
406 * Process the "referent" field in a java.lang.ref.Reference. If the
407 * referent has not yet been marked, put it on the appropriate list in
408 * the gcHeap for later processing.
409 */
410static void delayReferenceReferent(const DataObject *obj,
411 GcMarkContext *ctx)
412{
413 assert(obj != NULL);
414 assert(obj->obj.clazz != NULL);
415 assert(ctx != NULL);
416
417 GcHeap *gcHeap = gDvm.gcHeap;
418 Object *referent;
419
420 /* It's a subclass of java/lang/ref/Reference.
421 * The fields in this class have been arranged
422 * such that scanInstanceFields() did not actually
423 * mark the "referent" field; we need to handle
424 * it specially.
425 *
426 * If the referent already has a strong mark (isMarked(referent)),
427 * we don't care about its reference status.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800428 */
Barry Hayese1bccb92010-05-18 09:48:37 -0700429 referent = dvmGetFieldObject((Object *)obj,
430 gDvm.offJavaLangRefReference_referent);
431 if (referent != NULL && !isMarked(referent, ctx))
432 {
433 u4 refFlags;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800434
Barry Hayese1bccb92010-05-18 09:48:37 -0700435 /* Find out what kind of reference is pointing
436 * to referent.
437 */
438 refFlags = GET_CLASS_FLAG_GROUP(obj->obj.clazz,
439 CLASS_ISREFERENCE |
440 CLASS_ISWEAKREFERENCE |
441 CLASS_ISPHANTOMREFERENCE);
442
443 /* We use the vmData field of Reference objects
444 * as a next pointer in a singly-linked list.
445 * That way, we don't need to allocate any memory
446 * while we're doing a GC.
447 */
448#define ADD_REF_TO_LIST(list, ref) \
449 do { \
450 Object *ARTL_ref_ = (/*de-const*/Object *)(ref); \
451 dvmSetFieldObject(ARTL_ref_, \
452 gDvm.offJavaLangRefReference_vmData, list); \
453 list = ARTL_ref_; \
454 } while (false)
455
456 /* At this stage, we just keep track of all of
457 * the live references that we've seen. Later,
458 * we'll walk through each of these lists and
459 * deal with the referents.
460 */
461 if (refFlags == CLASS_ISREFERENCE) {
462 /* It's a soft reference. Depending on the state,
463 * we'll attempt to collect all of them, some of
464 * them, or none of them.
465 */
466 ADD_REF_TO_LIST(gcHeap->softReferences, obj);
467 } else {
468 /* It's a weak or phantom reference.
469 * Clearing CLASS_ISREFERENCE will reveal which.
470 */
471 refFlags &= ~CLASS_ISREFERENCE;
472 if (refFlags == CLASS_ISWEAKREFERENCE) {
473 ADD_REF_TO_LIST(gcHeap->weakReferences, obj);
474 } else if (refFlags == CLASS_ISPHANTOMREFERENCE) {
475 ADD_REF_TO_LIST(gcHeap->phantomReferences, obj);
476 } else {
477 assert(!"Unknown reference type");
478 }
479 }
480#undef ADD_REF_TO_LIST
481 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800482}
483
Barry Hayese1bccb92010-05-18 09:48:37 -0700484/*
485 * Scans the header and field references of a data object.
486 */
487static void scanDataObject(const DataObject *obj, GcMarkContext *ctx)
488{
489 assert(obj != NULL);
490 assert(obj->obj.clazz != NULL);
491 assert(ctx != NULL);
492 /* Scan the class object. */
493 markObject((Object *)obj->obj.clazz, ctx);
494 /* Scan the instance fields. */
495 scanInstanceFields((const Object *)obj, ctx);
496
497 if (IS_CLASS_FLAG_SET(obj->obj.clazz, CLASS_ISREFERENCE)) {
498 delayReferenceReferent(obj, ctx);
499 }
500}
501
502/*
503 * Scans an object reference. Determines the type of the reference
504 * and dispatches to a specialized scanning routine.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800505 */
506static void scanObject(const Object *obj, GcMarkContext *ctx)
507{
Barry Hayese1bccb92010-05-18 09:48:37 -0700508 assert(obj != NULL);
509 assert(ctx != NULL);
Barry Hayes899cdb72010-06-08 09:59:12 -0700510 assert(obj->clazz != NULL);
Carl Shapiro1a8e21a2010-06-08 13:19:57 -0700511#if WITH_HPROF
512 if (gDvm.gcHeap->hprofContext != NULL) {
513 hprofDumpHeapObject(gDvm.gcHeap->hprofContext, obj);
514 }
515#endif
Barry Hayese1bccb92010-05-18 09:48:37 -0700516 /* Dispatch a type-specific scan routine. */
Carl Shapiro1a8e21a2010-06-08 13:19:57 -0700517 if (obj->clazz == gDvm.classJavaLangClass) {
Barry Hayese1bccb92010-05-18 09:48:37 -0700518 scanClassObject((ClassObject *)obj, ctx);
Carl Shapiro1a8e21a2010-06-08 13:19:57 -0700519 } else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
Barry Hayes899cdb72010-06-08 09:59:12 -0700520 scanArrayObject((ArrayObject *)obj, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800521 } else {
Barry Hayes899cdb72010-06-08 09:59:12 -0700522 scanDataObject((DataObject *)obj, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800523 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800524}
525
526static void
527processMarkStack(GcMarkContext *ctx)
528{
529 const Object **const base = ctx->stack.base;
530
531 /* Scan anything that's on the mark stack.
532 * We can't use the bitmaps anymore, so use
533 * a finger that points past the end of them.
534 */
535 ctx->finger = (void *)ULONG_MAX;
536 while (ctx->stack.top != base) {
537 scanObject(*ctx->stack.top++, ctx);
538 }
539}
540
541#ifndef NDEBUG
542static uintptr_t gLastFinger = 0;
543#endif
544
545static bool
546scanBitmapCallback(size_t numPtrs, void **ptrs, const void *finger, void *arg)
547{
548 GcMarkContext *ctx = (GcMarkContext *)arg;
549 size_t i;
550
551#ifndef NDEBUG
552 assert((uintptr_t)finger >= gLastFinger);
553 gLastFinger = (uintptr_t)finger;
554#endif
555
556 ctx->finger = finger;
557 for (i = 0; i < numPtrs; i++) {
Carl Shapiro6343bd02010-02-16 17:40:19 -0800558 scanObject(*ptrs++, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800559 }
560
561 return true;
562}
563
564/* Given bitmaps with the root set marked, find and mark all
565 * reachable objects. When this returns, the entire set of
566 * live objects will be marked and the mark stack will be empty.
567 */
Carl Shapiro29540742010-03-26 15:34:39 -0700568void dvmHeapScanMarkedObjects(void)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800569{
570 GcMarkContext *ctx = &gDvm.gcHeap->markContext;
571
572 assert(ctx->finger == NULL);
573
574 /* The bitmaps currently have bits set for the root set.
575 * Walk across the bitmaps and scan each object.
576 */
577#ifndef NDEBUG
578 gLastFinger = 0;
579#endif
Carl Shapirof373efd2010-02-19 00:46:33 -0800580 dvmHeapBitmapWalk(ctx->bitmap, scanBitmapCallback, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800581
582 /* We've walked the mark bitmaps. Scan anything that's
583 * left on the mark stack.
584 */
585 processMarkStack(ctx);
586
587 LOG_SCAN("done with marked objects\n");
588}
589
Barry Hayes6930a112009-12-22 11:01:38 -0800590/** Clear the referent field.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800591 */
Barry Hayes6930a112009-12-22 11:01:38 -0800592static void clearReference(Object *reference)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800593{
594 /* This is what the default implementation of Reference.clear()
595 * does. We're required to clear all references to a given
596 * referent atomically, so we can't pop in and out of interp
597 * code each time.
598 *
Barry Hayes6930a112009-12-22 11:01:38 -0800599 * We don't ever actaully call overriding implementations of
600 * Reference.clear().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800601 */
602 dvmSetFieldObject(reference,
603 gDvm.offJavaLangRefReference_referent, NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800604}
605
Carl Shapiro29540742010-03-26 15:34:39 -0700606/*
607 * Returns true if the reference was registered with a reference queue
608 * and has not yet been enqueued.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800609 */
Carl Shapiro29540742010-03-26 15:34:39 -0700610static bool isEnqueuable(const Object *reference)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800611{
Barry Hayes6930a112009-12-22 11:01:38 -0800612 Object *queue = dvmGetFieldObject(reference,
613 gDvm.offJavaLangRefReference_queue);
614 Object *queueNext = dvmGetFieldObject(reference,
615 gDvm.offJavaLangRefReference_queueNext);
616 if (queue == NULL || queueNext != NULL) {
617 /* There is no queue, or the reference has already
618 * been enqueued. The Reference.enqueue() method
619 * will do nothing even if we call it.
620 */
621 return false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800622 }
623
624 /* We need to call enqueue(), but if we called it from
625 * here we'd probably deadlock. Schedule a call.
626 */
627 return true;
628}
629
Carl Shapiro29540742010-03-26 15:34:39 -0700630/*
631 * Schedules a reference to be appended to its reference queue.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800632 */
Carl Shapiro29540742010-03-26 15:34:39 -0700633static void enqueueReference(Object *ref)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800634{
Carl Shapiro29540742010-03-26 15:34:39 -0700635 LargeHeapRefTable **table;
636 Object *op;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800637
Carl Shapiro29540742010-03-26 15:34:39 -0700638 assert(((uintptr_t)ref & 3) == 0);
639 assert((WORKER_ENQUEUE & ~3) == 0);
640 assert(dvmGetFieldObject(ref, gDvm.offJavaLangRefReference_queue) != NULL);
641 assert(dvmGetFieldObject(ref, gDvm.offJavaLangRefReference_queueNext) == NULL);
642 /* Stuff the enqueue bit in the bottom of the pointer.
643 * Assumes that objects are 8-byte aligned.
Andy McFaddenb18992f2009-09-25 10:42:15 -0700644 *
Carl Shapiro29540742010-03-26 15:34:39 -0700645 * Note that we are adding the *Reference* (which
646 * is by definition already marked at this point) to
647 * this list; we're not adding the referent (which
648 * has already been cleared).
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800649 */
Carl Shapiro29540742010-03-26 15:34:39 -0700650 table = &gDvm.gcHeap->referenceOperations;
651 op = (Object *)((uintptr_t)ref | WORKER_ENQUEUE);
652 if (!dvmHeapAddRefToLargeTable(table, op)) {
653 LOGE_HEAP("enqueueReference(): no room for any more "
654 "reference operations\n");
655 dvmAbort();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800656 }
657}
658
Carl Shapiro29540742010-03-26 15:34:39 -0700659/*
660 * Walks the reference list marking any references subject to the
661 * reference clearing policy. References with a black referent are
662 * removed from the list. References with white referents biased
663 * toward saving are blackened and also removed from the list.
664 */
665void dvmHandleSoftRefs(Object **list)
666{
667 GcMarkContext *markContext;
668 Object *ref, *referent;
669 Object *prev, *next;
670 size_t referentOffset, vmDataOffset;
671 unsigned counter;
672 bool marked;
673
674 markContext = &gDvm.gcHeap->markContext;
675 vmDataOffset = gDvm.offJavaLangRefReference_vmData;
676 referentOffset = gDvm.offJavaLangRefReference_referent;
677 counter = 0;
678 prev = next = NULL;
679 ref = *list;
680 while (ref != NULL) {
681 referent = dvmGetFieldObject(ref, referentOffset);
682 next = dvmGetFieldObject(ref, vmDataOffset);
683 assert(referent != NULL);
684 marked = isMarked(referent, markContext);
685 if (!marked && ((++counter) & 1)) {
686 /* Referent is white and biased toward saving, mark it. */
Barry Hayese1bccb92010-05-18 09:48:37 -0700687 assert(referent != NULL);
688 markObject(referent, markContext);
Carl Shapiro29540742010-03-26 15:34:39 -0700689 marked = true;
690 }
691 if (marked) {
692 /* Referent is black, unlink it. */
693 if (prev != NULL) {
694 dvmSetFieldObject(ref, vmDataOffset, NULL);
695 dvmSetFieldObject(prev, vmDataOffset, next);
696 }
697 } else {
698 /* Referent is white, skip over it. */
699 prev = ref;
700 }
701 ref = next;
702 }
703 /*
704 * Restart the mark with the newly black references added to the
705 * root set.
706 */
707 processMarkStack(markContext);
708}
709
710/*
711 * Walks the reference list and clears references with an unmarked
712 * (white) referents. Cleared references registered to a reference
713 * queue are scheduled for appending by the heap worker thread.
714 */
715void dvmClearWhiteRefs(Object **list)
716{
717 GcMarkContext *markContext;
718 Object *ref, *referent;
719 size_t referentOffset, vmDataOffset;
720 bool doSignal;
721
722 markContext = &gDvm.gcHeap->markContext;
723 vmDataOffset = gDvm.offJavaLangRefReference_vmData;
724 referentOffset = gDvm.offJavaLangRefReference_referent;
725 doSignal = false;
726 while (*list != NULL) {
727 ref = *list;
728 referent = dvmGetFieldObject(ref, referentOffset);
729 *list = dvmGetFieldObject(ref, vmDataOffset);
730 assert(referent != NULL);
731 if (!isMarked(referent, markContext)) {
732 /* Referent is "white", clear it. */
733 clearReference(ref);
734 if (isEnqueuable(ref)) {
735 enqueueReference(ref);
736 doSignal = true;
737 }
738 }
739 }
740 /*
741 * If we cleared a reference with a reference queue we must notify
742 * the heap worker to append the reference.
743 */
744 if (doSignal) {
745 dvmSignalHeapWorker(false);
746 }
747 assert(*list == NULL);
748}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800749
750/* Find unreachable objects that need to be finalized,
751 * and schedule them for finalization.
752 */
753void dvmHeapScheduleFinalizations()
754{
755 HeapRefTable newPendingRefs;
756 LargeHeapRefTable *finRefs = gDvm.gcHeap->finalizableRefs;
757 Object **ref;
758 Object **lastRef;
759 size_t totalPendCount;
760 GcMarkContext *markContext = &gDvm.gcHeap->markContext;
761
762 /*
763 * All reachable objects have been marked.
764 * Any unmarked finalizable objects need to be finalized.
765 */
766
767 /* Create a table that the new pending refs will
768 * be added to.
769 */
770 if (!dvmHeapInitHeapRefTable(&newPendingRefs, 128)) {
771 //TODO: mark all finalizable refs and hope that
772 // we can schedule them next time. Watch out,
773 // because we may be expecting to free up space
774 // by calling finalizers.
775 LOGE_GC("dvmHeapScheduleFinalizations(): no room for "
776 "pending finalizations\n");
777 dvmAbort();
778 }
779
780 /* Walk through finalizableRefs and move any unmarked references
781 * to the list of new pending refs.
782 */
783 totalPendCount = 0;
784 while (finRefs != NULL) {
785 Object **gapRef;
786 size_t newPendCount = 0;
787
788 gapRef = ref = finRefs->refs.table;
789 lastRef = finRefs->refs.nextEntry;
790 while (ref < lastRef) {
Carl Shapiro6343bd02010-02-16 17:40:19 -0800791 if (!isMarked(*ref, markContext)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800792 if (!dvmHeapAddToHeapRefTable(&newPendingRefs, *ref)) {
793 //TODO: add the current table and allocate
794 // a new, smaller one.
795 LOGE_GC("dvmHeapScheduleFinalizations(): "
796 "no room for any more pending finalizations: %zd\n",
797 dvmHeapNumHeapRefTableEntries(&newPendingRefs));
798 dvmAbort();
799 }
800 newPendCount++;
801 } else {
802 /* This ref is marked, so will remain on finalizableRefs.
803 */
804 if (newPendCount > 0) {
805 /* Copy it up to fill the holes.
806 */
807 *gapRef++ = *ref;
808 } else {
809 /* No holes yet; don't bother copying.
810 */
811 gapRef++;
812 }
813 }
814 ref++;
815 }
816 finRefs->refs.nextEntry = gapRef;
817 //TODO: if the table is empty when we're done, free it.
818 totalPendCount += newPendCount;
819 finRefs = finRefs->next;
820 }
821 LOGD_GC("dvmHeapScheduleFinalizations(): %zd finalizers triggered.\n",
822 totalPendCount);
823 if (totalPendCount == 0) {
824 /* No objects required finalization.
825 * Free the empty temporary table.
826 */
827 dvmClearReferenceTable(&newPendingRefs);
828 return;
829 }
830
831 /* Add the new pending refs to the main list.
832 */
833 if (!dvmHeapAddTableToLargeTable(&gDvm.gcHeap->pendingFinalizationRefs,
834 &newPendingRefs))
835 {
836 LOGE_GC("dvmHeapScheduleFinalizations(): can't insert new "
837 "pending finalizations\n");
838 dvmAbort();
839 }
840
841 //TODO: try compacting the main list with a memcpy loop
842
843 /* Mark the refs we just moved; we don't want them or their
844 * children to get swept yet.
845 */
846 ref = newPendingRefs.table;
847 lastRef = newPendingRefs.nextEntry;
848 assert(ref < lastRef);
849 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_FINALIZING, 0);
850 while (ref < lastRef) {
Barry Hayese1bccb92010-05-18 09:48:37 -0700851 assert(*ref != NULL);
852 markObject(*ref, markContext);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800853 ref++;
854 }
855 HPROF_CLEAR_GC_SCAN_STATE();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800856 processMarkStack(markContext);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800857 dvmSignalHeapWorker(false);
858}
859
860void dvmHeapFinishMarkStep()
861{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800862 GcMarkContext *markContext;
863
864 markContext = &gDvm.gcHeap->markContext;
865
866 /* The sweep step freed every object that appeared in the
867 * HeapSource bitmaps that didn't appear in the mark bitmaps.
868 * The new state of the HeapSource is exactly the final
869 * mark bitmaps, so swap them in.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800870 */
Carl Shapirof373efd2010-02-19 00:46:33 -0800871 dvmHeapSourceSwapBitmaps();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800872
Carl Shapirof373efd2010-02-19 00:46:33 -0800873 /* Clean up everything else associated with the marking process.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800874 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800875 destroyMarkStack(&markContext->stack);
876
Carl Shapirof373efd2010-02-19 00:46:33 -0800877 markContext->finger = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800878}
879
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800880static bool
881sweepBitmapCallback(size_t numPtrs, void **ptrs, const void *finger, void *arg)
882{
883 const ClassObject *const classJavaLangClass = gDvm.classJavaLangClass;
Barry Hayes5cbb2302010-02-02 14:07:37 -0800884 const bool overwriteFree = gDvm.overwriteFree;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800885 size_t i;
Barry Hayesdde8ab02009-05-20 12:10:36 -0700886 void **origPtrs = ptrs;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800887
888 for (i = 0; i < numPtrs; i++) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800889 Object *obj;
890
Carl Shapiro6343bd02010-02-16 17:40:19 -0800891 obj = (Object *)*ptrs++;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800892
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800893 /* NOTE: Dereferencing clazz is dangerous. If obj was the last
894 * one to reference its class object, the class object could be
895 * on the sweep list, and could already have been swept, leaving
896 * us with a stale pointer.
897 */
898 LOGV_SWEEP("FREE: 0x%08x %s\n", (uint)obj, obj->clazz->name);
899
900 /* This assumes that java.lang.Class will never go away.
901 * If it can, and we were the last reference to it, it
902 * could have already been swept. However, even in that case,
903 * gDvm.classJavaLangClass should still have a useful
904 * value.
905 */
906 if (obj->clazz == classJavaLangClass) {
907 LOGV_SWEEP("---------------> %s\n", ((ClassObject *)obj)->name);
908 /* dvmFreeClassInnards() may have already been called,
909 * but it's safe to call on the same ClassObject twice.
910 */
911 dvmFreeClassInnards((ClassObject *)obj);
912 }
913
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800914 /* Overwrite the to-be-freed object to make stale references
915 * more obvious.
916 */
Barry Hayes5cbb2302010-02-02 14:07:37 -0800917 if (overwriteFree) {
Barry Hayes2e3c3e12010-02-22 09:39:10 -0800918 int objlen;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800919 ClassObject *clazz = obj->clazz;
Barry Hayes2e3c3e12010-02-22 09:39:10 -0800920 objlen = dvmHeapSourceChunkSize(obj);
921 memset(obj, 0xa5, objlen);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800922 obj->clazz = (ClassObject *)((uintptr_t)clazz ^ 0xffffffff);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800923 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800924 }
Barry Hayesdde8ab02009-05-20 12:10:36 -0700925 // TODO: dvmHeapSourceFreeList has a loop, just like the above
926 // does. Consider collapsing the two loops to save overhead.
927 dvmHeapSourceFreeList(numPtrs, origPtrs);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800928
929 return true;
930}
931
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800932/* Returns true if the given object is unmarked. Ignores the low bits
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800933 * of the pointer because the intern table may set them.
934 */
935static int isUnmarkedObject(void *object)
936{
Carl Shapiro6343bd02010-02-16 17:40:19 -0800937 return !isMarked((void *)((uintptr_t)object & ~(HB_OBJECT_ALIGNMENT-1)),
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800938 &gDvm.gcHeap->markContext);
939}
940
941/* Walk through the list of objects that haven't been
942 * marked and free them.
943 */
944void
Carl Shapirod25566d2010-03-11 20:39:47 -0800945dvmHeapSweepUnmarkedObjects(GcMode mode, int *numFreed, size_t *sizeFreed)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800946{
Carl Shapirof373efd2010-02-19 00:46:33 -0800947 HeapBitmap markBits[HEAP_SOURCE_MAX_HEAP_COUNT];
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700948 HeapBitmap liveBits[HEAP_SOURCE_MAX_HEAP_COUNT];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800949 size_t origObjectsAllocated;
950 size_t origBytesAllocated;
Carl Shapirod25566d2010-03-11 20:39:47 -0800951 size_t numBitmaps, numSweepBitmaps;
Barry Hayese168ebd2010-05-07 09:19:46 -0700952 size_t i;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800953
954 /* All reachable objects have been marked.
955 * Detach any unreachable interned strings before
956 * we sweep.
957 */
958 dvmGcDetachDeadInternedStrings(isUnmarkedObject);
959
960 /* Free any known objects that are not marked.
961 */
962 origObjectsAllocated = dvmHeapSourceGetValue(HS_OBJECTS_ALLOCATED, NULL, 0);
963 origBytesAllocated = dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);
964
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800965 dvmSweepMonitorList(&gDvm.monitorList, isUnmarkedObject);
966
Carl Shapirof373efd2010-02-19 00:46:33 -0800967 numBitmaps = dvmHeapSourceGetNumHeaps();
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700968 dvmHeapSourceGetObjectBitmaps(liveBits, markBits, numBitmaps);
Carl Shapirod25566d2010-03-11 20:39:47 -0800969 if (mode == GC_PARTIAL) {
970 numSweepBitmaps = 1;
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700971 assert((uintptr_t)gDvm.gcHeap->markContext.immuneLimit == liveBits[0].base);
Carl Shapirod25566d2010-03-11 20:39:47 -0800972 } else {
973 numSweepBitmaps = numBitmaps;
974 }
Barry Hayese168ebd2010-05-07 09:19:46 -0700975 for (i = 0; i < numSweepBitmaps; i++) {
976 dvmHeapBitmapXorWalk(&markBits[i], &liveBits[i],
977 sweepBitmapCallback, NULL);
978 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800979
980 *numFreed = origObjectsAllocated -
981 dvmHeapSourceGetValue(HS_OBJECTS_ALLOCATED, NULL, 0);
982 *sizeFreed = origBytesAllocated -
983 dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);
984
985#ifdef WITH_PROFILER
986 if (gDvm.allocProf.enabled) {
987 gDvm.allocProf.freeCount += *numFreed;
988 gDvm.allocProf.freeSize += *sizeFreed;
989 }
990#endif
991}