diff --git a/src/Common/src/TypeSystem/Common/TargetDetails.cs b/src/Common/src/TypeSystem/Common/TargetDetails.cs
index 79601a4eedd..7a84d6e3cf1 100644
--- a/src/Common/src/TypeSystem/Common/TargetDetails.cs
+++ b/src/Common/src/TypeSystem/Common/TargetDetails.cs
@@ -274,7 +274,8 @@ public LayoutInt GetObjectAlignment(LayoutInt fieldAlignment)
switch (Architecture)
{
case TargetArchitecture.ARM:
- // ARM supports two alignments for objects on the GC heap (4 byte and 8 byte)
+ case TargetArchitecture.Wasm32:
+ // ARM & Wasm32 support two alignments for objects on the GC heap (4 byte and 8 byte)
if (fieldAlignment.IsIndeterminate)
return LayoutInt.Indeterminate;
@@ -286,7 +287,6 @@ public LayoutInt GetObjectAlignment(LayoutInt fieldAlignment)
case TargetArchitecture.ARM64:
return new LayoutInt(8);
case TargetArchitecture.X86:
- case TargetArchitecture.Wasm32:
return new LayoutInt(4);
default:
throw new NotSupportedException();
diff --git a/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs b/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs
index 89fd08f3dba..c70b6fa99f8 100644
--- a/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs
@@ -202,11 +202,11 @@ public static bool IsArrayTypeWithoutGenericInterfaces(this TypeDesc type)
///
/// Determines whether an object of type '' requires 8-byte alignment on
- /// 32bit ARM architectures.
+ /// 32bit ARM or 32bit Wasm architectures.
///
public static bool RequiresAlign8(this TypeDesc type)
{
- if (type.Context.Target.Architecture != TargetArchitecture.ARM)
+ if (type.Context.Target.Architecture != TargetArchitecture.ARM && type.Context.Target.Architecture != TargetArchitecture.Wasm32)
{
return false;
}
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
index 809ba28e426..77150460e8f 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
@@ -4944,9 +4944,18 @@ private void ImportNewArray(int token)
else
{
arguments = new StackEntry[] { new LoadExpressionEntry(StackValueKind.ValueType, "eeType", GetEETypePointerForTypeDesc(runtimeDeterminedArrayType, true), eeTypeDesc), sizeOfArray };
- //TODO: call GetNewArrayHelperForType from JitHelper.cs (needs refactoring)
}
- PushNonNull(CallRuntime(_compilation.TypeSystemContext, InternalCalls, "RhpNewArray", arguments, runtimeDeterminedArrayType));
+ var helper = GetNewArrayHelperForType(runtimeDeterminedArrayType);
+ PushNonNull(CallRuntime(_compilation.TypeSystemContext, InternalCalls, helper, arguments, runtimeDeterminedArrayType));
+ }
+
+ //TODO: copy of the same method in JitHelper.cs but that is internal
+ public static string GetNewArrayHelperForType(TypeDesc type)
+ {
+ if (type.RequiresAlign8())
+ return "RhpNewArrayAlign8";
+
+ return "RhpNewArray";
}
LLVMValueRef GetGenericContext()
diff --git a/src/Native/CMakeLists.txt b/src/Native/CMakeLists.txt
index d1b27073ee4..f2257fe1c6a 100644
--- a/src/Native/CMakeLists.txt
+++ b/src/Native/CMakeLists.txt
@@ -50,6 +50,7 @@ elseif(CLR_CMAKE_TARGET_ARCH STREQUAL wasm)
set(CLR_CMAKE_PLATFORM_ARCH_WASM 1)
add_definitions(-DTARGET_WASM=1)
add_definitions(-DHOST_WASM=1)
+ add_definitions(-DFEATURE_64BIT_ALIGNMENT=1)
else()
clr_unknown_arch()
endif()
diff --git a/src/Native/Runtime/portable.cpp b/src/Native/Runtime/portable.cpp
index 4372925d0dd..797cc968834 100644
--- a/src/Native/Runtime/portable.cpp
+++ b/src/Native/Runtime/portable.cpp
@@ -36,7 +36,6 @@
#include "GCMemoryHelpers.inl"
#if defined(USE_PORTABLE_HELPERS)
-
EXTERN_C REDHAWK_API void* REDHAWK_CALLCONV RhpGcAlloc(EEType *pEEType, UInt32 uFlags, UIntNative cbSize, void * pTransitionFrame);
EXTERN_C REDHAWK_API void* REDHAWK_CALLCONV RhpPublishObject(void* pObject, UIntNative cbSize);
@@ -88,7 +87,9 @@ COOP_PINVOKE_HELPER(Object *, RhpNewFast, (EEType* pEEType))
return pObject;
}
-#define GC_ALLOC_FINALIZE 0x1 // TODO: Defined in gc.h
+#define GC_ALLOC_FINALIZE 0x1 // TODO: Defined in gc.h
+#define GC_ALLOC_ALIGN8_BIAS 0x4 // TODO: Defined in gc.h
+#define GC_ALLOC_ALIGN8 0x8 // TODO: Defined in gc.h
COOP_PINVOKE_HELPER(Object *, RhpNewFinalizable, (EEType* pEEType))
{
@@ -180,36 +181,149 @@ COOP_PINVOKE_HELPER(String *, RhNewString, (EEType * pArrayEEType, int numElemen
#endif
#if defined(USE_PORTABLE_HELPERS)
+#if defined(FEATURE_64BIT_ALIGNMENT)
+
+GPTR_DECL(EEType, g_pFreeObjectEEType);
-#ifdef HOST_ARM
COOP_PINVOKE_HELPER(Object *, RhpNewFinalizableAlign8, (EEType* pEEType))
{
Object * pObject = nullptr;
- /* TODO */ ASSERT_UNCONDITIONALLY("NYI");
+ /* Not reachable as finalizable types are never align8 */ ASSERT_UNCONDITIONALLY("UNREACHABLE");
return pObject;
}
-COOP_PINVOKE_HELPER(Object *, RhpNewFastMisalign, (EEType* pEEType))
+COOP_PINVOKE_HELPER(Object *, RhpNewFastAlign8, (EEType* pEEType))
{
- Object * pObject = nullptr;
- /* TODO */ ASSERT_UNCONDITIONALLY("NYI");
+ ASSERT(pEEType->RequiresAlign8());
+ ASSERT(!pEEType->HasFinalizer());
+
+ Thread* pCurThread = ThreadStore::GetCurrentThread();
+ gc_alloc_context* acontext = pCurThread->GetAllocContext();
+ Object* pObject;
+
+ size_t size = pEEType->get_BaseSize();
+ size = (size + (sizeof(UIntNative) - 1)) & ~(sizeof(UIntNative) - 1);
+
+ UInt8* result = acontext->alloc_ptr;
+
+ int requiresPadding = ((uint32_t)result) & 7;
+ if (requiresPadding) size += 12;
+ UInt8* advance = result + size;
+ if (advance <= acontext->alloc_limit)
+ {
+ acontext->alloc_ptr = advance;
+ if (requiresPadding)
+ {
+ Object* dummy = (Object*)result;
+ dummy->set_EEType(g_pFreeObjectEEType);
+ result += 12;
+ }
+ pObject = (Object*)result;
+ pObject->set_EEType(pEEType);
+
+ return pObject;
+ }
+
+ pObject = (Object*)RhpGcAlloc(pEEType, GC_ALLOC_ALIGN8, size, NULL);
+ if (pObject == nullptr)
+ {
+ ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw OOM
+ }
+ pObject->set_EEType(pEEType);
+
+ if (size >= RH_LARGE_OBJECT_SIZE)
+ RhpPublishObject(pObject, size);
+
return pObject;
}
-COOP_PINVOKE_HELPER(Object *, RhpNewFastAlign8, (EEType* pEEType))
+COOP_PINVOKE_HELPER(Object*, RhpNewFastMisalign, (EEType* pEEType))
{
- Object * pObject = nullptr;
- /* TODO */ ASSERT_UNCONDITIONALLY("NYI");
+ size_t size = pEEType->get_BaseSize();
+ Object* pObject = (Object*)RhpGcAlloc(pEEType, GC_ALLOC_ALIGN8_BIAS, size, NULL);
+ if (pObject == nullptr)
+ {
+ ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw OOM
+ }
+ pObject->set_EEType(pEEType);
+
+ if (size >= RH_LARGE_OBJECT_SIZE)
+ RhpPublishObject(pObject, size);
+
return pObject;
}
COOP_PINVOKE_HELPER(Array *, RhpNewArrayAlign8, (EEType * pArrayEEType, int numElements))
{
- Array * pObject = nullptr;
- /* TODO */ ASSERT_UNCONDITIONALLY("NYI");
+ ASSERT_MSG(pArrayEEType->RequiresAlign8(), "RhpNewArrayAlign8 called for a type that is not aligned 8");
+
+ 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 baseSize = pArrayEEType->get_BaseSize();
+#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)baseSize + ((uint64_t)numElements * (uint64_t)pArrayEEType->get_ComponentSize());
+ size64 = (size64 + (sizeof(UIntNative) - 1)) & ~(sizeof(UIntNative) - 1);
+
+ size = (size_t)size64;
+ if (size != size64)
+ {
+ ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw overflow
+ }
+ }
+ else
+#endif // !HOST_64BIT
+ {
+ size = (size_t)baseSize + ((size_t)numElements * (size_t)pArrayEEType->get_ComponentSize());
+ size = ALIGN_UP(size, sizeof(UIntNative));
+ }
+ UInt8* result = acontext->alloc_ptr;
+ int requiresAlignObject = ((uint32_t)result) & 7;
+ if (requiresAlignObject) size += 12;
+
+ UInt8* advance = result + size;
+ if (advance <= acontext->alloc_limit)
+ {
+ acontext->alloc_ptr = advance;
+ if (requiresAlignObject)
+ {
+ Object* dummy = (Object*)result;
+ dummy->set_EEType(g_pFreeObjectEEType);
+ result += 12;
+ }
+ pObject = (Array*)result;
+ pObject->set_EEType(pArrayEEType);
+ pObject->InitArrayLength((UInt32)numElements);
+ return pObject;
+ }
+
+ pObject = (Array*)RhpGcAlloc(pArrayEEType, GC_ALLOC_ALIGN8, size, NULL);
+ if (pObject == nullptr)
+ {
+ ASSERT_UNCONDITIONALLY("NYI"); // TODO: Throw OOM
+ }
+ pObject->set_EEType(pArrayEEType);
+ pObject->InitArrayLength((UInt32)numElements);
+
+ if (size >= RH_LARGE_OBJECT_SIZE)
+ RhpPublishObject(pObject, size);
+
return pObject;
}
-#endif
+#endif // defined(HOST_ARM) || defined(HOST_WASM)
COOP_PINVOKE_HELPER(void, RhpInitialDynamicInterfaceDispatch, ())
{
diff --git a/src/Native/gc/gc.cpp b/src/Native/gc/gc.cpp
index 3aae8dd4f3f..496f00a309a 100644
--- a/src/Native/gc/gc.cpp
+++ b/src/Native/gc/gc.cpp
@@ -17833,12 +17833,12 @@ uint8_t* gc_heap::find_object (uint8_t* interior)
{
// this is a pointer to a UOH object
heap_segment* seg = find_segment (interior, FALSE);
- if (seg
+ if (seg)
+ {
#ifdef FEATURE_CONSERVATIVE_GC
- && (GCConfig::GetConservativeGC() || interior <= heap_segment_allocated(seg))
+ if ( interior >= heap_segment_allocated(seg))
+ return 0;
#endif
- )
- {
// If interior falls within the first free object at the beginning of a generation,
// we don't have brick entry for it, and we may incorrectly treat it as on large object heap.
int align_const = get_alignment_constant (heap_segment_read_only_p (seg)
diff --git a/src/Runtime.Base/src/Runtime.Base.csproj b/src/Runtime.Base/src/Runtime.Base.csproj
index 50213144a2c..d11304a115b 100644
--- a/src/Runtime.Base/src/Runtime.Base.csproj
+++ b/src/Runtime.Base/src/Runtime.Base.csproj
@@ -21,6 +21,9 @@
FEATURE_64BIT_ALIGNMENT;$(DefineConstants)
+
+ FEATURE_64BIT_ALIGNMENT;$(DefineConstants)
+
diff --git a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
index 13f869da10d..14d5c0bbefd 100644
--- a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
+++ b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
@@ -495,6 +495,7 @@
INPLACE_RUNTIME;$(DefineConstants)
FEATURE_64BIT_ALIGNMENT;$(DefineConstants)
FEATURE_64BIT_ALIGNMENT;$(DefineConstants)
+ FEATURE_64BIT_ALIGNMENT;$(DefineConstants)