diff --git a/src/CLR/CorLib/corlib_native.cpp b/src/CLR/CorLib/corlib_native.cpp index 34d3d4dd95..0c8b5532cb 100644 --- a/src/CLR/CorLib/corlib_native.cpp +++ b/src/CLR/CorLib/corlib_native.cpp @@ -696,6 +696,10 @@ static const CLR_RT_MethodHandler method_lookup[] = Library_corlib_native_System_Random::_ctor___VOID, Library_corlib_native_System_Random::_ctor___VOID__I4, nullptr, + Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4, + nullptr, + nullptr, + nullptr, nullptr, nullptr, nullptr, @@ -711,6 +715,14 @@ static const CLR_RT_MethodHandler method_lookup[] = nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, Library_corlib_native_System_Reflection_ConstructorInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN, Library_corlib_native_System_Reflection_ConstructorInfo::Invoke___OBJECT__SZARRAY_OBJECT, nullptr, @@ -798,6 +810,7 @@ static const CLR_RT_MethodHandler method_lookup[] = nullptr, nullptr, nullptr, + Library_corlib_native_System_Span_1::_ctor___VOID__VOIDptr__I4, nullptr, nullptr, nullptr, @@ -827,6 +840,10 @@ static const CLR_RT_MethodHandler method_lookup[] = nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, + nullptr, Library_corlib_native_System_Threading_AutoResetEvent::_ctor___VOID__BOOLEAN, Library_corlib_native_System_Threading_AutoResetEvent::Reset___BOOLEAN, Library_corlib_native_System_Threading_AutoResetEvent::Set___BOOLEAN, @@ -1596,7 +1613,7 @@ const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib = #if (NANOCLR_REFLECTION == TRUE) - 0x3C34952A, + 0xCECAB752, #elif (NANOCLR_REFLECTION == FALSE) diff --git a/src/CLR/CorLib/corlib_native.h b/src/CLR/CorLib/corlib_native.h index 7305b59f69..bbeea04d69 100644 --- a/src/CLR/CorLib/corlib_native.h +++ b/src/CLR/CorLib/corlib_native.h @@ -783,6 +783,7 @@ struct Library_corlib_native_System_ReadOnlySpan_1 static const int FIELD___array = 1; static const int FIELD___length = 2; + NANOCLR_NATIVE_DECLARE(_ctor___VOID__VOIDptr__I4); NANOCLR_NATIVE_DECLARE(NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4); //--// @@ -962,6 +963,7 @@ struct Library_corlib_native_System_Span_1 static const int FIELD___array = 1; static const int FIELD___length = 2; + NANOCLR_NATIVE_DECLARE(_ctor___VOID__VOIDptr__I4); NANOCLR_NATIVE_DECLARE(CopyTo___VOID__SystemSpan_1); NANOCLR_NATIVE_DECLARE(NativeSpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4); diff --git a/src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp b/src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp index b3dcd53119..5fad33f016 100644 --- a/src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp +++ b/src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp @@ -6,6 +6,114 @@ #include "CorLib.h" +typedef Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers RuntimeHelpers; + +HRESULT Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4(CLR_RT_StackFrame &stack) +{ + NANOCLR_HEADER(); + + int32_t length; + bool isRefContainsRefs = false; + uintptr_t objectRawPointer; + + CLR_RT_HeapBlock_Array *destinationArray; + CLR_RT_HeapBlock *thisSpan = stack.This(); + + // grab caller to get the generic type + CLR_RT_MethodDef_Instance &caller = stack.MethodCall(); + + if (caller.genericType == nullptr || !NANOCLR_INDEX_IS_VALID(*caller.genericType)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + CLR_RT_TypeSpec_Instance typeSpec; + if (!typeSpec.InitializeFromIndex(*caller.genericType)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + CLR_RT_SignatureParser parser; + parser.Initialize_TypeSpec(typeSpec); + + CLR_RT_SignatureParser::Element element; + + if (FAILED(parser.Advance(element))) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + // The first element should be the generic type instantiation + if (element.DataType != DATATYPE_GENERICINST) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + // Advance to get the generic argument (T) + if (FAILED(parser.Advance(element))) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if (element.DataType == DATATYPE_VALUETYPE) + { + // For value types we need to advance again + if (FAILED(parser.Advance(element))) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + // check if T is a reference type or contains references + NANOCLR_CHECK_HRESULT( + RuntimeHelpers::CheckReferenceOrContainsReferences( + element.Class, + element.DataType, + &parser, + isRefContainsRefs)); + + if (isRefContainsRefs) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // validate length parameter + length = stack.Arg2().NumericByRefConst().s4; + + if (length < 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + // get the pointer to the array + // validate data type as being an unmanaged pointer + if (stack.Arg1().DataType() != DATATYPE_PTR) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + objectRawPointer = (uintptr_t)stack.Arg1().UnmanagedPointer(); + + { + CLR_RT_HeapBlock &refArray = thisSpan[FIELD___array]; + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(refArray, length, element.Class)); + + CLR_RT_ProtectFromGC gc(refArray); + + destinationArray = thisSpan[FIELD___array].DereferenceArray(); + CLR_UINT32 elementSize = destinationArray->m_sizeOfElement; + CLR_UINT8 *elementPtr = destinationArray->GetFirstElement(); + + // copy data from the raw pointer to the newly created array + memcpy(elementPtr, (void *)objectRawPointer, elementSize * length); + } + + // set length + thisSpan[FIELD___length].NumericByRef().s4 = length; + + NANOCLR_NOCLEANUP(); +} + HRESULT Library_corlib_native_System_ReadOnlySpan_1::NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4( CLR_RT_StackFrame &stack) { diff --git a/src/CLR/CorLib/corlib_native_System_Span_1.cpp b/src/CLR/CorLib/corlib_native_System_Span_1.cpp index e9cebde926..426c3b0442 100644 --- a/src/CLR/CorLib/corlib_native_System_Span_1.cpp +++ b/src/CLR/CorLib/corlib_native_System_Span_1.cpp @@ -6,6 +6,114 @@ #include "CorLib.h" +typedef Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers RuntimeHelpers; + +HRESULT Library_corlib_native_System_Span_1::_ctor___VOID__VOIDptr__I4(CLR_RT_StackFrame &stack) +{ + NANOCLR_HEADER(); + + int32_t length; + bool isRefContainsRefs = false; + uintptr_t objectRawPointer; + + CLR_RT_HeapBlock_Array *destinationArray; + CLR_RT_HeapBlock *thisSpan = stack.This(); + + // grab caller to get the generic type + CLR_RT_MethodDef_Instance &caller = stack.MethodCall(); + + if (caller.genericType == nullptr || !NANOCLR_INDEX_IS_VALID(*caller.genericType)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + CLR_RT_TypeSpec_Instance typeSpec; + if (!typeSpec.InitializeFromIndex(*caller.genericType)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + CLR_RT_SignatureParser parser; + parser.Initialize_TypeSpec(typeSpec); + + CLR_RT_SignatureParser::Element element; + + if (FAILED(parser.Advance(element))) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + // The first element should be the generic type instantiation + if (element.DataType != DATATYPE_GENERICINST) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + // Advance to get the generic argument (T) + if (FAILED(parser.Advance(element))) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if (element.DataType == DATATYPE_VALUETYPE) + { + // For value types we need to advance again + if (FAILED(parser.Advance(element))) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + // check if T is a reference type or contains references + NANOCLR_CHECK_HRESULT( + RuntimeHelpers::CheckReferenceOrContainsReferences( + element.Class, + element.DataType, + &parser, + isRefContainsRefs)); + + if (isRefContainsRefs) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // validate length parameter + length = stack.Arg2().NumericByRefConst().s4; + + if (length < 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + // get the pointer to the array + // validate data type as being an unmanaged pointer + if (stack.Arg1().DataType() != DATATYPE_PTR) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + objectRawPointer = (uintptr_t)stack.Arg1().UnmanagedPointer(); + + { + CLR_RT_HeapBlock &refArray = thisSpan[FIELD___array]; + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(refArray, length, element.Class)); + + CLR_RT_ProtectFromGC gc(refArray); + + destinationArray = thisSpan[FIELD___array].DereferenceArray(); + CLR_UINT32 elementSize = destinationArray->m_sizeOfElement; + CLR_UINT8 *elementPtr = destinationArray->GetFirstElement(); + + // copy data from the raw pointer to the newly created array + memcpy(elementPtr, (void *)objectRawPointer, elementSize * length); + } + + // set length + thisSpan[FIELD___length].NumericByRef().s4 = length; + + NANOCLR_NOCLEANUP(); +} + HRESULT Library_corlib_native_System_Span_1::CopyTo___VOID__SystemSpan_1(CLR_RT_StackFrame &stack) { NANOCLR_HEADER(); diff --git a/src/CLR/Core/CLR_RT_HeapBlock.cpp b/src/CLR/Core/CLR_RT_HeapBlock.cpp index ae1877f779..d0fee97ec0 100644 --- a/src/CLR/Core/CLR_RT_HeapBlock.cpp +++ b/src/CLR/Core/CLR_RT_HeapBlock.cpp @@ -641,6 +641,11 @@ HRESULT CLR_RT_HeapBlock::StoreToReference(CLR_RT_HeapBlock &ref, int size) { obj = &ref; } + else if (dt == DATATYPE_PTR) + { + // unmanaged pointer, perform a direct memory copy + memcpy((void *)ref.UnmanagedPointer(), (void *)&NumericByRef(), size); + } else { NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); @@ -2073,6 +2078,20 @@ HRESULT CLR_RT_HeapBlock::NumericAdd(const CLR_RT_HeapBlock &right) } break; + case DATATYPE_PTR: + if (right.DataType() == DATATYPE_I4) + { + // binary numeric add (byte wise) (ECMA-335 Table III.2) + uint8_t *unmanagedPtr = (uint8_t *)UnmanagedPointer(); + unmanagedPtr += right.NumericByRefConst().s4; + + SetUnmanagedPointer((uintptr_t)unmanagedPtr); + + break; + } + // fall through, can't add other types to a PTR + [[fallthrough]]; + default: NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } @@ -2159,6 +2178,21 @@ HRESULT CLR_RT_HeapBlock::NumericSub(const CLR_RT_HeapBlock &right) m_data.arrayReference.index -= right.m_data.numeric.s4 / array->m_sizeOfElement; } break; + + case DATATYPE_PTR: + if (right.DataType() == DATATYPE_I4) + { + // binary numeric sub (byte wise) (ECMA-335 Table III.2) + uint8_t *unmanagedPtr = (uint8_t *)UnmanagedPointer(); + unmanagedPtr -= right.NumericByRefConst().s4; + + SetUnmanagedPointer((uintptr_t)unmanagedPtr); + + break; + } + // fall through, can't subtract other types to a PTR + [[fallthrough]]; + default: NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } diff --git a/src/CLR/Core/CLR_RT_StackFrame.cpp b/src/CLR/Core/CLR_RT_StackFrame.cpp index 3a6678dd2e..e11e5be5ee 100644 --- a/src/CLR/Core/CLR_RT_StackFrame.cpp +++ b/src/CLR/Core/CLR_RT_StackFrame.cpp @@ -120,6 +120,14 @@ HRESULT CLR_RT_StackFrame::Push(CLR_RT_Thread *th, const CLR_RT_MethodDef_Instan // // Initialize generic type context storage to invalid stack->m_genericTypeSpecStorage.Clear(); + + // initialize localloc elements + stack->m_localAllocCount = 0; + for (CLR_INT32 i = 0; i < CLR_RT_StackFrame::c_Max_Localloc_Count; i++) + { + stack->m_localAllocs[i] = 0; + } + // #ifndef NANOCLR_NO_IL_INLINE stack->m_inlineFrame = nullptr; @@ -323,6 +331,11 @@ bool CLR_RT_StackFrame::PushInline( m_inlineFrame->m_frame.m_call = m_call; m_inlineFrame->m_frame.m_evalStack = m_evalStack; m_inlineFrame->m_frame.m_evalPos = pThis; + m_inlineFrame->m_frame.m_localAllocCount = m_localAllocCount; + for (CLR_INT32 i = 0; i < c_Max_Localloc_Count; i++) + { + m_inlineFrame->m_frame.m_localAllocs[i] = m_localAllocs[i]; + } // increment the evalPos pointer so that we don't corrupt the real stack evalPos++; @@ -338,6 +351,13 @@ bool CLR_RT_StackFrame::PushInline( m_IPstart = ip; m_IP = ip; + // initialize localloc for the inline frame + m_localAllocCount = 0; + for (CLR_INT32 i = 0; i < c_Max_Localloc_Count; i++) + { + m_localAllocs[i] = 0; + } + if (md->localsCount) { g_CLR_RT_ExecutionEngine.InitializeLocals(m_locals, calleeInst); @@ -412,6 +432,11 @@ void CLR_RT_StackFrame::RestoreFromInlineStack() m_IPstart = m_inlineFrame->m_frame.m_IPStart; m_evalStack = m_inlineFrame->m_frame.m_evalStack; m_evalStackPos = m_inlineFrame->m_frame.m_evalPos; + m_localAllocCount = m_inlineFrame->m_frame.m_localAllocCount; + for (CLR_INT32 i = 0; i < c_Max_Localloc_Count; i++) + { + m_localAllocs[i] = m_inlineFrame->m_frame.m_localAllocs[i]; + } } void CLR_RT_StackFrame::RestoreStack(CLR_RT_InlineFrame &frame) @@ -424,6 +449,11 @@ void CLR_RT_StackFrame::RestoreStack(CLR_RT_InlineFrame &frame) m_evalStack = frame.m_evalStack; m_evalStackPos = frame.m_evalPos; m_evalStackEnd -= m_call.target->localsCount; + m_localAllocCount = frame.m_localAllocCount; + for (CLR_INT32 i = 0; i < c_Max_Localloc_Count; i++) + { + m_localAllocs[i] = frame.m_localAllocs[i]; + } } void CLR_RT_StackFrame::SaveStack(CLR_RT_InlineFrame &frame) @@ -435,6 +465,11 @@ void CLR_RT_StackFrame::SaveStack(CLR_RT_InlineFrame &frame) frame.m_IPStart = m_IPstart; frame.m_evalPos = m_evalStackPos; frame.m_evalStack = m_evalStack; + frame.m_localAllocCount = m_localAllocCount; + for (CLR_INT32 i = 0; i < c_Max_Localloc_Count; i++) + { + frame.m_localAllocs[i] = m_localAllocs[i]; + } } #endif @@ -822,6 +857,14 @@ void CLR_RT_StackFrame::Pop() { NATIVE_PROFILE_CLR_CORE(); + // Clear localloc references before popping + for (CLR_INT32 i = 0; i < m_localAllocCount; i++) + { + platform_free((void *)m_localAllocs[i]); + m_localAllocs[i] = 0; + } + m_localAllocCount = 0; + #if defined(NANOCLR_PROFILE_NEW_CALLS) { // diff --git a/src/CLR/Core/Interpreter.cpp b/src/CLR/Core/Interpreter.cpp index 9fab21ea7d..cd837f76a0 100644 --- a/src/CLR/Core/Interpreter.cpp +++ b/src/CLR/Core/Interpreter.cpp @@ -1813,6 +1813,7 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg) evalPos[2].Promote(); NANOCLR_CHECK_HRESULT(evalPos[2].StoreToReference(evalPos[1], size)); + break; } @@ -3065,6 +3066,22 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } + // check if field has RVA + CLR_RT_FieldDef_Instance inst; + if (inst.InitializeFromIndex(field) && (inst.target->flags & CLR_RECORD_FIELDDEF::FD_HasFieldRVA) && + inst.target->defaultValue != CLR_EmptyIndex) + { + CLR_PMETADATA ptrSrc; + + // Get the data from the Signatures table (this contains the raw byte array) + ptrSrc = inst.assembly->GetSignature(inst.target->defaultValue); + CLR_UINT32 dummyVar; + NANOCLR_READ_UNALIGNED_UINT16(dummyVar, ptrSrc); + + // ptrSrc is now pointing to the raw byte data + ptr = (CLR_RT_HeapBlock *)ptrSrc; + } + evalPos++; CHECKSTACK(stack, evalPos); @@ -4204,6 +4221,79 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg) //----------------------------------------------------------------------------------------------------------// + OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT) + { + CLR_UINT32 size = evalPos[0].NumericByRef().u4; + + evalPos--; + CHECKSTACK(stack, evalPos); + + // check if we have room for another localloc + if (stack->m_localAllocCount >= CLR_RT_StackFrame::c_Max_Localloc_Count) + { + NANOCLR_SET_AND_LEAVE(CLR_E_STACK_OVERFLOW); + } + + // allocate from platform heap + uintptr_t allocPointer = (uintptr_t)platform_malloc(size); + + // sanity check + if (allocPointer == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // per ECMA-335 zero-initialize the memory + memset((void *)allocPointer, 0, size); + + // store the pointer to the local allocated memory + stack->m_localAllocs[stack->m_localAllocCount++] = allocPointer; + + evalPos++; + CHECKSTACK(stack, evalPos); + + // store the pointer of the local allocated memory + evalPos[0].SetUnmanagedPointer(allocPointer); + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CPBLK, "cpblk", PopI + PopI + PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x17, NEXT) + { + // Stack: ... ... -> ... + + // get size + CLR_UINT32 size = evalPos[0].NumericByRef().u4; + evalPos--; + + // get source address +#ifdef _WIN64 + uintptr_t sourceAddress = evalPos[0].NumericByRef().s8; +#else + uintptr_t sourceAddress = evalPos[0].NumericByRef().s4; +#endif + evalPos--; + + // get destination address +#ifdef _WIN64 + uintptr_t destinationAddress = evalPos[0].NumericByRef().s8; +#else + uintptr_t destinationAddress = evalPos[0].NumericByRef().s4; +#endif + evalPos--; + + CHECKSTACK(stack, evalPos); + + // perform memory move as addresses may overlap + memmove((void *)destinationAddress, (const void *)sourceAddress, size); + + break; + } + + //----------------------------------------------------------------------------------------------------------// + ////////////////////////////////////////////////////////////////////////////////////////// // // These opcodes do nothing... @@ -4219,12 +4309,10 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg) // Unsupported opcodes... // OPDEF(CEE_ARGLIST, "arglist", Pop0, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x00, NEXT) - OPDEF(CEE_CPBLK, "cpblk", PopI + PopI + PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x17, NEXT) OPDEF(CEE_JMP, "jmp", Pop0, Push0, InlineMethod, IPrimitive, 1, 0xFF, 0x27, CALL) OPDEF(CEE_INITBLK, "initblk", PopI + PopI + PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x18, NEXT) OPDEF(CEE_CALLI, "calli", VarPop, VarPush, InlineSig, IPrimitive, 1, 0xFF, 0x29, CALL) OPDEF(CEE_CKFINITE, "ckfinite", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0xC3, NEXT) - OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT) OPDEF(CEE_MKREFANY, "mkrefany", PopI, Push1, InlineType, IPrimitive, 1, 0xFF, 0xC6, NEXT) OPDEF(CEE_REFANYTYPE, "refanytype", Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x1D, NEXT) OPDEF(CEE_REFANYVAL, "refanyval", Pop1, PushI, InlineType, IPrimitive, 1, 0xFF, 0xC2, NEXT) diff --git a/src/CLR/Include/nanoCLR_Runtime.h b/src/CLR/Include/nanoCLR_Runtime.h index bcda8ff63b..b12da25076 100644 --- a/src/CLR/Include/nanoCLR_Runtime.h +++ b/src/CLR/Include/nanoCLR_Runtime.h @@ -2529,6 +2529,9 @@ struct CLR_RT_HeapCluster : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELO //--// +// maximum number of local allocations per stack frame +#define MAX_LOCALALLOC_COUNT 4 + #ifndef NANOCLR_NO_IL_INLINE struct CLR_RT_InlineFrame { @@ -2539,6 +2542,8 @@ struct CLR_RT_InlineFrame CLR_RT_MethodDef_Instance m_call; CLR_PMETADATA m_IP; CLR_PMETADATA m_IPStart; + CLR_UINT8 m_localAllocCount; + uintptr_t m_localAllocs[MAX_LOCALALLOC_COUNT]; }; struct CLR_RT_InlineBuffer @@ -2562,6 +2567,9 @@ struct CLR_RT_StackFrame : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOC static const int c_OverheadForNewObjOrInteropMethod = 2; static const int c_MinimumStack = 10; + // max mumber of local allocations per stack frame + static const int c_Max_Localloc_Count = MAX_LOCALALLOC_COUNT; + static const CLR_UINT32 c_MethodKind_Native = 0x00000000; static const CLR_UINT32 c_MethodKind_Interpreted = 0x00000001; static const CLR_UINT32 c_UNUSED_00000002 = 0x00000002; // c_MethodKind_Jitted @@ -2663,6 +2671,9 @@ struct CLR_RT_StackFrame : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOC bool m_fNativeProfiled; #endif + CLR_UINT8 m_localAllocCount; + uintptr_t m_localAllocs[c_Max_Localloc_Count]; + CLR_RT_HeapBlock m_extension[1]; //////////////////////////////////////// diff --git a/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h b/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h index d9a22795b4..119d68dea1 100644 --- a/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h +++ b/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h @@ -760,6 +760,13 @@ struct CLR_RT_HeapBlock //--// + struct UnmanagedPointer + { + uintptr_t ptr; + } unmanagedPointer; + + //--// + } m_data; public: @@ -1096,6 +1103,19 @@ struct CLR_RT_HeapBlock //--// + void SetUnmanagedPointer(const uintptr_t ptr) + { + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_PTR, 0, 1); + m_data.unmanagedPointer.ptr = ptr; + } + + uintptr_t UnmanagedPointer() const + { + return (DataType() == DATATYPE_PTR) ? m_data.unmanagedPointer.ptr : 0; + } + + //--// + CLR_RT_HeapBlock_Array *RecoverArrayHeader() const { return (DataType() == DATATYPE_ARRAY_BYREF) ? m_data.arrayReference.array : nullptr; diff --git a/src/CLR/Include/nanoCLR_Types.h b/src/CLR/Include/nanoCLR_Types.h index 666106a2cc..0d69281e78 100644 --- a/src/CLR/Include/nanoCLR_Types.h +++ b/src/CLR/Include/nanoCLR_Types.h @@ -518,6 +518,9 @@ enum NanoCLRDataType // KEEP IN SYNC WITH nanoCLR_DataType enum in nanoFramework DATATYPE_TYPE_PINNED = 0x05 | DATATYPE_TYPE_MODIFIER, DATATYPE_TYPE_R4_HFA = 0x06 | DATATYPE_TYPE_MODIFIER, // used only internally for R4 HFA types DATATYPE_TYPE_R8_HFA = 0x07 | DATATYPE_TYPE_MODIFIER, // used only internally for R8 HFA types + + // unamaged pointer + DATATYPE_PTR }; enum CLR_ReflectionType