Commit 22a4132f authored by Kunshan Wang's avatar Kunshan Wang

WIP: Bindings for all API messages.

parent fc2bb5bc
......@@ -43,13 +43,19 @@ typedef void (*MuCFP)();
// Result of a trap handler
typedef int MuTrapHandlerResult;
// Used by new_thread
typedef int MuHowToResume;
// Values or MuTrapHandlerResult
#define MU_THREAD_EXIT 0x00
// Values or MuTrapHandlerResult and muHowToResume
#define MU_REBIND_PASS_VALUES 0x01
#define MU_REBIND_THROW_EXC 0x02
// Used by MuTrapHandler
typedef void (*MuValuesFreer)(MuValue *values, MuCPtr freerdata);
// Declare the types here because they are used in the following signatures.
typedef struct MuVM MuVM;
typedef struct MuCtx MuCtx;
......@@ -57,13 +63,14 @@ typedef struct MuCtx MuCtx;
// Signature of the trap handler
typedef void (*MuTrapHandler)(MuCtx *ctx, MuThreadRefValue thread,
MuStackRefValue stack, int wpid, MuTrapHandlerResult *result,
MuStackRefValue *new_stack, MuValue *values, int *nvalues,
MuRefValue *exception,
MuStackRefValue *new_stack, MuValue **values, int *nvalues,
MuValuesFreer *freer, MuCPtr *freerdata, MuRefValue *exception,
MuCPtr userdata);
// Memory orders
typedef int MuMemOrd;
// Values of MuMemOrd
#define MU_NOT_ATOMIC 0x00
#define MU_RELAXED 0x01
#define MU_CONSUME 0x02
......@@ -75,6 +82,7 @@ typedef int MuMemOrd;
// Operations for the atomicrmw API function
typedef int MuAtomicRMWOp;
// Values of MuAtomicRMWOp
#define MU_XCHG 0x00
#define MU_ADD 0x01
#define MU_SUB 0x02
......@@ -213,7 +221,7 @@ struct MuCtx {
// Thread and stack creation and stack destruction
MuStackRefValue (*new_stack )(MuCtx *ctx, MuFuncRefValue func);
MuThreadRefValue (*new_thread)(MuCtx *ctx, MuStackRefValue stack,
MuHowToResume *htr, MuValue *vals, int nvals, MuRefValue *exc);
MuHowToResume *htr, MuValue *vals, int nvals, MuRefValue exc);
void (*kill_stack)(MuCtx *ctx, MuStackRefValue stack);
// Frame cursor operations
......
package uvm.refimpl.nat
import java.nio.charset.StandardCharsets
import scala.collection.mutable.HashMap
import scala.collection.mutable.HashSet
import scala.reflect.ClassTag
import scala.reflect.runtime.universe
import scala.reflect.runtime.{ universe => ru }
import org.slf4j.LoggerFactory
import com.kenai.jffi.CallingConvention
import com.kenai.jffi.Closure
import com.kenai.jffi.Closure.Buffer
import com.kenai.jffi.{ Type => JType }
import com.typesafe.scalalogging.Logger
import NativeSupport._
import PlatformConstants.WORD_SIZE_BYTES
import PlatformConstants.Word
import jnr.ffi.ObjectReferenceManager
import jnr.ffi.Pointer
import uvm.refimpl._
import uvm.ssavariables.MemoryOrder
import uvm.ssavariables.AtomicRMWOptr
import uvm.ssavariables.Flag
import uvm.ssavariables.Flag
/**
* This object calls a C function to handle the trap.
......@@ -39,14 +39,14 @@ object NativeMuVM {
import NativeMuHelpers._
import NativeClientSupport._
def new_context(microVM: MicroVM): MuCtxPtr = {
def new_context(microVM: MicroVM): MuCtxFak = {
val ctx = microVM.newContext()
val ptr = exposeMuCtx(ctx)
ptr
}
def id_of(microVM: MicroVM, name: MuName): MuID = microVM.idOf(name)
def name_of(microVM: MicroVM, id: MuID): MuName = microVM.nameOf(id)
def set_trap_handler(microVM: MicroVM, trap_handler: Word, userdata: Word): Unit = {
def set_trap_handler(microVM: MicroVM, trap_handler: MuTrapHandlerFP, userdata: MuCPtr): Unit = {
microVM.setTrapHandler(new NativeTrapHandler(trap_handler, userdata))
}
}
......@@ -68,34 +68,34 @@ object NativeMuCtx {
* NOTE: Should have taken MuCtx as the first parameter, but we need to de-allocate
* the function table, too.
*/
def close_context(funcTableAddr: Word): Unit = {
def close_context(funcTableAddr: FuncTablePtr): Unit = {
val ctx = getObjFromFuncTableAddrNotNull(funcTableAddr, NativeClientSupport.muCtxs)
unexposeMuCtx(funcTableAddr)
ctx.closeContext()
}
def load_bundle(ctx: MuCtx, buf: Word, sz: Int): Unit = {
def load_bundle(ctx: MuCtx, buf: CharArrayPtr, sz: Int): Unit = {
val str = theMemory.getString(buf, sz, StandardCharsets.US_ASCII)
ctx.loadBundle(str)
}
def load_hail(ctx: MuCtx, buf: Word, sz: Int): Unit = {
def load_hail(ctx: MuCtx, buf: CharArrayPtr, sz: Int): Unit = {
val str = theMemory.getString(buf, sz, StandardCharsets.US_ASCII)
ctx.loadHail(str)
}
def handle_from_sint8(ctx: MuCtx, num: Byte, len: Int): MuValuePtr = handleFromInt(ctx, num, len)
def handle_from_uint8(ctx: MuCtx, num: Byte, len: Int): MuValuePtr = handleFromInt(ctx, trunc(num, 8), len)
def handle_from_sint16(ctx: MuCtx, num: Short, len: Int): MuValuePtr = handleFromInt(ctx, num, len)
def handle_from_uint16(ctx: MuCtx, num: Short, len: Int): MuValuePtr = handleFromInt(ctx, trunc(num, 16), len)
def handle_from_sint32(ctx: MuCtx, num: Int, len: Int): MuValuePtr = handleFromInt(ctx, num, len)
def handle_from_uint32(ctx: MuCtx, num: Int, len: Int): MuValuePtr = handleFromInt(ctx, trunc(num, 32), len)
def handle_from_sint64(ctx: MuCtx, num: Long, len: Int): MuValuePtr = handleFromInt(ctx, num, len)
def handle_from_uint64(ctx: MuCtx, num: Long, len: Int): MuValuePtr = handleFromInt(ctx, trunc(num, 64), len)
def handle_from_float(ctx: MuCtx, num: Float): MuValuePtr = exposeMuValue(ctx, ctx.handleFromFloat(num))
def handle_from_double(ctx: MuCtx, num: Double): MuValuePtr = exposeMuValue(ctx, ctx.handleFromDouble(num))
def handle_from_ptr(ctx: MuCtx, mu_type: MuID, ptr: MuCPtr): MuValuePtr = exposeMuValue(ctx, ctx.handleFromPtr(mu_type, ptr))
def handle_from_fp(ctx: MuCtx, mu_type: MuID, fp: MuCFP): MuValuePtr = exposeMuValue(ctx, ctx.handleFromFP(mu_type, fp))
def handle_from_sint8(ctx: MuCtx, num: Byte, len: Int): MuValueFak = handleFromInt(ctx, num, len)
def handle_from_uint8(ctx: MuCtx, num: Byte, len: Int): MuValueFak = handleFromInt(ctx, trunc(num, 8), len)
def handle_from_sint16(ctx: MuCtx, num: Short, len: Int): MuValueFak = handleFromInt(ctx, num, len)
def handle_from_uint16(ctx: MuCtx, num: Short, len: Int): MuValueFak = handleFromInt(ctx, trunc(num, 16), len)
def handle_from_sint32(ctx: MuCtx, num: Int, len: Int): MuValueFak = handleFromInt(ctx, num, len)
def handle_from_uint32(ctx: MuCtx, num: Int, len: Int): MuValueFak = handleFromInt(ctx, trunc(num, 32), len)
def handle_from_sint64(ctx: MuCtx, num: Long, len: Int): MuValueFak = handleFromInt(ctx, num, len)
def handle_from_uint64(ctx: MuCtx, num: Long, len: Int): MuValueFak = handleFromInt(ctx, trunc(num, 64), len)
def handle_from_float(ctx: MuCtx, num: Float): MuValueFak = exposeMuValue(ctx, ctx.handleFromFloat(num))
def handle_from_double(ctx: MuCtx, num: Double): MuValueFak = exposeMuValue(ctx, ctx.handleFromDouble(num))
def handle_from_ptr(ctx: MuCtx, mu_type: MuID, ptr: MuCPtr): MuValueFak = exposeMuValue(ctx, ctx.handleFromPtr(mu_type, ptr))
def handle_from_fp(ctx: MuCtx, mu_type: MuID, fp: MuCFP): MuValueFak = exposeMuValue(ctx, ctx.handleFromFP(mu_type, fp))
def handle_to_sint8(ctx: MuCtx, opnd: MuIntValue): Byte = ctx.handleToSInt(opnd).toByte
def handle_to_uint8(ctx: MuCtx, opnd: MuIntValue): Byte = ctx.handleToUInt(opnd).toByte
......@@ -110,19 +110,113 @@ object NativeMuCtx {
def handle_to_ptr(ctx: MuCtx, opnd: MuUPtrValue): MuCPtr = ctx.handleToPtr(opnd)
def handle_to_fp(ctx: MuCtx, opnd: MuUFPValue): MuCFP = ctx.handleToFP(opnd)
def handle_from_const(ctx: MuCtx, id: MuID): MuValuePtr = exposeMuValue(ctx, ctx.handleFromConst(id))
def handle_from_global(ctx: MuCtx, id: MuID): MuValuePtr = exposeMuValue(ctx, ctx.handleFromGlobal(id))
def handle_from_func(ctx: MuCtx, id: MuID): MuValuePtr = exposeMuValue(ctx, ctx.handleFromFunc(id))
def handle_from_expose(ctx: MuCtx, id: MuID): MuValuePtr = exposeMuValue(ctx, ctx.handleFromExpose(id))
def handle_from_const(ctx: MuCtx, id: MuID): MuValueFak = exposeMuValue(ctx, ctx.handleFromConst(id))
def handle_from_global(ctx: MuCtx, id: MuID): MuValueFak = exposeMuValue(ctx, ctx.handleFromGlobal(id))
def handle_from_func(ctx: MuCtx, id: MuID): MuValueFak = exposeMuValue(ctx, ctx.handleFromFunc(id))
def handle_from_expose(ctx: MuCtx, id: MuID): MuValueFak = exposeMuValue(ctx, ctx.handleFromExpose(id))
/** Need to dispose the value manually. */
def delete_value(ctx: MuCtx, opnd: MuValuePtr): Unit = {
def delete_value(ctx: MuCtx, opnd: MuValueFak): Unit = {
logger.debug("Deleting %d 0x%x".format(opnd, opnd))
val muVal = getMuValueNotNull(opnd)
unexposeMuValue(ctx, opnd)
ctx.deleteValue(muVal)
}
def ref_eq(ctx: MuCtx, lhs: MuGenRefValue, rhs: MuGenRefValue): Int = if (ctx.refEq(lhs, rhs)) 1 else 0
def ref_ult(ctx: MuCtx, lhs: MuIRefValue, rhs: MuIRefValue): Int = if (ctx.refUlt(lhs, rhs)) 1 else 0
def extract_value(ctx: MuCtx, str: MuStructValue, index: Int): MuValueFak = exposeMuValue(ctx, ctx.extractValue(str, index))
def insert_value(ctx: MuCtx, str: MuStructValue, index: Int, newval: MuValue): MuValueFak = exposeMuValue(ctx, ctx.insertValue(str, index, newval))
def extract_element[T <: MuSeqValue](ctx: MuCtx, str: T, index: MuIntValue): MuValueFak = exposeMuValue(ctx, ctx.extractElement(str, index))
def insert_element[T <: MuSeqValue](ctx: MuCtx, str: T, index: MuIntValue, newval: MuValue): MuValueFak = exposeMuValue(ctx, ctx.insertElement(str, index, newval))
def new_fixed(ctx: MuCtx, mu_type: MuID): MuValueFak = exposeMuValue(ctx, ctx.newFixed(mu_type))
def new_hybrid(ctx: MuCtx, mu_type: MuID, length: MuIntValue): MuValueFak = exposeMuValue(ctx, ctx.newHybrid(mu_type, length))
def refcast[T <: MuGenRefValue](ctx: MuCtx, opnd: T, new_type: MuID): MuValueFak = exposeMuValue(ctx, ctx.refcast(opnd, new_type))
def get_iref(ctx: MuCtx, opnd: MuRefValue): MuValueFak = exposeMuValue(ctx, ctx.getIRef(opnd))
def get_field_iref(ctx: MuCtx, opnd: MuIRefValue, field: Int): MuValueFak = exposeMuValue(ctx, ctx.getFieldIRef(opnd, field))
def get_elem_iref(ctx: MuCtx, opnd: MuIRefValue, index: MuIntValue): MuValueFak = exposeMuValue(ctx, ctx.getElemIRef(opnd, index))
def shift_iref(ctx: MuCtx, opnd: MuIRefValue, offset: MuIntValue): MuValueFak = exposeMuValue(ctx, ctx.shiftIRef(opnd, offset))
def get_var_part_iref(ctx: MuCtx, opnd: MuIRefValue): MuValueFak = exposeMuValue(ctx, ctx.getVarPartIRef(opnd))
def load(ctx: MuCtx, ord: MuMemOrd, loc: MuIRefValue): MuValueFak = exposeMuValue(ctx, ctx.load(ord, loc))
def store(ctx: MuCtx, ord: MuMemOrd, loc: MuIRefValue, newval: MuValue): Unit = ctx.store(ord, loc, newval)
def cmpxchg(ctx: MuCtx, ord_succ: MuMemOrd, ord_fail: MuMemOrd, weak: Int, loc: MuIRefValue, expected: MuValue, desired: MuValue, is_succ: IntPtr): MuValueFak = {
val (rv, succ) = ctx.cmpXchg(ord_succ, ord_fail, weak != 0, loc, expected, desired)
theMemory.putInt(is_succ, if (succ) 1 else 0)
exposeMuValue(ctx, rv)
}
def atomicrmw(ctx: MuCtx, ord: MuMemOrd, op: MuAtomicRMWOp, loc: MuIRefValue, opnd: MuValue): MuValueFak = {
val rv = ctx.atomicRMW(ord, op, loc, opnd)
exposeMuValue(ctx, rv)
}
def fence(ctx: MuCtx, ord: MuMemOrd): Unit = ctx.fence(ord)
def new_stack(ctx: MuCtx, func: MuFuncRefValue): MuValueFak = exposeMuValue(ctx, ctx.newStack(func))
def new_thread(ctx: MuCtx, stack: MuStackRefValue, htr: MuHowToResume, vals: MuValueFakArrayPtr, nvals: Int, exc: MuRefValue): MuValueFak = {
val scalaHtr = htr match {
case MU_REBIND_PASS_VALUES => {
val values = for (i <- 0L until nvals) yield {
val addr = vals + i * WORD_SIZE_BYTES
val valFak = theMemory.getAddress(addr)
val v = getMuValueNotNull(valFak)
v
}
HowToResume.PassValues(values)
}
case MU_REBIND_THROW_EXC => {
HowToResume.ThrowExc(exc)
}
}
val rv = ctx.newThread(stack, scalaHtr)
exposeMuValue(ctx, rv)
}
def kill_stack(ctx: MuCtx, stack: MuStackRefValue): Unit = ctx.killStack(stack)
// Frame cursor operations
def new_cursor(ctx: MuCtx, stack: MuStackRefValue): MuValueFak = exposeMuValue(ctx, ctx.newCursor(stack))
def next_frame(ctx: MuCtx, cursor: MuFCRefValue): Unit = ctx.nextFrame(cursor)
def copy_cursor(ctx: MuCtx, cursor: MuFCRefValue): MuValueFak = exposeMuValue(ctx, ctx.copyCursor(cursor))
def close_cursor(ctx: MuCtx, cursor: MuFCRefValue): Unit = ctx.closeCursor(cursor)
// Stack introspection
def cur_func(ctx: MuCtx, cursor: MuFCRefValue): MuID = ctx.curFunc(cursor)
def cur_func_ver(ctx: MuCtx, cursor: MuFCRefValue): MuID = ctx.curFuncVer(cursor)
def cur_inst(ctx: MuCtx, cursor: MuFCRefValue): MuID = ctx.curInst(cursor)
def dump_keepalives(ctx: MuCtx, cursor: MuFCRefValue, results: MuValueFakArrayPtr): Unit = {
val kas = ctx.dumpKeepalives(cursor)
for ((ka, i) <- kas.zipWithIndex) {
val fak = exposeMuValue(ctx, ka)
val addr = results + i * WORD_SIZE_BYTES
theMemory.putAddress(addr, fak)
}
}
def pop_frames_to(ctx: MuCtx, cursor: MuFCRefValue): Unit = ctx.popFramesTo(cursor)
def push_frame(ctx: MuCtx, stack: MuStackRefValue, func: MuFuncRefValue): Unit = ctx.pushFrame(stack, func)
def tr64_is_fp(ctx: MuCtx, value: MuTagRef64Value): Int = if (ctx.tr64IsFp(value)) 1 else 0
def tr64_is_int(ctx: MuCtx, value: MuTagRef64Value): Int = if (ctx.tr64IsInt(value)) 1 else 0
def tr64_is_ref(ctx: MuCtx, value: MuTagRef64Value): Int = if (ctx.tr64IsRef(value)) 1 else 0
def tr64_to_fp(ctx: MuCtx, value: MuTagRef64Value): MuValueFak = exposeMuValue(ctx, ctx.tr64ToFp(value))
def tr64_to_int(ctx: MuCtx, value: MuTagRef64Value): MuValueFak = exposeMuValue(ctx, ctx.tr64ToInt(value))
def tr64_to_ref(ctx: MuCtx, value: MuTagRef64Value): MuValueFak = exposeMuValue(ctx, ctx.tr64ToRef(value))
def tr64_to_tag(ctx: MuCtx, value: MuTagRef64Value): MuValueFak = exposeMuValue(ctx, ctx.tr64ToTag(value))
def tr64_from_fp(ctx: MuCtx, value: MuDoubleValue): MuValueFak = exposeMuValue(ctx, ctx.tr64FromFp(value))
def tr64_from_int(ctx: MuCtx, value: MuIntValue): MuValueFak = exposeMuValue(ctx, ctx.tr64FromInt(value))
def tr64_from_ref(ctx: MuCtx, ref: MuRefValue, tag: MuIntValue): MuValueFak = exposeMuValue(ctx, ctx.tr64FromRef(ref, tag))
def enable_watchpoint(ctx: MuCtx, wpid: Int): Unit = ctx.enableWatchpoint(wpid)
def disable_watchpoint(ctx: MuCtx, wpid: Int): Unit = ctx.disableWatchpoint(wpid)
def pin(ctx: MuCtx, loc: MuValue): MuValueFak = exposeMuValue(ctx, ctx.pin(loc))
def unpin(ctx: MuCtx, loc: MuValue): Unit = ctx.unpin(loc)
def expose(ctx: MuCtx, func: MuFuncRefValue, call_conv: MuCallConv, cookie: MuIntValue): MuValueFak = exposeMuValue(ctx, ctx.expose(func, call_conv, cookie))
def unexpose(ctx: MuCtx, call_conv: MuCallConv, value: MuUFPValue): Unit = ctx.unexpose(call_conv, value)
}
/**
......@@ -131,7 +225,7 @@ object NativeMuCtx {
object NativeMuHelpers {
import NativeClientSupport._
val ONE = BigInt(1)
private val ONE = BigInt(1)
/**
* Convert unsigned integer to BigInt.
......@@ -143,15 +237,69 @@ object NativeMuHelpers {
*/
def trunc(num: BigInt, len: Int): BigInt = num & ((ONE << len) - ONE)
def handleFromInt(ctx: MuCtx, num: BigInt, len: Int): MuValuePtr = {
def handleFromInt(ctx: MuCtx, num: BigInt, len: Int): MuValueFak = {
exposeMuValue(ctx, ctx.handleFromInt(num, len))
}
val MU_THREAD_EXIT = 0x00
val MU_REBIND_PASS_VALUES = 0x01
val MU_REBIND_THROW_EXC = 0x02
val MU_NOT_ATOMIC = 0x00
val MU_RELAXED = 0x01
val MU_CONSUME = 0x02
val MU_ACQUIRE = 0x03
val MU_RELEASE = 0x04
val MU_ACQ_REL = 0x05
val MU_SEQ_CST = 0x06
val MU_XCHG = 0x00
val MU_ADD = 0x01
val MU_SUB = 0x02
val MU_AND = 0x03
val MU_NAND = 0x04
val MU_OR = 0x05
val MU_XOR = 0x06
val MU_MAX = 0x07
val MU_MIN = 0x08
val MU_UMAX = 0x09
val MU_UMIN = 0x0A
val MU_DEFAULT = 0x00
implicit def intToMemOrd(ord: MuMemOrd): MemoryOrder.MemoryOrder = ord match {
case MU_NOT_ATOMIC => MemoryOrder.NOT_ATOMIC
case MU_RELAXED => MemoryOrder.RELAXED
case MU_CONSUME => MemoryOrder.CONSUME
case MU_ACQUIRE => MemoryOrder.ACQUIRE
case MU_RELEASE => MemoryOrder.RELEASE
case MU_ACQ_REL => MemoryOrder.ACQ_REL
case MU_SEQ_CST => MemoryOrder.SEQ_CST
}
implicit def intToMemAtomicRMWOp(op: MuAtomicRMWOp): AtomicRMWOptr.AtomicRMWOptr = op match {
case MU_XCHG => AtomicRMWOptr.XCHG
case MU_ADD => AtomicRMWOptr.ADD
case MU_SUB => AtomicRMWOptr.SUB
case MU_AND => AtomicRMWOptr.AND
case MU_NAND => AtomicRMWOptr.NAND
case MU_OR => AtomicRMWOptr.OR
case MU_XOR => AtomicRMWOptr.XOR
case MU_MAX => AtomicRMWOptr.MAX
case MU_MIN => AtomicRMWOptr.MIN
case MU_UMAX => AtomicRMWOptr.UMAX
case MU_UMIN => AtomicRMWOptr.UMIN
}
implicit def intToCallConv(cc: MuCallConv): Flag = cc match {
case MU_DEFAULT => Flag("#DEFAULT")
}
}
object ClientAccessibleClassExposer {
val MAX_NAME_SIZE = 65536
import NativeClientSupport._
val logger = Logger(LoggerFactory.getLogger(getClass.getName))
val MAX_NAME_SIZE = 65536
// Type objects for common types.
val TUnit = ru.typeTag[Unit].tpe
......@@ -258,6 +406,7 @@ object ClientAccessibleClassExposer {
class ClientAccessibleClassExposer[T: ru.TypeTag: ClassTag](obj: T) {
import ClientAccessibleClassExposer._
import NativeSupport._
import NativeClientSupport._
/**
* A list of JFFI closure handles, one for each declared method in obj, in the declared order.
......@@ -320,7 +469,7 @@ class ClientAccessibleClassExposer[T: ru.TypeTag: ClassTag](obj: T) {
*
* @return The address of the function table.
*/
def makeFuncTable(objAddr: Word): Word = {
def makeFuncTable(objAddr: Word): FuncTablePtr = {
val nMethods = closureHandles.size
val structSizeWords = nMethods + 1
val structSizeBytes = structSizeWords * WORD_SIZE_BYTES.toInt
......@@ -356,16 +505,28 @@ class ClientAccessibleClassExposer[T: ru.TypeTag: ClassTag](obj: T) {
object NativeClientSupport {
val logger = Logger(LoggerFactory.getLogger(getClass.getName))
// Syntax sugar for MuCtx and MuValue return values, which are pointers
// Syntax sugar for C-level pointer types.
// "Fak" means "fake pointer", i.e. ObjectReferenceManager-generated "pointer".
type FuncTablePtr = Word
type MuVMPtr = FuncTablePtr
type MuCtxPtr = FuncTablePtr
type MuValuePtr = Word
type MuVMFak = FuncTablePtr
type MuCtxFak = FuncTablePtr
type MuValueFak = Word
type MuTrapHandlerFP = Word
type IntPtr = Word
type CharArrayPtr = Word
type MuValueFakPtr = Word
type MuValueFakArrayPtr = Word
// Mu API C-level types.
type MuID = Int
type MuName = String
type MuCPtr = Word
type MuCFP = Word
type MuMemOrd = Int
type MuAtomicRMWOp = Int
type MuHowToResume = Int
type MuHowToResumePtr = IntPtr
type MuCallConv = Int
// Give exposed objects a random "memory address" so native programs can pass them back to Mu as parameters.
val microVMs = jnrRuntime.newObjectReferenceManager[MicroVM]()
......@@ -373,23 +534,23 @@ object NativeClientSupport {
val muValues = jnrRuntime.newObjectReferenceManager[MuValue]()
/** Map each MuCtx to all of its current MuValues. This is needed when closing a MuCtx. */
val muCtxToMuValues = HashMap[MuCtx, HashSet[MuValuePtr]]()
val muCtxToMuValueFaks = HashMap[MuCtx, HashSet[MuValueFak]]()
/** Given a function table pointer, get an object from a ObjectReferenceManager. Assert it is not null. */
def getObjFromFuncTableAddrNotNull[T](funcTableAddr: FuncTablePtr, orm: ObjectReferenceManager[T]): T = {
val objAddr = theMemory.getAddress(funcTableAddr)
val obj = orm.get(jnrMemoryManager.newPointer(objAddr))
val objFak = theMemory.getAddress(funcTableAddr)
val obj = orm.get(jnrMemoryManager.newPointer(objFak))
if (obj == null) {
throw new UvmRefImplException("Exposed object not found. Address: %d 0x%x".format(objAddr, objAddr))
throw new UvmRefImplException("Exposed object not found. Fake address: %d 0x%x".format(objFak, objFak))
}
obj
}
/** Get the MuValue instance form a C MuValue (a pointer). */
def getMuValueNotNull(addr: MuValuePtr): MuValue = {
val muVal = muValues.get(jnrMemoryManager.newPointer(addr))
def getMuValueNotNull(fak: MuValueFak): MuValue = {
val muVal = muValues.get(jnrMemoryManager.newPointer(fak))
if (muVal == null) {
throw new UvmRefImplException("Exposed MuValue not found. Address: %d 0x%x".format(addr, addr))
throw new UvmRefImplException("Exposed MuValue not found. Fake address: %d 0x%x".format(fak, fak))
}
muVal
}
......@@ -413,30 +574,30 @@ object NativeClientSupport {
// Expose and unexpose objects
/** Expose a MicroVM. Return a pointer to the C MuVM structure. */
def exposeMicroVM(microVM: MicroVM): Word = {
val objAddr = microVMs.add(microVM).address()
val funcTableAddr = muVMExposer.makeFuncTable(objAddr)
def exposeMicroVM(microVM: MicroVM): FuncTablePtr = {
val objFak = microVMs.add(microVM).address()
val funcTableAddr = muVMExposer.makeFuncTable(objFak)
funcTableAddr
}
/** Expose a MuCtx. Return a pointer to the C MuCtx structure. */
def exposeMuCtx(muCtx: MuCtx): Word = {
require(!muCtxToMuValues.contains(muCtx), "Context %s is already exposed.".format(muCtx))
muCtxToMuValues(muCtx) = HashSet()
val objAddr = muCtxs.add(muCtx).address()
val funcTableAddr = muCtxExposer.makeFuncTable(objAddr)
def exposeMuCtx(muCtx: MuCtx): FuncTablePtr = {
require(!muCtxToMuValueFaks.contains(muCtx), "Context %s is already exposed.".format(muCtx))
muCtxToMuValueFaks(muCtx) = HashSet()
val objFak = muCtxs.add(muCtx).address()
val funcTableAddr = muCtxExposer.makeFuncTable(objFak)
funcTableAddr
}
/** Expose a MuValue. Return an "object pointer", i.e. faked by ObjectReferenceManager. */
def exposeMuValue(muCtx: MuCtx, muValue: MuValue): Word = {
val addr = muValues.add(muValue).address()
muCtxToMuValues(muCtx).add(addr)
addr
def exposeMuValue(muCtx: MuCtx, muValue: MuValue): MuValueFak = {
val fak = muValues.add(muValue).address()
muCtxToMuValueFaks(muCtx).add(fak)
fak
}
/** Unexpose a MicroVM. Remove the faked pointer and deallocate the function table (by removing the Pointer). */
def unexposeMicroVM(funcTableAddr: Word): Unit = {
def unexposeMicroVM(funcTableAddr: FuncTablePtr): Unit = {
require(funcTableToPointer.contains(funcTableAddr),
"MuVM struct pointer %d 0x%x does not exist".format(funcTableAddr, funcTableAddr))
val objPtr = theMemory.getPointer(funcTableAddr)
......@@ -448,12 +609,12 @@ object NativeClientSupport {
* Unexpose a MuCtx. Remove the faked pointer and deallocate the function table (by removing the Pointer).
* Also unexpose all MuValues held by the MuCtx.
*/
def unexposeMuCtx(funcTableAddr: Long): Unit = {
def unexposeMuCtx(funcTableAddr: FuncTablePtr): Unit = {
require(funcTableToPointer.contains(funcTableAddr),
"MuCtx struct pointer %d 0x%x does not exist".format(funcTableAddr, funcTableAddr))
val objPtr = theMemory.getPointer(funcTableAddr)
val muCtx = muCtxs.get(objPtr).ensuring { _ != null }
for (muValueAddr <- muCtxToMuValues.remove(muCtx).ensuring(_.isDefined).get) {
for (muValueAddr <- muCtxToMuValueFaks.remove(muCtx).ensuring(_.isDefined).get) {
// Don't remove it from muCtxToMuValues(muCtx) because the whole HashSet has just been detached.
muValues.remove(jnrMemoryManager.newPointer(muValueAddr)).ensuring(_ == true)
}
......@@ -462,8 +623,8 @@ object NativeClientSupport {
}
/** Unexpose a MuValue by removing it from the ORM. */
def unexposeMuValue(muCtx: MuCtx, addr: Long): Unit = {
muCtxToMuValues(muCtx).remove(addr)
def unexposeMuValue(muCtx: MuCtx, addr: MuValueFak): Unit = {
muCtxToMuValueFaks(muCtx).remove(addr)
muValues.remove(jnrMemoryManager.newPointer(addr)).ensuring(_ == true)
}
}
\ No newline at end of file
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