Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
84 changes: 71 additions & 13 deletions src/coreclr/runtime/portable/AllocFast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
//

#include <fcall.h>
#include <gcinterface.h>
#include "../gc/env/gcenv.ee.h"

extern void RhExceptionHandling_FailedAllocation(MethodTable *pMT, bool isOverflow);
EXTERN_C Object* RhpGcAlloc(MethodTable* pMT, uint32_t uFlags, uintptr_t numElements, void * pTransitionFrame);

EXTERN_C FCDECL2(Object*, RhpNewVariableSizeObject, MethodTable* pMT, INT_PTR numElements)
static Object* AllocateObject(MethodTable* pMT, uint32_t uFlags, INT_PTR numElements)
{
Object* obj = RhpGcAlloc(pMT, 0, numElements, nullptr);
Object* obj = RhpGcAlloc(pMT, uFlags, numElements, nullptr);
if (obj == NULL)
{
RhExceptionHandling_FailedAllocation(pMT, false /* isOverflow */);
Expand All @@ -18,7 +20,12 @@ EXTERN_C FCDECL2(Object*, RhpNewVariableSizeObject, MethodTable* pMT, INT_PTR nu
return obj;
}

static Object* _RhpNewArrayFastCore(MethodTable* pMT, INT_PTR size)
EXTERN_C FCDECL2(Object*, RhpNewVariableSizeObject, MethodTable* pMT, INT_PTR numElements)
{
return AllocateObject(pMT, 0, numElements);
}

static Object* NewArrayFastCore(MethodTable* pMT, INT_PTR size)
{
FCALL_CONTRACT;
_ASSERTE(pMT != NULL);
Expand All @@ -41,7 +48,64 @@ static Object* _RhpNewArrayFastCore(MethodTable* pMT, INT_PTR size)
return pObject;
}

return RhpNewVariableSizeObject(pMT, size);
return AllocateObject(pMT, 0, size);
}

static Object* NewArrayFastAlign8Core(MethodTable* pMT, INT_PTR size)
{
FCALL_CONTRACT;
_ASSERTE(pMT != NULL);
_ASSERTE(size < INT32_MAX);

Thread* thread = GetThread();
ee_alloc_context* cxt = thread->GetEEAllocContext();

size_t sizeInBytes = (size_t)pMT->GetBaseSize() + ((size_t)size * (size_t)pMT->RawGetComponentSize());
sizeInBytes = ALIGN_UP(sizeInBytes, sizeof(void*));

uint8_t* alloc_ptr = cxt->getAllocPtr();
int requiresAlignObject = ((uint32_t)alloc_ptr) & 7;
size_t paddedSize = sizeInBytes;
if (requiresAlignObject)
{
paddedSize += 12;
}

ASSERT(alloc_ptr <= cxt->getAllocLimit());
if ((size_t)(cxt->getAllocLimit() - alloc_ptr) >= paddedSize)
{
cxt->setAllocPtr(alloc_ptr + paddedSize);
if (requiresAlignObject)
{
Object* dummy = (Object*)alloc_ptr;
dummy->SetMethodTable(GCToEEInterface::GetFreeObjectMethodTable());
alloc_ptr += 12;
}
PtrArray* pObject = (PtrArray *)alloc_ptr;
pObject->SetMethodTable(pMT);
pObject->SetNumComponents((INT32)size);
return pObject;
}

return AllocateObject(pMT, GC_ALLOC_ALIGN8, size);
}

EXTERN_C FCDECL2(Object*, RhpNewArrayFastAlign8, MethodTable* pMT, INT_PTR size)
{
FCALL_CONTRACT;
_ASSERTE(pMT != NULL);

#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 (size > 0x10000)
{
// Overflow here should result in an OOM. Let the slow path take care of it.
return AllocateObject(pMT, GC_ALLOC_ALIGN8, size);
}
#endif // !HOST_64BIT

return NewArrayFastAlign8Core(pMT, size);
}

EXTERN_C FCDECL2(Object*, RhpNewArrayFast, MethodTable* pMT, INT_PTR size)
Expand All @@ -55,11 +119,11 @@ EXTERN_C FCDECL2(Object*, RhpNewArrayFast, MethodTable* pMT, INT_PTR size)
if (size > 0x10000)
{
// Overflow here should result in an OOM. Let the slow path take care of it.
return RhpNewVariableSizeObject(pMT, size);
return AllocateObject(pMT, 0, size);
}
#endif // !HOST_64BIT

return _RhpNewArrayFastCore(pMT, size);
return NewArrayFastCore(pMT, size);
}

EXTERN_C FCDECL2(Object*, RhpNewPtrArrayFast, MethodTable* pMT, INT_PTR size)
Expand All @@ -74,12 +138,6 @@ EXTERN_C FCDECL1(Object*, RhpNewFast, MethodTable* pMT)
return nullptr;
}

EXTERN_C FCDECL2(Object*, RhpNewArrayFastAlign8, MethodTable* pMT, INT_PTR size)
{
PORTABILITY_ASSERT("RhpNewArrayFastAlign8 is not yet implemented");
return nullptr;
}

EXTERN_C FCDECL1(Object*, RhpNewFastAlign8, MethodTable* pMT)
{
PORTABILITY_ASSERT("RhpNewFastAlign8 is not yet implemented");
Expand All @@ -104,5 +162,5 @@ EXTERN_C FCDECL2(Object*, RhNewString, MethodTable* pMT, INT_PTR stringLength)
RhExceptionHandling_FailedAllocation(pMT, false);
}

return _RhpNewArrayFastCore(pMT, stringLength);
return NewArrayFastCore(pMT, stringLength);
}
28 changes: 10 additions & 18 deletions src/tests/JIT/interpreter/Interpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2517,16 +2517,12 @@ public static bool TestArray()
if (!ArrayUInt32(32, uint.MinValue)) return false;
if (!ArrayUInt32(32, uint.MaxValue)) return false;

// active issue https://github.com/dotnet/runtime/issues/120659
if (RuntimeInformation.ProcessArchitecture != Architecture.Wasm)
{
// // long
if (!ArrayInt64(0, 0)) return false;
if (!ArrayInt64(1, 1)) return false;
if (!ArrayInt64(32, 32)) return false;
if (!ArrayInt64(32, Int64.MinValue)) return false;
if (!ArrayInt64(32, Int64.MaxValue)) return false;
}
// long
if (!ArrayInt64(0, 0)) return false;
if (!ArrayInt64(1, 1)) return false;
if (!ArrayInt64(32, 32)) return false;
if (!ArrayInt64(32, Int64.MinValue)) return false;
if (!ArrayInt64(32, Int64.MaxValue)) return false;

// float
if (!ArrayFloat(0, 0)) return false;
Expand All @@ -2535,14 +2531,10 @@ public static bool TestArray()
if (!ArrayFloat(32, float.MinValue)) return false;
if (!ArrayFloat(32, float.MaxValue)) return false;

// active issue https://github.com/dotnet/runtime/issues/120659
if (RuntimeInformation.ProcessArchitecture != Architecture.Wasm)
{
// double
if (!ArrayDouble(0, 0)) return false;
if (!ArrayDouble(1, 1)) return false;
if (!ArrayDouble(32, 32)) return false;
}
// double
if (!ArrayDouble(0, 0)) return false;
if (!ArrayDouble(1, 1)) return false;
if (!ArrayDouble(32, 32)) return false;

// ref and value types
if (!TestObjectArray()) return false;
Expand Down
Loading