Skip to content
16 changes: 16 additions & 0 deletions src/coreclr/interpreter/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3424,6 +3424,10 @@ void InterpCompiler::EmitPushUnboxAny(const CORINFO_GENERICHANDLE_RESULT& arg1,
PushStackType(resultStackType, clsHndStack);
int resultVar = m_pStackPointer[-1].var;

PushStackType(StackTypeI, NULL);
int32_t intermediateVar = m_pStackPointer[-1].var;
m_pStackPointer--;

GenericHandleData handleData = GenericHandleToGenericHandleData(arg1);

if (handleData.argType == HelperArgType::GenericResolution)
Expand All @@ -3433,6 +3437,12 @@ void InterpCompiler::EmitPushUnboxAny(const CORINFO_GENERICHANDLE_RESULT& arg1,
m_pLastNewIns->data[1] = handleData.dataItemIndex;

m_pLastNewIns->SetSVars2(handleData.genericVar, arg2);
m_pLastNewIns->SetDVar(intermediateVar);

AddIns(INTOP_UNBOX_END_GENERIC);
m_pLastNewIns->data[0] = handleData.dataItemIndex;

m_pLastNewIns->SetSVars2(handleData.genericVar, intermediateVar);
m_pLastNewIns->SetDVar(resultVar);
}
else
Expand All @@ -3442,6 +3452,12 @@ void InterpCompiler::EmitPushUnboxAny(const CORINFO_GENERICHANDLE_RESULT& arg1,
m_pLastNewIns->data[1] = handleData.dataItemIndex;

m_pLastNewIns->SetSVar(arg2);
m_pLastNewIns->SetDVar(intermediateVar);

AddIns(INTOP_UNBOX_END);
m_pLastNewIns->data[0] = handleData.dataItemIndex;

m_pLastNewIns->SetSVar(intermediateVar);
m_pLastNewIns->SetDVar(resultVar);
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/interpreter/inc/intops.def
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ OPDEF(INTOP_UNBOX_ANY, "unbox.any", 5, 1, 1, InterpOpHelperFtn) // [class handle
OPDEF(INTOP_UNBOX_ANY_GENERIC, "unbox.any.generic", 6, 1, 2, InterpOpGenericHelperFtn) // [class handle data item] [helper data item]
// Unary operations end

OPDEF(INTOP_UNBOX_END, "unbox.end", 4, 1, 1, InterpOpLdPtr)
OPDEF(INTOP_UNBOX_END_GENERIC, "unbox.end.generic", 5, 1, 2, InterpOpGenericLookup)

OPDEF(INTOP_ADD_I4_IMM, "add.i4.imm", 4, 1, 1, InterpOpInt)
OPDEF(INTOP_ADD_I8_IMM, "add.i8.imm", 4, 1, 1, InterpOpInt)

Expand Down
68 changes: 60 additions & 8 deletions src/coreclr/vm/interpexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2813,36 +2813,88 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
int opcode = *ip;
int dreg = ip[1];
int sreg = ip[2];
HELPER_FTN_BOX_UNBOX helper = GetPossiblyIndirectHelper<HELPER_FTN_BOX_UNBOX>(pMethod, ip[3]);
MethodDesc *pILTargetMethod = NULL;
HELPER_FTN_BOX_UNBOX helper = GetPossiblyIndirectHelper<HELPER_FTN_BOX_UNBOX>(pMethod, ip[3], &pILTargetMethod);
MethodTable *pMT = (MethodTable*)pMethod->pDataItems[ip[4]];
Object *src = LOCAL_VAR(sreg, Object*);

if (pILTargetMethod != NULL)
{
callArgsOffset = pMethod->allocaSize;
returnOffset = ip[1];

// Pass arguments to the target method
LOCAL_VAR(callArgsOffset, void*) = pMT;
LOCAL_VAR(callArgsOffset + INTERP_STACK_SLOT_SIZE, void*) = src;

targetMethod = pILTargetMethod;
ip += 5;

goto CALL_INTERP_METHOD;
}

// private static ref byte Unbox(MethodTable* toTypeHnd, object obj)
Object *src = LOCAL_VAR(sreg, Object*);
void *unboxedData = helper(pMT, src);
CopyValueClassUnchecked(LOCAL_VAR_ADDR(dreg, void), unboxedData, pMT);
LOCAL_VAR(dreg, void*) = helper(pMT, src);

ip += 5;
break;
}
case INTOP_UNBOX_END:
{
MethodTable *pMT = (MethodTable*)pMethod->pDataItems[ip[3]];
void *dest = LOCAL_VAR_ADDR(ip[1], void);
void *src = LOCAL_VAR(ip[2], void*);
NULL_CHECK(dest);
CopyValueClassUnchecked(dest, src, pMT);

ip += 4;
break;
}
case INTOP_UNBOX_ANY_GENERIC:
{
int opcode = *ip;
int dreg = ip[1];
int sreg = ip[3];
InterpGenericLookup *pLookup = (InterpGenericLookup*)&pMethod->pDataItems[ip[5]];
MethodTable *pMTBoxedObj = (MethodTable*)DoGenericLookup(LOCAL_VAR(ip[2], void*), pLookup);
Object *src = LOCAL_VAR(sreg, Object*);

HELPER_FTN_BOX_UNBOX helper = GetPossiblyIndirectHelper<HELPER_FTN_BOX_UNBOX>(pMethod, ip[4]);
MethodDesc *pILTargetMethod = NULL;
HELPER_FTN_BOX_UNBOX helper = GetPossiblyIndirectHelper<HELPER_FTN_BOX_UNBOX>(pMethod, ip[4], &pILTargetMethod);

if (pILTargetMethod != NULL)
{
callArgsOffset = pMethod->allocaSize;
returnOffset = ip[1];

// Pass arguments to the target method
LOCAL_VAR(callArgsOffset, void*) = pMTBoxedObj;
LOCAL_VAR(callArgsOffset + INTERP_STACK_SLOT_SIZE, void*) = src;

targetMethod = pILTargetMethod;
ip += 6;

goto CALL_INTERP_METHOD;
}

// private static ref byte Unbox(MethodTable* toTypeHnd, object obj)
Object *src = LOCAL_VAR(sreg, Object*);
void *unboxedData = helper(pMTBoxedObj, src);
CopyValueClassUnchecked(LOCAL_VAR_ADDR(dreg, void), unboxedData, pMTBoxedObj->IsNullable() ? pMTBoxedObj->GetInstantiation()[0].AsMethodTable() : pMTBoxedObj);
LOCAL_VAR(dreg, void*) = helper(pMTBoxedObj, src);

ip += 6;
break;
}
case INTOP_UNBOX_END_GENERIC:
{
InterpGenericLookup *pLookup = (InterpGenericLookup*)&pMethod->pDataItems[ip[4]];
MethodTable *pMT = (MethodTable*)pMethod->pDataItems[ip[2]];
void *dest = LOCAL_VAR_ADDR(ip[1], void);
void *src = LOCAL_VAR(ip[3], void*);
NULL_CHECK(dest);
CopyValueClassUnchecked(dest, src, pMT->IsNullable() ? pMT->GetInstantiation()[0].AsMethodTable() : pMT);

ip += 5;
break;
}
case INTOP_NEWARR:
{
int32_t length = LOCAL_VAR(ip[2], int32_t);
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/vm/wasm/helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,12 @@ namespace
*(int32_t*)pRet = (*fptr)(ARG_IND(0), ARG_I32(1));
}

void CallFunc_I32_I32IND_I32_RetI32(PCODE pcode, int8_t *pArgs, int8_t *pRet)
{
int32_t (*fptr)(int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t))pcode;
*(int32_t*)pRet = (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2));
}

void CallFunc_I32_I32IND_I32_I32IND_I32_RetI32(PCODE pcode, int8_t *pArgs, int8_t *pRet)
{
int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode;
Expand Down Expand Up @@ -720,6 +726,7 @@ namespace
{ "iiiii", (void*)&CallFunc_I32_I32_I32_I32_RetI32 },

{ "ini", (void*)&CallFunc_I32IND_I32_RetI32 },
{ "iini", (void*)&CallFunc_I32_I32IND_I32_RetI32 },
{ "iinini", (void*)&CallFunc_I32_I32IND_I32_I32IND_I32_RetI32 },
{ "iniiiii", (void*)&CallFunc_I32IND_I32_I32_I32_I32_I32_RetI32 },

Expand Down
Loading