//------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- namespace Memory { template class SmallFinalizableHeapBucketBaseT : public SmallNormalHeapBucketBase { typedef SmallNormalHeapBucketBase BaseT; public: typedef typename THeapBlockType::HeapBlockAttributes TBlockAttributes; SmallFinalizableHeapBucketBaseT(); ~SmallFinalizableHeapBucketBaseT(); void DisposeObjects(); void TransferDisposedObjects(); void FinalizeAllObjects(); static void FinalizeHeapBlockList(THeapBlockType * list); #if ENABLE_MEM_STATS void AggregateBucketStats(); #endif protected: void EnumerateObjects(ObjectInfoBits infoBits, void (*CallBackFunction)(void * address, size_t size)); friend class HeapBucket; template friend class HeapBucketGroup; void ResetMarks(ResetMarkFlags flags); void Sweep(RecyclerSweep& recyclerSweep); #if DBG || defined(RECYCLER_SLOW_CHECK_ENABLED) size_t GetNonEmptyHeapBlockCount(bool checkCount) const; #endif #ifdef RECYCLER_SLOW_CHECK_ENABLED size_t Check(); #endif #ifdef RECYCLER_MEMORY_VERIFY void Verify(); #endif #ifdef RECYCLER_VERIFY_MARK void VerifyMark(); #endif #ifdef ENABLE_DEBUG_CONFIG_OPTIONS friend class ::ScriptMemoryDumper; #endif template friend class HeapBucketT; protected: THeapBlockType * pendingDisposeList; // list of block that has finalizable object that needs to be disposed #if DBG || defined(RECYCLER_SLOW_CHECK_ENABLED) THeapBlockType * tempPendingDisposeList; #endif }; template class SmallFinalizableHeapBucketT : public SmallFinalizableHeapBucketBaseT > { }; #ifdef RECYCLER_VISITED_HOST template class SmallRecyclerVisitedHostHeapBucketT : public SmallFinalizableHeapBucketBaseT > { }; #endif #ifdef RECYCLER_WRITE_BARRIER template class SmallFinalizableWithBarrierHeapBucketT : public SmallFinalizableHeapBucketBaseT > { }; #endif typedef SmallFinalizableHeapBucketT MediumFinalizableHeapBucket; typedef SmallFinalizableHeapBucketT SmallFinalizableHeapBucket; #ifdef RECYCLER_VISITED_HOST typedef SmallRecyclerVisitedHostHeapBucketT MediumRecyclerVisitedHostHeapBucket; typedef SmallRecyclerVisitedHostHeapBucketT SmallRecyclerVisitedHostHeapBucket; #endif #ifdef RECYCLER_WRITE_BARRIER typedef SmallFinalizableWithBarrierHeapBucketT MediumFinalizableWithBarrierHeapBucket; typedef SmallFinalizableWithBarrierHeapBucketT SmallFinalizableWithBarrierHeapBucket; #endif // GC-TODO: Move this away template class SmallHeapBlockType { public: CompileAssert((attributes & FinalizeBit) != 0); #ifdef RECYCLER_VISITED_HOST // attributes with RecyclerVisitedHostBit must use SmallRecyclerVisitedHostHeap{Bucket|Block}T CompileAssert((attributes & RecyclerVisitedHostBit) == 0); #endif typedef SmallFinalizableHeapBlockT BlockType; typedef SmallFinalizableHeapBucketT BucketType; }; #ifdef RECYCLER_VISITED_HOST template <> class SmallHeapBlockType<(ObjectInfoBits)(RecyclerVisitedHostBit), SmallAllocationBlockAttributes> { public: typedef SmallRecyclerVisitedHostHeapBlock BlockType; typedef SmallRecyclerVisitedHostHeapBucket BucketType; }; template <> class SmallHeapBlockType<(ObjectInfoBits)(RecyclerVisitedHostTracedFinalizableBlockTypeBits), SmallAllocationBlockAttributes> { public: typedef SmallRecyclerVisitedHostHeapBlock BlockType; typedef SmallRecyclerVisitedHostHeapBucket BucketType; }; template <> class SmallHeapBlockType<(ObjectInfoBits)(RecyclerVisitedHostFinalizableBlockTypeBits), SmallAllocationBlockAttributes> { public: typedef SmallRecyclerVisitedHostHeapBlock BlockType; typedef SmallRecyclerVisitedHostHeapBucket BucketType; }; #endif template <> class SmallHeapBlockType { public: typedef SmallLeafHeapBlock BlockType; typedef SmallLeafHeapBucketT BucketType; }; template <> class SmallHeapBlockType { public: typedef SmallNormalHeapBlock BlockType; typedef SmallNormalHeapBucket BucketType; }; #ifdef RECYCLER_WRITE_BARRIER template <> class SmallHeapBlockType { public: typedef SmallNormalWithBarrierHeapBlock BlockType; typedef SmallNormalWithBarrierHeapBucket BucketType; }; template <> class SmallHeapBlockType<(ObjectInfoBits)(WithBarrierBit|LeafBit), SmallAllocationBlockAttributes> { public: typedef SmallLeafHeapBlock BlockType; typedef SmallLeafHeapBucketT BucketType; }; template <> class SmallHeapBlockType { public: typedef SmallFinalizableWithBarrierHeapBlock BlockType; typedef SmallFinalizableWithBarrierHeapBucket BucketType; }; #endif #if SMALLBLOCK_MEDIUM_ALLOC template <> class SmallHeapBlockType { public: typedef MediumFinalizableHeapBlock BlockType; typedef MediumFinalizableHeapBucket BucketType; }; #ifdef RECYCLER_VISITED_HOST template <> class SmallHeapBlockType<(ObjectInfoBits)(RecyclerVisitedHostBit), MediumAllocationBlockAttributes> { public: typedef MediumRecyclerVisitedHostHeapBlock BlockType; typedef MediumRecyclerVisitedHostHeapBucket BucketType; }; template <> class SmallHeapBlockType<(ObjectInfoBits)(RecyclerVisitedHostTracedFinalizableBlockTypeBits), MediumAllocationBlockAttributes> { public: typedef MediumRecyclerVisitedHostHeapBlock BlockType; typedef MediumRecyclerVisitedHostHeapBucket BucketType; }; template <> class SmallHeapBlockType<(ObjectInfoBits)(RecyclerVisitedHostFinalizableBlockTypeBits), MediumAllocationBlockAttributes> { public: typedef MediumRecyclerVisitedHostHeapBlock BlockType; typedef MediumRecyclerVisitedHostHeapBucket BucketType; }; #endif template <> class SmallHeapBlockType { public: typedef MediumLeafHeapBlock BlockType; typedef SmallLeafHeapBucketT BucketType; }; template <> class SmallHeapBlockType { public: typedef MediumNormalHeapBlock BlockType; typedef MediumNormalHeapBucket BucketType; }; #ifdef RECYCLER_WRITE_BARRIER template <> class SmallHeapBlockType { public: typedef MediumNormalWithBarrierHeapBlock BlockType; typedef MediumNormalWithBarrierHeapBucket BucketType; }; template <> class SmallHeapBlockType<(ObjectInfoBits)(WithBarrierBit | LeafBit), MediumAllocationBlockAttributes> { public: typedef MediumLeafHeapBlock BlockType; typedef SmallLeafHeapBucketT BucketType; }; template <> class SmallHeapBlockType { public: typedef MediumFinalizableWithBarrierHeapBlock BlockType; typedef MediumFinalizableWithBarrierHeapBucket BucketType; }; #endif #endif template class HeapBucketGroup { template class BucketGetter { public: typedef typename SmallHeapBlockType::BucketType BucketType; static BucketType& GetBucket(HeapBucketGroup * heapBucketGroup) { CompileAssert(objectAttributes & FinalizeBit); return heapBucketGroup->finalizableHeapBucket; } }; template <> class BucketGetter { public: typedef typename SmallHeapBlockType::BucketType BucketType; static BucketType& GetBucket(HeapBucketGroup * heapBucketGroup) { return heapBucketGroup->leafHeapBucket; } }; template <> class BucketGetter { public: typedef typename SmallHeapBlockType::BucketType BucketType; static BucketType& GetBucket(HeapBucketGroup * heapBucketGroup) { return heapBucketGroup->heapBucket; } }; template <> class BucketGetter<(ObjectInfoBits)(FinalizeBit | LeafBit)> { public: typedef typename SmallHeapBlockType<(ObjectInfoBits)(FinalizeBit | LeafBit), TBlockAttributes>::BucketType BucketType; static BucketType& GetBucket(HeapBucketGroup * heapBucketGroup) { // TODO: SWB implemente finalizable leaf bucket return heapBucketGroup->finalizableHeapBucket; } }; #ifdef RECYCLER_VISITED_HOST template <> class BucketGetter<(ObjectInfoBits)(RecyclerVisitedHostBit)> { public: typedef typename SmallHeapBlockType<(ObjectInfoBits)(RecyclerVisitedHostBit), TBlockAttributes>::BucketType BucketType; static BucketType& GetBucket(HeapBucketGroup * HeapBucketGroup) { return HeapBucketGroup->recyclerVisitedHostHeapBucket; } }; template <> class BucketGetter<(ObjectInfoBits)(RecyclerVisitedHostTracedFinalizableBlockTypeBits)> { public: typedef typename SmallHeapBlockType<(ObjectInfoBits)(RecyclerVisitedHostTracedFinalizableBlockTypeBits), TBlockAttributes>::BucketType BucketType; static BucketType& GetBucket(HeapBucketGroup * HeapBucketGroup) { return HeapBucketGroup->recyclerVisitedHostHeapBucket; } }; template <> class BucketGetter<(ObjectInfoBits)(RecyclerVisitedHostFinalizableBlockTypeBits)> { public: typedef typename SmallHeapBlockType<(ObjectInfoBits)(RecyclerVisitedHostFinalizableBlockTypeBits), TBlockAttributes>::BucketType BucketType; static BucketType& GetBucket(HeapBucketGroup * HeapBucketGroup) { return HeapBucketGroup->recyclerVisitedHostHeapBucket; } }; #endif #ifdef RECYCLER_WRITE_BARRIER template <> class BucketGetter { public: typedef typename SmallHeapBlockType::BucketType BucketType; static BucketType& GetBucket(HeapBucketGroup * heapBucketGroup) { return heapBucketGroup->smallNormalWithBarrierHeapBucket; } }; template <> class BucketGetter<(ObjectInfoBits)(WithBarrierBit | LeafBit)> { public: typedef typename SmallHeapBlockType<(ObjectInfoBits)(WithBarrierBit | LeafBit), TBlockAttributes>::BucketType BucketType; static BucketType& GetBucket(HeapBucketGroup * heapBucketGroup) { // WithBarrierBit | LeafBit combination should not exist, this is only for compilation purpose Assert(false); return heapBucketGroup->leafHeapBucket; } }; template <> class BucketGetter { public: typedef typename SmallHeapBlockType::BucketType BucketType; static BucketType& GetBucket(HeapBucketGroup * heapBucketGroup) { return heapBucketGroup->smallFinalizableWithBarrierHeapBucket; } }; #endif public: template typename SmallHeapBlockType::BucketType& GetBucket() { return BucketGetter::GetBucket(this); } void Initialize(HeapInfo * heapInfo, uint sizeCat); void ResetMarks(ResetMarkFlags flags); void ScanInitialImplicitRoots(Recycler * recycler); void ScanNewImplicitRoots(Recycler * recycler); void Sweep(RecyclerSweep& recyclerSweep); uint Rescan(Recycler * recycler, RescanFlags flags); #if ENABLE_CONCURRENT_GC void SweepPendingObjects(RecyclerSweep& recyclerSweep); #endif #if ENABLE_PARTIAL_GC void SweepPartialReusePages(RecyclerSweep& recyclerSweep); void FinishPartialCollect(RecyclerSweep * recyclerSweep); #endif #if ENABLE_CONCURRENT_GC void PrepareSweep(); void SetupBackgroundSweep(RecyclerSweep& recyclerSweep); void TransferPendingEmptyHeapBlocks(RecyclerSweep& recyclerSweep); #endif void SweepFinalizableObjects(RecyclerSweep& recyclerSweep); void DisposeObjects(); void TransferDisposedObjects(); void EnumerateObjects(ObjectInfoBits infoBits, void (*CallBackFunction)(void * address, size_t size)); void FinalizeAllObjects(); static unsigned int GetHeapBucketOffset() { return offsetof(HeapBucketGroup, heapBucket); } #if DBG || defined(RECYCLER_SLOW_CHECK_ENABLED) size_t GetNonEmptyHeapBlockCount(bool checkCount) const; size_t GetEmptyHeapBlockCount() const; #endif #ifdef RECYCLER_SLOW_CHECK_ENABLED size_t Check(); #endif #ifdef RECYCLER_MEMORY_VERIFY void Verify(); #endif #ifdef RECYCLER_VERIFY_MARK void VerifyMark(); #endif #if ENABLE_ALLOCATIONS_DURING_CONCURRENT_SWEEP void StartAllocationDuringConcurrentSweep(); bool DoTwoPassConcurrentSweepPreCheck(); void FinishSweepPrep(RecyclerSweep& recyclerSweep); void FinishConcurrentSweepPass1(RecyclerSweep& recyclerSweep); void FinishConcurrentSweep(); #endif #if DBG bool AllocatorsAreEmpty(); #endif private: SmallNormalHeapBucketT heapBucket; SmallLeafHeapBucketT leafHeapBucket; SmallFinalizableHeapBucketT finalizableHeapBucket; #ifdef RECYCLER_VISITED_HOST SmallRecyclerVisitedHostHeapBucketT recyclerVisitedHostHeapBucket; #endif #ifdef RECYCLER_WRITE_BARRIER SmallNormalWithBarrierHeapBucketT smallNormalWithBarrierHeapBucket; SmallFinalizableWithBarrierHeapBucketT smallFinalizableWithBarrierHeapBucket; #endif }; extern template class HeapBucketGroup; extern template class HeapBucketGroup; }