blob: 1abdffa7eec8fc26ce84f07eb5215532e5db10b8 [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"
Carl Shapiroec805ea2010-06-28 16:28:26 -070023#include "alloc/Visit.h"
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080024#include <limits.h> // for ULONG_MAX
25#include <sys/mman.h> // for madvise(), mmap()
26#include <cutils/ashmem.h>
The Android Open Source Project99409882009-03-18 22:20:24 -070027#include <errno.h>
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080028
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080029#define GC_LOG_TAG LOG_TAG "-gc"
30
31#if LOG_NDEBUG
32#define LOGV_GC(...) ((void)0)
33#define LOGD_GC(...) ((void)0)
34#else
35#define LOGV_GC(...) LOG(LOG_VERBOSE, GC_LOG_TAG, __VA_ARGS__)
36#define LOGD_GC(...) LOG(LOG_DEBUG, GC_LOG_TAG, __VA_ARGS__)
37#endif
38
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080039#define LOGI_GC(...) LOG(LOG_INFO, GC_LOG_TAG, __VA_ARGS__)
40#define LOGW_GC(...) LOG(LOG_WARN, GC_LOG_TAG, __VA_ARGS__)
41#define LOGE_GC(...) LOG(LOG_ERROR, GC_LOG_TAG, __VA_ARGS__)
42
43#define LOG_SCAN(...) LOGV_GC("SCAN: " __VA_ARGS__)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080044
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080045#define ALIGN_UP_TO_PAGE_SIZE(p) \
Andy McFadden96516932009-10-28 17:39:02 -070046 (((size_t)(p) + (SYSTEM_PAGE_SIZE - 1)) & ~(SYSTEM_PAGE_SIZE - 1))
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080047
48/* Do not cast the result of this to a boolean; the only set bit
49 * may be > 1<<8.
50 */
Carl Shapiro6343bd02010-02-16 17:40:19 -080051static inline long isMarked(const void *obj, const GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080052{
Carl Shapirof373efd2010-02-19 00:46:33 -080053 return dvmHeapBitmapIsObjectBitSet(ctx->bitmap, obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080054}
55
56static bool
57createMarkStack(GcMarkStack *stack)
58{
59 const Object **limit;
60 size_t size;
The Android Open Source Project99409882009-03-18 22:20:24 -070061 int fd, err;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080062
63 /* Create a stack big enough for the worst possible case,
64 * where the heap is perfectly full of the smallest object.
65 * TODO: be better about memory usage; use a smaller stack with
66 * overflow detection and recovery.
67 */
68 size = dvmHeapSourceGetIdealFootprint() * sizeof(Object*) /
69 (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD);
70 size = ALIGN_UP_TO_PAGE_SIZE(size);
71 fd = ashmem_create_region("dalvik-heap-markstack", size);
72 if (fd < 0) {
The Android Open Source Project99409882009-03-18 22:20:24 -070073 LOGE_GC("Could not create %d-byte ashmem mark stack: %s\n",
74 size, strerror(errno));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080075 return false;
76 }
77 limit = (const Object **)mmap(NULL, size, PROT_READ | PROT_WRITE,
78 MAP_PRIVATE, fd, 0);
The Android Open Source Project99409882009-03-18 22:20:24 -070079 err = errno;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080080 close(fd);
81 if (limit == MAP_FAILED) {
The Android Open Source Project99409882009-03-18 22:20:24 -070082 LOGE_GC("Could not mmap %d-byte ashmem mark stack: %s\n",
83 size, strerror(err));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080084 return false;
85 }
86
87 memset(stack, 0, sizeof(*stack));
88 stack->limit = limit;
89 stack->base = (const Object **)((uintptr_t)limit + size);
90 stack->top = stack->base;
91
92 return true;
93}
94
95static void
96destroyMarkStack(GcMarkStack *stack)
97{
98 munmap((char *)stack->limit,
99 (uintptr_t)stack->base - (uintptr_t)stack->limit);
100 memset(stack, 0, sizeof(*stack));
101}
102
103#define MARK_STACK_PUSH(stack, obj) \
104 do { \
105 *--(stack).top = (obj); \
106 } while (false)
107
108bool
Carl Shapirod25566d2010-03-11 20:39:47 -0800109dvmHeapBeginMarkStep(GcMode mode)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800110{
111 GcMarkContext *mc = &gDvm.gcHeap->markContext;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800112
113 if (!createMarkStack(&mc->stack)) {
114 return false;
115 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800116 mc->finger = NULL;
Carl Shapirod25566d2010-03-11 20:39:47 -0800117 mc->immuneLimit = dvmHeapSourceGetImmuneLimit(mode);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800118 return true;
119}
120
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800121static long
Carl Shapiro6343bd02010-02-16 17:40:19 -0800122setAndReturnMarkBit(GcMarkContext *ctx, const void *obj)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800123{
Carl Shapirof373efd2010-02-19 00:46:33 -0800124 return dvmHeapBitmapSetAndReturnObjectBit(ctx->bitmap, obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800125}
126
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800127static void
Barry Hayese1bccb92010-05-18 09:48:37 -0700128markObjectNonNull(const Object *obj, GcMarkContext *ctx,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800129 bool checkFinger, bool forceStack)
130{
Barry Hayese1bccb92010-05-18 09:48:37 -0700131 assert(ctx != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800132 assert(obj != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800133 assert(dvmIsValidObject(obj));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800134
Carl Shapirob31b3012010-05-25 18:35:37 -0700135 if (obj < (Object *)ctx->immuneLimit) {
Carl Shapirod25566d2010-03-11 20:39:47 -0800136 assert(isMarked(obj, ctx));
137 return;
138 }
Carl Shapiro6343bd02010-02-16 17:40:19 -0800139 if (!setAndReturnMarkBit(ctx, obj)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800140 /* This object was not previously marked.
141 */
Carl Shapiro6343bd02010-02-16 17:40:19 -0800142 if (forceStack || (checkFinger && (void *)obj < ctx->finger)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800143 /* This object will need to go on the mark stack.
144 */
145 MARK_STACK_PUSH(ctx->stack, obj);
146 }
147
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800148#if WITH_HPROF
149 if (gDvm.gcHeap->hprofContext != NULL) {
150 hprofMarkRootObject(gDvm.gcHeap->hprofContext, obj, 0);
151 }
152#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800153 }
154}
155
156/* Used to mark objects when recursing. Recursion is done by moving
157 * the finger across the bitmaps in address order and marking child
158 * objects. Any newly-marked objects whose addresses are lower than
159 * the finger won't be visited by the bitmap scan, so those objects
160 * need to be added to the mark stack.
161 */
Barry Hayese1bccb92010-05-18 09:48:37 -0700162static void markObject(const Object *obj, GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800163{
Barry Hayese1bccb92010-05-18 09:48:37 -0700164 if (obj != NULL) {
165 markObjectNonNull(obj, ctx, true, false);
166 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800167}
168
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800169/* If the object hasn't already been marked, mark it and
170 * schedule it to be scanned for references.
171 *
172 * obj may not be NULL. The macro dvmMarkObject() should
173 * be used in situations where a reference may be NULL.
174 *
175 * This function may only be called when marking the root
Barry Hayese1bccb92010-05-18 09:48:37 -0700176 * set. When recursing, use the internal markObject().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800177 */
178void
179dvmMarkObjectNonNull(const Object *obj)
180{
Barry Hayese1bccb92010-05-18 09:48:37 -0700181 assert(obj != NULL);
182 markObjectNonNull(obj, &gDvm.gcHeap->markContext, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800183}
184
185/* Mark the set of root objects.
186 *
187 * Things we need to scan:
188 * - System classes defined by root classloader
189 * - For each thread:
190 * - Interpreted stack, from top to "curFrame"
191 * - Dalvik registers (args + local vars)
192 * - JNI local references
193 * - Automatic VM local references (TrackedAlloc)
194 * - Associated Thread/VMThread object
195 * - ThreadGroups (could track & start with these instead of working
196 * upward from Threads)
197 * - Exception currently being thrown, if present
198 * - JNI global references
199 * - Interned string table
200 * - Primitive classes
201 * - Special objects
202 * - gDvm.outOfMemoryObj
203 * - Objects allocated with ALLOC_NO_GC
204 * - Objects pending finalization (but not yet finalized)
205 * - Objects in debugger object registry
206 *
207 * Don't need:
208 * - Native stack (for in-progress stuff in the VM)
209 * - The TrackedAlloc stuff watches all native VM references.
210 */
211void dvmHeapMarkRootSet()
212{
Barry Hayesd4f78d32010-06-08 09:34:42 -0700213 GcHeap *gcHeap = gDvm.gcHeap;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800214
215 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_STICKY_CLASS, 0);
216
Carl Shapirod25566d2010-03-11 20:39:47 -0800217 LOG_SCAN("immune objects");
Barry Hayes425848f2010-05-04 13:32:12 -0700218 dvmMarkImmuneObjects(gcHeap->markContext.immuneLimit);
Carl Shapirod25566d2010-03-11 20:39:47 -0800219
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800220 LOG_SCAN("root class loader\n");
221 dvmGcScanRootClassLoader();
222 LOG_SCAN("primitive classes\n");
223 dvmGcScanPrimitiveClasses();
224
225 /* dvmGcScanRootThreadGroups() sets a bunch of
226 * different scan states internally.
227 */
228 HPROF_CLEAR_GC_SCAN_STATE();
229
230 LOG_SCAN("root thread groups\n");
231 dvmGcScanRootThreadGroups();
232
233 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_INTERNED_STRING, 0);
234
235 LOG_SCAN("interned strings\n");
236 dvmGcScanInternedStrings();
237
238 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JNI_GLOBAL, 0);
239
240 LOG_SCAN("JNI global refs\n");
241 dvmGcMarkJniGlobalRefs();
242
243 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_REFERENCE_CLEANUP, 0);
244
245 LOG_SCAN("pending reference operations\n");
Carl Shapiro646ba092010-06-10 15:17:00 -0700246 dvmHeapMarkLargeTableRefs(gcHeap->referenceOperations);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800247
248 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_FINALIZING, 0);
249
250 LOG_SCAN("pending finalizations\n");
Carl Shapiro646ba092010-06-10 15:17:00 -0700251 dvmHeapMarkLargeTableRefs(gcHeap->pendingFinalizationRefs);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800252
253 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_DEBUGGER, 0);
254
255 LOG_SCAN("debugger refs\n");
256 dvmGcMarkDebuggerRefs();
257
258 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_VM_INTERNAL, 0);
259
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800260 /* Mark any special objects we have sitting around.
261 */
262 LOG_SCAN("special objects\n");
263 dvmMarkObjectNonNull(gDvm.outOfMemoryObj);
264 dvmMarkObjectNonNull(gDvm.internalErrorObj);
Andy McFadden7fc3ce82009-07-14 15:57:23 -0700265 dvmMarkObjectNonNull(gDvm.noClassDefFoundErrorObj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800266//TODO: scan object references sitting in gDvm; use pointer begin & end
267
268 HPROF_CLEAR_GC_SCAN_STATE();
269}
270
271/*
Barry Hayese1bccb92010-05-18 09:48:37 -0700272 * Nothing past this point is allowed to use dvmMarkObject() or
273 * dvmMarkObjectNonNull(), which are for root-marking only.
274 * Scanning/recursion must use markObject(), which takes the finger
275 * into account.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800276 */
Barry Hayese1bccb92010-05-18 09:48:37 -0700277#undef dvmMarkObject
278#define dvmMarkObject __dont_use_dvmMarkObject__
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800279#define dvmMarkObjectNonNull __dont_use_dvmMarkObjectNonNull__
280
Barry Hayese1bccb92010-05-18 09:48:37 -0700281/*
282 * Scans instance fields.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800283 */
Barry Hayese1bccb92010-05-18 09:48:37 -0700284static void scanInstanceFields(const Object *obj, GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800285{
Barry Hayese1bccb92010-05-18 09:48:37 -0700286 assert(obj != NULL);
287 assert(obj->clazz != NULL);
288 assert(ctx != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800289
Barry Hayese1bccb92010-05-18 09:48:37 -0700290 if (obj->clazz->refOffsets != CLASS_WALK_SUPER) {
291 unsigned int refOffsets = obj->clazz->refOffsets;
Barry Hayeseac47ed2009-06-22 11:45:20 -0700292 while (refOffsets != 0) {
293 const int rshift = CLZ(refOffsets);
294 refOffsets &= ~(CLASS_HIGH_BIT >> rshift);
295 markObject(dvmGetFieldObject((Object*)obj,
Barry Hayese1bccb92010-05-18 09:48:37 -0700296 CLASS_OFFSET_FROM_CLZ(rshift)), ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800297 }
Barry Hayeseac47ed2009-06-22 11:45:20 -0700298 } else {
Barry Hayese1bccb92010-05-18 09:48:37 -0700299 ClassObject *clazz;
300 int i;
301 for (clazz = obj->clazz; clazz != NULL; clazz = clazz->super) {
302 InstField *field = clazz->ifields;
303 for (i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
304 void *addr = BYTE_OFFSET((Object *)obj, field->byteOffset);
305 markObject(((JValue *)addr)->l, ctx);
Barry Hayeseac47ed2009-06-22 11:45:20 -0700306 }
Barry Hayeseac47ed2009-06-22 11:45:20 -0700307 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800308 }
309}
310
Barry Hayese1bccb92010-05-18 09:48:37 -0700311/*
312 * Scans the header, static field references, and interface
313 * pointers of a class object.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800314 */
Barry Hayese1bccb92010-05-18 09:48:37 -0700315static void scanClassObject(const ClassObject *obj, GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800316{
Barry Hayese1bccb92010-05-18 09:48:37 -0700317 int i;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800318
Barry Hayese1bccb92010-05-18 09:48:37 -0700319 assert(obj != NULL);
320 assert(obj->obj.clazz == gDvm.classJavaLangClass);
321 assert(ctx != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800322
Barry Hayese1bccb92010-05-18 09:48:37 -0700323 markObject((Object *)obj->obj.clazz, ctx);
324 if (IS_CLASS_FLAG_SET(obj, CLASS_ISARRAY)) {
325 markObject((Object *)obj->elementClass, ctx);
326 }
Barry Hayesc49db852010-05-14 13:43:34 -0700327 /* Do super and the interfaces contain Objects and not dex idx values? */
328 if (obj->status > CLASS_IDX) {
329 markObject((Object *)obj->super, ctx);
330 }
Barry Hayese1bccb92010-05-18 09:48:37 -0700331 markObject(obj->classLoader, ctx);
332 /* Scan static field references. */
333 for (i = 0; i < obj->sfieldCount; ++i) {
334 char ch = obj->sfields[i].field.signature[0];
335 if (ch == '[' || ch == 'L') {
336 markObject(obj->sfields[i].value.l, ctx);
337 }
338 }
339 /* Scan the instance fields. */
340 scanInstanceFields((const Object *)obj, ctx);
341 /* Scan interface references. */
Barry Hayesc49db852010-05-14 13:43:34 -0700342 if (obj->status > CLASS_IDX) {
343 for (i = 0; i < obj->interfaceCount; ++i) {
344 markObject((Object *)obj->interfaces[i], ctx);
345 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800346 }
347}
348
Barry Hayese1bccb92010-05-18 09:48:37 -0700349/*
350 * Scans the header of all array objects. If the array object is
351 * specialized to a reference type, scans the array data as well.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800352 */
Barry Hayese1bccb92010-05-18 09:48:37 -0700353static void scanArrayObject(const ArrayObject *obj, GcMarkContext *ctx)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800354{
Barry Hayese1bccb92010-05-18 09:48:37 -0700355 size_t i;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800356
Barry Hayese1bccb92010-05-18 09:48:37 -0700357 assert(obj != NULL);
358 assert(obj->obj.clazz != NULL);
359 assert(ctx != NULL);
360 /* Scan the class object reference. */
361 markObject((Object *)obj->obj.clazz, ctx);
362 if (IS_CLASS_FLAG_SET(obj->obj.clazz, CLASS_ISOBJECTARRAY)) {
363 /* Scan the array contents. */
364 Object **contents = (Object **)obj->contents;
365 for (i = 0; i < obj->length; ++i) {
366 markObject(contents[i], ctx);
367 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800368 }
Barry Hayese1bccb92010-05-18 09:48:37 -0700369}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800370
Barry Hayese1bccb92010-05-18 09:48:37 -0700371/*
372 * Process the "referent" field in a java.lang.ref.Reference. If the
373 * referent has not yet been marked, put it on the appropriate list in
374 * the gcHeap for later processing.
375 */
Barry Hayes697b5a92010-06-23 11:38:52 -0700376static void delayReferenceReferent(Object *obj, GcMarkContext *ctx)
Barry Hayese1bccb92010-05-18 09:48:37 -0700377{
378 assert(obj != NULL);
Barry Hayes697b5a92010-06-23 11:38:52 -0700379 assert(obj->clazz != NULL);
Barry Hayese1bccb92010-05-18 09:48:37 -0700380 assert(ctx != NULL);
381
382 GcHeap *gcHeap = gDvm.gcHeap;
383 Object *referent;
384
385 /* It's a subclass of java/lang/ref/Reference.
386 * The fields in this class have been arranged
387 * such that scanInstanceFields() did not actually
388 * mark the "referent" field; we need to handle
389 * it specially.
390 *
391 * If the referent already has a strong mark (isMarked(referent)),
392 * we don't care about its reference status.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800393 */
Barry Hayes697b5a92010-06-23 11:38:52 -0700394 referent = dvmGetFieldObject(obj, gDvm.offJavaLangRefReference_referent);
Barry Hayese1bccb92010-05-18 09:48:37 -0700395 if (referent != NULL && !isMarked(referent, ctx))
396 {
397 u4 refFlags;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800398
Barry Hayese1bccb92010-05-18 09:48:37 -0700399 /* Find out what kind of reference is pointing
400 * to referent.
401 */
Barry Hayes697b5a92010-06-23 11:38:52 -0700402 refFlags = GET_CLASS_FLAG_GROUP(obj->clazz,
Barry Hayese1bccb92010-05-18 09:48:37 -0700403 CLASS_ISREFERENCE |
404 CLASS_ISWEAKREFERENCE |
405 CLASS_ISPHANTOMREFERENCE);
406
Barry Hayese1bccb92010-05-18 09:48:37 -0700407#define ADD_REF_TO_LIST(list, ref) \
408 do { \
Barry Hayes697b5a92010-06-23 11:38:52 -0700409 Object *ARTL_ref_ = ref; \
410 assert(dvmGetFieldObject(ARTL_ref_, \
411 gDvm.offJavaLangRefReference_queueNext) == NULL); \
Barry Hayese1bccb92010-05-18 09:48:37 -0700412 dvmSetFieldObject(ARTL_ref_, \
Barry Hayes697b5a92010-06-23 11:38:52 -0700413 gDvm.offJavaLangRefReference_queueNext, list); \
Barry Hayese1bccb92010-05-18 09:48:37 -0700414 list = ARTL_ref_; \
415 } while (false)
416
417 /* At this stage, we just keep track of all of
418 * the live references that we've seen. Later,
419 * we'll walk through each of these lists and
420 * deal with the referents.
421 */
422 if (refFlags == CLASS_ISREFERENCE) {
423 /* It's a soft reference. Depending on the state,
424 * we'll attempt to collect all of them, some of
425 * them, or none of them.
426 */
427 ADD_REF_TO_LIST(gcHeap->softReferences, obj);
428 } else {
429 /* It's a weak or phantom reference.
430 * Clearing CLASS_ISREFERENCE will reveal which.
431 */
432 refFlags &= ~CLASS_ISREFERENCE;
433 if (refFlags == CLASS_ISWEAKREFERENCE) {
434 ADD_REF_TO_LIST(gcHeap->weakReferences, obj);
435 } else if (refFlags == CLASS_ISPHANTOMREFERENCE) {
436 ADD_REF_TO_LIST(gcHeap->phantomReferences, obj);
437 } else {
438 assert(!"Unknown reference type");
439 }
440 }
441#undef ADD_REF_TO_LIST
442 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800443}
444
Barry Hayese1bccb92010-05-18 09:48:37 -0700445/*
446 * Scans the header and field references of a data object.
447 */
Barry Hayes697b5a92010-06-23 11:38:52 -0700448static void scanDataObject(DataObject *obj, GcMarkContext *ctx)
Barry Hayese1bccb92010-05-18 09:48:37 -0700449{
450 assert(obj != NULL);
451 assert(obj->obj.clazz != NULL);
452 assert(ctx != NULL);
453 /* Scan the class object. */
454 markObject((Object *)obj->obj.clazz, ctx);
455 /* Scan the instance fields. */
456 scanInstanceFields((const Object *)obj, ctx);
Barry Hayese1bccb92010-05-18 09:48:37 -0700457 if (IS_CLASS_FLAG_SET(obj->obj.clazz, CLASS_ISREFERENCE)) {
Barry Hayes697b5a92010-06-23 11:38:52 -0700458 delayReferenceReferent((Object *)obj, ctx);
Barry Hayese1bccb92010-05-18 09:48:37 -0700459 }
460}
461
462/*
463 * Scans an object reference. Determines the type of the reference
464 * and dispatches to a specialized scanning routine.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800465 */
466static void scanObject(const Object *obj, GcMarkContext *ctx)
467{
Barry Hayese1bccb92010-05-18 09:48:37 -0700468 assert(obj != NULL);
469 assert(ctx != NULL);
Barry Hayes899cdb72010-06-08 09:59:12 -0700470 assert(obj->clazz != NULL);
Carl Shapiro1a8e21a2010-06-08 13:19:57 -0700471#if WITH_HPROF
472 if (gDvm.gcHeap->hprofContext != NULL) {
473 hprofDumpHeapObject(gDvm.gcHeap->hprofContext, obj);
474 }
475#endif
Barry Hayese1bccb92010-05-18 09:48:37 -0700476 /* Dispatch a type-specific scan routine. */
Carl Shapiro1a8e21a2010-06-08 13:19:57 -0700477 if (obj->clazz == gDvm.classJavaLangClass) {
Barry Hayese1bccb92010-05-18 09:48:37 -0700478 scanClassObject((ClassObject *)obj, ctx);
Carl Shapiro1a8e21a2010-06-08 13:19:57 -0700479 } else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
Barry Hayes899cdb72010-06-08 09:59:12 -0700480 scanArrayObject((ArrayObject *)obj, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800481 } else {
Barry Hayes899cdb72010-06-08 09:59:12 -0700482 scanDataObject((DataObject *)obj, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800483 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800484}
485
486static void
487processMarkStack(GcMarkContext *ctx)
488{
489 const Object **const base = ctx->stack.base;
490
491 /* Scan anything that's on the mark stack.
492 * We can't use the bitmaps anymore, so use
493 * a finger that points past the end of them.
494 */
495 ctx->finger = (void *)ULONG_MAX;
496 while (ctx->stack.top != base) {
497 scanObject(*ctx->stack.top++, ctx);
498 }
499}
500
501#ifndef NDEBUG
502static uintptr_t gLastFinger = 0;
503#endif
504
505static bool
506scanBitmapCallback(size_t numPtrs, void **ptrs, const void *finger, void *arg)
507{
508 GcMarkContext *ctx = (GcMarkContext *)arg;
509 size_t i;
510
511#ifndef NDEBUG
512 assert((uintptr_t)finger >= gLastFinger);
513 gLastFinger = (uintptr_t)finger;
514#endif
515
516 ctx->finger = finger;
517 for (i = 0; i < numPtrs; i++) {
Carl Shapiro6343bd02010-02-16 17:40:19 -0800518 scanObject(*ptrs++, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800519 }
520
521 return true;
522}
523
524/* Given bitmaps with the root set marked, find and mark all
525 * reachable objects. When this returns, the entire set of
526 * live objects will be marked and the mark stack will be empty.
527 */
Carl Shapiro29540742010-03-26 15:34:39 -0700528void dvmHeapScanMarkedObjects(void)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800529{
530 GcMarkContext *ctx = &gDvm.gcHeap->markContext;
531
532 assert(ctx->finger == NULL);
533
534 /* The bitmaps currently have bits set for the root set.
535 * Walk across the bitmaps and scan each object.
536 */
537#ifndef NDEBUG
538 gLastFinger = 0;
539#endif
Carl Shapirof373efd2010-02-19 00:46:33 -0800540 dvmHeapBitmapWalk(ctx->bitmap, scanBitmapCallback, ctx);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800541
542 /* We've walked the mark bitmaps. Scan anything that's
543 * left on the mark stack.
544 */
545 processMarkStack(ctx);
546
547 LOG_SCAN("done with marked objects\n");
548}
549
Carl Shapiroec805ea2010-06-28 16:28:26 -0700550static void dirtyObjectVisitor(void *ptr, void *arg)
551{
552 markObject(*(Object **)ptr, (GcMarkContext *)arg);
553}
554
555/*
556 * Callback applied to each gray object to blacken it.
557 */
558static bool dirtyObjectCallback(size_t numPtrs, void **ptrs,
559 const void *finger, void *arg)
560{
561 GcMarkContext *ctx;
562 size_t i;
563
564 ctx = (GcMarkContext *)arg;
565 for (i = 0; i < numPtrs; ++i) {
566 dvmVisitObject(dirtyObjectVisitor, ptrs[i], ctx);
567 }
568 return true;
569}
570
571/*
572 * Re-mark dirtied objects. Iterates through all blackened objects
573 * looking for references to white objects.
574 */
575void dvmMarkDirtyObjects(void)
576{
577 HeapBitmap markBits[HEAP_SOURCE_MAX_HEAP_COUNT];
578 HeapBitmap liveBits[HEAP_SOURCE_MAX_HEAP_COUNT];
579 GcMarkContext *ctx;
580 size_t numBitmaps;
581 size_t i;
582
583 ctx = &gDvm.gcHeap->markContext;
584 /*
Carl Shapirof5860332010-06-28 23:02:08 -0700585 * The finger must have been set to the maximum value to ensure
586 * that gray objects will be pushed onto the mark stack.
Carl Shapiroec805ea2010-06-28 16:28:26 -0700587 */
588 assert(ctx->finger == (void *)ULONG_MAX);
589 numBitmaps = dvmHeapSourceGetNumHeaps();
590 dvmHeapSourceGetObjectBitmaps(liveBits, markBits, numBitmaps);
591 for (i = 0; i < numBitmaps; i++) {
592 dvmHeapBitmapWalk(&markBits[i], dirtyObjectCallback, ctx);
593 }
594 processMarkStack(ctx);
595}
596
Barry Hayes6930a112009-12-22 11:01:38 -0800597/** Clear the referent field.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800598 */
Barry Hayes6930a112009-12-22 11:01:38 -0800599static void clearReference(Object *reference)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800600{
601 /* This is what the default implementation of Reference.clear()
602 * does. We're required to clear all references to a given
603 * referent atomically, so we can't pop in and out of interp
604 * code each time.
605 *
Barry Hayes6930a112009-12-22 11:01:38 -0800606 * We don't ever actaully call overriding implementations of
607 * Reference.clear().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800608 */
609 dvmSetFieldObject(reference,
610 gDvm.offJavaLangRefReference_referent, NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800611}
612
Carl Shapiro29540742010-03-26 15:34:39 -0700613/*
614 * Returns true if the reference was registered with a reference queue
615 * and has not yet been enqueued.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800616 */
Carl Shapiro29540742010-03-26 15:34:39 -0700617static bool isEnqueuable(const Object *reference)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800618{
Barry Hayes6930a112009-12-22 11:01:38 -0800619 Object *queue = dvmGetFieldObject(reference,
620 gDvm.offJavaLangRefReference_queue);
621 Object *queueNext = dvmGetFieldObject(reference,
622 gDvm.offJavaLangRefReference_queueNext);
623 if (queue == NULL || queueNext != NULL) {
624 /* There is no queue, or the reference has already
625 * been enqueued. The Reference.enqueue() method
626 * will do nothing even if we call it.
627 */
628 return false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800629 }
630
631 /* We need to call enqueue(), but if we called it from
632 * here we'd probably deadlock. Schedule a call.
633 */
634 return true;
635}
636
Carl Shapiro29540742010-03-26 15:34:39 -0700637/*
638 * Schedules a reference to be appended to its reference queue.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800639 */
Carl Shapiro29540742010-03-26 15:34:39 -0700640static void enqueueReference(Object *ref)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800641{
Carl Shapiro646ba092010-06-10 15:17:00 -0700642 assert(ref != NULL);
Carl Shapiro29540742010-03-26 15:34:39 -0700643 assert(dvmGetFieldObject(ref, gDvm.offJavaLangRefReference_queue) != NULL);
644 assert(dvmGetFieldObject(ref, gDvm.offJavaLangRefReference_queueNext) == NULL);
Carl Shapiro646ba092010-06-10 15:17:00 -0700645 if (!dvmHeapAddRefToLargeTable(&gDvm.gcHeap->referenceOperations, ref)) {
Carl Shapiro29540742010-03-26 15:34:39 -0700646 LOGE_HEAP("enqueueReference(): no room for any more "
647 "reference operations\n");
648 dvmAbort();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800649 }
650}
651
Carl Shapiro29540742010-03-26 15:34:39 -0700652/*
653 * Walks the reference list marking any references subject to the
654 * reference clearing policy. References with a black referent are
655 * removed from the list. References with white referents biased
656 * toward saving are blackened and also removed from the list.
657 */
658void dvmHandleSoftRefs(Object **list)
659{
660 GcMarkContext *markContext;
661 Object *ref, *referent;
662 Object *prev, *next;
Barry Hayes697b5a92010-06-23 11:38:52 -0700663 size_t referentOffset, queueNextOffset;
Carl Shapiro29540742010-03-26 15:34:39 -0700664 unsigned counter;
665 bool marked;
666
667 markContext = &gDvm.gcHeap->markContext;
Barry Hayes697b5a92010-06-23 11:38:52 -0700668 queueNextOffset = gDvm.offJavaLangRefReference_queueNext;
Carl Shapiro29540742010-03-26 15:34:39 -0700669 referentOffset = gDvm.offJavaLangRefReference_referent;
670 counter = 0;
671 prev = next = NULL;
672 ref = *list;
673 while (ref != NULL) {
674 referent = dvmGetFieldObject(ref, referentOffset);
Barry Hayes697b5a92010-06-23 11:38:52 -0700675 next = dvmGetFieldObject(ref, queueNextOffset);
Carl Shapiro29540742010-03-26 15:34:39 -0700676 assert(referent != NULL);
677 marked = isMarked(referent, markContext);
678 if (!marked && ((++counter) & 1)) {
679 /* Referent is white and biased toward saving, mark it. */
Barry Hayese1bccb92010-05-18 09:48:37 -0700680 assert(referent != NULL);
681 markObject(referent, markContext);
Carl Shapiro29540742010-03-26 15:34:39 -0700682 marked = true;
683 }
684 if (marked) {
685 /* Referent is black, unlink it. */
686 if (prev != NULL) {
Barry Hayes697b5a92010-06-23 11:38:52 -0700687 dvmSetFieldObject(ref, queueNextOffset, NULL);
688 dvmSetFieldObject(prev, queueNextOffset, next);
Carl Shapiro29540742010-03-26 15:34:39 -0700689 }
690 } else {
691 /* Referent is white, skip over it. */
692 prev = ref;
693 }
694 ref = next;
695 }
696 /*
697 * Restart the mark with the newly black references added to the
698 * root set.
699 */
700 processMarkStack(markContext);
701}
702
703/*
704 * Walks the reference list and clears references with an unmarked
705 * (white) referents. Cleared references registered to a reference
706 * queue are scheduled for appending by the heap worker thread.
707 */
708void dvmClearWhiteRefs(Object **list)
709{
710 GcMarkContext *markContext;
711 Object *ref, *referent;
Barry Hayes697b5a92010-06-23 11:38:52 -0700712 size_t referentOffset, queueNextOffset;
Carl Shapiro29540742010-03-26 15:34:39 -0700713 bool doSignal;
714
715 markContext = &gDvm.gcHeap->markContext;
Barry Hayes697b5a92010-06-23 11:38:52 -0700716 queueNextOffset = gDvm.offJavaLangRefReference_queueNext;
Carl Shapiro29540742010-03-26 15:34:39 -0700717 referentOffset = gDvm.offJavaLangRefReference_referent;
718 doSignal = false;
719 while (*list != NULL) {
720 ref = *list;
721 referent = dvmGetFieldObject(ref, referentOffset);
Barry Hayes697b5a92010-06-23 11:38:52 -0700722 *list = dvmGetFieldObject(ref, queueNextOffset);
723 dvmSetFieldObject(ref, queueNextOffset, NULL);
Carl Shapiro29540742010-03-26 15:34:39 -0700724 assert(referent != NULL);
725 if (!isMarked(referent, markContext)) {
726 /* Referent is "white", clear it. */
727 clearReference(ref);
728 if (isEnqueuable(ref)) {
729 enqueueReference(ref);
730 doSignal = true;
731 }
732 }
733 }
734 /*
735 * If we cleared a reference with a reference queue we must notify
736 * the heap worker to append the reference.
737 */
738 if (doSignal) {
739 dvmSignalHeapWorker(false);
740 }
741 assert(*list == NULL);
742}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800743
744/* Find unreachable objects that need to be finalized,
745 * and schedule them for finalization.
746 */
747void dvmHeapScheduleFinalizations()
748{
749 HeapRefTable newPendingRefs;
750 LargeHeapRefTable *finRefs = gDvm.gcHeap->finalizableRefs;
751 Object **ref;
752 Object **lastRef;
753 size_t totalPendCount;
754 GcMarkContext *markContext = &gDvm.gcHeap->markContext;
755
756 /*
757 * All reachable objects have been marked.
758 * Any unmarked finalizable objects need to be finalized.
759 */
760
761 /* Create a table that the new pending refs will
762 * be added to.
763 */
Barry Hayesd4f78d32010-06-08 09:34:42 -0700764 if (!dvmHeapInitHeapRefTable(&newPendingRefs)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800765 //TODO: mark all finalizable refs and hope that
766 // we can schedule them next time. Watch out,
767 // because we may be expecting to free up space
768 // by calling finalizers.
769 LOGE_GC("dvmHeapScheduleFinalizations(): no room for "
770 "pending finalizations\n");
771 dvmAbort();
772 }
773
774 /* Walk through finalizableRefs and move any unmarked references
775 * to the list of new pending refs.
776 */
777 totalPendCount = 0;
778 while (finRefs != NULL) {
779 Object **gapRef;
780 size_t newPendCount = 0;
781
782 gapRef = ref = finRefs->refs.table;
783 lastRef = finRefs->refs.nextEntry;
784 while (ref < lastRef) {
Carl Shapiro6343bd02010-02-16 17:40:19 -0800785 if (!isMarked(*ref, markContext)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800786 if (!dvmHeapAddToHeapRefTable(&newPendingRefs, *ref)) {
787 //TODO: add the current table and allocate
788 // a new, smaller one.
789 LOGE_GC("dvmHeapScheduleFinalizations(): "
790 "no room for any more pending finalizations: %zd\n",
791 dvmHeapNumHeapRefTableEntries(&newPendingRefs));
792 dvmAbort();
793 }
794 newPendCount++;
795 } else {
796 /* This ref is marked, so will remain on finalizableRefs.
797 */
798 if (newPendCount > 0) {
799 /* Copy it up to fill the holes.
800 */
801 *gapRef++ = *ref;
802 } else {
803 /* No holes yet; don't bother copying.
804 */
805 gapRef++;
806 }
807 }
808 ref++;
809 }
810 finRefs->refs.nextEntry = gapRef;
811 //TODO: if the table is empty when we're done, free it.
812 totalPendCount += newPendCount;
813 finRefs = finRefs->next;
814 }
815 LOGD_GC("dvmHeapScheduleFinalizations(): %zd finalizers triggered.\n",
816 totalPendCount);
817 if (totalPendCount == 0) {
818 /* No objects required finalization.
819 * Free the empty temporary table.
820 */
821 dvmClearReferenceTable(&newPendingRefs);
822 return;
823 }
824
825 /* Add the new pending refs to the main list.
826 */
827 if (!dvmHeapAddTableToLargeTable(&gDvm.gcHeap->pendingFinalizationRefs,
828 &newPendingRefs))
829 {
830 LOGE_GC("dvmHeapScheduleFinalizations(): can't insert new "
831 "pending finalizations\n");
832 dvmAbort();
833 }
834
835 //TODO: try compacting the main list with a memcpy loop
836
837 /* Mark the refs we just moved; we don't want them or their
838 * children to get swept yet.
839 */
840 ref = newPendingRefs.table;
841 lastRef = newPendingRefs.nextEntry;
842 assert(ref < lastRef);
843 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_FINALIZING, 0);
844 while (ref < lastRef) {
Barry Hayese1bccb92010-05-18 09:48:37 -0700845 assert(*ref != NULL);
846 markObject(*ref, markContext);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800847 ref++;
848 }
849 HPROF_CLEAR_GC_SCAN_STATE();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800850 processMarkStack(markContext);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800851 dvmSignalHeapWorker(false);
852}
853
854void dvmHeapFinishMarkStep()
855{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800856 GcMarkContext *markContext;
857
858 markContext = &gDvm.gcHeap->markContext;
859
860 /* The sweep step freed every object that appeared in the
861 * HeapSource bitmaps that didn't appear in the mark bitmaps.
862 * The new state of the HeapSource is exactly the final
863 * mark bitmaps, so swap them in.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800864 */
Carl Shapirof373efd2010-02-19 00:46:33 -0800865 dvmHeapSourceSwapBitmaps();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800866
Carl Shapirof373efd2010-02-19 00:46:33 -0800867 /* Clean up everything else associated with the marking process.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800868 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800869 destroyMarkStack(&markContext->stack);
870
Carl Shapirof373efd2010-02-19 00:46:33 -0800871 markContext->finger = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800872}
873
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800874static bool
875sweepBitmapCallback(size_t numPtrs, void **ptrs, const void *finger, void *arg)
876{
877 const ClassObject *const classJavaLangClass = gDvm.classJavaLangClass;
Barry Hayes5cbb2302010-02-02 14:07:37 -0800878 const bool overwriteFree = gDvm.overwriteFree;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800879 size_t i;
Barry Hayesdde8ab02009-05-20 12:10:36 -0700880 void **origPtrs = ptrs;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800881
882 for (i = 0; i < numPtrs; i++) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800883 Object *obj;
884
Carl Shapiro6343bd02010-02-16 17:40:19 -0800885 obj = (Object *)*ptrs++;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800886
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800887 /* This assumes that java.lang.Class will never go away.
888 * If it can, and we were the last reference to it, it
889 * could have already been swept. However, even in that case,
890 * gDvm.classJavaLangClass should still have a useful
891 * value.
892 */
893 if (obj->clazz == classJavaLangClass) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800894 /* dvmFreeClassInnards() may have already been called,
895 * but it's safe to call on the same ClassObject twice.
896 */
897 dvmFreeClassInnards((ClassObject *)obj);
898 }
899
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800900 /* Overwrite the to-be-freed object to make stale references
901 * more obvious.
902 */
Barry Hayes5cbb2302010-02-02 14:07:37 -0800903 if (overwriteFree) {
Barry Hayes2e3c3e12010-02-22 09:39:10 -0800904 int objlen;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800905 ClassObject *clazz = obj->clazz;
Barry Hayes2e3c3e12010-02-22 09:39:10 -0800906 objlen = dvmHeapSourceChunkSize(obj);
907 memset(obj, 0xa5, objlen);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800908 obj->clazz = (ClassObject *)((uintptr_t)clazz ^ 0xffffffff);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800909 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800910 }
Barry Hayesdde8ab02009-05-20 12:10:36 -0700911 // TODO: dvmHeapSourceFreeList has a loop, just like the above
912 // does. Consider collapsing the two loops to save overhead.
913 dvmHeapSourceFreeList(numPtrs, origPtrs);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800914
915 return true;
916}
917
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800918/* Returns true if the given object is unmarked. Ignores the low bits
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800919 * of the pointer because the intern table may set them.
920 */
921static int isUnmarkedObject(void *object)
922{
Carl Shapiro6343bd02010-02-16 17:40:19 -0800923 return !isMarked((void *)((uintptr_t)object & ~(HB_OBJECT_ALIGNMENT-1)),
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800924 &gDvm.gcHeap->markContext);
925}
926
927/* Walk through the list of objects that haven't been
928 * marked and free them.
929 */
930void
Carl Shapirod25566d2010-03-11 20:39:47 -0800931dvmHeapSweepUnmarkedObjects(GcMode mode, int *numFreed, size_t *sizeFreed)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800932{
Carl Shapirof373efd2010-02-19 00:46:33 -0800933 HeapBitmap markBits[HEAP_SOURCE_MAX_HEAP_COUNT];
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700934 HeapBitmap liveBits[HEAP_SOURCE_MAX_HEAP_COUNT];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800935 size_t origObjectsAllocated;
936 size_t origBytesAllocated;
Carl Shapirod25566d2010-03-11 20:39:47 -0800937 size_t numBitmaps, numSweepBitmaps;
Barry Hayese168ebd2010-05-07 09:19:46 -0700938 size_t i;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800939
940 /* All reachable objects have been marked.
941 * Detach any unreachable interned strings before
942 * we sweep.
943 */
944 dvmGcDetachDeadInternedStrings(isUnmarkedObject);
945
946 /* Free any known objects that are not marked.
947 */
948 origObjectsAllocated = dvmHeapSourceGetValue(HS_OBJECTS_ALLOCATED, NULL, 0);
949 origBytesAllocated = dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);
950
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800951 dvmSweepMonitorList(&gDvm.monitorList, isUnmarkedObject);
952
Carl Shapirof373efd2010-02-19 00:46:33 -0800953 numBitmaps = dvmHeapSourceGetNumHeaps();
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700954 dvmHeapSourceGetObjectBitmaps(liveBits, markBits, numBitmaps);
Carl Shapirod25566d2010-03-11 20:39:47 -0800955 if (mode == GC_PARTIAL) {
956 numSweepBitmaps = 1;
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700957 assert((uintptr_t)gDvm.gcHeap->markContext.immuneLimit == liveBits[0].base);
Carl Shapirod25566d2010-03-11 20:39:47 -0800958 } else {
959 numSweepBitmaps = numBitmaps;
960 }
Barry Hayese168ebd2010-05-07 09:19:46 -0700961 for (i = 0; i < numSweepBitmaps; i++) {
962 dvmHeapBitmapXorWalk(&markBits[i], &liveBits[i],
963 sweepBitmapCallback, NULL);
964 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800965
966 *numFreed = origObjectsAllocated -
967 dvmHeapSourceGetValue(HS_OBJECTS_ALLOCATED, NULL, 0);
968 *sizeFreed = origBytesAllocated -
969 dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);
970
971#ifdef WITH_PROFILER
972 if (gDvm.allocProf.enabled) {
973 gDvm.allocProf.freeCount += *numFreed;
974 gDvm.allocProf.freeSize += *sizeFreed;
975 }
976#endif
977}