Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2015-12-17 06:33:37 +0300
committerJan Kotas <jkotas@microsoft.com>2015-12-17 06:33:37 +0300
commit015151807b479ab92412cf3d1eb157786650f314 (patch)
tree04b25d72c5f54da1146c39848b163512a9be26c4 /src/Native
parent2f458a1db3e7ce82b24802f0a8372718f625b827 (diff)
parente223e35867c4660fe8423fedb2e547152dd7fd2d (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.h12
-rw-r--r--src/Native/Runtime/AsmOffsetsVerify.cpp2
-rw-r--r--src/Native/Runtime/Crst.h6
-rw-r--r--src/Native/Runtime/eetype.cpp2
-rw-r--r--src/Native/Runtime/gcenv.h2
-rw-r--r--src/Native/Runtime/gcrhenv.cpp22
-rw-r--r--src/Native/Runtime/inc/rhbinder.h8
-rw-r--r--src/Native/Runtime/thread.h9
-rw-r--r--src/Native/gc/gc.cpp130
-rw-r--r--src/Native/gc/gc.h6
-rw-r--r--src/Native/gc/gcpriv.h11
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);