diff options
author | Jan Kotas <jkotas@microsoft.com> | 2015-12-17 06:33:37 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2015-12-17 06:33:37 +0300 |
commit | 015151807b479ab92412cf3d1eb157786650f314 (patch) | |
tree | 04b25d72c5f54da1146c39848b163512a9be26c4 /src/Native | |
parent | 2f458a1db3e7ce82b24802f0a8372718f625b827 (diff) | |
parent | e223e35867c4660fe8423fedb2e547152dd7fd2d (diff) |
Merge pull request #545 from dotnet-bot/from-tfs
Merge changes from TFS
Diffstat (limited to 'src/Native')
-rw-r--r-- | src/Native/Runtime/AsmOffsets.h | 12 | ||||
-rw-r--r-- | src/Native/Runtime/AsmOffsetsVerify.cpp | 2 | ||||
-rw-r--r-- | src/Native/Runtime/Crst.h | 6 | ||||
-rw-r--r-- | src/Native/Runtime/eetype.cpp | 2 | ||||
-rw-r--r-- | src/Native/Runtime/gcenv.h | 2 | ||||
-rw-r--r-- | src/Native/Runtime/gcrhenv.cpp | 22 | ||||
-rw-r--r-- | src/Native/Runtime/inc/rhbinder.h | 8 | ||||
-rw-r--r-- | src/Native/Runtime/thread.h | 9 | ||||
-rw-r--r-- | src/Native/gc/gc.cpp | 130 | ||||
-rw-r--r-- | src/Native/gc/gc.h | 6 | ||||
-rw-r--r-- | src/Native/gc/gcpriv.h | 11 |
11 files changed, 162 insertions, 48 deletions
diff --git a/src/Native/Runtime/AsmOffsets.h b/src/Native/Runtime/AsmOffsets.h index 3a43cc962..e12bde0df 100644 --- a/src/Native/Runtime/AsmOffsets.h +++ b/src/Native/Runtime/AsmOffsets.h @@ -37,12 +37,12 @@ ASM_OFFSET( 4, 4, EEType, m_uBaseSize) ASM_OFFSET( 14, 18, EEType, m_VTable) ASM_OFFSET( 0, 0, Thread, m_rgbAllocContextBuffer) -ASM_OFFSET( 1c, 28, Thread, m_ThreadStateFlags) -ASM_OFFSET( 20, 30, Thread, m_pTransitionFrame) -ASM_OFFSET( 24, 38, Thread, m_pHackPInvokeTunnel) -ASM_OFFSET( 34, 58, Thread, m_ppvHijackedReturnAddressLocation) -ASM_OFFSET( 38, 60, Thread, m_pvHijackedReturnAddress) -ASM_OFFSET( 3c, 68, Thread, m_pExInfoStackHead) +ASM_OFFSET( 28, 38, Thread, m_ThreadStateFlags) +ASM_OFFSET( 2c, 40, Thread, m_pTransitionFrame) +ASM_OFFSET( 30, 48, Thread, m_pHackPInvokeTunnel) +ASM_OFFSET( 40, 68, Thread, m_ppvHijackedReturnAddressLocation) +ASM_OFFSET( 44, 70, Thread, m_pvHijackedReturnAddress) +ASM_OFFSET( 48, 78, Thread, m_pExInfoStackHead) ASM_SIZEOF( 14, 20, EHEnum) diff --git a/src/Native/Runtime/AsmOffsetsVerify.cpp b/src/Native/Runtime/AsmOffsetsVerify.cpp index 8e21e079f..99ca8a583 100644 --- a/src/Native/Runtime/AsmOffsetsVerify.cpp +++ b/src/Native/Runtime/AsmOffsetsVerify.cpp @@ -23,6 +23,8 @@ class AsmOffsets { + static_assert(sizeof(Thread::m_rgbAllocContextBuffer) >= sizeof(alloc_context), "Thread::m_rgbAllocContextBuffer is not big enough to hold an alloc_context"); + #define PLAT_ASM_OFFSET(offset, cls, member) \ static_assert((offsetof(cls, member) == 0x##offset) || (offsetof(cls, member) > 0x##offset), "Bad asm offset for '" #cls "." #member "', the actual offset is smaller than 0x" #offset "."); \ static_assert((offsetof(cls, member) == 0x##offset) || (offsetof(cls, member) < 0x##offset), "Bad asm offset for '" #cls "." #member "', the actual offset is larger than 0x" #offset "."); diff --git a/src/Native/Runtime/Crst.h b/src/Native/Runtime/Crst.h index bd2927000..c267a3c0c 100644 --- a/src/Native/Runtime/Crst.h +++ b/src/Native/Runtime/Crst.h @@ -22,23 +22,21 @@ private: // ----------------------------------------------------------------------------------------------------------- // // Minimal Crst implementation based on CRITICAL_SECTION. Doesn't support much except for the basic locking -// functionality (in particular there is no rank violation checking, but then again there's only one Crst type -// used currently). +// functionality (in particular there is no rank violation checking). // enum CrstType { CrstHandleTable, - CrstThreadStore, CrstDispatchCache, CrstAllocHeap, - CrstModuleList, CrstGenericInstHashtab, CrstMemAccessMgr, CrstInterfaceDispatchGlobalLists, CrstStressLog, CrstRestrictedCallouts, CrstGcStressControl, + CrstSuspendEE, }; enum CrstFlags diff --git a/src/Native/Runtime/eetype.cpp b/src/Native/Runtime/eetype.cpp index ee3a4d27b..8603787ce 100644 --- a/src/Native/Runtime/eetype.cpp +++ b/src/Native/Runtime/eetype.cpp @@ -45,7 +45,7 @@ bool EEType::Validate(bool assertOnFail /* default: true */) case CanonicalEEType: { // If the parent type is NULL this had better look like Object. - if (m_RelatedType.m_pBaseType == NULL) + if (!IsInterface() && (m_RelatedType.m_pBaseType == NULL)) { if (IsRelatedTypeViaIAT() || get_IsValueType() || diff --git a/src/Native/Runtime/gcenv.h b/src/Native/Runtime/gcenv.h index 2b9fb2767..8833a9452 100644 --- a/src/Native/Runtime/gcenv.h +++ b/src/Native/Runtime/gcenv.h @@ -98,6 +98,8 @@ public: UInt32 GetRequiredAlignment() const { return sizeof(void*); } #endif // FEATURE_BARTOK #endif // FEATURE_STRUCTALIGN + bool RequiresAlign8() { return ((EEType*)this)->RequiresAlign8(); } + bool IsValueType() { return ((EEType*)this)->get_IsValueType(); } UInt32_BOOL SanityCheck() { return ((EEType*)this)->Validate(); } // TODO: remove this method after the __isinst_class is gone MethodTable* GetParent() diff --git a/src/Native/Runtime/gcrhenv.cpp b/src/Native/Runtime/gcrhenv.cpp index dab53d690..25b6e160d 100644 --- a/src/Native/Runtime/gcrhenv.cpp +++ b/src/Native/Runtime/gcrhenv.cpp @@ -147,6 +147,12 @@ UInt32 EtwCallback(UInt32 IsEnabled, RH_ETW_CONTEXT * pContext) // success or false if a subsystem failed to initialize. #ifndef DACCESS_COMPILE +CrstStatic g_SuspendEELock; +#ifdef _MSC_VER +#pragma warning(disable:4815) // zero-sized array in stack object will have no elements +#endif // _MSC_VER +EEType g_FreeObjectEEType; + // static bool RedhawkGCInterface::InitializeSubsystems(GCType gcType) { @@ -167,13 +173,15 @@ bool RedhawkGCInterface::InitializeSubsystems(GCType gcType) InitializeSystemInfo(); // Initialize the special EEType used to mark free list entries in the GC heap. - EEType *pFreeObjectType = new (nothrow) EEType(); //@TODO: remove 'new' - pFreeObjectType->InitializeAsGcFreeType(); + g_FreeObjectEEType.InitializeAsGcFreeType(); // Place the pointer to this type in a global cell (typed as the structurally equivalent MethodTable // that the GC understands). - g_pFreeObjectMethodTable = (MethodTable *)pFreeObjectType; - g_pFreeObjectEEType = pFreeObjectType; + g_pFreeObjectMethodTable = (MethodTable *)&g_FreeObjectEEType; + g_pFreeObjectEEType = &g_FreeObjectEEType; + + if (!g_SuspendEELock.InitNoThrow(CrstSuspendEE)) + return false; // Set the GC heap type. bool fUseServerGC = (gcType == GCType_Server); @@ -802,6 +810,8 @@ void GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason) FireEtwGCSuspendEEBegin_V1(Info.SuspendEE.Reason, Info.SuspendEE.GcCount, GetClrInstanceId()); + g_SuspendEELock.Enter(); + g_TrapReturningThreads = TRUE; GCHeap::GetGCHeap()->SetGCInProgress(TRUE); @@ -824,7 +834,9 @@ void GCToEEInterface::RestartEE(bool /*bFinishedGC*/) GetThreadStore()->ResumeAllThreads(GCHeap::GetGCHeap()->GetWaitForGCEvent()); GCHeap::GetGCHeap()->SetGCInProgress(FALSE); - g_TrapReturningThreads = FALSE; // @TODO: map this to something meaningful in the new algorithm + g_TrapReturningThreads = FALSE; + + g_SuspendEELock.Leave(); FireEtwGCRestartEEEnd_V1(GetClrInstanceId()); } diff --git a/src/Native/Runtime/inc/rhbinder.h b/src/Native/Runtime/inc/rhbinder.h index fbd3cba6d..5e9c29baf 100644 --- a/src/Native/Runtime/inc/rhbinder.h +++ b/src/Native/Runtime/inc/rhbinder.h @@ -651,11 +651,13 @@ struct PInvokeTransitionFrame #define PInvokeTransitionFrame_MAX_SIZE (sizeof(PInvokeTransitionFrame) + (POINTER_SIZE * PInvokeTransitionFrame_SaveRegs_count)) #ifdef _TARGET_AMD64_ -#define OFFSETOF__Thread__m_pTransitionFrame 0x30 +#define OFFSETOF__Thread__m_pTransitionFrame 0x40 +#elif defined(_TARGET_ARM64_) +#define OFFSETOF__Thread__m_pTransitionFrame 0x40 #elif defined(_TARGET_X86_) -#define OFFSETOF__Thread__m_pTransitionFrame 0x20 +#define OFFSETOF__Thread__m_pTransitionFrame 0x2c #elif defined(_TARGET_ARM_) -#define OFFSETOF__Thread__m_pTransitionFrame 0x20 +#define OFFSETOF__Thread__m_pTransitionFrame 0x2c #endif #ifdef RHDUMP diff --git a/src/Native/Runtime/thread.h b/src/Native/Runtime/thread.h index 2fe85c23f..1f9808e7f 100644 --- a/src/Native/Runtime/thread.h +++ b/src/Native/Runtime/thread.h @@ -10,14 +10,19 @@ class ThreadStore; class CLREventStatic; class Thread; +// The offsets of some fields in the thread (in particular, m_pTransitionFrame) are known to the compiler and get +// inlined into the code. Let's make sure they don't change just because we enable/disable server GC in a particular +// runtime build. +#define KEEP_THREAD_LAYOUT_CONSTANT + #if defined(_X86_) || defined(_ARM_) -# ifdef FEATURE_SVR_GC +# if defined(FEATURE_SVR_GC) || defined(KEEP_THREAD_LAYOUT_CONSTANT) # define SIZEOF_ALLOC_CONTEXT 40 # else // FEATURE_SVR_GC # define SIZEOF_ALLOC_CONTEXT 28 # endif // FEATURE_SVR_GC #elif defined(_AMD64_) || defined(_ARM64_) -# ifdef FEATURE_SVR_GC +# if defined(FEATURE_SVR_GC) || defined(KEEP_THREAD_LAYOUT_CONSTANT) # define SIZEOF_ALLOC_CONTEXT 56 # else // FEATURE_SVR_GC # define SIZEOF_ALLOC_CONTEXT 40 diff --git a/src/Native/gc/gc.cpp b/src/Native/gc/gc.cpp index db878fbd8..30642686b 100644 --- a/src/Native/gc/gc.cpp +++ b/src/Native/gc/gc.cpp @@ -3667,10 +3667,16 @@ heap_segment* seg_mapping_table_segment_of (uint8_t* o) } #ifdef FEATURE_BASICFREEZE - if (!seg && (size_t)(entry->seg1) & ro_in_entry) + // TODO: This was originally written assuming that the seg_mapping_table would always contain entries for ro + // segments whenever the ro segment falls into the [g_lowest_address,g_highest_address) range. I.e., it had an + // extra "&& (size_t)(entry->seg1) & ro_in_entry" expression. However, at the moment, grow_brick_card_table does + // not correctly go through the ro segments and add them back to the seg_mapping_table when the [lowest,highest) + // range changes. We should probably go ahead and modify grow_brick_card_table and put back the + // "&& (size_t)(entry->seg1) & ro_in_entry" here. + if (!seg) { seg = ro_segment_lookup (o); - if (!in_range_for_segment (o, seg)) + if (seg && !in_range_for_segment (o, seg)) seg = 0; } #endif //FEATURE_BASICFREEZE @@ -3709,22 +3715,46 @@ public: if (this == NULL) return; + MethodTable * pMT = GetMethodTable(); + + _ASSERTE(pMT->SanityCheck()); + + bool noRangeChecks = + (g_pConfig->GetHeapVerifyLevel() & EEConfig::HEAPVERIFY_NO_RANGE_CHECKS) == EEConfig::HEAPVERIFY_NO_RANGE_CHECKS; + BOOL fSmallObjectHeapPtr = FALSE, fLargeObjectHeapPtr = FALSE; - fSmallObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this, TRUE); - if (!fSmallObjectHeapPtr) - fLargeObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this); + if (!noRangeChecks) + { + fSmallObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this, TRUE); + if (!fSmallObjectHeapPtr) + fLargeObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this); - _ASSERTE(fSmallObjectHeapPtr || fLargeObjectHeapPtr); - _ASSERTE(GetMethodTable()->GetBaseSize() >= 8); + _ASSERTE(fSmallObjectHeapPtr || fLargeObjectHeapPtr); + } #ifdef FEATURE_STRUCTALIGN _ASSERTE(IsStructAligned((uint8_t *)this, GetMethodTable()->GetBaseAlignment())); #endif // FEATURE_STRUCTALIGN +#ifdef FEATURE_64BIT_ALIGNMENT + if (pMT->RequiresAlign8()) + { + _ASSERTE((((size_t)this) & 0x7) == (pMT->IsValueType() ? 4U : 0U)); + } +#endif // FEATURE_64BIT_ALIGNMENT + #ifdef VERIFY_HEAP - if (bDeep) + if (bDeep && (g_pConfig->GetHeapVerifyLevel() & EEConfig::HEAPVERIFY_GC)) GCHeap::GetGCHeap()->ValidateObjectMember(this); #endif + if (fSmallObjectHeapPtr) + { +#ifdef FEATURE_BASICFREEZE + _ASSERTE(!GCHeap::GetGCHeap()->IsLargeObject(pMT) || GCHeap::GetGCHeap()->IsInFrozenSegment(this)); +#else + _ASSERTE(!GCHeap::GetGCHeap()->IsLargeObject(pMT)); +#endif + } } void ValidatePromote(ScanContext *sc, uint32_t flags) @@ -6717,12 +6747,21 @@ uint32_t* translate_mark_array (uint32_t* ma) } // from and end must be page aligned addresses. -void gc_heap::clear_mark_array (uint8_t* from, uint8_t* end, BOOL check_only/*=TRUE*/) +void gc_heap::clear_mark_array (uint8_t* from, uint8_t* end, BOOL check_only/*=TRUE*/ +#ifdef FEATURE_BASICFREEZE + , BOOL read_only/*=FALSE*/ +#endif // FEATURE_BASICFREEZE + ) { if(!gc_can_use_concurrent) return; - assert (from == align_on_mark_word (from)); +#ifdef FEATURE_BASICFREEZE + if (!read_only) +#endif // FEATURE_BASICFREEZE + { + assert (from == align_on_mark_word (from)); + } assert (end == align_on_mark_word (end)); #ifdef BACKGROUND_GC @@ -8767,7 +8806,11 @@ void gc_heap::seg_clear_mark_array_bits_soh (heap_segment* seg) uint8_t* range_end = 0; if (bgc_mark_array_range (seg, FALSE, &range_beg, &range_end)) { - clear_mark_array (range_beg, align_on_mark_word (range_end), FALSE); + clear_mark_array (range_beg, align_on_mark_word (range_end), FALSE +#ifdef FEATURE_BASICFREEZE + , TRUE +#endif // FEATURE_BASICFREEZE + ); } } @@ -20359,10 +20402,9 @@ void gc_heap::seg_clear_mark_bits (heap_segment* seg) } } +#ifdef FEATURE_BASICFREEZE void gc_heap::sweep_ro_segments (heap_segment* start_seg) { - UNREFERENCED_PARAMETER(start_seg); -#if 0 //go through all of the segment in range and reset the mark bit //TODO works only on small object segments @@ -20389,7 +20431,7 @@ void gc_heap::sweep_ro_segments (heap_segment* start_seg) { clear_mark_array (max (heap_segment_mem (seg), lowest_address), min (heap_segment_allocated (seg), highest_address), - false); // read_only segments need the mark clear + FALSE); // read_only segments need the mark clear } #else //MARK_ARRAY seg_clear_mark_bits (seg); @@ -20399,8 +20441,8 @@ void gc_heap::sweep_ro_segments (heap_segment* start_seg) } seg = heap_segment_next (seg); } -#endif //0 } +#endif // FEATURE_BASICFREEZE #ifdef FEATURE_LOH_COMPACTION inline @@ -21207,11 +21249,13 @@ void gc_heap::plan_phase (int condemned_gen_number) #endif //MARK_LIST +#ifdef FEATURE_BASICFREEZE if ((generation_start_segment (condemned_gen1) != ephemeral_heap_segment) && ro_segments_in_range) { sweep_ro_segments (generation_start_segment (condemned_gen1)); } +#endif // FEATURE_BASICFREEZE #ifndef MULTIPLE_HEAPS if (shigh != (uint8_t*)0) @@ -23166,6 +23210,26 @@ uint8_t* tree_search (uint8_t* tree, uint8_t* old_address) return tree; } +#ifdef FEATURE_BASICFREEZE +bool gc_heap::frozen_object_p (Object* obj) +{ +#ifdef MULTIPLE_HEAPS + ptrdiff_t delta = 0; + heap_segment* pSegment = segment_of ((uint8_t*)obj, delta); +#else //MULTIPLE_HEAPS + heap_segment* pSegment = gc_heap::find_segment ((uint8_t*)obj, FALSE); + _ASSERTE(pSegment); +#endif //MULTIPLE_HEAPS + + return heap_segment_read_only_p(pSegment); +} +#endif // FEATURE_BASICFREEZE + +#ifdef FEATURE_REDHAWK +// TODO: this was added on RH, we have not done perf runs to see if this is the right +// thing to do for other versions of the CLR. +inline +#endif // FEATURE_REDHAWK void gc_heap::relocate_address (uint8_t** pold_address THREAD_NUMBER_DCL) { uint8_t* old_address = *pold_address; @@ -23224,7 +23288,11 @@ void gc_heap::relocate_address (uint8_t** pold_address THREAD_NUMBER_DCL) } #ifdef FEATURE_LOH_COMPACTION - if (loh_compacted_p) + if (loh_compacted_p +#ifdef FEATURE_BASICFREEZE + && !frozen_object_p((Object*)old_address) +#endif // FEATURE_BASICFREEZE + ) { *pold_address = old_address + loh_node_relocation_distance (old_address); } @@ -25080,7 +25148,7 @@ BOOL gc_heap::commit_mark_array_new_seg (gc_heap* hp, { UNREFERENCED_PARAMETER(hp); // compiler bug? -- this *is*, indeed, referenced - uint8_t* start = (uint8_t*)seg; + uint8_t* start = (heap_segment_read_only_p(seg) ? heap_segment_mem(seg) : (uint8_t*)seg); uint8_t* end = heap_segment_reserved (seg); uint8_t* lowest = hp->background_saved_lowest_address; @@ -25177,7 +25245,7 @@ BOOL gc_heap::commit_mark_array_by_range (uint8_t* begin, uint8_t* end, uint32_t BOOL gc_heap::commit_mark_array_with_check (heap_segment* seg, uint32_t* new_mark_array_addr) { - uint8_t* start = (uint8_t*)seg; + uint8_t* start = (heap_segment_read_only_p(seg) ? heap_segment_mem(seg) : (uint8_t*)seg); uint8_t* end = heap_segment_reserved (seg); #ifdef MULTIPLE_HEAPS @@ -25204,11 +25272,13 @@ BOOL gc_heap::commit_mark_array_with_check (heap_segment* seg, uint32_t* new_mar BOOL gc_heap::commit_mark_array_by_seg (heap_segment* seg, uint32_t* mark_array_addr) { - dprintf (GC_TABLE_LOG, ("seg: %Ix->%Ix; MA: %Ix", - seg, - heap_segment_reserved (seg), - mark_array_addr)); - return commit_mark_array_by_range ((uint8_t*)seg, heap_segment_reserved (seg), mark_array_addr); + dprintf (GC_TABLE_LOG, ("seg: %Ix->%Ix; MA: %Ix", + seg, + heap_segment_reserved (seg), + mark_array_addr)); + uint8_t* start = (heap_segment_read_only_p (seg) ? heap_segment_mem (seg) : (uint8_t*)seg); + + return commit_mark_array_by_range (start, heap_segment_reserved (seg), mark_array_addr); } BOOL gc_heap::commit_mark_array_bgc_init (uint32_t* mark_array_addr) @@ -25258,7 +25328,7 @@ BOOL gc_heap::commit_mark_array_bgc_init (uint32_t* mark_array_addr) } else { - uint8_t* start = max (lowest_address, (uint8_t*)seg); + uint8_t* start = max (lowest_address, heap_segment_mem (seg)); uint8_t* end = min (highest_address, heap_segment_reserved (seg)); if (commit_mark_array_by_range (start, end, mark_array)) { @@ -25374,7 +25444,7 @@ void gc_heap::decommit_mark_array_by_seg (heap_segment* seg) if ((flags & heap_segment_flags_ma_committed) || (flags & heap_segment_flags_ma_pcommitted)) { - uint8_t* start = (uint8_t*)seg; + uint8_t* start = (heap_segment_read_only_p(seg) ? heap_segment_mem(seg) : (uint8_t*)seg); uint8_t* end = heap_segment_reserved (seg); if (flags & heap_segment_flags_ma_pcommitted) @@ -31181,11 +31251,13 @@ void gc_heap::background_sweep() current_bgc_state = bgc_sweep_soh; verify_soh_segment_list(); +#ifdef FEATURE_BASICFREEZE if ((generation_start_segment (gen) != ephemeral_heap_segment) && ro_segments_in_range) { sweep_ro_segments (generation_start_segment (gen)); } +#endif // FEATURE_BASICFREEZE //TODO BACKGROUND_GC: can we move this to where we switch to the LOH? if (current_c_gc_state != c_gc_state_planning) @@ -36782,7 +36854,13 @@ inline void testGCShadow(Object** ptr) if(*shadow!=INVALIDGCVALUE) { - _ASSERTE(!"Pointer updated without using write barrier"); +#ifdef FEATURE_BASICFREEZE + // Write barriers for stores of references to frozen objects may be optimized away. + if (!gc_heap::frozen_object_p(*ptr)) +#endif // FEATURE_BASICFREEZE + { + _ASSERTE(!"Pointer updated without using write barrier"); + } } /* else diff --git a/src/Native/gc/gc.h b/src/Native/gc/gc.h index 838f3bac7..3421a48bd 100644 --- a/src/Native/gc/gc.h +++ b/src/Native/gc/gc.h @@ -615,6 +615,12 @@ public: // static if since restricting for all heaps is fine virtual size_t GetValidSegmentSize(BOOL large_seg = FALSE) = 0; + static BOOL IsLargeObject(MethodTable *mt) { + WRAPPER_NO_CONTRACT; + + return mt->GetBaseSize() >= LARGE_OBJECT_SIZE; + } + static unsigned GetMaxGeneration() { LIMITED_METHOD_DAC_CONTRACT; return max_generation; diff --git a/src/Native/gc/gcpriv.h b/src/Native/gc/gcpriv.h index 78d4e93d7..7f56b49b9 100644 --- a/src/Native/gc/gcpriv.h +++ b/src/Native/gc/gcpriv.h @@ -1343,6 +1343,11 @@ public: PER_HEAP BOOL is_mark_set (uint8_t* o); +#ifdef FEATURE_BASICFREEZE + PER_HEAP_ISOLATED + bool frozen_object_p(Object* obj); +#endif // FEATURE_BASICFREEZE + protected: PER_HEAP @@ -1814,7 +1819,11 @@ protected: PER_HEAP void mark_array_clear_marked (uint8_t* add); PER_HEAP - void clear_mark_array (uint8_t* from, uint8_t* end, BOOL check_only=TRUE); + void clear_mark_array (uint8_t* from, uint8_t* end, BOOL check_only=TRUE +#ifdef FEATURE_BASICFREEZE + , BOOL read_only=FALSE +#endif // FEATURE_BASICFREEZE + ); #ifdef BACKGROUND_GC PER_HEAP void seg_clear_mark_array_bits_soh (heap_segment* seg); |