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

119 lines
4.3 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.Runtime.CompilerServices;
internal class ObjectLayout
{
// Tags on GC information provided by compiler.
internal const uint SPARSE_TAG = 0x1;
internal const uint DENSE_TAG = 0x3;
internal const uint PTR_VECTOR_TAG = 0x5;
internal const uint OTHER_VECTOR_TAG = 0x7;
internal const uint PTR_ARRAY_TAG = 0x9;
internal const uint OTHER_ARRAY_TAG = 0xb;
internal const uint STRING_TAG = 0xd;
internal const uint RESERVED_TAG = 0xf;
internal abstract class ObjectVisitor {
// Must return the size of the visited object.
internal abstract UIntPtr Visit(Object obj);
}
// Returns object size in bytes
[ManualRefCounts]
[NoHeapAllocation]
internal static UIntPtr ObjectSize(VTable vtable)
{
uint baseLength = unchecked((uint)vtable.baseLength);
VTable.Assert(Util.UIntPtrPad((UIntPtr) baseLength) == baseLength);
return (UIntPtr)baseLength;
}
// Returns string size in bytes
[ManualRefCounts]
[NoHeapAllocation]
internal static unsafe UIntPtr StringSize(VTable vtable,
uint arrayLength)
{
uint baseLength = unchecked((uint) vtable.baseLength);
uint size = (baseLength + sizeof(char)*arrayLength);
return Util.UIntPtrPad((UIntPtr) size);
}
// Returns array size in bytes
[ManualRefCounts]
[NoInline]
[NoHeapAllocation]
internal static UIntPtr ArraySize(VTable vtable, uint numElements)
{
UIntPtr baseLength = (UIntPtr)
unchecked((uint) vtable.baseLength);
UIntPtr elementSize = (UIntPtr)
unchecked((uint) vtable.arrayElementSize);
UIntPtr size = baseLength + elementSize * numElements;
return Util.UIntPtrPad(size);
}
// Returns object size in bytes
[ManualRefCounts]
[NoHeapAllocation]
internal unsafe static UIntPtr Sizeof(Object obj) {
return ObjectSize(Magic.addressOf(obj), obj.vtable);
}
[ManualRefCounts]
[NoHeapAllocation]
internal unsafe static UIntPtr ObjectSize(UIntPtr objectBase,
VTable vtable)
{
uint objectTag =
unchecked((uint) vtable.pointerTrackingMask) & 0xf;
switch (objectTag) {
case SPARSE_TAG:
case DENSE_TAG: {
return ObjectSize(vtable);
}
case PTR_VECTOR_TAG:
case OTHER_VECTOR_TAG: {
uint length = *(uint*) (objectBase + PostHeader.Size);
return ArraySize(vtable, length);
}
case PTR_ARRAY_TAG:
case OTHER_ARRAY_TAG: {
uint length =
*(uint*)(objectBase + PostHeader.Size + sizeof(uint));
return ArraySize(vtable, length);
}
case STRING_TAG: {
uint length = *(uint*) (objectBase + PostHeader.Size);
return StringSize(vtable, length);
}
case RESERVED_TAG: {
VTable.Assert(false, "RESERVED_TAG was used!");
return UIntPtr.Zero;
}
default: {
// escape case
return ObjectSize(vtable);
}
}
}
}
}