From 068e52802c3bc3e9f6ecdeb02ec627157b9e28b9 Mon Sep 17 00:00:00 2001 From: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Fri, 21 Jul 2023 23:53:06 +0300 Subject: [PATCH] Upstream some changes to portable allocation helpers (#89269) --- src/coreclr/nativeaot/Runtime/portable.cpp | 175 +++++++++-------------------- 1 file changed, 50 insertions(+), 125 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/portable.cpp b/src/coreclr/nativeaot/Runtime/portable.cpp index 25eb948..d45b3d0 100644 --- a/src/coreclr/nativeaot/Runtime/portable.cpp +++ b/src/coreclr/nativeaot/Runtime/portable.cpp @@ -37,15 +37,21 @@ #if defined(USE_PORTABLE_HELPERS) EXTERN_C NATIVEAOT_API void* REDHAWK_CALLCONV RhpGcAlloc(MethodTable *pEEType, uint32_t uFlags, uintptr_t numElements, void * pTransitionFrame); +static Object* AllocateObject(MethodTable* pEEType, uint32_t uFlags, uintptr_t numElements) +{ + Object* pObject = (Object*)RhpGcAlloc(pEEType, uFlags, numElements, nullptr); + if (pObject == nullptr) + { + ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw OOM + } + + return pObject; +} + struct gc_alloc_context { - uint8_t* alloc_ptr; - uint8_t* alloc_limit; - __int64 alloc_bytes; //Number of bytes allocated on SOH by this context - __int64 alloc_bytes_loh; //Number of bytes allocated on LOH by this context - void* gc_reserved_1; - void* gc_reserved_2; - int alloc_count; + uint8_t* alloc_ptr; + uint8_t* alloc_limit; }; // @@ -57,8 +63,6 @@ COOP_PINVOKE_HELPER(Object *, RhpNewFast, (MethodTable* pEEType)) Thread * pCurThread = ThreadStore::GetCurrentThread(); gc_alloc_context * acontext = pCurThread->GetAllocContext(); - Object * pObject; - size_t size = pEEType->get_BaseSize(); uint8_t* alloc_ptr = acontext->alloc_ptr; @@ -66,18 +70,12 @@ COOP_PINVOKE_HELPER(Object *, RhpNewFast, (MethodTable* pEEType)) if ((size_t)(acontext->alloc_limit - alloc_ptr) >= size) { acontext->alloc_ptr = alloc_ptr + size; - pObject = (Object *)alloc_ptr; + Object* pObject = (Object *)alloc_ptr; pObject->set_EEType(pEEType); return pObject; } - pObject = (Object *)RhpGcAlloc(pEEType, 0, size, NULL); - if (pObject == nullptr) - { - ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw OOM - } - - return pObject; + return AllocateObject(pEEType, 0, 0); } #define GC_ALLOC_FINALIZE 0x1 // TODO: Defined in gc.h @@ -87,70 +85,44 @@ COOP_PINVOKE_HELPER(Object *, RhpNewFast, (MethodTable* pEEType)) COOP_PINVOKE_HELPER(Object *, RhpNewFinalizable, (MethodTable* pEEType)) { ASSERT(pEEType->HasFinalizer()); - - size_t size = pEEType->get_BaseSize(); - - Object * pObject = (Object *)RhpGcAlloc(pEEType, GC_ALLOC_FINALIZE, size, NULL); - if (pObject == nullptr) - { - ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw OOM - } - - return pObject; + return AllocateObject(pEEType, GC_ALLOC_FINALIZE, 0); } COOP_PINVOKE_HELPER(Array *, RhpNewArray, (MethodTable * pArrayEEType, int numElements)) { Thread * pCurThread = ThreadStore::GetCurrentThread(); gc_alloc_context * acontext = pCurThread->GetAllocContext(); - Array * pObject; if (numElements < 0) { ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw overflow } - size_t size; #ifndef HOST_64BIT // if the element count is <= 0x10000, no overflow is possible because the component size is // <= 0xffff, and thus the product is <= 0xffff0000, and the base size is only ~12 bytes if (numElements > 0x10000) { - // Perform the size computation using 64-bit integeres to detect overflow - uint64_t size64 = (uint64_t)pArrayEEType->get_BaseSize() + ((uint64_t)numElements * (uint64_t)pArrayEEType->RawGetComponentSize()); - size64 = (size64 + (sizeof(uintptr_t)-1)) & ~(sizeof(uintptr_t)-1); - - size = (size_t)size64; - if (size != size64) - { - ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw overflow - } + // Overflow here should result in an OOM. Let the slow path take care of it. + return (Array*)AllocateObject(pArrayEEType, 0, numElements); } - else #endif // !HOST_64BIT - { - size = (size_t)pArrayEEType->get_BaseSize() + ((size_t)numElements * (size_t)pArrayEEType->RawGetComponentSize()); - size = ALIGN_UP(size, sizeof(uintptr_t)); - } + + size_t size = (size_t)pArrayEEType->get_BaseSize() + ((size_t)numElements * (size_t)pArrayEEType->RawGetComponentSize()); + size = ALIGN_UP(size, sizeof(uintptr_t)); uint8_t* alloc_ptr = acontext->alloc_ptr; ASSERT(alloc_ptr <= acontext->alloc_limit); if ((size_t)(acontext->alloc_limit - alloc_ptr) >= size) { acontext->alloc_ptr = alloc_ptr + size; - pObject = (Array *)alloc_ptr; + Array* pObject = (Array*)alloc_ptr; pObject->set_EEType(pArrayEEType); pObject->InitArrayLength((uint32_t)numElements); return pObject; } - pObject = (Array *)RhpGcAlloc(pArrayEEType, 0, size, NULL); - if (pObject == nullptr) - { - ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw OOM - } - - return pObject; + return (Array*)AllocateObject(pArrayEEType, 0, numElements); } COOP_PINVOKE_HELPER(String *, RhNewString, (MethodTable * pArrayEEType, int numElements)) @@ -168,37 +140,28 @@ GPTR_DECL(MethodTable, g_pFreeObjectEEType); COOP_PINVOKE_HELPER(Object *, RhpNewFinalizableAlign8, (MethodTable* pEEType)) { - Object * pObject = nullptr; - /* Not reachable as finalizable types are never align8 */ ASSERT_UNCONDITIONALLY("UNREACHABLE"); - return pObject; + return AllocateObject(pEEType, GC_ALLOC_FINALIZE | GC_ALLOC_ALIGN8, 0); } #ifndef HOST_64BIT -COOP_PINVOKE_HELPER(Object *, RhpNewFastAlign8, (MethodTable* pEEType)) +COOP_PINVOKE_HELPER(Object*, RhpNewFastAlign8, (MethodTable* pEEType)) { ASSERT(!pEEType->HasFinalizer()); Thread* pCurThread = ThreadStore::GetCurrentThread(); gc_alloc_context* acontext = pCurThread->GetAllocContext(); - Object* pObject; size_t size = pEEType->get_BaseSize(); size = (size + (sizeof(uintptr_t) - 1)) & ~(sizeof(uintptr_t) - 1); - uint8_t* result = acontext->alloc_ptr; - - int requiresPadding = ((uint32_t)result) & 7; + uint8_t* alloc_ptr = acontext->alloc_ptr; + int requiresPadding = ((uint32_t)alloc_ptr) & 7; size_t paddedSize = size; if (requiresPadding) { - if(paddedSize > SIZE_MAX - 12) - { - ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw overflow - } paddedSize += 12; } - uint8_t* alloc_ptr = acontext->alloc_ptr; ASSERT(alloc_ptr <= acontext->alloc_limit); if ((size_t)(acontext->alloc_limit - alloc_ptr) >= paddedSize) { @@ -207,42 +170,31 @@ COOP_PINVOKE_HELPER(Object *, RhpNewFastAlign8, (MethodTable* pEEType)) { Object* dummy = (Object*)alloc_ptr; dummy->set_EEType(g_pFreeObjectEEType); - alloc_ptr += 12; // if result + paddedSize was ok, then cant overflow + alloc_ptr += 12; } - pObject = (Object *)alloc_ptr; + Object* pObject = (Object *)alloc_ptr; pObject->set_EEType(pEEType); return pObject; } - pObject = (Object*)RhpGcAlloc(pEEType, GC_ALLOC_ALIGN8, size, NULL); - if (pObject == nullptr) - { - ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw OOM - } - - return pObject; + return AllocateObject(pEEType, GC_ALLOC_ALIGN8, 0); } COOP_PINVOKE_HELPER(Object*, RhpNewFastMisalign, (MethodTable* pEEType)) { Thread* pCurThread = ThreadStore::GetCurrentThread(); gc_alloc_context* acontext = pCurThread->GetAllocContext(); - Object* pObject; size_t size = pEEType->get_BaseSize(); - uint8_t* result = acontext->alloc_ptr; - int requiresPadding = (((uint32_t)result) & 7) != 4; + uint8_t* alloc_ptr = acontext->alloc_ptr; + int requiresPadding = (((uint32_t)alloc_ptr) & 7) != 4; size_t paddedSize = size; if (requiresPadding) { - if(paddedSize > SIZE_MAX - 12) - { - ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw overflow - } paddedSize += 12; } - uint8_t* alloc_ptr = acontext->alloc_ptr; + ASSERT(alloc_ptr <= acontext->alloc_limit); if ((size_t)(acontext->alloc_limit - alloc_ptr) >= paddedSize) { @@ -251,67 +203,46 @@ COOP_PINVOKE_HELPER(Object*, RhpNewFastMisalign, (MethodTable* pEEType)) { Object* dummy = (Object*)alloc_ptr; dummy->set_EEType(g_pFreeObjectEEType); - alloc_ptr += 12; // if result + paddedSize was ok, then cant overflow + alloc_ptr += 12; } - pObject = (Object *)alloc_ptr; + Object* pObject = (Object *)alloc_ptr; pObject->set_EEType(pEEType); return pObject; } - pObject = (Object*)RhpGcAlloc(pEEType, GC_ALLOC_ALIGN8 | GC_ALLOC_ALIGN8_BIAS, size, NULL); - if (pObject == nullptr) - { - ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw OOM - } - - return pObject; + return AllocateObject(pEEType, GC_ALLOC_ALIGN8 | GC_ALLOC_ALIGN8_BIAS, 0); } -COOP_PINVOKE_HELPER(Array *, RhpNewArrayAlign8, (MethodTable * pArrayEEType, int numElements)) +COOP_PINVOKE_HELPER(Array*, RhpNewArrayAlign8, (MethodTable* pArrayEEType, int numElements)) { Thread* pCurThread = ThreadStore::GetCurrentThread(); gc_alloc_context* acontext = pCurThread->GetAllocContext(); - Array* pObject; if (numElements < 0) { ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw overflow } - size_t size; - - uint32_t baseSize = pArrayEEType->get_BaseSize(); // if the element count is <= 0x10000, no overflow is possible because the component size is // <= 0xffff, and thus the product is <= 0xffff0000, and the base size is only ~12 bytes if (numElements > 0x10000) { - // Perform the size computation using 64-bit integeres to detect overflow - uint64_t size64 = (uint64_t)baseSize + ((uint64_t)numElements * (uint64_t)pArrayEEType->RawGetComponentSize()); - size64 = (size64 + (sizeof(uintptr_t) - 1)) & ~(sizeof(uintptr_t) - 1); - - size = (size_t)size64; - if (size != size64) - { - ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw overflow - } - } - else - { - size = (size_t)baseSize + ((size_t)numElements * (size_t)pArrayEEType->RawGetComponentSize()); - size = ALIGN_UP(size, sizeof(uintptr_t)); + // Overflow here should result in an OOM. Let the slow path take care of it. + return (Array*)AllocateObject(pArrayEEType, GC_ALLOC_ALIGN8, numElements); } - uint8_t* result = acontext->alloc_ptr; - int requiresAlignObject = ((uint32_t)result) & 7; + + uint32_t baseSize = pArrayEEType->get_BaseSize(); + size_t size = (size_t)baseSize + ((size_t)numElements * (size_t)pArrayEEType->RawGetComponentSize()); + size = ALIGN_UP(size, sizeof(uintptr_t)); + + uint8_t* alloc_ptr = acontext->alloc_ptr; + int requiresAlignObject = ((uint32_t)alloc_ptr) & 7; size_t paddedSize = size; if (requiresAlignObject) { - if(paddedSize > SIZE_MAX - 12) - { - ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw overflow - } paddedSize += 12; } - uint8_t* alloc_ptr = acontext->alloc_ptr; + ASSERT(alloc_ptr <= acontext->alloc_limit); if ((size_t)(acontext->alloc_limit - alloc_ptr) >= paddedSize) { @@ -320,21 +251,15 @@ COOP_PINVOKE_HELPER(Array *, RhpNewArrayAlign8, (MethodTable * pArrayEEType, int { Object* dummy = (Object*)alloc_ptr; dummy->set_EEType(g_pFreeObjectEEType); - alloc_ptr += 12; // if result + paddedSize was ok, then cant overflow + alloc_ptr += 12; } - pObject = (Array*)alloc_ptr; + Array* pObject = (Array*)alloc_ptr; pObject->set_EEType(pArrayEEType); pObject->InitArrayLength((uint32_t)numElements); return pObject; } - pObject = (Array*)RhpGcAlloc(pArrayEEType, GC_ALLOC_ALIGN8, size, NULL); - if (pObject == nullptr) - { - ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw OOM - } - - return pObject; + return (Array*)AllocateObject(pArrayEEType, GC_ALLOC_ALIGN8, numElements); } #endif // !HOST_64BIT #endif // defined(HOST_ARM) || defined(HOST_WASM) -- 2.7.4