Commit 6420c55d authored by Kunshan Wang's avatar Kunshan Wang

WIP: Transitive closure over top-levels

parent 8456f370
......@@ -63,6 +63,11 @@ class TrantientBundle extends Bundle {
* This kind of bundle holds the global state. Functions and versions are fully merged.
*/
class GlobalBundle extends Bundle {
/**
* Map all functions to their versions, latest version first. All declared functions are in this map. Undefine
* functions map to empty lists.
*/
val funcToVers = new HashMap[Function, List[FuncVer]]()
private def simpleMerge[T <: Identified](oldNs: Namespace[T], newNs: Namespace[T], newSourceInfoRepo: SourceInfoRepo) {
......
......@@ -7,55 +7,85 @@ import uvm.ssavariables._
import uvm.refimpl._
import uvm.refimpl.mem.TypeSizes.Word
import scala.collection.mutable.Queue
import scala.collection.mutable.{ Set, Queue }
class BootImageBuilder(implicit microVM: MicroVM) {
def makeBootImage(whiteList: Seq[Int], outputFile: String): Unit = {
implicit val tc = new TransitiveClosure(whiteList)
implicit val tc = new TransitiveClosureBuilder(whiteList)
tc.doTransitiveClosure()
}
}
object TransitiveClosure {
abstract class Item
case class TopLevel(id: Int) extends Item
case class HeapObj(ref: Word) extends Item
def apply[T](initialElems: T*) = new TransitiveClosure(initialElems)
}
class TransitiveClosure(initialSet: Seq[Int])(
implicit microVM: MicroVM) {
import TransitiveClosure._
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 {
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
}
}
}
private val initialItems = initialSet.map(TopLevel)
class TransitiveClosureBuilder(initialSet: Seq[Int])(
implicit microVM: MicroVM) {
import TransitiveClosureBuilder._
val set = Set[Item](initialItems: _*)
val queue = Queue[Item](initialItems: _*)
/**
* 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): _*)
val idVisisted = Set[Int](initialSet: _*)
val objVisited = Set[Word]()
/**
* Global cells + heap objects.
*/
val objs = TransitiveClosure[Word]()
def doTransitiveClosure(): Unit = {
while (!queue.isEmpty) {
val item = queue.dequeue()
if (set contains item) {
// continue
} else {
visitItem(item)
while (tls.hasPending || objs.hasPending) {
while (tls.hasPending) {
visitTopLevel(tls.dequeue())
}
while (objs.hasPending) {
visitHeapObj(objs.dequeue())
}
}
}
private def visitItem(item: Item): Unit = item match {
case TopLevel(id) => visitTopLevel(id)
case HeapObj(ref) => visitHeapObj(ref)
}
private def visitTopLevel(id: Int): Unit = {
val thing = microVM.globalBundle.allNs(id)
thing match {
private def visitTopLevel(tl: Identified): Unit = {
tl match {
case t: Type => visitType(t)
case s: FuncSig => visitFuncSig(s)
case c: Constant => visitConstant(c)
......@@ -65,32 +95,122 @@ class TransitiveClosure(initialSet: Seq[Int])(
}
}
private def visitType(ty: Type): Unit = {
???
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
// Scan this cell and visit reachable heap objects or other global cells, too.
}
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(i: Instruction): Unit = {
???
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 UvmRuntimeException("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 visitHeapObj(ref: Word): Unit = {
......
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