summaryrefslogtreecommitdiff
path: root/src/vm/invokeutil.cpp
diff options
context:
space:
mode:
authorAtsushi Kanamori <AtsushiKan@users.noreply.github.com>2018-04-23 13:42:24 -0700
committerGitHub <noreply@github.com>2018-04-23 13:42:24 -0700
commit5a42b8c7348ba7dfa0dbf423d36245570488c888 (patch)
treec35278add0c8c8ab6fd9d2063f1d37494c5feb7e /src/vm/invokeutil.cpp
parent72dd7f2146cee213babb18378130e4375442aca1 (diff)
downloadcoreclr-5a42b8c7348ba7dfa0dbf423d36245570488c888.tar.gz
coreclr-5a42b8c7348ba7dfa0dbf423d36245570488c888.tar.bz2
coreclr-5a42b8c7348ba7dfa0dbf423d36245570488c888.zip
Enable Invoke and GetValue for ref-returning members (#17732)
* Reapply https://github.com/dotnet/coreclr/pull/17639 * tryagain-wip 4/23/2018 7:27:37 AM - Fix Invoke of enum-returning methods * Assert for refbufargs implying valuetype * Catch ref to void in managed layer
Diffstat (limited to 'src/vm/invokeutil.cpp')
-rw-r--r--src/vm/invokeutil.cpp57
1 files changed, 16 insertions, 41 deletions
diff --git a/src/vm/invokeutil.cpp b/src/vm/invokeutil.cpp
index 170b0da6d6..a45e81b262 100644
--- a/src/vm/invokeutil.cpp
+++ b/src/vm/invokeutil.cpp
@@ -649,9 +649,14 @@ void InvokeUtil::ValidField(TypeHandle th, OBJECTREF* value)
COMPlusThrow(kArgumentException,W("Arg_ObjObj"));
}
-// InternalCreateObject
-// This routine will create the specified object from the value
-OBJECTREF InvokeUtil::CreateObject(TypeHandle th, void * pValue) {
+//
+// 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) {
CONTRACTL {
THROWS;
GC_TRIGGERS;
@@ -663,9 +668,11 @@ OBJECTREF InvokeUtil::CreateObject(TypeHandle th, void * pValue) {
CONTRACTL_END;
CorElementType type = th.GetSignatureCorElementType();
- 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:
@@ -677,18 +684,6 @@ OBJECTREF InvokeUtil::CreateObject(TypeHandle th, void * pValue) {
break;
}
- case ELEMENT_TYPE_FNPTR:
- pMT = MscorlibBinder::GetElementType(ELEMENT_TYPE_I);
- goto PrimitiveType;
-
- case ELEMENT_TYPE_VALUETYPE:
- {
- _ASSERTE(!th.IsTypeDesc());
- pMT = th.AsMethodTable();
- obj = pMT->Box(pValue);
- break;
- }
-
case ELEMENT_TYPE_CLASS: // Class
case ELEMENT_TYPE_SZARRAY: // Single Dim, Zero
case ELEMENT_TYPE_ARRAY: // General Array
@@ -698,35 +693,15 @@ OBJECTREF InvokeUtil::CreateObject(TypeHandle th, void * pValue) {
obj = *(OBJECTREF *)pValue;
break;
- case ELEMENT_TYPE_BOOLEAN: // boolean
- case ELEMENT_TYPE_I1: // byte
- case ELEMENT_TYPE_U1:
- case ELEMENT_TYPE_I2: // short
- case ELEMENT_TYPE_U2:
- case ELEMENT_TYPE_CHAR: // char
- case ELEMENT_TYPE_I4: // int
- case ELEMENT_TYPE_U4:
- case ELEMENT_TYPE_I8: // long
- case ELEMENT_TYPE_U8:
- case ELEMENT_TYPE_R4: // float
- case ELEMENT_TYPE_R8: // double
- case ELEMENT_TYPE_I:
- case ELEMENT_TYPE_U:
- _ASSERTE(!th.IsTypeDesc());
- pMT = th.AsMethodTable();
- PrimitiveType:
+ case ELEMENT_TYPE_FNPTR:
{
- // Don't use MethodTable::Box here for perf reasons
- PREFIX_ASSUME(pMT != NULL);
- obj = AllocateObject(pMT);
- DWORD size = pMT->GetNumInstanceFieldBytes();
- memcpyNoGCRefs(obj->UnBox(), pValue, size);
+ LPVOID capturedValue = *(LPVOID*)pValue;
+ INDEBUG(pValue = (LPVOID)0xcccccccc); // We're about to allocate a GC object - can no longer trust pValue
+ obj = AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I));
+ *(LPVOID*)(obj->UnBox()) = capturedValue;
}
break;
- case ELEMENT_TYPE_BYREF:
- COMPlusThrow(kNotSupportedException, W("NotSupported_ByRefReturn"));
- case ELEMENT_TYPE_END:
default:
_ASSERTE(!"Unknown Type");
COMPlusThrow(kNotSupportedException);