Skip to content
Merged
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
137 changes: 137 additions & 0 deletions src/coreclr/interpreter/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1645,6 +1645,11 @@ static void FreeInterpreterStackMap(void *key, void *value, void *userdata)
delete (InterpreterStackMap *)value;
}

static void InterpreterCompilerBreak()
{
assert(!"InterpreterCompilerBreak reached");
}

InterpCompiler::InterpCompiler(COMP_HANDLE compHnd,
CORINFO_METHOD_INFO* methodInfo)
: m_stackmapsByClass(FreeInterpreterStackMap)
Expand Down Expand Up @@ -1689,6 +1694,13 @@ InterpMethod* InterpCompiler::CompileMethod()
printf("Interpreter compile method %s\n", m_methodName.GetUnderlyingArray());
}
#endif
#ifdef DEBUG
if (InterpConfig.InterpBreak().contains(m_compHnd, m_methodInfo->ftn, m_classHnd, &m_methodInfo->args))
{
InterpreterCompilerBreak();
}
#endif

m_isSynchronized = m_compHnd->getMethodAttribs(m_methodHnd) & CORINFO_FLG_SYNCH;
if (m_isSynchronized)
{
Expand Down Expand Up @@ -3679,6 +3691,90 @@ void InterpCompiler::EmitCalli(bool isTailCall, void* calliCookie, int callIFunc
m_pLastNewIns->SetSVars2(CALL_ARGS_SVAR, callIFunctionPointerVar);
}

void InterpCompiler::EmitCanAccessCallout(CORINFO_RESOLVED_TOKEN *pResolvedToken)
{
CORINFO_HELPER_DESC calloutHelper;
CorInfoIsAccessAllowedResult accessAllowed =
m_compHnd->canAccessClass(pResolvedToken, m_methodHnd, &calloutHelper);

// Inject call to callsite callout helper
EmitCallsiteCallout(accessAllowed, &calloutHelper);
}

void InterpCompiler::EmitCallsiteCallout(CorInfoIsAccessAllowedResult accessAllowed, CORINFO_HELPER_DESC* calloutDesc)
{
if (accessAllowed == CORINFO_ACCESS_ILLEGAL)
{
int32_t svars[CORINFO_ACCESS_ALLOWED_MAX_ARGS];

for (unsigned i = 0; i < calloutDesc->numArgs; i++)
{
void *value = NULL;
void *pValue = NULL;

switch (calloutDesc->args[i].argType)
{
case CORINFO_HELPER_ARG_TYPE_Class:
value = (void*)m_compHnd->embedClassHandle(calloutDesc->args[i].classHandle, &pValue);
break;
case CORINFO_HELPER_ARG_TYPE_Method:
value = (void*)m_compHnd->embedMethodHandle(calloutDesc->args[i].methodHandle, &pValue);
break;
default:
NO_WAY("Callsite callout with unsupported arg type");
}

if (value == NULL)
{
if (pValue == NULL)
{
NO_WAY("Callsite callout with unsupported arg type");
}

AddIns(INTOP_LDPTR);
m_pLastNewIns->data[0] = GetDataItemIndex(pValue);
PushInterpType(InterpTypeI, nullptr);
int tempVar = m_pStackPointer[-1].var;
m_pLastNewIns->SetDVar(tempVar);

// Now we generate an LDIND_I to get the actual value out of the ref
AddIns(INTOP_LDIND_I);
m_pLastNewIns->data[0] = 0;
m_pLastNewIns->SetSVar(tempVar);
m_pStackPointer--;
PushInterpType(InterpTypeI, NULL);
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
m_pStackPointer--;
svars[i] = m_pStackPointer[0].var;
}
else
{
AddIns(INTOP_LDPTR);
m_pLastNewIns->data[0] = GetDataItemIndex(value);
PushInterpType(InterpTypeI, nullptr);
svars[i] = m_pStackPointer[-1].var;
m_pLastNewIns->SetDVar(svars[i]);
m_pStackPointer--;
}
}
if (calloutDesc->numArgs == 2)
{
AddIns(INTOP_CALL_HELPER_V_SS);
m_pLastNewIns->SetSVars2(svars[0], svars[1]);
}
else if (calloutDesc->numArgs == 3)
{
AddIns(INTOP_CALL_HELPER_V_SSS);
m_pLastNewIns->SetSVars3(svars[0], svars[1], svars[2]);
}
else
{
NO_WAY("Callsite callout with unsupported number of args");
}
m_pLastNewIns->data[0] = GetDataForHelperFtn(calloutDesc->helperNum);
}
}

void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool readonly, bool tailcall, bool newObj, bool isCalli)
{
uint32_t token = getU4LittleEndian(m_ip + 1);
Expand Down Expand Up @@ -3761,6 +3857,10 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
flags = (CORINFO_CALLINFO_FLAGS)(flags | CORINFO_CALLINFO_CALLVIRT);

m_compHnd->getCallInfo(&resolvedCallToken, pConstrainedToken, m_methodInfo->ftn, flags, &callInfo);

// Inject call to callsite callout helper
EmitCallsiteCallout(callInfo.accessAllowed, &callInfo.callsiteCalloutHelper);

if (callInfo.methodFlags & CORINFO_FLG_INTRINSIC)
{
NamedIntrinsic ni = GetNamedIntrinsic(m_compHnd, m_methodHnd, callInfo.hMethod);
Expand Down Expand Up @@ -6293,6 +6393,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
ResolveToken(token, CORINFO_TOKENKIND_Field, &resolvedToken);
m_compHnd->getFieldInfo(&resolvedToken, m_methodHnd, CORINFO_ACCESS_ADDRESS, &fieldInfo);

// Inject call to callsite callout helper
EmitCallsiteCallout(fieldInfo.accessAllowed, &fieldInfo.accessCalloutHelper);

bool isStatic = !!(fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC);

if (isStatic)
Expand Down Expand Up @@ -6324,6 +6427,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
ResolveToken(token, CORINFO_TOKENKIND_Field, &resolvedToken);
m_compHnd->getFieldInfo(&resolvedToken, m_methodHnd, CORINFO_ACCESS_GET, &fieldInfo);

// Inject call to callsite callout helper
EmitCallsiteCallout(fieldInfo.accessAllowed, &fieldInfo.accessCalloutHelper);

CorInfoType fieldType = fieldInfo.fieldType;
bool isStatic = !!(fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC);
InterpType interpFieldType = GetInterpType(fieldType);
Expand Down Expand Up @@ -6384,6 +6490,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
ResolveToken(token, CORINFO_TOKENKIND_Field, &resolvedToken);
m_compHnd->getFieldInfo(&resolvedToken, m_methodHnd, CORINFO_ACCESS_GET, &fieldInfo);

// Inject call to callsite callout helper
EmitCallsiteCallout(fieldInfo.accessAllowed, &fieldInfo.accessCalloutHelper);

CorInfoType fieldType = fieldInfo.fieldType;
bool isStatic = !!(fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC);
InterpType interpFieldType = GetInterpType(fieldType);
Expand Down Expand Up @@ -6418,6 +6527,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
ResolveToken(token, CORINFO_TOKENKIND_Field, &resolvedToken);
m_compHnd->getFieldInfo(&resolvedToken, m_methodHnd, CORINFO_ACCESS_ADDRESS, &fieldInfo);

// Inject call to callsite callout helper
EmitCallsiteCallout(fieldInfo.accessAllowed, &fieldInfo.accessCalloutHelper);

EmitStaticFieldAddress(&fieldInfo, &resolvedToken);

m_ip += 5;
Expand All @@ -6431,6 +6543,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
ResolveToken(token, CORINFO_TOKENKIND_Field, &resolvedToken);
m_compHnd->getFieldInfo(&resolvedToken, m_methodHnd, CORINFO_ACCESS_GET, &fieldInfo);

// Inject call to callsite callout helper
EmitCallsiteCallout(fieldInfo.accessAllowed, &fieldInfo.accessCalloutHelper);

CorInfoType fieldType = fieldInfo.fieldType;
InterpType interpFieldType = GetInterpType(fieldType);

Expand All @@ -6454,6 +6569,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
ResolveToken(token, CORINFO_TOKENKIND_Field, &resolvedToken);
m_compHnd->getFieldInfo(&resolvedToken, m_methodHnd, CORINFO_ACCESS_GET, &fieldInfo);

// Inject call to callsite callout helper
EmitCallsiteCallout(fieldInfo.accessAllowed, &fieldInfo.accessCalloutHelper);

CorInfoType fieldType = fieldInfo.fieldType;
InterpType interpFieldType = GetInterpType(fieldType);

Expand Down Expand Up @@ -6584,6 +6702,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)

CORINFO_RESOLVED_TOKEN resolvedToken;
ResolveToken(token, CORINFO_TOKENKIND_Class, &resolvedToken);

EmitCanAccessCallout(&resolvedToken);

CORINFO_GENERICHANDLE_RESULT embedInfo;
m_compHnd->embedGenericHandle(&resolvedToken, true, m_methodInfo->ftn, &embedInfo);
assert(embedInfo.compileTimeHandle != NULL);
Expand Down Expand Up @@ -6834,6 +6955,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
NO_WAY("Currently do not support LDFTN of Parameterized functions");
}

// Inject call to callsite callout helper
EmitCallsiteCallout(callInfo.accessAllowed, &callInfo.callsiteCalloutHelper);

m_pStackPointer--;
int thisVar = m_pStackPointer[0].var;

Expand Down Expand Up @@ -6864,6 +6988,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
NO_WAY("Currently do not support LDFTN of Parameterized functions");
}

// Inject call to callsite callout helper
EmitCallsiteCallout(callInfo.accessAllowed, &callInfo.callsiteCalloutHelper);

DO_LDFTN:
if (callInfo.kind == CORINFO_CALL)
{
Expand Down Expand Up @@ -6961,6 +7088,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
CHECK_STACK(1);
CORINFO_RESOLVED_TOKEN resolvedToken;
ResolveToken(token, CORINFO_TOKENKIND_Box, &resolvedToken);

EmitCanAccessCallout(&resolvedToken);

if (m_compHnd->isValueClass(resolvedToken.hClass))
{
CORINFO_GENERICHANDLE_RESULT embedInfo;
Expand All @@ -6980,6 +7110,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
CHECK_STACK(1);
CORINFO_RESOLVED_TOKEN resolvedToken;
ResolveToken(token, CORINFO_TOKENKIND_Class, &resolvedToken);

EmitCanAccessCallout(&resolvedToken);

CORINFO_GENERICHANDLE_RESULT embedInfo;
m_compHnd->embedGenericHandle(&resolvedToken, false, m_methodInfo->ftn, &embedInfo);
DeclarePointerIsClass((CORINFO_CLASS_HANDLE)embedInfo.compileTimeHandle);
Expand Down Expand Up @@ -7067,6 +7200,8 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
CORINFO_RESOLVED_TOKEN resolvedToken;
ResolveToken(token, CORINFO_TOKENKIND_Newarr, &resolvedToken);

EmitCanAccessCallout(&resolvedToken);

CORINFO_CLASS_HANDLE arrayClsHnd = resolvedToken.hClass;
CorInfoHelpFunc helpFunc = m_compHnd->getNewArrHelper(arrayClsHnd);
DeclarePointerIsClass(arrayClsHnd);
Expand Down Expand Up @@ -7465,6 +7600,8 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
CORINFO_RESOLVED_TOKEN resolvedToken;
ResolveToken(getU4LittleEndian(m_ip + 1), CORINFO_TOKENKIND_Casting, &resolvedToken);

EmitCanAccessCallout(&resolvedToken);

CorInfoHelpFunc castingHelper = m_compHnd->getCastingHelper(&resolvedToken, *m_ip == CEE_CASTCLASS /* throwing */);

CORINFO_GENERICHANDLE_RESULT embedInfo;
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/interpreter/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,8 @@ class InterpCompiler
void EmitBox(StackInfo* pStackInfo, const CORINFO_GENERICHANDLE_RESULT &boxType, bool argByRef);
void EmitLeave(int32_t ilOffset, int32_t target);
void EmitPushSyncObject();
void EmitCallsiteCallout(CorInfoIsAccessAllowedResult accessAllowed, CORINFO_HELPER_DESC* calloutDesc);
void EmitCanAccessCallout(CORINFO_RESOLVED_TOKEN *pResolvedToken);

// Var Offset allocator
TArray<InterpInst*, MemPoolAllocator> *m_pActiveCalls;
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/interpreter/inc/intops.def
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,10 @@ OPDEF(INTOP_CALL_HELPER_V_AGS, "call.helper.v.ags", 6, 1, 2, InterpOpGenericHelp
// Call a helper function with a signature of void helper(SVar1, AddrOfSVar2)
OPDEF(INTOP_CALL_HELPER_V_SA, "call.helper.v.sa", 4, 0, 2, InterpOpHelperFtnNoArgs)

// Call a helper function with a signature of void helper(Pointer,Pointer,Pointer)
OPDEF(INTOP_CALL_HELPER_V_SS, "call.helper.v.ss", 4, 0, 2, InterpOpHelperFtnNoArgs)
OPDEF(INTOP_CALL_HELPER_V_SSS, "call.helper.v.sss", 5, 0, 3, InterpOpHelperFtnNoArgs)

OPDEF(INTOP_GENERICLOOKUP, "generic", 4, 1, 1, InterpOpGenericLookup)

OPDEF(INTOP_CALL_FINALLY, "call.finally", 2, 0, 0, InterpOpBranch)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/interpreter/interpconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
RELEASE_CONFIG_METHODSET(Interpreter, "Interpreter")
CONFIG_METHODSET(InterpHaltOnCall, "InterpHaltOnCall"); // Assert in the compiler when compiling a call to these method(s)
CONFIG_METHODSET(InterpHalt, "InterpHalt");
CONFIG_METHODSET(InterpBreak, "InterpBreak"); // Break into the debugger when compiling this method
CONFIG_METHODSET(InterpDump, "InterpDump");
CONFIG_INTEGER(InterpList, "InterpList", 0); // List the methods which are compiled by the interpreter JIT
RELEASE_CONFIG_INTEGER(InterpMode, "InterpMode", 0); // Interpreter mode, one of the following:
Expand Down
53 changes: 53 additions & 0 deletions src/coreclr/vm/interpexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2333,6 +2333,59 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
ip += 4;
break;
}
case INTOP_CALL_HELPER_V_SS:
{
void* helperArg1 = LOCAL_VAR(ip[1], void*);
void* helperArg2 = LOCAL_VAR(ip[2], void*);
MethodDesc *pILTargetMethod = NULL;
HELPER_FTN_V_PP helperFtn = GetPossiblyIndirectHelper<HELPER_FTN_V_PP>(pMethod, ip[3], &pILTargetMethod);
if (pILTargetMethod != NULL)
{
returnOffset = pMethod->allocaSize;
callArgsOffset = pMethod->allocaSize;

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

targetMethod = pILTargetMethod;
ip += 4;
goto CALL_INTERP_METHOD;
}

_ASSERTE(helperFtn != NULL);
helperFtn(helperArg1, helperArg2);
ip += 4;
break;
}

case INTOP_CALL_HELPER_V_SSS:
{
void* helperArg1 = LOCAL_VAR(ip[1], void*);
void* helperArg2 = LOCAL_VAR(ip[2], void*);
void* helperArg3 = LOCAL_VAR(ip[3], void*);
MethodDesc *pILTargetMethod = NULL;
HELPER_FTN_V_PPP helperFtn = GetPossiblyIndirectHelper<HELPER_FTN_V_PPP>(pMethod, ip[4], &pILTargetMethod);
if (pILTargetMethod != NULL)
{
returnOffset = pMethod->allocaSize;
callArgsOffset = pMethod->allocaSize;

// Pass arguments to the target method
LOCAL_VAR(callArgsOffset, void*) = helperArg1;
LOCAL_VAR(callArgsOffset + INTERP_STACK_SLOT_SIZE, void*) = helperArg2;
LOCAL_VAR(callArgsOffset + 2 * INTERP_STACK_SLOT_SIZE, void*) = helperArg3;

targetMethod = pILTargetMethod;
ip += 5;
goto CALL_INTERP_METHOD;
}

_ASSERTE(helperFtn != NULL);
helperFtn(helperArg1, helperArg2, helperArg3);
ip += 5;
break;
}

case INTOP_CALLVIRT_TAIL:
case INTOP_CALLVIRT:
Expand Down
Loading