//
// 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;

    //[CCtorIsRunDuringStartup]
    //[NoBarriers]
    [NoCCtor]
    internal abstract unsafe class Barrier
    {

        [TrustedNonNull]
        [NoBarriers]
        protected internal static Barrier installedBarrier;

        [TrustedNonNull]
        private static CopyFieldsVisitor copyFieldsVisitor;

        [TrustedNonNull]
        private static ZeroFieldsVisitor zeroFieldsVisitor;

        [TrustedNonNull]
        private static SlowCopyFieldsVisitor slowCopyFieldsVisitor;

        [TrustedNonNull]
        private static SlowZeroFieldsVisitor slowZeroFieldsVisitor;

        [NoBarriers]
        [NoHeapAllocation]
        internal static void PreInitialize()
        {
#if !SINGULARITY || CONCURRENT_MS_COLLECTOR
            if (GC.wbType == WBType.CMS) {
                // We need a write barrier even if we haven't set up enough of the memory
                // system to support allocating from bootstrap memory yet.
                installedBarrier = WriteBarrierCMS.MakeEarlyInstance();
            }
#endif
        }

        [NoBarriers]
        [PreInitRefCounts]
        internal static void Initialize()
        {
            switch (GC.wbType) {
#if !SINGULARITY || MARK_SWEEP_COLLECTOR || NULL_COLLECTOR
              case WBType.noWB: {
                  EmptyWriteBarrier.Initialize();
                  installedBarrier = EmptyWriteBarrier.instance;
                  break;
              }
#endif
#if !SINGULARITY || SEMISPACE_COLLECTOR || SLIDING_COLLECTOR || ADAPTIVE_COPYING_COLLECTOR
              case WBType.Generational: {
                  GenerationalWriteBarrier.Initialize();
                  installedBarrier = GenerationalWriteBarrier.instance;
                  break;
              }
#endif
#if !SINGULARITY || CONCURRENT_MS_COLLECTOR
              case WBType.CMS: {
                  WriteBarrierCMS.Initialize();
                  installedBarrier = WriteBarrierCMS.instance;
                  break;
              }
#endif
#if !SINGULARITY || ATOMIC_RC_COLLECTOR
              case WBType.ARC: {
                  AtomicRCWriteBarrier.Initialize();
                  installedBarrier = AtomicRCWriteBarrier.instance;
                  break;
              }
#endif
#if !SINGULARITY || SEMISPACE_COLLECTOR || SLIDING_COLLECTOR || ADAPTIVE_COPYING_COLLECTOR
              case WBType.AllCards: {
                  AllCardsWriteBarrier.Initialize();
                  installedBarrier = AllCardsWriteBarrier.instance;
                  break;
              }
#endif
#if !SINGULARITY
              case WBType.ExpandingCoCo: {
                  ExpandingCoCoBarrier.Initialize();
                  installedBarrier = ExpandingCoCoBarrier.instance;
                  break;
              }
              case WBType.ProbabilisticCoCo: {
                  ProbabilisticCoCoBarrier.Initialize();
                  installedBarrier = ProbabilisticCoCoBarrier.instance;
                  break;
              }
              case WBType.AbortingCoCo: {
                  AbortingCoCoBarrier.Initialize();
                  installedBarrier = AbortingCoCoBarrier.instance;
                  break;
              }
              case WBType.BrooksTest: {
                  BrooksBarrierTest.Initialize();
                  installedBarrier = BrooksBarrierTest.instance;
                  break;
              }
              case WBType.BrooksCMSTest: {
                  BrooksCMSBarrierTest.Initialize();
                  installedBarrier = BrooksCMSBarrierTest.instance;
                  break;
              }
#endif
              default: {
                  VTable.NotReached("Unknown write barrier type: "+GC.wbType);
                  break;
              }
            }
            // copyFieldsVisitor = new CopyFieldsVisitor();
            Barrier.copyFieldsVisitor = (CopyFieldsVisitor)
                BootstrapMemory.Allocate(typeof(CopyFieldsVisitor));
            // zeroFieldsVisitor = new ZeroFieldsVisitor();
            Barrier.zeroFieldsVisitor = (ZeroFieldsVisitor)
                BootstrapMemory.Allocate(typeof(ZeroFieldsVisitor));
            // slowCopyFieldsVisitor = new SlowCopyFieldsVisitor();
            Barrier.slowCopyFieldsVisitor = (SlowCopyFieldsVisitor)
                BootstrapMemory.Allocate(typeof(SlowCopyFieldsVisitor));
            // slowZeroFieldsVisitor = new SlowZeroFieldsVisitor();
            Barrier.slowZeroFieldsVisitor = (SlowZeroFieldsVisitor)
                BootstrapMemory.Allocate(typeof(SlowZeroFieldsVisitor));
        }

        // 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!

        //////////////////////// StoreIndirectImpl /////////////////////

        [ForceInline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImplByRef(ref Object location,
                                                      Object value,
                                                      int mask)
        {
            this.WriteImplByRef(ref location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImplByRef(ref float location,
                                                      float value,
                                                      int mask)
        {
            this.WriteImplByRef(ref location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImplByRef(ref double location,
                                                      double value,
                                                      int mask)
        {
            this.WriteImplByRef(ref location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImplByRef(ref byte location,
                                                      byte value,
                                                      int mask)
        {
            this.WriteImplByRef(ref location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImplByRef(ref ushort location,
                                                      ushort value,
                                                      int mask)
        {
            this.WriteImplByRef(ref location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImplByRef(ref uint location,
                                                      uint value,
                                                      int mask)
        {
            this.WriteImplByRef(ref location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImplByRef(ref ulong location,
                                                      ulong value,
                                                      int mask)
        {
            this.WriteImplByRef(ref location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImplByRef(ref UIntPtr location,
                                                      UIntPtr value,
                                                      int mask)
        {
            this.WriteImplByRef(ref location, value, mask);
        }

        //////////////////////// StoreIndirectImpl to ptr /////////////////////

        [ForceInline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImpl(UIntPtr* location,
                                                 Object value,
                                                 int mask)
        {
            this.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImpl(float* location,
                                                 float value,
                                                 int mask)
        {
            this.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImpl(double* location,
                                                 double value,
                                                 int mask)
        {
            this.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImpl(byte* location,
                                                 byte value,
                                                 int mask)
        {
            this.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImpl(ushort* location,
                                                 ushort value,
                                                 int mask)
        {
            this.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImpl(uint* location,
                                                 uint value,
                                                 int mask)
        {
            this.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImpl(ulong* location,
                                                 ulong value,
                                                 int mask)
        {
            this.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreIndirectImpl(UIntPtr* location,
                                                 UIntPtr value,
                                                 int mask)
        {
            this.WriteImpl(location, value, mask);
        }

        //////////////////////// LoadIndirectImpl from ptr /////////////////////

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual Object LoadObjIndirectImpl(UIntPtr* location,
                                                     int mask)
        {
            return this.ReadObjImpl(location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual float LoadIndirectImpl(float* location,
                                                 int mask)
        {
            return this.ReadImpl(location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual double LoadIndirectImpl(double* location,
                                                  int mask)
        {
            return this.ReadImpl(location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual byte LoadIndirectImpl(byte* location,
                                                int mask)
        {
            return this.ReadImpl(location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual ushort LoadIndirectImpl(ushort* location,
                                                  int mask)
        {
            return this.ReadImpl(location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual uint LoadIndirectImpl(uint* location,
                                                int mask)
        {
            return this.ReadImpl(location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual ulong LoadIndirectImpl(ulong* location,
                                                 int mask)
        {
            return this.ReadImpl(location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual UIntPtr LoadIndirectImpl(UIntPtr* location,
                                                   int mask)
        {
            return this.ReadImpl(location, mask);
        }

        //////////////////////// LoadIndirectImpl /////////////////////

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual Object LoadIndirectImplByRef(ref Object location,
                                                       int mask)
        {
            return this.ReadImplByRef(ref location, mask);
        }

        [Inline]
        [NoBarriers]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected virtual float LoadIndirectImplByRef(ref float location,
                                                      int mask)
        {
            return this.ReadImplByRef(ref location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual double LoadIndirectImplByRef(ref double location,
                                                       int mask)
        {
            return this.ReadImplByRef(ref location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual byte LoadIndirectImplByRef(ref byte location,
                                                     int mask)
        {
            return this.ReadImplByRef(ref location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual ushort LoadIndirectImplByRef(ref ushort location,
                                                       int mask)
        {
            return this.ReadImplByRef(ref location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual uint LoadIndirectImplByRef(ref uint location,
                                                     int mask)
        {
            return this.ReadImplByRef(ref location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual ulong LoadIndirectImplByRef(ref ulong location,
                                                      int mask)
        {
            return this.ReadImplByRef(ref location, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual UIntPtr LoadIndirectImplByRef(ref UIntPtr location,
                                                        int mask)
        {
            return this.ReadImplByRef(ref location, mask);
        }

        /////////////////////// StoreObjectFieldImpl ///////////////////

        [ForceInline]
        [NoBarriers]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected virtual void StoreObjectFieldImpl(Object obj,
                                                    UIntPtr fieldOffset,
                                                    Object value,
                                                    int mask)
        {
            this.WriteImpl(obj, fieldOffset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreObjectFieldImpl(Object obj,
                                                    UIntPtr fieldOffset,
                                                    float value,
                                                    int mask)
        {
            this.WriteImpl(obj, fieldOffset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreObjectFieldImpl(Object obj,
                                                    UIntPtr fieldOffset,
                                                    double value,
                                                    int mask)
        {
            this.WriteImpl(obj, fieldOffset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreObjectFieldImpl(Object obj,
                                                    UIntPtr fieldOffset,
                                                    byte value,
                                                    int mask)
        {
            this.WriteImpl(obj, fieldOffset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreObjectFieldImpl(Object obj,
                                                    UIntPtr fieldOffset,
                                                    ushort value,
                                                    int mask)
        {
            this.WriteImpl(obj, fieldOffset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreObjectFieldImpl(Object obj,
                                                    UIntPtr fieldOffset,
                                                    uint value,
                                                    int mask)
        {
            this.WriteImpl(obj, fieldOffset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreObjectFieldImpl(Object obj,
                                                    UIntPtr fieldOffset,
                                                    ulong value,
                                                    int mask)
        {
            this.WriteImpl(obj, fieldOffset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreObjectFieldImpl(Object obj,
                                                    UIntPtr fieldOffset,
                                                    UIntPtr value,
                                                    int mask)
        {
            this.WriteImpl(obj, fieldOffset, value, mask);
        }

        /////////////////////// LoadObjectFieldImpl ///////////////////

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual Object LoadObjObjectFieldImpl(Object obj,
                                                        UIntPtr fieldOffset,
                                                        int mask)
        {
            return this.ReadObjImpl(obj, fieldOffset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual float LoadFloatObjectFieldImpl(Object obj,
                                                         UIntPtr fieldOffset,
                                                         int mask)
        {
            return this.ReadFloatImpl(obj, fieldOffset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual double LoadDoubleObjectFieldImpl(Object obj,
                                                           UIntPtr fieldOffset,
                                                           int mask)
        {
            return this.ReadDoubleImpl(obj, fieldOffset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual byte LoadByteObjectFieldImpl(Object obj,
                                                       UIntPtr fieldOffset,
                                                       int mask)
        {
            return this.ReadByteImpl(obj, fieldOffset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual ushort LoadUShortObjectFieldImpl(Object obj,
                                                           UIntPtr fieldOffset,
                                                           int mask)
        {
            return this.ReadUShortImpl(obj, fieldOffset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual uint LoadUIntObjectFieldImpl(Object obj,
                                                       UIntPtr fieldOffset,
                                                       int mask)
        {
            return this.ReadUIntImpl(obj, fieldOffset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual ulong LoadULongObjectFieldImpl(Object obj,
                                                         UIntPtr fieldOffset,
                                                         int mask)
        {
            return this.ReadULongImpl(obj, fieldOffset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        UIntPtr LoadUIntPtrObjectFieldImpl(Object obj,
                                           UIntPtr fieldOffset,
                                           int mask)
        {
            return this.ReadUIntPtrImpl(obj, fieldOffset, mask);
        }

        ////////////////////// StoreStructFieldImpl ////////////////////

        [ForceInline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreStructFieldImpl(UIntPtr structPtr,
                                                    UIntPtr fieldOffset,
                                                    Object value,
                                                    int mask)
        {
            UIntPtr *fieldPtr = (UIntPtr *) (structPtr + fieldOffset);
            this.WriteImpl(fieldPtr, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreStructFieldImpl(UIntPtr structPtr,
                                                    UIntPtr fieldOffset,
                                                    float value,
                                                    int mask)
        {
            float *fieldPtr = (float *) (structPtr + fieldOffset);
            this.WriteImpl(fieldPtr, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreStructFieldImpl(UIntPtr structPtr,
                                                    UIntPtr fieldOffset,
                                                    double value,
                                                    int mask)
        {
            double *fieldPtr = (double *) (structPtr + fieldOffset);
            this.WriteImpl(fieldPtr, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreStructFieldImpl(UIntPtr structPtr,
                                                    UIntPtr fieldOffset,
                                                    byte value,
                                                    int mask)
        {
            byte *fieldPtr = (byte *) (structPtr + fieldOffset);
            this.WriteImpl(fieldPtr, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreStructFieldImpl(UIntPtr structPtr,
                                                    UIntPtr fieldOffset,
                                                    ushort value,
                                                    int mask)
        {
            ushort *fieldPtr = (ushort *) (structPtr + fieldOffset);
            this.WriteImpl(fieldPtr, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreStructFieldImpl(UIntPtr structPtr,
                                                    UIntPtr fieldOffset,
                                                    uint value,
                                                    int mask)
        {
            uint *fieldPtr = (uint *) (structPtr + fieldOffset);
            this.WriteImpl(fieldPtr, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreStructFieldImpl(UIntPtr structPtr,
                                                    UIntPtr fieldOffset,
                                                    ulong value,
                                                    int mask)
        {
            ulong *fieldPtr = (ulong *) (structPtr + fieldOffset);
            this.WriteImpl(fieldPtr, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreStructFieldImpl(UIntPtr structPtr,
                                                    UIntPtr fieldOffset,
                                                    UIntPtr value,
                                                    int mask)
        {
            UIntPtr *fieldPtr = (UIntPtr *) (structPtr + fieldOffset);
            this.WriteImpl(fieldPtr, value, mask);
        }

        //////////////////// LoadStructFieldImpl ////////////////////

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual Object LoadObjStructFieldImpl(UIntPtr structPtr,
                                                        UIntPtr fieldOffset,
                                                        int mask)
        {
            UIntPtr *fieldPtr = (UIntPtr *) (structPtr + fieldOffset);
            return this.ReadObjImpl(fieldPtr, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual float LoadFloatStructFieldImpl(UIntPtr structPtr,
                                                         UIntPtr fieldOffset,
                                                         int mask)
        {
            float *fieldPtr = (float *) (structPtr + fieldOffset);
            return this.ReadImpl(fieldPtr, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual double LoadDoubleStructFieldImpl(UIntPtr structPtr,
                                                           UIntPtr fieldOffset,
                                                           int mask)
        {
            double *fieldPtr = (double *) (structPtr + fieldOffset);
            return this.ReadImpl(fieldPtr, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual byte LoadByteStructFieldImpl(UIntPtr structPtr,
                                                       UIntPtr fieldOffset,
                                                       int mask)
        {
            byte *fieldPtr = (byte *) (structPtr + fieldOffset);
            return this.ReadImpl(fieldPtr, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual ushort LoadUShortStructFieldImpl(UIntPtr structPtr,
                                                           UIntPtr fieldOffset,
                                                           int mask)
        {
            ushort *fieldPtr = (ushort *) (structPtr + fieldOffset);
            return this.ReadImpl(fieldPtr, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual uint LoadUIntStructFieldImpl(UIntPtr structPtr,
                                                       UIntPtr fieldOffset,
                                                       int mask)
        {
            uint *fieldPtr = (uint *) (structPtr + fieldOffset);
            return this.ReadImpl(fieldPtr, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual ulong LoadULongStructFieldImpl(UIntPtr structPtr,
                                                         UIntPtr fieldOffset,
                                                         int mask)
        {
            ulong *fieldPtr = (ulong *) (structPtr + fieldOffset);
            return this.ReadImpl(fieldPtr, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        UIntPtr LoadUIntPtrStructFieldImpl(UIntPtr structPtr,
                                           UIntPtr fieldOffset,
                                           int mask)
        {
            UIntPtr *fieldPtr = (UIntPtr *) (structPtr + fieldOffset);
            return this.ReadImpl(fieldPtr, mask);
        }

        //////////////////// StoreVectorElementImpl ////////////////////

        [ForceInline]
        [NoBarriers]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected virtual void StoreVectorElementImpl(Array vector,
                                                      int index,
                                                      int arrayElementSize,
                                                      UIntPtr fieldOffset,
                                                      Object value,
                                                      int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(vector, offset, value, mask);

        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreVectorElementImpl(Array vector,
                                                      int index,
                                                      int arrayElementSize,
                                                      UIntPtr fieldOffset,
                                                      float value,
                                                      int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(vector, offset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreVectorElementImpl(Array vector,
                                                      int index,
                                                      int arrayElementSize,
                                                      UIntPtr fieldOffset,
                                                      double value,
                                                      int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(vector, offset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected virtual void StoreVectorElementImpl(Array vector,
                                                      int index,
                                                      int arrayElementSize,
                                                      UIntPtr fieldOffset,
                                                      byte value,
                                                      int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(vector, offset, value, mask);
        }

        [Inline]
        [AssertDevirtualize]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        protected virtual void StoreVectorElementImpl(Array vector,
                                                      int index,
                                                      int arrayElementSize,
                                                      UIntPtr fieldOffset,
                                                      ushort value,
                                                      int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(vector, offset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreVectorElementImpl(Array vector,
                                                      int index,
                                                      int arrayElementSize,
                                                      UIntPtr fieldOffset,
                                                      uint value,
                                                      int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(vector, offset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreVectorElementImpl(Array vector,
                                                      int index,
                                                      int arrayElementSize,
                                                      UIntPtr fieldOffset,
                                                      ulong value,
                                                      int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(vector, offset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreVectorElementImpl(Array vector,
                                                      int index,
                                                      int arrayElementSize,
                                                      UIntPtr fieldOffset,
                                                      UIntPtr value,
                                                      int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(vector, offset, value, mask);
        }

        //////////////////// LoadVectorElementImpl ////////////////////

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual Object LoadObjVectorElementImpl(Array vector,
                                                          int index,
                                                          int arrayElementSize,
                                                          UIntPtr fieldOffset,
                                                          int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadObjImpl(vector, offset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        float LoadFloatVectorElementImpl(Array vector,
                                         int index,
                                         int arrayElementSize,
                                         UIntPtr fieldOffset,
                                         int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadFloatImpl(vector, offset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        double LoadDoubleVectorElementImpl(Array vector,
                                           int index,
                                           int arrayElementSize,
                                           UIntPtr fieldOffset,
                                           int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadDoubleImpl(vector, offset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        byte LoadByteVectorElementImpl(Array vector,
                                       int index,
                                       int arrayElementSize,
                                       UIntPtr fieldOffset,
                                       int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadByteImpl(vector, offset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        ushort LoadUShortVectorElementImpl(Array vector,
                                           int index,
                                           int arrayElementSize,
                                           UIntPtr fieldOffset,
                                           int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadUShortImpl(vector, offset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        uint LoadUIntVectorElementImpl(Array vector,
                                       int index,
                                       int arrayElementSize,
                                       UIntPtr fieldOffset,
                                       int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadUIntImpl(vector, offset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        ulong LoadULongVectorElementImpl(Array vector,
                                         int index,
                                         int arrayElementSize,
                                         UIntPtr fieldOffset,
                                         int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadULongImpl(vector, offset, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        UIntPtr LoadUIntPtrVectorElementImpl(Array vector,
                                             int index,
                                             int arrayElementSize,
                                             UIntPtr fieldOffset,
                                             int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadUIntPtrImpl(vector, offset, mask);
        }

        //////////////////// StoreArrayElementImpl ////////////////////

        [ForceInline]
        [NoBarriers]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected virtual void StoreArrayElementImpl(Array array,
                                                     int index,
                                                     int arrayElementSize,
                                                     UIntPtr fieldOffset,
                                                     Object value,
                                                     int mask)
        {
            UIntPtr offset = IndexedFieldOffset(array, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(array, offset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreArrayElementImpl(Array array,
                                                     int index,
                                                     int arrayElementSize,
                                                     UIntPtr fieldOffset,
                                                     float value,
                                                     int mask)
        {
            UIntPtr offset = IndexedFieldOffset(array, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(array, offset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreArrayElementImpl(Array array,
                                                     int index,
                                                     int arrayElementSize,
                                                     UIntPtr fieldOffset,
                                                     double value,
                                                     int mask)
        {
            UIntPtr offset = IndexedFieldOffset(array, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(array, offset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreArrayElementImpl(Array array,
                                                     int index,
                                                     int arrayElementSize,
                                                     UIntPtr fieldOffset,
                                                     byte value,
                                                     int mask)
        {
            UIntPtr offset = IndexedFieldOffset(array, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(array, offset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreArrayElementImpl(Array array,
                                                     int index,
                                                     int arrayElementSize,
                                                     UIntPtr fieldOffset,
                                                     ushort value,
                                                     int mask)
        {
            UIntPtr offset = IndexedFieldOffset(array, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(array, offset, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreArrayElementImpl(Array array,
                                                     int index,
                                                     int arrayElementSize,
                                                     UIntPtr fieldOffset,
                                                     uint value,
                                                     int mask)
        {
            UIntPtr offset = IndexedFieldOffset(array, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(array, offset, value, mask);
        }

        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected virtual void StoreArrayElementImpl(Array array,
                                                     int index,
                                                     int arrayElementSize,
                                                     UIntPtr fieldOffset,
                                                     ulong value,
                                                     int mask)
        {
            UIntPtr offset = IndexedFieldOffset(array, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(array, offset, value, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual void StoreArrayElementImpl(Array array,
                                                     int index,
                                                     int arrayElementSize,
                                                     UIntPtr fieldOffset,
                                                     UIntPtr value,
                                                     int mask)
        {
            UIntPtr offset = IndexedFieldOffset(array, index,
                                                arrayElementSize, fieldOffset);
            this.WriteImpl(array, offset, value, mask);
        }

        //////////////////// LoadArrayElementImpl ////////////////////

        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected virtual Object LoadObjArrayElementImpl(Array vector,
                                                         int index,
                                                         int arrayElementSize,
                                                         UIntPtr fieldOffset,
                                                         int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadObjImpl(vector, offset, mask);
        }

        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected virtual
        float LoadFloatArrayElementImpl(Array vector,
                                        int index,
                                        int arrayElementSize,
                                        UIntPtr fieldOffset,
                                        int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadFloatImpl(vector, offset, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        double LoadDoubleArrayElementImpl(Array vector,
                                          int index,
                                          int arrayElementSize,
                                          UIntPtr fieldOffset,
                                          int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadDoubleImpl(vector, offset, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        byte LoadByteArrayElementImpl(Array vector,
                                      int index,
                                      int arrayElementSize,
                                      UIntPtr fieldOffset,
                                      int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadByteImpl(vector, offset, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        ushort LoadUShortArrayElementImpl(Array vector,
                                          int index,
                                          int arrayElementSize,
                                          UIntPtr fieldOffset,
                                          int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadUShortImpl(vector, offset, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        uint LoadUIntArrayElementImpl(Array vector,
                                      int index,
                                      int arrayElementSize,
                                      UIntPtr fieldOffset,
                                      int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadUIntImpl(vector, offset, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected virtual
        ulong LoadULongArrayElementImpl(Array vector,
                                        int index,
                                        int arrayElementSize,
                                        UIntPtr fieldOffset,
                                        int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadULongImpl(vector, offset, mask);
        }

        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected virtual
        UIntPtr LoadUIntPtrArrayElementImpl(Array vector,
                                            int index,
                                            int arrayElementSize,
                                            UIntPtr fieldOffset,
                                            int mask)
        {
            UIntPtr offset = IndexedFieldOffset(vector, index,
                                                arrayElementSize, fieldOffset);
            return this.ReadUIntPtrImpl(vector, offset, mask);
        }

        ////////////////// StoreStaticFieldImpl ///////////////////////

        [ForceInline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected virtual void StoreStaticFieldImpl(ref Object staticField,
                                                    Object value,
                                                    int mask)
        {
            this.WriteImplByRef(ref staticField, value, mask);
        }

        ////////////////// LoadStaticFieldImpl ///////////////////////

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual Object LoadStaticFieldImpl(ref Object staticField,
                                                     int mask)
        {
            return this.ReadImplByRef(ref staticField, mask);
        }

        ///////////////////////// AtomicSwapImpl ///////////////////////

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual Object AtomicSwapImpl(ref Object reference,
                                                Object value,
                                                int mask)
        {
            return Interlocked.Exchange(ref reference,value);
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual int AtomicSwapImpl(ref int reference,
                                             int value,
                                             int mask)
        {
            return Interlocked.Exchange(ref reference,value);
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual UIntPtr AtomicSwapImpl(ref UIntPtr reference,
                                                 UIntPtr value,
                                                 int mask)
        {
            return Interlocked.Exchange(ref reference,value);
        }

        ////////////////////// AtomicCompareAndSwapImpl ////////////////

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual Object
        AtomicCompareAndSwapImpl(ref Object reference,
                                 Object newValue,
                                 Object comparand,
                                 int mask)
        {
            return Interlocked.CompareExchange(ref reference,
                                               newValue,comparand);
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual int
        AtomicCompareAndSwapImpl(ref int reference,
                                 int newValue,
                                 int comparand,
                                 int mask)
        {
            return Interlocked.CompareExchange(ref reference,
                                               newValue, comparand);
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual long
        AtomicCompareAndSwapImpl(ref long reference,
                                 long newValue,
                                 long comparand,
                                 int mask)
        {
            return Interlocked.CompareExchange(ref reference,
                                               newValue, comparand);
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual UIntPtr
        AtomicCompareAndSwapImpl(ref UIntPtr reference,
                                 UIntPtr newValue,
                                 UIntPtr comparand,
                                 int mask)
        {
            return Interlocked.CompareExchange(ref reference,
                                               newValue, comparand);
        }

        /////////////////////////// ForwardImpl ///////////////////////

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual Object ForwardImpl(Object o,int mask)
        {
            return o;
        }

        /////////////////////////// MemoryBarrierImpl ///////////////////////

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual void MemoryBarrierImpl(int mask)
        {
#if !ARM && !ISA_ARM
            // HACK: MemoryBarrier is unimplemented in ARM
            // and causes compile-time failures when building
            // mscorlib in sepcomp mode. This change will break
            // CoCo if built with ARM.
            Thread.MemoryBarrier();
#endif
        }

        //////////////////////// PinImpl //////////////////////////////

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual UIntPtr PinImpl(UIntPtr address,
                                          int mask)
        {
            return address;
        }

        /////////////////////// InitObjectImpl ////////////////////////

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual void InitObjectImpl(Object o,VTable vtable)
        {
            MyInitObject(o, vtable);
        }

        [ForceInline]
        [NoBarriers]
        protected static void BootstrapInitObjectImpl(Object o, VTable vtable)
        {
            MyInitObject(o, vtable);
        }

        [ForceInline]
        [NoBarriers]
        private static void MyInitObject(Object o, VTable vtable)
        {
            o.vtable = vtable;
        }

        ///////////////////////// Weak Ref ////////////////////////////

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual Object WeakRefReadImpl(UIntPtr addr, int mask)
        {
            return Magic.fromAddress(addr);
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual UIntPtr WeakRefWriteImpl(Object obj, int mask)
        {
            return Magic.addressOf(obj);
        }

        //////////////////////////// EqImpl ///////////////////////////

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual bool EqImpl(Object a,Object b, int mask)
        {
            return a==b;
        }

        ////////////////////////// fast path selection ////////////////

        [ForceInline]
        [AssertDevirtualize]
        protected virtual bool AllowFastPathImpl()
        {
            return false;
        }

        ///////////////////////// CopyStructImpl ///////////////////////

        [AssertDevirtualize]
        [Inline]
        protected virtual void CopyStructImpl(Object srcObj,
                                              Object dstObj,
                                              VTable vtable,
                                              UIntPtr srcPtr,
                                              UIntPtr dstPtr)
        {
            CopyStructWithBarrier(vtable, srcPtr, dstPtr);
        }

        ////////////////////////// CloneImpl //////////////////////////

        [AssertDevirtualize]
        [Inline]
        protected virtual void CloneImpl(Object srcObject, Object dstObject)
        {
            CloneWithBarrier(srcObject, dstObject);
        }

        /////////////////////// ArrayZeroImpl /////////////////////////

        // 'offset' is not relative to the lower bound, but is a count
        // of elements from the first element in the array.
        [AssertDevirtualize]
        [Inline]
        protected virtual void ArrayZeroImpl(Array array,
                                             int offset,
                                             int length)
        {
            ArrayZeroWithBarrier(array, offset, length);
        }

        /////////////////////// ArrayCopyImpl /////////////////////////

        // 'offset' is not relative to the lower bound, but is a count
        // of elements from the first element in the array.
        [AssertDevirtualize]
        [Inline]
        protected virtual void ArrayCopyImpl(Array srcArray, int srcOffset,
                                             Array dstArray, int dstOffset,
                                             int length)
        {
            ArrayCopyWithBarrier(srcArray, srcOffset,
                                 dstArray, dstOffset,
                                 length);
        }

        ///////////////////// WriteImpl to ptr //////////////////////

        [AssertDevirtualize]
        [ForceInline]
        protected virtual void WriteImpl(UIntPtr *location,
                                         Object value,
                                         int mask)
        {
            *location = Magic.addressOf(value);
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual void WriteImpl(float *location,
                                         float value,
                                         int mask)
        {
            *location = value;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual void WriteImpl(double *location,
                                         double value,
                                         int mask)
        {
            *location = value;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual void WriteImpl(byte *location,
                                         byte value,
                                         int mask)
        {
            *location = value;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual void WriteImpl(ushort *location,
                                         ushort value,
                                         int mask)
        {
            *location = value;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual void WriteImpl(uint *location,
                                         uint value,
                                         int mask)
        {
            *location = value;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual void WriteImpl(ulong *location,
                                         ulong value,
                                         int mask)
        {
            *location = value;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual void WriteImpl(UIntPtr *location,
                                         UIntPtr value,
                                         int mask)
        {
            *location = value;
        }

        ////////////////////// WriteImpl to Object, pointer /////////////////

        [AssertDevirtualize]
        [ForceInline]
        protected virtual void WriteImpl(Object o,
                                         UIntPtr *ptr,
                                         Object value,
                                         int mask)
        {
            this.WriteImpl(ptr, value, mask);
        }

        [AssertDevirtualize]
        [Inline]
        protected virtual void WriteImpl(Object o,
                                         float *ptr,
                                         float value,
                                         int mask)
        {
            this.WriteImpl(ptr, value, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         double *ptr,
                                         double value,
                                         int mask)
        {
            this.WriteImpl(ptr, value, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         byte *ptr,
                                         byte value,
                                         int mask)
        {
            this.WriteImpl(ptr, value, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         ushort *ptr,
                                         ushort value,
                                         int mask)
        {
            this.WriteImpl(ptr, value, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         uint *ptr,
                                         uint value,
                                         int mask)
        {
            this.WriteImpl(ptr, value, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         ulong *ptr,
                                         ulong value,
                                         int mask)
        {
            this.WriteImpl(ptr, value, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         UIntPtr *ptr,
                                         UIntPtr value,
                                         int mask)
        {
            this.WriteImpl(ptr, value, mask);
        }

        ///////////////////// WriteImpl to Object+offset //////////////////////

        [ForceInline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         UIntPtr offset,
                                         Object value,
                                         int mask)
        {
            this.WriteImpl(o,
                           (UIntPtr*)(Magic.addressOf(o)+offset),
                           value,
                           mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         UIntPtr offset,
                                         float value,
                                         int mask)
        {
            this.WriteImpl(o,
                           (float*)(Magic.addressOf(o)+offset),
                           value,
                           mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         UIntPtr offset,
                                         double value,
                                         int mask)
        {
            this.WriteImpl(o,
                           (double*)(Magic.addressOf(o)+offset),
                           value,
                           mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         UIntPtr offset,
                                         byte value,
                                         int mask)
        {
            this.WriteImpl(o,
                           (byte*)(Magic.addressOf(o)+offset),
                           value,
                           mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         UIntPtr offset,
                                         ushort value,
                                         int mask)
        {
            this.WriteImpl(o,
                           (ushort*)(Magic.addressOf(o)+offset),
                           value,
                           mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         UIntPtr offset,
                                         uint value,
                                         int mask)
        {
            this.WriteImpl(o,
                           (uint*)(Magic.addressOf(o)+offset),
                           value,
                           mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         UIntPtr offset,
                                         ulong value,
                                         int mask)
        {
            this.WriteImpl(o,
                           (ulong*)(Magic.addressOf(o)+offset),
                           value,
                           mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual void WriteImpl(Object o,
                                         UIntPtr offset,
                                         UIntPtr value,
                                         int mask)
        {
            this.WriteImpl(o,
                           (UIntPtr*)(Magic.addressOf(o)+offset),
                           value,
                           mask);
        }

        ///////////////////// WriteImpl to ref //////////////////////

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual void WriteImplByRef(ref Object location,
                                              Object value,
                                              int mask)
        {
            location = value;
        }

        [AssertDevirtualize]
        [NoBarriers]
        [ForceInline]
        protected virtual void WriteImplByRef(ref float location,
                                              float value,
                                              int mask)
        {
            location = value;
        }

        [AssertDevirtualize]
        [NoBarriers]
        [ForceInline]
        protected virtual void WriteImplByRef(ref double location,
                                              double value,
                                              int mask)
        {
            location = value;
        }

        [AssertDevirtualize]
        [NoBarriers]
        [ForceInline]
        protected virtual void WriteImplByRef(ref byte location,
                                              byte value,
                                              int mask)
        {
            location = value;
        }

        [AssertDevirtualize]
        [NoBarriers]
        [ForceInline]
        protected virtual void WriteImplByRef(ref ushort location,
                                              ushort value,
                                              int mask)
        {
            location = value;
        }

        [AssertDevirtualize]
        [NoBarriers]
        [ForceInline]
        protected virtual void WriteImplByRef(ref uint location,
                                              uint value,
                                              int mask)
        {
            location = value;
        }

        [AssertDevirtualize]
        [NoBarriers]
        [ForceInline]
        protected virtual void WriteImplByRef(ref ulong location,
                                              ulong value,
                                              int mask)
        {
            location = value;
        }

        [AssertDevirtualize]
        [NoBarriers]
        [ForceInline]
        protected virtual void WriteImplByRef(ref UIntPtr location,
                                              UIntPtr value,
                                              int mask)
        {
            location = value;
        }

        ///////////////////// ReadImpl from ptr //////////////////////

        [AssertDevirtualize]
        [ForceInline]
        protected virtual Object ReadObjImpl(UIntPtr *location,
                                             int mask)
        {
            return Magic.fromAddress(*location);
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual float ReadImpl(float *location,
                                         int mask)
        {
            return *location;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual double ReadImpl(double *location,
                                          int mask)
        {
            return *location;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual byte ReadImpl(byte *location,
                                        int mask)
        {
            return *location;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual ushort ReadImpl(ushort *location,
                                          int mask)
        {
            return *location;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual uint ReadImpl(uint *location,
                                        int mask)
        {
            return *location;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual ulong ReadImpl(ulong *location,
                                         int mask)
        {
            return *location;
        }

        [AssertDevirtualize]
        [ForceInline]
        protected virtual UIntPtr ReadImpl(UIntPtr *location,
                                           int mask)
        {
            return *location;
        }

        ///////////////////// ReadImpl from Object, ptr ///////////////////

        [Inline]
        [AssertDevirtualize]
        protected virtual Object ReadObjImpl(Object o,
                                             UIntPtr *ptr,
                                             int mask)
        {
            return this.ReadObjImpl(ptr, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual float ReadImpl(Object o,
                                         float *ptr,
                                         int mask)
        {
            return this.ReadImpl(ptr, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual double ReadImpl(Object o,
                                          double *ptr,
                                          int mask)
        {
            return this.ReadImpl(ptr, mask);
        }

        [AssertDevirtualize]
        [Inline]
        protected virtual byte ReadImpl(Object o,
                                        byte *ptr,
                                        int mask)
        {
            return this.ReadImpl(ptr, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual ushort ReadImpl(Object o,
                                          ushort *ptr,
                                          int mask)
        {
            return this.ReadImpl(ptr, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual uint ReadImpl(Object o,
                                        uint *ptr,
                                        int mask)
        {
            return this.ReadImpl(ptr, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual ulong ReadImpl(Object o,
                                         ulong *ptr,
                                         int mask)
        {
            return this.ReadImpl(ptr, mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual UIntPtr ReadImpl(Object o,
                                           UIntPtr *ptr,
                                           int mask)
        {
            return this.ReadImpl(ptr, mask);
        }

        ///////////////////// ReadImpl from Object+off //////////////////////

        [Inline]
        [AssertDevirtualize]
        protected virtual Object ReadObjImpl(Object o,
                                             UIntPtr offset,
                                             int mask)
        {
            return this.ReadObjImpl(o,
                                    (UIntPtr*)(Magic.addressOf(o)+offset),
                                    mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual float ReadFloatImpl(Object o,
                                              UIntPtr offset,
                                              int mask)
        {
            return this.ReadImpl(o,
                                 (float*)(Magic.addressOf(o)+offset),
                                 mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual double ReadDoubleImpl(Object o,
                                                UIntPtr offset,
                                                int mask)
        {
            return this.ReadImpl(o,
                                 (double*)(Magic.addressOf(o)+offset),
                                 mask);
        }

        [AssertDevirtualize]
        [Inline]
        protected virtual byte ReadByteImpl(Object o,
                                            UIntPtr offset,
                                            int mask)
        {
            return this.ReadImpl(o,
                                 (byte*)(Magic.addressOf(o)+offset),
                                 mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual ushort ReadUShortImpl(Object o,
                                                UIntPtr offset,
                                                int mask)
        {
            return this.ReadImpl(o,
                                 (ushort*)(Magic.addressOf(o)+offset),
                                 mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual uint ReadUIntImpl(Object o,
                                            UIntPtr offset,
                                            int mask)
        {
            return this.ReadImpl(o,
                                 (uint*)(Magic.addressOf(o)+offset),
                                 mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual ulong ReadULongImpl(Object o,
                                              UIntPtr offset,
                                              int mask)
        {
            return this.ReadImpl(o,
                                 (ulong*)(Magic.addressOf(o)+offset),
                                 mask);
        }

        [Inline]
        [AssertDevirtualize]
        protected virtual UIntPtr ReadUIntPtrImpl(Object o,
                                                  UIntPtr offset,
                                                  int mask)
        {
            return this.ReadImpl(o,
                                 (UIntPtr*)(Magic.addressOf(o)+offset),
                                 mask);
        }

        ///////////////////// ReadImpl from ref //////////////////////

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual Object ReadImplByRef(ref Object location,
                                               int mask)
        {
            return location;
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual float ReadImplByRef(ref float location,
                                              int mask)
        {
            return location;
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual double ReadImplByRef(ref double location,
                                               int mask)
        {
            return location;
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual byte ReadImplByRef(ref byte location,
                                             int mask)
        {
            return location;
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual ushort ReadImplByRef(ref ushort location,
                                               int mask)
        {
            return location;
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual uint ReadImplByRef(ref uint location,
                                             int mask)
        {
            return location;
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual ulong ReadImplByRef(ref ulong location,
                                              int mask)
        {
            return location;
        }

        [AssertDevirtualize]
        [ForceInline]
        [NoBarriers]
        protected virtual UIntPtr ReadImplByRef(ref UIntPtr location,
                                                int mask)
        {
            return location;
        }

        /////////////////////// Helpers... //////////////////////////////

        [ForceInline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected static UIntPtr IndexedDataPtr(Array array) {
            return (UIntPtr) (Magic.addressOf(array) +
                              (array.vtable.baseLength-(uint)PreHeader.Size));
        }

        [ForceInline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected static UIntPtr IndexedFieldOffset(Array array,
                                                    int index,
                                                    int arrayElementSize,
                                                    UIntPtr fieldOffset)
        {
            return ((UIntPtr)(uint)index * (UIntPtr)(uint)arrayElementSize
                    + array.vtable.baseLength
                    + fieldOffset
                    - (UIntPtr)(uint)PreHeader.Size);
        }

        [ForceInline]
        [AssertDevirtualize]
        protected static UIntPtr IndexedElementOffset(Array array,
                                                      int index)
        {
            return (UIntPtr)(uint)index * (UIntPtr)(uint)array.vtable.arrayElementSize
                 + array.vtable.baseLength
                 - (UIntPtr)(uint)PreHeader.Size;
        }

        // copies a span of primitives from one object to another invoking
        // word-size read and write barriers along the way.
        // mostly useful as part of a greater implementation of struct,
        // object, or array copy in a GC that requires primitive barriers.
        // note that dstOff, srcOff, and nBytes must be word-aligned.
        // call this with great care.
        [Inline]
        protected static void MemCopyBarrierSlow(Object dst,
                                                 UIntPtr dstOff,
                                                 Object src,
                                                 UIntPtr srcOff,
                                                 UIntPtr nBytes) {
            for (;nBytes>0;nBytes-=sizeof(UIntPtr)) {
                installedBarrier
                    .WriteImpl(dst,dstOff,
                               installedBarrier.ReadUIntPtrImpl(src,srcOff,0),0);
                dstOff+=sizeof(UIntPtr);
                srcOff+=sizeof(UIntPtr);
            }
        }

        // Same as above but without knowledge of the object base.
        [Inline]
        protected static void MemCopyBarrierSlow(UIntPtr *dstPtr,
                                                 UIntPtr *srcPtr,
                                                 UIntPtr nBytes) {
            for (;nBytes>0;nBytes-=sizeof(UIntPtr)) {
                installedBarrier
                    .WriteImpl(dstPtr,installedBarrier.ReadImpl(srcPtr,0),0);
                dstPtr++;
                srcPtr++;
            }
        }

        // Really slow way of zeroing memory while invoking write
        // barriers.  Assumes that everything is word-aligned.
        [Inline]
        protected static void MemZeroBarrierSlow(Object dst,
                                                 UIntPtr dstOff,
                                                 UIntPtr nBytes) {
            for (;nBytes>0;nBytes-=sizeof(UIntPtr)) {
                installedBarrier.WriteImpl(dst,dstOff,UIntPtr.Zero,0);
                dstOff+=sizeof(UIntPtr);
            }
        }

        // Really slow way of zeroing memory while invoking write
        // barriers.  Assumes that everything is word-aligned.
        [Inline]
        protected static void MemZeroBarrierSlow(UIntPtr *dstPtr,
                                                 UIntPtr nBytes) {
            for (;nBytes>0;nBytes-=sizeof(UIntPtr)) {
                installedBarrier.WriteImpl(dstPtr,UIntPtr.Zero,0);
                dstPtr++;
            }
        }

        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected void CopyStructNoBarrier(VTable vtable,
                                           UIntPtr srcPtr,
                                           UIntPtr dstPtr)
        {
            int preHeaderSize = PreHeader.Size;
            int postHeaderSize = PostHeader.Size;
            int structSize = ((int) ObjectLayout.ObjectSize(vtable) -
                              (preHeaderSize + postHeaderSize));
            Buffer.MoveMemory((byte *) dstPtr, (byte *) srcPtr, structSize);
        }

        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected void CopyStructWithBarrier(VTable vtable,
                                             UIntPtr srcPtr,
                                             UIntPtr dstPtr)
        {
            copyFieldsVisitor.VisitReferenceFields(vtable, srcPtr, dstPtr);
        }

        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected void CopyStructWithSlowBarrier(Object srcObj,
                                                 Object dstObj,
                                                 VTable vtable,
                                                 UIntPtr srcOff,
                                                 UIntPtr dstOff)
        {
            slowCopyFieldsVisitor.VisitReferenceFields(vtable,
                                                       srcObj, dstObj,
                                                       srcOff, dstOff);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected void CloneNoBarrier(Object srcObject,
                                      Object dstObject)
        {
            UIntPtr objectSize = System.GCs.ObjectLayout.Sizeof(srcObject);
            int preHeaderSize = PreHeader.Size;
            int postHeaderSize = PostHeader.Size;
            // We don't copy any of the header fields.
            Util.MemCopy(Magic.addressOf(dstObject) + postHeaderSize,
                         Magic.addressOf(srcObject) + postHeaderSize,
                         objectSize - preHeaderSize - postHeaderSize);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected void CloneWithBarrier(Object srcObject,
                                        Object dstObject)
        {
            copyFieldsVisitor.VisitReferenceFields(srcObject, dstObject);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        [AssertDevirtualize]
        protected void CloneWithSlowBarrier(Object srcObject,
                                        Object dstObject)
        {
            slowCopyFieldsVisitor.VisitReferenceFields(srcObject, dstObject);
        }

        // 'offset' is not relative to the lower bound, but is a count
        // of elements from the first element in the array.
        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected void ArrayZeroNoBarrier(Array array, int offset,
                                          int length)
        {
            UIntPtr dataPtr = IndexedDataPtr(array);
            int elementSize = array.vtable.arrayElementSize;
            Buffer.ZeroMemory((byte *)dataPtr + offset * elementSize,
                              length * elementSize);
        }

        // 'offset' is not relative to the lower bound, but is a count
        // of elements from the first element in the array.
        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected void ArrayZeroWithBarrier(Array array, int offset,
                                            int length)
        {
            UIntPtr dataPtr = IndexedDataPtr(array);
            int elementSize = array.vtable.arrayElementSize;
            UIntPtr startAddr = dataPtr + offset * elementSize;
            zeroFieldsVisitor.VisitReferenceFields(array.vtable,
                                                   startAddr, length);
        }

        // 'offset' is not relative to the lower bound, but is a count
        // of elements from the first element in the array.
        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected void ArrayZeroWithSlowBarrier(Array array, int offset,
                                                int length)
        {
            slowZeroFieldsVisitor
                .VisitReferenceFields(array,
                                      IndexedElementOffset(array,offset),
                                      length);
        }

        // 'offset' is not relative to the lower bound, but is a count
        // of elements from the first element in the array.
        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected void ArrayCopyNoBarrier(Array srcArray, int srcOffset,
                                          Array dstArray, int dstOffset,
                                          int length)
        {
            UIntPtr srcDataAddr = IndexedDataPtr(srcArray);
            UIntPtr dstDataAddr = IndexedDataPtr(dstArray);
            int elementSize = srcArray.vtable.arrayElementSize;
            VTable.Assert(elementSize ==
                          dstArray.vtable.arrayElementSize);
            Buffer.MoveMemory((byte *) (dstDataAddr + dstOffset * elementSize),
                              (byte *) (srcDataAddr + srcOffset * elementSize),
                              length * elementSize);
        }

        // 'offset' is not relative to the lower bound, but is a count
        // of elements from the first element in the array.
        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected void ArrayCopyWithBarrier(Array srcArray, int srcOffset,
                                            Array dstArray, int dstOffset,
                                            int length)
        {
            UIntPtr srcDataAddr = IndexedDataPtr(srcArray);
            UIntPtr dstDataAddr = IndexedDataPtr(dstArray);
            int elementSize = srcArray.vtable.arrayElementSize;
            VTable.Assert(elementSize == dstArray.vtable.arrayElementSize);
            UIntPtr srcStartAddr = srcDataAddr + srcOffset * elementSize;
            UIntPtr dstStartAddr = dstDataAddr + dstOffset * elementSize;
            copyFieldsVisitor.VisitReferenceFields(srcArray.vtable,
                                                   srcStartAddr,
                                                   dstStartAddr,
                                                   length);
        }

        // 'offset' is not relative to the lower bound, but is a count
        // of elements from the first element in the array.
        [Inline]
        [AssertDevirtualize]
        [NoStackLinkCheckTrans]
        protected void ArrayCopyWithSlowBarrier(Array srcArray, int srcOffset,
                                                Array dstArray, int dstOffset,
                                                int length)
        {
            VTable.Assert(srcArray.vtable.arrayElementSize
                          == dstArray.vtable.arrayElementSize);
            slowCopyFieldsVisitor
                .VisitReferenceFields(srcArray.vtable,
                                      srcArray,
                                      dstArray,
                                      IndexedElementOffset(srcArray,
                                                           srcOffset),
                                      IndexedElementOffset(dstArray,
                                                           dstOffset),
                                      length);
        }

        ////////////////////// StoreIndirect to pointer ///////////////////
        // this isn't called by the compiler

        [ForceInline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirect(UIntPtr *location,
                                           Object value,
                                           int mask)
        {
            installedBarrier.StoreIndirectImpl(location, value, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirect(float *location,
                                           float value,
                                           int mask)
        {
            installedBarrier.StoreIndirectImpl(location, value, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirect(double *location,
                                           double value,
                                           int mask)
        {
            installedBarrier.StoreIndirectImpl(location, value, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirect(byte *location,
                                           byte value,
                                           int mask)
        {
            installedBarrier.StoreIndirectImpl(location, value, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirect(ushort *location,
                                           ushort value,
                                           int mask)
        {
            installedBarrier.StoreIndirectImpl(location, value, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirect(uint *location,
                                           uint value,
                                           int mask)
        {
            installedBarrier.StoreIndirectImpl(location, value, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirect(ulong *location,
                                           ulong value,
                                           int mask)
        {
            installedBarrier.StoreIndirectImpl(location, value, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirect(UIntPtr *location,
                                           UIntPtr value,
                                           int mask)
        {
            installedBarrier.StoreIndirectImpl(location, value, mask);
        }

        //////////////////// StoreIndirect to ref /////////////////////////

        [RequiredByBartok]
        [ForceInline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirectByRef(ref Object reference,
                                                Object value,
                                                int mask)
        {
            installedBarrier.StoreIndirectImplByRef(ref reference,
                                                    value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirectByRef(ref float reference,
                                                float value,
                                                int mask)
        {
            installedBarrier.StoreIndirectImplByRef(ref reference,
                                                    value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirectByRef(ref double reference,
                                                double value,
                                                int mask)
        {
            installedBarrier.StoreIndirectImplByRef(ref reference,
                                                    value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirectByRef(ref byte reference,
                                                byte value,
                                                int mask)
        {
            installedBarrier.StoreIndirectImplByRef(ref reference,
                                                    value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirectByRef(ref ushort reference,
                                                ushort value,
                                                int mask)
        {
            installedBarrier.StoreIndirectImplByRef(ref reference,
                                                    value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirectByRef(ref uint reference,
                                                uint value,
                                                int mask)
        {
            installedBarrier.StoreIndirectImplByRef(ref reference,
                                                    value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirectByRef(ref ulong reference,
                                                ulong value,
                                                int mask)
        {
            installedBarrier.StoreIndirectImplByRef(ref reference,
                                                    value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreIndirectByRef(ref UIntPtr reference,
                                                UIntPtr value,
                                                int mask)
        {
            installedBarrier.StoreIndirectImplByRef(ref reference,
                                                    value, mask);
        }

        //////////////////// LoadIndirect from ptr /////////////////////////

        [Inline]
        [NoStackLinkCheckTrans]
        internal static Object LoadObjIndirect(UIntPtr *reference,
                                               int mask)
        {
            return installedBarrier.LoadObjIndirectImpl(reference, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static float LoadIndirect(float* reference,
                                           int mask)
        {
            return installedBarrier.LoadIndirectImpl(reference, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static double LoadIndirect(double* reference,
                                            int mask)
        {
            return installedBarrier.LoadIndirectImpl(reference, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static byte LoadIndirect(byte* reference,
                                          int mask)
        {
            return installedBarrier.LoadIndirectImpl(reference, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static ushort LoadIndirect(ushort* reference,
                                            int mask)
        {
            return installedBarrier.LoadIndirectImpl(reference, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static uint LoadIndirect(uint* reference,
                                          int mask)
        {
            return installedBarrier.LoadIndirectImpl(reference, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static ulong LoadIndirect(ulong* reference,
                                           int mask)
        {
            return installedBarrier.LoadIndirectImpl(reference, mask);
        }

        [Inline]
        [NoStackLinkCheckTrans]
        internal static UIntPtr LoadIndirect(UIntPtr* reference,
                                             int mask)
        {
            return installedBarrier.LoadIndirectImpl(reference, mask);
        }

        //////////////////// LoadIndirect from ref /////////////////////////

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static Object LoadIndirectByRef(ref Object reference,
                                                 int mask)
        {
            return installedBarrier.LoadIndirectImplByRef(ref reference, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static float LoadIndirectByRef(ref float reference,
                                                int mask)
        {
            return installedBarrier.LoadIndirectImplByRef(ref reference, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static double LoadIndirectByRef(ref double reference,
                                                 int mask)
        {
            return installedBarrier.LoadIndirectImplByRef(ref reference, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static byte LoadIndirectByRef(ref byte reference,
                                               int mask)
        {
            return installedBarrier.LoadIndirectImplByRef(ref reference, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static ushort LoadIndirectByRef(ref ushort reference,
                                                 int mask)
        {
            return installedBarrier.LoadIndirectImplByRef(ref reference, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static uint LoadIndirectByRef(ref uint reference,
                                               int mask)
        {
            return installedBarrier.LoadIndirectImplByRef(ref reference, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static ulong LoadIndirectByRef(ref ulong reference,
                                                int mask)
        {
            return installedBarrier.LoadIndirectImplByRef(ref reference, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static UIntPtr LoadIndirectByRef(ref UIntPtr reference,
                                                  int mask)
        {
            return installedBarrier.LoadIndirectImplByRef(ref reference, mask);
        }

        ///////////////////// StoreObjectField /////////////////////////

        [RequiredByBartok]
        [ForceInline]
        [NoStackLinkCheckTrans]
        internal static void StoreObjectField(Object obj,
                                              UIntPtr fieldOffset,
                                              Object value,
                                              int mask)
        {
            installedBarrier.StoreObjectFieldImpl(obj, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreObjectField(Object obj,
                                              UIntPtr fieldOffset,
                                              float value,
                                              int mask)
        {
            installedBarrier.StoreObjectFieldImpl(obj, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreObjectField(Object obj,
                                              UIntPtr fieldOffset,
                                              double value,
                                              int mask)
        {
            installedBarrier.StoreObjectFieldImpl(obj, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreObjectField(Object obj,
                                              UIntPtr fieldOffset,
                                              byte value,
                                              int mask)
        {
            installedBarrier.StoreObjectFieldImpl(obj, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreObjectField(Object obj,
                                              UIntPtr fieldOffset,
                                              ushort value,
                                              int mask)
        {
            installedBarrier.StoreObjectFieldImpl(obj, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreObjectField(Object obj,
                                              UIntPtr fieldOffset,
                                              uint value,
                                              int mask)
        {
            installedBarrier.StoreObjectFieldImpl(obj, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreObjectField(Object obj,
                                              UIntPtr fieldOffset,
                                              ulong value,
                                              int mask)
        {
            installedBarrier.StoreObjectFieldImpl(obj, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreObjectField(Object obj,
                                              UIntPtr fieldOffset,
                                              UIntPtr value,
                                              int mask)
        {
            installedBarrier.StoreObjectFieldImpl(obj, fieldOffset,
                                                  value, mask);
        }

        ///////////////////// LoadObjectField /////////////////////////

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static Object LoadObjObjectField(Object obj,
                                                  UIntPtr fieldOffset,
                                                  int mask)
        {
            return installedBarrier.LoadObjObjectFieldImpl(obj,
                                                           fieldOffset,
                                                           mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static float LoadFloatObjectField(Object obj,
                                                   UIntPtr fieldOffset,
                                                   int mask)
        {
            return installedBarrier.LoadFloatObjectFieldImpl(obj,
                                                             fieldOffset,
                                                             mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static double LoadDoubleObjectField(Object obj,
                                                     UIntPtr fieldOffset,
                                                     int mask)
        {
            return installedBarrier.LoadDoubleObjectFieldImpl(obj,
                                                              fieldOffset,
                                                              mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static byte LoadByteObjectField(Object obj,
                                                 UIntPtr fieldOffset,
                                                 int mask)
        {
            return installedBarrier.LoadByteObjectFieldImpl(obj,
                                                            fieldOffset,
                                                            mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static ushort LoadUShortObjectField(Object obj,
                                                     UIntPtr fieldOffset,
                                                     int mask)
        {
            return installedBarrier.LoadUShortObjectFieldImpl(obj,
                                                              fieldOffset,
                                                              mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static uint LoadUIntObjectField(Object obj,
                                                 UIntPtr fieldOffset,
                                                 int mask)
        {
            return installedBarrier.LoadUIntObjectFieldImpl(obj,
                                                            fieldOffset,
                                                            mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static ulong LoadULongObjectField(Object obj,
                                                   UIntPtr fieldOffset,
                                                   int mask)
        {
            return installedBarrier.LoadULongObjectFieldImpl(obj,
                                                             fieldOffset,
                                                             mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static UIntPtr LoadUIntPtrObjectField(Object obj,
                                                       UIntPtr fieldOffset,
                                                       int mask)
        {
            return installedBarrier.LoadUIntPtrObjectFieldImpl(obj,
                                                               fieldOffset,
                                                               mask);
        }

        ///////////////////// StoreStructField ////////////////////////
        // what does this mean for CoCo?
        // find base obj pointer.  if there is none then
        // ignore.  if there is then delegate to StoreObjectField

        [RequiredByBartok]
        [ForceInline]
        [NoStackLinkCheckTrans]
        internal static void StoreStructField(UIntPtr structPtr,
                                              UIntPtr fieldOffset,
                                              Object value,
                                              int mask)
        {
            installedBarrier.StoreStructFieldImpl(structPtr, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreStructField(UIntPtr structPtr,
                                              UIntPtr fieldOffset,
                                              float value,
                                              int mask)
        {
            installedBarrier.StoreStructFieldImpl(structPtr, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreStructField(UIntPtr structPtr,
                                              UIntPtr fieldOffset,
                                              double value,
                                              int mask)
        {
            installedBarrier.StoreStructFieldImpl(structPtr, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreStructField(UIntPtr structPtr,
                                              UIntPtr fieldOffset,
                                              byte value,
                                              int mask)
        {
            installedBarrier.StoreStructFieldImpl(structPtr, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreStructField(UIntPtr structPtr,
                                              UIntPtr fieldOffset,
                                              ushort value,
                                              int mask)
        {
            installedBarrier.StoreStructFieldImpl(structPtr, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreStructField(UIntPtr structPtr,
                                              UIntPtr fieldOffset,
                                              uint value,
                                              int mask)
        {
            installedBarrier.StoreStructFieldImpl(structPtr, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreStructField(UIntPtr structPtr,
                                              UIntPtr fieldOffset,
                                              ulong value,
                                              int mask)
        {
            installedBarrier.StoreStructFieldImpl(structPtr, fieldOffset,
                                                  value, mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreStructField(UIntPtr structPtr,
                                              UIntPtr fieldOffset,
                                              UIntPtr value,
                                              int mask)
        {
            installedBarrier.StoreStructFieldImpl(structPtr, fieldOffset,
                                                  value, mask);
        }

        ///////////////////// LoadStructField ////////////////////////

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static Object LoadObjStructField(UIntPtr obj,
                                                  UIntPtr fieldOffset,
                                                  int mask)
        {
            return installedBarrier.LoadObjStructFieldImpl(obj,
                                                           fieldOffset,
                                                           mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static float LoadFloatStructField(UIntPtr obj,
                                                   UIntPtr fieldOffset,
                                                   int mask)
        {
            return installedBarrier.LoadFloatStructFieldImpl(obj,
                                                             fieldOffset,
                                                             mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static double LoadDoubleStructField(UIntPtr obj,
                                                     UIntPtr fieldOffset,
                                                     int mask)
        {
            return installedBarrier.LoadDoubleStructFieldImpl(obj,
                                                              fieldOffset,
                                                              mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static byte LoadByteStructField(UIntPtr obj,
                                                 UIntPtr fieldOffset,
                                                 int mask)
        {
            return installedBarrier.LoadByteStructFieldImpl(obj,
                                                            fieldOffset,
                                                            mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static ushort LoadUShortStructField(UIntPtr obj,
                                                     UIntPtr fieldOffset,
                                                     int mask)
        {
            return installedBarrier.LoadUShortStructFieldImpl(obj,
                                                              fieldOffset,
                                                              mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static uint LoadUIntStructField(UIntPtr obj,
                                                 UIntPtr fieldOffset,
                                                 int mask)
        {
            return installedBarrier.LoadUIntStructFieldImpl(obj,
                                                            fieldOffset,
                                                            mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static ulong LoadULongStructField(UIntPtr obj,
                                                   UIntPtr fieldOffset,
                                                   int mask)
        {
            return installedBarrier.LoadULongStructFieldImpl(obj,
                                                             fieldOffset,
                                                             mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static UIntPtr LoadUIntPtrStructField(UIntPtr obj,
                                                       UIntPtr fieldOffset,
                                                       int mask)
        {
            return installedBarrier.LoadUIntPtrStructFieldImpl(obj,
                                                               fieldOffset,
                                                               mask);
        }

        ////////////////////// StoreVectorElement ////////////////////

        [RequiredByBartok]
        [ForceInline]
        [NoStackLinkCheckTrans]
        internal static void StoreVectorElement(Array vector,
                                                int index,
                                                int arrayElementSize,
                                                UIntPtr fieldOffset,
                                                Object value,
                                                int mask)
        {
            installedBarrier.StoreVectorElementImpl(vector,
                                                    index,
                                                    arrayElementSize,
                                                    fieldOffset,
                                                    value,
                                                    mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreVectorElement(Array vector,
                                                int index,
                                                int arrayElementSize,
                                                UIntPtr fieldOffset,
                                                float value,
                                                int mask)
        {
            installedBarrier.StoreVectorElementImpl(vector,
                                                    index,
                                                    arrayElementSize,
                                                    fieldOffset,
                                                    value,
                                                    mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreVectorElement(Array vector,
                                                int index,
                                                int arrayElementSize,
                                                UIntPtr fieldOffset,
                                                double value,
                                                int mask)
        {
            installedBarrier.StoreVectorElementImpl(vector,
                                                    index,
                                                    arrayElementSize,
                                                    fieldOffset,
                                                    value,
                                                    mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreVectorElement(Array vector,
                                                int index,
                                                int arrayElementSize,
                                                UIntPtr fieldOffset,
                                                byte value,
                                                int mask)
        {
            installedBarrier.StoreVectorElementImpl(vector,
                                                    index,
                                                    arrayElementSize,
                                                    fieldOffset,
                                                    value,
                                                    mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreVectorElement(Array vector,
                                                int index,
                                                int arrayElementSize,
                                                UIntPtr fieldOffset,
                                                ushort value,
                                                int mask)
        {
            installedBarrier.StoreVectorElementImpl(vector,
                                                    index,
                                                    arrayElementSize,
                                                    fieldOffset,
                                                    value,
                                                    mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreVectorElement(Array vector,
                                                int index,
                                                int arrayElementSize,
                                                UIntPtr fieldOffset,
                                                uint value,
                                                int mask)
        {
            installedBarrier.StoreVectorElementImpl(vector,
                                                    index,
                                                    arrayElementSize,
                                                    fieldOffset,
                                                    value,
                                                    mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreVectorElement(Array vector,
                                                int index,
                                                int arrayElementSize,
                                                UIntPtr fieldOffset,
                                                ulong value,
                                                int mask)
        {
            installedBarrier.StoreVectorElementImpl(vector,
                                                    index,
                                                    arrayElementSize,
                                                    fieldOffset,
                                                    value,
                                                    mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreVectorElement(Array vector,
                                                int index,
                                                int arrayElementSize,
                                                UIntPtr fieldOffset,
                                                UIntPtr value,
                                                int mask)
        {
            installedBarrier.StoreVectorElementImpl(vector,
                                                    index,
                                                    arrayElementSize,
                                                    fieldOffset,
                                                    value,
                                                    mask);
        }

        ////////////////////// LoadVectorElement ////////////////////

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static Object LoadObjVectorElement(Array vector,
                                                    int index,
                                                    int arrayElementSize,
                                                    UIntPtr fieldOffset,
                                                    int mask)
        {
            return installedBarrier.LoadObjVectorElementImpl(vector,
                                                             index,
                                                             arrayElementSize,
                                                             fieldOffset,
                                                             mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static float LoadFloatVectorElement(Array vector,
                                                     int index,
                                                     int arrayElementSize,
                                                     UIntPtr fieldOffset,
                                                     int mask)
        {
            return installedBarrier
                .LoadFloatVectorElementImpl(vector,
                                            index,
                                            arrayElementSize,
                                            fieldOffset,
                                            mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static double LoadDoubleVectorElement(Array vector,
                                                       int index,
                                                       int arrayElementSize,
                                                       UIntPtr fieldOffset,
                                                       int mask)
        {
            return installedBarrier
                .LoadDoubleVectorElementImpl(vector,
                                             index,
                                             arrayElementSize,
                                             fieldOffset,
                                             mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static byte LoadByteVectorElement(Array vector,
                                                   int index,
                                                   int arrayElementSize,
                                                   UIntPtr fieldOffset,
                                                   int mask)
        {
            return installedBarrier.LoadByteVectorElementImpl(vector,
                                                              index,
                                                              arrayElementSize,
                                                              fieldOffset,
                                                              mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static ushort LoadUShortVectorElement(Array vector,
                                                       int index,
                                                       int arrayElementSize,
                                                       UIntPtr fieldOffset,
                                                       int mask)
        {
            return installedBarrier
                .LoadUShortVectorElementImpl(vector,
                                             index,
                                             arrayElementSize,
                                             fieldOffset,
                                             mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static uint LoadUIntVectorElement(Array vector,
                                                   int index,
                                                   int arrayElementSize,
                                                   UIntPtr fieldOffset,
                                                   int mask)
        {
            return installedBarrier.LoadUIntVectorElementImpl(vector,
                                                              index,
                                                              arrayElementSize,
                                                              fieldOffset,
                                                              mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static ulong LoadULongVectorElement(Array vector,
                                                     int index,
                                                     int arrayElementSize,
                                                     UIntPtr fieldOffset,
                                                     int mask)
        {
            return installedBarrier
                .LoadULongVectorElementImpl(vector,
                                            index,
                                            arrayElementSize,
                                            fieldOffset,
                                            mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static UIntPtr LoadUIntPtrVectorElement(Array vector,
                                                         int index,
                                                         int arrayElementSize,
                                                         UIntPtr fieldOffset,
                                                         int mask)
        {
            return installedBarrier
                .LoadUIntPtrVectorElementImpl(vector,
                                              index,
                                              arrayElementSize,
                                              fieldOffset,
                                              mask);
        }

        ///////////////////// StoreArrayElement /////////////////////

        [RequiredByBartok]
        [ForceInline]
        [NoStackLinkCheckTrans]
        internal static void StoreArrayElement(Array array,
                                               int index,
                                               int arrayElementSize,
                                               UIntPtr fieldOffset,
                                               Object value,
                                               int mask)
        {
            installedBarrier.StoreArrayElementImpl(array,
                                                   index,
                                                   arrayElementSize,
                                                   fieldOffset,
                                                   value,
                                                   mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreArrayElement(Array array,
                                               int index,
                                               int arrayElementSize,
                                               UIntPtr fieldOffset,
                                               float value,
                                               int mask)
        {
            installedBarrier.StoreArrayElementImpl(array,
                                                   index,
                                                   arrayElementSize,
                                                   fieldOffset,
                                                   value,
                                                   mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreArrayElement(Array array,
                                               int index,
                                               int arrayElementSize,
                                               UIntPtr fieldOffset,
                                               double value,
                                               int mask)
        {
            installedBarrier.StoreArrayElementImpl(array,
                                                   index,
                                                   arrayElementSize,
                                                   fieldOffset,
                                                   value,
                                                   mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreArrayElement(Array array,
                                               int index,
                                               int arrayElementSize,
                                               UIntPtr fieldOffset,
                                               byte value,
                                               int mask)
        {
            installedBarrier.StoreArrayElementImpl(array,
                                                   index,
                                                   arrayElementSize,
                                                   fieldOffset,
                                                   value,
                                                   mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreArrayElement(Array array,
                                               int index,
                                               int arrayElementSize,
                                               UIntPtr fieldOffset,
                                               ushort value,
                                               int mask)
        {
            installedBarrier.StoreArrayElementImpl(array,
                                                   index,
                                                   arrayElementSize,
                                                   fieldOffset,
                                                   value,
                                                   mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreArrayElement(Array array,
                                               int index,
                                               int arrayElementSize,
                                               UIntPtr fieldOffset,
                                               uint value,
                                               int mask)
        {
            installedBarrier.StoreArrayElementImpl(array,
                                                   index,
                                                   arrayElementSize,
                                                   fieldOffset,
                                                   value,
                                                   mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreArrayElement(Array array,
                                               int index,
                                               int arrayElementSize,
                                               UIntPtr fieldOffset,
                                               ulong value,
                                               int mask)
        {
            installedBarrier.StoreArrayElementImpl(array,
                                                   index,
                                                   arrayElementSize,
                                                   fieldOffset,
                                                   value,
                                                   mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static void StoreArrayElement(Array array,
                                               int index,
                                               int arrayElementSize,
                                               UIntPtr fieldOffset,
                                               UIntPtr value,
                                               int mask)
        {
            installedBarrier.StoreArrayElementImpl(array,
                                                   index,
                                                   arrayElementSize,
                                                   fieldOffset,
                                                   value,
                                                   mask);
        }

        ////////////////////// LoadArrayElement ////////////////////

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static Object LoadObjArrayElement(Array vector,
                                                   int index,
                                                   int arrayElementSize,
                                                   UIntPtr fieldOffset,
                                                   int mask)
        {
            return installedBarrier.LoadObjArrayElementImpl(vector,
                                                            index,
                                                            arrayElementSize,
                                                            fieldOffset,
                                                            mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static float LoadFloatArrayElement(Array vector,
                                                    int index,
                                                    int arrayElementSize,
                                                    UIntPtr fieldOffset,
                                                    int mask)
        {
            return installedBarrier.LoadFloatArrayElementImpl(vector,
                                                              index,
                                                              arrayElementSize,
                                                              fieldOffset,
                                                              mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static double LoadDoubleArrayElement(Array vector,
                                                      int index,
                                                      int arrayElementSize,
                                                      UIntPtr fieldOffset,
                                                      int mask)
        {
            return installedBarrier
                .LoadDoubleArrayElementImpl(vector,
                                            index,
                                            arrayElementSize,
                                            fieldOffset,
                                            mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static byte LoadByteArrayElement(Array vector,
                                                  int index,
                                                  int arrayElementSize,
                                                  UIntPtr fieldOffset,
                                                  int mask)
        {
            return installedBarrier.LoadByteArrayElementImpl(vector,
                                                             index,
                                                             arrayElementSize,
                                                             fieldOffset,
                                                             mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static ushort LoadUShortArrayElement(Array vector,
                                                      int index,
                                                      int arrayElementSize,
                                                      UIntPtr fieldOffset,
                                                      int mask)
        {
            return installedBarrier
                .LoadUShortArrayElementImpl(vector,
                                            index,
                                            arrayElementSize,
                                            fieldOffset,
                                            mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static uint LoadUIntArrayElement(Array vector,
                                                  int index,
                                                  int arrayElementSize,
                                                  UIntPtr fieldOffset,
                                                  int mask)
        {
            return installedBarrier.LoadUIntArrayElementImpl(vector,
                                                             index,
                                                             arrayElementSize,
                                                             fieldOffset,
                                                             mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static ulong LoadULongArrayElement(Array vector,
                                                    int index,
                                                    int arrayElementSize,
                                                    UIntPtr fieldOffset,
                                                    int mask)
        {
            return installedBarrier.LoadULongArrayElementImpl(vector,
                                                              index,
                                                              arrayElementSize,
                                                              fieldOffset,
                                                              mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoStackLinkCheckTrans]
        internal static UIntPtr LoadUIntPtrArrayElement(Array vector,
                                                        int index,
                                                        int arrayElementSize,
                                                        UIntPtr fieldOffset,
                                                        int mask)
        {
            return installedBarrier
                .LoadUIntPtrArrayElementImpl(vector,
                                             index,
                                             arrayElementSize,
                                             fieldOffset,
                                             mask);
        }

        //////////////////// StoreStaticField /////////////////////////
        // only support ref wb for now, since nobody needs integral
        // wb on statics

        [RequiredByBartok]
        [ForceInline]
        [NoStackLinkCheckTrans]
        internal static void StoreStaticField(ref Object staticField,
                                              Object value,
                                              int mask)
        {
            installedBarrier.StoreStaticFieldImpl(ref staticField,
                                                  value, mask);
        }

        //////////////////// LoadStaticField /////////////////////////
        // only support ref rb for now, since nobody needs integral
        // rb on statics

        [RequiredByBartok]
        [Inline]
        internal static Object LoadStaticField(ref Object staticField,
                                               int mask)
        {
            return installedBarrier.LoadStaticFieldImpl(ref staticField,
                                                        mask);
        }

        ///////////////////////// Increment/Decrement /////////////////////
        // REVIEW: maybe optimize these.  or not.

        [ForceInline]
        [RequiredByBartok]
        internal static int AtomicIncrement(ref int reference,
                                            int maskmask)
        {
            for (;;) {
                int oldVal = reference;
                if (Interlocked.CompareExchange(ref reference,
                                                oldVal+1,
                                                oldVal)
                    == oldVal) {
                    return oldVal+1;
                }
            }
        }

        [ForceInline]
        [RequiredByBartok]
        internal static int AtomicDecrement(ref int reference,
                                            int mask)
        {
            for (;;) {
                int oldVal = reference;
                if (Interlocked.CompareExchange(ref reference,
                                                oldVal-1,
                                                oldVal)
                    == oldVal) {
                    return oldVal-1;
                }
            }
        }

        /////////////////////////// AtomicSwap /////////////

        [RequiredByBartok]
        [ForceInline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static Object AtomicSwap(ref Object reference,
                                          Object value,
                                          int mask)
        {
            return installedBarrier.AtomicSwapImpl(ref reference,
                                                   value,
                                                   mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static int AtomicSwap(ref int reference,
                                       int value,
                                       int mask)
        {
            return installedBarrier.AtomicSwapImpl(ref reference,
                                                   value,
                                                   mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static UIntPtr AtomicSwap(ref UIntPtr reference,
                                           UIntPtr value,
                                           int mask)
        {
            return installedBarrier.AtomicSwapImpl(ref reference,
                                                   value,
                                                   mask);
        }

        //////////////// AtomicCompareAndSwap /////////////////

        [RequiredByBartok]
        [ForceInline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static Object AtomicCompareAndSwap(ref Object reference,
                                                    Object newValue,
                                                    Object comparand,
                                                    int mask)
        {
            return
                installedBarrier.AtomicCompareAndSwapImpl(ref reference,
                                                          newValue,
                                                          comparand,
                                                          mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static int AtomicCompareAndSwap(ref int reference,
                                                 int newValue,
                                                 int comparand,
                                                 int mask)
        {
            return
                installedBarrier.AtomicCompareAndSwapImpl(ref reference,
                                                          newValue,
                                                          comparand,
                                                          mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static long AtomicCompareAndSwap(ref long reference,
                                                  long newValue,
                                                  long comparand,
                                                  int mask)
        {
            return
                installedBarrier.AtomicCompareAndSwapImpl(ref reference,
                                                          newValue,
                                                          comparand,
                                                          mask);
        }

        [RequiredByBartok]
        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static UIntPtr AtomicCompareAndSwap(ref UIntPtr reference,
                                                     UIntPtr newValue,
                                                     UIntPtr comparand,
                                                     int mask)
        {
            return
                installedBarrier.AtomicCompareAndSwapImpl(ref reference,
                                                          newValue,
                                                          comparand,
                                                          mask);
        }

        /////////////////////// Forward ////////////////////////

        [RequiredByBartok]
        [ForceInline]
        internal static Object Forward(Object o,int mask)
        {
            return installedBarrier.ForwardImpl(o,mask);
        }

        /////////////////////// MemmoryBarrier ///////////////////////////

        [RequiredByBartok]
        [ForceInline]
        internal static void MemoryBarrier(int mask)
        {
            installedBarrier.MemoryBarrierImpl(mask);
        }

        //////////////////////// Pin ///////////////////////////
        //
        // takes an address at which you wish to pin and returns to
        // you a suitable "pinned" address to use.  may also cause
        // you to wait for any arbitrary amount of time.  but the
        // invariants are:
        // -> the address returned is pinned until the next safepoint,
        //    or until no pinned locals refer to it, whichever comes
        //    later.
        // -> even though the address returned may be different from
        //    the address given, and even though non-pinned pointers
        //    to the object may use totally different addresses, you're
        //    guaranteed that the address returned is the "true"
        //    address of the object, and any modifications made to it
        //    will be seen by anyone else accessing the same object, even
        //    if they do it via a different address.
        [RequiredByBartok]
        [ForceInline]
        internal static UIntPtr Pin(UIntPtr address,
                                    int mask)
        {
            return installedBarrier.PinImpl(address, mask);
        }

        ////////////////////////// Initialize Object /////////////////

        [Inline]
        internal static void InitObject(Object o,VTable vtable)
        {
            installedBarrier.InitObjectImpl(o,vtable);
        }

        // TODO: Eliminate this hack when possible.  That should be either
        // when the compiler is smart enough to devirtualize the
        // installedBarrier.InitObjectImpl call in Barrier.InitObject when
        // doing sepcomp, or when we stop using a class hierarchy of barriers.
        //
        // This method is called only from BootstrapMemory and is required
        // when the compiler cannot statically resolve which barrier to
        // use and the installedBarrier field has not been initialized.
        internal static void BootstrapInitObject(Object o, VTable vtable)
        {
            switch (GC.wbType) {
#if !SINGULARITY || MARK_SWEEP_COLLECTOR || NULL_COLLECTOR
              case WBType.noWB: {
                  EmptyWriteBarrier.BootstrapInitObjectImpl(o, vtable);
                  break;
              }
#endif
#if !SINGULARITY || SEMISPACE_COLLECTOR || SLIDING_COLLECTOR || ADAPTIVE_COPYING_COLLECTOR
              case WBType.Generational: {
                  GenerationalWriteBarrier.BootstrapInitObjectImpl(o, vtable);
                  break;
              }
#endif
#if !SINGULARITY || CONCURRENT_MS_COLLECTOR
              case WBType.CMS: {
                  WriteBarrierCMS.BootstrapInitObjectImpl(o, vtable);
                  break;
              }
#endif
#if !SINGULARITY || ATOMIC_RC_COLLECTOR
              case WBType.ARC: {
                  AtomicRCWriteBarrier.BootstrapInitObjectImpl(o, vtable);
                  break;
              }
#endif
#if !SINGULARITY || SEMISPACE_COLLECTOR || SLIDING_COLLECTOR || ADAPTIVE_COPYING_COLLECTOR
              case WBType.AllCards: {
                  AllCardsWriteBarrier.BootstrapInitObjectImpl(o, vtable);
                  break;
              }
#endif
#if !SINGULARITY
              case WBType.ExpandingCoCo: {
                  ExpandingCoCoBarrier.BootstrapInitObjectImpl(o, vtable);
                  break;
              }
              case WBType.ProbabilisticCoCo: {
                  ProbabilisticCoCoBarrier.BootstrapInitObjectImpl(o, vtable);
                  break;
              }
              case WBType.AbortingCoCo: {
                  AbortingCoCoBarrier.BootstrapInitObjectImpl(o, vtable);
                  break;
              }
              case WBType.BrooksTest: {
                  BrooksBarrierTest.BootstrapInitObjectImpl(o, vtable);
                  break;
              }
              case WBType.BrooksCMSTest: {
                  BrooksCMSBarrierTest.BootstrapInitObjectImpl(o, vtable);
                  break;
              }
#endif
              default: {
                  VTable.NotReached("Unknown write barrier type: "+GC.wbType);
                  break;
              }
            }
        }

        //////////////////////// Weak Ref ////////////////////////////

        [Inline]
        internal static Object WeakRefRead(UIntPtr addr,
                                           int mask)
        {
            return installedBarrier.WeakRefReadImpl(addr, mask);
        }

        [Inline]
        internal static UIntPtr WeakRefWrite(Object obj,
                                             int mask)
        {
            return installedBarrier.WeakRefWriteImpl(obj, mask);
        }

        ///////////////////////// Equality Barriers ///////////////////

        [RequiredByBartok]
        [Inline]
        internal static bool Eq(Object a, Object b, int mask)
        {
            return installedBarrier.EqImpl(a, b, mask);
        }

        [RequiredByBartok]
        [Inline]
        internal static bool Neq(Object a, Object b, int mask)
        {
            return !Eq(a, b, mask);
        }

        ////////////////////////// fast path selection ////////////////

        [RequiredByBartok]
        [ForceInline]
        internal static bool AllowFastPath()
        {
            return installedBarrier.AllowFastPathImpl();
        }

        /////////////////////// CopyStruct ////////////////////////////

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void CopyStruct(Object srcObj,
                                        Object dstObj,
                                        VTable vtable,
                                        UIntPtr srcPtr,
                                        UIntPtr dstPtr)
        {
            installedBarrier.CopyStructImpl(srcObj, dstObj,
                                            vtable, srcPtr, dstPtr);
        }

        //////////////////////////// Clone /////////////////////////////

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void Clone(Object srcObject, Object dstObject)
        {
            installedBarrier.CloneImpl(srcObject, dstObject);
        }

        //////////////////////// ArrayZero //////////////////////////////

        // 'offset' is not relative to the lower bound, but is a count
        // of elements from the first element in the array.
        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void ArrayZero(Array array, int offset, int length)
        {
            installedBarrier.ArrayZeroImpl(array, offset, length);
        }

        ////////////////////////// ArrayCopy ////////////////////////////

        // 'offset' is not relative to the lower bound, but is a count
        // of elements from the first element in the array.
        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void ArrayCopy(Array srcArray, int srcOffset,
                                       Array dstArray, int dstOffset,
                                       int length)
        {
            installedBarrier.ArrayCopyImpl(srcArray, srcOffset,
                                           dstArray, dstOffset,
                                           length);
        }

        ////////////////////// Write ////////////////////////////

        [ForceInline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void Write(UIntPtr *location, Object value, int mask)
        {
            installedBarrier.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void Write(float *location, float value, int mask)
        {
            installedBarrier.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void Write(double *location, double value, int mask)
        {
            installedBarrier.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void Write(byte *location, byte value, int mask)
        {
            installedBarrier.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void Write(ushort *location, ushort value, int mask)
        {
            installedBarrier.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void Write(uint *location, uint value, int mask)
        {
            installedBarrier.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void Write(ulong *location, ulong value, int mask)
        {
            installedBarrier.WriteImpl(location, value, mask);
        }

        [Inline]
        [NoBarriers]
        [NoStackLinkCheckTrans]
        internal static void Write(UIntPtr *location, UIntPtr value, int mask)
        {
            installedBarrier.WriteImpl(location, value, mask);
        }

        ///////////////////////// Visitors... /////////////////////////////

        private class CopyFieldsVisitor : OffsetReferenceVisitor
        {

            // Struct copy
            internal void VisitReferenceFields(VTable vtable,
                                               UIntPtr srcPtr,
                                               UIntPtr dstPtr)
            {
                int postHeaderSize = PostHeader.Size;
                ObjectDescriptor objDesc =
                    new ObjectDescriptor(vtable,
                                         srcPtr - postHeaderSize,
                                         dstPtr - postHeaderSize,
                                         (UIntPtr) postHeaderSize);
                VisitReferenceFieldsTemplate(ref objDesc);
                int preHeaderSize = PreHeader.Size;
                UIntPtr limitSize =
                    ObjectLayout.ObjectSize(vtable) - preHeaderSize;
                UIntPtr previouslyDone = objDesc.extra;
                UIntPtr tailSize = limitSize - previouslyDone;
                if (tailSize > UIntPtr.Zero) {
                    Util.MemCopy(objDesc.secondBase + previouslyDone,
                                 objDesc.objectBase + previouslyDone,
                                 tailSize);
                }
            }

            internal void VisitReferenceFields(Object srcObject,
                                               Object dstObject)
            {
                int postHeaderSize = PostHeader.Size;
                ObjectDescriptor objDesc =
                    new ObjectDescriptor(srcObject.vtable,
                                         Magic.addressOf(srcObject),
                                         Magic.addressOf(dstObject),
                                         (UIntPtr) postHeaderSize);
                UIntPtr objectSize = VisitReferenceFieldsTemplate(ref objDesc);
                int preHeaderSize = PreHeader.Size;
                UIntPtr limitSize = objectSize - preHeaderSize;
                UIntPtr previouslyDone = objDesc.extra;
                UIntPtr tailSize = limitSize - previouslyDone;
                if (tailSize > UIntPtr.Zero) {
                    Util.MemCopy(objDesc.secondBase + previouslyDone,
                                 objDesc.objectBase + previouslyDone,
                                 tailSize);
                }
            }

            // Partial array copy
            internal void VisitReferenceFields(VTable vtable,
                                               UIntPtr srcElementPtr,
                                               UIntPtr dstElementPtr,
                                               int length)
            {
                ObjectDescriptor objDesc =
                    new ObjectDescriptor(vtable, srcElementPtr, dstElementPtr);
                VisitReferenceFieldsTemplate(ref objDesc, length);
                UIntPtr dataSize =
                    srcElementPtr + length * vtable.arrayElementSize;
                UIntPtr srcLimitAddr = Util.UIntPtrPad(dataSize);
                UIntPtr previouslyDone = objDesc.objectBase + objDesc.extra;
                UIntPtr tailSize = srcLimitAddr - previouslyDone;
                if (tailSize > UIntPtr.Zero) {
                    Util.MemCopy(objDesc.secondBase + objDesc.extra,
                                 previouslyDone, tailSize);
                }
            }

            internal override void FieldOffset(UIntPtr offset,
                                               ref ObjectDescriptor objDesc)
            {
                UIntPtr previouslyDone = objDesc.extra;
                objDesc.extra = offset + UIntPtr.Size;
                UIntPtr norefSize = offset - previouslyDone;
                if (norefSize > UIntPtr.Zero) {
                    Util.MemCopy(objDesc.secondBase + previouslyDone,
                                 objDesc.objectBase + previouslyDone,
                                 norefSize);
                }
                UIntPtr *srcAddr = (UIntPtr *) (objDesc.objectBase + offset);
                UIntPtr *dstAddr = (UIntPtr *) (objDesc.secondBase + offset);
                Object fieldValue = installedBarrier.ReadObjImpl(srcAddr, 0);
                fieldValue =
                    installedBarrier.ForwardImpl(fieldValue,
                                                 BarrierMask.Forward.Nullable);
                installedBarrier.WriteImpl(dstAddr, fieldValue, 0);
            }

        }

        private class SlowCopyFieldsVisitor : OffsetReferenceVisitor
        {

            // Struct copy
            internal void VisitReferenceFields(VTable vtable,
                                               Object src,
                                               Object dst,
                                               UIntPtr srcOff,
                                               UIntPtr dstOff)
            {
                int postHeaderSize = PostHeader.Size;
                ObjectDescriptor objDesc =
                    new ObjectDescriptor(vtable,
                                         Magic.addressOf(src)
                                         + srcOff - postHeaderSize,
                                         Magic.addressOf(dst)
                                         + dstOff - postHeaderSize,
                                         (UIntPtr) postHeaderSize,
                                         src,dst);
                VisitReferenceFieldsTemplate(ref objDesc);
                int preHeaderSize = PreHeader.Size;
                UIntPtr limitSize =
                    ObjectLayout.ObjectSize(vtable) - preHeaderSize;
                UIntPtr previouslyDone = objDesc.extra;
                UIntPtr tailSize = limitSize - previouslyDone;
                MemCopyBarrierSlow(dst,
                                   objDesc.secondBase
                                   + previouslyDone
                                   - Magic.addressOf(dst),
                                   src,
                                   objDesc.objectBase
                                   + previouslyDone
                                   - Magic.addressOf(src),
                                   tailSize);
            }

            // Partial array copy
            internal void VisitReferenceFields(VTable vtable,
                                               Object srcArr,
                                               Object dstArr,
                                               UIntPtr srcOff,
                                               UIntPtr dstOff,
                                               int length)
            {
                ObjectDescriptor objDesc =
                    new ObjectDescriptor(vtable,
                                         Magic.addressOf(srcArr) + srcOff,
                                         Magic.addressOf(dstArr) + dstOff,
                                         UIntPtr.Zero,
                                         srcArr, dstArr);
                VisitReferenceFieldsTemplate(ref objDesc, length);
                UIntPtr srcLimitAddr =
                    Magic.addressOf(srcArr) + srcOff
                    + length * vtable.arrayElementSize;
                UIntPtr previouslyDone = objDesc.objectBase + objDesc.extra;
                UIntPtr tailSize = srcLimitAddr - previouslyDone;
                MemCopyBarrierSlow(dstArr,
                                   objDesc.secondBase + objDesc.extra
                                   - Magic.addressOf(dstArr),
                                   srcArr,
                                   previouslyDone - Magic.addressOf(srcArr),
                                   tailSize);
            }

            internal void VisitReferenceFields(Object srcObject,
                                               Object dstObject)
            {
                int postHeaderSize = PostHeader.Size;
                ObjectDescriptor objDesc =
                    new ObjectDescriptor(srcObject.vtable,
                                         Magic.addressOf(srcObject),
                                         Magic.addressOf(dstObject),
                                         (UIntPtr) postHeaderSize,
                                         srcObject,
                                         dstObject);
                UIntPtr objectSize = VisitReferenceFieldsTemplate(ref objDesc);
                int preHeaderSize = PreHeader.Size;
                UIntPtr limitSize = objectSize - preHeaderSize;
                UIntPtr previouslyDone = objDesc.extra;
                UIntPtr tailSize = limitSize - previouslyDone;
                MemCopyBarrierSlow(dstObject,previouslyDone,
                                   srcObject,previouslyDone,
                                   tailSize);
            }

            internal override void FieldOffset(UIntPtr offset,
                                               ref ObjectDescriptor objDesc)
            {
                UIntPtr previouslyDone = objDesc.extra;
                objDesc.extra = offset + UIntPtr.Size;
                UIntPtr norefSize = offset - previouslyDone;
                MemCopyBarrierSlow(objDesc.realSecondBase,
                                   previouslyDone + objDesc.secondBase
                                   - Magic.addressOf(objDesc.realSecondBase),
                                   objDesc.realObjectBase,
                                   previouslyDone + objDesc.objectBase
                                   - Magic.addressOf(objDesc.realObjectBase),
                                   norefSize);
                Object fieldValue =
                    installedBarrier
                    .ReadObjImpl(objDesc.realObjectBase,
                                 offset + objDesc.objectBase
                                 - Magic.addressOf(objDesc.realObjectBase),
                                 0);
                installedBarrier
                    .WriteImpl(objDesc.realSecondBase,
                               offset + objDesc.secondBase
                               - Magic.addressOf(objDesc.realSecondBase),
                               fieldValue,
                               0);
            }

        }

        private class ZeroFieldsVisitor : OffsetReferenceVisitor
        {

            internal void VisitReferenceFields(VTable vtable,
                                               UIntPtr elementAddr,
                                               int length)
            {
                ObjectDescriptor objDesc =
                    new ObjectDescriptor(vtable, elementAddr);
                VisitReferenceFieldsTemplate(ref objDesc, length);
                UIntPtr limitAddr =
                    elementAddr + length * vtable.arrayElementSize;
                UIntPtr previouslyDone = objDesc.objectBase + objDesc.extra;
                UIntPtr tailSize = limitAddr - previouslyDone;
                if (tailSize > UIntPtr.Zero) {
                    Buffer.ZeroMemory((byte *) previouslyDone, tailSize);
                }
            }

            internal override void FieldOffset(UIntPtr offset,
                                               ref ObjectDescriptor objDesc)
            {
                UIntPtr previouslyDone = objDesc.extra;
                objDesc.extra = offset + UIntPtr.Size;
                UIntPtr norefSize = offset - previouslyDone;
                if (norefSize > UIntPtr.Zero) {
                    Util.MemClear(objDesc.objectBase + previouslyDone,
                                  norefSize);
                }
                UIntPtr *fieldAddr = (UIntPtr *) (objDesc.objectBase + offset);
                installedBarrier.WriteImpl(fieldAddr, null, 0);
            }

        }

        private class SlowZeroFieldsVisitor : OffsetReferenceVisitor
        {

            internal void VisitReferenceFields(Object arr,
                                               UIntPtr off,
                                               int length)
            {
                ObjectDescriptor objDesc =
                    new ObjectDescriptor(arr.vtable,
                                         Magic.addressOf(arr) + off,
                                         off,
                                         UIntPtr.Zero,
                                         arr,
                                         null);
                VisitReferenceFieldsTemplate(ref objDesc, length);
                UIntPtr limitAddr =
                    Magic.addressOf(arr) + off + length * arr.vtable.arrayElementSize;
                UIntPtr previouslyDone = objDesc.objectBase + objDesc.extra;
                UIntPtr tailSize = limitAddr - previouslyDone;
                Barrier.MemZeroBarrierSlow(arr,
                                           previouslyDone - Magic.addressOf(arr),
                                           tailSize);
            }

            internal override void FieldOffset(UIntPtr offset,
                                               ref ObjectDescriptor objDesc)
            {
                UIntPtr previouslyDone = objDesc.extra;
                objDesc.extra = offset + UIntPtr.Size;
                UIntPtr norefSize = offset - previouslyDone;
                Barrier
                    .MemZeroBarrierSlow(objDesc.realObjectBase,
                                        objDesc.secondBase + previouslyDone,
                                        norefSize);
                installedBarrier
                    .WriteImpl(objDesc.realObjectBase,
                               objDesc.secondBase + offset,
                               null,
                               0);
            }

        }

    }

}
