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.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.2% of users enabled 2FA.

Commit 5c2d1c03 authored by Kunshan Wang's avatar Kunshan Wang
Browse files

Adding uvm.meta.* comminsts...

parent 6b3ecf77
......@@ -39,4 +39,23 @@ object CommInsts extends SimpleNamespace[CommInst] {
commInst(0x242, "@uvm.native.expose")
commInst(0x243, "@uvm.native.unexpose")
commInst(0x244, "@uvm.native.get_cookie")
commInst(0x250, "@uvm.meta.id_of")
commInst(0x251, "@uvm.meta.name_of")
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(0x258, "@uvm.meta.pop_frame")
commInst(0x259, "@uvm.meta.push_frame")
commInst(0x25a, "@uvm.meta.enable_watchpoint")
commInst(0x25b, "@uvm.meta.disable_watchpoint")
commInst(0x25c, "@uvm.meta.set_trap_handler")
}
\ No newline at end of file
package uvm.refimpl
import java.io.Reader
import uvm.refimpl.mem.Mutator
/** Common implementations of operations on the MicroVM. Used by both the MuCtx and many comminsts. */
object MetaOperations {
/** Load a Mu IR bundle */
def loadBundle(r: Reader)(implicit microVM: MicroVM): Unit = {
val bundle = microVM.irReader.read(r, microVM.globalBundle)
microVM.addBundle(bundle)
}
/** Load a Mu IR bundle */
def loadBundle(s: String)(implicit microVM: MicroVM): Unit = {
val bundle = microVM.irReader.read(s, microVM.globalBundle)
microVM.addBundle(bundle)
}
/** Load a HAIL script */
def loadHail(r: Reader)(implicit microVM: MicroVM, mutator: Mutator): Unit = ???
/** Load a HAIL script */
def loadHail(s: String)(implicit microVM: MicroVM, mutator: Mutator): Unit = ???
}
\ No newline at end of file
......@@ -42,6 +42,12 @@ class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE,
globalBundle.typeNs.add(InternalTypes.VOID)
globalBundle.typeNs.add(InternalTypes.BYTE)
globalBundle.typeNs.add(InternalTypes.BYTE_ARRAY)
// Types for the @uvm.meta.* common instructions.
globalBundle.typeNs.add(InternalTypes.BYTES)
globalBundle.typeNs.add(InternalTypes.BYTES_R)
globalBundle.typeNs.add(InternalTypes.REFS)
globalBundle.typeNs.add(InternalTypes.REFS_R)
}
/**
......
......@@ -13,23 +13,24 @@ import scala.collection.mutable.ArrayBuffer
import uvm.ssavariables.Flag
import uvm.refimpl.itpr.{ HowToResume => ItprHowToResume }
import scala.collection.mutable.Buffer
import java.nio.charset.Charset
object MuValue {
def apply(ty: Type, vb: ValueBox): MuValue = (ty, vb) match {
case (t: TypeInt, v: BoxInt) => MuIntValue(t, v)
case (t: TypeFloat, v: BoxFloat) => MuFloatValue(t, v)
case (t: TypeDouble, v: BoxDouble) => MuDoubleValue(t, v)
case (t: TypeRef, v: BoxRef) => MuRefValue(t, v)
case (t: TypeIRef, v: BoxIRef) => MuIRefValue(t, v)
case (t: TypeStruct, v: BoxSeq) => MuStructValue(t, v)
case (t: TypeArray, v: BoxSeq) => MuArrayValue(t, v)
case (t: TypeVector, v: BoxSeq) => MuVectorValue(t, v)
case (t: TypeFuncRef, v: BoxFunc) => MuFuncRefValue(t, v)
case (t: TypeThreadRef, v: BoxThread) => MuThreadRefValue(t, v)
case (t: TypeStackRef, v: BoxStack) => MuStackRefValue(t, v)
case (t: TypeInt, v: BoxInt) => MuIntValue(t, v)
case (t: TypeFloat, v: BoxFloat) => MuFloatValue(t, v)
case (t: TypeDouble, v: BoxDouble) => MuDoubleValue(t, v)
case (t: TypeRef, v: BoxRef) => MuRefValue(t, v)
case (t: TypeIRef, v: BoxIRef) => MuIRefValue(t, v)
case (t: TypeStruct, v: BoxSeq) => MuStructValue(t, v)
case (t: TypeArray, v: BoxSeq) => MuArrayValue(t, v)
case (t: TypeVector, v: BoxSeq) => MuVectorValue(t, v)
case (t: TypeFuncRef, v: BoxFunc) => MuFuncRefValue(t, v)
case (t: TypeThreadRef, v: BoxThread) => MuThreadRefValue(t, v)
case (t: TypeStackRef, v: BoxStack) => MuStackRefValue(t, v)
case (t: TypeTagRef64, v: BoxTagRef64) => MuTagRef64Value(t, v)
case (t: TypeUPtr, v: BoxPointer) => MuUPtrValue(t, v)
case (t: TypeUFuncPtr, v: BoxPointer) => MuUFPValue(t, v)
case (t: TypeUPtr, v: BoxPointer) => MuUPtrValue(t, v)
case (t: TypeUFuncPtr, v: BoxPointer) => MuUFPValue(t, v)
case (t, v) => {
throw new IllegalArgumentException("Improper type-box pair: %s,%s".format(t.toString, vb.getClass.getSimpleName))
}
......@@ -91,12 +92,19 @@ trait UndefinedFunctionHandler {
def handleUndefinedFunction(functionID: Int): Unit
}
object MuCtx {
val US_ASCII = Charset.forName("US-ASCII")
}
/**
* A client context. The main part of the API. It keeps thread-local states, including a set of handles. It provides
* operations on the Mu VM.
*/
class MuCtx(mutator: Mutator)(
class MuCtx(_mutator: Mutator)(
implicit microVM: MicroVM, memorySupport: MemorySupport) extends ObjectPinner {
implicit def mutator = _mutator
val handles = new HashSet[MuValue]()
val pinSet = new ArrayBuffer[Word]
......@@ -116,21 +124,23 @@ class MuCtx(mutator: Mutator)(
/** Load a Mu IR bundle */
def loadBundle(r: Reader): Unit = {
val bundle = microVM.irReader.read(r, microVM.globalBundle)
microVM.addBundle(bundle)
MetaOperations.loadBundle(r)
}
/** Load a Mu IR bundle */
def loadBundle(s: String): Unit = {
val bundle = microVM.irReader.read(s, microVM.globalBundle)
microVM.addBundle(bundle)
MetaOperations.loadBundle(s)
}
/** Load a HAIL script */
def loadHail(r: Reader): Unit = ???
def loadHail(r: Reader): Unit = {
MetaOperations.loadHail(r)
}
/** Load a HAIL script */
def loadHail(s: String): Unit = ???
def loadHail(s: String): Unit = {
MetaOperations.loadHail(s)
}
private def addHandle[T <: MuValue](h: T): T = {
handles.add(h)
......@@ -244,11 +254,11 @@ class MuCtx(mutator: Mutator)(
/** Compare general reference types for equality. */
def refEq(lhs: MuGenRefValue, rhs: MuGenRefValue): Boolean = (lhs, rhs) match {
case (l: MuRefValue, r: MuRefValue) => l.vb.objRef == r.vb.objRef
case (l: MuIRefValue, r: MuIRefValue) => l.vb.oo == r.vb.oo
case (l: MuFuncRefValue, r: MuFuncRefValue) => l.vb.func == r.vb.func
case (l: MuRefValue, r: MuRefValue) => l.vb.objRef == r.vb.objRef
case (l: MuIRefValue, r: MuIRefValue) => l.vb.oo == r.vb.oo
case (l: MuFuncRefValue, r: MuFuncRefValue) => l.vb.func == r.vb.func
case (l: MuThreadRefValue, r: MuThreadRefValue) => l.vb.thread == r.vb.thread
case (l: MuStackRefValue, r: MuStackRefValue) => l.vb.stack == r.vb.stack
case (l: MuStackRefValue, r: MuStackRefValue) => l.vb.stack == r.vb.stack
case (l, r) => {
throw new IllegalArgumentException("Bad types for refEq: %s and %s".format(
l.showTy, r.showTy))
......@@ -326,8 +336,8 @@ class MuCtx(mutator: Mutator)(
val nt = microVM.globalBundle.typeNs(newType)
val nh = (opnd, nt) match {
case (MuRefValue(ty, vb), ty2 @ TypeRef(_)) => MuRefValue(ty2, vb)
case (MuIRefValue(ty, vb), ty2 @ TypeIRef(_)) => MuIRefValue(ty2, vb)
case (MuRefValue(ty, vb), ty2 @ TypeRef(_)) => MuRefValue(ty2, vb)
case (MuIRefValue(ty, vb), ty2 @ TypeIRef(_)) => MuIRefValue(ty2, vb)
case (MuFuncRefValue(ty, vb), ty2 @ TypeFuncRef(_)) => MuFuncRefValue(ty2, vb)
case _ => {
throw new IllegalArgumentException("Bad types for refcast: opnd:%s, newType:%s".format(
......@@ -431,7 +441,7 @@ class MuCtx(mutator: Mutator)(
/** Perform compare exchange on a location. */
def cmpXchg(ordSucc: MemoryOrder, ordFail: MemoryOrder, weak: Boolean,
loc: MuIRefValue, expected: MuValue, desired: MuValue): (MuValue, Boolean) = {
loc: MuIRefValue, expected: MuValue, desired: MuValue): (MuValue, Boolean) = {
val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t)
}
......@@ -485,7 +495,7 @@ class MuCtx(mutator: Mutator)(
val sv = getStackNotNull(stack)
val itprHtr = htr match {
case HowToResume.PassValues(values) => ItprHowToResume.PassValues(values.map(_.vb))
case HowToResume.ThrowExc(exc) => ItprHowToResume.ThrowExc(exc.vb.objRef)
case HowToResume.ThrowExc(exc) => ItprHowToResume.ThrowExc(exc.vb.objRef)
}
val thr = microVM.threadStackManager.newThread(sv, itprHtr)
......@@ -500,31 +510,10 @@ class MuCtx(mutator: Mutator)(
sv.kill()
}
private def nthFrame(stack: InterpreterStack, n: Int): InterpreterFrame = {
val it = stack.frames
for (i <- (0 until n)) {
if (it.hasNext) {
it.next()
} else {
throw new UvmRuntimeException("The stack %d only has %d frames, but the %d-th frame is requested.".format(i, n))
}
}
if (it.hasNext) {
it.next()
} else {
throw new UvmRuntimeException("The stack %d only has %d frames, but the %d-th frame is requested.".format(n, n))
}
}
/** Get the ID of the current function of a frame. Return 0 for native frames. */
def curFunc(stack: MuStackRefValue, frame: Int): Int = {
val sv = getStackNotNull(stack)
val fr = nthFrame(sv, frame)
fr match {
case f: NativeFrame => 0
case f: MuFrame => f.func.id
}
sv.nthFrame(frame).curFuncID
}
/**
......@@ -533,12 +522,7 @@ class MuCtx(mutator: Mutator)(
*/
def curFuncVer(stack: MuStackRefValue, frame: Int): Int = {
val sv = getStackNotNull(stack)
val fr = nthFrame(sv, frame)
fr match {
case f: NativeFrame => 0
case f: UndefinedMuFrame => 0
case f: DefinedMuFrame => f.funcVer.id
}
sv.nthFrame(frame).curFuncVerID
}
/**
......@@ -547,18 +531,13 @@ class MuCtx(mutator: Mutator)(
*/
def curInst(stack: MuStackRefValue, frame: Int): Int = {
val sv = getStackNotNull(stack)
val fr = nthFrame(sv, frame)
fr match {
case f: NativeFrame => 0
case f: UndefinedMuFrame => 0
case f: DefinedMuFrame => if (f.justCreated) 0 else f.curInst.id
}
sv.nthFrame(frame).curInstID
}
/** Dump keep-alive variables of the current instruction. */
def dumpKeepalives(stack: MuStackRefValue, frame: Int): Seq[MuValue] = {
val sv = getStackNotNull(stack)
val fr = nthFrame(sv, frame)
val fr = sv.nthFrame(frame)
fr match {
case f: NativeFrame => {
throw new UvmRefImplException("Attempt to dump keepalives from a native frame. Funciton 0x%x".format(f.func))
......@@ -681,10 +660,10 @@ class MuCtx(mutator: Mutator)(
def pin(loc: MuValue): MuUPtrValue = {
val (objTy, (objRef, offset)) = loc match {
case MuRefValue(t, vb) => (t, (vb.objRef, 0L))
case MuRefValue(t, vb) => (t, (vb.objRef, 0L))
case MuIRefValue(t, vb) => (t, vb.oo)
case _ => {
throw new IllegalArgumentException("loc must be ref or iref. Found %s".format())
throw new IllegalArgumentException("loc must be ref or iref. Found %s".format(loc.ty))
}
}
pin(objRef)
......@@ -695,10 +674,10 @@ class MuCtx(mutator: Mutator)(
def unpin(loc: MuValue): Unit = {
val (objTy, objRef) = loc match {
case MuRefValue(t, vb) => (t, vb.objRef)
case MuRefValue(t, vb) => (t, vb.objRef)
case MuIRefValue(t, vb) => (t, vb.objRef)
case _ => {
throw new IllegalArgumentException("loc must be ref or iref. Found %s".format())
throw new IllegalArgumentException("loc must be ref or iref. Found %s".format(loc.ty))
}
}
unpin(objRef)
......@@ -748,14 +727,18 @@ object RichMuCtx {
def handleFromInt52(num: BigInt) = ctx.handleFromInt(num, 52)
def handleFromInt64(num: BigInt) = ctx.handleFromInt(num, 64)
def deleteValue(vs: MuValue*) = vs.foreach(ctx.deleteValue)
class DelayedDisposer(garbageList: Buffer[MuValue]) {
def apply[T<:MuValue](v: T): T = {
def apply[T <: MuValue](v: T): T = {
garbageList += v
v
}
def <<[T <: MuValue](v: T): T = {
garbageList += v
v
}
}
def autoDispose[T](f: DelayedDisposer => T) = {
val garbages = ArrayBuffer[MuValue]()
val dd = new DelayedDisposer(garbages)
......@@ -763,7 +746,7 @@ object RichMuCtx {
garbages.foreach(ctx.deleteValue)
rv
}
def loadInt(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuIntValue]
def loadFloat(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuFloatValue]
def loadDouble(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuDoubleValue]
......@@ -785,5 +768,24 @@ object RichMuCtx {
def storeStackRef(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuStackRefValue]
def storeTagRef64(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuTagRef64Value]
def storeVector(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuVectorValue]
def bytesToStr(bytes: MuRefValue): String = ctx.autoDispose { x =>
val hIR = x << ctx.getIRef(bytes)
val hFix = x << ctx.getFieldIRef(hIR, 0)
val hLen = x << ctx.loadInt(NOT_ATOMIC, hFix)
val len = ctx.handleToSInt(hLen).toLong
val hVar = x << ctx.getVarPartIRef(hIR)
val byteValues = for (i <- 0L until len) yield ctx.autoDispose { x =>
val hI = x << ctx.handleFromInt64(i)
val hVarI = x << ctx.shiftIRef(hVar, hI)
val hByte = x << ctx.loadInt(NOT_ATOMIC, hVarI)
val byte = ctx.handleToSInt(hByte).toByte
byte
}
val bytesArray = byteValues.toArray
val str = new String(bytesArray, MuCtx.US_ASCII)
str
}
}
}
\ No newline at end of file
......@@ -18,12 +18,21 @@ object InternalTypes {
i.name = Some(name)
i
}
def :=(idName: (Int, String)): T = {
val (id, name) = idName
i.id = id
i.name = Some(name)
i
}
}
def internal(name: String) = "@uvm.internal.types." + name
val I1 = TypeInt(1) := internal("i1")
val I6 = TypeInt(6) := internal("i6")
val I8 = TypeInt(6) := internal("i8")
val I16 = TypeInt(6) := internal("i16")
val I32 = TypeInt(32) := internal("i32")
val I52 = TypeInt(52) := internal("i52")
val I64 = TypeInt(52) := internal("i64")
......@@ -39,6 +48,11 @@ object InternalTypes {
val STACK = TypeStackRef() := internal("stack")
val THREAD = TypeThreadRef() := internal("thread")
val TAGREF64 = TypeTagRef64() := internal("tagref64")
val BYTES = TypeHybrid(Seq(I64), I8) := (0x260, "@uvm.meta.bytes")
val BYTES_R = TypeRef(BYTES) := (0x261, "@uvm.meta.bytes_r")
val REFS = TypeHybrid(Seq(I64), REF_VOID) := (0x262, "@uvm.meta.refs")
val REFS_R = TypeRef(BYTES) := (0x263, "@uvm.meta.refs_r")
}
object InternalTypePool {
......@@ -146,10 +160,28 @@ object TypeInferer {
case TypeRef(t) => Seq(ptrOf(t))
case TypeIRef(t) => Seq(ptrOf(t))
}
case "@uvm.native.unpin" => Seq()
case "@uvm.native.expose" => Seq(funcPtrOf(i.funcSigList(0)))
case "@uvm.native.unexpose" => Seq()
case "@uvm.native.get_cookie" => Seq(I64)
case "@uvm.native.unpin" => Seq()
case "@uvm.native.expose" => Seq(funcPtrOf(i.funcSigList(0)))
case "@uvm.native.unexpose" => Seq()
case "@uvm.native.get_cookie" => Seq(I64)
case "@uvm.meta.id_of" => Seq(I32)
case "@uvm.meta.name_of" => Seq(BYTES_R)
case "@uvm.meta.load_bundle" => Seq(BYTES_R)
case "@uvm.meta.load_hail" => Seq(BYTES_R)
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.push_frame" => Seq()
case "@uvm.meta.enable_watchpoint" => Seq()
case "@uvm.meta.disable_watchpoint" => Seq()
case "@uvm.meta.set_trap_handler" => Seq()
}
}
}
\ No newline at end of file
......@@ -17,7 +17,7 @@ import uvm.refimpl.nat.NativeCallResult
trait CommInstExecutor extends InterpreterActions with ObjectPinner {
import InterpreterThread.logger
protected def mutator: Mutator
implicit protected def mutator: Mutator
implicit protected def memorySupport: MemorySupport
override def interpretCurrentCommonInstruction(): Unit = {
......@@ -314,6 +314,45 @@ trait CommInstExecutor extends InterpreterActions with ObjectPinner {
continueNormally()
}
case "@uvm.meta.id_of" => {
val Seq(name) = argList
val nameStr = MemoryOperations.bytesToStr(boxOf(name).asInstanceOf[BoxRef].objRef)
val theID = microVM.idOf(nameStr)
resultBox(0).asInstanceOf[BoxInt].value = OpHelper.unprepare(theID, 32)
continueNormally()
}
case "@uvm.meta.name_of" => {
val Seq(theID) = argList
val idInt = boxOf(theID).asInstanceOf[BoxInt].value.toInt
val name = microVM.nameOf(idInt)
val bytesRef = MemoryOperations.strToBytes(name)
resultBox(0).asInstanceOf[BoxRef].objRef = bytesRef
continueNormally()
}
case "@uvm.meta.load_bundle" => {
val Seq(bundle) = argList
val bundleStr = MemoryOperations.bytesToStr(boxOf(bundle).asInstanceOf[BoxRef].objRef)
MetaOperations.loadBundle(bundleStr)
continueNormally()
}
case "@uvm.meta.load_hail" => {
val Seq(hailScript) = argList
val hailStr = MemoryOperations.bytesToStr(boxOf(hailScript).asInstanceOf[BoxRef].objRef)
MetaOperations.loadHail(hailStr)
continueNormally()
}
// Insert more CommInsts here.
case ciName => {
......
package uvm.refimpl.itpr
import uvm.types._
import uvm.ssavariables._
import java.nio.charset.Charset
import uvm.refimpl._
import uvm.refimpl.mem.TypeSizes._
import uvm.refimpl.mem.MemorySupport
import AtomicRMWOptr._
import uvm.refimpl.mem.Mutator
import uvm.refimpl.mem.TypeSizes._
import uvm.refimpl.mem.TypeSizes
import uvm.ssavariables._
import uvm.ssavariables.AtomicRMWOptr._
import uvm.types._
object OpHelper {
......@@ -564,5 +568,39 @@ object MemoryOperations {
}
case _ => throw new UnimplementedOprationException("Futex of %d bit int is not supported".format(len))
}
val US_ASCII = Charset.forName("US-ASCII")
/**
* Read an ASCII string from the memory.
*
* @param loc A ref to a @uvm.meta.bytes object.
*/
def bytesToStr(loc: Word)(implicit memorySupport: MemorySupport): String = {
// It is a hybrid<@i64 @i8> object. The length is determined by the fixed part.
val len = memorySupport.loadLong(loc)
val bytes = new Array[Byte](len.toInt)
val begin = loc + TypeSizes.WORD_SIZE_BYTES
memorySupport.loadBytes(begin, bytes, 0, len, true)
val result = new String(bytes, US_ASCII)
result
}
/**
* Create a Mu @uvm.meta.bytes object to hold an ASCII string.
*
* @return The address of the allocated object.
*/
def strToBytes(str: String)(implicit memorySupport: MemorySupport, mutator: Mutator): Word = {
val bytes = str.getBytes(US_ASCII)
val len = bytes.length
val loc = mutator.newHybrid(InternalTypes.BYTES, len)
memorySupport.storeLong(loc, bytes.length.toLong)
val begin = loc + TypeSizes.WORD_SIZE_BYTES
memorySupport.storeBytes(begin, bytes, 0, len, true)
loc
}
}
......@@ -258,6 +258,18 @@ class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFun
}
}
/**
* Return the n-th frame of the current stack.
*/
def nthFrame(n: Int): InterpreterFrame = {
val dropped = frames.drop(n)
if (dropped.hasNext) {
dropped.next
} else {
throw new UvmRuntimeException("The stack %d only has %d frames, but the %d-th frame is requested.".format(id, n))
}
}
/** Pop a frame. Part of the API. Also used by THROW */
def popFrame(): Unit = {
top match {
......@@ -281,6 +293,16 @@ abstract class InterpreterFrame(val prev: Option[InterpreterFrame]) {
* The state of the frame. Must be set when creating the frame.
*/
var state: FrameState = _
/** ID of the current function. Return 0 for native frames. */
def curFuncID: Int
/** ID of the current function version Return 0 for native frames or undefined Mu frames. */
def curFuncVerID: Int
/** ID of the current instruction. Return 0 for native frames, undefined Mu frames, or a just-created frame. */
def curInstID: Int
}
object InterpreterFrame {
......@@ -305,7 +327,11 @@ object InterpreterFrame {
}
}
class NativeFrame(val func: Word, prev: Option[InterpreterFrame]) extends InterpreterFrame(prev)
class NativeFrame(val func: Word, prev: Option[InterpreterFrame]) extends InterpreterFrame(prev) {
override def curFuncID: Int = 0
override def curFuncVerID: Int = 0
override def curInstID: Int = 0
}
abstract class MuFrame(val func: Function, prev: Option[InterpreterFrame]) extends InterpreterFrame(prev) {
/**
......@@ -354,6 +380,10 @@ class UndefinedMuFrame(func: Function, prev: Option[InterpreterFrame]) extends M
var virtInst = VIRT_INST_NOT_STARTED
override def scannableBoxes = boxes
override def curFuncID: Int = func.id
override def curFuncVerID: Int = 0
override de