Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 50 additions & 125 deletions src/coreclr/nativeaot/Runtime/portable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

//
Expand All @@ -57,27 +63,19 @@ 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;
ASSERT(alloc_ptr <= acontext->alloc_limit);
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
Expand All @@ -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))
Expand All @@ -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)
{
Expand All @@ -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)
{
Expand All @@ -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)
{
Expand All @@ -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)
Expand Down