Skip to content

Commit d104e3e

Browse files
[clr-interp] Fix issues found in the startup path with the interpreter (#118497)
- Fix virtual function resolution might not handle dispatch to a shared generic method if the exact type of the method is visible at compile time - Fix ldelema for an array of reference types doesn't handle shared generics properly - Fix issue where the readonly prefix for ldelema is ignored
1 parent dc00334 commit d104e3e

File tree

3 files changed

+57
-12
lines changed

3 files changed

+57
-12
lines changed

src/coreclr/interpreter/compiler.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3095,7 +3095,7 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
30953095
break;
30963096

30973097
case CORINFO_VIRTUALCALL_LDVIRTFTN:
3098-
if ((callInfo.sig.sigInst.methInstCount != 0) || (m_compHnd->getClassAttribs(resolvedCallToken.hClass) & CORINFO_FLG_SHAREDINST))
3098+
if ((callInfo.sig.sigInst.methInstCount != 0) || (m_compHnd->getMethodAttribs(callInfo.hMethod) & CORINFO_FLG_SHAREDINST))
30993099
{
31003100
assert(extraParamArgLocation == INT_MAX);
31013101
// We should not have a type argument for the ldvirtftn path since we don't know
@@ -5805,17 +5805,34 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
58055805
CorInfoType elemCorType = m_compHnd->asCorInfoType(elemClsHnd);
58065806

58075807
m_pStackPointer -= 2;
5808-
if (elemCorType == CORINFO_TYPE_CLASS)
5808+
if ((elemCorType == CORINFO_TYPE_CLASS) && !readonly)
58095809
{
5810-
AddIns(INTOP_LDELEMA_REF);
5811-
m_pLastNewIns->SetSVars2(m_pStackPointer[0].var, m_pStackPointer[1].var);
5812-
PushInterpType(InterpTypeByRef, elemClsHnd);
5813-
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
5814-
m_pLastNewIns->data[0] = m_compHnd->getClassSize(elemClsHnd);
5815-
m_pLastNewIns->data[1] = GetDataItemIndex(elemClsHnd);
5810+
CORINFO_GENERICHANDLE_RESULT embedInfo;
5811+
m_compHnd->embedGenericHandle(&resolvedToken, false, m_methodInfo->ftn, &embedInfo);
5812+
DeclarePointerIsClass((CORINFO_CLASS_HANDLE)embedInfo.compileTimeHandle);
5813+
5814+
if (embedInfo.lookup.lookupKind.needsRuntimeLookup)
5815+
{
5816+
GenericHandleData handleData = GenericHandleToGenericHandleData(embedInfo);
5817+
5818+
AddIns(INTOP_LDELEMA_REF_GENERIC);
5819+
m_pLastNewIns->SetSVars3(m_pStackPointer[0].var, m_pStackPointer[1].var, handleData.genericVar);
5820+
PushInterpType(InterpTypeByRef, elemClsHnd);
5821+
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
5822+
m_pLastNewIns->data[0] = handleData.dataItemIndex;
5823+
}
5824+
else
5825+
{
5826+
AddIns(INTOP_LDELEMA_REF);
5827+
m_pLastNewIns->SetSVars2(m_pStackPointer[0].var, m_pStackPointer[1].var);
5828+
PushInterpType(InterpTypeByRef, elemClsHnd);
5829+
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
5830+
m_pLastNewIns->data[0] = GetDataItemIndex(elemClsHnd);
5831+
}
58165832
}
58175833
else
58185834
{
5835+
readonly = false; // If readonly was set, it is no longer needed as its been handled.
58195836
AddIns(INTOP_LDELEMA);
58205837
m_pLastNewIns->SetSVars2(m_pStackPointer[0].var, m_pStackPointer[1].var);
58215838
PushInterpType(InterpTypeByRef, elemClsHnd);

src/coreclr/interpreter/intops.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ OPDEF(INTOP_STELEM_VT, "stelem.vt", 6, 0, 3, InterpOpTwoInts)
5353
OPDEF(INTOP_STELEM_VT_NOREF, "stelem.vt.noref", 5, 0, 3, InterpOpInt)
5454

5555
OPDEF(INTOP_LDELEMA, "ldelema", 5, 1, 2, InterpOpInt)
56-
OPDEF(INTOP_LDELEMA_REF, "ldelema.ref", 6, 1, 2, InterpOpTwoInts)
56+
OPDEF(INTOP_LDELEMA_REF, "ldelema.ref", 5, 1, 2, InterpOpClassHandle)
57+
OPDEF(INTOP_LDELEMA_REF_GENERIC, "ldelema.ref.generic", 6, 1, 3, InterpOpGenericLookup)
5758

5859
OPDEF(INTOP_MOV_I4_I1, "mov.i4.i1", 3, 1, 1, InterpOpNoArgs)
5960
OPDEF(INTOP_MOV_I4_U1, "mov.i4.u1", 3, 1, 1, InterpOpNoArgs)

src/coreclr/vm/interpexec.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,11 +2459,38 @@ do { \
24592459
COMPlusThrow(kIndexOutOfRangeException);
24602460

24612461
uint8_t* pData = arr->GetDataPtr();
2462-
size_t elemSize = ip[4];
2463-
void* elemAddr = pData + idx * elemSize;
2462+
void* elemAddr = pData + idx * sizeof(void*);
24642463

24652464
MethodTable* arrayElemMT = arr->GetArrayElementTypeHandle().AsMethodTable();
2466-
MethodTable* expectedMT = (MethodTable*)pMethod->pDataItems[ip[5]];
2465+
MethodTable* expectedMT = (MethodTable*)pMethod->pDataItems[ip[4]];
2466+
if (arrayElemMT != expectedMT)
2467+
{
2468+
COMPlusThrow(kArrayTypeMismatchException);
2469+
}
2470+
2471+
LOCAL_VAR(ip[1], void*) = elemAddr;
2472+
ip += 5;
2473+
break;
2474+
}
2475+
2476+
case INTOP_LDELEMA_REF_GENERIC:
2477+
{
2478+
BASEARRAYREF arrayRef = LOCAL_VAR(ip[2], BASEARRAYREF);
2479+
if (arrayRef == NULL)
2480+
COMPlusThrow(kNullReferenceException);
2481+
2482+
ArrayBase* arr = (ArrayBase*)OBJECTREFToObject(arrayRef);
2483+
uint32_t len = arr->GetNumComponents();
2484+
uint32_t idx = (uint32_t)LOCAL_VAR(ip[3], int32_t);
2485+
if (idx >= len)
2486+
COMPlusThrow(kIndexOutOfRangeException);
2487+
2488+
uint8_t* pData = arr->GetDataPtr();
2489+
void* elemAddr = pData + idx * sizeof(void*);
2490+
2491+
MethodTable* arrayElemMT = arr->GetArrayElementTypeHandle().AsMethodTable();
2492+
InterpGenericLookup *pLookup = (InterpGenericLookup*)&pMethod->pDataItems[ip[5]];
2493+
MethodTable* expectedMT = (MethodTable*)DoGenericLookup(LOCAL_VAR(ip[4], void*), pLookup);
24672494
if (arrayElemMT != expectedMT)
24682495
{
24692496
COMPlusThrow(kArrayTypeMismatchException);

0 commit comments

Comments
 (0)