* Fix CoreRT frozen strings handling.
* Review response.
* Delete noway_assert.
* Additional checks.
* Fix failures.
assert(assertion->op2.u1.iconFlags != 0);
break;
case O1K_LCLVAR:
- assert((lvaTable[assertion->op1.lcl.lclNum].lvType != TYP_REF) || (assertion->op2.u1.iconVal == 0));
+ assert((lvaTable[assertion->op1.lcl.lclNum].lvType != TYP_REF) ||
+ (assertion->op2.u1.iconVal == 0) || doesMethodHaveFrozenString());
break;
case O1K_VALUE_NUMBER:
assert((vnStore->TypeOfVN(assertion->op1.vn) != TYP_REF) || (assertion->op2.u1.iconVal == 0));
#define OMF_HAS_EXPRUNTIMELOOKUP 0x00000100 // Method contains a runtime lookup to an expandable dictionary.
#define OMF_HAS_PATCHPOINT 0x00000200 // Method contains patchpoints
#define OMF_NEEDS_GCPOLLS 0x00000400 // Method needs GC polls
+#define OMF_HAS_FROZEN_STRING 0x00000800 // Method has a frozen string (REF constant int), currently only on CoreRT.
bool doesMethodHaveFatPointer()
{
void addFatPointerCandidate(GenTreeCall* call);
- bool doesMethodHaveGuardedDevirtualization()
+ bool doesMethodHaveFrozenString() const
+ {
+ return (optMethodFlags & OMF_HAS_FROZEN_STRING) != 0;
+ }
+
+ void setMethodHasFrozenString()
+ {
+ optMethodFlags |= OMF_HAS_FROZEN_STRING;
+ }
+
+ bool doesMethodHaveGuardedDevirtualization() const
{
return (optMethodFlags & OMF_HAS_GUARDEDDEVIRT) != 0;
}
{
assert(obj->gtType == TYP_REF || obj->gtType == TYP_BYREF);
- // We can see non-zero byrefs for RVA statics.
+ // We can see non-zero byrefs for RVA statics or for frozen strings.
if (obj->AsIntCon()->gtIconVal != 0)
{
- assert(obj->gtType == TYP_BYREF);
+#ifdef DEBUG
+ if (!obj->TypeIs(TYP_BYREF))
+ {
+ assert(obj->TypeIs(TYP_REF));
+ assert(obj->IsIconHandle(GTF_ICON_STR_HDL));
+ if (!doesMethodHaveFrozenString())
+ {
+ assert(compIsForInlining());
+ assert(impInlineInfo->InlinerCompiler->doesMethodHaveFrozenString());
+ }
+ }
+#endif // DEBUG
return obj;
}
switch (iat)
{
case IAT_VALUE:
- // For CoreRT only - Constant object can be a frozen string.
- if (!IsTargetAbi(CORINFO_CORERT_ABI))
- {
- // Non CoreRT - This case is illegal, creating a TYP_REF from an INT_CNS
- noway_assert(!"unreachable IAT_VALUE case in gtNewStringLiteralNode");
- }
-
+ setMethodHasFrozenString();
tree = gtNewIconEmbHndNode(pValue, nullptr, GTF_ICON_STR_HDL, nullptr);
tree->gtType = TYP_REF;
#ifdef DEBUG
// Check for assignment of NULL.
if (value->OperIs(GT_CNS_INT))
{
- JITDUMP("\nstelem of null: skipping covariant store check\n");
- assert((value->gtType == TYP_REF) && (value->AsIntCon()->gtIconVal == 0));
- return true;
+ assert(value->gtType == TYP_REF);
+ if (value->AsIntCon()->gtIconVal == 0)
+ {
+ JITDUMP("\nstelem of null: skipping covariant store check\n");
+ return true;
+ }
+ // Non-0 const refs can only occur with frozen objects
+ assert(value->IsIconHandle(GTF_ICON_STR_HDL));
+ assert(doesMethodHaveFrozenString() ||
+ (compIsForInlining() && impInlineInfo->InlinerCompiler->doesMethodHaveFrozenString()));
}
// Try and get a class handle for the array
}
else
{
- assert(tree->gtFlags == GTF_ICON_STR_HDL); // Constant object can be only frozen string.
+ assert(tree->IsIconHandle(GTF_ICON_STR_HDL)); // Constant object can be only frozen string.
tree->gtVNPair.SetBoth(
vnStore->VNForHandle(ssize_t(tree->AsIntConCommon()->IconValue()), tree->GetIconHandleFlag()));
}