117 lines
3.9 KiB
C#
117 lines
3.9 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 System.Runtime.CompilerServices;
|
||
|
|
||
|
internal unsafe struct UIntPtrStack {
|
||
|
|
||
|
private UnmanagedPageList pageList;
|
||
|
private UIntPtr stackPage;
|
||
|
private UIntPtr *stackBottom;
|
||
|
private UIntPtr *stackPtr;
|
||
|
private UIntPtr *stackTop;
|
||
|
|
||
|
internal bool IsEmpty {
|
||
|
get {
|
||
|
return ((this.stackPtr == this.stackBottom) &&
|
||
|
this.pageList.IsEmpty);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Write(UIntPtr value) {
|
||
|
if (this.stackPtr == stackTop) {
|
||
|
AdvancePage();
|
||
|
}
|
||
|
*this.stackPtr = value;
|
||
|
this.stackPtr++;
|
||
|
}
|
||
|
|
||
|
internal void Write(UIntPtr value1, UIntPtr value2) {
|
||
|
if (this.stackPtr + 2 <= stackTop) {
|
||
|
*this.stackPtr = value1;
|
||
|
*(this.stackPtr + 1) = value2;
|
||
|
this.stackPtr += 2;
|
||
|
} else {
|
||
|
this.Write(value1);
|
||
|
this.Write(value2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal UIntPtr Read() {
|
||
|
if (this.stackPtr == stackBottom) {
|
||
|
RetractPage();
|
||
|
}
|
||
|
this.stackPtr--;
|
||
|
return *this.stackPtr;
|
||
|
}
|
||
|
|
||
|
internal UIntPtr Read(out UIntPtr value2) {
|
||
|
if (this.stackPtr - 2 >= stackBottom) {
|
||
|
value2 = *(this.stackPtr - 1);
|
||
|
UIntPtr value1 = *(this.stackPtr - 2);
|
||
|
this.stackPtr -= 2;
|
||
|
return value1;
|
||
|
} else {
|
||
|
value2 = this.Read();
|
||
|
UIntPtr value1 = this.Read();
|
||
|
return value1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Cleanup(bool mustBeEmpty) {
|
||
|
if (mustBeEmpty) {
|
||
|
VTable.Assert(this.IsEmpty);
|
||
|
}
|
||
|
if (this.stackPage != UIntPtr.Zero) {
|
||
|
UnmanagedPageList.pageCache.AddHead(this.stackPage);
|
||
|
this.stackPage = UIntPtr.Zero;
|
||
|
}
|
||
|
while (!this.pageList.IsEmpty) {
|
||
|
UIntPtr headPage = this.pageList.RemoveHead();
|
||
|
UnmanagedPageList.pageCache.AddHead(headPage);
|
||
|
}
|
||
|
this.stackBottom = null;
|
||
|
this.stackTop = null;
|
||
|
this.stackPtr = null;
|
||
|
}
|
||
|
|
||
|
private void AdvancePage() {
|
||
|
if (this.stackPage != UIntPtr.Zero) {
|
||
|
this.pageList.AddHead(this.stackPage);
|
||
|
}
|
||
|
if (UnmanagedPageList.pageCache.IsEmpty) {
|
||
|
bool fCleanPages = true;
|
||
|
UIntPtr page = PageManager.EnsurePages(null, (UIntPtr) 1,
|
||
|
PageType.System,
|
||
|
ref fCleanPages);
|
||
|
this.stackPage = PageTable.PageAddr(page);
|
||
|
} else {
|
||
|
this.stackPage = UnmanagedPageList.pageCache.RemoveHead();
|
||
|
}
|
||
|
this.stackBottom = UnmanagedPageList.FirstPageAddr(this.stackPage);
|
||
|
this.stackPtr = this.stackBottom;
|
||
|
this.stackTop = UnmanagedPageList.EndPageAddr(this.stackPage);
|
||
|
}
|
||
|
|
||
|
private void RetractPage() {
|
||
|
UnmanagedPageList.pageCache.AddHead(this.stackPage);
|
||
|
this.stackPage = this.pageList.RemoveHead();
|
||
|
this.stackBottom = UnmanagedPageList.FirstPageAddr(this.stackPage);
|
||
|
this.stackTop = UnmanagedPageList.EndPageAddr(this.stackPage);
|
||
|
this.stackPtr = this.stackTop;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|