Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing COM Aggregation and XAML reference tracking on .NET AOT #90283

Merged
merged 20 commits into from Aug 13, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/coreclr/nativeaot/Directory.Build.props
Expand Up @@ -56,6 +56,7 @@
</PropertyGroup>
<PropertyGroup>
<FeatureComWrappers>true</FeatureComWrappers>
<DefineConstants Condition="'$(FeatureComWrappers)' == 'true'">FEATURE_COMWRAPPERS;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<FeatureObjCMarshal>false</FeatureObjCMarshal>
Expand Down
Expand Up @@ -60,14 +60,14 @@ internal static class InternalCalls

// Force a garbage collection.
[RuntimeExport("RhCollect")]
internal static void RhCollect(int generation, InternalGCCollectionMode mode)
internal static void RhCollect(int generation, InternalGCCollectionMode mode, bool lowMemoryP = false)
{
RhpCollect(generation, mode);
RhpCollect(generation, mode, lowMemoryP);
}

[DllImport(Redhawk.BaseName)]
[UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
private static extern void RhpCollect(int generation, InternalGCCollectionMode mode);
private static extern void RhpCollect(int generation, InternalGCCollectionMode mode, bool lowMemoryP);

[RuntimeExport("RhGetGcTotalMemory")]
internal static long RhGetGcTotalMemory()
Expand Down
9 changes: 7 additions & 2 deletions src/coreclr/nativeaot/Runtime/GCHelpers.cpp
Expand Up @@ -25,7 +25,7 @@
#include "threadstore.inl"
#include "thread.inl"

EXTERN_C NATIVEAOT_API void __cdecl RhpCollect(uint32_t uGeneration, uint32_t uMode)
EXTERN_C NATIVEAOT_API void __cdecl RhpCollect(uint32_t uGeneration, uint32_t uMode, UInt32_BOOL lowMemoryP)
{
// This must be called via p/invoke rather than RuntimeImport to make the stack crawlable.

Expand All @@ -35,7 +35,7 @@ EXTERN_C NATIVEAOT_API void __cdecl RhpCollect(uint32_t uGeneration, uint32_t uM
pCurThread->DisablePreemptiveMode();

ASSERT(!pCurThread->IsDoNotTriggerGcSet());
GCHeapUtilities::GetGCHeap()->GarbageCollect(uGeneration, FALSE, uMode);
GCHeapUtilities::GetGCHeap()->GarbageCollect(uGeneration, lowMemoryP, uMode);

pCurThread->EnablePreemptiveMode();
}
Expand Down Expand Up @@ -128,6 +128,11 @@ COOP_PINVOKE_HELPER(int32_t, RhSetGcLatencyMode, (int32_t newLatencyMode))
return GCHeapUtilities::GetGCHeap()->SetGcLatencyMode(newLatencyMode);
}

COOP_PINVOKE_HELPER(FC_BOOL_RET, RhIsPromoted, (OBJECTREF obj))
{
FC_RETURN_BOOL(GCHeapUtilities::GetGCHeap()->IsPromoted(obj));
}

COOP_PINVOKE_HELPER(FC_BOOL_RET, RhIsServerGc, ())
{
FC_RETURN_BOOL(GCHeapUtilities::IsServerHeap());
Expand Down
14 changes: 9 additions & 5 deletions src/coreclr/nativeaot/Runtime/gcrhenv.cpp
Expand Up @@ -989,15 +989,19 @@ bool GCToEEInterface::EagerFinalized(Object* obj)
// Managed code should not be running.
ASSERT(GCHeapUtilities::GetGCHeap()->IsGCInProgressHelper());

// the lowermost 1 bit is reserved for storing additional info about the handle
const uintptr_t HandleTagBits = 1;
// the lowermost 2 bits are reserved for storing additional info about the handle
// we can use these bits because handle is at least 4 byte aligned
const uintptr_t HandleTagBits = 3;

WeakReference* weakRefObj = (WeakReference*)obj;
OBJECTHANDLE handle = (OBJECTHANDLE)(weakRefObj->m_taggedHandle & ~HandleTagBits);
_ASSERTE((weakRefObj->m_taggedHandle & 2) == 0);
HandleType handleType = (weakRefObj->m_taggedHandle & 1) ? HandleType::HNDTYPE_WEAK_LONG : HandleType::HNDTYPE_WEAK_SHORT;
HandleType handleType = (weakRefObj->m_taggedHandle & 2) ?
HandleType::HNDTYPE_STRONG :
(weakRefObj->m_taggedHandle & 1) ?
HandleType::HNDTYPE_WEAK_LONG :
HandleType::HNDTYPE_WEAK_SHORT;
// keep the bit that indicates whether this reference was tracking resurrection, clear the rest.
weakRefObj->m_taggedHandle &= HandleTagBits;
weakRefObj->m_taggedHandle &= (uintptr_t)1;
GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, handleType);
return true;
}
Expand Down
Expand Up @@ -210,6 +210,7 @@
<Compile Include="System\Runtime\InteropServices\Marshal.NativeAot.cs" />
<Compile Include="System\Runtime\InteropServices\Marshal.Com.cs" Condition="'$(FeatureCominterop)' == 'true'" />
<Compile Include="System\Runtime\InteropServices\MemoryMarshal.NativeAot.cs" />
<Compile Include="System\Runtime\InteropServices\TrackerObjectManager.NativeAot.cs" Condition="'$(FeatureComWrappers)' == 'true'" />
<Compile Include="System\Runtime\InteropServices\ObjectiveCMarshal.NativeAot.cs" Condition="'$(FeatureObjCMarshal)' == 'true'" />
<Compile Include="System\Runtime\InteropServices\UnsafeGCHandle.cs" />
<Compile Include="System\Runtime\Intrinsics\X86\X86Base.NativeAot.cs" Condition="'$(SupportsX86Intrinsics)' == 'true'" />
Expand Down Expand Up @@ -273,6 +274,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\Ole32\Interop.CoGetApartmentType.cs">
<Link>Interop\Windows\Ole32\Interop.CoGetApartmentType.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\Ole32\Interop.CoGetContextToken.cs">
<Link>Interop\Windows\Ole32\Interop.CoGetContextToken.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\OleAut32\Interop.VariantClear.cs">
<Link>Interop\Windows\OleAut32\Interop.VariantClear.cs</Link>
</Compile>
Expand Down
Expand Up @@ -2,32 +2,47 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;

#if FEATURE_COMINTEROP || FEATURE_COMWRAPPERS

#pragma warning disable IDE0060

namespace System
{
internal sealed partial class ComAwareWeakReference
{
internal static object? ComWeakRefToObject(IntPtr pComWeakRef, long wrapperId)
// We don't want to consult ComWrappers if no RCW objects have been created.
// In addition we don't want a direct reference to ComWrappers to allow for better
// trimming. So we instead make use of delegates that ComWrappers registers when
// it is used.
private static unsafe delegate*<IntPtr, long, object?> s_comWeakRefToObjectCallback;
private static unsafe delegate*<object, bool> s_possiblyComObjectCallback;
private static unsafe delegate*<object, out long, IntPtr> s_objectToComWeakRefCallback;

internal static unsafe void InitializeCallbacks(
delegate*<IntPtr, long, object?> comWeakRefToObject,
delegate*<object, bool> possiblyComObject,
delegate*<object, out long, IntPtr> objectToComWeakRef)
{
s_comWeakRefToObjectCallback = comWeakRefToObject;
s_objectToComWeakRefCallback = objectToComWeakRef;
s_possiblyComObjectCallback = possiblyComObject;
}

internal static unsafe object? ComWeakRefToObject(IntPtr pComWeakRef, long wrapperId)
{
// NativeAOT support for COM WeakReference is NYI
throw new NotImplementedException();
return s_comWeakRefToObjectCallback != null ? s_comWeakRefToObjectCallback(pComWeakRef, wrapperId) : null;
}

internal static bool PossiblyComObject(object target)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
manodasanW marked this conversation as resolved.
Show resolved Hide resolved
internal static unsafe bool PossiblyComObject(object target)
{
// NativeAOT support for COM WeakReference is NYI
return false;
return s_possiblyComObjectCallback != null ? s_possiblyComObjectCallback(target) : false;
}

internal static IntPtr ObjectToComWeakRef(object target, out long wrapperId)
internal static unsafe IntPtr ObjectToComWeakRef(object target, out long wrapperId)
{
// NativeAOT support for COM WeakReference is NYI
wrapperId = 0;
return 0;
return s_objectToComWeakRefCallback != null ? s_objectToComWeakRefCallback(target, out wrapperId) : IntPtr.Zero;
}
}
}
Expand Down