// // 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; #if SINGULARITY using Microsoft.Singularity; #endif // REVIEW: This should probably only be on the mixin types to // CalleeSaveRegisters, but it seems to be lost if put there. [AccessedByRuntime("referenced from halforgc.asm")] internal struct CalleeSaveRegisters { internal void DebugTrace() { // Placeholder for an override method } internal UIntPtr GetFramePointer() { // Placeholder for an override method return UIntPtr.Zero; } } internal unsafe struct CalleeSaveLocations { #if SINGULARITY_KERNEL internal void SetCalleeSaves(ThreadContext *context) { // Placeholder for an override method } #endif internal void SetCalleeSaves(CalleeSaveRegisters *calleeSaveRegisters) { // Placeholder for an override method } internal void ClearCalleeSaves() { // Placeholder for an override method } [PreInitRefCounts] internal void ScanLiveRegs(UIntPtr mask, NonNullReferenceVisitor referenceVisitor) { // Placeholder for an override method } internal void PopFrame(UIntPtr *framePointer, UIntPtr calleeSaveMask, bool framePointerOmitted, bool hasTransitionRecord) { // Placeholder for an override method } internal void ClearFrame(UIntPtr calleeSaveMask, bool framePointerOmitted) { // Placeholder for an override method } internal UIntPtr GetFramePointer() { // Placeholder for an override method return UIntPtr.Zero; } internal struct RegLocation { [Inline] internal void SetCalleeReg(UIntPtr *regField) { this.pending = false; this.value = *regField; this.head = regField; *regField = UIntPtr.Zero; } internal void ClearCalleeReg() { VTable.Deny(this.pending); UIntPtr *scan = this.head; while (scan != null) { UIntPtr temp = *scan; *scan = value; scan = (UIntPtr *) temp; } this.head = null; } [PreInitRefCounts] internal void ScanLiveReg(uint kind, NonNullReferenceVisitor visitor) { switch (kind) { case 0: { // Value is not a traceable heap pointer break; } case 1: { // Value is a pointer variable VTable.Deny(this.head == null); if (value != UIntPtr.Zero) { fixed (UIntPtr *valueField = &this.value) { visitor.Visit(valueField); } } ClearCalleeReg(); break; } case 2: { // Value is unchanged since function entry VTable.Deny(this.pending); this.pending = true; break; } case 3: default: { VTable.NotReached("ScanLiveReg 3 or default"); break; } } } internal void PopFrameReg(ref UIntPtr *calleeSaveStart) { if (this.head != null && !this.pending) { ClearCalleeReg(); } if (this.head == null) { this.value = *calleeSaveStart; } else { VTable.Assert(this.pending, "pending should be true"); VTable.Assert(*calleeSaveStart == this.value, "values are not equal"); } this.pending = false; *calleeSaveStart = (UIntPtr) this.head; this.head = calleeSaveStart; calleeSaveStart--; } internal void ClearFrameReg() { UIntPtr *scan = this.head; while (scan != null) { UIntPtr temp = *scan; *scan = value; scan = (UIntPtr *) temp; } this.head = null; this.pending = false; this.value = UIntPtr.Zero; } internal bool pending; internal UIntPtr value; internal UIntPtr *head; } CalleeSaveLocations.RegLocation FramePointer; } }