singrdk/base/Imported/Bartok/runtime/shared/GCs/WriteBarrierCMS.cs

139 lines
5.2 KiB
C#
Raw Permalink Normal View History

2008-11-17 18:29:00 -05:00
//
// 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;
}
}
}