diff options
Diffstat (limited to 'src/vm/gchelpers.cpp')
-rw-r--r-- | src/vm/gchelpers.cpp | 89 |
1 files changed, 73 insertions, 16 deletions
diff --git a/src/vm/gchelpers.cpp b/src/vm/gchelpers.cpp index bf81847716..20a3a29540 100644 --- a/src/vm/gchelpers.cpp +++ b/src/vm/gchelpers.cpp @@ -16,7 +16,7 @@ #include "threads.h" #include "eetwain.h" #include "eeconfig.h" -#include "gc.h" +#include "gcheaputilities.h" #include "corhost.h" #include "threads.h" #include "fieldmarshaler.h" @@ -51,15 +51,50 @@ orObject = (ArrayBase *) OBJECTREFToObject(objref); -inline alloc_context* GetThreadAllocContext() +inline gc_alloc_context* GetThreadAllocContext() { WRAPPER_NO_CONTRACT; - assert(GCHeap::UseAllocationContexts()); + assert(GCHeapUtilities::UseAllocationContexts()); return & GetThread()->m_alloc_context; } +// Checks to see if the given allocation size exceeds the +// largest object size allowed - if it does, it throws +// an OutOfMemoryException with a message indicating that +// the OOM was not from memory pressure but from an object +// being too large. +inline void CheckObjectSize(size_t alloc_size) +{ + CONTRACTL { + THROWS; + GC_TRIGGERS; + } CONTRACTL_END; + + size_t max_object_size; +#ifdef BIT64 + if (g_pConfig->GetGCAllowVeryLargeObjects()) + { + max_object_size = (INT64_MAX - 7 - min_obj_size); + } + else +#endif // BIT64 + { + max_object_size = (INT32_MAX - 7 - min_obj_size); + } + + if (alloc_size >= max_object_size) + { + if (g_pConfig->IsGCBreakOnOOMEnabled()) + { + DebugBreak(); + } + + ThrowOutOfMemoryDimensionsExceeded(); + } +} + // There are only three ways to get into allocate an object. // * Call optimized helpers that were generated on the fly. This is how JIT compiled code does most @@ -98,14 +133,21 @@ inline Object* Alloc(size_t size, BOOL bFinalize, BOOL bContainsPointers ) (bFinalize ? GC_ALLOC_FINALIZE : 0)); Object *retVal = NULL; + CheckObjectSize(size); // We don't want to throw an SO during the GC, so make sure we have plenty // of stack before calling in. INTERIOR_STACK_PROBE_FOR(GetThread(), static_cast<unsigned>(DEFAULT_ENTRY_PROBE_AMOUNT * 1.5)); - if (GCHeap::UseAllocationContexts()) - retVal = GCHeap::GetGCHeap()->Alloc(GetThreadAllocContext(), size, flags); + if (GCHeapUtilities::UseAllocationContexts()) + retVal = GCHeapUtilities::GetGCHeap()->Alloc(GetThreadAllocContext(), size, flags); else - retVal = GCHeap::GetGCHeap()->Alloc(size, flags); + retVal = GCHeapUtilities::GetGCHeap()->Alloc(size, flags); + + if (!retVal) + { + ThrowOutOfMemory(); + } + END_INTERIOR_STACK_PROBE; return retVal; } @@ -126,14 +168,20 @@ inline Object* AllocAlign8(size_t size, BOOL bFinalize, BOOL bContainsPointers, (bAlignBias ? GC_ALLOC_ALIGN8_BIAS : 0)); Object *retVal = NULL; + CheckObjectSize(size); // We don't want to throw an SO during the GC, so make sure we have plenty // of stack before calling in. INTERIOR_STACK_PROBE_FOR(GetThread(), static_cast<unsigned>(DEFAULT_ENTRY_PROBE_AMOUNT * 1.5)); - if (GCHeap::UseAllocationContexts()) - retVal = GCHeap::GetGCHeap()->AllocAlign8(GetThreadAllocContext(), size, flags); + if (GCHeapUtilities::UseAllocationContexts()) + retVal = GCHeapUtilities::GetGCHeap()->AllocAlign8(GetThreadAllocContext(), size, flags); else - retVal = GCHeap::GetGCHeap()->AllocAlign8(size, flags); + retVal = GCHeapUtilities::GetGCHeap()->AllocAlign8(size, flags); + + if (!retVal) + { + ThrowOutOfMemory(); + } END_INTERIOR_STACK_PROBE; return retVal; @@ -169,11 +217,18 @@ inline Object* AllocLHeap(size_t size, BOOL bFinalize, BOOL bContainsPointers ) (bFinalize ? GC_ALLOC_FINALIZE : 0)); Object *retVal = NULL; + CheckObjectSize(size); // We don't want to throw an SO during the GC, so make sure we have plenty // of stack before calling in. INTERIOR_STACK_PROBE_FOR(GetThread(), static_cast<unsigned>(DEFAULT_ENTRY_PROBE_AMOUNT * 1.5)); - retVal = GCHeap::GetGCHeap()->AllocLHeap(size, flags); + retVal = GCHeapUtilities::GetGCHeap()->AllocLHeap(size, flags); + + if (!retVal) + { + ThrowOutOfMemory(); + } + END_INTERIOR_STACK_PROBE; return retVal; } @@ -427,7 +482,7 @@ OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, B if (bAllocateInLargeHeap || (totalSize >= LARGE_OBJECT_SIZE)) { - GCHeap::GetGCHeap()->PublishObject((BYTE*)orArray); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orArray); } #ifdef _LOGALLOC @@ -651,7 +706,7 @@ OBJECTREF FastAllocatePrimitiveArray(MethodTable* pMT, DWORD cElements, BOOL b if (bPublish) { - GCHeap::GetGCHeap()->PublishObject((BYTE*)orObject); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject); } // Notify the profiler of the allocation @@ -860,7 +915,7 @@ STRINGREF SlowAllocateString( DWORD cchStringLength ) if (ObjectSize >= LARGE_OBJECT_SIZE) { - GCHeap::GetGCHeap()->PublishObject((BYTE*)orObject); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject); } // Notify the profiler of the allocation @@ -951,8 +1006,10 @@ OBJECTREF AllocateObject(MethodTable *pMT g_IBCLogger.LogMethodTableAccess(pMT); SetTypeHandleOnThreadForAlloc(TypeHandle(pMT)); +#ifdef FEATURE_CER if (pMT->HasCriticalFinalizer()) PrepareCriticalFinalizerObject(pMT); +#endif #ifdef FEATURE_COMINTEROP #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION @@ -1000,7 +1057,7 @@ OBJECTREF AllocateObject(MethodTable *pMT if ((baseSize >= LARGE_OBJECT_SIZE)) { orObject->SetMethodTableForLargeObject(pMT); - GCHeap::GetGCHeap()->PublishObject((BYTE*)orObject); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject); } else { @@ -1234,7 +1291,7 @@ extern "C" HCIMPL2_RAW(VOID, JIT_WriteBarrier, Object **dst, Object *ref) *dst = ref; // If the store above succeeded, "dst" should be in the heap. - assert(GCHeap::GetGCHeap()->IsHeapPointer((void*)dst)); + assert(GCHeapUtilities::GetGCHeap()->IsHeapPointer((void*)dst)); #ifdef WRITE_BARRIER_CHECK updateGCShadow(dst, ref); // support debugging write barrier @@ -1280,7 +1337,7 @@ extern "C" HCIMPL2_RAW(VOID, JIT_WriteBarrierEnsureNonHeapTarget, Object **dst, STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_NOTRIGGER; - assert(!GCHeap::GetGCHeap()->IsHeapPointer((void*)dst)); + assert(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((void*)dst)); // no HELPER_METHOD_FRAME because we are MODE_COOPERATIVE, GC_NOTRIGGER |