Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
76 changes: 57 additions & 19 deletions src/coreclr/interpreter/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ int32_t InterpCompiler::CreateVarExplicit(InterpType interpType, CORINFO_CLASS_H
m_varsCapacity *= 2;
if (m_varsCapacity < 16)
m_varsCapacity = 16;

m_pVars = getAllocator(IMK_Var).allocateZeroed<InterpVar>(m_varsCapacity);
if (oldVars != NULL)
{
Expand All @@ -791,7 +791,7 @@ void InterpCompiler::EnsureStack(int additional)
m_stackCapacity *= 2;
if (m_stackCapacity < 4)
m_stackCapacity = 4;

m_pStackBase = new (getAllocator(IMK_StackInfo)) StackInfo[m_stackCapacity];
if (oldStackBase != NULL)
{
Expand Down Expand Up @@ -2026,23 +2026,23 @@ InterpMethod* InterpCompiler::FinalizeMethodData(void* baseAddressRW, void* base
uint32_t currentIntervalMapOffset = intervalMapsOffset;
const uint32_t asyncSuspendDataSectionEnd = asyncSuspendDataOffset + asyncSuspendDataSectionSize;
const uint32_t intervalMapsSectionEnd = intervalMapsOffset + intervalMapsSectionSize;

InterpByteCodeStart* pByteCodeStart = (InterpByteCodeStart*)rxBase;

for (int32_t i = 0; i < m_asyncSuspendDataItems.GetSize(); i++)
{
assert(currentAsyncOffset + sizeof(InterpAsyncSuspendData) <= asyncSuspendDataSectionEnd);

InterpAsyncSuspendData* srcData = m_asyncSuspendDataItems.Get(i);
InterpAsyncSuspendData* dstDataRW = (InterpAsyncSuspendData*)(rwBase + currentAsyncOffset);

// Copy the struct
memcpy(dstDataRW, srcData, sizeof(InterpAsyncSuspendData));

// Fix up the methodStartIP to point to the final bytecode start
dstDataRW->methodStartIP = pByteCodeStart;
dstDataRW->resumeInfo.DiagnosticIP += (TARGET_SIZE_T)pByteCodeStart;

// Fix up interval map pointers if they exist
// Note: The interval maps were allocated via AllocMethodData in the old model,
// we need to copy them to the new allocation and fix up the pointers
Expand All @@ -2055,14 +2055,14 @@ InterpMethod* InterpCompiler::FinalizeMethodData(void* baseAddressRW, void* base

uint32_t mapSize = (uint32_t)count * sizeof(InterpIntervalMapEntry);
assert(currentIntervalMapOffset + mapSize <= intervalMapsSectionEnd);

InterpIntervalMapEntry* dstMapRW = (InterpIntervalMapEntry*)(rwBase + currentIntervalMapOffset);
InterpIntervalMapEntry* dstMapRX = (InterpIntervalMapEntry*)(rxBase + currentIntervalMapOffset);
memcpy(dstMapRW, srcData->liveLocalsIntervals, mapSize);
dstDataRW->liveLocalsIntervals = dstMapRX;
currentIntervalMapOffset += mapSize;
}

if (srcData->zeroedLocalsIntervals != nullptr)
{
// Count entries
Expand All @@ -2072,7 +2072,7 @@ InterpMethod* InterpCompiler::FinalizeMethodData(void* baseAddressRW, void* base

uint32_t mapSize = (uint32_t)count * sizeof(InterpIntervalMapEntry);
assert(currentIntervalMapOffset + mapSize <= intervalMapsSectionEnd);

InterpIntervalMapEntry* dstMapRW = (InterpIntervalMapEntry*)(rwBase + currentIntervalMapOffset);
InterpIntervalMapEntry* dstMapRX = (InterpIntervalMapEntry*)(rxBase + currentIntervalMapOffset);
memcpy(dstMapRW, srcData->zeroedLocalsIntervals, mapSize);
Expand Down Expand Up @@ -2121,7 +2121,7 @@ InterpMethod* InterpCompiler::FinalizeMethodData(void* baseAddressRW, void* base
{
DataItemAsyncSuspendRef ref = m_dataItemAsyncSuspendRefs.Get(i);
// Calculate the final address of this async suspend data in the RX allocation
InterpAsyncSuspendData* finalAddr = (InterpAsyncSuspendData*)(rxBase + asyncSuspendDataOffset +
InterpAsyncSuspendData* finalAddr = (InterpAsyncSuspendData*)(rxBase + asyncSuspendDataOffset +
ref.asyncSuspendDataIndex * sizeof(InterpAsyncSuspendData));
pDataItemsRW[ref.dataItemIndex] = finalAddr;
}
Expand Down Expand Up @@ -3562,6 +3562,44 @@ bool InterpCompiler::EmitNamedIntrinsicCall(NamedIntrinsic ni, bool nonVirtualCa
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
return true;

case NI_IsSupported_Type:
{
CORINFO_CLASS_HANDLE typeArgHnd = m_compHnd->getTypeInstantiationArgument(clsHnd, 0);
CorInfoType simdBaseJitType = m_compHnd->getTypeForPrimitiveNumericClass(typeArgHnd);

AddIns(INTOP_LDC_I4);

switch (simdBaseJitType)
{
case CORINFO_TYPE_BYTE:
case CORINFO_TYPE_UBYTE:
case CORINFO_TYPE_SHORT:
case CORINFO_TYPE_USHORT:
case CORINFO_TYPE_INT:
case CORINFO_TYPE_UINT:
case CORINFO_TYPE_LONG:
case CORINFO_TYPE_ULONG:
case CORINFO_TYPE_FLOAT:
case CORINFO_TYPE_DOUBLE:
case CORINFO_TYPE_NATIVEINT:
case CORINFO_TYPE_NATIVEUINT:
{
m_pLastNewIns->data[0] = true;
break;
}

default:
{
m_pLastNewIns->data[0] = false;
break;
}
}

PushStackType(StackTypeI4, NULL);
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
return true;
}

case NI_PRIMITIVE_ConvertToIntegerNative:
{
CHECK_STACK(1);
Expand Down Expand Up @@ -4423,7 +4461,7 @@ void InterpCompiler::EmitCalli(bool isTailCall, void* calliCookie, int callIFunc
{
if (m_compHnd->pInvokeMarshalingRequired(NULL, callSiteSig))
{
// If we remove this restriction, we should handle the track transitions scenario by forcing a
// If we remove this restriction, we should handle the track transitions scenario by forcing a
// p/invoke marshaling calli stub even when not needed.
BADCODE("PInvoke marshalling for calli is not supported in interpreted code");
}
Expand Down Expand Up @@ -6011,7 +6049,7 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation
}
InterpType interpType = m_pVars[var].interpType;
CORINFO_CLASS_HANDLE clsHnd = m_pVars[var].clsHnd;

int32_t alignUNUSED;
int32_t size = GetInterpTypeStackSize(clsHnd, interpType, &alignUNUSED);

Expand Down Expand Up @@ -6058,7 +6096,7 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation
SetSlotToTrue(objRefSlots, currentOffset + slotInfo.m_offsetBytes);
}
}

currentOffset += size;
}

Expand Down Expand Up @@ -6099,7 +6137,7 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation
suspendData->suspensionPointIndex = suspensionPointIndex;
CORINFO_ASYNC_INFO asyncInfo;
m_compHnd->getAsyncInfo(&asyncInfo);

GetDataForHelperFtn(CORINFO_HELP_ALLOC_CONTINUATION);
suspendData->continuationTypeHnd = continuationTypeHnd;
AllocateIntervalMapData_ForVars(&suspendData->liveLocalsIntervals, liveVars);
Expand Down Expand Up @@ -6232,13 +6270,13 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation

AddIns(handleContinuationOpcode);
int32_t suspendDataIndex = GetDataItemIndex(suspendData);

// Track this data item -> async suspend data reference for fixup during finalization
DataItemAsyncSuspendRef ref;
ref.dataItemIndex = suspendDataIndex;
ref.asyncSuspendDataIndex = m_asyncSuspendDataItems.GetSize() - 1; // suspendData was just added
m_dataItemAsyncSuspendRefs.Add(ref);

m_pLastNewIns->data[0] = suspendDataIndex;
m_pLastNewIns->data[1] = GetDataForHelperFtn(helperFuncForAllocatingContinuation);
PushInterpType(InterpTypeO, NULL);
Expand Down Expand Up @@ -6279,7 +6317,7 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation
// Add location to resume to. The implementation of this opcode will:
// - restore the data captured
// - If there is an exception, throw it
// - if there is a captured exec context, call the restoration function.
// - if there is a captured exec context, call the restoration function.
AddIns(INTOP_HANDLE_CONTINUATION_RESUME);
m_pLastNewIns->data[0] = suspendDataIndex;

Expand Down Expand Up @@ -9930,7 +9968,7 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
BADCODE("CEE_JMP in synchronized or async method");
}
EmitCall(m_pConstrainedToken, readonly, true /* tailcall */, false /*newObj*/, false /*isCalli*/);
EmitRet(methodInfo); // The tail-call infrastructure in the interpreter is not 100% guaranteed to do a
EmitRet(methodInfo); // The tail-call infrastructure in the interpreter is not 100% guaranteed to do a
// tail-call, so inject the ret logic here to cover that case.
linkBBlocks = false;
break;
Expand Down
13 changes: 11 additions & 2 deletions src/coreclr/interpreter/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,23 @@ NamedIntrinsic GetNamedIntrinsic(COMP_HANDLE compHnd, CORINFO_METHOD_HANDLE comp
if (!strcmp(className, "Vector") && !strcmp(methodName, "get_IsHardwareAccelerated"))
return NI_IsSupported_False;

if (!strcmp(className, "Vector`1") && !strcmp(methodName, "get_IsSupported"))
return NI_IsSupported_Type;

// Fall back to managed implementation for everything else.
return NI_Illegal;
}
else if (!strcmp(namespaceName, "System.Runtime.Intrinsics"))
{
// Vector128<T> etc
if (HAS_PREFIX(className, "Vector") && !strcmp(methodName, "get_IsHardwareAccelerated"))
return NI_IsSupported_False;
if (HAS_PREFIX(className, "Vector"))
{
if (!strcmp(methodName, "get_IsHardwareAccelerated"))
return NI_IsSupported_False;

if (!strcmp(methodName, "get_IsSupported"))
return NI_IsSupported_Type;
}
Comment thread
tannergooding marked this conversation as resolved.

// Fall back to managed implementation for everything else.
return NI_Illegal;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,7 @@ public static bool IsSupported
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (typeof(T) == typeof(byte))
|| (typeof(T) == typeof(double))
|| (typeof(T) == typeof(short))
|| (typeof(T) == typeof(int))
|| (typeof(T) == typeof(long))
|| (typeof(T) == typeof(nint))
|| (typeof(T) == typeof(sbyte))
|| (typeof(T) == typeof(float))
|| (typeof(T) == typeof(ushort))
|| (typeof(T) == typeof(uint))
|| (typeof(T) == typeof(ulong))
|| (typeof(T) == typeof(nuint));
return Scalar<T>.IsSupported;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,7 @@ public static bool IsSupported
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (typeof(T) == typeof(byte))
|| (typeof(T) == typeof(double))
|| (typeof(T) == typeof(short))
|| (typeof(T) == typeof(int))
|| (typeof(T) == typeof(long))
|| (typeof(T) == typeof(nint))
|| (typeof(T) == typeof(sbyte))
|| (typeof(T) == typeof(float))
|| (typeof(T) == typeof(ushort))
|| (typeof(T) == typeof(uint))
|| (typeof(T) == typeof(ulong))
|| (typeof(T) == typeof(nuint));
return Scalar<T>.IsSupported;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,7 @@ public static bool IsSupported
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (typeof(T) == typeof(byte))
|| (typeof(T) == typeof(double))
|| (typeof(T) == typeof(short))
|| (typeof(T) == typeof(int))
|| (typeof(T) == typeof(long))
|| (typeof(T) == typeof(nint))
|| (typeof(T) == typeof(sbyte))
|| (typeof(T) == typeof(float))
|| (typeof(T) == typeof(ushort))
|| (typeof(T) == typeof(uint))
|| (typeof(T) == typeof(ulong))
|| (typeof(T) == typeof(nuint));
return Scalar<T>.IsSupported;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,7 @@ public static bool IsSupported
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (typeof(T) == typeof(byte))
|| (typeof(T) == typeof(double))
|| (typeof(T) == typeof(short))
|| (typeof(T) == typeof(int))
|| (typeof(T) == typeof(long))
|| (typeof(T) == typeof(nint))
|| (typeof(T) == typeof(sbyte))
|| (typeof(T) == typeof(float))
|| (typeof(T) == typeof(ushort))
|| (typeof(T) == typeof(uint))
|| (typeof(T) == typeof(ulong))
|| (typeof(T) == typeof(nuint));
return Scalar<T>.IsSupported;
}
}

Expand Down
40 changes: 34 additions & 6 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -2677,9 +2677,22 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas
*op = MINT_LDC_I4_0;
} else if (in_corlib && (!strncmp ("System.Runtime.Intrinsics", klass_name_space, 25))) {
if (klass_name_space[25] == '\0' &&
!strncmp ("Vector", klass_name, 6) &&
!strcmp (tm, "get_IsHardwareAccelerated")) {
*op = MINT_LDC_I4_0;
!strncmp ("Vector", klass_name, 6)) {
if (!strcmp (tm, "get_IsHardwareAccelerated")) {
*op = MINT_LDC_I4_0;
} else if (!strcmp (tm, "get_IsSupported")) {
g_assert (mono_class_is_ginst (target_method->klass));

// Apart from filtering out non-primitive types this also filters out shared generic instance types like: T_BYTE which cannot be intrinsified
MonoType *etype = mono_class_get_context (target_method->klass)->class_inst->type_argv [0];

if (MONO_TYPE_IS_VECTOR_PRIMITIVE (etype)) {
*op = MINT_LDC_I4_1;
} else if (mini_type_get_underlying_type (etype)->type == MONO_TYPE_OBJECT) {
// Happens often in gshared code
Comment on lines +2684 to +2692
*op = MINT_LDC_I4_0;
}
}
} else if (klass_name_space[25] == '.') {
if (!strncmp ("Arm", klass_name_space + 26, 3) ||
!strncmp ("X86", klass_name_space + 26, 3)) {
Expand Down Expand Up @@ -2712,9 +2725,24 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas
}
}
} else if (in_corlib && !strncmp ("System.Numerics", klass_name_space, 15)) {
if (!strcmp ("Vector", klass_name) &&
!strcmp (tm, "get_IsHardwareAccelerated")) {
*op = MINT_LDC_I4_0;
if (!strcmp ("Vector", klass_name)) {
if (!strcmp (tm, "get_IsHardwareAccelerated")) {
*op = MINT_LDC_I4_0;
}
} else if (!strcmp ("Vector`1", klass_name)) {
if (!strcmp (tm, "get_IsSupported")) {
g_assert (mono_class_is_ginst (target_method->klass));

// Apart from filtering out non-primitive types this also filters out shared generic instance types like: T_BYTE which cannot be intrinsified
MonoType *etype = mono_class_get_context (target_method->klass)->class_inst->type_argv [0];

if (MONO_TYPE_IS_VECTOR_PRIMITIVE (etype)) {
*op = MINT_LDC_I4_1;
} else if (mini_type_get_underlying_type (etype)->type == MONO_TYPE_OBJECT) {
// Happens often in gshared code
*op = MINT_LDC_I4_0;
Comment on lines +2734 to +2743
}
Comment thread
tannergooding marked this conversation as resolved.
}
} else if (!strcmp ("BitOperations", klass_name)) {
int arg_type = (csignature->param_count > 0) ? csignature->params [0]->type : MONO_TYPE_VOID;
if ((!strcmp (tm, "RotateLeft") || !strcmp (tm, "RotateRight")) && MINT_IS_LDC_I4 (td->last_ins->opcode)) {
Expand Down
22 changes: 22 additions & 0 deletions src/mono/mono/mini/intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -2436,6 +2436,28 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
ins->type = STACK_I4;
return ins;
}

if (!strcmp (cmethod_name, "get_IsSupported")) {
if (mono_class_is_ginst (cmethod->klass)) {
// Apart from filtering out non-primitive types this also filters out shared generic instance types like: T_BYTE which cannot be intrinsified
MonoType *etype = mono_class_get_context (cmethod->klass)->class_inst->type_argv [0];

if (MONO_TYPE_IS_VECTOR_PRIMITIVE (etype)) {
EMIT_NEW_ICONST (cfg, ins, 1);
ins->type = STACK_I4;
return ins;
} else if (mini_type_get_underlying_type (etype)->type == MONO_TYPE_OBJECT) {
// Happens often in gshared code
EMIT_NEW_ICONST (cfg, ins, 0);
ins->type = STACK_I4;
return ins;
}
} else {
EMIT_NEW_ICONST (cfg, ins, 0);
ins->type = STACK_I4;
return ins;
}
}
}

// On FullAOT, return false for RuntimeFeature:
Expand Down
Loading
Loading