From fc0b204cf83ce1596c78fd66b8c0047eb2719c90 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 16 May 2022 07:40:22 -0700 Subject: [PATCH] Add `IntPtr` conversion APIs for some runtime handles (#69363) * Add conversion APIs for runtime handles --- .../src/System/RuntimeHandles.cs | 64 ++++++++++++++++++- .../src/System/RuntimeFieldHandle.cs | 9 +++ .../src/System/RuntimeMethodHandle.cs | 11 +++- .../src/System/RuntimeTypeHandle.cs | 11 +++- src/coreclr/vm/ecalllist.h | 1 + src/coreclr/vm/runtimehandles.cpp | 25 +++++++- src/coreclr/vm/runtimehandles.h | 1 + .../System.Runtime/ref/System.Runtime.cs | 6 ++ .../tests/System/HandleTests.cs | 18 ++++++ .../src/System/RuntimeFieldHandle.cs | 4 ++ .../src/System/RuntimeMethodHandle.cs | 4 ++ .../src/System/RuntimeTypeHandle.cs | 4 ++ 12 files changed, 154 insertions(+), 4 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 166ecd396186f..504b6243381ef 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -68,6 +68,20 @@ internal static Type GetTypeHelper(Type typeStart, Type[]? genericArgs, IntPtr p return type; } + /// + /// Returns a new object created from a handle to a RuntimeType. + /// + /// An IntPtr handle to a RuntimeType to create a object from. + /// A new object that corresponds to the value parameter. + public static RuntimeTypeHandle FromIntPtr(IntPtr value) => new RuntimeTypeHandle(Type.GetTypeFromHandleUnsafe(value)); + + /// + /// Returns the internal pointer representation of a object. + /// + /// A object to retrieve an internal pointer representation from. + /// An object that represents a object. + public static IntPtr ToIntPtr(RuntimeTypeHandle value) => value.Value; + public static bool operator ==(RuntimeTypeHandle left, object? right) => left.Equals(right); public static bool operator ==(object? left, RuntimeTypeHandle right) => right.Equals(left); @@ -864,6 +878,25 @@ public override bool Equals(object? obj) return handle.Value == Value; } + /// + /// Returns a new object created from a handle to a RuntimeMethodInfo. + /// + /// An IntPtr handle to a RuntimeMethodInfo to create a object from. + /// A new object that corresponds to the value parameter. + public static RuntimeMethodHandle FromIntPtr(IntPtr value) + { + var handle = new RuntimeMethodHandleInternal(value); + var methodInfo = new RuntimeMethodInfoStub(handle, RuntimeMethodHandle.GetLoaderAllocator(handle)); + return new RuntimeMethodHandle(methodInfo); + } + + /// + /// Returns the internal pointer representation of a object. + /// + /// A object to retrieve an internal pointer representation from. + /// An object that represents a object. + public static IntPtr ToIntPtr(RuntimeMethodHandle value) => value.Value; + public static bool operator ==(RuntimeMethodHandle left, RuntimeMethodHandle right) => left.Equals(right); public static bool operator !=(RuntimeMethodHandle left, RuntimeMethodHandle right) => !left.Equals(right); @@ -1124,9 +1157,16 @@ RuntimeFieldHandleInternal Value [StructLayout(LayoutKind.Sequential)] internal sealed class RuntimeFieldInfoStub : IRuntimeFieldInfo { + public RuntimeFieldInfoStub(RuntimeFieldHandleInternal fieldHandle, object keepalive) + { + m_keepalive = keepalive; + m_fieldHandle = fieldHandle; + } + + private readonly object m_keepalive; + // These unused variables are used to ensure that this class has the same layout as RuntimeFieldInfo #pragma warning disable 414, 169 - private object? m_keepalive; private object? m_c; private object? m_d; private int m_b; @@ -1190,6 +1230,25 @@ public bool Equals(RuntimeFieldHandle handle) return handle.Value == Value; } + /// + /// Returns a new object created from a handle to a RuntimeFieldInfo. + /// + /// An IntPtr handle to a RuntimeFieldInfo to create a object from. + /// A new object that corresponds to the value parameter. + public static RuntimeFieldHandle FromIntPtr(IntPtr value) + { + var handle = new RuntimeFieldHandleInternal(value); + var fieldInfo = new RuntimeFieldInfoStub(handle, RuntimeFieldHandle.GetLoaderAllocator(handle)); + return new RuntimeFieldHandle(fieldInfo); + } + + /// + /// Returns the internal pointer representation of a object. + /// + /// A object to retrieve an internal pointer representation from. + /// An object that represents a object. + public static IntPtr ToIntPtr(RuntimeFieldHandle value) => value.Value; + public static bool operator ==(RuntimeFieldHandle left, RuntimeFieldHandle right) => left.Equals(right); public static bool operator !=(RuntimeFieldHandle left, RuntimeFieldHandle right) => !left.Equals(right); @@ -1239,6 +1298,9 @@ internal static RuntimeType GetApproxDeclaringType(IRuntimeFieldInfo field) [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool AcquiresContextFromThis(RuntimeFieldHandleInternal field); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern LoaderAllocator GetLoaderAllocator(RuntimeFieldHandleInternal method); + // ISerializable interface public void GetObjectData(SerializationInfo info, StreamingContext context) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs index 4922be6e4fd50..527f040f10d36 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs @@ -15,6 +15,11 @@ public struct RuntimeFieldHandle : IEquatable, ISerializable { private IntPtr _value; + private RuntimeFieldHandle(IntPtr value) + { + _value = value; + } + public IntPtr Value => _value; public override bool Equals(object? obj) @@ -61,6 +66,10 @@ public override int GetHashCode() return (hashcode + _rotl(hashcode, 13)) ^ fieldName.GetHashCode(); } + public static RuntimeFieldHandle FromIntPtr(IntPtr value) => new RuntimeFieldHandle(value); + + public static IntPtr ToIntPtr(RuntimeFieldHandle value) => value.Value; + public static bool operator ==(RuntimeFieldHandle left, RuntimeFieldHandle right) { return left.Equals(right); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs index 6bb32c2db2db1..27e6c489030af 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs @@ -17,7 +17,12 @@ public struct RuntimeMethodHandle : IEquatable, ISerializab { private IntPtr _value; - public unsafe IntPtr Value => _value; + private RuntimeMethodHandle(IntPtr value) + { + _value = value; + } + + public IntPtr Value => _value; public override bool Equals(object? obj) { @@ -92,6 +97,10 @@ public override int GetHashCode() return hashcode; } + public static RuntimeMethodHandle FromIntPtr(IntPtr value) => new RuntimeMethodHandle(value); + + public static IntPtr ToIntPtr(RuntimeMethodHandle value) => value.Value; + public static bool operator ==(RuntimeMethodHandle left, RuntimeMethodHandle right) { return left.Equals(right); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs index 8097a471242a1..83fce9bcd1cc1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs @@ -21,8 +21,13 @@ public unsafe struct RuntimeTypeHandle : IEquatable, ISeriali // internal RuntimeTypeHandle(EETypePtr pEEType) + : this(pEEType.RawValue) { - _value = pEEType.RawValue; + } + + private RuntimeTypeHandle(IntPtr value) + { + _value = value; } public override bool Equals(object? obj) @@ -60,6 +65,10 @@ public bool Equals(RuntimeTypeHandle handle) } } + public static RuntimeTypeHandle FromIntPtr(IntPtr value) => new RuntimeTypeHandle(value); + + public static IntPtr ToIntPtr(RuntimeTypeHandle value) => value.Value; + public static bool operator ==(object? left, RuntimeTypeHandle right) { if (left is RuntimeTypeHandle) diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 593284165f165..a8e23ecf43072 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -251,6 +251,7 @@ FCFuncStart(gCOMFieldHandleNewFuncs) FCFuncElement("GetToken", RuntimeFieldHandle::GetToken) FCFuncElement("GetStaticFieldForGenericType", RuntimeFieldHandle::GetStaticFieldForGenericType) FCFuncElement("AcquiresContextFromThis", RuntimeFieldHandle::AcquiresContextFromThis) + FCFuncElement("GetLoaderAllocator", RuntimeFieldHandle::GetLoaderAllocator) FCFuncEnd() FCFuncStart(gCOMModuleFuncs) diff --git a/src/coreclr/vm/runtimehandles.cpp b/src/coreclr/vm/runtimehandles.cpp index 650fbf79fc2fb..400f3f2a1c61f 100644 --- a/src/coreclr/vm/runtimehandles.cpp +++ b/src/coreclr/vm/runtimehandles.cpp @@ -362,7 +362,7 @@ FCIMPL1(AssemblyBaseObject*, RuntimeTypeHandle::GetAssembly, ReflectClassBaseObj FCIMPLEND -FCIMPL1(FC_BOOL_RET, RuntimeFieldHandle::AcquiresContextFromThis, FieldDesc *pField) +FCIMPL1(FC_BOOL_RET, RuntimeFieldHandle::AcquiresContextFromThis, FieldDesc* pField) { CONTRACTL { FCALL_CHECK; @@ -375,6 +375,29 @@ FCIMPL1(FC_BOOL_RET, RuntimeFieldHandle::AcquiresContextFromThis, FieldDesc *pFi } FCIMPLEND +FCIMPL1(Object*, RuntimeFieldHandle::GetLoaderAllocator, FieldDesc* pField) +{ + CONTRACTL { + FCALL_CHECK; + } + CONTRACTL_END; + + OBJECTREF loaderAllocator = NULL; + + if (!pField) + FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); + + HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(loaderAllocator); + + LoaderAllocator *pLoaderAllocator = pField->GetApproxEnclosingMethodTable()->GetLoaderAllocator(); + loaderAllocator = pLoaderAllocator->GetExposedObject(); + + HELPER_METHOD_FRAME_END(); + + return OBJECTREFToObject(loaderAllocator); +} +FCIMPLEND + FCIMPL1(ReflectModuleBaseObject*, RuntimeTypeHandle::GetModule, ReflectClassBaseObject *pTypeUNSAFE) { CONTRACTL { FCALL_CHECK; diff --git a/src/coreclr/vm/runtimehandles.h b/src/coreclr/vm/runtimehandles.h index 29bdfa08a846f..c16a3473bb170 100644 --- a/src/coreclr/vm/runtimehandles.h +++ b/src/coreclr/vm/runtimehandles.h @@ -322,6 +322,7 @@ class RuntimeFieldHandle { static FCDECL1(INT32, GetToken, ReflectFieldObject *pFieldUNSAFE); static FCDECL2(FieldDesc*, GetStaticFieldForGenericType, FieldDesc *pField, ReflectClassBaseObject *pDeclaringType); static FCDECL1(FC_BOOL_RET, AcquiresContextFromThis, FieldDesc *pField); + static FCDECL1(Object*, GetLoaderAllocator, FieldDesc *pField); }; class ModuleHandle { diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index e77452e0ab885..cb1861d7e74f4 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -4087,6 +4087,8 @@ public partial struct RuntimeFieldHandle : System.IEquatable new RuntimeFieldHandle(value); + + public static IntPtr ToIntPtr(RuntimeFieldHandle value) => value.Value; + public static bool operator ==(RuntimeFieldHandle left, RuntimeFieldHandle right) { return left.Equals(right); diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs index 2f0e1b726082f..791b39c408d9b 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs @@ -56,6 +56,10 @@ public override int GetHashCode() return value.GetHashCode(); } + public static RuntimeMethodHandle FromIntPtr(IntPtr value) => new RuntimeMethodHandle(value); + + public static IntPtr ToIntPtr(RuntimeMethodHandle value) => value.Value; + public static bool operator ==(RuntimeMethodHandle left, RuntimeMethodHandle right) { return left.Equals(right); diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs index d49f92a945bb9..a2b911d0125ca 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs @@ -90,6 +90,10 @@ public override int GetHashCode() return value.GetHashCode(); } + public static RuntimeTypeHandle FromIntPtr(IntPtr value) => new RuntimeTypeHandle(value); + + public static IntPtr ToIntPtr(RuntimeTypeHandle value) => value.Value; + public static bool operator ==(RuntimeTypeHandle left, object right) { return (right != null) && (right is RuntimeTypeHandle) && left.Equals((RuntimeTypeHandle)right);