//===================================================================================================== // Free //===================================================================================================== void LargeHeapBucket::ExplicitFree(void * object, size_t sizeCat) { Assert(HeapInfo::GetMediumObjectAlignedSizeNoCheck(sizeCat) == this->sizeCat); LargeObjectHeader * header = LargeHeapBlock::GetHeaderFromAddress(object); Assert(header->GetAttributes(this->heapInfo->recycler->Cookie) == ObjectInfoBits::NoBit || header->GetAttributes(this->heapInfo->recycler->Cookie) == ObjectInfoBits::LeafBit); Assert(!header->isExplicitFreed); DebugOnly(header->isExplicitFreed = true); Assert(header->objectSize >= sizeCat); #if DBG HeapBlock* heapBlock = this->GetRecycler()->FindHeapBlock(object); Assert(heapBlock != nullptr); Assert(heapBlock->IsLargeHeapBlock()); LargeHeapBlock * largeHeapBlock = (LargeHeapBlock *)heapBlock; LargeObjectHeader * dbgHeader; Assert(largeHeapBlock->GetObjectHeader(object, &dbgHeader)); Assert(dbgHeader == header); #endif FreeObject * freeObject = (FreeObject *)object; freeObject->SetNext(this->explicitFreeList); this->explicitFreeList = freeObject; header->SetAttributes(this->heapInfo->recycler->Cookie, ObjectInfoBits::LeafBit); // We can stop scanning it now. }
char * LargeHeapBucket::TryAllocFromExplicitFreeList(Recycler * recycler, size_t sizeCat, ObjectInfoBits attributes) { Assert((attributes & InternalObjectInfoBitMask) == attributes); FreeObject * currFreeObject = this->explicitFreeList; FreeObject * prevFreeObject = nullptr; while (currFreeObject != nullptr) { char * memBlock = (char *)currFreeObject; LargeObjectHeader * header = LargeHeapBlock::GetHeaderFromAddress(memBlock); Assert(header->isExplicitFreed); Assert(HeapInfo::GetMediumObjectAlignedSizeNoCheck(header->objectSize) == this->sizeCat); if (header->objectSize < sizeCat) { prevFreeObject = currFreeObject; currFreeObject = currFreeObject->GetNext(); continue; } DebugOnly(header->isExplicitFreed = false); if (prevFreeObject) { prevFreeObject->SetNext(currFreeObject->GetNext()); } else { this->explicitFreeList = currFreeObject->GetNext(); } #ifdef RECYCLER_MEMORY_VERIFY HeapBlock* heapBlock = recycler->FindHeapBlock(memBlock); Assert(heapBlock != nullptr); Assert(heapBlock->IsLargeHeapBlock()); LargeHeapBlock * largeHeapBlock = (LargeHeapBlock *)heapBlock; LargeObjectHeader * dbgHeader; Assert(largeHeapBlock->GetObjectHeader(memBlock, &dbgHeader)); Assert(dbgHeader == header); ((FreeObject *)memBlock)->DebugFillNext(); #endif #ifdef RECYCLER_ZERO_MEM_CHECK // TODO: large heap block doesn't separate leaf object on to different page allocator. // so all the memory should still be zeroed. memset(memBlock, 0, sizeof(FreeObject)); #endif header->SetAttributes(recycler->Cookie, (attributes & StoredObjectInfoBitMask)); if ((attributes & ObjectInfoBits::FinalizeBit) != 0) { LargeHeapBlock* heapBlock = (LargeHeapBlock *)recycler->FindHeapBlock(memBlock); heapBlock->finalizeCount++; #ifdef RECYCLER_FINALIZE_CHECK heapInfo->liveFinalizableObjectCount++; heapInfo->newFinalizableObjectCount++; #endif } return memBlock; } return nullptr; }