diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 2fb4c3e7ffa6bb..c12d6c854ac0c0 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -223,6 +223,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.CoreCLR.cs similarity index 81% rename from src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.CoreCLR.cs index 42f3b023a4803c..357e3575812e5c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.CoreCLR.cs @@ -12,39 +12,24 @@ public static partial class JavaMarshal { public static unsafe void Initialize(delegate* unmanaged markCrossReferences) { -#if NATIVEAOT - throw new NotImplementedException(); -#elif FEATURE_JAVAMARSHAL ArgumentNullException.ThrowIfNull(markCrossReferences); if (!InitializeInternal((IntPtr)markCrossReferences)) { throw new InvalidOperationException(SR.InvalidOperation_ReinitializeJavaMarshal); } -#else - throw new PlatformNotSupportedException(); -#endif } public static unsafe GCHandle CreateReferenceTrackingHandle(object obj, void* context) { -#if NATIVEAOT - throw new NotImplementedException(); -#elif FEATURE_JAVAMARSHAL ArgumentNullException.ThrowIfNull(obj); IntPtr handle = CreateReferenceTrackingHandleInternal(ObjectHandleOnStack.Create(ref obj), context); return GCHandle.FromIntPtr(handle); -#else - throw new PlatformNotSupportedException(); -#endif } public static unsafe void* GetContext(GCHandle obj) { -#if NATIVEAOT - throw new NotImplementedException(); -#elif FEATURE_JAVAMARSHAL IntPtr handle = GCHandle.ToIntPtr(obj); if (handle == IntPtr.Zero || !GetContextInternal(handle, out void* context)) @@ -53,18 +38,12 @@ public static unsafe GCHandle CreateReferenceTrackingHandle(object obj, void* co } return context; -#else - throw new PlatformNotSupportedException(); -#endif } public static unsafe void FinishCrossReferenceProcessing( MarkCrossReferencesArgs* crossReferences, ReadOnlySpan unreachableObjectHandles) { -#if NATIVEAOT - throw new NotImplementedException(); -#elif FEATURE_JAVAMARSHAL fixed (GCHandle* pHandles = unreachableObjectHandles) { FinishCrossReferenceProcessing( @@ -72,12 +51,8 @@ public static unsafe void FinishCrossReferenceProcessing( (nuint)unreachableObjectHandles.Length, pHandles); } -#else - throw new PlatformNotSupportedException(); -#endif } -#if FEATURE_JAVAMARSHAL && !NATIVEAOT [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "JavaMarshal_Initialize")] [return: MarshalAs(UnmanagedType.Bool)] private static partial bool InitializeInternal(IntPtr callback); @@ -92,6 +67,5 @@ public static unsafe void FinishCrossReferenceProcessing( [SuppressGCTransition] [return: MarshalAs(UnmanagedType.Bool)] private static unsafe partial bool GetContextInternal(IntPtr handle, out void* context); -#endif } } diff --git a/src/coreclr/nativeaot/CMakeLists.txt b/src/coreclr/nativeaot/CMakeLists.txt index e1c43480500970..3aaa04c774c20f 100644 --- a/src/coreclr/nativeaot/CMakeLists.txt +++ b/src/coreclr/nativeaot/CMakeLists.txt @@ -30,7 +30,14 @@ endif (CLR_CMAKE_HOST_UNIX) if(CLR_CMAKE_TARGET_ANDROID) add_definitions(-DFEATURE_EMULATED_TLS) + set(FEATURE_JAVAMARSHAL 1) endif() +if(NOT DEFINED FEATURE_JAVAMARSHAL) + set(FEATURE_JAVAMARSHAL $,1,0>) +endif() + +add_compile_definitions($<${FEATURE_JAVAMARSHAL}:FEATURE_JAVAMARSHAL>) + add_subdirectory(Bootstrap) add_subdirectory(Runtime) diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt index c6a19f9b9bf023..61ed486a7989c8 100644 --- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt @@ -20,6 +20,7 @@ set(COMMON_RUNTIME_SOURCES gcenv.ee.cpp GcStressControl.cpp HandleTableHelpers.cpp + interoplibinterface_java.cpp MathHelpers.cpp MiscHelpers.cpp TypeManager.cpp @@ -38,6 +39,7 @@ set(COMMON_RUNTIME_SOURCES yieldprocessornormalized.cpp ${GC_DIR}/gceventstatus.cpp + ${GC_DIR}/gcbridge.cpp ${GC_DIR}/gcload.cpp ${GC_DIR}/gcconfig.cpp ${GC_DIR}/gchandletable.cpp diff --git a/src/coreclr/nativeaot/Runtime/HandleTableHelpers.cpp b/src/coreclr/nativeaot/Runtime/HandleTableHelpers.cpp index 91750c078e4539..7cf154d29c0cb3 100644 --- a/src/coreclr/nativeaot/Runtime/HandleTableHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/HandleTableHelpers.cpp @@ -6,6 +6,7 @@ #include "objecthandle.h" #include "RestrictedCallouts.h" #include "gchandleutilities.h" +#include "interoplibinterface.h" FCIMPL2(OBJECTHANDLE, RhpHandleAlloc, Object *pObject, int type) @@ -64,6 +65,27 @@ FCIMPL2(void, RhUnregisterRefCountedHandleCallback, void * pCallout, MethodTable } FCIMPLEND +FCIMPL2(OBJECTHANDLE, RhpHandleAllocCrossReference, Object *pPrimary, void *pContext) +{ + return GCHandleUtilities::GetGCHandleManager()->GetGlobalHandleStore()->CreateHandleWithExtraInfo(pPrimary, HNDTYPE_CROSSREFERENCE, pContext); +} +FCIMPLEND + +FCIMPL2(FC_BOOL_RET, RhHandleTryGetCrossReferenceContext, OBJECTHANDLE handle, void **pContext) +{ + *pContext = nullptr; + + IGCHandleManager* gcHandleManager = GCHandleUtilities::GetGCHandleManager(); + if (gcHandleManager->HandleFetchType(handle) != HNDTYPE_CROSSREFERENCE) + { + FC_RETURN_BOOL(false); + } + + *pContext = gcHandleManager->GetExtraInfoFromHandle(handle); + FC_RETURN_BOOL(true); +} +FCIMPLEND + // This structure mirrors the managed type System.Runtime.InteropServices.ComWrappers.ManagedObjectWrapper. struct ManagedObjectWrapper { diff --git a/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp b/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp index 9285e676354434..e2c31db91e328b 100644 --- a/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp +++ b/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp @@ -809,4 +809,11 @@ void GCToEEInterface::FreeStringConfigValue(const char* value) delete[] value; } +void GCToEEInterface::TriggerClientBridgeProcessing(MarkCrossReferencesArgs* args) +{ +#ifdef FEATURE_JAVAMARSHAL + JavaMarshalNative::TriggerClientBridgeProcessing(args); +#endif +} + #endif // !DACCESS_COMPILE diff --git a/src/coreclr/nativeaot/Runtime/interoplibinterface.h b/src/coreclr/nativeaot/Runtime/interoplibinterface.h index fce04b81f90249..c89281d152d8cc 100644 --- a/src/coreclr/nativeaot/Runtime/interoplibinterface.h +++ b/src/coreclr/nativeaot/Runtime/interoplibinterface.h @@ -22,3 +22,15 @@ class ObjCMarshalNative }; #endif // FEATURE_OBJCMARSHAL + +#ifdef FEATURE_JAVAMARSHAL + +struct MarkCrossReferencesArgs; + +class JavaMarshalNative +{ +public: + static void TriggerClientBridgeProcessing( + MarkCrossReferencesArgs* args); +}; +#endif // FEATURE_JAVAMARSHAL diff --git a/src/coreclr/nativeaot/Runtime/interoplibinterface_java.cpp b/src/coreclr/nativeaot/Runtime/interoplibinterface_java.cpp new file mode 100644 index 00000000000000..78a65ca93ecd6a --- /dev/null +++ b/src/coreclr/nativeaot/Runtime/interoplibinterface_java.cpp @@ -0,0 +1,173 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifdef FEATURE_JAVAMARSHAL + +// Runtime headers +#include "common.h" +#include "gcenv.h" +#include "gcenv.ee.h" +#include "gcheaputilities.h" +#include "gchandleutilities.h" +#include "thread.h" +#include "threadstore.h" +#include "threadstore.inl" +#include "event.h" + +#include "interoplibinterface.h" + +using CrossreferenceHandleCallback = void(__stdcall *)(MarkCrossReferencesArgs*); + +namespace +{ + volatile CrossreferenceHandleCallback g_MarkCrossReferences = NULL; + + Volatile g_GCBridgeActive = false; + CLREventStatic g_bridgeFinished; + + void ReleaseGCBridgeArgumentsWorker( + MarkCrossReferencesArgs* args) + { + _ASSERTE(args != NULL); + + // Memory was allocated for the collections by the GC. + // See callers of GCToEEInterface::TriggerGCBridge(). + + // Free memory in each of the SCCs + for (size_t i = 0; i < args->ComponentCount; i++) + { + delete[] args->Components[i].Contexts; + } + delete[] args->Components; + delete[] args->CrossReferences; + delete args; + } +} + +void JavaMarshalNative::TriggerClientBridgeProcessing( + _In_ MarkCrossReferencesArgs* args) +{ + _ASSERTE(GCHeapUtilities::IsGCInProgress()); + + if (g_GCBridgeActive) + { + // Release the memory allocated since the GCBridge + // is already running and we're not passing them to it. + ReleaseGCBridgeArgumentsWorker(args); + return; + } + + // Not initialized + if (g_MarkCrossReferences == NULL) + { + // Release the memory allocated since we + // don't have a GC bridge callback. + ReleaseGCBridgeArgumentsWorker(args); + return; + } + + g_MarkCrossReferences(args); + + // This runs during GC while the world is stopped, no synchronisation required + g_bridgeFinished.Reset(); + + // Mark the GCBridge as active. + g_GCBridgeActive = true; +} + +extern "C" BOOL QCALLTYPE JavaMarshal_Initialize( + void* markCrossReferences) +{ + _ASSERTE(markCrossReferences != NULL); + + BOOL success = FALSE; + + // Switch to Cooperative mode since we are setting callbacks that + // will be used during a GC and we want to ensure a GC isn't occurring + // while they are being set. + Thread* pThisThread = ThreadStore::GetCurrentThreadIfAvailable(); + pThisThread->DeferTransitionFrame(); + pThisThread->DisablePreemptiveMode(); + + if (PalInterlockedCompareExchangePointer((void* volatile*)&g_MarkCrossReferences, (void*)markCrossReferences, NULL) == NULL) + { + success = g_bridgeFinished.CreateManualEventNoThrow(false); + } + + pThisThread->EnablePreemptiveMode(); + + return success; +} + +extern "C" void QCALLTYPE JavaMarshal_FinishCrossReferenceProcessing( + MarkCrossReferencesArgs *crossReferences, + size_t length, + void* unreachableObjectHandles) +{ + _ASSERTE(crossReferences->ComponentCount >= 0); + + _ASSERTE(g_GCBridgeActive); + + // Mark the GCBridge as inactive. + // This must be synchronized with the GC so switch to cooperative mode. + { + Thread* pThisThread = ThreadStore::GetCurrentThreadIfAvailable(); + pThisThread->DeferTransitionFrame(); + pThisThread->DisablePreemptiveMode(); + + GCHeapUtilities::GetGCHeap()->NullBridgeObjectsWeakRefs(length, unreachableObjectHandles); + + IGCHandleManager* pHandleManager = GCHandleUtilities::GetGCHandleManager(); + OBJECTHANDLE* handles = (OBJECTHANDLE*)unreachableObjectHandles; + for (size_t i = 0; i < length; i++) + pHandleManager->DestroyHandleOfUnknownType(handles[i]); + + g_GCBridgeActive = false; + g_bridgeFinished.Set(); + + pThisThread->EnablePreemptiveMode(); + } + + ReleaseGCBridgeArgumentsWorker(crossReferences); +} + +FCIMPL2(FC_BOOL_RET, GCHandle_InternalTryGetBridgeWait, OBJECTHANDLE handle, OBJECTREF* pObjResult) +{ + if (g_GCBridgeActive) + { + FC_RETURN_BOOL(false); + } + + *pObjResult = ObjectFromHandle(handle); + FC_RETURN_BOOL(true); +} +FCIMPLEND + +extern "C" void QCALLTYPE GCHandle_InternalGetBridgeWait(OBJECTHANDLE handle, OBJECTREF* pObj) +{ + _ASSERTE(pObj != NULL); + + // Transition to cooperative mode to ensure that the GC is not in progress + Thread* pThisThread = ThreadStore::GetCurrentThreadIfAvailable(); + pThisThread->DeferTransitionFrame(); + pThisThread->DisablePreemptiveMode(); + + while (g_GCBridgeActive) + { + // This wait will transition to pre-emptive mode to wait for the bridge to finish. + g_bridgeFinished.Wait(INFINITE, false, false); + } + + // If we reach here, then the bridge has finished processing and we can be sure that + // it isn't currently active. + + // No GC can happen between the wait and obtaining of the reference, so the + // bridge processing status can't change, guaranteeing the nulling of weak refs + // took place in the bridge processing finish stage. + *pObj = ObjectFromHandle(handle); + + // Re-enable preemptive mode before we exit the QCall to ensure we're in the right GC state. + pThisThread->EnablePreemptiveMode(); +} + +#endif // FEATURE_JAVAMARSHAL diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index f8f6e6374592c0..2c96332adf7d00 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -159,6 +159,7 @@ + diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.NativeAot.cs index 7b66abd31635f0..551d50a98b2bbe 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.NativeAot.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.CompilerServices; + namespace System.Runtime.InteropServices { public partial struct GCHandle @@ -14,11 +16,24 @@ public partial struct GCHandle internal static void InternalSet(IntPtr handle, object? value) => RuntimeImports.RhHandleSet(handle, value); #if FEATURE_JAVAMARSHAL - // FIXME implement waiting for bridge processing - internal static object? InternalGetBridgeWait(IntPtr handle) + internal static unsafe object? InternalGetBridgeWait(IntPtr handle) { - return InternalGet(handle); + object? target = null; + + if (InternalTryGetBridgeWait(handle, ref target)) + return target; + + InternalGetBridgeWait(handle, &target); + + return target; } + + [MethodImpl(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeImports.RuntimeLibrary, "GCHandle_InternalTryGetBridgeWait")] + private static extern bool InternalTryGetBridgeWait(IntPtr handle, ref object? result); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "GCHandle_InternalGetBridgeWait")] + private static unsafe partial void InternalGetBridgeWait(IntPtr handle, object?* result); #endif } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.NativeAot.cs new file mode 100644 index 00000000000000..c253114be4602d --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.NativeAot.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System.Runtime.Versioning; + +namespace System.Runtime.InteropServices.Java +{ + [CLSCompliant(false)] + [SupportedOSPlatform("android")] + public static partial class JavaMarshal + { + public static unsafe void Initialize(delegate* unmanaged markCrossReferences) + { + ArgumentNullException.ThrowIfNull(markCrossReferences); + + if (!InitializeInternal((IntPtr)markCrossReferences)) + { + throw new InvalidOperationException(SR.InvalidOperation_ReinitializeJavaMarshal); + } + } + + public static unsafe GCHandle CreateReferenceTrackingHandle(object obj, void* context) + { + ArgumentNullException.ThrowIfNull(obj); + return GCHandle.FromIntPtr(RuntimeImports.RhHandleAllocCrossReference(obj, (IntPtr)context)); + } + + public static unsafe void* GetContext(GCHandle obj) + { + IntPtr handle = GCHandle.ToIntPtr(obj); + if (handle == IntPtr.Zero + || !RuntimeImports.RhHandleTryGetCrossReferenceContext(handle, out nint context)) + { + throw new InvalidOperationException(SR.InvalidOperation_IncorrectGCHandleType); + } + return (void*)context; + } + + public static unsafe void FinishCrossReferenceProcessing( + MarkCrossReferencesArgs* crossReferences, + ReadOnlySpan unreachableObjectHandles) + { + fixed (GCHandle* handlesPtr = unreachableObjectHandles) + { + FinishCrossReferenceProcessingBridge( + crossReferences, + (nuint)unreachableObjectHandles.Length, + handlesPtr); + } + } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "JavaMarshal_Initialize")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static unsafe partial bool InitializeInternal(IntPtr markCrossReferences); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "JavaMarshal_FinishCrossReferenceProcessing")] + internal static unsafe partial void FinishCrossReferenceProcessingBridge( + MarkCrossReferencesArgs* crossReferences, + nuint numHandles, + GCHandle* unreachableObjectHandles); + } +} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index e1886df7006f31..298dc148009042 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -294,6 +294,26 @@ internal static IntPtr RhHandleAllocDependent(object primary, object secondary) return h; } + [MethodImpl(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhpHandleAllocCrossReference")] + private static extern IntPtr RhpHandleAllocCrossReference(object value, IntPtr context); + + internal static IntPtr RhHandleAllocCrossReference(object value, IntPtr context) + { + IntPtr h = RhpHandleAllocCrossReference(value, context); + if (h == IntPtr.Zero) + throw new OutOfMemoryException(); + return h; + } + + [MethodImpl(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhHandleTryGetCrossReferenceContext")] + internal static extern bool RhHandleTryGetCrossReferenceContext(IntPtr handle, out IntPtr context); + + [MethodImpl(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhIsGCBridgeActive")] + internal static extern bool RhIsGCBridgeActive(); + // Free handle. [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhHandleFree")] diff --git a/src/coreclr/vm/interoplibinterface_java.cpp b/src/coreclr/vm/interoplibinterface_java.cpp index 0a30dce519f471..e4f1f07f11997b 100644 --- a/src/coreclr/vm/interoplibinterface_java.cpp +++ b/src/coreclr/vm/interoplibinterface_java.cpp @@ -36,11 +36,11 @@ namespace // Free memory in each of the SCCs for (size_t i = 0; i < args->ComponentCount; i++) { - free(args->Components[i].Contexts); + delete[] args->Components[i].Contexts; } - free(args->Components); - free(args->CrossReferences); - free(args); + delete[] args->Components; + delete[] args->CrossReferences; + delete args; } } diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index fa5371c97cad5b..1c2303c097a6aa 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -997,7 +997,7 @@ - + diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.Unsupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.Unsupported.cs new file mode 100644 index 00000000000000..3914d81c2e6ab7 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.Unsupported.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System.Runtime.Versioning; + +namespace System.Runtime.InteropServices.Java +{ + [CLSCompliant(false)] + [SupportedOSPlatform("android")] + public static partial class JavaMarshal + { + public static unsafe void Initialize(delegate* unmanaged markCrossReferences) + { + throw new PlatformNotSupportedException(); + } + + public static unsafe GCHandle CreateReferenceTrackingHandle(object obj, void* context) + { + throw new PlatformNotSupportedException(); + } + + public static unsafe void* GetContext(GCHandle obj) + { + throw new PlatformNotSupportedException(); + } + + public static unsafe void FinishCrossReferenceProcessing( + MarkCrossReferencesArgs* crossReferences, + ReadOnlySpan unreachableObjectHandles) + { + throw new PlatformNotSupportedException(); + } + } +} diff --git a/src/tests/Interop/GCBridge/BridgeTest.csproj b/src/tests/Interop/GCBridge/BridgeTest.csproj index 1425b1f51b2c64..965f8371061bb7 100644 --- a/src/tests/Interop/GCBridge/BridgeTest.csproj +++ b/src/tests/Interop/GCBridge/BridgeTest.csproj @@ -4,8 +4,6 @@ true true true - - true true diff --git a/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index a4c77237e317fc..244de7b0a0c9a1 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -218,6 +218,12 @@ static bool IsComInterop(IMarshalInfoProvider marshalInfoProvider, TypeReference if (nativeType == NativeType.None) { + if (parameterType.IsPointer) + { + // Pointer types are passed without marshalling + return false; + } + // Resolve will look at the element type var parameterTypeDef = context.TryResolve(parameterType);