Skip to content

Commit 7f35658

Browse files
authored
JIT: Update class for Unsafe.As<>() (#85954)
1 parent 209d681 commit 7f35658

File tree

4 files changed

+51
-18
lines changed

4 files changed

+51
-18
lines changed

src/coreclr/jit/compiler.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3923,7 +3923,7 @@ class Compiler
39233923
CORINFO_METHOD_HANDLE method,
39243924
CORINFO_SIG_INFO* sig,
39253925
unsigned methodFlags,
3926-
int memberRef,
3926+
CORINFO_RESOLVED_TOKEN* pResolvedToken,
39273927
bool readonlyCall,
39283928
bool tailCall,
39293929
CORINFO_RESOLVED_TOKEN* pContstrainedResolvedToken,
@@ -3945,7 +3945,8 @@ class Compiler
39453945
GenTree* impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic,
39463946
CORINFO_CLASS_HANDLE clsHnd,
39473947
CORINFO_METHOD_HANDLE method,
3948-
CORINFO_SIG_INFO* sig);
3948+
CORINFO_SIG_INFO* sig,
3949+
CORINFO_RESOLVED_TOKEN* pResolvedToken);
39493950

39503951
GenTree* impPrimitiveNamedIntrinsic(NamedIntrinsic intrinsic,
39513952
CORINFO_CLASS_HANDLE clsHnd,
@@ -4028,7 +4029,7 @@ class Compiler
40284029
Statement* impAppendTree(GenTree* tree, unsigned chkLevel, const DebugInfo& di, bool checkConsumedDebugInfo = true);
40294030
void impAssignTempGen(unsigned lclNum,
40304031
GenTree* val,
4031-
unsigned curLevel = CHECK_SPILL_NONE,
4032+
unsigned curLevel,
40324033
Statement** pAfterStmt = nullptr,
40334034
const DebugInfo& di = DebugInfo(),
40344035
BasicBlock* block = nullptr);

src/coreclr/jit/importer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1638,7 +1638,7 @@ GenTree* Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken
16381638

16391639
// Spilling it to a temp improves CQ (mainly in Tier0)
16401640
unsigned callLclNum = lvaGrabTemp(true DEBUGARG("spilling helperCall"));
1641-
impAssignTempGen(callLclNum, helperCall);
1641+
impAssignTempGen(callLclNum, helperCall, CHECK_SPILL_NONE);
16421642
return gtNewLclvNode(callLclNum, helperCall->TypeGet());
16431643
}
16441644

src/coreclr/jit/importercalls.cpp

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,8 @@ var_types Compiler::impImportCall(OPCODE opcode,
233233

234234
const bool isTailCall = canTailCall && (tailCallFlags != 0);
235235

236-
call =
237-
impIntrinsic(newobjThis, clsHnd, methHnd, sig, mflags, pResolvedToken->token, isReadonlyCall,
238-
isTailCall, pConstrainedResolvedToken, callInfo->thisTransform, &ni, &isSpecialIntrinsic);
236+
call = impIntrinsic(newobjThis, clsHnd, methHnd, sig, mflags, pResolvedToken, isReadonlyCall, isTailCall,
237+
pConstrainedResolvedToken, callInfo->thisTransform, &ni, &isSpecialIntrinsic);
239238

240239
if (compDonotInline())
241240
{
@@ -2301,7 +2300,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
23012300
CORINFO_METHOD_HANDLE method,
23022301
CORINFO_SIG_INFO* sig,
23032302
unsigned methodFlags,
2304-
int memberRef,
2303+
CORINFO_RESOLVED_TOKEN* pResolvedToken,
23052304
bool readonlyCall,
23062305
bool tailCall,
23072306
CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken,
@@ -2312,6 +2311,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
23122311
bool mustExpand = false;
23132312
bool isSpecial = false;
23142313
const bool isIntrinsic = (methodFlags & CORINFO_FLG_INTRINSIC) != 0;
2314+
int memberRef = pResolvedToken->token;
23152315

23162316
NamedIntrinsic ni = lookupNamedIntrinsic(method);
23172317

@@ -2455,7 +2455,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
24552455
{
24562456
assert(ni > NI_SRCS_UNSAFE_START);
24572457
assert(!mustExpand);
2458-
return impSRCSUnsafeIntrinsic(ni, clsHnd, method, sig);
2458+
return impSRCSUnsafeIntrinsic(ni, clsHnd, method, sig, pResolvedToken);
24592459
}
24602460
else
24612461
{
@@ -3909,10 +3909,11 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
39093909
return retNode;
39103910
}
39113911

3912-
GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic,
3913-
CORINFO_CLASS_HANDLE clsHnd,
3914-
CORINFO_METHOD_HANDLE method,
3915-
CORINFO_SIG_INFO* sig)
3912+
GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic,
3913+
CORINFO_CLASS_HANDLE clsHnd,
3914+
CORINFO_METHOD_HANDLE method,
3915+
CORINFO_SIG_INFO* sig,
3916+
CORINFO_RESOLVED_TOKEN* pResolvedToken)
39163917
{
39173918
// NextCallRetAddr requires a CALL, so return nullptr.
39183919
if (info.compHasNextCallRetAddr)
@@ -3991,6 +3992,37 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic,
39913992
{
39923993
assert((sig->sigInst.methInstCount == 1) || (sig->sigInst.methInstCount == 2));
39933994

3995+
if (sig->sigInst.methInstCount == 1)
3996+
{
3997+
CORINFO_SIG_INFO exactSig;
3998+
info.compCompHnd->getMethodSig(pResolvedToken->hMethod, &exactSig);
3999+
const CORINFO_CLASS_HANDLE inst = exactSig.sigInst.methInst[0];
4000+
assert(inst != nullptr);
4001+
4002+
GenTree* op = impPopStack().val;
4003+
assert(op->TypeIs(TYP_REF));
4004+
4005+
JITDUMP("Expanding Unsafe.As<%s>(...)\n", eeGetClassName(inst));
4006+
4007+
bool isExact, isNonNull;
4008+
CORINFO_CLASS_HANDLE oldClass = gtGetClassHandle(op, &isExact, &isNonNull);
4009+
if ((oldClass != NO_CLASS_HANDLE) &&
4010+
((oldClass == inst) || !info.compCompHnd->isMoreSpecificType(oldClass, inst)))
4011+
{
4012+
JITDUMP("Unsafe.As: Keep using old '%s' type\n", eeGetClassName(oldClass));
4013+
return op;
4014+
}
4015+
4016+
// In order to change the class handle of the object we need to spill it to a temp
4017+
// and update class info for that temp.
4018+
unsigned localNum = lvaGrabTemp(true DEBUGARG("updating class info"));
4019+
impAssignTempGen(localNum, op, CHECK_SPILL_ALL);
4020+
4021+
// NOTE: we still can't say for sure that it is the exact type of the argument
4022+
lvaSetClass(localNum, inst, /*isExact*/ false);
4023+
return gtNewLclvNode(localNum, TYP_REF);
4024+
}
4025+
39944026
// ldarg.0
39954027
// ret
39964028

src/coreclr/jit/importervectorization.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -645,12 +645,12 @@ GenTree* Compiler::impStringEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO
645645
strLenOffset + sizeof(int), cmpMode);
646646
if (unrolled != nullptr)
647647
{
648-
impAssignTempGen(varStrTmp, varStr);
648+
impAssignTempGen(varStrTmp, varStr, CHECK_SPILL_NONE);
649649
if (unrolled->OperIs(GT_QMARK))
650650
{
651651
// QMARK nodes cannot reside on the evaluation stack
652652
unsigned rootTmp = lvaGrabTemp(true DEBUGARG("spilling unroll qmark"));
653-
impAssignTempGen(rootTmp, unrolled);
653+
impAssignTempGen(rootTmp, unrolled, CHECK_SPILL_NONE);
654654
unrolled = gtNewLclvNode(rootTmp, TYP_INT);
655655
}
656656

@@ -797,13 +797,13 @@ GenTree* Compiler::impSpanEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO*
797797
if (unrolled != nullptr)
798798
{
799799
// We succeeded, fill the placeholders:
800-
impAssignTempGen(spanObjRef, impGetStructAddr(spanObj, CHECK_SPILL_NONE, true));
801-
impAssignTempGen(spanDataTmp, spanData);
800+
impAssignTempGen(spanObjRef, impGetStructAddr(spanObj, CHECK_SPILL_NONE, true), CHECK_SPILL_NONE);
801+
impAssignTempGen(spanDataTmp, spanData, CHECK_SPILL_NONE);
802802
if (unrolled->OperIs(GT_QMARK))
803803
{
804804
// QMARK can't be a root node, spill it to a temp
805805
unsigned rootTmp = lvaGrabTemp(true DEBUGARG("spilling unroll qmark"));
806-
impAssignTempGen(rootTmp, unrolled);
806+
impAssignTempGen(rootTmp, unrolled, CHECK_SPILL_NONE);
807807
unrolled = gtNewLclvNode(rootTmp, TYP_INT);
808808
}
809809

0 commit comments

Comments
 (0)