From: Jakob Botsch Nielsen Date: Fri, 4 Sep 2020 05:47:26 +0000 (+0200) Subject: Properly handle byrefs in tailcall helper stubs (#41815) X-Git-Tag: submit/tizen/20210909.063632~5628 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8ceca25036b395d12c1feedf6f3318786ddb355c;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Properly handle byrefs in tailcall helper stubs (#41815) * Properly handle byrefs in tailcall helper stubs Switch to using ByReference instead of using stind.i/ldind.i and relying on the JIT to report the locations being moved between. Fixes #41555 * Move NextCallReturnAddress call back --- diff --git a/src/coreclr/src/vm/corelib.h b/src/coreclr/src/vm/corelib.h index 044147c..bd5a8a6 100644 --- a/src/coreclr/src/vm/corelib.h +++ b/src/coreclr/src/vm/corelib.h @@ -589,6 +589,8 @@ DEFINE_FIELD(NULL, VALUE, Value) DEFINE_CLASS(NULLABLE, System, Nullable`1) DEFINE_CLASS(BYREFERENCE, System, ByReference`1) +DEFINE_METHOD(BYREFERENCE, CTOR, .ctor, NoSig) +DEFINE_METHOD(BYREFERENCE, GET_VALUE, get_Value, NoSig) DEFINE_CLASS(SPAN, System, Span`1) DEFINE_METHOD(SPAN, GET_ITEM, get_Item, IM_Int_RetRefT) DEFINE_CLASS(READONLY_SPAN, System, ReadOnlySpan`1) diff --git a/src/coreclr/src/vm/tailcallhelp.cpp b/src/coreclr/src/vm/tailcallhelp.cpp index 10a9c50..7dcb8dd 100644 --- a/src/coreclr/src/vm/tailcallhelp.cpp +++ b/src/coreclr/src/vm/tailcallhelp.cpp @@ -372,7 +372,6 @@ MethodDesc* TailCallHelp::CreateStoreArgsStub(TailCallInfo& info) for (COUNT_T i = 0; i < info.ArgBufLayout.Values.GetCount(); i++) { const ArgBufferValue& arg = info.ArgBufLayout.Values[i]; - CorElementType ty = arg.TyHnd.GetSignatureCorElementType(); emitOffs(arg.Offset); pCode->EmitLDARG(i); @@ -629,35 +628,63 @@ void TailCallHelp::CreateCallTargetStubSig(const TailCallInfo& info, SigBuilder* #endif // _DEBUG } +// Get TypeHandle for ByReference +static TypeHandle GetByReferenceOfByteType() +{ + TypeHandle byteTH(CoreLibBinder::GetElementType(ELEMENT_TYPE_U1)); + Instantiation byteInst(&byteTH, 1); + TypeHandle th = TypeHandle(CoreLibBinder::GetClass(CLASS__BYREFERENCE)).Instantiate(byteInst); + return th; +} + +// Get MethodDesc* for ByReference::get_Value +static MethodDesc* GetByReferenceOfByteValueGetter() +{ + MethodDesc* getter = CoreLibBinder::GetMethod(METHOD__BYREFERENCE__GET_VALUE); + getter = + MethodDesc::FindOrCreateAssociatedMethodDesc( + getter, + GetByReferenceOfByteType().GetMethodTable(), + false, + Instantiation(), + TRUE); + + return getter; +} + +// Get MethodDesc* for ByReference::.ctor +static MethodDesc* GetByReferenceOfByteCtor() +{ + MethodDesc* ctor = CoreLibBinder::GetMethod(METHOD__BYREFERENCE__CTOR); + ctor = + MethodDesc::FindOrCreateAssociatedMethodDesc( + ctor, + GetByReferenceOfByteType().GetMethodTable(), + false, + Instantiation(), + TRUE); + + return ctor; +} + void TailCallHelp::EmitLoadTyHnd(ILCodeStream* stream, TypeHandle tyHnd) { - CorElementType ty = tyHnd.GetSignatureCorElementType(); if (tyHnd.IsByRef()) - { - // Note: we can use an "untracked" ldind.i here even with byrefs because - // we are loading between two tracked positions. - stream->EmitLDIND_I(); - } + stream->EmitCALL(stream->GetToken(GetByReferenceOfByteValueGetter()), 1, 1); else - { - int token = stream->GetToken(tyHnd); - stream->EmitLDOBJ(token); - } + stream->EmitLDOBJ(stream->GetToken(tyHnd)); } void TailCallHelp::EmitStoreTyHnd(ILCodeStream* stream, TypeHandle tyHnd) { - CorElementType ty = tyHnd.GetSignatureCorElementType(); if (tyHnd.IsByRef()) { - // Note: we can use an "untracked" stind.i here even with byrefs because - // we are storing between two tracked positions. - stream->EmitSTIND_I(); + stream->EmitNEWOBJ(stream->GetToken(GetByReferenceOfByteCtor()), 1); + stream->EmitSTOBJ(stream->GetToken(GetByReferenceOfByteType())); } else { - int token = stream->GetToken(tyHnd); - stream->EmitSTOBJ(token); + stream->EmitSTOBJ(stream->GetToken(tyHnd)); } }