#endif //BACKGROUND_GC
#endif // MARK_ARRAY
- size_t maxObjectSize = (INT32_MAX - 7 - Align(min_obj_size));
-
-#ifdef BIT64
- if (g_pConfig->GetGCAllowVeryLargeObjects())
- {
- maxObjectSize = (INT64_MAX - 7 - Align(min_obj_size));
- }
-#endif
-
- if (jsize >= maxObjectSize)
- {
- if (g_pConfig->IsGCBreakOnOOMEnabled())
- {
- GCToOSInterface::DebugBreak();
- }
-
-#ifndef FEATURE_REDHAWK
- ThrowOutOfMemoryDimensionsExceeded();
-#else
- return 0;
-#endif
- }
+ // these next few lines are not strictly necessary anymore - they are here
+ // to sanity check that we didn't get asked to create an object
+ // that's too large.
+ #if BIT64
+ size_t maxObjectSize = (INT64_MAX - 7 - Align(min_obj_size));
+ #else
+ size_t maxObjectSize = (INT32_MAX - 7 - Align(min_obj_size));
+ #endif
+
+ // The VM should have thrown instead of passing us an allocation
+ // request that's too large.
+ assert(jsize < maxObjectSize);
size_t size = AlignQword (jsize);
int align_const = get_alignment_constant (FALSE);
#define REGISTER_FOR_FINALIZATION(_object, _size) true
#endif // FEATURE_PREMORTEM_FINALIZATION
-#ifdef FEATURE_REDHAWK
#define CHECK_ALLOC_AND_POSSIBLY_REGISTER_FOR_FINALIZATION(_object, _size, _register) do { \
if ((_object) == NULL || ((_register) && !REGISTER_FOR_FINALIZATION(_object, _size))) \
{ \
return NULL; \
} \
} while (false)
-#else // FEATURE_REDHAWK
-#define CHECK_ALLOC_AND_POSSIBLY_REGISTER_FOR_FINALIZATION(_object, _size, _register) do { \
- if ((_object) == NULL) \
- { \
- STRESS_LOG_OOM_STACK(_size); \
- ThrowOutOfMemory(); \
- } \
- if (_register) \
- { \
- REGISTER_FOR_FINALIZATION(_object, _size); \
- } \
-} while (false)
-#endif // FEATURE_REDHAWK
//
// Small Object Allocator
GCHeap::Alloc( size_t size, uint32_t flags REQD_ALIGN_DCL)
{
CONTRACTL {
-#ifdef FEATURE_REDHAWK
- // Under Redhawk NULL is returned on failure.
NOTHROW;
-#else
- THROWS;
-#endif
GC_TRIGGERS;
} CONTRACTL_END;
-#if defined(_DEBUG) && !defined(FEATURE_REDHAWK)
- if (g_pConfig->ShouldInjectFault(INJECTFAULT_GCHEAP))
- {
- char *a = new char;
- delete a;
- }
-#endif //_DEBUG && !FEATURE_REDHAWK
-
TRIGGERSGC();
Object* newAlloc = NULL;
{
#ifdef FEATURE_64BIT_ALIGNMENT
CONTRACTL {
-#ifdef FEATURE_REDHAWK
- // Under Redhawk NULL is returned on failure.
NOTHROW;
-#else
- THROWS;
-#endif
GC_TRIGGERS;
} CONTRACTL_END;
{
#ifdef FEATURE_64BIT_ALIGNMENT
CONTRACTL {
-#ifdef FEATURE_REDHAWK
- // Under Redhawk NULL is returned on failure.
NOTHROW;
-#else
- THROWS;
-#endif
GC_TRIGGERS;
} CONTRACTL_END;
{
#ifdef FEATURE_64BIT_ALIGNMENT
CONTRACTL {
-#ifdef FEATURE_REDHAWK
- // Under Redhawk NULL is returned on failure.
NOTHROW;
-#else
- THROWS;
-#endif
GC_TRIGGERS;
} CONTRACTL_END;
gc_heap* hp = (gc_heap*)_hp;
-#if defined(_DEBUG) && !defined(FEATURE_REDHAWK)
- if (g_pConfig->ShouldInjectFault(INJECTFAULT_GCHEAP))
- {
- char *a = new char;
- delete a;
- }
-#endif //_DEBUG && !FEATURE_REDHAWK
-
TRIGGERSGC();
Object* newAlloc = NULL;
GCHeap::AllocLHeap( size_t size, uint32_t flags REQD_ALIGN_DCL)
{
CONTRACTL {
-#ifdef FEATURE_REDHAWK
- // Under Redhawk NULL is returned on failure.
NOTHROW;
-#else
- THROWS;
-#endif
GC_TRIGGERS;
} CONTRACTL_END;
-#if defined(_DEBUG) && !defined(FEATURE_REDHAWK)
- if (g_pConfig->ShouldInjectFault(INJECTFAULT_GCHEAP))
- {
- char *a = new char;
- delete a;
- }
-#endif //_DEBUG && !FEATURE_REDHAWK
-
TRIGGERSGC();
Object* newAlloc = NULL;
GCHeap::Alloc(gc_alloc_context* context, size_t size, uint32_t flags REQD_ALIGN_DCL)
{
CONTRACTL {
-#ifdef FEATURE_REDHAWK
- // Under Redhawk NULL is returned on failure.
NOTHROW;
-#else
- THROWS;
-#endif
GC_TRIGGERS;
} CONTRACTL_END;
-#if defined(_DEBUG) && !defined(FEATURE_REDHAWK)
- if (g_pConfig->ShouldInjectFault(INJECTFAULT_GCHEAP))
- {
- char *a = new char;
- delete a;
- }
-#endif //_DEBUG && !FEATURE_REDHAWK
-
TRIGGERSGC();
Object* newAlloc = NULL;
CFinalize::RegisterForFinalization (int gen, Object* obj, size_t size)
{
CONTRACTL {
-#ifdef FEATURE_REDHAWK
- // Under Redhawk false is returned on failure.
NOTHROW;
-#else
- THROWS;
-#endif
GC_NOTRIGGER;
} CONTRACTL_END;
{
GCToOSInterface::DebugBreak();
}
-#ifdef FEATURE_REDHAWK
return false;
-#else
- ThrowOutOfMemory();
-#endif
}
}
Object*** end_si = &SegQueueLimit (dest);
#define LARGE_OBJECT_SIZE ((size_t)(85000))
+// The minimum size of an object is three pointers wide: one for the syncblock,
+// one for the object header, and one for the first field in the object.
+#define min_obj_size ((sizeof(uint8_t*) + sizeof(uintptr_t) + sizeof(size_t)))
+
class Object;
class IGCHeap;
/*
===========================================================================
Allocation routines. These all call into the GC's allocator and may trigger a garbage
- collection.
+ collection. All allocation routines return NULL when the allocation request
+ couldn't be serviced due to being out of memory.
+
+ These allocation routines should not be called with allocation requests
+ larger than:
+ 32-bit -> 0x7FFFFFE0
+ 64-bit -> 0x7FFFFFFFFFFFFFE0
+
+ It is up to the caller of the API to raise appropriate errors if the amount
+ of requested memory is too large.
===========================================================================
*/
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
(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.
retVal = GCHeapUtilities::GetGCHeap()->Alloc(GetThreadAllocContext(), size, flags);
else
retVal = GCHeapUtilities::GetGCHeap()->Alloc(size, flags);
+
+ if (!retVal)
+ {
+ ThrowOutOfMemory();
+ }
+
END_INTERIOR_STACK_PROBE;
return retVal;
}
(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.
else
retVal = GCHeapUtilities::GetGCHeap()->AllocAlign8(size, flags);
+ if (!retVal)
+ {
+ ThrowOutOfMemory();
+ }
+
END_INTERIOR_STACK_PROBE;
return retVal;
}
(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 = GCHeapUtilities::GetGCHeap()->AllocLHeap(size, flags);
+
+ if (!retVal)
+ {
+ ThrowOutOfMemory();
+ }
+
END_INTERIOR_STACK_PROBE;
return retVal;
}