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

[mono] Implement synch block fast paths in managed #81380

Merged
merged 44 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9028f00
[mono] Implement synch block fast paths in managed
lambdageek Jan 30, 2023
10a6c3d
Implement TryEnterFast and TryEnterInflatedFast
lambdageek Jan 30, 2023
4d62281
wip
lambdageek Jan 31, 2023
9ae85c0
Add replacements for test_owner and test_synchronized icalls
lambdageek Jan 31, 2023
c3c16cf
use sequential layout for LockWord
lambdageek Feb 1, 2023
bca9113
remove managed Inflate (ifdef'd out)
lambdageek Feb 1, 2023
cef418a
access sync block through helpers
lambdageek Feb 1, 2023
a97a01f
add DumpRef to print out pointer values from ObjectHeader
lambdageek Feb 1, 2023
e810d94
Get a pointer to the object header another way
lambdageek Feb 1, 2023
c51ff1c
remove DumpRef
lambdageek Feb 1, 2023
2939ac2
XXX temporary return from MonoResolveUnmanagedDll if context is null
lambdageek Feb 1, 2023
6060694
XXX some bug in GetHashCode :-(
lambdageek Feb 1, 2023
93ba644
BUGFIX: logical shifts, not arithmetic
lambdageek Feb 1, 2023
a9bd40e
XXX disable hacks
lambdageek Feb 1, 2023
129de86
put back the ALC hack
lambdageek Feb 1, 2023
7496a54
force inlining
lambdageek Feb 1, 2023
5845dac
move fast path into ReliableEnterTimeout
lambdageek Feb 2, 2023
847382b
Don't pass lockTaken to ObjectHolder.TryEnterFast
lambdageek Feb 2, 2023
7a356ab
TryEnterFast: handle flat recursive locking, too
lambdageek Feb 2, 2023
5fc1cdc
whitespace
lambdageek Feb 2, 2023
bf088fd
Implement Monitor.Exit fast path in managed
lambdageek Feb 2, 2023
1ac6759
Don't call MonoResolveUnmanagedDll for the default ALC
lambdageek Feb 2, 2023
60ba170
[interp] don't lookup internal calls that were replaced by an opcode
lambdageek Feb 2, 2023
8ecb7ff
Add Interlocked.CompareExchange interp intrinsics for I4 and I8
lambdageek Feb 2, 2023
14cd820
ask EE to inline LockWordCompareExchange
lambdageek Feb 2, 2023
0360524
Use a ref struct to pass around the address of a MonoObject* on the s…
lambdageek Feb 2, 2023
bb1e698
Add fast path for Monitor.Exit for inflated monitors with no waiters
lambdageek Feb 6, 2023
6506515
Check for obj == null before ThrowIfNull
lambdageek Feb 6, 2023
91446f9
Inline RuntimeHelpers.GetHashCode
lambdageek Feb 6, 2023
76805ba
inline TryEnterInflatedFast; nano-opts
lambdageek Feb 6, 2023
064eb10
disable the TryGetHashCode fast path helper
lambdageek Feb 6, 2023
bbe5cde
Fix last exit from inflated monitor
lambdageek Feb 6, 2023
cabd864
avoid repeated calls in TryEnterInflatedFast
lambdageek Feb 7, 2023
f8da57d
Combine TryExit and IsEntered into TryExitChecked
lambdageek Feb 7, 2023
2204a82
Re-enable managed GetHashCode in JIT; intrinsify in interp
lambdageek Feb 7, 2023
47f2135
[coop][interp] Fix GC transitions for thunk invoke wrappers
lambdageek Feb 7, 2023
fae8a2f
add CMPXCHG opcodes to the jiterpreter
lambdageek Feb 8, 2023
1c0f6ae
Revert "[coop][interp] Fix GC transitions for thunk invoke wrappers"
lambdageek Feb 10, 2023
921cb08
Assert that CEE_MONO_GET_SP is followed by gc safe enter/exit icalls
lambdageek Feb 10, 2023
7a55bf0
[marshal] Add GCUnsafeTransitionBuilder; use for thunk_invoke_wrapper
lambdageek Feb 10, 2023
779b3ff
fix whitespace
lambdageek Feb 13, 2023
def185c
Merge remote-tracking branch 'origin/main' into feature-lockword-in-m…
lambdageek Feb 13, 2023
71a9422
more whitespace
lambdageek Feb 13, 2023
ee39682
[jiterp] Allow null obj in hashcode intrinsics
lambdageek Feb 14, 2023
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 @@ -266,6 +266,7 @@
<Compile Include="$(BclSourcesRoot)\System\Security\DynamicSecurityMethodAttribute.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Interlocked.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Monitor.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\ObjectHeader.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Thread.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\ThreadPool.Mono.cs" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ public static int OffsetToStringData
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern int InternalGetHashCode(object? o);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetHashCode(object? o)
lambdageek marked this conversation as resolved.
Show resolved Hide resolved
{
// NOTE: the interpreter does not run this code. It intrinsifies the whole RuntimeHelpers.GetHashCode function
if (Threading.ObjectHeader.TryGetHashCode (o, out int hash))
return hash;
return InternalGetHashCode(o);
}

Expand All @@ -55,8 +59,12 @@ public static int GetHashCode(object? o)
/// The advantage of this over <see cref="GetHashCode" /> is that it avoids assigning a hash
/// code to the object if it does not already have one.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int TryGetHashCode(object? o)
{
// NOTE: the interpreter does not run this code. It intrinsifies the whole RuntimeHelpers.TryGetHashCode function
if (Threading.ObjectHeader.TryGetHashCode (o, out int hash))
return hash;
return InternalTryGetHashCode(o);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,17 @@ public static void Enter(object obj, ref bool lockTaken)
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern void Exit(object obj);
private static extern void InternalExit(object obj);

public static void Exit(object obj)
{
if (obj == null)
ArgumentNullException.ThrowIfNull(obj);
if (ObjectHeader.TryExitChecked(obj))
return;

InternalExit(obj);
}

public static bool TryEnter(object obj)
{
Expand All @@ -43,6 +53,7 @@ public static void TryEnter(object obj, ref bool lockTaken)
public static bool TryEnter(object obj, int millisecondsTimeout)
{
bool lockTaken = false;

lambdageek marked this conversation as resolved.
Show resolved Hide resolved
TryEnter(obj, millisecondsTimeout, ref lockTaken);
return lockTaken;
}
Expand All @@ -51,13 +62,14 @@ public static void TryEnter(object obj, int millisecondsTimeout, ref bool lockTa
{
if (lockTaken)
throw new ArgumentException(SR.Argument_MustBeFalse, nameof(lockTaken));

ReliableEnterTimeout(obj, millisecondsTimeout, ref lockTaken);
}

public static bool IsEntered(object obj)
{
ArgumentNullException.ThrowIfNull(obj);
return IsEnteredNative(obj);
return ObjectHeader.IsEntered(obj);
}

[UnsupportedOSPlatform("browser")]
Expand All @@ -79,15 +91,12 @@ public static void PulseAll(object obj)
ObjPulseAll(obj);
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool Monitor_test_synchronised(object obj);

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void Monitor_pulse(object obj);

private static void ObjPulse(object obj)
{
if (!Monitor_test_synchronised(obj))
if (!ObjectHeader.HasOwner(obj))
throw new SynchronizationLockException();

Monitor_pulse(obj);
Expand All @@ -98,7 +107,7 @@ private static void ObjPulse(object obj)

private static void ObjPulseAll(object obj)
{
if (!Monitor_test_synchronised(obj))
if (!ObjectHeader.HasOwner(obj))
throw new SynchronizationLockException();

Monitor_pulse_all(obj);
Expand All @@ -111,7 +120,7 @@ private static bool ObjWait(int millisecondsTimeout, object obj)
{
if (millisecondsTimeout < 0 && millisecondsTimeout != (int)Timeout.Infinite)
throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout));
if (!Monitor_test_synchronised(obj))
if (!ObjectHeader.HasOwner(obj))
throw new SynchronizationLockException();

return Monitor_wait(obj, millisecondsTimeout, true);
Expand All @@ -120,22 +129,22 @@ private static bool ObjWait(int millisecondsTimeout, object obj)
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void try_enter_with_atomic_var(object obj, int millisecondsTimeout, bool allowInterruption, ref bool lockTaken);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void ReliableEnterTimeout(object obj, int timeout, ref bool lockTaken)
{
ArgumentNullException.ThrowIfNull(obj);
if (obj == null)
ArgumentNullException.ThrowIfNull(obj);

if (timeout < 0 && timeout != (int)Timeout.Infinite)
throw new ArgumentOutOfRangeException(nameof(timeout));

try_enter_with_atomic_var(obj, timeout, true, ref lockTaken);
}
// fast path
if (ObjectHeader.TryEnterFast(obj)) {
lockTaken = true;
return;
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool Monitor_test_owner(object obj);

private static bool IsEnteredNative(object obj)
{
return Monitor_test_owner(obj);
try_enter_with_atomic_var(obj, timeout, true, ref lockTaken);
}

public static extern long LockContentionCount
Expand Down
Loading