singrdk/base/Kernel/Bartok/GCs/BootstrapMemory.cs

154 lines
5.5 KiB
C#

/*******************************************************************/
/* 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. */
/*******************************************************************/
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
namespace System.GCs {
using Microsoft.Bartok.Runtime;
using System.Threading;
using System.Runtime.CompilerServices;
internal unsafe class BootstrapMemory
{
// WARNING: don't initialize any static fields in this class
// without manually running the class constructor at startup!
private static BumpAllocator pool;
[PreInitRefCounts]
#if !SINGULARITY
[NoStackLinkCheck]
#endif
internal static void Initialize(UIntPtr systemMemorySize) {
pool = new BumpAllocator(PageType.NonGC);
UIntPtr memStart = MemoryManager.AllocateMemory(systemMemorySize);
pool.SetZeroedRange(memStart, systemMemorySize);
if(GC.gcType != GCType.NullCollector) {
PageManager.SetStaticDataPages(memStart, systemMemorySize);
#if !SINGULARITY
PageTable.SetProcess(PageTable.Page(memStart),
PageTable.PageCount(systemMemorySize));
#endif
}
}
[ManualRefCounts]
#if !SINGULARITY
[NoStackLinkCheck]
#endif
internal static Object Allocate(VTable vtable) {
UIntPtr numBytes = ObjectLayout.ObjectSize(vtable);
UIntPtr objectAddr =
pool.AllocateFast(numBytes, vtable.baseAlignment);
VTable.Assert(objectAddr != UIntPtr.Zero,
"Out of BootstrapMemory");
Object result = Magic.fromAddress(objectAddr);
#if REFERENCE_COUNTING_GC
result.REF_STATE = vtable.isAcyclicRefType ?
(ReferenceCountingCollector.
acyclicFlagMask | 1): 1;
result.REF_STATE = (result.REF_STATE | 2) &
~ReferenceCountingCollector.countingONFlagMask;
#elif DEFERRED_REFERENCE_COUNTING_GC
result.REF_STATE = vtable.isAcyclicRefType ?
(DeferredReferenceCountingCollector.
acyclicFlagMask |
DeferredReferenceCountingCollector.
markFlagMask) :
DeferredReferenceCountingCollector.
markFlagMask;
result.REF_STATE &=
~DeferredReferenceCountingCollector.countingONFlagMask;
#endif
*result.VTableFieldAddr = Magic.addressOf(vtable);
return result;
}
[ManualRefCounts]
#if !SINGULARITY
[NoStackLinkCheck]
#endif
internal static Object Allocate(VTable vtable, uint count) {
UIntPtr numBytes = ObjectLayout.ArraySize(vtable, count);
UIntPtr objectAddr =
pool.AllocateFast(numBytes, vtable.baseAlignment);
VTable.Assert(objectAddr != UIntPtr.Zero,
"Out of BootstrapMemory");
Array result = Magic.toArray(Magic.fromAddress(objectAddr));
#if REFERENCE_COUNTING_GC
result.REF_STATE = vtable.isAcyclicRefType ?
(ReferenceCountingCollector.
acyclicFlagMask | 1): 1;
result.REF_STATE = (result.REF_STATE | 2) &
~ReferenceCountingCollector.countingONFlagMask;
#elif DEFERRED_REFERENCE_COUNTING_GC
result.REF_STATE = vtable.isAcyclicRefType ?
(DeferredReferenceCountingCollector.
acyclicFlagMask |
DeferredReferenceCountingCollector.
markFlagMask) :
DeferredReferenceCountingCollector.
markFlagMask;
result.REF_STATE &=
~DeferredReferenceCountingCollector.countingONFlagMask;
#endif
*result.VTableFieldAddr = Magic.addressOf(vtable);
result.InitializeVectorLength((int) count);
return result;
}
[PreInitRefCounts]
#if !SINGULARITY
[NoStackLinkCheck]
#endif
internal static Object Allocate(Type t) {
return Allocate((RuntimeType) t);
}
[PreInitRefCounts]
#if !SINGULARITY
[NoStackLinkCheck]
#endif
internal static Object Allocate(Type t, uint count) {
return Allocate((RuntimeType) t, count);
}
[PreInitRefCounts]
#if !SINGULARITY
[NoStackLinkCheck]
#endif
internal static Object Allocate(RuntimeType t) {
return Allocate(t.classVtable);
}
[PreInitRefCounts]
#if !SINGULARITY
[NoStackLinkCheck]
#endif
internal static Object Allocate(RuntimeType t, uint count) {
return Allocate(t.classVtable, count);
}
internal static void Truncate() {
UIntPtr allocLimit = PageTable.PagePad(pool.AllocPtr);
UIntPtr unusedSize = pool.ReserveLimit - allocLimit;
if(GC.gcType != GCType.NullCollector) {
PageManager.ReleaseUnusedPages(PageTable.Page(allocLimit),
PageTable.PageCount(unusedSize),
true);
}
pool.Truncate();
}
}
}