Skip to content

Commit

Permalink
JIT: Update class for Unsafe.As<>() (#85954)
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorBo authored May 9, 2023
1 parent 209d681 commit 7f35658
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 18 deletions.
7 changes: 4 additions & 3 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3923,7 +3923,7 @@ class Compiler
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
unsigned methodFlags,
int memberRef,
CORINFO_RESOLVED_TOKEN* pResolvedToken,
bool readonlyCall,
bool tailCall,
CORINFO_RESOLVED_TOKEN* pContstrainedResolvedToken,
Expand All @@ -3945,7 +3945,8 @@ class Compiler
GenTree* impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic,
CORINFO_CLASS_HANDLE clsHnd,
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig);
CORINFO_SIG_INFO* sig,
CORINFO_RESOLVED_TOKEN* pResolvedToken);

GenTree* impPrimitiveNamedIntrinsic(NamedIntrinsic intrinsic,
CORINFO_CLASS_HANDLE clsHnd,
Expand Down Expand Up @@ -4028,7 +4029,7 @@ class Compiler
Statement* impAppendTree(GenTree* tree, unsigned chkLevel, const DebugInfo& di, bool checkConsumedDebugInfo = true);
void impAssignTempGen(unsigned lclNum,
GenTree* val,
unsigned curLevel = CHECK_SPILL_NONE,
unsigned curLevel,
Statement** pAfterStmt = nullptr,
const DebugInfo& di = DebugInfo(),
BasicBlock* block = nullptr);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1638,7 +1638,7 @@ GenTree* Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken

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

Expand Down
50 changes: 41 additions & 9 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,8 @@ var_types Compiler::impImportCall(OPCODE opcode,

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

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

if (compDonotInline())
{
Expand Down Expand Up @@ -2301,7 +2300,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
unsigned methodFlags,
int memberRef,
CORINFO_RESOLVED_TOKEN* pResolvedToken,
bool readonlyCall,
bool tailCall,
CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken,
Expand All @@ -2312,6 +2311,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
bool mustExpand = false;
bool isSpecial = false;
const bool isIntrinsic = (methodFlags & CORINFO_FLG_INTRINSIC) != 0;
int memberRef = pResolvedToken->token;

NamedIntrinsic ni = lookupNamedIntrinsic(method);

Expand Down Expand Up @@ -2455,7 +2455,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
{
assert(ni > NI_SRCS_UNSAFE_START);
assert(!mustExpand);
return impSRCSUnsafeIntrinsic(ni, clsHnd, method, sig);
return impSRCSUnsafeIntrinsic(ni, clsHnd, method, sig, pResolvedToken);
}
else
{
Expand Down Expand Up @@ -3909,10 +3909,11 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
return retNode;
}

GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic,
CORINFO_CLASS_HANDLE clsHnd,
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig)
GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic,
CORINFO_CLASS_HANDLE clsHnd,
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
CORINFO_RESOLVED_TOKEN* pResolvedToken)
{
// NextCallRetAddr requires a CALL, so return nullptr.
if (info.compHasNextCallRetAddr)
Expand Down Expand Up @@ -3991,6 +3992,37 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic,
{
assert((sig->sigInst.methInstCount == 1) || (sig->sigInst.methInstCount == 2));

if (sig->sigInst.methInstCount == 1)
{
CORINFO_SIG_INFO exactSig;
info.compCompHnd->getMethodSig(pResolvedToken->hMethod, &exactSig);
const CORINFO_CLASS_HANDLE inst = exactSig.sigInst.methInst[0];
assert(inst != nullptr);

GenTree* op = impPopStack().val;
assert(op->TypeIs(TYP_REF));

JITDUMP("Expanding Unsafe.As<%s>(...)\n", eeGetClassName(inst));

bool isExact, isNonNull;
CORINFO_CLASS_HANDLE oldClass = gtGetClassHandle(op, &isExact, &isNonNull);
if ((oldClass != NO_CLASS_HANDLE) &&
((oldClass == inst) || !info.compCompHnd->isMoreSpecificType(oldClass, inst)))
{
JITDUMP("Unsafe.As: Keep using old '%s' type\n", eeGetClassName(oldClass));
return op;
}

// In order to change the class handle of the object we need to spill it to a temp
// and update class info for that temp.
unsigned localNum = lvaGrabTemp(true DEBUGARG("updating class info"));
impAssignTempGen(localNum, op, CHECK_SPILL_ALL);

// NOTE: we still can't say for sure that it is the exact type of the argument
lvaSetClass(localNum, inst, /*isExact*/ false);
return gtNewLclvNode(localNum, TYP_REF);
}

// ldarg.0
// ret

Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/jit/importervectorization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,12 +645,12 @@ GenTree* Compiler::impStringEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO
strLenOffset + sizeof(int), cmpMode);
if (unrolled != nullptr)
{
impAssignTempGen(varStrTmp, varStr);
impAssignTempGen(varStrTmp, varStr, CHECK_SPILL_NONE);
if (unrolled->OperIs(GT_QMARK))
{
// QMARK nodes cannot reside on the evaluation stack
unsigned rootTmp = lvaGrabTemp(true DEBUGARG("spilling unroll qmark"));
impAssignTempGen(rootTmp, unrolled);
impAssignTempGen(rootTmp, unrolled, CHECK_SPILL_NONE);
unrolled = gtNewLclvNode(rootTmp, TYP_INT);
}

Expand Down Expand Up @@ -797,13 +797,13 @@ GenTree* Compiler::impSpanEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO*
if (unrolled != nullptr)
{
// We succeeded, fill the placeholders:
impAssignTempGen(spanObjRef, impGetStructAddr(spanObj, CHECK_SPILL_NONE, true));
impAssignTempGen(spanDataTmp, spanData);
impAssignTempGen(spanObjRef, impGetStructAddr(spanObj, CHECK_SPILL_NONE, true), CHECK_SPILL_NONE);
impAssignTempGen(spanDataTmp, spanData, CHECK_SPILL_NONE);
if (unrolled->OperIs(GT_QMARK))
{
// QMARK can't be a root node, spill it to a temp
unsigned rootTmp = lvaGrabTemp(true DEBUGARG("spilling unroll qmark"));
impAssignTempGen(rootTmp, unrolled);
impAssignTempGen(rootTmp, unrolled, CHECK_SPILL_NONE);
unrolled = gtNewLclvNode(rootTmp, TYP_INT);
}

Expand Down

0 comments on commit 7f35658

Please sign in to comment.