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

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

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

7
import uvm._
Kunshan Wang's avatar
Kunshan Wang committed
8 9
import uvm.ir.irbuilder.IRBuilder
import uvm.ir.irbuilder.IRNode
Kunshan Wang's avatar
Kunshan Wang committed
10
import uvm.ir.textinput.UIRTextReader
Kunshan Wang's avatar
Kunshan Wang committed
11
import uvm.ir.textoutput.BundleSerializer
Kunshan Wang's avatar
Kunshan Wang committed
12
import uvm.refimpl.hail.HailScriptLoader
13 14 15
import uvm.refimpl.itpr._
import uvm.refimpl.mem._
import uvm.refimpl.mem.TypeSizes.Word
Kunshan Wang's avatar
Kunshan Wang committed
16
import uvm.refimpl.nat.NativeCallHelper
Kunshan Wang's avatar
Kunshan Wang committed
17
import uvm.refimpl.nat.NativeLibraryHolder
18
import uvm.staticanalysis.StaticAnalyzer
19
import uvm.utils.IDFactory
20
import uvm.refimpl.bootimg.BootImageBuilder
21 22

object MicroVM {
23 24
  val DEFAULT_SOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
  val DEFAULT_LOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
25 26
  val DEFAULT_GLOBAL_SIZE: Word = 1L * 1024L * 1024L; // 1MiB
  val DEFAULT_STACK_SIZE: Word = 63L * 1024L; // 60KiB per stack
27

Kunshan Wang's avatar
Kunshan Wang committed
28
  val FIRST_CLIENT_USABLE_ID: Int = 65536
29

30
  def apply(): MicroVM = {
Kunshan Wang's avatar
Kunshan Wang committed
31 32
    val vmConf = new VMConf()
    new MicroVM(vmConf)
33 34 35
  }
  
  def apply(confStr: String): MicroVM = {
Kunshan Wang's avatar
Kunshan Wang committed
36 37
    val vmConf = VMConf(confStr)
    new MicroVM(vmConf)
38 39
  }
}
Kunshan Wang's avatar
Kunshan Wang committed
40

Kunshan Wang's avatar
Kunshan Wang committed
41
class MicroVM(vmConf: VMConf) {
42 43
  // implicitly injected resources
  private implicit val microVM = this
44

45
  val globalBundle = new GlobalBundle()
46
  val constantPool = new ConstantPool()
Kunshan Wang's avatar
Kunshan Wang committed
47
  val memoryManager = new MemoryManager(vmConf)
Kunshan Wang's avatar
Kunshan Wang committed
48 49

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

Kunshan Wang's avatar
Kunshan Wang committed
51 52
  val nativeLibraryHolder = NativeLibraryHolder(vmConf.extraLibs: _*)
  
53
  implicit val nativeCallHelper = new NativeCallHelper()
Kunshan Wang's avatar
Kunshan Wang committed
54

55
  val threadStackManager = new ThreadStackManager()
56

57
  val trapManager = new TrapManager()
Kunshan Wang's avatar
Kunshan Wang committed
58
  val contexts = new HashSet[MuCtx]()
Kunshan Wang's avatar
Kunshan Wang committed
59

60 61
  val idFactory = new IDFactory(MicroVM.FIRST_CLIENT_USABLE_ID)
  val irBuilder = new IRBuilder(globalBundle, idFactory)
62
  val irNodeRegistry = new SequentialObjectKeeper[IRNode]()
63
  val irReader = new UIRTextReader(idFactory, recordSourceInfo=vmConf.sourceInfo)
64
  val hailScriptLoader = new HailScriptLoader(recordSourceInfo=vmConf.sourceInfo)
65
  val staticAnalyzer = new StaticAnalyzer()
66 67
  
  val bootImageBuilder = new BootImageBuilder()
Kunshan Wang's avatar
Kunshan Wang committed
68

69
  {
Kunshan Wang's avatar
Kunshan Wang committed
70 71
    // 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.
72
    // So the GC must know about this type because the GC looks up the globalBundle for types.
Kunshan Wang's avatar
Kunshan Wang committed
73 74 75 76 77 78 79 80 81

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

Kunshan Wang's avatar
Kunshan Wang committed
83 84 85 86
    for (c <- Seq(NULL_REF_VOID, NULL_IREF_VOID, NULL_FUNCREF_VV, NULL_THREADREF, NULL_STACKREF)) {
      globalBundle.constantNs.add(c)
      constantPool.addGlobalVar(c)
    }
87
  }
88 89 90 91

  /**
   * Add things from a bundle to the Micro VM.
   */
92
  def addBundle(bundle: TrantientBundle) {
93 94 95
    if (vmConf.staticCheck) {
      staticAnalyzer.checkBundle(bundle, Some(globalBundle))
    }
96

97 98 99 100 101
    globalBundle.merge(bundle);

    for (gc <- bundle.globalCellNs.all) {
      memoryManager.globalMemory.addGlobalCell(gc)
    }
102
    for (ef <- bundle.expFuncNs.all) {
103
      nativeCallHelper.exposeFuncStatic(ef)
104 105
    }
    // Must allocate the memory and expose the functions before making constants.
106 107 108 109
    for (g <- bundle.globalVarNs.all) {
      constantPool.addGlobalVar(g)
    }
  }
110 111
  
  private val contextIDFactory = new IDFactory(1)
Kunshan Wang's avatar
Kunshan Wang committed
112

113
  /**
Kunshan Wang's avatar
Kunshan Wang committed
114
   * Create a new MuCtx. Part of the API.
115
   */
116 117 118 119 120 121 122 123 124
  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
125
    contexts.add(ca)
Kunshan Wang's avatar
Kunshan Wang committed
126 127
    ca
  }
128 129 130
  /**
   * Given a name, get the ID of an identified entity.
   */
Kunshan Wang's avatar
Kunshan Wang committed
131
  def idOf(name: String): Int = globalBundle.allNs(name).id
Kunshan Wang's avatar
Kunshan Wang committed
132

133 134 135
  /**
   * Given an ID, get the name of an identified entity.
   */
Kunshan Wang's avatar
Kunshan Wang committed
136
  def nameOf(id: Int): String = globalBundle.allNs(id).name.get
Kunshan Wang's avatar
Kunshan Wang committed
137

Kunshan Wang's avatar
Kunshan Wang committed
138 139 140 141 142 143
  /**
   * Set the trap handler.
   */
  def setTrapHandler(trapHandler: TrapHandler): Unit = {
    trapManager.trapHandler = trapHandler
  }
Kunshan Wang's avatar
Kunshan Wang committed
144 145 146 147 148
  
  /**
   * Make boot image.
   */
  def makeBootImage(whiteList: Seq[Int], outputFile: String): Unit = {
149 150 151 152 153 154 155 156 157 158 159
    val whiteListObjs = whiteList.map { id =>
      val obj = globalBundle.allNs(id)
      obj match {
        case tl: TopLevel => tl
        case _ => throw new UvmRuntimeException(
            "White list may only contain top-level definitions. Entity ID %d%s is a %s".format(
                obj.id, obj.name.map(n => s" (${n})").getOrElse(""), obj.getClass.getName))
      }
    }
    
    bootImageBuilder.makeBootImage(whiteListObjs, outputFile)
Kunshan Wang's avatar
Kunshan Wang committed
160
  }
Kunshan Wang's avatar
Kunshan Wang committed
161 162 163 164 165 166 167 168
  
  /**
   * 
   */
  def debugPrintGlobalBundle(w: Writer): Unit = {
    val bs = new BundleSerializer(globalBundle, None)
    bs.writeUIR(w)
  }
Kunshan Wang's avatar
Kunshan Wang committed
169

Kunshan Wang's avatar
Kunshan Wang committed
170 171 172 173 174 175
  /**
   * Execute. This is the external pusher of the execution.
   */
  def execute(): Unit = {
    threadStackManager.execute()
  }
176
}