Commit ff2815e8 authored by Kunshan Wang's avatar Kunshan Wang

WIP: frame cursor

parent 756f3e64
......@@ -45,17 +45,22 @@ object CommInsts extends SimpleNamespace[CommInst] {
commInst(0x252, "@uvm.meta.load_bundle")
commInst(0x253, "@uvm.meta.load_hail")
commInst(0x254, "@uvm.meta.cur_func")
commInst(0x255, "@uvm.meta.cur_func_ver")
commInst(0x256, "@uvm.meta.cur_inst")
commInst(0x257, "@uvm.meta.dump_keepalives")
commInst(0x254, "@uvm.meta.new_cursor")
commInst(0x255, "@uvm.meta.next_frame")
commInst(0x256, "@uvm.meta.copy_cursor")
commInst(0x257, "@uvm.meta.close_cursor")
commInst(0x258, "@uvm.meta.pop_frame")
commInst(0x259, "@uvm.meta.push_frame")
commInst(0x258, "@uvm.meta.cur_func")
commInst(0x259, "@uvm.meta.cur_func_ver")
commInst(0x25a, "@uvm.meta.cur_inst")
commInst(0x25b, "@uvm.meta.dump_keepalives")
commInst(0x25a, "@uvm.meta.enable_watchpoint")
commInst(0x25b, "@uvm.meta.disable_watchpoint")
commInst(0x25c, "@uvm.meta.pop_frames_to")
commInst(0x25d, "@uvm.meta.push_frame")
commInst(0x25c, "@uvm.meta.set_trap_handler")
commInst(0x25e, "@uvm.meta.enable_watchpoint")
commInst(0x25f, "@uvm.meta.disable_watchpoint")
commInst(0x260, "@uvm.meta.set_trap_handler")
}
\ No newline at end of file
......@@ -15,6 +15,7 @@ import java.io.StringWriter
import java.nio.CharBuffer
import uvm.utils.AntlrHelpers._
import uvm.utils.IOHelpers
import uvm.utils.IDFactory
class UIRTextReader(val idFactory: IDFactory) {
import UIRTextReader._
......
......@@ -3,7 +3,7 @@ package uvm.refimpl
import scala.collection.mutable.HashSet
import uvm._
import uvm.ir.textinput.IDFactory
import uvm.utils.IDFactory
import uvm.ir.textinput.UIRTextReader
import uvm.refimpl.hail.HailScriptLoader
import uvm.refimpl.itpr._
......@@ -15,6 +15,8 @@ object MicroVM {
val DEFAULT_HEAP_SIZE: Word = 4L * 1024L * 1024L; // 4MiB
val DEFAULT_GLOBAL_SIZE: Word = 1L * 1024L * 1024L; // 1MiB
val DEFAULT_STACK_SIZE: Word = 63L * 1024L; // 60KiB per stack
val FIRST_CLIENT_USABLE_ID: Int = 65536
}
class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE,
......@@ -33,10 +35,11 @@ class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE,
implicit val nativeCallHelper = new NativeCallHelper()
val threadStackManager = new ThreadStackManager()
val trapManager = new TrapManager()
val contexts = new HashSet[MuCtx]()
val irReader = new UIRTextReader(new IDFactory())
val irReader = new UIRTextReader(new IDFactory(MicroVM.FIRST_CLIENT_USABLE_ID))
val hailScriptLoader = new HailScriptLoader()
{
......
......@@ -71,6 +71,7 @@ case class MuStackRefValue(ty: TypeStackRef, vb: BoxStack) extends MuGenRefValue
case class MuTagRef64Value(ty: TypeTagRef64, vb: BoxTagRef64) extends MuValue
case class MuUPtrValue(ty: TypeUPtr, vb: BoxPointer) extends MuValue
case class MuUFPValue(ty: TypeUFuncPtr, vb: BoxPointer) extends MuValue
case class MuFrameCursorRefValue(ty: TypeFrameCursorRef, vb: BoxFrameCursor) extends MuValue
abstract class TrapHandlerResult
object TrapHandlerResult {
......
......@@ -4,7 +4,7 @@ import uvm._
import uvm.types._
import uvm.ssavariables._
import uvm.utils.LazyPool
import uvm.ir.textinput.IDFactory
import uvm.utils.IDFactory
import scala.collection.mutable.HashMap
import uvm.FuncSig
import uvm.IdentifiedSettable
......@@ -42,6 +42,7 @@ object InternalTypes {
val STACKREF = TypeStackRef() := internal("stackref")
val THREADREF = TypeThreadRef() := internal("threadref")
val FRAMECURSORREF = TypeFrameCursorRef() := internal("framecursorref")
val TAGREF64 = TypeTagRef64() := internal("tagref64")
val BYTES = TypeHybrid(Seq(I64), I8) := (0x260, "@uvm.meta.bytes")
......@@ -172,12 +173,17 @@ object TypeInferer {
case "@uvm.meta.load_bundle" => Seq(BYTES_R)
case "@uvm.meta.load_hail" => Seq(BYTES_R)
case "@uvm.meta.new_cursor" => Seq(FRAMECURSORREF)
case "@uvm.meta.next_frame" => Seq()
case "@uvm.meta.copy_cursor" => Seq(FRAMECURSORREF)
case "@uvm.meta.close_cursor" => Seq()
case "@uvm.meta.cur_func" => Seq(I32)
case "@uvm.meta.cur_func_ver" => Seq(I32)
case "@uvm.meta.cur_inst" => Seq(I32)
case "@uvm.meta.dump_keepalives" => Seq(REFS_R)
case "@uvm.meta.pop_frame" => Seq()
case "@uvm.meta.pop_frames_to" => Seq()
case "@uvm.meta.push_frame" => Seq()
case "@uvm.meta.enable_watchpoint" => Seq()
......
......@@ -28,7 +28,7 @@ object HowToResume {
* A thread that interprets Mu instruction.
*/
class InterpreterThread(val id: Int, initialStack: InterpreterStack, val mutator: Mutator, htr: HowToResume)(
implicit protected val microVM: MicroVM) extends InstructionExecutor {
implicit protected val microVM: MicroVM) extends InstructionExecutor with HasID {
import InterpreterThread._
// Injectable resources (used by memory access instructions)
......
......@@ -8,6 +8,56 @@ import scala.collection.mutable.ArrayBuffer
import org.slf4j.LoggerFactory
import com.typesafe.scalalogging.Logger
import uvm.refimpl.nat.NativeCallHelper
import uvm.utils.IDFactory
import uvm.refimpl.UvmRuntimeException
/**
* An object with this trait can be uniquely identified within a MicroVM using an Int ID.
* <p>
* This is different from Identified because the ID in this context is used as opaque references to these objects. Currently, these
* objects are threads, stacks and frame cursors. These are referred by opaque references which, in the memory are represented as numerical
* IDs.
*/
trait HasID {
def id: Int
}
/**
* Keep HasID objects and allow looking them up by their IDs.
*
* @param kind A name that indicates what kind of object it holds. For debugging.
*/
class IDObjectKeeper[T <: HasID](val kind: String) {
val registry = new HashMap[Int, T]()
val idFactory = new IDFactory(1)
/** Get an object by its ID. */
def apply(id: Int) = registry.apply(id)
/** Get an object by its ID, handle non-existing cases. */
def get(id: Int) = registry.get(id)
/** Add an object to the registry. */
def put(obj: T): Unit = {
if (registry.put(obj.id, obj).isDefined) {
throw new UvmRuntimeException("%s of ID %s already exists.".format(kind, obj.id))
}
}
/** Iterate through all objects. */
def values: Iterable[T] = registry.values
/** Remove an object from the registry. */
def remove(obj: T): Unit = {
val old = registry.remove(obj.id)
if (old.isDefined && !(old.get eq obj)) {
throw new UvmRuntimeException("The %s removed is not the same object as the argument. ID: %d".format(kind, obj.id))
}
}
/** Create an ID for a new object of this type. */
def getID() = idFactory.getID()
}
object ThreadStackManager {
val logger = Logger(LoggerFactory.getLogger(getClass.getName))
......@@ -20,26 +70,12 @@ object ThreadStackManager {
class ThreadStackManager(implicit microVM: MicroVM, nativeCallHelper: NativeCallHelper) {
import ThreadStackManager._
private val stackRegistry = new HashMap[Int, InterpreterStack]()
private val threadRegistry = new HashMap[Int, InterpreterThread]()
def getStackByID(id: Int): Option[InterpreterStack] = stackRegistry.get(id)
def getThreadByID(id: Int): Option[InterpreterThread] = threadRegistry.get(id)
val stackRegistry = new IDObjectKeeper[InterpreterStack]("stack")
val threadRegistry = new IDObjectKeeper[InterpreterThread]("thread")
def iterateAllLiveStacks: Iterable[InterpreterStack] = stackRegistry.values.filter(_.state != FrameState.Dead)
def iterateAllLiveThreads: Iterable[InterpreterThread] = threadRegistry.values.filter(_.isRunning)
private var nextStackID: Int = 1
private def makeStackID(): Int = { val id = nextStackID; nextStackID += 1; id }
private var nextThreadID: Int = 1
private def makeThreadID(): Int = { val id = nextThreadID; nextThreadID += 1; id }
val futexManager = new FutexManager
/**
......@@ -57,9 +93,9 @@ class ThreadStackManager(implicit microVM: MicroVM, nativeCallHelper: NativeCall
*/
def newStack(func: Function, mutator: Mutator): InterpreterStack = {
val stackMemory = microVM.memoryManager.makeStackMemory(mutator)
val id = makeStackID()
val id = stackRegistry.getID()
val sta = new InterpreterStack(id, stackMemory, func)
stackRegistry.put(id, sta)
stackRegistry.put(sta)
sta
}
......@@ -68,9 +104,9 @@ class ThreadStackManager(implicit microVM: MicroVM, nativeCallHelper: NativeCall
*/
def newThread(stack: InterpreterStack, htr: HowToResume): InterpreterThread = {
val mutator = microVM.memoryManager.makeMutator()
val id = makeThreadID()
val id = threadRegistry.getID()
val thr = new InterpreterThread(id, stack, mutator, htr)
threadRegistry.put(id, thr)
threadRegistry.put(thr)
thr
}
......
......@@ -65,6 +65,10 @@ case class BoxStack(var stack: Option[InterpreterStack]) extends ObjectBox[Inter
def obj = stack
def obj_=(other: Option[InterpreterStack]): Unit = { stack = other }
}
case class BoxFrameCursor(var cursor: Option[FrameCursor]) extends ObjectBox[FrameCursor] {
def obj = cursor
def obj_=(other: Option[FrameCursor]): Unit = { cursor = other }
}
case class BoxTagRef64(var raw: Long) extends HasObjRef {
def copyFrom(other: ValueBox): Unit = { this.raw = other.asInstanceOf[BoxTagRef64].raw }
def hasObjRef() = OpHelper.tr64IsRef(raw)
......@@ -97,6 +101,7 @@ object ValueBox {
case _: TypeFuncRef => BoxFunc(None)
case _: TypeStackRef => BoxStack(None)
case _: TypeThreadRef => BoxThread(None)
case _: TypeFrameCursorRef => BoxFrameCursor(None)
case _: TypeTagRef64 => BoxTagRef64(0L)
case _: TypeUPtr => BoxPointer(0L)
case _: TypeUFuncPtr => BoxPointer(0L)
......
......@@ -377,12 +377,12 @@ object MemoryOperations {
case _: TypeThreadRef =>
noAccessViaPointer(ptr, ty)
val tid = memorySupport.loadLong(loc).toInt
val thr = microVM.threadStackManager.getThreadByID(tid)
val thr = microVM.threadStackManager.threadRegistry.get(tid)
br.asInstanceOf[BoxThread].thread = thr
case _: TypeStackRef =>
noAccessViaPointer(ptr, ty)
val sid = memorySupport.loadLong(loc).toInt
val sta = microVM.threadStackManager.getStackByID(sid)
val sta = microVM.threadStackManager.stackRegistry.get(sid)
br.asInstanceOf[BoxStack].stack = sta
case _: TypeTagRef64 =>
noAccessViaPointer(ptr, ty)
......@@ -512,7 +512,7 @@ object MemoryOperations {
val el = eb.asInstanceOf[BoxThread].thread.map(_.id).getOrElse(0).toLong
val dl = db.asInstanceOf[BoxThread].thread.map(_.id).getOrElse(0).toLong
val (succ, rl) = memorySupport.cmpXchgLong(loc, el, dl)
val rt = microVM.threadStackManager.getThreadByID(rl.toInt)
val rt = microVM.threadStackManager.threadRegistry.get(rl.toInt)
br.asInstanceOf[BoxThread].thread = rt
succ
case _: TypeStackRef =>
......@@ -520,7 +520,7 @@ object MemoryOperations {
val el = eb.asInstanceOf[BoxStack].stack.map(_.id).getOrElse(0).toLong
val dl = db.asInstanceOf[BoxStack].stack.map(_.id).getOrElse(0).toLong
val (succ, rl) = memorySupport.cmpXchgLong(loc, el, dl)
val rs = microVM.threadStackManager.getStackByID(rl.toInt)
val rs = microVM.threadStackManager.stackRegistry.get(rl.toInt)
br.asInstanceOf[BoxStack].stack = rs
succ
case _: TypeUPtr | _: TypeUFuncPtr =>
......@@ -568,13 +568,13 @@ object MemoryOperations {
noAccessViaPointer(ptr, ty)
val ol = ob.asInstanceOf[BoxThread].thread.map(_.id).getOrElse(0).toLong
val rl = memorySupport.atomicRMWLong(op, loc, ol)
val rt = microVM.threadStackManager.getThreadByID(rl.toInt)
val rt = microVM.threadStackManager.threadRegistry.get(rl.toInt)
br.asInstanceOf[BoxThread].thread = rt
case _: TypeStackRef =>
noAccessViaPointer(ptr, ty)
val ol = ob.asInstanceOf[BoxStack].stack.map(_.id).getOrElse(0).toLong
val rl = memorySupport.atomicRMWLong(op, loc, ol)
val rs = microVM.threadStackManager.getStackByID(rl.toInt)
val rs = microVM.threadStackManager.stackRegistry.get(rl.toInt)
br.asInstanceOf[BoxStack].stack = rs
case _: TypeTagRef64 =>
noAccessViaPointer(ptr, ty)
......
......@@ -30,7 +30,7 @@ object FrameState {
* Implements a Mu Stack. Contains both Mu frames and native frames.
*/
class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFunc: Function)(
implicit nativeCallHelper: NativeCallHelper) {
implicit nativeCallHelper: NativeCallHelper) extends HasID {
var gcMark: Boolean = false // Mark for GC.
private var _top: InterpreterFrame = InterpreterFrame.forMuFunc(stackMemory.top, stackBottomFunc, 0L, None)
......@@ -331,6 +331,8 @@ class NativeFrame(val func: Word, prev: Option[InterpreterFrame]) extends Interp
override def curFuncID: Int = 0
override def curFuncVerID: Int = 0
override def curInstID: Int = 0
override def toString(): String = "NativeFrame(func=0x%x)".format(func)
}
abstract class MuFrame(val func: Function, prev: Option[InterpreterFrame]) extends InterpreterFrame(prev) {
......@@ -416,6 +418,7 @@ class UndefinedMuFrame(func: Function, prev: Option[InterpreterFrame]) extends M
}
}
override def toString(): String = "UndefinedMuFrame(func=%s)".format(func.repr)
}
object DefinedMuFrame {
......@@ -554,5 +557,20 @@ class DefinedMuFrame(val savedStackPointer: Word, val funcVer: FuncVer, val cook
!wasJustCreated
}
override def toString(): String = "DefinedMuFrame(func=%s, funcVer=%s)".format(func.repr, funcVer.repr)
}
/**
* A mutable cursor that iterates through stack frames.
*/
class FrameCursor(val id: Int, val stack: InterpreterStack, val frame: InterpreterFrame) extends HasID {
/** The current frame it refers to. */
var curFrame = frame
def nextFrame(): Unit = {
curFrame = curFrame.prev.getOrElse {
throw new UvmRuntimeException("Attempt to go below the stack-bottom frame. Stack id: %d, Frame: %s".format(
stack.id, curFrame.toString))
}
}
}
......@@ -112,7 +112,7 @@ object MemoryDataScanner extends StrictLogging {
val maybeToStack = if (toStackID == 0) {
None
} else {
val toStack = microVM.threadStackManager.getStackByID(toStackID.toInt).getOrElse {
val toStack = microVM.threadStackManager.stackRegistry.get(toStackID.toInt).getOrElse {
throw new UvmRefImplException("Memory location 0x%x referring to non-existing stack %d".format(iRef, toStackID))
}
Some(toStack)
......
......@@ -46,6 +46,7 @@ case class TypeTagRef64() extends Type
case class TypeVector(var elemTy: Type, var len: Long) extends AbstractSeqType
case class TypeUPtr(var ty: Type) extends AbstractPointerType
case class TypeUFuncPtr(var sig: FuncSig) extends AbstractPointerType
case class TypeFrameCursorRef() extends AbstractGenRefType
object Type {
def prettyPrint(ty: Type): String = ty match {
......@@ -66,6 +67,7 @@ object Type {
case TypeVector(elemTy, len) => "vector<%s %d>".format(elemTy.repr, len)
case TypeUPtr(ty) => "uptr<%s>".format(ty.repr)
case TypeUFuncPtr(sig) => "ufuncptr<%s>".format(sig.repr)
case TypeFrameCursorRef() => "framecursorref"
case _ => "unknown type " + ty.getClass.getName
}
}
package uvm.ir.textinput
package uvm.utils
class IDFactory(val initialID: Int = 65536) {
class IDFactory(initialID: Int) {
private var id: Int = initialID
def getID(): Int = {
......
......@@ -6,7 +6,7 @@ import org.scalatest.Matchers
import org.scalatest.matchers.{ Matcher, MatchResult }
import TextIRWriter._
import uvm.ir.textinput.UIRTextReader
import uvm.ir.textinput.IDFactory
import uvm.utils.IDFactory
class TextIRWriterTest extends FlatSpec with Matchers {
......@@ -717,6 +717,6 @@ class TextIRWriterTest extends FlatSpec with Matchers {
println(ir)
val muBundle = new UIRTextReader(new IDFactory).read(ir, new uvm.GlobalBundle())
val muBundle = new UIRTextReader(new IDFactory(65536)).read(ir, new uvm.GlobalBundle())
}
}
\ No newline at end of file
......@@ -2,15 +2,15 @@ package uvm.ir.textinput
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import uvm.GlobalBundle
import uvm.TrantientBundle
import uvm.utils.IDFactory
class NicerErrorMessage extends FlatSpec with Matchers
with TestingBundlesValidators {
def parseFile(fileName: String, globalBundle: GlobalBundle, fac: Option[IDFactory] = None): TrantientBundle = {
val idf = fac.getOrElse(new IDFactory())
val idf = fac.getOrElse(new IDFactory(uvm.refimpl.MicroVM.FIRST_CLIENT_USABLE_ID))
val r = new UIRTextReader(idf)
val ir = r.read(new java.io.FileReader(fileName), globalBundle)
ir
......
......@@ -2,15 +2,15 @@ package uvm.ir.textinput
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import uvm.GlobalBundle
import uvm.TrantientBundle
import uvm.utils.IDFactory
class UIRTextReaderSpec extends FlatSpec with Matchers
with TestingBundlesValidators {
def parseFile(fileName: String, globalBundle: GlobalBundle, fac: Option[IDFactory] = None): TrantientBundle = {
val idf = fac.getOrElse(new IDFactory())
val idf = fac.getOrElse(new IDFactory(uvm.refimpl.MicroVM.FIRST_CLIENT_USABLE_ID))
val r = new UIRTextReader(idf)
val ir = r.read(new java.io.FileReader(fileName), globalBundle)
ir
......
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