Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Marshal.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\MemoryMarshal.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NativeLibrary.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Java\JavaMarshal.CoreCLR.cs" Condition="'$(FeatureJavaMarshal)' == 'true'" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\Intrinsics\X86\X86Base.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\Loader\AssemblyLoadContext.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\RuntimeArgumentHandle.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,24 @@ public static partial class JavaMarshal
{
public static unsafe void Initialize(delegate* unmanaged<MarkCrossReferencesArgs*, void> 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))
Expand All @@ -53,31 +38,21 @@ public static unsafe GCHandle CreateReferenceTrackingHandle(object obj, void* co
}

return context;
#else
throw new PlatformNotSupportedException();
#endif
}

public static unsafe void FinishCrossReferenceProcessing(
MarkCrossReferencesArgs* crossReferences,
ReadOnlySpan<GCHandle> unreachableObjectHandles)
{
#if NATIVEAOT
throw new NotImplementedException();
#elif FEATURE_JAVAMARSHAL
fixed (GCHandle* pHandles = unreachableObjectHandles)
{
FinishCrossReferenceProcessing(
crossReferences,
(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);
Expand All @@ -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
}
}
7 changes: 7 additions & 0 deletions src/coreclr/nativeaot/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 $<IF:$<CONFIG:Debug,Checked>,1,0>)
endif()

add_compile_definitions($<${FEATURE_JAVAMARSHAL}:FEATURE_JAVAMARSHAL>)

add_subdirectory(Bootstrap)
add_subdirectory(Runtime)
2 changes: 2 additions & 0 deletions src/coreclr/nativeaot/Runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ set(COMMON_RUNTIME_SOURCES
gcenv.ee.cpp
GcStressControl.cpp
HandleTableHelpers.cpp
interoplibinterface_java.cpp
MathHelpers.cpp
MiscHelpers.cpp
TypeManager.cpp
Expand All @@ -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
Expand Down
22 changes: 22 additions & 0 deletions src/coreclr/nativeaot/Runtime/HandleTableHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "objecthandle.h"
#include "RestrictedCallouts.h"
#include "gchandleutilities.h"
#include "interoplibinterface.h"


FCIMPL2(OBJECTHANDLE, RhpHandleAlloc, Object *pObject, int type)
Expand Down Expand Up @@ -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
{
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/nativeaot/Runtime/gcenv.ee.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 12 additions & 0 deletions src/coreclr/nativeaot/Runtime/interoplibinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
173 changes: 173 additions & 0 deletions src/coreclr/nativeaot/Runtime/interoplibinterface_java.cpp
Original file line number Diff line number Diff line change
@@ -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<bool> 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
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
<Compile Include="System\CrashInfo.cs" />
<Compile Include="System\Runtime\InteropServices\ComAwareWeakReference.NativeAot.cs" />
<Compile Include="System\Runtime\InteropServices\CriticalHandle.NativeAot.cs" />
<Compile Include="System\Runtime\InteropServices\Java\JavaMarshal.NativeAot.cs" Condition="'$(FeatureJavaMarshal)' == 'true'" />
<Compile Include="System\Activator.NativeAot.cs" />
<Compile Include="System\AppContext.NativeAot.cs" />
<Compile Include="System\ArgIterator.cs" />
Expand Down
Loading
Loading