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