WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

Commit 59c285d4 authored by Kunshan Wang's avatar Kunshan Wang
Browse files

WIP: updating interpreter...

parent 7e002594
...@@ -16,8 +16,7 @@ case class Handle(ty: Type, vb: ValueBox) ...@@ -16,8 +16,7 @@ case class Handle(ty: Type, vb: ValueBox)
abstract class TrapHandlerResult abstract class TrapHandlerResult
case class TrapExit() extends TrapHandlerResult case class TrapExit() extends TrapHandlerResult
case class TrapRebindPassValue(newStack: Handle, value: Handle) extends TrapHandlerResult case class TrapRebindPassValues(newStack: Handle, values: Seq[Handle]) extends TrapHandlerResult
case class TrapRebindPassVoid(newStack: Handle) extends TrapHandlerResult
case class TrapRebindThrowExc(newStack: Handle, exc: Handle) extends TrapHandlerResult case class TrapRebindThrowExc(newStack: Handle, exc: Handle) extends TrapHandlerResult
trait TrapHandler { trait TrapHandler {
...@@ -264,7 +263,7 @@ class ClientAgent(mutator: Mutator)( ...@@ -264,7 +263,7 @@ class ClientAgent(mutator: Mutator)(
def load(ord: MemoryOrder, loc: Handle): Handle = { def load(ord: MemoryOrder, loc: Handle): Handle = {
val (ptr, ty) = loc.ty match { val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t) case TypeIRef(t) => (false, t)
case TypeUPtr(t) => (true, t) case TypeUPtr(t) => (true, t)
} }
val uty = InternalTypePool.unmarkedOf(ty) val uty = InternalTypePool.unmarkedOf(ty)
val addr = MemoryOperations.addressOf(ptr, loc.vb) val addr = MemoryOperations.addressOf(ptr, loc.vb)
...@@ -278,7 +277,7 @@ class ClientAgent(mutator: Mutator)( ...@@ -278,7 +277,7 @@ class ClientAgent(mutator: Mutator)(
def store(ord: MemoryOrder, loc: Handle, newVal: Handle): Unit = { def store(ord: MemoryOrder, loc: Handle, newVal: Handle): Unit = {
val (ptr, ty) = loc.ty match { val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t) case TypeIRef(t) => (false, t)
case TypeUPtr(t) => (true, t) case TypeUPtr(t) => (true, t)
} }
val uty = InternalTypePool.unmarkedOf(ty) val uty = InternalTypePool.unmarkedOf(ty)
val addr = MemoryOperations.addressOf(ptr, loc.vb) val addr = MemoryOperations.addressOf(ptr, loc.vb)
...@@ -291,7 +290,7 @@ class ClientAgent(mutator: Mutator)( ...@@ -291,7 +290,7 @@ class ClientAgent(mutator: Mutator)(
def cmpXchg(ordSucc: MemoryOrder, ordFail: MemoryOrder, weak: Boolean, loc: Handle, expected: Handle, desired: Handle): (Boolean, Handle) = { def cmpXchg(ordSucc: MemoryOrder, ordFail: MemoryOrder, weak: Boolean, loc: Handle, expected: Handle, desired: Handle): (Boolean, Handle) = {
val (ptr, ty) = loc.ty match { val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t) case TypeIRef(t) => (false, t)
case TypeUPtr(t) => (true, t) case TypeUPtr(t) => (true, t)
} }
val uty = InternalTypePool.unmarkedOf(ty) val uty = InternalTypePool.unmarkedOf(ty)
val addr = MemoryOperations.addressOf(ptr, loc.vb) val addr = MemoryOperations.addressOf(ptr, loc.vb)
...@@ -305,7 +304,7 @@ class ClientAgent(mutator: Mutator)( ...@@ -305,7 +304,7 @@ class ClientAgent(mutator: Mutator)(
def atomicRMW(ord: MemoryOrder, op: AtomicRMWOptr, loc: Handle, opnd: Handle): Handle = { def atomicRMW(ord: MemoryOrder, op: AtomicRMWOptr, loc: Handle, opnd: Handle): Handle = {
val (ptr, ty) = loc.ty match { val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t) case TypeIRef(t) => (false, t)
case TypeUPtr(t) => (true, t) case TypeUPtr(t) => (true, t)
} }
val uty = InternalTypePool.unmarkedOf(ty) val uty = InternalTypePool.unmarkedOf(ty)
val addr = MemoryOperations.addressOf(ptr, loc.vb) val addr = MemoryOperations.addressOf(ptr, loc.vb)
...@@ -318,18 +317,12 @@ class ClientAgent(mutator: Mutator)( ...@@ -318,18 +317,12 @@ class ClientAgent(mutator: Mutator)(
def fence(ord: MemoryOrder): Unit = { def fence(ord: MemoryOrder): Unit = {
} }
def newStack(func: Handle, args: Seq[Handle]): Handle = { def newStack(func: Handle): Handle = {
val funcVal = func.vb.asInstanceOf[BoxFunc].func.getOrElse { val funcVal = func.vb.asInstanceOf[BoxFunc].func.getOrElse {
throw new UvmRuntimeException("Stack-bottom function must not be NULL") throw new UvmRuntimeException("Stack-bottom function must not be NULL")
} }
val funcVer = funcVal.versions.headOption.getOrElse { val sta = microVM.threadStackManager.newStack(funcVal, mutator)
throw new UvmRuntimeException("Stack-bottom function %s is not defined.".format(funcVal.repr))
}
val argBoxes = args.map(_.vb)
val sta = microVM.threadStackManager.newStack(funcVer, argBoxes, mutator)
val nb = BoxStack(Some(sta)) val nb = BoxStack(Some(sta))
newHandle(InternalTypes.STACK, nb) newHandle(InternalTypes.STACK, nb)
...@@ -377,8 +370,9 @@ class ClientAgent(mutator: Mutator)( ...@@ -377,8 +370,9 @@ class ClientAgent(mutator: Mutator)(
val sv = getStackNotNull(stack) val sv = getStackNotNull(stack)
val fr = nthFrame(sv, frame) val fr = nthFrame(sv, frame)
fr match { fr match {
case f: NativeFrame => 0 case f: NativeFrame => 0
case f: MuFrame => f.funcVer.id case f: UndefinedMuFrame => 0
case f: DefinedMuFrame => f.funcVer.id
} }
} }
...@@ -386,8 +380,9 @@ class ClientAgent(mutator: Mutator)( ...@@ -386,8 +380,9 @@ class ClientAgent(mutator: Mutator)(
val sv = getStackNotNull(stack) val sv = getStackNotNull(stack)
val fr = nthFrame(sv, frame) val fr = nthFrame(sv, frame)
fr match { fr match {
case f: NativeFrame => 0 case f: NativeFrame => 0
case f: MuFrame => f.curInst.id case f: UndefinedMuFrame => 0
case f: DefinedMuFrame => f.curInst.id
} }
} }
...@@ -398,7 +393,12 @@ class ClientAgent(mutator: Mutator)( ...@@ -398,7 +393,12 @@ class ClientAgent(mutator: Mutator)(
case f: NativeFrame => { case f: NativeFrame => {
throw new UvmRefImplException("Attempt to dump keepalive variables for a native frame for native funciton 0x%x".format(f.func)) throw new UvmRefImplException("Attempt to dump keepalive variables for a native frame for native funciton 0x%x".format(f.func))
} }
case f: MuFrame => { case f: UndefinedMuFrame => {
for ((ty,box) <- f.func.sig.paramTys zip f.boxes) yield {
newHandle(ty, box)
}
}
case f: DefinedMuFrame => {
val i = f.curInst val i = f.curInst
i match { i match {
case hkac: HasKeepAliveClause => { case hkac: HasKeepAliveClause => {
...@@ -429,7 +429,7 @@ class ClientAgent(mutator: Mutator)( ...@@ -429,7 +429,7 @@ class ClientAgent(mutator: Mutator)(
} }
} }
def pushFrame(stack: Handle, func: Handle, argList: Seq[Handle]): Unit = { def pushFrame(stack: Handle, func: Handle): Unit = {
val sta = stack.vb.asInstanceOf[BoxStack].stack.getOrElse { val sta = stack.vb.asInstanceOf[BoxStack].stack.getOrElse {
throw new UvmRuntimeException("Stack must not be NULL") throw new UvmRuntimeException("Stack must not be NULL")
} }
...@@ -438,13 +438,7 @@ class ClientAgent(mutator: Mutator)( ...@@ -438,13 +438,7 @@ class ClientAgent(mutator: Mutator)(
throw new UvmRuntimeException("Stack-bottom function must not be NULL") throw new UvmRuntimeException("Stack-bottom function must not be NULL")
} }
val funcVer = funcVal.versions.headOption.getOrElse { sta.pushFrame(funcVal)
throw new UvmRuntimeException("Stack-bottom function %s is not defined.".format(funcVal.repr))
}
val argBoxes = argList.map(_.vb)
sta.pushMuFrame(funcVer, argBoxes)
} }
def tr64IsFp(handle: Handle): Boolean = { def tr64IsFp(handle: Handle): Boolean = {
...@@ -545,19 +539,19 @@ class ClientAgent(mutator: Mutator)( ...@@ -545,19 +539,19 @@ class ClientAgent(mutator: Mutator)(
} }
unpin(objRef) unpin(objRef)
} }
def expose(func: Handle, callConv: Flag, cookie: Handle): Handle = { def expose(func: Handle, callConv: Flag, cookie: Handle): Handle = {
val TypeFuncRef(sig) = func.ty val TypeFuncRef(sig) = func.ty
val f = func.vb.asInstanceOf[BoxFunc].func.getOrElse { val f = func.vb.asInstanceOf[BoxFunc].func.getOrElse {
throw new UvmRuntimeException("Attempt to expose NULL Mu function") throw new UvmRuntimeException("Attempt to expose NULL Mu function")
} }
val c = cookie.vb.asInstanceOf[BoxInt].value.toLong val c = cookie.vb.asInstanceOf[BoxInt].value.toLong
val addr = microVM.nativeCallHelper.exposeFuncDynamic(f,c) val addr = microVM.nativeCallHelper.exposeFuncDynamic(f, c)
newHandle(InternalTypePool.funcPtrOf(sig), BoxPointer(addr)) newHandle(InternalTypePool.funcPtrOf(sig), BoxPointer(addr))
} }
def unexpose(callConv: Flag, addr: Handle): Unit = { def unexpose(callConv: Flag, addr: Handle): Unit = {
val a = addr.vb.asInstanceOf[BoxPointer].addr val a = addr.vb.asInstanceOf[BoxPointer].addr
microVM.nativeCallHelper.unexposeFunc(a) microVM.nativeCallHelper.unexposeFunc(a)
......
This diff is collapsed.
package uvm.refimpl.itpr package uvm.refimpl.itpr
import uvm.FuncVer import uvm.Function
import uvm.refimpl.MicroVM import uvm.refimpl.MicroVM
import uvm.refimpl.mem._ import uvm.refimpl.mem._
import scala.collection.mutable.HashMap import scala.collection.mutable.HashMap
...@@ -28,7 +28,7 @@ class ThreadStackManager(implicit microVM: MicroVM, nativeCallHelper: NativeCall ...@@ -28,7 +28,7 @@ class ThreadStackManager(implicit microVM: MicroVM, nativeCallHelper: NativeCall
def getThreadByID(id: Int): Option[InterpreterThread] = threadRegistry.get(id) def getThreadByID(id: Int): Option[InterpreterThread] = threadRegistry.get(id)
def iterateAllLiveStacks: Iterable[InterpreterStack] = stackRegistry.values.filter(_.state != StackState.Dead) def iterateAllLiveStacks: Iterable[InterpreterStack] = stackRegistry.values.filter(_.state != FrameState.Dead)
def iterateAllLiveThreads: Iterable[InterpreterThread] = threadRegistry.values.filter(_.isRunning) def iterateAllLiveThreads: Iterable[InterpreterThread] = threadRegistry.values.filter(_.isRunning)
...@@ -55,10 +55,10 @@ class ThreadStackManager(implicit microVM: MicroVM, nativeCallHelper: NativeCall ...@@ -55,10 +55,10 @@ class ThreadStackManager(implicit microVM: MicroVM, nativeCallHelper: NativeCall
* via the "new_stack" message or micro VM threads (the InterpreterThread class) which can execute the NEWSTACK * via the "new_stack" message or micro VM threads (the InterpreterThread class) which can execute the NEWSTACK
* instruction. * instruction.
*/ */
def newStack(funcVer: FuncVer, args: Seq[ValueBox], mutator: Mutator): InterpreterStack = { def newStack(func: Function, mutator: Mutator): InterpreterStack = {
val stackMemory = microVM.memoryManager.makeStackMemory(mutator) val stackMemory = microVM.memoryManager.makeStackMemory(mutator)
val id = makeStackID() val id = makeStackID()
val sta = new InterpreterStack(id, stackMemory, funcVer, args) val sta = new InterpreterStack(id, stackMemory, func)
stackRegistry.put(id, sta) stackRegistry.put(id, sta)
sta sta
} }
......
...@@ -361,8 +361,8 @@ object MemoryOperations { ...@@ -361,8 +361,8 @@ object MemoryOperations {
} }
} }
def store(ptr: Boolean, ty: Type, loc: Word, nvb: ValueBox, br: ValueBox)(implicit memorySupport: MemorySupport): Unit = { def store(ptr: Boolean, ty: Type, loc: Word, nvb: ValueBox)(implicit memorySupport: MemorySupport): Unit = {
def storeScalar(ty: Type, loc: Word, nvb: ValueBox, br: ValueBox): Unit = ty match { def storeScalar(ty: Type, loc: Word, nvb: ValueBox): Unit = ty match {
case TypeInt(l) => case TypeInt(l) =>
val bi = nvb.asInstanceOf[BoxInt].value val bi = nvb.asInstanceOf[BoxInt].value
l match { l match {
...@@ -412,12 +412,11 @@ object MemoryOperations { ...@@ -412,12 +412,11 @@ object MemoryOperations {
ty match { ty match {
case TypeVector(ety, len) => case TypeVector(ety, len) =>
val nvbs = nvb.asInstanceOf[BoxSeq].values val nvbs = nvb.asInstanceOf[BoxSeq].values
val brs = br.asInstanceOf[BoxSeq].values
val elemSkip = alignUp(sizeOf(ety), alignOf(ety)) val elemSkip = alignUp(sizeOf(ety), alignOf(ety))
for (((brElem, nvbElem), i) <- (brs zip nvbs).zipWithIndex) { for ((nvbElem, i) <- nvbs.zipWithIndex) {
storeScalar(ety, loc + elemSkip * i, nvbElem, brElem) storeScalar(ety, loc + elemSkip * i, nvbElem)
} }
case sty => storeScalar(sty, loc, nvb, br) case sty => storeScalar(sty, loc, nvb)
} }
} }
......
...@@ -14,28 +14,37 @@ import uvm.refimpl.nat.NativeCallHelper ...@@ -14,28 +14,37 @@ import uvm.refimpl.nat.NativeCallHelper
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import com.typesafe.scalalogging.Logger import com.typesafe.scalalogging.Logger
abstract class StackState /** The state of a frame. */
abstract class FrameState
object StackState {
case class Ready(t: Type) extends uvm.refimpl.itpr.StackState object FrameState {
case object Running extends StackState /** If values of ts are given, it is ready to resume. */
case object Dead extends StackState case class Ready(ts: Seq[Type]) extends FrameState
/** A thread is executing it. */
case object Running extends FrameState
/** Killed. */
case object Dead extends FrameState
} }
class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFunc: FuncVer, args: Seq[ValueBox])( /**
* 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) {
var gcMark: Boolean = false // Mark for GC. var gcMark: Boolean = false // Mark for GC.
private var _state: StackState = StackState.Ready(InternalTypes.VOID) // Initial state is READY<void> private var _top: InterpreterFrame = InterpreterFrame.forMuFunc(stackMemory.top, stackBottomFunc, 0L, None)
def state = _state /** The top frame */
private def state_=(s: StackState) = _state = s
private var _top: InterpreterFrame = InterpreterFrame.forMuFunc(stackBottomFunc, 0L, args, None)
def top = _top def top = _top
private def top_=(f: InterpreterFrame) = _top = f private def top_=(f: InterpreterFrame) = _top = f
/** The state of the stack (i.e. state of the top frame) */
def state = top.state
/** A lazily created native stack keeper. */
var maybeNSK: Option[NativeStackKeeper] = None var maybeNSK: Option[NativeStackKeeper] = None
/** Lazily create the nsk. */
private def ensureNSK(): Unit = { private def ensureNSK(): Unit = {
if (maybeNSK == None) { if (maybeNSK == None) {
val nsk = new NativeStackKeeper() val nsk = new NativeStackKeeper()
...@@ -43,6 +52,7 @@ class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFun ...@@ -43,6 +52,7 @@ class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFun
} }
} }
/** Iterate through all frames. */
def frames: Iterator[InterpreterFrame] = new AbstractIterator[InterpreterFrame] { def frames: Iterator[InterpreterFrame] = new AbstractIterator[InterpreterFrame] {
var curFrame: Option[InterpreterFrame] = Some(top) var curFrame: Option[InterpreterFrame] = Some(top)
def hasNext = curFrame.isDefined def hasNext = curFrame.isDefined
...@@ -53,122 +63,323 @@ class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFun ...@@ -53,122 +63,323 @@ class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFun
} }
} }
/** Iterate through Mu frames only. */
def muFrames: Iterator[MuFrame] = frames.filter(_.isInstanceOf[MuFrame]).map(_.asInstanceOf[MuFrame]) def muFrames: Iterator[MuFrame] = frames.filter(_.isInstanceOf[MuFrame]).map(_.asInstanceOf[MuFrame])
def pushMuFrame(funcVer: FuncVer, args: Seq[ValueBox]): Unit = { ///////// frame manipulations
val newFrame = InterpreterFrame.forMuFunc(funcVer, 0L, args, Some(top))
/** Create a new Mu frame, usually for Mu calling Mu, or OSR. */
private def pushMuFrame(func: Function): Unit = {
assert(top.isInstanceOf[MuFrame])
val newFrame = InterpreterFrame.forMuFunc(stackMemory.top, func, 0L, Some(top))
top = newFrame top = newFrame
top.savedStackPointer = stackMemory.top
} }
def pushMuFrameForCallBack(funcVer: FuncVer, cookie: Long, args: Seq[ValueBox]): Unit = { /** Create a new Mu frame for calling from native. */
val newFrame = InterpreterFrame.forMuFunc(funcVer, cookie, args, Some(top)) private def pushMuFrameForCallBack(func: Function, cookie: Long): Unit = {
assert(top.isInstanceOf[NativeFrame])
val newFrame = InterpreterFrame.forMuFunc(stackMemory.top, func, cookie, Some(top))
top = newFrame top = newFrame
top.savedStackPointer = stackMemory.top
} }
def replaceTopMuFrame(funcVer: FuncVer, args: Seq[ValueBox]): Unit = { /** Replace the top Mu frame with a frame of a different function. Usually used by tailcall. */
val newFrame = InterpreterFrame.forMuFunc(funcVer, 0L, args, top.prev) private def replaceTopMuFrame(func: Function): Unit = {
stackMemory.rewind(top.savedStackPointer) assert(top.isInstanceOf[MuFrame])
if (top.isInstanceOf[DefinedMuFrame]) {
stackMemory.rewind(top.asInstanceOf[DefinedMuFrame].savedStackPointer)
}
val newFrame = InterpreterFrame.forMuFunc(stackMemory.top, func, 0L, top.prev)
top = newFrame top = newFrame
top.savedStackPointer = stackMemory.top
} }
private def pushNativeFrame(func: Word): Unit = { /** Push a (conceptual) native frame. The "real native frame" is held by the NSK slave, of course. */
private def pushNativeFrame(sig: FuncSig, func: Word): Unit = {
assert(top.isInstanceOf[MuFrame])
val newFrame = InterpreterFrame.forNativeFunc(func, Some(top)) val newFrame = InterpreterFrame.forNativeFunc(func, Some(top))
top = newFrame top = newFrame
top.savedStackPointer = stackMemory.top
} }
def callNativeOnStack(sig: FuncSig, func: Word, args: Seq[ValueBox], retBox: ValueBox): NativeCallResult = { /** Pop a Mu frame or a native frame. Throw error when popping the bottom frame. */
private def _popFrame(): Unit = {
top = top.prev.getOrElse {
throw new UvmRuntimeException("Attemting to pop the last frame of a stack. Stack ID: %d.".format(id))
}
}
/** Pop a Mu frame */
private def popMuFrame(): Unit = {
assert(top.isInstanceOf[MuFrame]) assert(top.isInstanceOf[MuFrame])
ensureNSK() if (top.isInstanceOf[DefinedMuFrame]) {
pushNativeFrame(func) stackMemory.rewind(top.asInstanceOf[DefinedMuFrame].savedStackPointer)
val result = maybeNSK.get.callNative(sig, func, args, retBox) }
handleNativeCallResult(result) _popFrame()
result }
/** Pop a native frame */
private def popNativeFrame(): Unit = {
assert(top.isInstanceOf[NativeFrame])
_popFrame()
} }
def returnToNativeOnStack(): NativeCallResult = { /**
* Return from a Mu frame to a native frame. This will eventually resume in Mu.
* @return true if the interpreter needs to increment the PC.
*/
private def returnToNative(maybeRvb: Option[ValueBox]): Boolean = {
assert(top.isInstanceOf[NativeFrame]) assert(top.isInstanceOf[NativeFrame])
val result = maybeNSK.get.returnToCallBack() val result = maybeNSK.get.returnToNative(maybeRvb)
handleNativeCallResult(result) handleNativeCallResult(result)
result
} }
private def handleNativeCallResult(nsr: NativeCallResult): Unit = nsr match { /**
case r: NativeCallResult.Return => popNativeFrame() * Handle native call result. This will eventually resume in Mu.
case r: NativeCallResult.CallBack => top.asInstanceOf[NativeFrame].maybeCallback = Some(r) * @return true if the interpreter needs to increment the PC.
*/
private def handleNativeCallResult(ncr: NativeCallResult): Boolean = {
ncr match {
case r @ NativeCallResult.ReturnToMu(maybeRvb) => {
assert(top.isInstanceOf[NativeFrame])
popNativeFrame()
assert(top.isInstanceOf[MuFrame])
top.asInstanceOf[MuFrame].resumeNormally(maybeRvb.toSeq)
}
case r @ NativeCallResult.CallMu(func, cookie, args) => {
assert(top.isInstanceOf[NativeFrame])
pushMuFrameForCallBack(func, cookie)
top.asInstanceOf[MuFrame].resumeNormally(args.toSeq)
}
}
} }
def popFrame(): Unit = { ///////// interpreter/client-visible stack state transitions
stackMemory.rewind(top.savedStackPointer)
top = top.prev.getOrElse { /**
throw new UvmRuntimeException("Attemting to pop the last frame of a stack. Stack ID: %d.".format(id)) * Mu calling a Mu function.
*/
def callMu(func: Function, args: Seq[ValueBox]): Boolean = {
assert(top.isInstanceOf[MuFrame])
top.state = FrameState.Ready(func.sig.retTys)
pushMuFrame(func)
top.asInstanceOf[MuFrame].resumeNormally(args)
}
/** Mu tail-calling a Mu function. */
def tailCallMu(func: Function, args: Seq[ValueBox]): Boolean = {
assert(top.isInstanceOf[MuFrame])
replaceTopMuFrame(func)
top.asInstanceOf[MuFrame].resumeNormally(args)
}
/** Returning from a Mu frame. Will eventually resume in Mu.*/
def retFromMu(rvs: Seq[ValueBox]): Boolean = {
assert(top.isInstanceOf[MuFrame])
popMuFrame()
top match {
case f: MuFrame => {
f.resumeNormally(rvs)
}
case f: NativeFrame => {
val maybeRvb = rvs match {
case Seq() => None
case Seq(b) => Some(b)
case bs => throw new UvmRefImplException(
"Cannot return multiple values to native functions. Native func: 0x%x".format(f.func))
}
returnToNative(maybeRvb)
}
} }
} }
private def popNativeFrame(): Unit = { /** Mu calling a native function. */
assert(top.isInstanceOf[NativeFrame]) def callNative(sig: FuncSig, func: Word, args: Seq[ValueBox]): Boolean = {
popFrame() assert(top.isInstanceOf[MuFrame])
ensureNSK()
pushNativeFrame(sig, func)
val result = maybeNSK.get.callNative(sig, func, args)
handleNativeCallResult(result)
} }
/** Unwind to a Mu frame. The interpreter will handle the resumption. */
def unwindTo(f: InterpreterFrame): Unit = { def unwindTo(f: InterpreterFrame): Unit = {
top = f top = f
stackMemory.rewind(top.savedStackPointer) top match {
case mf: DefinedMuFrame => {
stackMemory.rewind(mf.savedStackPointer)
top.state = FrameState.Running
}
case mf: UndefinedMuFrame => {