TypeSizes.scala 5.05 KB
Newer Older
1 2 3 4
package uvm.refimpl.mem

import uvm.types._
import uvm.refimpl.UvmRefImplException
5
import uvm.refimpl.nat.PlatformConstants
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

/**
 * 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 {
49
  type Word = PlatformConstants.Word
50

51 52 53
  val WORD_SIZE_LOG: Word = PlatformConstants.WORD_SIZE_LOG
  val WORD_SIZE_BITS: Word = PlatformConstants.WORD_SIZE_BITS
  val WORD_SIZE_BYTES: Word = PlatformConstants.WORD_SIZE_BYTES
54 55 56 57 58 59 60

  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;

61 62 63 64
  val MARK_MASK = 0x4000000000000000L

  val MOVE_MASK = 0x8000000000000000L

65
  def sizeOf(ty: Type): Word = ty match {
66 67 68 69 70 71
    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
72
    case t @ TypeStruct(ftys)  => structPrefixSizeOf(t, ftys.size)
73 74 75
    case t @ TypeArray(et, l)  => seqPrefixSizeOf(t, l)
    case _: TypeHybrid         => throw new IllegalArgumentException("Hybrid should use hybridSizeOf to probe size")
    case _: TypeVoid           => 0L
76 77 78
    case _: TypeFuncRef        => WORD_SIZE_BYTES
    case _: TypeThreadRef      => WORD_SIZE_BYTES
    case _: TypeStackRef       => WORD_SIZE_BYTES
79 80
    case _: TypeTagRef64       => 8L
    case t @ TypeVector(et, l) => seqPrefixSizeOf(t, l)
81 82
    case _: TypeUPtr           => WORD_SIZE_BYTES
    case _: TypeUFuncPtr       => WORD_SIZE_BYTES
83 84 85
  }

  def alignOf(ty: Type): Word = ty match {
Kunshan Wang's avatar
Kunshan Wang committed
86
    case TypeStruct(ftys) => ftys.map(alignOf).max
87 88 89 90
    case TypeArray(et, _) => alignOf(et)
    case _: TypeHybrid    => throw new IllegalArgumentException("Hybrid should use hybridAlignOf to probe alignment")
    case _: TypeVoid      => 1L
    case _                => sizeOf(ty)
91 92 93
  }

  def hybridSizeOf(ty: TypeHybrid, len: Word): Word = {
Kunshan Wang's avatar
Kunshan Wang committed
94
    val fixedSize = structPrefixSizeOf(ty, ty.fieldTys.size)
95 96 97 98 99 100 101
    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
102
    val fieldAligns = ty.fieldTys.map(alignOf)
103
    val varAlign = alignOf(ty.varTy)
Kunshan Wang's avatar
Kunshan Wang committed
104
    val align = fieldAligns.foldLeft(varAlign)(Math.max)
105 106 107
    return align
  }

Kunshan Wang's avatar
Kunshan Wang committed
108
  def fieldOffsetOf(ty: AbstractStructType, index: Int): Word = {
109
    val fieldType = ty.fieldTys(index)
110
    val fieldAlign = alignOf(fieldType)
111
    val prefixSize = structPrefixSizeOf(ty, index)
112 113 114
    val offset = alignUp(prefixSize, fieldAlign)
    return offset
  }
115

116 117 118 119 120 121 122
  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
  }
123

124
  def varPartOffsetOf(ty: TypeHybrid): Word = {
Kunshan Wang's avatar
Kunshan Wang committed
125
    return alignUp(structPrefixSizeOf(ty, ty.fieldTys.length), alignOf(ty.varTy))
126
  }
127

Kunshan Wang's avatar
Kunshan Wang committed
128
  def structPrefixSizeOf(ty: AbstractStructType, prefixLen: Int): Word = {
129
    val sz = ty.fieldTys.take(prefixLen).foldLeft(0L) { (oldSz, nextTy) =>
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 157 158 159 160 161 162
      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);
  }
Kunshan Wang's avatar
Kunshan Wang committed
163 164 165 166 167 168

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