static bool createMarkStack(GcMarkStack *stack) { const Object **limit; const char *name; size_t size; /* Create a stack big enough for the worst possible case, * where the heap is perfectly full of the smallest object. * TODO: be better about memory usage; use a smaller stack with * overflow detection and recovery. */ size = dvmHeapSourceGetIdealFootprint() * sizeof(Object*) / (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD); size = ALIGN_UP_TO_PAGE_SIZE(size); name = "dalvik-mark-stack"; limit = dvmAllocRegion(size, PROT_READ | PROT_WRITE, name); if (limit == NULL) { LOGE_GC("Could not mmap %zd-byte ashmem region '%s'", size, name); return false; } stack->limit = limit; stack->base = (const Object **)((uintptr_t)limit + size); stack->top = stack->base; return true; }
static DvmDex* allocateAuxStructures(DexFile* pDexFile) { DvmDex* pDvmDex; const DexHeader* pHeader; u4 stringSize, classSize, methodSize, fieldSize; pHeader = pDexFile->pHeader; stringSize = pHeader->stringIdsSize * sizeof(struct StringObject*); classSize = pHeader->typeIdsSize * sizeof(struct ClassObject*); methodSize = pHeader->methodIdsSize * sizeof(struct Method*); fieldSize = pHeader->fieldIdsSize * sizeof(struct Field*); u4 totalSize = sizeof(DvmDex) + stringSize + classSize + methodSize + fieldSize; u1 *blob = (u1 *)dvmAllocRegion(totalSize, PROT_READ | PROT_WRITE, "dalvik-aux-structure"); if ((void *)blob == MAP_FAILED) return NULL; pDvmDex = (DvmDex*)blob; blob += sizeof(DvmDex); pDvmDex->pDexFile = pDexFile; pDvmDex->pHeader = pHeader; pDvmDex->pResStrings = (struct StringObject**)blob; blob += stringSize; pDvmDex->pResClasses = (struct ClassObject**)blob; blob += classSize; pDvmDex->pResMethods = (struct Method**)blob; blob += methodSize; pDvmDex->pResFields = (struct Field**)blob; ALOGV("+++ DEX %p: allocateAux (%d+%d+%d+%d)*4 = %d bytes", pDvmDex, stringSize/4, classSize/4, methodSize/4, fieldSize/4, stringSize + classSize + methodSize + fieldSize); pDvmDex->pInterfaceCache = dvmAllocAtomicCache(DEX_INTERFACE_CACHE_SIZE); dvmInitMutex(&pDvmDex->modLock); return pDvmDex; }
/* * Create a stack big enough for the worst possible case, where the * heap is perfectly full of the smallest object. * TODO: be better about memory usage; use a smaller stack with * overflow detection and recovery. */ static bool allocMarkStack(GcMarkStack *stack, size_t maximumSize) { const char *name = "dalvik-mark-stack"; void *addr; assert(stack != NULL); stack->length = maximumSize * sizeof(Object*) / (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD); addr = dvmAllocRegion(stack->length, PROT_READ | PROT_WRITE, name); if (addr == NULL) { return false; } stack->base = (const Object **)addr; stack->limit = (const Object **)((char *)addr + stack->length); stack->top = NULL; madvise(stack->base, stack->length, MADV_DONTNEED); return true; }
/* * Initialize a HeapBitmap so that it points to a bitmap large * enough to cover a heap at <base> of <maxSize> bytes, where * objects are guaranteed to be HB_OBJECT_ALIGNMENT-aligned. */ bool dvmHeapBitmapInit(HeapBitmap *hb, const void *base, size_t maxSize, const char *name) { void *bits; size_t bitsLen; assert(hb != NULL); assert(name != NULL); bitsLen = HB_OFFSET_TO_INDEX(maxSize) * sizeof(*hb->bits); bits = dvmAllocRegion(bitsLen, PROT_READ | PROT_WRITE, name); if (bits == NULL) { ALOGE("Could not mmap %zd-byte ashmem region '%s'", bitsLen, name); return false; } hb->bits = (unsigned long *)bits; hb->bitsLen = hb->allocLen = bitsLen; hb->base = (uintptr_t)base; hb->max = hb->base - 1; return true; }
/* * 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; }