MicroVM.scala 4.81 KB
Newer Older
1 2
package uvm.refimpl

Kunshan Wang's avatar
Kunshan Wang committed
3 4
import scala.collection.mutable.HashSet

5
import uvm._
Kunshan Wang's avatar
Kunshan Wang committed
6
import uvm.utils.IDFactory
Kunshan Wang's avatar
Kunshan Wang committed
7 8
import uvm.ir.textinput.UIRTextReader
import uvm.refimpl.hail.HailScriptLoader
9 10 11
import uvm.refimpl.itpr._
import uvm.refimpl.mem._
import uvm.refimpl.mem.TypeSizes.Word
Kunshan Wang's avatar
Kunshan Wang committed
12
import uvm.refimpl.nat.NativeCallHelper
13
import uvm.staticanalysis.StaticAnalyzer
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
object GCConf {
  val ReComment = """^\s*#.*$""".r
  val ReBlank = """^\s*$""".r
  val ReConf = """^\s*(\w+)=(\w+)\s*$""".r

  def apply(confStr: String): GCConf = {
    var sosSize = MicroVM.DEFAULT_SOS_SIZE
    var losSize = MicroVM.DEFAULT_LOS_SIZE
    var globalSize = MicroVM.DEFAULT_GLOBAL_SIZE
    var stackSize = MicroVM.DEFAULT_GLOBAL_SIZE
    confStr.lines foreach {
      case ReComment() => 
      case ReBlank() =>
      case ReConf(key, value) => {
        key match {
          case "sosSize" => sosSize = value.toLong
          case "losSize" => losSize = value.toLong
          case "globalSize" => globalSize = value.toLong
          case "stackSize" => stackSize = value.toLong
          case _ => throw new UvmRefImplException("Unrecognized option %s".format(key))
        }
      }
    }
    new GCConf(sosSize, losSize, globalSize, stackSize)
  }
}

class GCConf(
  val sosSize: Word = MicroVM.DEFAULT_SOS_SIZE,
  val losSize: Word = MicroVM.DEFAULT_LOS_SIZE,
  val globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE,
  val stackSize: Word = MicroVM.DEFAULT_STACK_SIZE)

48
object MicroVM {
49 50
  val DEFAULT_SOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
  val DEFAULT_LOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
51 52
  val DEFAULT_GLOBAL_SIZE: Word = 1L * 1024L * 1024L; // 1MiB
  val DEFAULT_STACK_SIZE: Word = 63L * 1024L; // 60KiB per stack
53

Kunshan Wang's avatar
Kunshan Wang committed
54
  val FIRST_CLIENT_USABLE_ID: Int = 65536
55

56 57 58 59 60 61 62 63 64 65
  def apply(): MicroVM = {
    val gcConf = new GCConf()
    new MicroVM(gcConf)
  }
  
  def apply(confStr: String): MicroVM = {
    val gcConf = GCConf(confStr)
    new MicroVM(gcConf)
  }
}
Kunshan Wang's avatar
Kunshan Wang committed
66

67
class MicroVM(gcConf: GCConf) {
68 69
  // implicitly injected resources
  private implicit val microVM = this
70

71
  val globalBundle = new GlobalBundle()
72
  val constantPool = new ConstantPool()
73
  val memoryManager = new MemoryManager(gcConf)
Kunshan Wang's avatar
Kunshan Wang committed
74 75

  private implicit val memorySupport = memoryManager.memorySupport
Kunshan Wang's avatar
Kunshan Wang committed
76

77
  implicit val nativeCallHelper = new NativeCallHelper()
Kunshan Wang's avatar
Kunshan Wang committed
78

79
  val threadStackManager = new ThreadStackManager()
80

81
  val trapManager = new TrapManager()
Kunshan Wang's avatar
Kunshan Wang committed
82
  val contexts = new HashSet[MuCtx]()
Kunshan Wang's avatar
Kunshan Wang committed
83

Kunshan Wang's avatar
Kunshan Wang committed
84
  val irReader = new UIRTextReader(new IDFactory(MicroVM.FIRST_CLIENT_USABLE_ID))
Kunshan Wang's avatar
Kunshan Wang committed
85
  val hailScriptLoader = new HailScriptLoader()
86
  val staticAnalyzer = new StaticAnalyzer()
Kunshan Wang's avatar
Kunshan Wang committed
87

88
  {
Kunshan Wang's avatar
Kunshan Wang committed
89 90
    // VOID, BYTE, BYTE_ARRAY: The micro VM allocates stacks on the heap in the large object space.
    // It is represented as a big chunk of byte array.
91
    // So the GC must know about this type because the GC looks up the globalBundle for types.
Kunshan Wang's avatar
Kunshan Wang committed
92 93 94 95 96 97 98 99 100

    // BYTES, BYTES_R, REFS, REFS_R: Types for the @uvm.meta.* common instructions.

    import InternalTypes._
    for (ty <- Seq(VOID, BYTE, BYTE_ARRAY, BYTES, BYTES_R, REFS, REFS_R)) {
      globalBundle.typeNs.add(ty)
    }

    // Some internal constants needed by the HAIL loader
101

Kunshan Wang's avatar
Kunshan Wang committed
102 103 104 105
    for (c <- Seq(NULL_REF_VOID, NULL_IREF_VOID, NULL_FUNCREF_VV, NULL_THREADREF, NULL_STACKREF)) {
      globalBundle.constantNs.add(c)
      constantPool.addGlobalVar(c)
    }
106
  }
107 108 109 110

  /**
   * Add things from a bundle to the Micro VM.
   */
111
  def addBundle(bundle: TrantientBundle) {
112
    staticAnalyzer.checkBundle(bundle, Some(globalBundle))
113

114 115 116 117 118
    globalBundle.merge(bundle);

    for (gc <- bundle.globalCellNs.all) {
      memoryManager.globalMemory.addGlobalCell(gc)
    }
119
    for (ef <- bundle.expFuncNs.all) {
120
      nativeCallHelper.exposeFuncStatic(ef)
121 122
    }
    // Must allocate the memory and expose the functions before making constants.
123 124 125 126
    for (g <- bundle.globalVarNs.all) {
      constantPool.addGlobalVar(g)
    }
  }
Kunshan Wang's avatar
Kunshan Wang committed
127

128
  /**
Kunshan Wang's avatar
Kunshan Wang committed
129
   * Create a new MuCtx. Part of the API.
130
   */
Kunshan Wang's avatar
Kunshan Wang committed
131
  def newContext(): MuCtx = {
Kunshan Wang's avatar
Kunshan Wang committed
132
    val mutator = microVM.memoryManager.heap.makeMutator() // This may trigger GC
Kunshan Wang's avatar
Kunshan Wang committed
133 134
    val ca = new MuCtx(mutator)
    contexts.add(ca)
Kunshan Wang's avatar
Kunshan Wang committed
135 136
    ca
  }
137 138 139
  /**
   * Given a name, get the ID of an identified entity.
   */
Kunshan Wang's avatar
Kunshan Wang committed
140 141 142
  def idOf(name: String): Int = try {
    globalBundle.allNs(name).id
  } catch {
Kunshan Wang's avatar
Kunshan Wang committed
143
    case e: NoSuchElementException => throw new UvmRefImplException("No Mu entity has name %s".format(name), e)
Kunshan Wang's avatar
Kunshan Wang committed
144
  }
Kunshan Wang's avatar
Kunshan Wang committed
145

146 147 148
  /**
   * Given an ID, get the name of an identified entity.
   */
Kunshan Wang's avatar
Kunshan Wang committed
149 150 151
  def nameOf(id: Int): String = try {
    globalBundle.allNs(id).name.get
  } catch {
Kunshan Wang's avatar
Kunshan Wang committed
152
    case e: NoSuchElementException => throw new UvmRefImplException("No Mu entity has ID %d".format(id), e)
Kunshan Wang's avatar
Kunshan Wang committed
153
  }
Kunshan Wang's avatar
Kunshan Wang committed
154

Kunshan Wang's avatar
Kunshan Wang committed
155 156 157 158 159 160 161
  /**
   * Set the trap handler.
   */
  def setTrapHandler(trapHandler: TrapHandler): Unit = {
    trapManager.trapHandler = trapHandler
  }

Kunshan Wang's avatar
Kunshan Wang committed
162 163 164 165 166 167
  /**
   * Execute. This is the external pusher of the execution.
   */
  def execute(): Unit = {
    threadStackManager.execute()
  }
168
}