From: Atsushi Kanamori Date: Thu, 19 Apr 2018 19:23:43 +0000 (-0700) Subject: Rollback https://github.com/dotnet/coreclr/pull/17639 (#17671) X-Git-Tag: accepted/tizen/unified/20190422.045933~2274 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=93612175dfa6b814e1e422d6e2832ebadef91ef7;p=platform%2Fupstream%2Fcoreclr.git Rollback https://github.com/dotnet/coreclr/pull/17639 (#17671) --- diff --git a/src/dlls/mscorrc/mscorrc.rc b/src/dlls/mscorrc/mscorrc.rc index 42c0be4..61f5c9a 100644 --- a/src/dlls/mscorrc/mscorrc.rc +++ b/src/dlls/mscorrc/mscorrc.rc @@ -1538,7 +1538,6 @@ BEGIN IDS_EE_TORNSTATE "Unexpected change made to file '%1'." - IDS_INVOKE_NULLREF_RETURNED "The target method returned a null reference." END // These strings are generated from within the EE for streams diff --git a/src/dlls/mscorrc/resource.h b/src/dlls/mscorrc/resource.h index 49f1d0e..b8e1b2b 100644 --- a/src/dlls/mscorrc/resource.h +++ b/src/dlls/mscorrc/resource.h @@ -898,5 +898,3 @@ #define IDS_EE_NDIRECT_LOADLIB_MAC 0x263f #define IDS_EE_NDIRECT_GETPROCADDRESS_UNIX 0x2640 #define IDS_EE_ERROR_COM 0x2641 - -#define IDS_INVOKE_NULLREF_RETURNED 0x2642 diff --git a/src/mscorlib/Resources/Strings.resx b/src/mscorlib/Resources/Strings.resx index 29ebb33..8ec81b9 100644 --- a/src/mscorlib/Resources/Strings.resx +++ b/src/mscorlib/Resources/Strings.resx @@ -2938,8 +2938,8 @@ Cannot create arrays of ByRef-like values. - - ByRef to ByRefLike return values not supported in reflection invocation. + + ByRef return value not supported in reflection invocation. Vararg calling convention not supported. diff --git a/src/mscorlib/src/System/Reflection/RuntimeMethodInfo.cs b/src/mscorlib/src/System/Reflection/RuntimeMethodInfo.cs index 692bfa3..1c23f16 100644 --- a/src/mscorlib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/mscorlib/src/System/Reflection/RuntimeMethodInfo.cs @@ -41,7 +41,7 @@ namespace System.Reflection // // first take care of all the NO_INVOKE cases. if (ContainsGenericParameters || - (ReturnType.IsByRef && ReturnType.GetElementType().IsByRefLike) || + ReturnType.IsByRef || (declaringType != null && declaringType.ContainsGenericParameters) || ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)) { @@ -444,10 +444,10 @@ namespace System.Reflection { throw new MemberAccessException(); } - // ByRef to ByRefLike returns are not allowed in reflection - else if (ReturnType.IsByRef && ReturnType.GetElementType().IsByRefLike) + // ByRef return are not allowed in reflection + else if (ReturnType.IsByRef) { - throw new NotSupportedException(SR.NotSupported_ByRefToByRefLikeReturn); + throw new NotSupportedException(SR.NotSupported_ByRefReturn); } throw new TargetException(); diff --git a/src/vm/invokeutil.cpp b/src/vm/invokeutil.cpp index 3672cc2..170b0da 100644 --- a/src/vm/invokeutil.cpp +++ b/src/vm/invokeutil.cpp @@ -649,14 +649,9 @@ void InvokeUtil::ValidField(TypeHandle th, OBJECTREF* value) COMPlusThrow(kArgumentException,W("Arg_ObjObj")); } -// -// CreateObjectAfterInvoke -// This routine will create the specified object from the value returned by the Invoke target. -// -// This does not handle the ELEMENT_TYPE_VALUETYPE case. The caller must preallocate the box object and -// copy the value type into it afterward. -// -OBJECTREF InvokeUtil::CreateObjectAfterInvoke(TypeHandle th, void * pValue) { +// InternalCreateObject +// This routine will create the specified object from the value +OBJECTREF InvokeUtil::CreateObject(TypeHandle th, void * pValue) { CONTRACTL { THROWS; GC_TRIGGERS; @@ -671,9 +666,6 @@ OBJECTREF InvokeUtil::CreateObjectAfterInvoke(TypeHandle th, void * pValue) { MethodTable *pMT = NULL; OBJECTREF obj = NULL; - // WARNING: pValue can be an inner reference into a managed object and it is not protected from GC. You must do nothing that - // triggers a GC until the all the data it points to has been captured in a GC-protected location. - // Handle the non-table types switch (type) { case ELEMENT_TYPE_VOID: @@ -690,8 +682,12 @@ OBJECTREF InvokeUtil::CreateObjectAfterInvoke(TypeHandle th, void * pValue) { goto PrimitiveType; case ELEMENT_TYPE_VALUETYPE: - _ASSERTE(!"You cannot use this function for arbitrary value types. You must preallocate a box object and copy the value in yourself."); + { + _ASSERTE(!th.IsTypeDesc()); + pMT = th.AsMethodTable(); + obj = pMT->Box(pValue); break; + } case ELEMENT_TYPE_CLASS: // Class case ELEMENT_TYPE_SZARRAY: // Single Dim, Zero @@ -722,17 +718,14 @@ OBJECTREF InvokeUtil::CreateObjectAfterInvoke(TypeHandle th, void * pValue) { { // Don't use MethodTable::Box here for perf reasons PREFIX_ASSUME(pMT != NULL); - DWORD size = pMT->GetNumInstanceFieldBytes(); - - UINT64 capturedValue; - memcpyNoGCRefs(&capturedValue, pValue, size); // Must capture the primitive value before we allocate the boxed object which can trigger a GC. - - INDEBUG(pValue = (LPVOID)0xcccccccc); // We're about to allocate a GC object - can no longer trust pValue obj = AllocateObject(pMT); - memcpyNoGCRefs(obj->UnBox(), &capturedValue, size); + DWORD size = pMT->GetNumInstanceFieldBytes(); + memcpyNoGCRefs(obj->UnBox(), pValue, size); } break; + case ELEMENT_TYPE_BYREF: + COMPlusThrow(kNotSupportedException, W("NotSupported_ByRefReturn")); case ELEMENT_TYPE_END: default: _ASSERTE(!"Unknown Type"); diff --git a/src/vm/invokeutil.h b/src/vm/invokeutil.h index 79ded1d..80db622 100644 --- a/src/vm/invokeutil.h +++ b/src/vm/invokeutil.h @@ -105,7 +105,7 @@ public: // Given a type, this routine will convert an return value representing that // type into an ObjectReference. If the type is a primitive, the // value is wrapped in one of the Value classes. - static OBJECTREF CreateObjectAfterInvoke(TypeHandle th, void * pValue); + static OBJECTREF CreateObject(TypeHandle th, void * pValue); // This is a special purpose Exception creation function. It // creates the TargetInvocationExeption placing the passed diff --git a/src/vm/reflectioninvocation.cpp b/src/vm/reflectioninvocation.cpp index 2cc86e5..d4f5a99 100644 --- a/src/vm/reflectioninvocation.cpp +++ b/src/vm/reflectioninvocation.cpp @@ -1092,28 +1092,12 @@ FCIMPL5(Object*, RuntimeMethodHandle::InvokeMethod, // if we have the magic Value Class return, we need to allocate that class // and place a pointer to it on the stack. - BOOL hasRefReturnAndNeedsBoxing = FALSE; // Indicates that the method has a BYREF return type and the target type needs to be copied into a preallocated boxed object. - TypeHandle retTH = gc.pSig->GetReturnTypeHandle(); - TypeHandle refReturnTargetTH; // Valid only if retType == ELEMENT_TYPE_BYREF. Caches the TypeHandle of the byref target. BOOL fHasRetBuffArg = argit.HasRetBuffArg(); CorElementType retType = retTH.GetInternalCorElementType(); if (retType == ELEMENT_TYPE_VALUETYPE || fHasRetBuffArg) { gc.retVal = retTH.GetMethodTable()->Allocate(); } - else if (retType == ELEMENT_TYPE_BYREF) - { - refReturnTargetTH = retTH.AsTypeDesc()->GetTypeParam(); - CorElementType refReturnTargetType = refReturnTargetTH.GetInternalCorElementType(); - - // If the target of the byref is a general valuetype (i.e. not one of the primitives), we need to preallocate a boxed object - // to hold the managed return value. - if (refReturnTargetType == ELEMENT_TYPE_VALUETYPE) - { - hasRefReturnAndNeedsBoxing = TRUE; - gc.retVal = refReturnTargetTH.GetMethodTable()->Allocate(); - } - } // Copy "this" pointer if (!pMeth->IsStatic()) { @@ -1339,23 +1323,13 @@ FCIMPL5(Object*, RuntimeMethodHandle::InvokeMethod, gc.retVal = Nullable::NormalizeBox(gc.retVal); } else - if (retType == ELEMENT_TYPE_VALUETYPE || hasRefReturnAndNeedsBoxing) + if (retType == ELEMENT_TYPE_VALUETYPE) { _ASSERTE(gc.retVal != NULL); - if (hasRefReturnAndNeedsBoxing) - { - // Method has BYREF return and the target type is one that needs boxing. We need to copy into the boxed object we have allocated for this purpose. - LPVOID pReturnedReference = *(LPVOID*)&callDescrData.returnValue; - if (pReturnedReference == NULL) - { - COMPlusThrow(kNullReferenceException, IDS_INVOKE_NULLREF_RETURNED); - } - CopyValueClass(gc.retVal->GetData(), pReturnedReference, gc.retVal->GetMethodTable(), gc.retVal->GetAppDomain()); - } // if the structure is returned by value, then we need to copy in the boxed object // we have allocated for this purpose. - else if (!fHasRetBuffArg) + if (!fHasRetBuffArg) { CopyValueClass(gc.retVal->GetData(), &callDescrData.returnValue, gc.retVal->GetMethodTable(), gc.retVal->GetAppDomain()); } @@ -1370,20 +1344,9 @@ FCIMPL5(Object*, RuntimeMethodHandle::InvokeMethod, // If the return type is a Nullable box it into the correct form gc.retVal = Nullable::NormalizeBox(gc.retVal); } - else if (retType == ELEMENT_TYPE_BYREF) - { - // WARNING: pReturnedReference is an unprotected inner reference so we must not trigger a GC until the referenced value has been safely captured. - LPVOID pReturnedReference = *(LPVOID*)&callDescrData.returnValue; - if (pReturnedReference == NULL) - { - COMPlusThrow(kNullReferenceException, IDS_INVOKE_NULLREF_RETURNED); - } - - gc.retVal = InvokeUtil::CreateObjectAfterInvoke(refReturnTargetTH, pReturnedReference); - } else { - gc.retVal = InvokeUtil::CreateObjectAfterInvoke(retTH, &callDescrData.returnValue); + gc.retVal = InvokeUtil::CreateObject(retTH, &callDescrData.returnValue); } while (byRefToNullables != NULL) {