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

Kunshan Wang's avatar
Kunshan Wang committed
3
import java.io.OutputStreamWriter
Kunshan Wang's avatar
Kunshan Wang committed
4 5
import java.io.Writer

Kunshan Wang's avatar
Kunshan Wang committed
6 7
import scala.collection.mutable.HashSet

8
import uvm._
Kunshan Wang's avatar
Kunshan Wang committed
9
import uvm.ir.irbuilder.IRBuilder
10
import uvm.ir.irbuilder.IRBuilderListener
Kunshan Wang's avatar
Kunshan Wang committed
11
import uvm.ir.textinput.UIRTextReader
Kunshan Wang's avatar
Kunshan Wang committed
12
import uvm.ir.textoutput.BundleSerializer
Kunshan Wang's avatar
Kunshan Wang committed
13
import uvm.ir.textoutput.DebugBundleSerializer
Kunshan Wang's avatar
Kunshan Wang committed
14
import uvm.refimpl.bootimg.BootImageBuilder
Kunshan Wang's avatar
Kunshan Wang committed
15
import uvm.refimpl.bootimg.BootImageLoader
Kunshan Wang's avatar
Kunshan Wang committed
16
import uvm.refimpl.hail.HailScriptLoader
17
import uvm.refimpl.integerize.IDObjectKeeper
18 19
import uvm.refimpl.itpr._
import uvm.refimpl.mem._
Kunshan Wang's avatar
Kunshan Wang committed
20
import uvm.refimpl.nat.NativeCallHelper
Kunshan Wang's avatar
Kunshan Wang committed
21
import uvm.refimpl.nat.NativeLibraryHolder
22
import uvm.staticanalysis.StaticAnalyzer
23
import uvm.utils.IDFactory
24
import uvm.utils.WithUtils.tryWithResource
Kunshan Wang's avatar
Kunshan Wang committed
25
import uvm.refimpl.bootimg.PrimordialInfo
26 27

object MicroVM {
28 29
  val DEFAULT_SOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
  val DEFAULT_LOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
30 31
  val DEFAULT_GLOBAL_SIZE: Word = 1L * 1024L * 1024L; // 1MiB
  val DEFAULT_STACK_SIZE: Word = 63L * 1024L; // 60KiB per stack
32 33

  def apply(): MicroVM = {
Kunshan Wang's avatar
Kunshan Wang committed
34 35
    val vmConf = new VMConf()
    new MicroVM(vmConf)
36
  }
Kunshan Wang's avatar
Kunshan Wang committed
37

38
  def apply(confStr: String): MicroVM = {
Kunshan Wang's avatar
Kunshan Wang committed
39 40
    val vmConf = VMConf(confStr)
    new MicroVM(vmConf)
41 42
  }
}
Kunshan Wang's avatar
Kunshan Wang committed
43

44
class MicroVM(val vmConf: VMConf) extends IRBuilderListener {
45 46
  // implicitly injected resources
  private implicit val microVM = this
47

48
  val globalBundle = new GlobalBundle()
49
  val constantPool = new ConstantPool()
Kunshan Wang's avatar
Kunshan Wang committed
50

51
  /// Initialise the global bundle and constant pool with (private) pre-loaded stuff
52
  {
Kunshan Wang's avatar
Kunshan Wang committed
53 54
    // 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.
55
    // So the GC must know about this type because the GC looks up the globalBundle for types.
Kunshan Wang's avatar
Kunshan Wang committed
56 57 58 59 60 61 62 63 64

    // 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
65

Kunshan Wang's avatar
Kunshan Wang committed
66 67 68 69
    for (c <- Seq(NULL_REF_VOID, NULL_IREF_VOID, NULL_FUNCREF_VV, NULL_THREADREF, NULL_STACKREF)) {
      globalBundle.constantNs.add(c)
      constantPool.addGlobalVar(c)
    }
70

71
    // Some types required by the RunMu class
72

73 74 75
    for (ty <- Seq(C_INT, C_CHAR, C_CHARP, C_CHARPP)) {
      globalBundle.typeNs.add(ty)
    }
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
  }
  
  val memoryManager = new MemoryManager(vmConf)

  private implicit val memorySupport = memoryManager.memorySupport

  val nativeLibraryHolder = NativeLibraryHolder(vmConf.extraLibs: _*)

  implicit val nativeCallHelper = new NativeCallHelper()

  val threadStackManager = new ThreadStackManager()

  val trapManager = new TrapManager()
  val contexts = new HashSet[MuCtx]()

  val idFactory = IDFactory.newClientIDFactory()
  val irBuilderRegistry = new IDObjectKeeper[IRBuilder]("IR builder")
  val irReader = new UIRTextReader(idFactory, recordSourceInfo = vmConf.sourceInfo)
  val hailScriptLoader = new HailScriptLoader(recordSourceInfo = vmConf.sourceInfo)
  val staticAnalyzer = new StaticAnalyzer()

  val bootImageBuilder = new BootImageBuilder()
  
  /// Bundle building stuff
  
  def newIRBuilder(): IRBuilder = {
Kunshan Wang's avatar
Kunshan Wang committed
102
    val irBuilder = new IRBuilder(irBuilderRegistry.newID(), globalBundle, idFactory, Some(this))
103 104 105 106 107
    irBuilderRegistry.put(irBuilder)
    irBuilder
  }
  
  override def onBundleLoad(irBuilder: IRBuilder, bundle: TrantientBundle): Unit = {
Kunshan Wang's avatar
Kunshan Wang committed
108 109
    addBundle(bundle)
    irBuilderRegistry.remove(irBuilder)
110 111 112
  }
  
  override def onBundleAbort(irBuilder: IRBuilder): Unit = {
Kunshan Wang's avatar
Kunshan Wang committed
113
    irBuilderRegistry.remove(irBuilder)
114
  }
115 116 117 118

  /**
   * Add things from a bundle to the Micro VM.
   */
119
  def addBundle(bundle: TrantientBundle) {
120 121 122 123 124
    if (vmConf.dumpBundle) {
      val dbs = new DebugBundleSerializer(bundle)
      dbs.writeUIR(new OutputStreamWriter(System.err))
    }

125 126 127
    if (vmConf.staticCheck) {
      staticAnalyzer.checkBundle(bundle, Some(globalBundle))
    }
128

129 130 131 132 133
    globalBundle.merge(bundle);

    for (gc <- bundle.globalCellNs.all) {
      memoryManager.globalMemory.addGlobalCell(gc)
    }
134
    for (ef <- bundle.expFuncNs.all) {
135
      nativeCallHelper.exposeFuncStatic(ef)
136 137
    }
    // Must allocate the memory and expose the functions before making constants.
138 139 140 141
    for (g <- bundle.globalVarNs.all) {
      constantPool.addGlobalVar(g)
    }
  }
Kunshan Wang's avatar
Kunshan Wang committed
142 143

  private val contextIDFactory = IDFactory.newOneBasedIDFactory()
Kunshan Wang's avatar
Kunshan Wang committed
144

145
  /**
Kunshan Wang's avatar
Kunshan Wang committed
146
   * Create a new MuCtx. Part of the API.
147
   */
148 149 150 151 152 153 154 155 156
  def newContext(): MuCtx = newContext("user")

  /**
   * Create a new MuCtx. Extended to add a name for debugging.
   */
  def newContext(name: String): MuCtx = {
    val id = contextIDFactory.getID()
    val mutator = microVM.memoryManager.heap.makeMutator("MuCtx-%d-%s".format(id, name)) // This may trigger GC
    val ca = new MuCtx(id, mutator)
Kunshan Wang's avatar
Kunshan Wang committed
157
    contexts.add(ca)
Kunshan Wang's avatar
Kunshan Wang committed
158 159
    ca
  }
160 161 162
  /**
   * Given a name, get the ID of an identified entity.
   */
Kunshan Wang's avatar
Kunshan Wang committed
163
  def idOf(name: MuName): MuID = globalBundle.allNs(name).id
Kunshan Wang's avatar
Kunshan Wang committed
164

165 166 167
  /**
   * Given an ID, get the name of an identified entity.
   */
Kunshan Wang's avatar
Kunshan Wang committed
168
  def nameOf(id: MuID): MuName = globalBundle.allNs(id).name.get
Kunshan Wang's avatar
Kunshan Wang committed
169

Kunshan Wang's avatar
Kunshan Wang committed
170 171 172 173 174 175
  /**
   * Set the trap handler.
   */
  def setTrapHandler(trapHandler: TrapHandler): Unit = {
    trapManager.trapHandler = trapHandler
  }
Kunshan Wang's avatar
Kunshan Wang committed
176

Kunshan Wang's avatar
Kunshan Wang committed
177 178 179
  /**
   * Make boot image.
   */
Kunshan Wang's avatar
Kunshan Wang committed
180
  def makeBootImage(whiteList: Seq[MuID], outputFile: String): Unit = {
Kunshan Wang's avatar
Kunshan Wang committed
181
    val whiteListObjs = whiteList.map(globalBundle.topLevelNs.apply)
Kunshan Wang's avatar
Kunshan Wang committed
182

Kunshan Wang's avatar
Kunshan Wang committed
183
    bootImageBuilder.makeBootImage(whiteListObjs, PrimordialInfo.NO_PRIMORDIAL, Seq(), Seq(), outputFile)
Kunshan Wang's avatar
Kunshan Wang committed
184
  }
Kunshan Wang's avatar
Kunshan Wang committed
185

Kunshan Wang's avatar
Kunshan Wang committed
186
  /**
Kunshan Wang's avatar
Kunshan Wang committed
187
   * Print the global bundle to the writer w.
Kunshan Wang's avatar
Kunshan Wang committed
188 189
   */
  def debugPrintGlobalBundle(w: Writer): Unit = {
Kunshan Wang's avatar
Kunshan Wang committed
190
    val bs = new BundleSerializer(globalBundle, globalBundle.allTopLevels().toSet)
Kunshan Wang's avatar
Kunshan Wang committed
191 192
    bs.writeUIR(w)
  }
Kunshan Wang's avatar
Kunshan Wang committed
193 194 195 196 197 198 199 200

  /**
   * Print the global bundle to stderr.
   */
  def debugPrintGlobalBundle(): Unit = {
    debugPrintGlobalBundle(new OutputStreamWriter(System.err))
  }

Kunshan Wang's avatar
Kunshan Wang committed
201 202 203 204
  /**
   * Load from a boot image.
   */
  def loadBootImage(file: String): Unit = {
205 206 207
    tryWithResource(new BootImageLoader(file)) { bil =>
      bil.load()
    }
Kunshan Wang's avatar
Kunshan Wang committed
208
  }
Kunshan Wang's avatar
Kunshan Wang committed
209

Kunshan Wang's avatar
Kunshan Wang committed
210 211 212 213 214 215
  /**
   * Execute. This is the external pusher of the execution.
   */
  def execute(): Unit = {
    threadStackManager.execute()
  }
Kunshan Wang's avatar
Kunshan Wang committed
216 217 218 219 220 221 222

  // Automatically load the boot image if provided
  {
    vmConf.bootImg foreach { fileName =>
      loadBootImage(fileName)
    }
  }
223
}