Commit 50d1de21 authored by Kunshan Wang's avatar Kunshan Wang

Relocating global/heap mem. TODO: test

parent 7485f52c
package uvm.refimpl.bootimg
import java.io.BufferedReader
import java.io.Closeable
import java.io.InputStream
import java.io.InputStreamReader
import java.io.Reader
......@@ -12,13 +13,15 @@ import scala.collection.Map
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
import uvm.refimpl.nat.PlatformConstants.{ Word, WORD_SIZE_BYTES }
import uvm.types.TypeHybrid
import uvm.utils.IOHelpers.forEachLine
import uvm.utils.MappedIDFactory
import uvm.utils.WithUtils.tryWithResource
import uvm.refimpl.itpr.OpHelper
import uvm.Function
object BootImageLoader {
val MUTATOR_NAME = "bootimgldr"
......@@ -28,6 +31,7 @@ class BootImageLoader(file: String)(implicit microVM: MicroVM) {
import BootImageLoader._
import BootImageWriter._
private val globalBundle = microVM.globalBundle
private val memoryManager = microVM.memoryManager
private val heap = memoryManager.heap
private val globalMemory = memoryManager.globalMemory
......@@ -38,6 +42,10 @@ class BootImageLoader(file: String)(implicit microVM: MicroVM) {
val zip = new ZipFile(bootImagePath.toFile())
val objNumToAddr = new HashMap[Long, Word]()
def globalNumToAddr(num: Long): Word = {
val g = globalBundle.globalCellNs(num.toInt)
globalMemory.addrForGlobalCell(g)
}
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)
......@@ -54,7 +62,7 @@ class BootImageLoader(file: String)(implicit microVM: MicroVM) {
val mappedIDFactory = new MappedIDFactory(map)
tryWithResource(zipFileText(UIRBUNDLE_FILE)) { r =>
val bundle = microVM.irReader.read(r, microVM.globalBundle, mappedIDFactory)
val bundle = microVM.irReader.read(r, globalBundle, mappedIDFactory)
microVM.addBundle(bundle)
}
......@@ -99,10 +107,7 @@ class BootImageLoader(file: String)(implicit microVM: MicroVM) {
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 addr = globalNumToAddr(num)
val size = TypeSizes.sizeOf(ty)
ais.readToMemory(addr, size)
......@@ -125,6 +130,8 @@ class BootImageLoader(file: String)(implicit microVM: MicroVM) {
}
}
objNumToAddr(num) = addr
ais.readToMemory(addr, size)
}
}
......@@ -133,30 +140,94 @@ class BootImageLoader(file: String)(implicit microVM: MicroVM) {
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)
}
}
forEachLine(allocIS) { 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 = globalBundle.typeNs(tyID)
val ar = UnitAllocRecord(num, fileOffset, ty, varLen, 0L)
dataIS.seekTo(fileOffset)
f(dataIS, ar)
}
}
}
}
private def relocate(): Unit = {
forEachReloc("global") { rr =>
val FieldRelocRecord(num, fieldOffset, fieldKind, targetKind, targetNum, targetOffset) = rr
val base = globalNumToAddr(num)
relocField(base, fieldOffset, fieldKind, targetKind, targetNum, targetOffset)
}
forEachReloc("heap") { rr =>
val FieldRelocRecord(num, fieldOffset, fieldKind, targetKind, targetNum, targetOffset) = rr
val base = objNumToAddr(num)
relocField(base, fieldOffset, fieldKind, targetKind, targetNum, targetOffset)
}
}
private def forEachReloc(groupName: String)(f: FieldRelocRecord => Unit): Unit = {
tryWithResource(zipFileTextBuf(groupName + FILEEXT_RELOC)) { relocIS =>
forEachLine(relocIS) { line =>
val elems = line.split(",")
val num = elems(0).toLong
val fieldOffset = elems(1).toLong
val fieldKind = elems(2)
val targetKind = elems(3)
val targetNum = elems(4).toLong
val targetOffset = elems(5).toLong
val rr = FieldRelocRecord(num, fieldOffset, fieldKind, targetKind, targetNum, targetOffset)
f(rr)
}
}
}
private def relocField(srcBase: Word, srcOffset: Word, fieldKind: String, targetKind: String, targetNum: Long, targetOffset: Word): Unit = {
val srcFieldAddr = srcBase + srcOffset
fieldKind match {
case AS_REF => {
assert(targetOffset == 0L)
assert(targetKind != TO_FUNC, "BUG: ref field referring to function")
val targetBase = getTargetMemBase(targetKind, targetNum)
memorySupport.storeLong(srcFieldAddr, targetBase)
}
case AS_IREF => {
assert(targetKind != TO_FUNC, "BUG: iref field referring to function")
val targetBase = getTargetMemBase(targetKind, targetNum)
val (irefBase, irefOffset) = targetKind match {
case TO_GLOBAL => (0L, targetBase + targetOffset)
case TO_HEAP => (targetBase, targetOffset)
}
memorySupport.storeLong(srcFieldAddr, irefBase)
memorySupport.storeLong(srcFieldAddr + WORD_SIZE_BYTES, irefOffset)
}
case AS_TAGREF => {
assert(targetOffset == 0L)
assert(targetKind != TO_FUNC, "BUG: tagref64 field referring to function")
val targetBase = getTargetMemBase(targetKind, targetNum)
val oldTR64 = memorySupport.loadLong(srcFieldAddr)
val oldTag = OpHelper.tr64ToTag(oldTR64)
val newTR64 = OpHelper.refToTr64(targetBase, oldTag)
memorySupport.storeLong(srcFieldAddr, newTR64)
}
case AS_FUNCREF => {
assert(targetOffset == 0L)
assert(targetKind == TO_FUNC, "BUG: funcref field referring to memory")
assert(targetNum != 0L, "BUG: funcref target is 0")
memorySupport.storeLong(srcFieldAddr, targetNum)
}
}
}
private def getTargetMemBase(targetKind: String, targetNum: Long): Word = {
targetKind match {
case TO_GLOBAL => globalNumToAddr(targetNum)
case TO_HEAP => objNumToAddr(targetNum)
}
}
}
......
package uvm.utils
import java.io.Reader
import java.io.OutputStream
import java.io.BufferedReader
import java.io.InputStream
import java.io.OutputStream
import java.io.Reader
import WithUtils.tryWithResource
object IOHelpers {
def slurp(r: Reader): String = {
......@@ -21,9 +25,9 @@ object IOHelpers {
sb.toString()
}
private val BYTE_BUFFER_SIZE = 16384
def copy(in: InputStream, out: OutputStream): Unit = {
val buf = new Array[Byte](BYTE_BUFFER_SIZE)
......@@ -37,4 +41,16 @@ object IOHelpers {
}
}
}
def forEachLine(br: BufferedReader)(f: String => Unit): Unit = {
var finished = false
while (!finished) {
Option(br.readLine()) match {
case None => finished = true
case Some(line) => {
f(line)
}
}
}
}
}
\ No newline at end of file
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