diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index bf7d5a07c12b2..d7603e6ad416e 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -33324,6 +33324,9 @@ void gc_heap::walk_relocation (void* profiling_context, record_surv_fn fn) int condemned_gen_number = settings.condemned_generation; int stop_gen_idx = get_stop_generation_index (condemned_gen_number); + reset_pinned_queue_bos(); + update_oldest_pinned_plug(); + for (int i = condemned_gen_number; i >= stop_gen_idx; i--) { generation* condemned_gen = generation_of (i); @@ -33337,9 +33340,6 @@ void gc_heap::walk_relocation (void* profiling_context, record_surv_fn fn) size_t current_brick = brick_of (start_address); PREFIX_ASSUME(current_heap_segment != NULL); - - reset_pinned_queue_bos(); - update_oldest_pinned_plug(); size_t end_brick = brick_of (heap_segment_allocated (current_heap_segment)-1); walk_relocate_args args; args.is_shortened = FALSE; diff --git a/src/coreclr/gc/gcee.cpp b/src/coreclr/gc/gcee.cpp index 3c07a0745866e..745aefccb69f8 100644 --- a/src/coreclr/gc/gcee.cpp +++ b/src/coreclr/gc/gcee.cpp @@ -450,6 +450,9 @@ segment_handle GCHeap::RegisterFrozenSegment(segment_info *pseginfo) heap_segment_next(seg) = 0; heap_segment_used(seg) = heap_segment_allocated(seg); heap_segment_plan_allocated(seg) = 0; +#ifdef USE_REGIONS + heap_segment_gen_num(seg) = max_generation; +#endif //USE_REGIONS seg->flags = heap_segment_flags_readonly; #ifdef MULTIPLE_HEAPS diff --git a/src/coreclr/vm/frozenobjectheap.cpp b/src/coreclr/vm/frozenobjectheap.cpp index 5767a15bc3a14..20c767ced81f8 100644 --- a/src/coreclr/vm/frozenobjectheap.cpp +++ b/src/coreclr/vm/frozenobjectheap.cpp @@ -18,7 +18,7 @@ FrozenObjectHeapManager::FrozenObjectHeapManager(): // Allocates an object of the give size (including header) on a frozen segment. // May return nullptr if object is too large (larger than FOH_COMMIT_SIZE) // in such cases caller is responsible to find a more appropriate heap to allocate it -Object* FrozenObjectHeapManager::TryAllocateObject(PTR_MethodTable type, size_t objectSize) +Object* FrozenObjectHeapManager::TryAllocateObject(PTR_MethodTable type, size_t objectSize, bool publish) { CONTRACTL { @@ -32,51 +32,59 @@ Object* FrozenObjectHeapManager::TryAllocateObject(PTR_MethodTable type, size_t return nullptr; #else // FEATURE_BASICFREEZE - CrstHolder ch(&m_Crst); + Object* obj = nullptr; + { + CrstHolder ch(&m_Crst); - _ASSERT(type != nullptr); - _ASSERT(FOH_COMMIT_SIZE >= MIN_OBJECT_SIZE); + _ASSERT(type != nullptr); + _ASSERT(FOH_COMMIT_SIZE >= MIN_OBJECT_SIZE); -#ifdef FEATURE_64BIT_ALIGNMENT - _ASSERT(!type->RequiresAlign8()); -#endif + #ifdef FEATURE_64BIT_ALIGNMENT + _ASSERT(!type->RequiresAlign8()); + #endif - // NOTE: objectSize is expected be the full size including header - _ASSERT(objectSize >= MIN_OBJECT_SIZE); + // NOTE: objectSize is expected be the full size including header + _ASSERT(objectSize >= MIN_OBJECT_SIZE); - if (objectSize > FOH_COMMIT_SIZE) - { - // The current design doesn't allow objects larger than FOH_COMMIT_SIZE and - // since FrozenObjectHeap is just an optimization, let's not fill it with huge objects. - return nullptr; - } + if (objectSize > FOH_COMMIT_SIZE) + { + // The current design doesn't allow objects larger than FOH_COMMIT_SIZE and + // since FrozenObjectHeap is just an optimization, let's not fill it with huge objects. + return nullptr; + } - if (m_CurrentSegment == nullptr) - { - // Create the first segment on first allocation - m_CurrentSegment = new FrozenObjectSegment(FOH_SEGMENT_DEFAULT_SIZE); - m_FrozenSegments.Append(m_CurrentSegment); - _ASSERT(m_CurrentSegment != nullptr); - } + if (m_CurrentSegment == nullptr) + { + // Create the first segment on first allocation + m_CurrentSegment = new FrozenObjectSegment(FOH_SEGMENT_DEFAULT_SIZE); + m_FrozenSegments.Append(m_CurrentSegment); + _ASSERT(m_CurrentSegment != nullptr); + } - Object* obj = m_CurrentSegment->TryAllocateObject(type, objectSize); + obj = m_CurrentSegment->TryAllocateObject(type, objectSize); - // The only case where it can be null is when the current segment is full and we need - // to create a new one - if (obj == nullptr) - { - // Double the reserved size to reduce the number of frozen segments in apps with lots of frozen objects - // Use the same size in case if prevSegmentSize*2 operation overflows. - size_t prevSegmentSize = m_CurrentSegment->GetSize(); - m_CurrentSegment = new FrozenObjectSegment(max(prevSegmentSize, prevSegmentSize * 2)); - m_FrozenSegments.Append(m_CurrentSegment); + // The only case where it can be null is when the current segment is full and we need + // to create a new one + if (obj == nullptr) + { + // Double the reserved size to reduce the number of frozen segments in apps with lots of frozen objects + // Use the same size in case if prevSegmentSize*2 operation overflows. + size_t prevSegmentSize = m_CurrentSegment->GetSize(); + m_CurrentSegment = new FrozenObjectSegment(max(prevSegmentSize, prevSegmentSize * 2)); + m_FrozenSegments.Append(m_CurrentSegment); - // Try again - obj = m_CurrentSegment->TryAllocateObject(type, objectSize); + // Try again + obj = m_CurrentSegment->TryAllocateObject(type, objectSize); - // This time it's not expected to be null - _ASSERT(obj != nullptr); + // This time it's not expected to be null + _ASSERT(obj != nullptr); + } + } + if (publish) + { + PublishFrozenObject(obj); } + return obj; #endif // !FEATURE_BASICFREEZE } diff --git a/src/coreclr/vm/frozenobjectheap.h b/src/coreclr/vm/frozenobjectheap.h index 35fc7c00332f6..f62d37678a785 100644 --- a/src/coreclr/vm/frozenobjectheap.h +++ b/src/coreclr/vm/frozenobjectheap.h @@ -27,7 +27,7 @@ class FrozenObjectHeapManager { public: FrozenObjectHeapManager(); - Object* TryAllocateObject(PTR_MethodTable type, size_t objectSize); + Object* TryAllocateObject(PTR_MethodTable type, size_t objectSize, bool publish = true); private: Crst m_Crst; diff --git a/src/coreclr/vm/gchelpers.cpp b/src/coreclr/vm/gchelpers.cpp index e09f4c9345cd6..cccf11914aad2 100644 --- a/src/coreclr/vm/gchelpers.cpp +++ b/src/coreclr/vm/gchelpers.cpp @@ -342,6 +342,11 @@ void PublishObjectAndNotify(TObj* &orObject, GC_ALLOC_FLAGS flags) #endif // FEATURE_EVENT_TRACE } +void PublishFrozenObject(Object*& orObject) +{ + PublishObjectAndNotify(orObject, GC_ALLOC_NO_FLAGS); +} + inline SIZE_T MaxArrayLength() { // Impose limits on maximum array length to prevent corner case integer overflow bugs @@ -886,10 +891,12 @@ STRINGREF AllocateString(DWORD cchStringLength, bool preferFrozenHeap, bool* pIs if (preferFrozenHeap) { FrozenObjectHeapManager* foh = SystemDomain::GetFrozenObjectHeapManager(); - orString = static_cast(foh->TryAllocateObject(g_pStringClass, totalSize)); + orString = static_cast(foh->TryAllocateObject(g_pStringClass, totalSize, /* publish = */false)); if (orString != nullptr) { orString->SetStringLength(cchStringLength); + // Publish needs to be postponed in this case because we need to specify string length + PublishObjectAndNotify(orString, GC_ALLOC_NO_FLAGS); _ASSERTE(orString->GetBuffer()[cchStringLength] == W('\0')); orStringRef = ObjectToSTRINGREF(orString); *pIsFrozen = true; diff --git a/src/coreclr/vm/gchelpers.h b/src/coreclr/vm/gchelpers.h index d861f33a34f75..3a0382f6f6bb6 100644 --- a/src/coreclr/vm/gchelpers.h +++ b/src/coreclr/vm/gchelpers.h @@ -68,4 +68,7 @@ extern void ThrowOutOfMemoryDimensionsExceeded(); void ErectWriteBarrier(OBJECTREF* dst, OBJECTREF ref); void SetCardsAfterBulkCopy(Object **start, size_t len); + +void PublishFrozenObject(Object*& orObject); + #endif // _GCHELPERS_H_