// // 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.Runtime.CompilerServices; using System.Threading; //[NoBarriers] internal unsafe class GenerationalWriteBarrier : RefWriteBarrier { internal static GenerationalWriteBarrier instance; [NoBarriers] internal static new void Initialize() { GenerationalWriteBarrier.instance = (GenerationalWriteBarrier) BootstrapMemory.Allocate(typeof(GenerationalWriteBarrier)); } [Inline] [NoBarriers] protected override void StoreStaticFieldImpl(ref Object staticField, Object value, int mask) { // No need to perform a ReferenceCheck here! staticField = value; } protected override void CopyStructImpl(Object srcObj, Object dstObj, VTable vtable, UIntPtr srcPtr, UIntPtr dstPtr) { CopyStructWithBarrier(vtable, srcPtr, dstPtr); } [Inline] protected override Object AtomicSwapImpl(ref Object reference, Object value, int mask) { UIntPtr *ptr=Magic.toPointer(ref reference); UIntPtr resultAddr = Interlocked.Exchange(ptr, Magic.addressOf(value)); ReferenceCheck(ptr, value); return Magic.fromAddress(resultAddr); } [Inline] protected override Object AtomicCompareAndSwapImpl(ref Object reference, Object newValue, Object comparand, int mask) { UIntPtr *ptr=Magic.toPointer(ref reference); UIntPtr resultAddr = Interlocked.CompareExchange(ptr, Magic.addressOf(newValue), Magic.addressOf(comparand)); ReferenceCheck(ptr, newValue); return Magic.fromAddress(resultAddr); } [Inline] protected override void CloneImpl(Object srcObject, Object dstObject) { CloneNoBarrier(srcObject, dstObject); ReferenceCheck(dstObject); } // 'offset' is not relative to the lower bound, but is a count // of elements from the first element in the array. protected override void ArrayZeroImpl(Array array, int offset, int length) { ArrayZeroNoBarrier(array, offset, length); } // 'offset' is not relative to the lower bound, but is a count // of elements from the first element in the array. protected override void ArrayCopyImpl(Array srcArray, int srcOffset, Array dstArray, int dstOffset, int length) { if ((length > 1000) || ((length << 2) >= dstArray.Length)) { ArrayCopyNoBarrier(srcArray, srcOffset, dstArray, dstOffset, length); ReferenceCheck(dstArray); } else { ArrayCopyWithBarrier(srcArray, srcOffset, dstArray, dstOffset, length); } } [Inline] protected override void WriteImpl(UIntPtr *location, Object value, int mask) { WriteImplNoMask(location, value); } [RequiredByBartok] [Inline] private static void WriteImplNoMask(UIntPtr *location, Object value) { *location = Magic.addressOf(value); ReferenceCheck(location, value); } [Inline] protected override void WriteImplByRef(ref Object location, Object value, int mask) { WriteImpl(Magic.toPointer(ref location), value, mask); } [Inline] private static void ReferenceCheck(Object obj) { PageType pageType = PageTable.Type(PageTable.Page(Magic.addressOf(obj))); if (GenerationalGCData.MAX_GENERATION == PageType.Owner1) { if (pageType == PageType.Owner1) { GenerationalGCData. installedRemSet.RecordClonedObject(obj); } } else { if (pageType != GenerationalGCData.nurseryGeneration) { GenerationalGCData. installedRemSet.RecordClonedObject(obj); } } } [Inline] private static void ReferenceCheck(UIntPtr *addr, Object value) { PageType addrType = PageTable.Type(PageTable.Page((UIntPtr) addr)); if (GenerationalGCData.MAX_GENERATION == PageType.Owner1) { if (addrType != PageType.Owner1) { return; } else { ReferenceCheck(addrType, addr, value); } } else { if (PageTable.IsLiveGcPage(addrType)){ ReferenceCheck(addrType, addr, value); } } } [NoInline] private static void ReferenceCheck(PageType addrType, UIntPtr *addr, Object value) { VTable.Assert(PageTable.IsGcPage(addrType)); if (GC.remsetType == RemSetType.Cards) { GenerationalGCData. installedRemSet.RecordReference(addr, value); return; } UIntPtr valueAddr = Magic.addressOf(value); PageType valType = PageTable.Type(PageTable.Page(valueAddr)); if (PageTable.IsGcPage(valType) && (addrType > valType)){ GenerationalGCData. installedRemSet.RecordReference(addr, value); } } } }