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)