Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
57fe91c
Move DependentHandle to System.Runtime
Sergio0694 Jun 15, 2021
b1f54b5
Update DependentHandle APIs to follow review
Sergio0694 Jun 15, 2021
b331b8f
Make DependentHandle type public
Sergio0694 Jun 15, 2021
a96fa3f
Update DependentHandle on Mono runtime
Sergio0694 Jun 15, 2021
16fdf0e
Add allocation checks to DependentHandle APIs
Sergio0694 Jun 15, 2021
748d88e
Add more unit tests for new public DependentHandle APIs
Sergio0694 Jun 16, 2021
247fa5a
Add faster, unsafe internal APIs versions to DependentHandle
Sergio0694 Jun 16, 2021
66d2ac5
Naming improvements to Ephemeron type
Sergio0694 Jun 16, 2021
4067ac3
Code style tweaks, improved nullability annotations
Sergio0694 Jun 16, 2021
1670339
Remove incorrect DependentHandle comment on Mono
Sergio0694 Jun 16, 2021
96cfc91
Add default Dispose test for DependentHandle
Sergio0694 Jun 16, 2021
6a8db56
Fix race condition in DependentHandle on Mono
Sergio0694 Jun 16, 2021
1601d88
Optimize DependentHandle.nGetPrimary on CoreCLR
Sergio0694 Jun 16, 2021
359938b
Small IL codegen improvement in DependentHandle.nGetPrimary
Sergio0694 Jun 16, 2021
312851a
Simplify comments, add #ifdef for using directive
Sergio0694 Jun 16, 2021
0145a76
Minor code style tweaks
Sergio0694 Jun 16, 2021
4925877
Change nGetPrimaryAndSecondary to nGetSecondary
Sergio0694 Jun 16, 2021
1664a95
Minor code refactoring to DependentHandle on Mono
Sergio0694 Jun 16, 2021
ca515b6
Rename DependentHandle FCalls
Sergio0694 Jun 16, 2021
08df598
Remove DependentHandle.UnsafeGetTargetAndDependent
Sergio0694 Jun 16, 2021
4e2b624
Remove DependentHandle.GetTargetAndDependent
Sergio0694 Jun 16, 2021
4e03297
Fix FCall path for internal DependentHandle APIs
Sergio0694 Jun 16, 2021
25b34c2
Add more DependentHandle unit tests
Sergio0694 Jun 17, 2021
01f32a3
Reintroduce DependentHandle.GetTargetAndDependent()
Sergio0694 Jun 17, 2021
b3963f2
Minor IL tweaks to produce smaller IR in the JIT
Sergio0694 Jun 18, 2021
34e1bcb
Add DependentHandle.StopTracking() API
Sergio0694 Jun 21, 2021
9fd1da4
Rename InternalSetTarget to StopTracking, remove redundant param
Sergio0694 Jun 21, 2021
d7146e0
Remove FCUnique from InternalStopTracking
Sergio0694 Jun 21, 2021
c9c6325
Update API surface to match approved specs from API review
Sergio0694 Jun 22, 2021
c463d54
Update DependentHandle XML docs
Sergio0694 Jun 23, 2021
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
Prev Previous commit
Next Next commit
Rename DependentHandle FCalls
  • Loading branch information
Sergio0694 committed Jun 18, 2021
commit ca515b6c9c0711a188cd20994e5f00e393059d71
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public struct DependentHandle : IDisposable
public DependentHandle(object? target, object? dependent)
{
// no need to check for null result: nInitialize expected to throw OOM.
_handle = nInitialize(target, dependent);
_handle = InternalInitialize(target, dependent);
}

/// <summary>
Expand All @@ -79,7 +79,7 @@ public object? Target
ThrowHelper.ThrowInvalidOperationException();
}

return nGetPrimary(handle);
return InternalGetTarget(handle);
}
set
{
Expand All @@ -90,7 +90,7 @@ public object? Target
ThrowHelper.ThrowInvalidOperationException();
}

nSetPrimary(handle, value);
InternalSetTarget(handle, value);
}
}

Expand All @@ -114,7 +114,7 @@ public object? Dependent
ThrowHelper.ThrowInvalidOperationException();
}

return nGetSecondary(handle);
return InternalGetDependent(handle);
}
set
{
Expand All @@ -125,7 +125,7 @@ public object? Dependent
ThrowHelper.ThrowInvalidOperationException();
}

nSetSecondary(handle, value);
InternalSetDependent(handle, value);
}
}

Expand All @@ -143,8 +143,8 @@ public object? Dependent
ThrowHelper.ThrowInvalidOperationException();
}

object? target = nGetPrimary(handle);
object? secondary = nGetSecondary(handle);
object? target = InternalGetTarget(handle);
object? secondary = InternalGetDependent(handle);

return (target, secondary);
}
Expand All @@ -156,7 +156,7 @@ public object? Dependent
/// <remarks>This method mirrors <see cref="Target"/>, but without the allocation check.</remarks>
internal object? UnsafeGetTarget()
{
return nGetPrimary(_handle);
return InternalGetTarget(_handle);
}

/// <summary>
Expand All @@ -165,7 +165,7 @@ public object? Dependent
/// <remarks>This method mirrors <see cref="Target"/>, but without the allocation check.</remarks>
internal void UnsafeSetTarget(object? target)
{
nSetPrimary(_handle, target);
InternalSetTarget(_handle, target);
}

/// <summary>
Expand All @@ -174,7 +174,7 @@ internal void UnsafeSetTarget(object? target)
/// <remarks>This method mirrors <see cref="Dependent"/>, but without the allocation check.</remarks>
internal void UnsafeSetDependent(object? dependent)
{
nSetSecondary(_handle, dependent);
InternalSetDependent(_handle, dependent);
}

/// <summary>
Expand All @@ -190,9 +190,9 @@ internal void UnsafeSetDependent(object? dependent)
{
IntPtr handle = _handle;

object? target = nGetPrimary(handle);
object? target = InternalGetTarget(handle);

dependent = nGetSecondary(handle);
dependent = InternalGetDependent(handle);

return target;
}
Expand All @@ -207,18 +207,18 @@ public void Dispose()
{
IntPtr handle = _handle;
_handle = IntPtr.Zero;
nFree(handle);
InternalFree(handle);
}
}

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern IntPtr nInitialize(object? primary, object? secondary);
private static extern IntPtr InternalInitialize(object? target, object? dependent);

#if DEBUG
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern object? nGetPrimary(IntPtr dependentHandle);
private static extern object? InternalGetTarget(IntPtr dependentHandle);
#else
private static unsafe object? nGetPrimary(IntPtr dependentHandle)
private static unsafe object? InternalGetTarget(IntPtr dependentHandle)
{
// This optimization is the same that is used in GCHandle in RELEASE mode.
// This is not used in DEBUG builds as the runtime performs additional checks.
Expand All @@ -228,15 +228,15 @@ public void Dispose()
#endif

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern object? nGetSecondary(IntPtr dependentHandle);
private static extern object? InternalGetDependent(IntPtr dependentHandle);

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void nSetPrimary(IntPtr dependentHandle, object? primary);
private static extern void InternalSetTarget(IntPtr dependentHandle, object? target);

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void nSetSecondary(IntPtr dependentHandle, object? secondary);
private static extern void InternalSetDependent(IntPtr dependentHandle, object? dependent);

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void nFree(IntPtr dependentHandle);
private static extern void InternalFree(IntPtr dependentHandle);
}
}
59 changes: 26 additions & 33 deletions src/coreclr/vm/comdependenthandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,71 +14,64 @@
#include "common.h"
#include "comdependenthandle.h"



FCIMPL2(OBJECTHANDLE, DependentHandle::nInitialize, Object *_primary, Object *_secondary)
FCIMPL2(OBJECTHANDLE, DependentHandle::InternalInitialize, Object *_target, Object *_dependent)
{
FCALL_CONTRACT;

OBJECTREF primary(_primary);
OBJECTREF secondary(_secondary);
OBJECTREF target(_target);
OBJECTREF dependent(_dependent);
OBJECTHANDLE result = NULL;

HELPER_METHOD_FRAME_BEGIN_RET_NOPOLL();

// Create the handle.
result = GetAppDomain()->CreateDependentHandle(primary, secondary);
result = GetAppDomain()->CreateDependentHandle(target, dependent);

HELPER_METHOD_FRAME_END_POLL();

return result;
}
FCIMPLEND



FCIMPL1(VOID, DependentHandle::nFree, OBJECTHANDLE handle)
FCIMPL1(Object*, DependentHandle::InternalGetTarget, OBJECTHANDLE handle)
{
FCALL_CONTRACT;

FCUnique(0x54);
_ASSERTE(handle != NULL);

HELPER_METHOD_FRAME_BEGIN_0();

DestroyDependentHandle(handle);

HELPER_METHOD_FRAME_END();

return OBJECTREFToObject(ObjectFromHandle(handle));
}
FCIMPLEND



FCIMPL1(Object*, DependentHandle::nGetPrimary, OBJECTHANDLE handle)
FCIMPL1(Object*, DependentHandle::InternalGetDependent, OBJECTHANDLE handle)
{
FCALL_CONTRACT;
FCUnique(0x54);

_ASSERTE(handle != NULL);
return OBJECTREFToObject(ObjectFromHandle(handle));
}
FCIMPLEND

OBJECTREF target = ObjectFromHandle(handle);

IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();

FCIMPL1(Object*, DependentHandle::nGetSecondary, OBJECTHANDLE handle)
// The dependent is tracked only if target is non-null
return (target != NULL) ? mgr->GetDependentHandleSecondary(handle) : NULL;
}
FCIMPLEND

FCIMPL1(VOID, DependentHandle::InternalFree, OBJECTHANDLE handle)
{
FCALL_CONTRACT;

_ASSERTE(handle != NULL);

OBJECTREF primary = ObjectFromHandle(handle);
HELPER_METHOD_FRAME_BEGIN_0();

IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();
// Secondary is tracked only if primary is non-null
return (primary != NULL) ? mgr->GetDependentHandleSecondary(handle) : NULL;
DestroyDependentHandle(handle);

HELPER_METHOD_FRAME_END();
}
FCIMPLEND

FCIMPL2(VOID, DependentHandle::nSetPrimary, OBJECTHANDLE handle, Object *_primary)
FCIMPL2(VOID, DependentHandle::InternalSetTarget, OBJECTHANDLE handle, Object *_target)
{
FCALL_CONTRACT;

Expand All @@ -88,17 +81,17 @@ FCIMPL2(VOID, DependentHandle::nSetPrimary, OBJECTHANDLE handle, Object *_primar
FCUnique(0x12);

IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();
mgr->StoreObjectInHandle(handle, _primary);
mgr->StoreObjectInHandle(handle, _target);
}
FCIMPLEND

FCIMPL2(VOID, DependentHandle::nSetSecondary, OBJECTHANDLE handle, Object *_secondary)
FCIMPL2(VOID, DependentHandle::InternalSetDependent, OBJECTHANDLE handle, Object *_dependent)
{
FCALL_CONTRACT;

_ASSERTE(handle != NULL);

IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();
mgr->SetDependentHandleSecondary(handle, _secondary);
mgr->SetDependentHandleSecondary(handle, _dependent);
}
FCIMPLEND
27 changes: 13 additions & 14 deletions src/coreclr/vm/comdependenthandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@

// A dependent handle is conceputally a tuple containing two object reference
//
// * A Primary object (think key)
// * A Secondary Object (think value)
// * A Target object (think key)
// * A Dependent Object (think value)
//
// The reference to both the primary object is (long) weak (will not keep the object alive). However the
// reference to the secondary object is (long) weak if the primary object is dead, and strong if the primary
// object is alive. (Hence it is a 'Dependent' handle since the strength of the secondary reference depends
// on the primary).
// The reference to both the target object is (long) weak (will not keep the object alive). However the
// reference to the dependent object is (long) weak if the target object is dead, and strong if the target
// object is alive. (Hence it is a 'Dependent' handle since the strength of the dependent reference depends
// on the target).
//
// The effect of this semantics is that it seems that while the DependentHandle exists, the system behaves as
// if there was a normal strong reference from the primary object to the secondary one.
// if there was a normal strong reference from the target object to the dependent one.
//
// The usefulness of a DependentHandle is to allow other objects to be 'attached' to a given object. By
// having a hash table where the entries are dependent handles you can attach arbitrary objects to another
Expand All @@ -40,13 +40,12 @@
class DependentHandle
{
public:
static FCDECL2(OBJECTHANDLE, nInitialize, Object *primary, Object *secondary);
static FCDECL1(Object *, nGetPrimary, OBJECTHANDLE handle);
static FCDECL1(Object *, nGetSecondary, OBJECTHANDLE handle);
static FCDECL1(VOID, nFree, OBJECTHANDLE handle);
static FCDECL2(VOID, nSetPrimary, OBJECTHANDLE handle, Object *primary);
static FCDECL2(VOID, nSetSecondary, OBJECTHANDLE handle, Object *secondary);
static FCDECL2(OBJECTHANDLE, InternalInitialize, Object *target, Object *dependent);
static FCDECL1(Object *, InternalGetTarget, OBJECTHANDLE handle);
static FCDECL1(Object *, InternalGetDependent, OBJECTHANDLE handle);
static FCDECL1(VOID, InternalFree, OBJECTHANDLE handle);
static FCDECL2(VOID, InternalSetTarget, OBJECTHANDLE handle, Object *target);
static FCDECL2(VOID, InternalSetDependent, OBJECTHANDLE handle, Object *dependent);
};

#endif

12 changes: 6 additions & 6 deletions src/coreclr/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@


FCFuncStart(gDependentHandleFuncs)
FCFuncElement("nInitialize", DependentHandle::nInitialize)
FCFuncElement("nGetPrimary", DependentHandle::nGetPrimary)
FCFuncElement("nGetSecondary", DependentHandle::nGetSecondary)
FCFuncElement("nFree", DependentHandle::nFree)
FCFuncElement("nSetPrimary", DependentHandle::nSetPrimary)
FCFuncElement("nSetSecondary", DependentHandle::nSetSecondary)
FCFuncElement("InternalInitialize", DependentHandle::InternalInitialize)
FCFuncElement("InternalGetTarget", DependentHandle::InternalGetTarget)
FCFuncElement("InternalGetDependent", DependentHandle::InternalGetDependent)
FCFuncElement("InternalFree", DependentHandle::InternalFree)
FCFuncElement("InternalSetTarget", DependentHandle::InternalSetTarget)
FCFuncElement("InternalSetDependent", DependentHandle::InternalSetDependent)
FCFuncEnd()


Expand Down