139 lines
5.2 KiB
C#
139 lines
5.2 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 System.Threading;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
|
|
//[NoBarriers]
|
|
internal unsafe class WriteBarrierCMS : UniversalWriteBarrier
|
|
{
|
|
|
|
internal static WriteBarrierCMS instance;
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
struct FakeObjectBytes
|
|
{
|
|
public PreHeader preBytes;
|
|
public PostHeader postBytes;
|
|
}
|
|
private static FakeObjectBytes memoryForFakeObject;
|
|
|
|
[NoBarriers]
|
|
[NoHeapAllocation]
|
|
internal static WriteBarrierCMS MakeEarlyInstance()
|
|
{
|
|
// We need a write barrier even if we haven't set up enough of the
|
|
// memory system to support allocating from bootstrap memory yet.
|
|
VTable vtable =
|
|
((RuntimeType) typeof(WriteBarrierCMS)).classVtable;
|
|
UIntPtr numBytes = ObjectLayout.ObjectSize(vtable);
|
|
if (numBytes > (UIntPtr) sizeof(FakeObjectBytes)) {
|
|
return null; // too big to allocate in memoryForFakeObject
|
|
}
|
|
UIntPtr fakeObjectAddr;
|
|
fixed (PostHeader *middlePtr = & memoryForFakeObject.postBytes) {
|
|
fakeObjectAddr = (UIntPtr) middlePtr;
|
|
}
|
|
Object result = Magic.fromAddress(fakeObjectAddr);
|
|
*result.VTableFieldAddr = Magic.addressOf(vtable);
|
|
return (WriteBarrierCMS) result;
|
|
}
|
|
|
|
[PreInitRefCounts]
|
|
[NoBarriers]
|
|
internal static new void Initialize() {
|
|
if (WriteBarrierCMS.instance == null) {
|
|
WriteBarrierCMS.instance = (WriteBarrierCMS)
|
|
BootstrapMemory.Allocate(typeof(WriteBarrierCMS));
|
|
}
|
|
}
|
|
|
|
// NOTE: this code uses ForceInline instead of Inline to indicate that
|
|
// inlining should occur even if the caller is huge. In general, this
|
|
// attribute should be used with great care. DO NOT USE IT ELSEWHERE
|
|
// IN THE RUNTIME UNLESS YOU ARE WILLING TO DOCUMENT YOUR USE IN
|
|
// IrSimpleInliner.cs AND Attributes.cs! AND NEVER USE IT IN
|
|
// APPLICATION OR OS CODE!
|
|
|
|
[ForceInline]
|
|
protected override bool AllowFastPathImpl()
|
|
{
|
|
return CMSMarking.referenceCheckIsFast;
|
|
}
|
|
|
|
[ForceInline]
|
|
[NoBarriers]
|
|
[NoStackLinkCheckTrans]
|
|
protected override Object AtomicSwapImpl(ref Object reference,
|
|
Object value,
|
|
int mask)
|
|
{
|
|
CMSMarking.ReferenceCheck(ref reference, value, mask);
|
|
UIntPtr resultAddr =
|
|
Interlocked.Exchange(Magic.toPointer(ref reference),
|
|
Magic.addressOf(value));
|
|
return Magic.fromAddress(resultAddr);
|
|
}
|
|
|
|
[ForceInline]
|
|
[NoBarriers]
|
|
[NoStackLinkCheckTrans]
|
|
protected override
|
|
Object AtomicCompareAndSwapImpl(ref Object reference,
|
|
Object newValue,
|
|
Object comparand,
|
|
int mask)
|
|
{
|
|
CMSMarking.ReferenceCheck(ref reference, newValue, mask);
|
|
UIntPtr resultAddr =
|
|
Interlocked.CompareExchange(Magic.toPointer(ref reference),
|
|
Magic.addressOf(newValue),
|
|
Magic.addressOf(comparand));
|
|
return Magic.fromAddress(resultAddr);
|
|
}
|
|
|
|
[Inline]
|
|
[NoBarriers]
|
|
[NoStackLinkCheckTrans]
|
|
protected override void CloneImpl(Object srcObject, Object dstObject)
|
|
{
|
|
// There is no need to keep track of initial writes, so do nothing!
|
|
CloneNoBarrier(srcObject, dstObject);
|
|
}
|
|
|
|
[ForceInline]
|
|
[NoBarriers]
|
|
[NoStackLinkCheckTrans]
|
|
protected override void WriteImpl(UIntPtr *location,
|
|
Object value,
|
|
int mask)
|
|
{
|
|
CMSMarking.ReferenceCheck(location, value, mask);
|
|
*location = Magic.addressOf(value);
|
|
}
|
|
|
|
[ForceInline]
|
|
[NoBarriers]
|
|
[NoStackLinkCheckTrans]
|
|
protected override void WriteImplByRef(ref Object location,
|
|
Object value,
|
|
int mask)
|
|
{
|
|
CMSMarking.ReferenceCheck(ref location, value, mask);
|
|
location = value;
|
|
}
|
|
}
|
|
}
|