Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Update class for Unsafe.As<>() #85954

Merged
merged 12 commits into from
May 9, 2023
5 changes: 3 additions & 2 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3945,7 +3945,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 @@ -3967,7 +3967,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
49 changes: 40 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 @@ -3905,10 +3905,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 @@ -3987,6 +3988,36 @@ 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) && !info.compCompHnd->isMoreSpecificType(oldClass, inst))
{
JITDUMP("Unsafe.As: Keep using old '%s' type as it is more specific\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);
EgorBo marked this conversation as resolved.
Show resolved Hide resolved

// 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