To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

Commit 58cf0076 authored by Kunshan Wang's avatar Kunshan Wang
Browse files

Fixes transitive closure. Runs bootimg echo.

parent 10171176
...@@ -22,54 +22,17 @@ object EntityUtils { ...@@ -22,54 +22,17 @@ object EntityUtils {
def isMetaEntity(id: Int): Boolean = { def isMetaEntity(id: Int): Boolean = {
id < 65536 id < 65536
} }
def isMetaEntity(obj: Identified): Boolean = { def isMetaEntity(obj: Identified): Boolean = {
isMetaEntity(obj.id) isMetaEntity(obj.id)
} }
} }
class BundleSerializer(val bundle: GlobalBundle, val whiteList: Set[TopLevel]) { abstract class AbstractBundleSerializer(bundle: Bundle) {
import EntityUtils._ import EntityUtils._
import BundleSerializer._ import AbstractBundleSerializer._
def filter(obj: TopLevel): Boolean = { def writeUIR(sb: StringBuilder): Unit
!isMetaEntity(obj) && whiteList.contains(obj)
}
def writeIDNameMap(output: Writer): Unit = {
val sb = new StringBuilder()
writeIDNameMap(sb)
output.append(sb)
output.flush()
}
def writeIDNameMap(output: StringBuilder): Unit = {
for (obj <- whiteList if !isMetaEntity(obj)) {
writeIDNamePair(obj, output)
obj match {
case func: Function => {
bundle.funcToVers(func).headOption match {
case Some(fv) => {
writeIDNamePair(fv, output)
fv.bbs foreach { bb =>
writeIDNamePair(bb, output)
bb.localVarNs.all foreach { lv => writeIDNamePair(lv, output) }
bb.insts foreach { inst => writeIDNamePair(inst, output) }
}
}
case None => // ignore
}
}
case _ => // ignore
}
}
}
private def writeIDNamePair(obj: Identified, output: StringBuilder): Unit = {
val id = obj.id
val name = getName(obj)
output.append("%d,%s\n".format(id, name))
}
def writeUIR(output: Writer): Unit = { def writeUIR(output: Writer): Unit = {
val sb = new StringBuilder() val sb = new StringBuilder()
...@@ -78,16 +41,6 @@ class BundleSerializer(val bundle: GlobalBundle, val whiteList: Set[TopLevel]) { ...@@ -78,16 +41,6 @@ class BundleSerializer(val bundle: GlobalBundle, val whiteList: Set[TopLevel]) {
output.flush() output.flush()
} }
def writeUIR(output: StringBuilder): Unit = {
for (obj <- bundle.typeNs.all if filter(obj)) { writeType(obj, output) }
for (obj <- bundle.funcSigNs.all if filter(obj)) { writeSig(obj, output) }
for (obj <- bundle.constantNs.all if filter(obj)) { writeConst(obj, output) }
for (obj <- bundle.globalCellNs.all if filter(obj)) { writeGlobal(obj, output) }
for (obj <- bundle.expFuncNs.all if filter(obj)) { writeExpFunc(obj, output) }
for (obj <- bundle.funcNs.all if filter(obj)) { writeFunc(obj, output) }
}
def writeType(ty: Type, output: StringBuilder): Unit = { def writeType(ty: Type, output: StringBuilder): Unit = {
val ctor = ty match { val ctor = ty match {
case TypeInt(l) => s"int<${l}>" case TypeInt(l) => s"int<${l}>"
...@@ -141,16 +94,16 @@ class BundleSerializer(val bundle: GlobalBundle, val whiteList: Set[TopLevel]) { ...@@ -141,16 +94,16 @@ class BundleSerializer(val bundle: GlobalBundle, val whiteList: Set[TopLevel]) {
} }
def writeFunc(func: Function, output: StringBuilder): Unit = { def writeFunc(func: Function, output: StringBuilder): Unit = {
bundle.funcToVers(func).headOption match { output.append(s".funcdecl ${func.n} <${func.sig.n}>\n")
case None => }
output.append(s".funcdecl ${func.n} <${func.sig.n}>\n")
case Some(ver) => def writeFuncVer(ver: FuncVer, output: StringBuilder): Unit = {
output.append(s".funcdef ${func.n} VERSION ${ver.n} <${func.sig.n}> {\n") val func = ver.func
for (bb <- ver.bbs) { output.append(s".funcdef ${func.n} VERSION ${ver.n} <${func.sig.n}> {\n")
writeBB(bb, output) for (bb <- ver.bbs) {
} writeBB(bb, output)
output.append("}\n")
} }
output.append("}\n")
} }
def norParamToString(p: NorParam): String = { def norParamToString(p: NorParam): String = {
...@@ -225,7 +178,7 @@ class BundleSerializer(val bundle: GlobalBundle, val whiteList: Set[TopLevel]) { ...@@ -225,7 +178,7 @@ class BundleSerializer(val bundle: GlobalBundle, val whiteList: Set[TopLevel]) {
} }
} }
object BundleSerializer { object AbstractBundleSerializer {
import EntityUtils._ import EntityUtils._
def destToString(dest: DestClause): String = { def destToString(dest: DestClause): String = {
...@@ -295,4 +248,89 @@ object BundleSerializer { ...@@ -295,4 +248,89 @@ object BundleSerializer {
def p: String = if (value) "PTR" else "" def p: String = if (value) "PTR" else ""
def w: String = if (value) "WEAK" else "" def w: String = if (value) "WEAK" else ""
} }
}
/**
* This class serialises TrantientBundle, suitable for debugging (the dumpBundle VMConf option uses this).
*/
class DebugBundleSerializer(val bundle: TrantientBundle) extends AbstractBundleSerializer(bundle) {
def writeUIR(output: StringBuilder): Unit = {
for (obj <- bundle.typeNs.all) { writeType(obj, output) }
for (obj <- bundle.funcSigNs.all) { writeSig(obj, output) }
for (obj <- bundle.constantNs.all) { writeConst(obj, output) }
for (obj <- bundle.globalCellNs.all) { writeGlobal(obj, output) }
for (obj <- bundle.expFuncNs.all) { writeExpFunc(obj, output) }
val funcSet = bundle.funcNs.all.toSet
val verFuncSet = bundle.funcVerNs.all.map(_.func).toSet
val declSet = funcSet diff verFuncSet
for (obj <- declSet) { writeFunc(obj, output) }
for (obj <- bundle.funcVerNs.all) { writeFuncVer(obj, output) }
}
}
/**
* This class serialises GlobalBundle using a whiteList of top-levels, suitable for building boot image.
*/
class BundleSerializer(val bundle: GlobalBundle, val whiteList: Set[TopLevel]) extends AbstractBundleSerializer(bundle) {
import EntityUtils._
import AbstractBundleSerializer._
def filter(obj: TopLevel): Boolean = {
!isMetaEntity(obj) && whiteList.contains(obj)
}
def writeIDNameMap(output: Writer): Unit = {
val sb = new StringBuilder()
writeIDNameMap(sb)
output.append(sb)
output.flush()
}
def writeIDNameMap(output: StringBuilder): Unit = {
for (obj <- whiteList if !isMetaEntity(obj)) {
writeIDNamePair(obj, output)
obj match {
case func: Function => {
bundle.funcToVers(func).headOption match {
case Some(fv) => {
writeIDNamePair(fv, output)
fv.bbs foreach { bb =>
writeIDNamePair(bb, output)
bb.localVarNs.all foreach { lv => writeIDNamePair(lv, output) }
bb.insts foreach { inst => writeIDNamePair(inst, output) }
}
}
case None => // ignore
}
}
case _ => // ignore
}
}
}
private def writeIDNamePair(obj: Identified, output: StringBuilder): Unit = {
val id = obj.id
val name = getName(obj)
output.append("%d,%s\n".format(id, name))
}
def writeUIR(output: StringBuilder): Unit = {
for (obj <- bundle.typeNs.all if filter(obj)) { writeType(obj, output) }
for (obj <- bundle.funcSigNs.all if filter(obj)) { writeSig(obj, output) }
for (obj <- bundle.constantNs.all if filter(obj)) { writeConst(obj, output) }
for (obj <- bundle.globalCellNs.all if filter(obj)) { writeGlobal(obj, output) }
for (obj <- bundle.expFuncNs.all if filter(obj)) { writeExpFunc(obj, output) }
for (obj <- bundle.funcNs.all if filter(obj)) { writeFuncWithMaybeVersion(obj, output) }
}
def writeFuncWithMaybeVersion(func: Function, output: StringBuilder): Unit = {
bundle.funcToVers(func).headOption match {
case None => writeFunc(func, output)
case Some(ver) => writeFuncVer(ver, output)
}
}
} }
\ No newline at end of file
...@@ -22,6 +22,7 @@ import uvm.refimpl.nat.NativeLibraryHolder ...@@ -22,6 +22,7 @@ import uvm.refimpl.nat.NativeLibraryHolder
import uvm.staticanalysis.StaticAnalyzer import uvm.staticanalysis.StaticAnalyzer
import uvm.utils.IDFactory import uvm.utils.IDFactory
import uvm.utils.WithUtils.tryWithResource import uvm.utils.WithUtils.tryWithResource
import uvm.ir.textoutput.DebugBundleSerializer
object MicroVM { object MicroVM {
val DEFAULT_SOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB val DEFAULT_SOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
...@@ -92,6 +93,11 @@ class MicroVM(val vmConf: VMConf) { ...@@ -92,6 +93,11 @@ class MicroVM(val vmConf: VMConf) {
* Add things from a bundle to the Micro VM. * Add things from a bundle to the Micro VM.
*/ */
def addBundle(bundle: TrantientBundle) { def addBundle(bundle: TrantientBundle) {
if (vmConf.dumpBundle) {
val dbs = new DebugBundleSerializer(bundle)
dbs.writeUIR(new OutputStreamWriter(System.err))
}
if (vmConf.staticCheck) { if (vmConf.staticCheck) {
staticAnalyzer.checkBundle(bundle, Some(globalBundle)) staticAnalyzer.checkBundle(bundle, Some(globalBundle))
} }
......
...@@ -87,6 +87,12 @@ object VMConfParser { ...@@ -87,6 +87,12 @@ object VMConfParser {
parser = sizeWithSuffix, parser = sizeWithSuffix,
default = VMConf.DEFAULT_CONF.stackSize) default = VMConf.DEFAULT_CONF.stackSize)
val dumpBundle = opt[Boolean](
name = "dumpBundle",
desc = """Dump the bundle when a bundle is loaded.""",
parser = parseBoolean,
default = VMConf.DEFAULT_CONF.staticCheck)
val staticCheck = opt[Boolean]( val staticCheck = opt[Boolean](
name = "staticCheck", name = "staticCheck",
desc = """Run static checker after each bundle is loaded.""", desc = """Run static checker after each bundle is loaded.""",
...@@ -153,6 +159,7 @@ object VMConf { ...@@ -153,6 +159,7 @@ object VMConf {
losSize = VMConfParser.losSize(kvMap), losSize = VMConfParser.losSize(kvMap),
globalSize = VMConfParser.globalSize(kvMap), globalSize = VMConfParser.globalSize(kvMap),
stackSize = VMConfParser.stackSize(kvMap), stackSize = VMConfParser.stackSize(kvMap),
dumpBundle = VMConfParser.dumpBundle(kvMap),
staticCheck = VMConfParser.staticCheck(kvMap), staticCheck = VMConfParser.staticCheck(kvMap),
sourceInfo = VMConfParser.sourceInfo(kvMap), sourceInfo = VMConfParser.sourceInfo(kvMap),
extraLibs = VMConfParser.extraLibs(kvMap), extraLibs = VMConfParser.extraLibs(kvMap),
...@@ -177,6 +184,7 @@ class VMConf( ...@@ -177,6 +184,7 @@ class VMConf(
val losSize: Word = MicroVM.DEFAULT_LOS_SIZE, val losSize: Word = MicroVM.DEFAULT_LOS_SIZE,
val globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE, val globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE,
val stackSize: Word = MicroVM.DEFAULT_STACK_SIZE, val stackSize: Word = MicroVM.DEFAULT_STACK_SIZE,
val dumpBundle: Boolean = false,
val staticCheck: Boolean = true, val staticCheck: Boolean = true,
val sourceInfo: Boolean = false, val sourceInfo: Boolean = false,
val extraLibs: Seq[String] = Seq(), val extraLibs: Seq[String] = Seq(),
......
...@@ -47,18 +47,40 @@ object TransitiveClosureBuilder { ...@@ -47,18 +47,40 @@ object TransitiveClosureBuilder {
val logger = Logger(LoggerFactory.getLogger(getClass.getName)) val logger = Logger(LoggerFactory.getLogger(getClass.getName))
implicit class RichTransitiveClosure[T <: Identified](val tc: TransitiveClosure[T]) extends AnyVal { implicit class RichTransitiveClosure[T <: Identified](val tc: TransitiveClosure[T]) extends AnyVal {
def ?=(elem: SSAVariable) = { def ?=(elem: SSAVariable): TransitiveClosure[T] = {
if (elem.isInstanceOf[GlobalVariable]) { if (elem.isInstanceOf[GlobalVariable]) {
tc += elem.asInstanceOf[T] tc += elem.asInstanceOf[T]
} }
tc tc
} }
def ??=(elems: Seq[SSAVariable]) = { def ??=(elems: Seq[SSAVariable]): TransitiveClosure[T] = {
for (elem <- elems) { for (elem <- elems) {
this ?= elem this ?= elem
} }
tc tc
} }
def ??=(dest: DestClause): TransitiveClosure[T] = {
this ??= dest.args
tc
}
def ??=(maybeExcClause: Option[ExcClause]): TransitiveClosure[T] = {
maybeExcClause foreach { excClause =>
this ??= excClause.nor.args ??= excClause.exc.args
}
tc
}
def ???=(maybeElem: Option[SSAVariable]): TransitiveClosure[T] = { // More ? to work around type erasure
for (elem <- maybeElem) {
this ?= elem
}
tc
}
def ????=(maybeDest: Option[DestClause]): TransitiveClosure[T] = {
for (dest <- maybeDest) {
this ??= dest.args
}
tc
}
} }
case class GlobalCellRec(begin: Word, end: Word, g: GlobalCell) case class GlobalCellRec(begin: Word, end: Word, g: GlobalCell)
...@@ -203,14 +225,14 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr ...@@ -203,14 +225,14 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr
} }
private def visitInstruction(inst: Instruction): Unit = inst match { private def visitInstruction(inst: Instruction): Unit = inst match {
case InstBinOp(op, opndTy, op1, op2, excClause) => tls += opndTy ?= op1 ?= op2 case InstBinOp(op, opndTy, op1, op2, excClause) => tls += opndTy ?= op1 ?= op2 ??= excClause
case InstCmp(op, opndTy, op1, op2) => tls += opndTy ?= op1 ?= op2 case InstCmp(op, opndTy, op1, op2) => tls += opndTy ?= op1 ?= op2
case InstConv(op, fromTy, toTy, opnd) => tls += fromTy += toTy ?= opnd case InstConv(op, fromTy, toTy, opnd) => tls += fromTy += toTy ?= opnd
case InstSelect(condTy, opndTy, cond, ifTrue, ifFalse) => tls += condTy += opndTy ?= cond ?= ifTrue ?= ifFalse case InstSelect(condTy, opndTy, cond, ifTrue, ifFalse) => tls += condTy += opndTy ?= cond ?= ifTrue ?= ifFalse
case InstBranch(dest) => case InstBranch(dest) => tls ??= dest
case InstBranch2(cond, ifTrue, ifFalse) => tls ?= cond case InstBranch2(cond, ifTrue, ifFalse) => tls ?= cond ??= ifTrue ??= ifFalse
case i @ InstSwitch(opndTy, opnd, defDest, cases) => tls += opndTy ?= opnd ??= cases.map(_._1) case i @ InstSwitch(opndTy, opnd, defDest, cases) => tls += opndTy ?= opnd ??= defDest ??= cases.map(_._1)
case InstCall(sig, callee, argList, excClause, keepalives) => tls += sig ?= callee ??= argList case InstCall(sig, callee, argList, excClause, keepalives) => tls += sig ?= callee ??= argList ??= excClause
case InstTailCall(sig, callee, argList) => tls += sig ?= callee ??= argList case InstTailCall(sig, callee, argList) => tls += sig ?= callee ??= argList
case InstRet(funcVer, retVals) => tls ??= retVals case InstRet(funcVer, retVals) => tls ??= retVals
case InstThrow(excVal) => tls ?= excVal case InstThrow(excVal) => tls ?= excVal
...@@ -219,33 +241,32 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr ...@@ -219,33 +241,32 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr
case InstExtractElement(seqTy, indTy, opnd, index) => tls += seqTy += indTy ?= opnd ?= index case InstExtractElement(seqTy, indTy, opnd, index) => tls += seqTy += indTy ?= opnd ?= index
case InstInsertElement(seqTy, indTy, opnd, index, newVal) => tls += seqTy += indTy ?= opnd ?= index ?= newVal case InstInsertElement(seqTy, indTy, opnd, index, newVal) => tls += seqTy += indTy ?= opnd ?= index ?= newVal
case InstShuffleVector(vecTy, maskTy, vec1, vec2, mask) => tls += vecTy += maskTy ?= vec1 ?= vec2 ?= mask case InstShuffleVector(vecTy, maskTy, vec1, vec2, mask) => tls += vecTy += maskTy ?= vec1 ?= vec2 ?= mask
case InstNew(allocTy, excClause) => tls += allocTy case InstNew(allocTy, excClause) => tls += allocTy ??= excClause
case InstNewHybrid(allocTy, lenTy, length, excClause) => tls += allocTy += lenTy ?= length case InstNewHybrid(allocTy, lenTy, length, excClause) => tls += allocTy += lenTy ?= length ??= excClause
case InstAlloca(allocTy, excClause) => tls += allocTy case InstAlloca(allocTy, excClause) => tls += allocTy ??= excClause
case InstAllocaHybrid(allocTy, lenTy, length, excClause) => tls += allocTy += lenTy ?= length case InstAllocaHybrid(allocTy, lenTy, length, excClause) => tls += allocTy += lenTy ?= length ??= excClause
case InstGetIRef(referentTy, opnd) => tls += referentTy ?= opnd case InstGetIRef(referentTy, opnd) => tls += referentTy ?= opnd
case InstGetFieldIRef(ptr, referentTy, index, opnd) => tls += referentTy ?= opnd case InstGetFieldIRef(ptr, referentTy, index, opnd) => tls += referentTy ?= opnd
case InstGetElemIRef(ptr, referentTy, indTy, opnd, index) => tls += referentTy += indTy ?= opnd ?= index case InstGetElemIRef(ptr, referentTy, indTy, opnd, index) => tls += referentTy += indTy ?= opnd ?= index
case InstShiftIRef(ptr, referentTy, offTy, opnd, offset) => tls += referentTy += offTy ?= opnd ?= offset case InstShiftIRef(ptr, referentTy, offTy, opnd, offset) => tls += referentTy += offTy ?= opnd ?= offset
case InstGetVarPartIRef(ptr, referentTy, opnd) => tls += referentTy ?= opnd case InstGetVarPartIRef(ptr, referentTy, opnd) => tls += referentTy ?= opnd
case InstLoad(ptr, ord, referentTy, loc, excClause) => tls += referentTy ?= loc case InstLoad(ptr, ord, referentTy, loc, excClause) => tls += referentTy ?= loc ??= excClause
case InstStore(ptr, ord, referentTy, loc, newVal, excClause) => tls += referentTy ?= loc ?= newVal case InstStore(ptr, ord, referentTy, loc, newVal, excClause) => tls += referentTy ?= loc ?= newVal ??= excClause
case InstCmpXchg(ptr, weak, ordSucc, ordFail, referentTy, loc, expected, desired, excClause) // This line is long ... case InstCmpXchg(ptr, weak, ordSucc, ordFail, referentTy, loc, expected, desired, excClause) // This line is long ...
=> tls += referentTy ?= loc ?= expected ?= desired => tls += referentTy ?= loc ?= expected ?= desired ??= excClause
case InstAtomicRMW(ptr, ord, op, referentTy, loc, opnd, excClause) => tls += referentTy ?= loc ?= opnd case InstAtomicRMW(ptr, ord, op, referentTy, loc, opnd, excClause) => tls += referentTy ?= loc ?= opnd ??= excClause
case InstFence(ord) => case InstFence(ord) =>
case InstTrap(retTys, excClause, keepalives) => tls ++= retTys case InstTrap(retTys, excClause, keepalives) => tls ++= retTys ??= excClause
case InstWatchPoint(wpID, retTys, dis, ena, exc, keepalives) => tls ++= retTys case InstWatchPoint(wpID, retTys, dis, ena, exc, keepalives) => tls ++= retTys ??= dis ??= ena ????= exc
case InstWPBranch(wpID, dis, ena) => case InstWPBranch(wpID, dis, ena) => tls ??= dis ??= ena
case InstCCall(callConv, funcTy, sig, callee, argList, excClause, keepalives) // This line is long, too... case InstCCall(callConv, funcTy, sig, callee, argList, excClause, keepalives) // This line is long, too...
=> tls += funcTy += sig ?= callee ??= argList => tls += funcTy += sig ?= callee ??= argList ??= excClause
case InstNewThread(stack, threadLocal, newStackAction, excClause) => { case InstNewThread(stack, threadLocal, newStackAction, excClause) => {
tls ?= stack tls ?= stack ???= threadLocal ??= excClause
threadLocal.foreach(tls.?=)
visitNewStackAction(newStackAction) visitNewStackAction(newStackAction)
} }
case InstSwapStack(swappee, curStackAction, newStackAction, excClause, keepalives) => { case InstSwapStack(swappee, curStackAction, newStackAction, excClause, keepalives) => {
tls ?= swappee tls ?= swappee ??= excClause
curStackAction match { curStackAction match {
case RetWith(ts) => tls ++= ts case RetWith(ts) => tls ++= ts
case KillOld() => case KillOld() =>
...@@ -253,7 +274,7 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr ...@@ -253,7 +274,7 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr
visitNewStackAction(newStackAction) visitNewStackAction(newStackAction)
} }
case InstCommInst(ci, flagList, typeList, funcSigList, argList, excClause, keepalives) => case InstCommInst(ci, flagList, typeList, funcSigList, argList, excClause, keepalives) =>
tls ++= typeList ++= funcSigList ??= argList tls ++= typeList ++= funcSigList ??= argList ??= excClause
case _ => throw new BootImageBuilderException("Unknown instruction: " + inst.getClass.getName) case _ => throw new BootImageBuilderException("Unknown instruction: " + inst.getClass.getName)
} }
...@@ -307,10 +328,10 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr ...@@ -307,10 +328,10 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr
if (largeObjectSpace.isInSpace(toOffset)) { if (largeObjectSpace.isInSpace(toOffset)) {
throw new BootImageBuilderException(("Error: non-object iref to LOS found. This is probably a reference to " + throw new BootImageBuilderException(("Error: non-object iref to LOS found. This is probably a reference to " +
"a stack cell (ALLOCA). It should not exist during boot image building. source: [0x%x + 0x%x] -> dest 0x%x").format( "a stack cell (ALLOCA). It should not exist during boot image building. source: [0x%x + 0x%x] -> dest 0x%x").format(
objRef, iRef, toOffset)) objRef, iRef, toOffset))
} else { } else {
throw new BootImageBuilderException(("Error: non-object iref not referring to global. source: [0x%x + 0x%x] -> dest 0x%x").format( throw new BootImageBuilderException(("Error: non-object iref not referring to global. source: [0x%x + 0x%x] -> dest 0x%x").format(
objRef, iRef, toOffset)) objRef, iRef, toOffset))
} }
} }
} else { } else {
...@@ -319,7 +340,7 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr ...@@ -319,7 +340,7 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr
} }
} }
} }
override def visitTagRefField(objRef: Word, iRef: Word, toObj: Word): Unit = { override def visitTagRefField(objRef: Word, iRef: Word, toObj: Word): Unit = {
if (toObj != 0L) { if (toObj != 0L) {
allocs += toObj allocs += toObj
...@@ -329,18 +350,18 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr ...@@ -329,18 +350,18 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr
override def visitFuncRefField(objRef: Word, iRef: Word, toFunc: Option[Function]): Unit = { override def visitFuncRefField(objRef: Word, iRef: Word, toFunc: Option[Function]): Unit = {
toFunc.foreach(tls+=) toFunc.foreach(tls+=)
} }
override def visitStackRefField(objRef: Word, iRef: Word, toStack: Option[InterpreterStack]): Unit = override def visitStackRefField(objRef: Word, iRef: Word, toStack: Option[InterpreterStack]): Unit =
toStack.foreach(o => throw noReach("stack", objRef, iRef, o)) toStack.foreach(o => throw noReach("stack", objRef, iRef, o))
override def visitThreadRefField(objRef: Word, iRef: Word, toThread: Option[InterpreterThread]): Unit = override def visitThreadRefField(objRef: Word, iRef: Word, toThread: Option[InterpreterThread]): Unit =
toThread.foreach(o => throw noReach("thread", objRef, iRef, o)) toThread.foreach(o => throw noReach("thread", objRef, iRef, o))
override def visitFCRefField(objRef: Word, iRef: Word, toFCRef: Option[FrameCursor]): Unit = override def visitFCRefField(objRef: Word, iRef: Word, toFCRef: Option[FrameCursor]): Unit =
toFCRef.foreach(o => throw noReach("frame cursor", objRef, iRef, o)) toFCRef.foreach(o => throw noReach("frame cursor", objRef, iRef, o))
override def visitIRNodeRefField(objRef: Word, iRef: Word, toIRNode: Option[IRNode]): Unit = override def visitIRNodeRefField(objRef: Word, iRef: Word, toIRNode: Option[IRNode]): Unit =
toIRNode.foreach(o => throw noReach("IR node", objRef, iRef, o)) toIRNode.foreach(o => throw noReach("IR node", objRef, iRef, o))
private def noReach(kind: String, objRef: Word, iRef: Word, obj: AnyRef) = private def noReach(kind: String, objRef: Word, iRef: Word, obj: AnyRef) =
new BootImageBuilderException( new BootImageBuilderException(
"Error: Non-null %s field is not allowed in boot image. From: obj 0x%x, iref 0x%x. To stack id: %s".format( "Error: Non-null %s field is not allowed in boot image. From: obj 0x%x, iref 0x%x. To stack id: %s".format(
objRef, iRef, obj)) objRef, iRef, obj))
} }
\ No newline at end of file
...@@ -87,14 +87,14 @@ object RunMu { ...@@ -87,14 +87,14 @@ object RunMu {
val argc = appArgs.size + 1 val argc = appArgs.size + 1
val argvSB = new StringBuilder() val argvSB = new StringBuilder()
val argvOffs = new Array[Long](argc) val argvOffs = new Array[Long](argc)
for ((arg, i) <- (bootImg :: appArgs).zipWithIndex) { for ((arg, i) <- (bootImg :: appArgs).zipWithIndex) {
argvOffs(i) = argvOffs.length argvOffs(i) = argvSB.length
argvSB ++= arg += '\0' argvSB ++= arg += '\0'
} }
val cArgv = NativeSupport.jnrMemoryManager.allocate(argvOffs.length * PlatformConstants.WORD_SIZE_BYTES.toInt) val cArgv = NativeSupport.jnrMemoryManager.allocateDirect(argvOffs.length * PlatformConstants.WORD_SIZE_BYTES.toInt)
val cArgvBuf = NativeSupport.jnrMemoryManager.allocate(argvSB.length) val cArgvBuf = NativeSupport.jnrMemoryManager.allocateDirect(argvSB.length)
for (i <- 0 until argvOffs.length) { for (i <- 0 until argvOffs.length) {
cArgv.putAddress(i * PlatformConstants.WORD_SIZE_BYTES, cArgvBuf.address() + argvOffs(i)) cArgv.putAddress(i * PlatformConstants.WORD_SIZE_BYTES, cArgvBuf.address() + argvOffs(i))
} }
......
.newhybrid $hw <@charh> 14 .newhybrid $hw <@charh> 13
// "Hello world!\n" // "Hello world!"
.init $hw = {{72 101 108 108 111 32 119 111 114 108 100 33 10 0}} .init $hw = {{72 101 108 108 111 32 119 111 114 108 100 33 0}}
.init @hw = $hw