GitLab will be partched to the latest stable version on 15 July 2020 at 2.00pm (AEDT) to 2.30pm (AEDT) due to Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

Commit 1d41a37e authored by Kunshan Wang's avatar Kunshan Wang

Reorganised files.

parent f62845b3
......@@ -29,293 +29,3 @@ class BootImageBuilder(implicit microVM: MicroVM) {
tc.doTransitiveClosure()
}
}
object TransitiveClosure {
def apply[T](initialElems: T*) = new TransitiveClosure(initialElems)
}
class TransitiveClosure[T](initialElems: Seq[T]) {
val set = Set[T](initialElems: _*)
val queue = Queue[T](initialElems: _*)
def hasPending = !queue.isEmpty
def dequeue() = queue.dequeue()
def maybeEnqueue(elem: T): Boolean = {
if (set.contains(elem)) {
false
} else {
set += elem
queue += elem
true
}
}
def +=(elem: T): TransitiveClosure[T] = { maybeEnqueue(elem); this }
def ++=(elems: Seq[T]): TransitiveClosure[T] = { elems.foreach(this +=); this }
}
object TransitiveClosureBuilder {
val logger = Logger(LoggerFactory.getLogger(getClass.getName))
implicit class RichTransitiveClosure[T <: Identified](val tc: TransitiveClosure[T]) extends AnyVal {
def ?=(elem: SSAVariable) = {
if (elem.isInstanceOf[GlobalVariable]) {
tc += elem.asInstanceOf[T]
}
tc
}
def ??=(elems: Seq[SSAVariable]) = {
for (elem <- elems) {
this ?= elem
}
tc
}
}
case class GlobalCellRec(begin: Word, end: Word, g: GlobalCell)
}
class TransitiveClosureBuilder(initialSet: Seq[Int])(implicit microVM: MicroVM) extends RefFieldHandler {
import TransitiveClosureBuilder._
private val globalMemory: Space = microVM.memoryManager.globalMemory
private val smallObjectSpace: Space = microVM.memoryManager.heap.space
private val largeObjectSpace: Space = microVM.memoryManager.heap.los
private implicit val memorySupport = microVM.memoryManager.memorySupport
/**
* Top-level definitions in the closure. Function versions are not considered top-level here. A function may have at
* most one function version. Only that version is serialised into the boot image.
*/
val tls = TransitiveClosure[Identified](initialSet.map(microVM.globalBundle.allNs.apply): _*)
/**
* Global cells + heap objects.
*/
val allocs = TransitiveClosure[Word]()
def getGlobalCellAddr(g: GlobalCell): Word = {
microVM.constantPool.getGlobalVarBox(g).asInstanceOf[BoxIRef].addr
}
/**
* Map the global cell's starting address to the global cell itself.
*/
val globalCellMap = {
val elems = microVM.globalBundle.globalCellNs.all.toSeq.map { g =>
val begin = getGlobalCellAddr(g)
val ty = g.cellTy
assert(!ty.isInstanceOf[TypeHybrid])
val size = TypeSizes.sizeOf(ty)
val end = begin + size
(begin, GlobalCellRec(begin, end, g))
}
TreeMap[Word, GlobalCellRec](elems: _*)
}
def getGlobalCellRec(iref: Word): GlobalCellRec = {
require(microVM.memoryManager.globalMemory.isInSpace(iref),
"Address %d 0x%x is not in the global space".format(iref, iref))
val (begin, gcr) = globalCellMap.to(iref).last
assert(begin <= iref && iref < gcr.end,
"Address %d 0x%x is in the global space, but the previous global cell's address range is %d 0x%x - %d 0x%x".format(
iref, iref, begin, begin, gcr.end, gcr.end))
gcr
}
def doTransitiveClosure(): Unit = {
while (tls.hasPending || allocs.hasPending) {
while (tls.hasPending) {
visitTopLevel(tls.dequeue())
}
while (allocs.hasPending) {
visitAllocUnit(allocs.dequeue())
}
}
}
private def visitTopLevel(tl: Identified): Unit = {
tl match {
case t: Type => visitType(t)
case s: FuncSig => visitFuncSig(s)
case c: Constant => visitConstant(c)
case g: GlobalCell => visitGlobalCell(g)
case f: Function => visitFunction(f)
case e: ExposedFunc => visitExpFunc(e)
}
}
private def visitType(ty: Type): Unit = ty match {
case TypeUPtr(t) => tls += t
case TypeUFuncPtr(s) => tls += s
case TypeStruct(ts) => tls ++= ts
case TypeHybrid(fs, v) => tls ++= fs += v
case TypeArray(t, _) => tls += t
case TypeVector(t, _) => tls += t
case TypeRef(t) => tls += t
case TypeIRef(t) => tls += t
case TypeWeakRef(t) => tls += t
case TypeFuncRef(s) => tls += s
case _ => // Not nested or recursive. Do nothing.
}
private def visitFuncSig(s: FuncSig): Unit = {
tls ++= s.paramTys ++= s.retTys
}
private def visitConstant(c: Constant): Unit = {
tls += c.constTy
c match {
case ConstSeq(_, elems) => tls ++= elems
case _ => // Not nested. Do nothing.
}
}
private def visitGlobalCell(g: GlobalCell): Unit = {
tls += g.cellTy
allocs += getGlobalCellAddr(g)
}
private def visitFunction(f: Function): Unit = {
tls += f.sig
microVM.globalBundle.funcToVers(f).headOption match {
case None => // Undefined. Do nothing
case Some(mostRecent) => {
// Visit all TOP-LEVELS (mostly types sigs and SSA variables).
// This version, including all of its basic blocks and instructions, will be in the boot image.
for (bb <- mostRecent.bbs) {
tls ++= bb.norParams.map(_.ty)
for (inst <- bb.insts) {
visitInstruction(inst)
}
}
}
}
}
private def visitExpFunc(e: ExposedFunc): Unit = {
tls += e.func
tls += e.cookie
}
private def visitInstruction(inst: Instruction): Unit = inst match {
case InstBinOp(op, opndTy, op1, op2, excClause) => 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 InstSelect(condTy, opndTy, cond, ifTrue, ifFalse) => tls += condTy += opndTy ?= cond ?= ifTrue ?= ifFalse
case InstBranch(dest) =>
case InstBranch2(cond, ifTrue, ifFalse) => tls ?= cond
case i @ InstSwitch(opndTy, opnd, defDest, cases) => tls += opndTy ?= opnd ??= cases.map(_._1)
case InstCall(sig, callee, argList, excClause, keepalives) => tls += sig ?= callee ??= argList
case InstTailCall(sig, callee, argList) => tls += sig ?= callee ??= argList
case InstRet(funcVer, retVals) => tls ??= retVals
case InstThrow(excVal) => tls ?= excVal
case InstExtractValue(strTy, index, opnd) => tls += strTy ?= opnd
case InstInsertValue(strTy, index, opnd, newVal) => tls += strTy ?= opnd ?= newVal
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 InstShuffleVector(vecTy, maskTy, vec1, vec2, mask) => tls += vecTy += maskTy ?= vec1 ?= vec2 ?= mask
case InstNew(allocTy, excClause) => tls += allocTy
case InstNewHybrid(allocTy, lenTy, length, excClause) => tls += allocTy += lenTy ?= length
case InstAlloca(allocTy, excClause) => tls += allocTy
case InstAllocaHybrid(allocTy, lenTy, length, excClause) => tls += allocTy += lenTy ?= length
case InstGetIRef(referentTy, 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 InstShiftIRef(ptr, referentTy, offTy, opnd, offset) => tls += referentTy += offTy ?= opnd ?= offset
case InstGetVarPartIRef(ptr, referentTy, opnd) => tls += referentTy ?= opnd
case InstLoad(ptr, ord, referentTy, loc, excClause) => tls += referentTy ?= loc
case InstStore(ptr, ord, referentTy, loc, newVal, excClause) => tls += referentTy ?= loc ?= newVal
case InstCmpXchg(ptr, weak, ordSucc, ordFail, referentTy, loc, expected, desired, excClause) // This line is long ...
=> tls += referentTy ?= loc ?= expected ?= desired
case InstAtomicRMW(ptr, ord, op, referentTy, loc, opnd, excClause) => tls += referentTy ?= loc ?= opnd
case InstFence(ord) =>
case InstTrap(retTys, excClause, keepalives) => tls ++= retTys
case InstWatchPoint(wpID, retTys, dis, ena, exc, keepalives) => tls ++= retTys
case InstWPBranch(wpID, dis, ena) =>
case InstCCall(callConv, funcTy, sig, callee, argList, excClause, keepalives) // This line is long, too...
=> tls += funcTy += sig ?= callee ??= argList
case InstNewThread(stack, threadLocal, newStackAction, excClause) => {
tls ?= stack
threadLocal.foreach(tls.?=)
visitNewStackAction(newStackAction)
}
case InstSwapStack(swappee, curStackAction, newStackAction, excClause, keepalives) => {
tls ?= swappee
curStackAction match {
case RetWith(ts) => tls ++= ts
case KillOld() =>
}
visitNewStackAction(newStackAction)
}
case InstCommInst(ci, flagList, typeList, funcSigList, argList, excClause, keepalives) =>
tls ++= typeList ++= funcSigList ??= argList
case _ => throw new BootImageBuilderException("Unknown instruction: " + inst.getClass.getName)
}
private def visitNewStackAction(nsa: NewStackAction): Unit = nsa match {
case PassValues(ts, vs) => tls ++= ts ??= vs
case ThrowExc(e) =>
}
private def visitAllocUnit(addrOrObjRef: Word): Unit = {
logger.debug("Visiting allocation unit 0x%x".format(addrOrObjRef))
if (globalMemory.isInSpace(addrOrObjRef)) {
val GlobalCellRec(begin, end, g) = getGlobalCellRec(addrOrObjRef)
logger.debug(" It's global cell. begin=0x%x, end=0x%x, type=%s".format(begin, end, g.cellTy))
tls += g
visitAllocUnitFields(begin, g.cellTy)
} else if (smallObjectSpace.isInSpace(addrOrObjRef) || largeObjectSpace.isInSpace(addrOrObjRef)) {
val objRef = addrOrObjRef
val tag = HeaderUtils.getTag(objRef)
val ty = HeaderUtils.getType(microVM, tag)
tls += ty
visitAllocUnitFields(objRef, ty)
} else {
throw new BootImageBuilderException("Address %d 0x%x is not in the heap or global space".format(addrOrObjRef, addrOrObjRef))
}
}
private def visitAllocUnitFields(begin: Word, ty: Type): Unit = {
MemoryDataScanner.scanAllocUnit(begin, this)
}
def boxToHeap(box: HasObjRef): Option[Word] =
throw new BootImageBuilderException("BUG: Box should not have been scanned during boot image building.")
def boxToStack(box: BoxStack): Option[InterpreterStack] =
throw new BootImageBuilderException("BUG: Box should not have been scanned during boot image building.")
def memToHeap(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Option[Word] = {
if (toObj != 0L) {
allocs += toObj
Some(toObj)
} else {
None
}
}
def memToStack(objRef: Word, iRef: Word, toStack: Option[InterpreterStack]): Option[InterpreterStack] = {
if (toStack.isDefined) {
throw new BootImageBuilderException(
"Error: Stack reachable during boot image building. From: obj 0x%x, iref 0x%x. To stack id: %d".format(
objRef, iRef, toStack.get.id))
}
None
}
def stackToStackMem(stack: InterpreterStack, toObj: Word): Option[Word] =
throw new BootImageBuilderException("BUG: Stack should not have been scanned during boot image building.")
def threadToStack(thread: InterpreterThread, toStack: Option[InterpreterStack]): Option[InterpreterStack] =
throw new BootImageBuilderException("BUG: Thread should not have been scanned during boot image building.")
def pinSetToMem(toObj: Word): Option[Word] =
throw new BootImageBuilderException("BUG: Pin set should not have been scanned during boot image building.")
}
\ No newline at end of file
package uvm.refimpl.bootimg
import scala.collection.immutable.TreeMap
import scala.collection.mutable.{ Set, Queue }
import org.slf4j.LoggerFactory
import com.typesafe.scalalogging.Logger
import uvm._
import uvm.refimpl._
import uvm.refimpl.itpr._
import uvm.refimpl.mem.HeaderUtils
import uvm.refimpl.mem.Space
import uvm.refimpl.mem.TypeSizes
import uvm.refimpl.mem.TypeSizes.Word
import uvm.refimpl.mem.scanning.MemoryDataScanner
import uvm.refimpl.mem.scanning.RefFieldHandler
import uvm.ssavariables._
import uvm.types._
object TransitiveClosure {
def apply[T](initialElems: T*) = new TransitiveClosure(initialElems)
}
class TransitiveClosure[T](initialElems: Seq[T]) {
val set = Set[T](initialElems: _*)
val queue = Queue[T](initialElems: _*)
def hasPending = !queue.isEmpty
def dequeue() = queue.dequeue()
def maybeEnqueue(elem: T): Boolean = {
if (set.contains(elem)) {
false
} else {
set += elem
queue += elem
true
}
}
def +=(elem: T): TransitiveClosure[T] = { maybeEnqueue(elem); this }
def ++=(elems: Seq[T]): TransitiveClosure[T] = { elems.foreach(this +=); this }
}
object TransitiveClosureBuilder {
val logger = Logger(LoggerFactory.getLogger(getClass.getName))
implicit class RichTransitiveClosure[T <: Identified](val tc: TransitiveClosure[T]) extends AnyVal {
def ?=(elem: SSAVariable) = {
if (elem.isInstanceOf[GlobalVariable]) {
tc += elem.asInstanceOf[T]
}
tc
}
def ??=(elems: Seq[SSAVariable]) = {
for (elem <- elems) {
this ?= elem
}
tc
}
}
case class GlobalCellRec(begin: Word, end: Word, g: GlobalCell)
}
class TransitiveClosureBuilder(initialSet: Seq[Int])(implicit microVM: MicroVM) extends RefFieldHandler {
import TransitiveClosureBuilder._
private val globalMemory: Space = microVM.memoryManager.globalMemory
private val smallObjectSpace: Space = microVM.memoryManager.heap.space
private val largeObjectSpace: Space = microVM.memoryManager.heap.los
private implicit val memorySupport = microVM.memoryManager.memorySupport
/**
* Top-level definitions in the closure. Function versions are not considered top-level here. A function may have at
* most one function version. Only that version is serialised into the boot image.
*/
val tls = TransitiveClosure[Identified](initialSet.map(microVM.globalBundle.allNs.apply): _*)
/**
* Global cells + heap objects.
*/
val allocs = TransitiveClosure[Word]()
def getGlobalCellAddr(g: GlobalCell): Word = {
microVM.constantPool.getGlobalVarBox(g).asInstanceOf[BoxIRef].addr
}
/**
* Map the global cell's starting address to the global cell itself.
*/
val globalCellMap = {
val elems = microVM.globalBundle.globalCellNs.all.toSeq.map { g =>
val begin = getGlobalCellAddr(g)
val ty = g.cellTy
assert(!ty.isInstanceOf[TypeHybrid])
val size = TypeSizes.sizeOf(ty)
val end = begin + size
(begin, GlobalCellRec(begin, end, g))
}
TreeMap[Word, GlobalCellRec](elems: _*)
}
def getGlobalCellRec(iref: Word): GlobalCellRec = {
require(microVM.memoryManager.globalMemory.isInSpace(iref),
"Address %d 0x%x is not in the global space".format(iref, iref))
val (begin, gcr) = globalCellMap.to(iref).last
assert(begin <= iref && iref < gcr.end,
"Address %d 0x%x is in the global space, but the previous global cell's address range is %d 0x%x - %d 0x%x".format(
iref, iref, begin, begin, gcr.end, gcr.end))
gcr
}
def doTransitiveClosure(): Unit = {
while (tls.hasPending || allocs.hasPending) {
while (tls.hasPending) {
visitTopLevel(tls.dequeue())
}
while (allocs.hasPending) {
visitAllocUnit(allocs.dequeue())
}
}
}
private def visitTopLevel(tl: Identified): Unit = {
tl match {
case t: Type => visitType(t)
case s: FuncSig => visitFuncSig(s)
case c: Constant => visitConstant(c)
case g: GlobalCell => visitGlobalCell(g)
case f: Function => visitFunction(f)
case e: ExposedFunc => visitExpFunc(e)
}
}
private def visitType(ty: Type): Unit = ty match {
case TypeUPtr(t) => tls += t
case TypeUFuncPtr(s) => tls += s
case TypeStruct(ts) => tls ++= ts
case TypeHybrid(fs, v) => tls ++= fs += v
case TypeArray(t, _) => tls += t
case TypeVector(t, _) => tls += t
case TypeRef(t) => tls += t
case TypeIRef(t) => tls += t
case TypeWeakRef(t) => tls += t
case TypeFuncRef(s) => tls += s
case _ => // Not nested or recursive. Do nothing.
}
private def visitFuncSig(s: FuncSig): Unit = {
tls ++= s.paramTys ++= s.retTys
}
private def visitConstant(c: Constant): Unit = {
tls += c.constTy
c match {
case ConstSeq(_, elems) => tls ++= elems
case _ => // Not nested. Do nothing.
}
}
private def visitGlobalCell(g: GlobalCell): Unit = {
tls += g.cellTy
allocs += getGlobalCellAddr(g)
}
private def visitFunction(f: Function): Unit = {
tls += f.sig
microVM.globalBundle.funcToVers(f).headOption match {
case None => // Undefined. Do nothing
case Some(mostRecent) => {
// Visit all TOP-LEVELS (mostly types sigs and SSA variables).
// This version, including all of its basic blocks and instructions, will be in the boot image.
for (bb <- mostRecent.bbs) {
tls ++= bb.norParams.map(_.ty)
for (inst <- bb.insts) {
visitInstruction(inst)
}
}
}
}
}
private def visitExpFunc(e: ExposedFunc): Unit = {
tls += e.func
tls += e.cookie
}
private def visitInstruction(inst: Instruction): Unit = inst match {
case InstBinOp(op, opndTy, op1, op2, excClause) => 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 InstSelect(condTy, opndTy, cond, ifTrue, ifFalse) => tls += condTy += opndTy ?= cond ?= ifTrue ?= ifFalse
case InstBranch(dest) =>
case InstBranch2(cond, ifTrue, ifFalse) => tls ?= cond
case i @ InstSwitch(opndTy, opnd, defDest, cases) => tls += opndTy ?= opnd ??= cases.map(_._1)
case InstCall(sig, callee, argList, excClause, keepalives) => tls += sig ?= callee ??= argList
case InstTailCall(sig, callee, argList) => tls += sig ?= callee ??= argList
case InstRet(funcVer, retVals) => tls ??= retVals
case InstThrow(excVal) => tls ?= excVal
case InstExtractValue(strTy, index, opnd) => tls += strTy ?= opnd
case InstInsertValue(strTy, index, opnd, newVal) => tls += strTy ?= opnd ?= newVal
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 InstShuffleVector(vecTy, maskTy, vec1, vec2, mask) => tls += vecTy += maskTy ?= vec1 ?= vec2 ?= mask
case InstNew(allocTy, excClause) => tls += allocTy
case InstNewHybrid(allocTy, lenTy, length, excClause) => tls += allocTy += lenTy ?= length
case InstAlloca(allocTy, excClause) => tls += allocTy
case InstAllocaHybrid(allocTy, lenTy, length, excClause) => tls += allocTy += lenTy ?= length
case InstGetIRef(referentTy, 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 InstShiftIRef(ptr, referentTy, offTy, opnd, offset) => tls += referentTy += offTy ?= opnd ?= offset
case InstGetVarPartIRef(ptr, referentTy, opnd) => tls += referentTy ?= opnd
case InstLoad(ptr, ord, referentTy, loc, excClause) => tls += referentTy ?= loc
case InstStore(ptr, ord, referentTy, loc, newVal, excClause) => tls += referentTy ?= loc ?= newVal
case InstCmpXchg(ptr, weak, ordSucc, ordFail, referentTy, loc, expected, desired, excClause) // This line is long ...
=> tls += referentTy ?= loc ?= expected ?= desired
case InstAtomicRMW(ptr, ord, op, referentTy, loc, opnd, excClause) => tls += referentTy ?= loc ?= opnd
case InstFence(ord) =>
case InstTrap(retTys, excClause, keepalives) => tls ++= retTys
case InstWatchPoint(wpID, retTys, dis, ena, exc, keepalives) => tls ++= retTys
case InstWPBranch(wpID, dis, ena) =>
case InstCCall(callConv, funcTy, sig, callee, argList, excClause, keepalives) // This line is long, too...
=> tls += funcTy += sig ?= callee ??= argList
case InstNewThread(stack, threadLocal, newStackAction, excClause) => {
tls ?= stack
threadLocal.foreach(tls.?=)
visitNewStackAction(newStackAction)
}
case InstSwapStack(swappee, curStackAction, newStackAction, excClause, keepalives) => {
tls ?= swappee
curStackAction match {
case RetWith(ts) => tls ++= ts
case KillOld() =>
}
visitNewStackAction(newStackAction)
}
case InstCommInst(ci, flagList, typeList, funcSigList, argList, excClause, keepalives) =>
tls ++= typeList ++= funcSigList ??= argList
case _ => throw new BootImageBuilderException("Unknown instruction: " + inst.getClass.getName)
}
private def visitNewStackAction(nsa: NewStackAction): Unit = nsa match {
case PassValues(ts, vs) => tls ++= ts ??= vs
case ThrowExc(e) =>
}
private def visitAllocUnit(addrOrObjRef: Word): Unit = {
logger.debug("Visiting allocation unit 0x%x".format(addrOrObjRef))
if (globalMemory.isInSpace(addrOrObjRef)) {
val GlobalCellRec(begin, end, g) = getGlobalCellRec(addrOrObjRef)
logger.debug(" It's global cell. begin=0x%x, end=0x%x, type=%s".format(begin, end, g.cellTy))
tls += g
visitAllocUnitFields(begin, g.cellTy)
} else if (smallObjectSpace.isInSpace(addrOrObjRef) || largeObjectSpace.isInSpace(addrOrObjRef)) {
val objRef = addrOrObjRef
val tag = HeaderUtils.getTag(objRef)
val ty = HeaderUtils.getType(microVM, tag)
tls += ty
visitAllocUnitFields(objRef, ty)
} else {
throw new BootImageBuilderException("Address %d 0x%x is not in the heap or global space".format(addrOrObjRef, addrOrObjRef))
}
}
private def visitAllocUnitFields(begin: Word, ty: Type): Unit = {
MemoryDataScanner.scanAllocUnit(begin, this)
}
def boxToHeap(box: HasObjRef): Option[Word] =
throw new BootImageBuilderException("BUG: Box should not have been scanned during boot image building.")
def boxToStack(box: BoxStack): Option[InterpreterStack] =
throw new BootImageBuilderException("BUG: Box should not have been scanned during boot image building.")
def memToHeap(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Option[Word] = {
if (toObj != 0L) {
allocs += toObj
Some(toObj)
} else {
None
}
}
def memToStack(objRef: Word, iRef: Word, toStack: Option[InterpreterStack]): Option[InterpreterStack] = {
if (toStack.isDefined) {
throw new BootImageBuilderException(
"Error: Stack reachable during boot image building. From: obj 0x%x, iref 0x%x. To stack id: %d".format(
objRef, iRef, toStack.get.id))
}
None
}
def stackToStackMem(stack: InterpreterStack, toObj: Word): Option[Word] =
throw new BootImageBuilderException("BUG: Stack should not have been scanned during boot image building.")
def threadToStack(thread: InterpreterThread, toStack: Option[InterpreterStack]): Option[InterpreterStack] =
throw new BootImageBuilderException("BUG: Thread should not have been scanned during boot image building.")
def pinSetToMem(toObj: Word): Option[Word] =
throw new BootImageBuilderException("BUG: Pin set should not have been scanned during boot image building.")
}
\ No newline at end of file
......@@ -2,12 +2,12 @@
.new $o2 <@ll>
.new $o3 <@ll>
.init @llhead = $o1
.init @llhead_void = $o1
.init $o1 = {100 $o2}
.init $o2 = {200 $o3}
.init $o3 = {300 NULL}
.init @gr1 = 42
.init @gr2 = &@gr1
.init @llhead = $o1
.init @llhead_void = $o1
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