188 lines
6.0 KiB
C#
188 lines
6.0 KiB
C#
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
|
||
|
/*******************************************************************/
|
||
|
/* WARNING */
|
||
|
/* This file should be identical in the Bartok and Singularity */
|
||
|
/* depots. Master copy resides in Bartok Depot. Changes should be */
|
||
|
/* made to Bartok Depot and propagated to Singularity Depot. */
|
||
|
/*******************************************************************/
|
||
|
|
||
|
namespace System.GCs {
|
||
|
|
||
|
using Microsoft.Bartok.Runtime;
|
||
|
using Microsoft.Bartok.Options;
|
||
|
using System.Runtime.CompilerServices;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using System.Threading;
|
||
|
|
||
|
internal unsafe class BrooksCMSBarrierTest: UniversalWriteBarrier {
|
||
|
internal static BrooksCMSBarrierTest instance;
|
||
|
|
||
|
internal static bool allowFastPath;
|
||
|
|
||
|
[NoBarriers]
|
||
|
internal static new void Initialize()
|
||
|
{
|
||
|
BrooksCMSBarrierTest.instance =
|
||
|
(BrooksCMSBarrierTest)
|
||
|
BootstrapMemory.Allocate(typeof(BrooksCMSBarrierTest));
|
||
|
}
|
||
|
|
||
|
[RequiredByBartok]
|
||
|
[MixinConditional("BrooksCMSBarrierTest")]
|
||
|
[Mixin(typeof(PreHeader))]
|
||
|
internal struct BrooksPreHeader {
|
||
|
internal MultiUseWord muw;
|
||
|
[SelfPoint]
|
||
|
internal Object forward;
|
||
|
}
|
||
|
|
||
|
[MixinConditional("BrooksCMSBarrierTest")]
|
||
|
[Mixin(typeof(Object))]
|
||
|
internal class BrooksObject: System.Object {
|
||
|
internal new BrooksPreHeader preHeader;
|
||
|
}
|
||
|
|
||
|
internal static BrooksObject MixinObject(Object o) {
|
||
|
return (BrooksObject)o;
|
||
|
}
|
||
|
|
||
|
[NoBarriers]
|
||
|
internal static Object Forward(Object o)
|
||
|
{
|
||
|
Object result=MixinObject(o).preHeader.forward;
|
||
|
VTable.Assert(result == o);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
[NoBarriers]
|
||
|
internal static Object ForwardNullable(Object o)
|
||
|
{
|
||
|
if (o==null) {
|
||
|
return null;
|
||
|
} else {
|
||
|
return Forward(o);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[NoBarriers]
|
||
|
[Inline]
|
||
|
protected override Object ForwardImpl(Object o, int mask)
|
||
|
{
|
||
|
if ((mask&BarrierMask.PathSpec.AllowFast)!=0) {
|
||
|
return o;
|
||
|
} else {
|
||
|
if ((mask&BarrierMask.Forward.Nullable)!=0 && o == null) {
|
||
|
return null;
|
||
|
} else {
|
||
|
return Forward(o);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[ForceInline]
|
||
|
[NoBarriers]
|
||
|
protected override bool AllowFastPathImpl()
|
||
|
{
|
||
|
return allowFastPath;
|
||
|
}
|
||
|
|
||
|
[ForceInline]
|
||
|
[NoBarriers]
|
||
|
protected override void InitObjectImpl(Object o, VTable vtable)
|
||
|
{
|
||
|
MyInitObject(o, vtable);
|
||
|
}
|
||
|
|
||
|
internal static new void BootstrapInitObjectImpl(Object o,
|
||
|
VTable vtable)
|
||
|
{
|
||
|
MyInitObject(o, vtable);
|
||
|
}
|
||
|
|
||
|
[ForceInline]
|
||
|
[NoBarriers]
|
||
|
private static void MyInitObject(Object o, VTable vtable)
|
||
|
{
|
||
|
MixinObject(o).preHeader.forward = o;
|
||
|
o.vtable = vtable;
|
||
|
}
|
||
|
|
||
|
[ForceInline]
|
||
|
[NoBarriers]
|
||
|
protected override Object AtomicSwapImpl(ref Object reference,
|
||
|
Object value,
|
||
|
int mask)
|
||
|
{
|
||
|
CMSMarking.ReferenceCheck(ref reference, value, 0);
|
||
|
UIntPtr resultAddr =
|
||
|
Interlocked.Exchange(Magic.toPointer(ref reference),
|
||
|
Magic.addressOf(value));
|
||
|
return Magic.fromAddress(resultAddr);
|
||
|
}
|
||
|
|
||
|
[ForceInline]
|
||
|
[NoBarriers]
|
||
|
protected override Object AtomicCompareAndSwapImpl(ref Object loc,
|
||
|
Object newVal,
|
||
|
Object comp,
|
||
|
int mask)
|
||
|
{
|
||
|
CMSMarking.ReferenceCheck(ref loc, newVal, 0);
|
||
|
newVal = ForwardNullable(newVal);
|
||
|
for (;;) {
|
||
|
Object oldVal = loc;
|
||
|
Object commitVal;
|
||
|
if (oldVal == comp ||
|
||
|
ForwardNullable(oldVal) == ForwardNullable(comp)) {
|
||
|
commitVal = newVal;
|
||
|
} else {
|
||
|
// still CAS but only to get a memory barrier
|
||
|
commitVal = oldVal;
|
||
|
}
|
||
|
if (Interlocked.CompareExchange(ref loc,
|
||
|
commitVal, oldVal)
|
||
|
== oldVal) {
|
||
|
return oldVal;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[ForceInline]
|
||
|
[NoBarriers]
|
||
|
protected override bool EqImpl(Object a, Object b, int mask)
|
||
|
{
|
||
|
if ((mask&BarrierMask.PathSpec.AllowFast)!=0) {
|
||
|
return a == b;
|
||
|
} else {
|
||
|
return a == b || ForwardNullable(a) == ForwardNullable(b);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[ForceInline]
|
||
|
[NoBarriers]
|
||
|
[NoStackLinkCheckTrans]
|
||
|
protected override void WriteImpl(UIntPtr *location,
|
||
|
Object value,
|
||
|
int mask)
|
||
|
{
|
||
|
CMSMarking.ReferenceCheck(location, value, 0);
|
||
|
*location = Magic.addressOf(value);
|
||
|
}
|
||
|
|
||
|
[ForceInline]
|
||
|
[NoBarriers]
|
||
|
[NoStackLinkCheckTrans]
|
||
|
protected override void WriteImplByRef(ref Object location,
|
||
|
Object value,
|
||
|
int mask)
|
||
|
{
|
||
|
CMSMarking.ReferenceCheck(ref location, value, 0);
|
||
|
location = value;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|