Commit 7485f52c authored by Kunshan Wang's avatar Kunshan Wang

WIP: load mem data. TODO: relocate

parent 7de5b4b4
......@@ -301,6 +301,7 @@ private[textinput] class InstanceUIRTextReader(idFactory: IDFactory, source: Str
val gc = mkGlobalCell(ty)
val name = gdctx.nam
gc.id = idFactory.getID(name)
logger.info("global cell: id=%d, name=%s".format(gc.id, gc.name))
gc.name = Some(name)
addGlobalCell(gc, toSourceInfo(name))
}
......
......@@ -31,7 +31,8 @@ object MuCtx {
* operations on the Mu VM.
*/
class MuCtx(val ctxID: Int, _mutator: Mutator)(
implicit protected val microVM: MicroVM, memorySupport: MemorySupport) extends ObjectPinner with MuCtxIRBuilderPart {
implicit protected val microVM: MicroVM, memorySupport: MemorySupport)
extends ObjectPinner with MuCtxIRBuilderPart with AutoCloseable {
import MuCtx._
implicit def mutator = _mutator
......@@ -52,6 +53,9 @@ class MuCtx(val ctxID: Int, _mutator: Mutator)(
mutator.close()
microVM.contexts.remove(this)
}
/** Synonym of closeContext, for AutoCloseable. */
override def close(): Unit = closeContext()
/** Load a Mu IR bundle */
def loadBundle(r: Reader): Unit = {
......
......@@ -4,6 +4,8 @@ import java.io._
import java.io.OutputStream
import java.nio.charset.StandardCharsets
import java.nio.file._
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.HashMap
......@@ -28,10 +30,8 @@ import uvm.refimpl.mem.scanning.MemoryFieldHandler
import uvm.refimpl.nat.NativeSupport
import uvm.refimpl.nat.PlatformConstants.Word
import uvm.types._
import uvm.utils.WithUtils.tryWithResource
import java.util.zip.ZipOutputStream
import uvm.utils.IOHelpers
import java.util.zip.ZipEntry
import uvm.utils.WithUtils.tryWithResource
class BootImageBuilder(implicit microVM: MicroVM) {
def makeBootImage(whiteList: Seq[TopLevel], outputFile: String): Unit = {
......@@ -177,11 +177,11 @@ class BootImageWriter(tcb: TransitiveClosureBuilder, outputFile: String)(implici
}
}
val num = if (isGlobal) ty.id else group.allocRecs.length
val num = if (isGlobal) addrToGlobalCell(addr).g.id else group.allocRecs.length
group.dataOS.alignUp(align)
val pos = group.dataOS.position
group.dataOS.copy(addr, size)
group.dataOS.writeFromMemory(addr, size)
val rec = UnitAllocRecord(num, pos, ty, varLen, addr)
group.allocRecs += rec
......@@ -265,7 +265,7 @@ class BootImageWriter(tcb: TransitiveClosureBuilder, outputFile: String)(implici
bundleSerializer.writeUIR(writer)
}
}
private def makeZipPackage(): Unit = {
tryWithResource(new ZipOutputStream(Files.newOutputStream(zipPath))) { zos =>
for (path <- allZipContents) {
......@@ -293,7 +293,7 @@ class AlignedOutputStream(os: OutputStream) extends Closeable {
position = newPos
}
def copy(addr: Long, size: Long): Unit = {
def writeFromMemory(addr: Long, size: Long): Unit = {
var nextAddr = addr
var remain = size
......
......@@ -14,32 +14,52 @@ import scala.collection.mutable.HashMap
import uvm.refimpl.MicroVM
import uvm.utils.WithUtils.tryWithResource
import uvm.utils.MappedIDFactory
import uvm.types.TypeHybrid
import uvm.refimpl.mem.TypeSizes
import uvm.refimpl.nat.NativeSupport
import java.io.Closeable
import uvm.refimpl.nat.PlatformConstants.Word
object BootImageLoader {
val MUTATOR_NAME = "bootimgldr"
}
class BootImageLoader(file: String)(implicit microVM: MicroVM) {
import BootImageLoader._
import BootImageWriter._
private val memoryManager = microVM.memoryManager
private val heap = memoryManager.heap
private val globalMemory = memoryManager.globalMemory
private val constantPool = microVM.constantPool
private implicit val memorySupport = memoryManager.memorySupport
val bootImagePath = Paths.get(file)
val zip = new ZipFile(bootImagePath.toFile())
val objNumToAddr = new HashMap[Long, Word]()
def zipFile(name: String): InputStream = zip.getInputStream(zip.getEntry(name))
def zipFileText(name: String): Reader = new InputStreamReader(zip.getInputStream(zip.getEntry(name)), StandardCharsets.UTF_8)
def zipFileTextBuf(name: String): BufferedReader = new BufferedReader(zipFileText(name))
def load(): Unit = {
loadUIRBundle()
initializeMemory()
}
private def loadUIRBundle(): Unit = {
val map = loadIDNameMap()
val mappedIDFactory = new MappedIDFactory(map)
tryWithResource(zipFileText(UIRBUNDLE_FILE)) { r =>
val bundle = microVM.irReader.read(r, microVM.globalBundle, mappedIDFactory)
microVM.addBundle(bundle)
}
val maxID = map.values.max
microVM.idFactory.setNextID(maxID+1)
microVM.idFactory.setNextID(maxID + 1)
}
private def loadIDNameMap(): Map[String, Int] = {
......@@ -60,4 +80,124 @@ class BootImageLoader(file: String)(implicit microVM: MicroVM) {
}
map
}
private def initializeMemory(): Unit = {
// Disable GC and prevent object movement
heap.gcDisabled = true
allocateAndCopy()
relocate()
// Re-enable GC when we are done.
heap.gcDisabled = false
}
private def allocateAndCopy(): Unit = {
// Initialise global cell and heap objects.
forEachUnit("global") { (ais, ar) =>
val UnitAllocRecord(num, fileOffset, ty, varLen, _) = ar
assert(!ty.isInstanceOf[TypeHybrid], "BUG: hybrid found in global space. num: %d, fileOffset: %d, type: %s".format(
num, fileOffset, ty))
val gID = num.toInt
val g = microVM.globalBundle.globalCellNs(gID)
val addr = globalMemory.addrForGlobalCell(g)
val size = TypeSizes.sizeOf(ty)
ais.readToMemory(addr, size)
}
tryWithResource(heap.makeMutator(MUTATOR_NAME)) { mutator =>
forEachUnit("heap") { (ais, ar) =>
val UnitAllocRecord(num, fileOffset, ty, varLen, _) = ar
val (size, addr) = ty match {
case t: TypeHybrid => {
val sz = TypeSizes.hybridSizeOf(t, varLen)
val ad = mutator.newHybrid(t, varLen)
(sz, ad)
}
case t => {
val sz = TypeSizes.sizeOf(t)
val ad = mutator.newScalar(t)
(sz, ad)
}
}
ais.readToMemory(addr, size)
}
}
}
private def forEachUnit(groupName: String)(f: (AlignedInputStream, UnitAllocRecord) => Unit): Unit = {
tryWithResource(new AlignedInputStream(zipFile(groupName + FILEEXT_DATA))) { dataIS =>
tryWithResource(zipFileTextBuf(groupName + FILEEXT_ALLOC)) { allocIS =>
var finished = false
while (!finished) {
Option(allocIS.readLine()) match {
case None => finished = true
case Some(line) => {
val elems = line.split(",")
val num = elems(0).toLong
val fileOffset = elems(1).toLong
val tyID = elems(2).toInt
val varLen = elems(3).toLong
val tyName = elems(4)
val ty = microVM.globalBundle.typeNs(tyID)
val ar = UnitAllocRecord(num, fileOffset, ty, varLen, 0L)
dataIS.seekTo(fileOffset)
f(dataIS, ar)
}
}
}
}
}
}
private def relocate(): Unit = {
}
}
class AlignedInputStream(is: InputStream) extends Closeable {
var position: Long = 0L
private val BUFFER_SZ = 16384
private val buffer = new Array[Byte](BUFFER_SZ)
def seekTo(newPosition: Long): Unit = {
assert(newPosition >= position)
if (newPosition > position) {
is.skip(newPosition - position)
position = newPosition
}
}
def readToMemory(addr: Long, size: Long): Unit = {
var nextAddr = addr
var remain = size
while (remain > BUFFER_SZ) {
transfer(nextAddr, BUFFER_SZ)
nextAddr += BUFFER_SZ
remain -= BUFFER_SZ
}
if (remain > 0) {
transfer(nextAddr, remain.toInt)
}
position += size
}
private def transfer(addr: Long, size: Int): Unit = {
is.read(buffer, 0, size)
NativeSupport.theMemory.put(addr, buffer, 0, size)
}
def close(): Unit = {
is.close()
}
}
\ No newline at end of file
......@@ -3,3 +3,4 @@ package uvm.refimpl.bootimg
import uvm.refimpl.UvmRuntimeException
class BootImageBuilderException(message: String = null, cause: Throwable = null) extends UvmRuntimeException(message, cause)
class BootImageLoaderException(message: String = null, cause: Throwable = null) extends UvmRuntimeException(message, cause)
......@@ -22,6 +22,12 @@ abstract class Heap {
protected var mustFreeSpace: Boolean = _
protected var gcException: Exception = null
/**
* Set this when GC is not supposed to happen. GC, when seeing this flag set, will throw an exception.
* Used by boot image loader to prevent any object movement during memory initialisation.
*/
var gcDisabled: Boolean = false
def mutatorTriggerAndWaitForGCEnd(mustFreeSpace: Boolean) {
lock.lock()
......
......@@ -9,7 +9,7 @@ object Mutator {
val logger = Logger(LoggerFactory.getLogger(getClass.getName))
}
abstract class Mutator(val name: String)(implicit memorySupport: MemorySupport) {
abstract class Mutator(val name: String)(implicit memorySupport: MemorySupport) extends AutoCloseable {
import Mutator._
def alloc(size: Word, align: Word, headerSize: Word): Word
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment