TypeSizes.scala 4.82 KB
Newer Older
1 2
package uvm.refimpl.mem

3
import uvm.refimpl._
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
import uvm.types._

/**
 * Responsible for object layout.
 * <p>
 * Scalar object:
 *
 * <pre>
 *     8 bytes
 * +----------------+----------------
 * | tag            | payload...
 * +----------------+----------------
 * ^objref-8bytes   ^ objref
 * </pre>
 *
 * Hybrid:
 *
 * <pre>
 *    8 bytes           8 bytes
 * +-----------------+-----------------+------------+--------------
 * | var part length | tag             | fixed part | var part
 * +-----------------+-----------------+------------+--------------
 * ^objref-16bytes   ^objref-8bytes    ^ objref
 * </pre>
 *
 * tag: (not forwarded)
 *
 * <pre>
 *   1bit         1bit       30bit            32bit
 * +-----------+--------+------------------+---------+
 * | moved = 0 | marked | (unused bits...) | type id |
 * +-----------+--------+------------------+---------+
 * 64          63       62                 32        0
 * </pre>
 * (forwarded)
 * <pre>
 *   1bit            15bit               48bits
 * +-----------+------------------+------------------+
 * | moved = 1 | (unused bits...) | destination addr |
 * +-----------+------------------+------------------+
 * 64          63                 48                 0
 * </pre>
 */
object TypeSizes {
  val GC_HEADER_SIZE_SCALAR: Word = 8L;
  val GC_HEADER_SIZE_HYBRID: Word = 16L;

  val GC_HEADER_OFFSET_TAG: Word = -8L;
  val GC_HEADER_OFFSET_HYBRID_LENGTH: Word = -16L;

54 55 56 57
  val MARK_MASK = 0x4000000000000000L

  val MOVE_MASK = 0x8000000000000000L

58
  def sizeOf(ty: Type): Word = ty match {
59 60 61 62 63 64
    case TypeInt(l)            => intBitsToBytes(l)
    case _: TypeFloat          => 4L
    case _: TypeDouble         => 8L
    case _: TypeRef            => WORD_SIZE_BYTES
    case _: TypeIRef           => 2L * WORD_SIZE_BYTES
    case _: TypeWeakRef        => WORD_SIZE_BYTES
65
    case t @ TypeStruct(ftys)  => structPrefixSizeOf(t, ftys.size)
66 67 68
    case t @ TypeArray(et, l)  => seqPrefixSizeOf(t, l)
    case _: TypeHybrid         => throw new IllegalArgumentException("Hybrid should use hybridSizeOf to probe size")
    case _: TypeVoid           => 0L
69 70 71
    case _: TypeFuncRef        => WORD_SIZE_BYTES
    case _: TypeThreadRef      => WORD_SIZE_BYTES
    case _: TypeStackRef       => WORD_SIZE_BYTES
72
    case _: TypeIRBuilderRef   => WORD_SIZE_BYTES
73 74
    case _: TypeTagRef64       => 8L
    case t @ TypeVector(et, l) => seqPrefixSizeOf(t, l)
75 76
    case _: TypeUPtr           => WORD_SIZE_BYTES
    case _: TypeUFuncPtr       => WORD_SIZE_BYTES
77 78 79
  }

  def alignOf(ty: Type): Word = ty match {
Kunshan Wang's avatar
Kunshan Wang committed
80
    case TypeStruct(ftys) => ftys.map(alignOf).max
81 82 83 84
    case TypeArray(et, _) => alignOf(et)
    case _: TypeHybrid    => throw new IllegalArgumentException("Hybrid should use hybridAlignOf to probe alignment")
    case _: TypeVoid      => 1L
    case _                => sizeOf(ty)
85 86 87
  }

  def hybridSizeOf(ty: TypeHybrid, len: Word): Word = {
Kunshan Wang's avatar
Kunshan Wang committed
88
    val fixedSize = structPrefixSizeOf(ty, ty.fieldTys.size)
89 90 91 92 93 94 95
    val varAlign = alignOf(ty.varTy)
    val varSize = shiftOffsetOf(ty.varTy, len)
    val size = alignUp(fixedSize, varAlign) + varSize
    return size
  }

  def hybridAlignOf(ty: TypeHybrid, len: Word): Word = {
Kunshan Wang's avatar
Kunshan Wang committed
96
    val fieldAligns = ty.fieldTys.map(alignOf)
97
    val varAlign = alignOf(ty.varTy)
Kunshan Wang's avatar
Kunshan Wang committed
98
    val align = fieldAligns.foldLeft(varAlign)(Math.max)
99 100 101
    return align
  }

102
  def fieldOffsetOf(ty: AbstractStructType, index: Int): Word = {
103
    val fieldType = ty.fieldTys(index)
104
    val fieldAlign = alignOf(fieldType)
105
    val prefixSize = structPrefixSizeOf(ty, index)
106 107 108
    val offset = alignUp(prefixSize, fieldAlign)
    return offset
  }
109

110 111 112 113 114 115 116
  def elemOffsetOf(ty: AbstractSeqType, length: Word): Word = {
    return seqPrefixSizeOf(ty, length)
  }

  def shiftOffsetOf(ty: Type, index: Word): Word = {
    return alignUp(sizeOf(ty), alignOf(ty)) * index
  }
117

118
  def varPartOffsetOf(ty: TypeHybrid): Word = {
Kunshan Wang's avatar
Kunshan Wang committed
119
    return alignUp(structPrefixSizeOf(ty, ty.fieldTys.length), alignOf(ty.varTy))
120
  }
121

Kunshan Wang's avatar
Kunshan Wang committed
122
  def structPrefixSizeOf(ty: AbstractStructType, prefixLen: Int): Word = {
123
    val sz = ty.fieldTys.take(prefixLen).foldLeft(0L) { (oldSz, nextTy) =>
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
      alignUp(oldSz, alignOf(nextTy)) + sizeOf(nextTy)
    }
    return sz
  }

  def seqPrefixSizeOf(ty: AbstractSeqType, length: Word): Word = {
    return shiftOffsetOf(ty.elemTy, length)
  }

  def nextPowOfTwo(n: Word): Word = {
    var i = 1L
    while (i < n) {
      i <<= 1L
    }
    return i
  }

  def intBitsToBytes(n: Word): Word = {
    val p2 = nextPowOfTwo(n)
    if (p2 < 8L) {
      return 1L;
    } else {
      return p2 / 8L;
    }
  }

  def alignUp(n: Word, alignment: Word): Word = {
    return ((n - 1) & ~(alignment - 1)) + alignment;
  }

  def alignDown(n: Word, alignment: Word): Word = {
    return n & ~(alignment - 1);
  }
157 158 159 160 161 162

  implicit class MagicalWord(val word: Word) extends AnyVal {
    def alignUpAndAdd(align: Word, size: Word): Word = {
      return alignUp(word, align) + size
    }
  }
163
}