// // 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 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); } } [Inline] internal void Write(UIntPtr value) { if (this.stackPtr == stackTop) { AdvancePage(); } *this.stackPtr = value; this.stackPtr++; } [Inline] 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); } } [Inline] internal UIntPtr Read() { if (this.stackPtr == stackBottom) { RetractPage(); } this.stackPtr--; return *this.stackPtr; } [Inline] 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; } } }