|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
|
|
#pragma warning disable 1591
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
|
|
|
|
namespace FASTER.core
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// AddressInfo struct
|
|
|
|
|
/// </summary>
|
|
|
|
|
[StructLayout(LayoutKind.Explicit, Size = 8)]
|
|
|
|
|
public unsafe struct AddressInfo
|
|
|
|
|
{
|
|
|
|
|
private const int kMultiplierBits = 1;
|
|
|
|
|
private static readonly int kTotalBits = sizeof(IntPtr) * 8;
|
|
|
|
|
private static readonly int kAddressBits = 42*kTotalBits/64;
|
|
|
|
|
private static readonly int kSizeBits = kTotalBits - kAddressBits - kMultiplierBits;
|
|
|
|
|
private static readonly long kSizeMaskInWord = ((1L << kSizeBits) - 1) << kAddressBits;
|
|
|
|
|
private static readonly long kSizeMaskInInteger = (1L << kSizeBits) - 1;
|
|
|
|
|
private static readonly long kMultiplierMaskInWord = ((1L << kMultiplierBits) - 1) << (kAddressBits + kSizeBits);
|
|
|
|
|
private const long kMultiplierMaskInInteger = (1L << kMultiplierBits) - 1;
|
|
|
|
|
private static readonly long kAddressMask = (1L << kAddressBits) - 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[FieldOffset(0)]
|
|
|
|
|
private IntPtr word;
|
|
|
|
|
|
|
|
|
|
public static void WriteInfo(AddressInfo* info, long address, long size)
|
|
|
|
|
{
|
|
|
|
|
info->word = default(IntPtr);
|
|
|
|
|
info->Address = address;
|
|
|
|
|
info->Size = size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static string ToString(AddressInfo* info)
|
|
|
|
|
{
|
|
|
|
|
return "RecordHeader Word = " + info->word;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public long Size
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
int multiplier = (int)((((long)word & kMultiplierMaskInWord) >> (kAddressBits + kSizeBits)) & kMultiplierMaskInInteger);
|
|
|
|
|
return (multiplier == 0 ? 512 : 1<<20)*((((long)word & kSizeMaskInWord) >> kAddressBits) & kSizeMaskInInteger);
|
|
|
|
|
}
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
int multiplier = 0;
|
|
|
|
|
int val = (int)(value >> 9);
|
|
|
|
|
if ((value & ((1<<9)-1)) != 0) val++;
|
|
|
|
|
|
|
|
|
|
if (val >= (1 << kSizeBits))
|
|
|
|
|
{
|
|
|
|
|
val = (int)(value >> 20);
|
|
|
|
|
if ((value & ((1<<20) - 1)) != 0) val++;
|
|
|
|
|
multiplier = 1;
|
|
|
|
|
if (val >= (1 << kSizeBits))
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Unsupported object size: " + value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var _word = (long)word;
|
|
|
|
|
_word &= ~kSizeMaskInWord;
|
|
|
|
|
_word &= ~kMultiplierMaskInWord;
|
|
|
|
|
_word |= (val & kSizeMaskInInteger) << kAddressBits;
|
|
|
|
|
_word |= (multiplier & kMultiplierMaskInInteger) << (kAddressBits + kSizeBits);
|
|
|
|
|
word = (IntPtr)_word;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public long Address
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return (long)word & kAddressMask;
|
|
|
|
|
}
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
var _word = (long)word;
|
|
|
|
|
_word &= ~kAddressMask;
|
|
|
|
|
_word |= (value & kAddressMask);
|
|
|
|
|
word = (IntPtr)_word;
|
|
|
|
|
if (value != Address)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Overflow in AddressInfo" + ((kAddressBits < 64) ? " - consider running the program in x64 mode for larger address space support" : ""));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|