119 lines
4.3 KiB
C#
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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|