return NoVN;
}
-bool ValueNumStore::IsVNNewArr(ValueNum vn)
+bool ValueNumStore::IsVNNewArr(ValueNum vn, VNFuncApp* funcApp)
{
if (vn == NoVN) return false;
- VNFuncApp funcAttr;
- return (GetVNFunc(vn, &funcAttr) && funcAttr.m_func == VNF_JitNewArr);
+ bool result = false;
+ if (GetVNFunc(vn, funcApp))
+ {
+ result = (funcApp->m_func == VNF_JitNewArr) ||
+ (funcApp->m_func == VNF_JitReadyToRunNewArr);
+ }
+ return result;
}
int ValueNumStore::GetNewArrSize(ValueNum vn)
{
- if (vn == NoVN) return 0;
- VNFuncApp funcAttr;
- if (GetVNFunc(vn, &funcAttr) && funcAttr.m_func == VNF_JitNewArr)
+ VNFuncApp funcApp;
+ if (IsVNNewArr(vn, &funcApp))
{
- ValueNum arg1VN = funcAttr.m_args[1];
+ ValueNum arg1VN = funcApp.m_args[1];
if (IsVNConstant(arg1VN) && TypeOfVN(arg1VN) == TYP_INT)
{
return ConstantValue<int>(arg1VN);
{
unsigned nArgs = ValueNumStore::VNFuncArity(vnf);
assert(vnf != VNF_Boundary);
+ GenTreeArgList* args = call->gtCallArgs;
+ bool generateUniqueVN = false;
+ bool useEntryPointAddrAsArg0 = false;
+
switch (vnf)
{
case VNF_JitNew:
{
- GenTreeArgList* args = call->gtCallArgs;
- ValueNumPair vnp0; ValueNumPair vnp0x = ValueNumStore::VNPForEmptyExcSet();
- vnStore->VNPUnpackExc(args->Current()->gtVNPair, &vnp0, &vnp0x);
- // Generate unique VN so, VNForFunc generates a uniq value number for new.
- ValueNumPair vnpUniq;
- vnpUniq.SetBoth(vnStore->VNForExpr(call->TypeGet()));
- call->gtVNPair = vnStore->VNPWithExc(vnStore->VNPairForFunc(call->TypeGet(), vnf, vnp0, vnpUniq), vnp0x);
+ generateUniqueVN = true;
+ vnpExc = ValueNumStore::VNPForEmptyExcSet();
}
break;
case VNF_JitNewArr:
{
- GenTreeArgList* args = call->gtCallArgs;
- ValueNumPair vnp0; ValueNumPair vnp0x = ValueNumStore::VNPForEmptyExcSet();
- vnStore->VNPUnpackExc(args->Current()->gtVNPair, &vnp0, &vnp0x);
- args = args->Rest();
- ValueNumPair vnp1; ValueNumPair vnp1x = ValueNumStore::VNPForEmptyExcSet();
- vnStore->VNPUnpackExc(args->Current()->gtVNPair, &vnp1, &vnp1x);
-
- // Generate unique VN so, VNForFunc generates a uniq value number for new.
- ValueNumPair vnpUniq; vnpUniq.SetBoth(vnStore->VNForExpr(call->TypeGet()));
+ generateUniqueVN = true;
+ ValueNumPair vnp1 = vnStore->VNPNormVal(args->Rest()->Current()->gtVNPair);
// The New Array helper may throw an overflow exception
vnpExc = vnStore->VNPExcSetSingleton(vnStore->VNPairForFunc(TYP_REF, VNF_NewArrOverflowExc, vnp1));
-
- // Also include in the argument exception sets
- vnpExc = vnStore->VNPExcSetUnion(vnpExc, vnp0x);
- vnpExc = vnStore->VNPExcSetUnion(vnpExc, vnp1x);
-
- call->gtVNPair = vnStore->VNPWithExc(vnStore->VNPairForFunc(call->TypeGet(), vnf, vnp0, vnp1, vnpUniq), vnpExc);
}
break;
case VNF_BoxNullable:
{
- GenTreeArgList* args = call->gtCallArgs;
- ValueNumPair vnp0; ValueNumPair vnp0x = ValueNumStore::VNPForEmptyExcSet();
- vnStore->VNPUnpackExc(args->Current()->gtVNPair, &vnp0, &vnp0x);
- args = args->Rest();
- ValueNumPair vnp1; ValueNumPair vnp1x = ValueNumStore::VNPForEmptyExcSet();
- vnStore->VNPUnpackExc(args->Current()->gtVNPair, &vnp1, &vnp1x);
-
// Generate unique VN so, VNForFunc generates a uniq value number for box nullable.
- ValueNumPair vnpUniq;
- vnpUniq.SetBoth(vnStore->VNForExpr(call->TypeGet()));
-
// Alternatively instead of using vnpUniq below in VNPairForFunc(...),
// we could use the value number of what the byref arg0 points to.
//
// But retrieving the value number of what the byref arg0 points to is quite a bit more work
// and doing so only very rarely allows for an additional optimization.
+ generateUniqueVN = true;
+ }
+ break;
- // Also include in the argument exception sets
- vnpExc = vnStore->VNPExcSetUnion(vnpExc, vnp0x);
- vnpExc = vnStore->VNPExcSetUnion(vnpExc, vnp1x);
+ case VNF_JitReadyToRunNew:
+ {
+ generateUniqueVN = true;
+ vnpExc = ValueNumStore::VNPForEmptyExcSet();
+ useEntryPointAddrAsArg0 = true;
+ }
+ break;
- call->gtVNPair = vnStore->VNPWithExc(vnStore->VNPairForFunc(call->TypeGet(), vnf, vnp0, vnp1, vnpUniq), vnpExc);
+ case VNF_JitReadyToRunNewArr:
+ {
+ generateUniqueVN = true;
+ ValueNumPair vnp1 = vnStore->VNPNormVal(args->Current()->gtVNPair);
+
+ // The New Array helper may throw an overflow exception
+ vnpExc = vnStore->VNPExcSetSingleton(vnStore->VNPairForFunc(TYP_REF, VNF_NewArrOverflowExc, vnp1));
+ useEntryPointAddrAsArg0 = true;
+ }
+ break;
+
+ case VNF_ReadyToRunStaticBase:
+ case VNF_ReadyToRunIsInstanceOf:
+ case VNF_ReadyToRunCastClass:
+ {
+ useEntryPointAddrAsArg0 = true;
}
break;
default:
- GenTreeArgList* args = call->gtCallArgs;
- assert(s_helperCallProperties.IsPure(eeGetHelperNum(call->gtCallMethHnd)));
+ {
+ assert(s_helperCallProperties.IsPure(eeGetHelperNum(call->gtCallMethHnd)));
+ }
+ break;
+ }
+
+ if (generateUniqueVN)
+ {
+ nArgs--;
+ }
- if (nArgs == 0)
+ ValueNumPair vnpUniq;
+ if (generateUniqueVN)
+ {
+ // Generate unique VN so, VNForFunc generates a unique value number.
+ vnpUniq.SetBoth(vnStore->VNForExpr(call->TypeGet()));
+ }
+
+ if (nArgs == 0)
+ {
+ if (generateUniqueVN)
+ {
+ call->gtVNPair = vnStore->VNPairForFunc(call->TypeGet(), vnf, vnpUniq);
+ }
+ else
{
call->gtVNPair.SetBoth(vnStore->VNForFunc(call->TypeGet(), vnf));
}
+ }
+ else
+ {
+ // Has at least one argument.
+ ValueNumPair vnp0; ValueNumPair vnp0x = ValueNumStore::VNPForEmptyExcSet();
+#ifdef FEATURE_READYTORUN_COMPILER
+ if (useEntryPointAddrAsArg0)
+ {
+ ValueNum callAddrVN = vnStore->VNForPtrSizeIntCon((ssize_t)call->gtCall.gtEntryPoint.addr);
+ vnp0 = ValueNumPair(callAddrVN, callAddrVN);
+ }
else
+#endif
{
- // Has at least one argument.
+ assert(!useEntryPointAddrAsArg0);
ValueNumPair vnp0wx = args->Current()->gtVNPair;
- ValueNumPair vnp0; ValueNumPair vnp0x = ValueNumStore::VNPForEmptyExcSet();
vnStore->VNPUnpackExc(vnp0wx, &vnp0, &vnp0x);
// Also include in the argument exception sets
vnpExc = vnStore->VNPExcSetUnion(vnpExc, vnp0x);
args = args->Rest();
- if (nArgs == 1)
+ }
+ if (nArgs == 1)
+ {
+ if (generateUniqueVN)
+ {
+ call->gtVNPair = vnStore->VNPairForFunc(call->TypeGet(), vnf, vnp0, vnpUniq);
+ }
+ else
{
call->gtVNPair = vnStore->VNPairForFunc(call->TypeGet(), vnf, vnp0);
}
+ }
+ else
+ {
+ // Has at least two arguments.
+ ValueNumPair vnp1wx = args->Current()->gtVNPair;
+ ValueNumPair vnp1; ValueNumPair vnp1x = ValueNumStore::VNPForEmptyExcSet();
+ vnStore->VNPUnpackExc(vnp1wx, &vnp1, &vnp1x);
+ vnpExc = vnStore->VNPExcSetUnion(vnpExc, vnp1x);
+
+ args = args->Rest();
+ if (nArgs == 2)
+ {
+ if (generateUniqueVN)
+ {
+ call->gtVNPair = vnStore->VNPairForFunc(call->TypeGet(), vnf, vnp0, vnp1, vnpUniq);
+ }
+ else
+ {
+ call->gtVNPair = vnStore->VNPairForFunc(call->TypeGet(), vnf, vnp0, vnp1);
+ }
+ }
else
{
- // Has at least two arguments.
- ValueNumPair vnp1wx = args->Current()->gtVNPair;
- ValueNumPair vnp1; ValueNumPair vnp1x = ValueNumStore::VNPForEmptyExcSet();
- vnStore->VNPUnpackExc(vnp1wx, &vnp1, &vnp1x);
- vnpExc = vnStore->VNPExcSetUnion(vnpExc, vnp1x);
+ ValueNumPair vnp2wx = args->Current()->gtVNPair;
+ ValueNumPair vnp2; ValueNumPair vnp2x = ValueNumStore::VNPForEmptyExcSet();
+ vnStore->VNPUnpackExc(vnp2wx, &vnp2, &vnp2x);
+ vnpExc = vnStore->VNPExcSetUnion(vnpExc, vnp2x);
args = args->Rest();
- if (nArgs == 2)
+ assert(nArgs == 3); // Our current maximum.
+ assert(args == NULL);
+ if (generateUniqueVN)
{
- call->gtVNPair = vnStore->VNPairForFunc(call->TypeGet(), vnf, vnp0, vnp1);
+ call->gtVNPair = vnStore->VNPairForFunc(call->TypeGet(), vnf, vnp0, vnp1, vnp2, vnpUniq);
}
else
{
- ValueNumPair vnp2wx = args->Current()->gtVNPair;
- ValueNumPair vnp2; ValueNumPair vnp2x = ValueNumStore::VNPForEmptyExcSet();
- vnStore->VNPUnpackExc(vnp2wx, &vnp2, &vnp2x);
- vnpExc = vnStore->VNPExcSetUnion(vnpExc, vnp2x);
-
- args = args->Rest();
- assert(nArgs == 3); // Our current maximum.
- assert(args == NULL);
call->gtVNPair = vnStore->VNPairForFunc(call->TypeGet(), vnf, vnp0, vnp1, vnp2);
}
}
- // Add the accumulated exceptions.
- call->gtVNPair = vnStore->VNPWithExc(call->gtVNPair, vnpExc);
}
- break;
+ // Add the accumulated exceptions.
+ call->gtVNPair = vnStore->VNPWithExc(call->gtVNPair, vnpExc);
}
}
vnf = VNF_JitNew;
break;
+ case CORINFO_HELP_READYTORUN_NEW:
+ vnf = VNF_JitReadyToRunNew;
+ break;
+
case CORINFO_HELP_NEWARR_1_DIRECT:
case CORINFO_HELP_NEWARR_1_OBJ:
case CORINFO_HELP_NEWARR_1_VC:
vnf = VNF_JitNewArr;
break;
+ case CORINFO_HELP_READYTORUN_NEWARR_1:
+ vnf = VNF_JitReadyToRunNewArr;
+ break;
+
case CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
vnf = VNF_GetgenericsGcstaticBase; break;
case CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE:
vnf = VNF_GetsharedGcstaticBaseNoctor; break;
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
vnf = VNF_GetsharedNongcstaticBaseNoctor; break;
+ case CORINFO_HELP_READYTORUN_STATIC_BASE:
+ vnf = VNF_ReadyToRunStaticBase; break;
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
vnf = VNF_GetsharedGcstaticBaseDynamicclass; break;
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
case CORINFO_HELP_CHKCASTINTERFACE:
case CORINFO_HELP_CHKCASTANY:
vnf = VNF_CastClass; break;
+
+ case CORINFO_HELP_READYTORUN_CHKCAST:
+ vnf = VNF_ReadyToRunCastClass; break;
+
case CORINFO_HELP_ISINSTANCEOFCLASS:
case CORINFO_HELP_ISINSTANCEOFINTERFACE:
case CORINFO_HELP_ISINSTANCEOFARRAY:
case CORINFO_HELP_ISINSTANCEOFANY:
vnf = VNF_IsInstanceOf; break;
+ case CORINFO_HELP_READYTORUN_ISINSTANCEOF:
+ vnf = VNF_ReadyToRunIsInstanceOf; break;
+
case CORINFO_HELP_LDELEMA_REF:
vnf = VNF_LdElemA; break;
ValueNumFuncDef(CastClass, 2, false, false, false) // Args: 0: Handle of class being cast to, 1: object being cast.
ValueNumFuncDef(IsInstanceOf, 2, false, false, false) // Args: 0: Handle of class being queried, 1: object being queried.
-
+ValueNumFuncDef(ReadyToRunCastClass, 2, false, false, false) // Args: 0: Helper stub address, 1: object being cast.
+ValueNumFuncDef(ReadyToRunIsInstanceOf, 2, false, false, false) // Args: 0: Helper stub address, 1: object being queried.
ValueNumFuncDef(LdElemA, 3, false, false, false) // Args: 0: array value; 1: index value; 2: type handle of element.
ValueNumFuncDef(GetsharedNongcstaticBase, 2, false, true, true)
ValueNumFuncDef(GetsharedGcstaticBaseNoctor, 1, false, true, true)
ValueNumFuncDef(GetsharedNongcstaticBaseNoctor, 1, false, true, true)
+ValueNumFuncDef(ReadyToRunStaticBase, 1, false, true, true)
ValueNumFuncDef(GetsharedGcstaticBaseDynamicclass, 2, false, true, true)
ValueNumFuncDef(GetsharedNongcstaticBaseDynamicclass, 2, false, true, true)
ValueNumFuncDef(GetgenericsGcthreadstaticBase, 1, false, true, true)
ValueNumFuncDef(JitNew, 2, false, true, false)
ValueNumFuncDef(JitNewArr, 3, false, true, false)
+ValueNumFuncDef(JitReadyToRunNew, 2, false, true, false)
+ValueNumFuncDef(JitReadyToRunNewArr, 3, false, true, false)
ValueNumFuncDef(BoxNullable, 3, false, false, false)
ValueNumFuncDef(LT_UN, 2, false, false, false)