/* * Tears down the entire GcHeap structure and all of the substructures * attached to it. This call has the side effect of setting the given * gcHeap pointer and gHs to NULL. */ void dvmHeapSourceShutdown(GcHeap **gcHeap) { assert(gcHeap != NULL); if (*gcHeap != NULL && (*gcHeap)->heapSource != NULL) { HeapSource *hs = (*gcHeap)->heapSource; dvmHeapBitmapDelete(&hs->liveBits); dvmHeapBitmapDelete(&hs->markBits); freeMarkStack(&(*gcHeap)->markContext.stack); munmap(hs->heapBase, hs->heapLength); free(hs); gHs = NULL; free(*gcHeap); *gcHeap = NULL; } }
/* * Clean up any resources associated with the bitmaps. */ void dvmHeapBitmapDeleteList(HeapBitmap hbs[], size_t numBitmaps) { size_t i; for (i = 0; i < numBitmaps; i++) { dvmHeapBitmapDelete(&hbs[i]); } }
void test_init() { HeapBitmap hb; bool ok; memset(&hb, 0x55, sizeof(hb)); ok = dvmHeapBitmapInit(&hb, HEAP_BASE, HEAP_SIZE, "test"); assert(ok); assert(hb.bits != NULL); assert(hb.bitsLen >= HB_OFFSET_TO_INDEX(HEAP_SIZE)); assert(hb.base == (uintptr_t)HEAP_BASE); assert(hb.max < hb.base); /* Make sure hb.bits is mapped. */ *hb.bits = 0x55; assert(*hb.bits = 0x55); *hb.bits = 0; #define TEST_UNMAP 0 #if TEST_UNMAP /* Hold onto this to make sure it's unmapped later. */ unsigned long int *bits = hb.bits; #endif dvmHeapBitmapDelete(&hb); assert(hb.bits == NULL); assert(hb.bitsLen == 0); assert(hb.base == 0); assert(hb.max == 0); #if TEST_UNMAP /* This pointer shouldn't be mapped anymore. */ *bits = 0x55; assert(!"Should have segfaulted"); #endif }
void test_clear() { HeapBitmap hb; bool ok; ok = dvmHeapBitmapInit(&hb, HEAP_BASE, HEAP_SIZE, "test"); assert(ok); assert_empty(&hb); /* Set the highest address. */ dvmHeapBitmapSetObjectBit(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT); assert(!is_zeroed(&hb)); /* Clear the bitmap. */ dvmHeapBitmapZero(&hb); assert_empty(&hb); /* Clean up. */ dvmHeapBitmapDelete(&hb); }
/* * Initializes the heap source; must be called before any other * dvmHeapSource*() functions. Returns a GcHeap structure * allocated from the heap source. */ GcHeap* dvmHeapSourceStartup(size_t startSize, size_t maximumSize, size_t growthLimit) { GcHeap *gcHeap = NULL; HeapSource *hs = NULL; mspace msp; size_t length; void *base; assert(gHs == NULL); if (!(startSize <= growthLimit && growthLimit <= maximumSize)) { ALOGE("Bad heap size parameters (start=%zd, max=%zd, limit=%zd)", startSize, maximumSize, growthLimit); return NULL; } /* * Allocate a contiguous region of virtual memory to subdivided * among the heaps managed by the garbage collector. */ length = ALIGN_UP_TO_PAGE_SIZE(maximumSize); base = dvmAllocRegion(length, PROT_NONE, gDvm.zygote ? "dalvik-zygote" : "dalvik-heap"); if (base == NULL) { dvmAbort(); } /* Create an unlocked dlmalloc mspace to use as * a heap source. */ msp = createMspace(base, kInitialMorecoreStart, startSize); if (msp == NULL) { dvmAbort(); } gcHeap = (GcHeap *)calloc(1, sizeof(*gcHeap)); if (gcHeap == NULL) { LOGE_HEAP("Can't allocate heap descriptor"); dvmAbort(); } hs = (HeapSource *)calloc(1, sizeof(*hs)); if (hs == NULL) { LOGE_HEAP("Can't allocate heap source"); dvmAbort(); } hs->targetUtilization = gDvm.heapTargetUtilization * HEAP_UTILIZATION_MAX; hs->minFree = gDvm.heapMinFree; hs->maxFree = gDvm.heapMaxFree; hs->startSize = startSize; hs->maximumSize = maximumSize; hs->growthLimit = growthLimit; hs->idealSize = startSize; hs->softLimit = SIZE_MAX; // no soft limit at first hs->numHeaps = 0; hs->sawZygote = gDvm.zygote; hs->nativeBytesAllocated = 0; hs->nativeFootprintGCWatermark = startSize; hs->nativeFootprintLimit = startSize * 2; hs->nativeNeedToRunFinalization = false; hs->hasGcThread = false; hs->heapBase = (char *)base; hs->heapLength = length; if (hs->maxFree > hs->maximumSize) { hs->maxFree = hs->maximumSize; } if (hs->minFree < CONCURRENT_START) { hs->minFree = CONCURRENT_START; } else if (hs->minFree > hs->maxFree) { hs->minFree = hs->maxFree; } if (!addInitialHeap(hs, msp, growthLimit)) { LOGE_HEAP("Can't add initial heap"); dvmAbort(); } if (!dvmHeapBitmapInit(&hs->liveBits, base, length, "dalvik-bitmap-1")) { LOGE_HEAP("Can't create liveBits"); dvmAbort(); } if (!dvmHeapBitmapInit(&hs->markBits, base, length, "dalvik-bitmap-2")) { LOGE_HEAP("Can't create markBits"); dvmHeapBitmapDelete(&hs->liveBits); dvmAbort(); } if (!allocMarkStack(&gcHeap->markContext.stack, hs->maximumSize)) { ALOGE("Can't create markStack"); dvmHeapBitmapDelete(&hs->markBits); dvmHeapBitmapDelete(&hs->liveBits); dvmAbort(); } gcHeap->markContext.bitmap = &hs->markBits; gcHeap->heapSource = hs; gHs = hs; return gcHeap; }
/* * Initializes the heap source; must be called before any other * dvmHeapSource*() functions. Returns a GcHeap structure * allocated from the heap source. */ GcHeap* dvmHeapSourceStartup(size_t startSize, size_t maximumSize, size_t growthLimit) { GcHeap *gcHeap; HeapSource *hs; mspace msp; size_t length; void *base; assert(gHs == NULL); if (!(startSize <= growthLimit && growthLimit <= maximumSize)) { ALOGE("Bad heap size parameters (start=%zd, max=%zd, limit=%zd)", startSize, maximumSize, growthLimit); return NULL; } /* * Allocate a contiguous region of virtual memory to subdivided * among the heaps managed by the garbage collector. */ length = ALIGN_UP_TO_PAGE_SIZE(maximumSize); base = dvmAllocRegion(length, PROT_NONE, "dalvik-heap"); if (base == NULL) { return NULL; } /* Create an unlocked dlmalloc mspace to use as * a heap source. */ msp = createMspace(base, startSize, maximumSize); if (msp == NULL) { goto fail; } gcHeap = (GcHeap *)calloc(1, sizeof(*gcHeap)); if (gcHeap == NULL) { LOGE_HEAP("Can't allocate heap descriptor"); goto fail; } hs = (HeapSource *)calloc(1, sizeof(*hs)); if (hs == NULL) { LOGE_HEAP("Can't allocate heap source"); free(gcHeap); goto fail; } hs->targetUtilization = DEFAULT_HEAP_UTILIZATION; hs->startSize = startSize; hs->maximumSize = maximumSize; hs->growthLimit = growthLimit; hs->idealSize = startSize; hs->softLimit = SIZE_MAX; // no soft limit at first hs->numHeaps = 0; hs->sawZygote = gDvm.zygote; hs->hasGcThread = false; hs->heapBase = (char *)base; hs->heapLength = length; if (!addInitialHeap(hs, msp, growthLimit)) { LOGE_HEAP("Can't add initial heap"); goto fail; } if (!dvmHeapBitmapInit(&hs->liveBits, base, length, "dalvik-bitmap-1")) { LOGE_HEAP("Can't create liveBits"); goto fail; } if (!dvmHeapBitmapInit(&hs->markBits, base, length, "dalvik-bitmap-2")) { LOGE_HEAP("Can't create markBits"); dvmHeapBitmapDelete(&hs->liveBits); goto fail; } if (!allocMarkStack(&gcHeap->markContext.stack, hs->maximumSize)) { ALOGE("Can't create markStack"); dvmHeapBitmapDelete(&hs->markBits); dvmHeapBitmapDelete(&hs->liveBits); goto fail; } gcHeap->markContext.bitmap = &hs->markBits; gcHeap->heapSource = hs; gHs = hs; return gcHeap; fail: munmap(base, length); return NULL; }
void run_xor(ssize_t offset, size_t step) { assert(step != 0); assert(step < HEAP_SIZE); /* Figure out the range. */ uintptr_t base; uintptr_t top; if (offset >= 0) { base = (uintptr_t)HEAP_BASE + offset; } else { base = (uintptr_t)HEAP_BASE + (uintptr_t)HEAP_SIZE + offset; } if (base < (uintptr_t)HEAP_BASE) { base = (uintptr_t)HEAP_BASE; } else if (base > (uintptr_t)(HEAP_BASE + HEAP_SIZE)) { base = (uintptr_t)(HEAP_BASE + HEAP_SIZE); } else { base = (base + HB_OBJECT_ALIGNMENT - 1) & ~(HB_OBJECT_ALIGNMENT - 1); } step *= HB_OBJECT_ALIGNMENT; top = base + step * NUM_XOR_PTRS; if (top > (uintptr_t)(HEAP_BASE + HEAP_SIZE)) { top = (uintptr_t)(HEAP_BASE + HEAP_SIZE); } /* Create the pointers. */ gNumPtrs = 0; memset(gXorPtrs, 0, sizeof(gXorPtrs)); memset(gClearedPtrs, 0, sizeof(gClearedPtrs)); memset(gSeenPtrs, 0, sizeof(gSeenPtrs)); uintptr_t addr; void **p = gXorPtrs; for (addr = base; addr < top; addr += step) { *p++ = (void *)addr; gNumPtrs++; } assert(seenAndClearedMatch()); /* Set up the bitmaps. */ HeapBitmap hb1, hb2; bool ok; ok = dvmHeapBitmapInit(&hb1, HEAP_BASE, HEAP_SIZE, "test1"); assert(ok); ok = dvmHeapBitmapInitFromTemplate(&hb2, &hb1, "test2"); assert(ok); /* Walk two empty bitmaps. */ TRACE("walk 0\n"); ok = dvmHeapBitmapXorWalk(&hb1, &hb2, xorCallback, gCallbackArg); assert(ok); assert(seenAndClearedMatch()); /* Walk one empty bitmap. */ TRACE("walk 1\n"); dvmHeapBitmapSetObjectBit(&hb1, (void *)base); ok = dvmHeapBitmapXorWalk(&hb1, &hb2, xorCallback, gCallbackArg); assert(ok); /* Make the bitmaps match. */ TRACE("walk 2\n"); dvmHeapBitmapSetObjectBit(&hb2, (void *)base); ok = dvmHeapBitmapXorWalk(&hb1, &hb2, xorCallback, gCallbackArg); assert(ok); /* Clear the bitmaps. */ dvmHeapBitmapZero(&hb1); assert_empty(&hb1); dvmHeapBitmapZero(&hb2); assert_empty(&hb2); /* Set the pointers we created in one of the bitmaps, * then visit them. */ size_t i; for (i = 0; i < gNumPtrs; i++) { dvmHeapBitmapSetObjectBit(&hb1, gXorPtrs[i]); } TRACE("walk 3\n"); ok = dvmHeapBitmapXorWalk(&hb1, &hb2, xorCallback, gCallbackArg); assert(ok); /* Set every third pointer in the other bitmap, and visit again. */ for (i = 0; i < gNumPtrs; i += 3) { dvmHeapBitmapSetObjectBit(&hb2, gXorPtrs[i]); } TRACE("walk 4\n"); ok = dvmHeapBitmapXorWalk(&hb1, &hb2, xorCallback, gCallbackArg); assert(ok); /* Set every other pointer in the other bitmap, and visit again. */ for (i = 0; i < gNumPtrs; i += 2) { dvmHeapBitmapSetObjectBit(&hb2, gXorPtrs[i]); } TRACE("walk 5\n"); ok = dvmHeapBitmapXorWalk(&hb1, &hb2, xorCallback, gCallbackArg); assert(ok); /* Walk just one bitmap. */ TRACE("walk 6\n"); ok = dvmHeapBitmapWalk(&hb2, xorCallback, gCallbackArg); assert(ok); //xxx build an expect list for the callback //xxx test where max points to beginning, middle, and end of a word /* Clean up. */ dvmHeapBitmapDelete(&hb1); dvmHeapBitmapDelete(&hb2); }
void test_modify() { HeapBitmap hb; bool ok; unsigned long bit; ok = dvmHeapBitmapInit(&hb, HEAP_BASE, HEAP_SIZE, "test"); assert(ok); assert_empty(&hb); /* Set the lowest address. */ bit = dvmHeapBitmapSetAndReturnObjectBit(&hb, HEAP_BASE); assert(bit == 0); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE)); assert(dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); /* Set the lowest address again. */ bit = dvmHeapBitmapSetAndReturnObjectBit(&hb, HEAP_BASE); assert(bit != 0); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE)); assert(dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); /* Set the highest address. */ bit = dvmHeapBitmapSetAndReturnObjectBit(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT); assert(bit == 0); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE)); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE)); assert(dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); /* Set the highest address again. */ bit = dvmHeapBitmapSetAndReturnObjectBit(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT); assert(bit != 0); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE)); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE)); assert(dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); /* Clean up. */ dvmHeapBitmapDelete(&hb); }
void test_bits() { HeapBitmap hb; bool ok; ok = dvmHeapBitmapInit(&hb, HEAP_BASE, HEAP_SIZE, "test"); assert(ok); assert_empty(&hb); /* Set the lowest address. */ dvmHeapBitmapSetObjectBit(&hb, HEAP_BASE); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE)); assert(dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); /* Set the highest address. */ dvmHeapBitmapSetObjectBit(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE)); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapMayContainObject(&hb, HEAP_BASE + HEAP_SIZE)); assert(dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); /* Clear the lowest address. */ dvmHeapBitmapClearObjectBit(&hb, HEAP_BASE); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); assert(!is_zeroed(&hb)); /* Clear the highest address. */ dvmHeapBitmapClearObjectBit(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HB_OBJECT_ALIGNMENT)); assert(!dvmHeapBitmapIsObjectBitSet(&hb, HEAP_BASE + HEAP_SIZE - HB_OBJECT_ALIGNMENT)); assert(is_zeroed(&hb)); /* Clean up. */ dvmHeapBitmapDelete(&hb); }