33//
44
55#include < fcall.h>
6+ #include < gcinterface.h>
7+ #include < vars.hpp>
68
79extern void RhExceptionHandling_FailedAllocation (MethodTable *pMT, bool isOverflow);
810EXTERN_C Object* RhpGcAlloc (MethodTable* pMT, uint32_t uFlags, uintptr_t numElements, void * pTransitionFrame);
911
10- EXTERN_C FCDECL2 ( Object*, RhpNewVariableSizeObject, MethodTable* pMT, INT_PTR numElements)
12+ static Object* AllocateObject ( MethodTable* pMT, uint32_t uFlags , INT_PTR numElements)
1113{
12- Object* obj = RhpGcAlloc (pMT, 0 , numElements, nullptr );
14+ FCALL_CONTRACT;
15+ Object* obj = RhpGcAlloc (pMT, uFlags, numElements, nullptr );
1316 if (obj == NULL )
1417 {
1518 RhExceptionHandling_FailedAllocation (pMT, false /* isOverflow */ );
@@ -18,11 +21,21 @@ EXTERN_C FCDECL2(Object*, RhpNewVariableSizeObject, MethodTable* pMT, INT_PTR nu
1821 return obj;
1922}
2023
21- static Object* _RhpNewArrayFastCore (MethodTable* pMT, INT_PTR size)
24+ EXTERN_C FCDECL2 (Object*, RhpNewVariableSizeObject, MethodTable* pMT, INT_PTR numElements)
25+ {
26+ WRAPPER_NO_CONTRACT;
27+ return AllocateObject (pMT, 0 , numElements);
28+ }
29+
30+ static Object* NewArrayFastCore (MethodTable* pMT, INT_PTR size)
2231{
2332 FCALL_CONTRACT;
2433 _ASSERTE (pMT != NULL );
25- _ASSERTE (size < INT32_MAX);
34+ if (size < 0 || size > INT32_MAX)
35+ {
36+ RhExceptionHandling_FailedAllocation (pMT, true /* isOverflow */ );
37+ return nullptr ;
38+ }
2639
2740 Thread* thread = GetThread ();
2841 ee_alloc_context* cxt = thread->GetEEAllocContext ();
@@ -31,7 +44,7 @@ static Object* _RhpNewArrayFastCore(MethodTable* pMT, INT_PTR size)
3144 sizeInBytes = ALIGN_UP (sizeInBytes, sizeof (void *));
3245
3346 uint8_t * alloc_ptr = cxt->getAllocPtr ();
34- ASSERT (alloc_ptr <= cxt->getAllocLimit ());
47+ _ASSERTE (alloc_ptr <= cxt->getAllocLimit ());
3548 if ((size_t )(cxt->getAllocLimit () - alloc_ptr) >= sizeInBytes)
3649 {
3750 cxt->setAllocPtr (alloc_ptr + sizeInBytes);
@@ -41,9 +54,72 @@ static Object* _RhpNewArrayFastCore(MethodTable* pMT, INT_PTR size)
4154 return pObject;
4255 }
4356
44- return RhpNewVariableSizeObject (pMT, size);
57+ return AllocateObject (pMT, 0 , size);
58+ }
59+
60+ #if defined(FEATURE_64BIT_ALIGNMENT)
61+ static Object* NewArrayFastAlign8Core (MethodTable* pMT, INT_PTR size)
62+ {
63+ FCALL_CONTRACT;
64+ _ASSERTE (pMT != NULL );
65+
66+ if (size < 0 || size > INT32_MAX)
67+ {
68+ RhExceptionHandling_FailedAllocation (pMT, true /* isOverflow */ );
69+ return nullptr ;
70+ }
71+
72+ Thread* thread = GetThread ();
73+ ee_alloc_context* cxt = thread->GetEEAllocContext ();
74+
75+ size_t sizeInBytes = (size_t )pMT->GetBaseSize () + ((size_t )size * (size_t )pMT->RawGetComponentSize ());
76+ sizeInBytes = ALIGN_UP (sizeInBytes, sizeof (void *));
77+
78+ uint8_t * alloc_ptr = cxt->getAllocPtr ();
79+ bool requiresAlignObject = !IS_ALIGNED (alloc_ptr, sizeof (int64_t ));
80+ size_t paddedSize = sizeInBytes;
81+ if (requiresAlignObject)
82+ {
83+ // We are assuming that allocation of minimal object flips the alignment
84+ paddedSize += MIN_OBJECT_SIZE;
85+ }
86+
87+ _ASSERTE (alloc_ptr <= cxt->getAllocLimit ());
88+ if ((size_t )(cxt->getAllocLimit () - alloc_ptr) >= paddedSize)
89+ {
90+ cxt->setAllocPtr (alloc_ptr + paddedSize);
91+ if (requiresAlignObject)
92+ {
93+ Object* dummy = (Object*)alloc_ptr;
94+ dummy->SetMethodTable (g_pFreeObjectMethodTable);
95+ alloc_ptr += MIN_OBJECT_SIZE;
96+ }
97+ PtrArray* pObject = (PtrArray *)alloc_ptr;
98+ pObject->SetMethodTable (pMT);
99+ pObject->SetNumComponents ((INT32)size);
100+ return pObject;
101+ }
102+
103+ return AllocateObject (pMT, GC_ALLOC_ALIGN8, size);
45104}
46105
106+ EXTERN_C FCDECL2 (Object*, RhpNewArrayFastAlign8, MethodTable* pMT, INT_PTR size)
107+ {
108+ FCALL_CONTRACT;
109+ _ASSERTE (pMT != NULL );
110+
111+ // if the element count is <= 0x10000, no overflow is possible because the component size is
112+ // <= 0xffff, and thus the product is <= 0xffff0000, and the base size is only ~12 bytes
113+ if (size > 0x10000 )
114+ {
115+ // Overflow here should result in an OOM. Let the slow path take care of it.
116+ return AllocateObject (pMT, GC_ALLOC_ALIGN8, size);
117+ }
118+
119+ return NewArrayFastAlign8Core (pMT, size);
120+ }
121+ #endif // FEATURE_64BIT_ALIGNMENT
122+
47123EXTERN_C FCDECL2 (Object*, RhpNewArrayFast, MethodTable* pMT, INT_PTR size)
48124{
49125 FCALL_CONTRACT;
@@ -55,11 +131,11 @@ EXTERN_C FCDECL2(Object*, RhpNewArrayFast, MethodTable* pMT, INT_PTR size)
55131 if (size > 0x10000 )
56132 {
57133 // Overflow here should result in an OOM. Let the slow path take care of it.
58- return RhpNewVariableSizeObject (pMT, size);
134+ return AllocateObject (pMT, 0 , size);
59135 }
60136#endif // !HOST_64BIT
61137
62- return _RhpNewArrayFastCore (pMT, size);
138+ return NewArrayFastCore (pMT, size);
63139}
64140
65141EXTERN_C FCDECL2 (Object*, RhpNewPtrArrayFast, MethodTable* pMT, INT_PTR size)
@@ -74,12 +150,6 @@ EXTERN_C FCDECL1(Object*, RhpNewFast, MethodTable* pMT)
74150 return nullptr ;
75151}
76152
77- EXTERN_C FCDECL2 (Object*, RhpNewArrayFastAlign8, MethodTable* pMT, INT_PTR size)
78- {
79- PORTABILITY_ASSERT (" RhpNewArrayFastAlign8 is not yet implemented" );
80- return nullptr ;
81- }
82-
83153EXTERN_C FCDECL1 (Object*, RhpNewFastAlign8, MethodTable* pMT)
84154{
85155 PORTABILITY_ASSERT (" RhpNewFastAlign8 is not yet implemented" );
@@ -104,5 +174,5 @@ EXTERN_C FCDECL2(Object*, RhNewString, MethodTable* pMT, INT_PTR stringLength)
104174 RhExceptionHandling_FailedAllocation (pMT, false );
105175 }
106176
107- return _RhpNewArrayFastCore (pMT, stringLength);
177+ return NewArrayFastCore (pMT, stringLength);
108178}
0 commit comments