static void _markObjectNonNullCommon(const Object *obj, GcMarkContext *ctx, bool checkFinger, bool forceStack) { DvmHeapChunk *hc; assert(obj != NULL); #if GC_DEBUG(GC_DEBUG_PARANOID) //TODO: make sure we're locked assert(obj != (Object *)gDvm.unlinkedJavaLangClass); assert(dvmIsValidObject(obj)); #endif hc = ptr2chunk(obj); if (!setAndReturnMarkBit(ctx, hc)) { /* This object was not previously marked. */ if (forceStack || (checkFinger && (void *)hc < ctx->finger)) { /* This object will need to go on the mark stack. */ MARK_STACK_PUSH(ctx->stack, obj); } #if WITH_OBJECT_HEADERS if (hc->scanGeneration != hc->markGeneration) { LOGE("markObject(0x%08x): wasn't scanned last time\n", (uint)obj); dvmAbort(); } if (hc->markGeneration == gGeneration) { LOGE("markObject(0x%08x): already marked this generation\n", (uint)obj); dvmAbort(); } hc->oldMarkGeneration = hc->markGeneration; hc->markGeneration = gGeneration; hc->markFingerOld = hc->markFinger; hc->markFinger = ctx->finger; if (gMarkParent != NULL) { hc->parentOld = hc->parent; hc->parent = gMarkParent; } else { hc->parent = (const Object *)((uintptr_t)hc->parent | 1); } hc->markCount++; #endif #if WITH_HPROF if (gDvm.gcHeap->hprofContext != NULL) { hprofMarkRootObject(gDvm.gcHeap->hprofContext, obj, 0); } #endif #if DVM_TRACK_HEAP_MARKING gDvm.gcHeap->markCount++; gDvm.gcHeap->markSize += dvmHeapSourceChunkSize((void *)hc) + HEAP_SOURCE_CHUNK_OVERHEAD; #endif /* obj->clazz can be NULL if we catch an object between * dvmMalloc() and DVM_OBJECT_INIT(). This is ok. */ LOGV_MARK("0x%08x %s\n", (uint)obj, obj->clazz == NULL ? "<null class>" : obj->clazz->name); } }
size_t dvmObjectSizeInHeap(const Object *obj) { return dvmHeapSourceChunkSize(obj); }
static bool sweepBitmapCallback(size_t numPtrs, void **ptrs, const void *finger, void *arg) { const ClassObject *const classJavaLangClass = gDvm.classJavaLangClass; size_t i; for (i = 0; i < numPtrs; i++) { DvmHeapChunk *hc; Object *obj; /* The pointers we're getting back are DvmHeapChunks, not * Objects. */ hc = (DvmHeapChunk *)*ptrs++; obj = (Object *)chunk2ptr(hc); #if WITH_OBJECT_HEADERS if (hc->markGeneration == gGeneration) { LOGE("sweeping marked object: 0x%08x\n", (uint)obj); dvmAbort(); } #endif /* Free the monitor associated with the object. */ dvmFreeObjectMonitor(obj); /* NOTE: Dereferencing clazz is dangerous. If obj was the last * one to reference its class object, the class object could be * on the sweep list, and could already have been swept, leaving * us with a stale pointer. */ LOGV_SWEEP("FREE: 0x%08x %s\n", (uint)obj, obj->clazz->name); /* This assumes that java.lang.Class will never go away. * If it can, and we were the last reference to it, it * could have already been swept. However, even in that case, * gDvm.classJavaLangClass should still have a useful * value. */ if (obj->clazz == classJavaLangClass) { LOGV_SWEEP("---------------> %s\n", ((ClassObject *)obj)->name); /* dvmFreeClassInnards() may have already been called, * but it's safe to call on the same ClassObject twice. */ dvmFreeClassInnards((ClassObject *)obj); } #if 0 /* Overwrite the to-be-freed object to make stale references * more obvious. */ { int chunklen; ClassObject *clazz = obj->clazz; #if WITH_OBJECT_HEADERS DvmHeapChunk chunk = *hc; chunk.header = ~OBJECT_HEADER | 1; #endif chunklen = dvmHeapSourceChunkSize(hc); memset(hc, 0xa5, chunklen); obj->clazz = (ClassObject *)((uintptr_t)clazz ^ 0xffffffff); #if WITH_OBJECT_HEADERS *hc = chunk; #endif } #endif //TODO: provide a heapsource function that takes a list of pointers to free // and call it outside of this loop. dvmHeapSourceFree(hc); } return true; }