summaryrefslogtreecommitdiff
path: root/src/vm/gchelpers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/gchelpers.cpp')
-rw-r--r--src/vm/gchelpers.cpp89
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