Commit b2e215ec authored by Kunshan Wang's avatar Kunshan Wang

Memory operations via pointers.

parent 31a531fe
......@@ -94,6 +94,11 @@ class ClientAgent(microVM: MicroVM) {
val et = t.elemTy.asInstanceOf[TypeDouble]
newHandle(t, BoxVector(vs.map(BoxDouble)))
}
def putPointer(typeID: Int, v: Word): Handle = {
val t = microVM.globalBundle.typeNs(typeID)
newHandle(t, BoxPointer(v))
}
def putConstant(id: Int): Handle = {
val c = microVM.globalBundle.constantNs(id)
......@@ -152,6 +157,10 @@ class ClientAgent(microVM: MicroVM) {
def toDoubleVec(h: Handle): Seq[Double] = {
h.vb.asInstanceOf[BoxVector].values.map(b => b.asInstanceOf[BoxDouble].value)
}
def toPointer(h: Handle): Word = {
h.vb.asInstanceOf[BoxPointer].addr
}
def extractValue(str: Handle, index: Int): Handle = {
val st = str.ty.asInstanceOf[TypeStruct]
......@@ -251,48 +260,56 @@ class ClientAgent(microVM: MicroVM) {
}
def load(ord: MemoryOrder, loc: Handle): Handle = {
val ty = loc.ty.asInstanceOf[TypeIRef].ty
val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t)
case TypePtr(t) => (true, t)
}
val uty = InternalTypePool.unmarkedOf(ty)
val b = loc.vb.asInstanceOf[BoxIRef]
val iRef = b.objRef + b.offset
val addr = MemoryOperations.addressOf(ptr, loc.vb)
val nb = ValueBox.makeBoxForType(uty)
MemoryOperations.load(uty, iRef, nb)
MemoryOperations.load(ptr, uty, addr, nb)
newHandle(uty, nb)
}
def store(ord: MemoryOrder, loc: Handle, newVal: Handle): Unit = {
val ty = loc.ty.asInstanceOf[TypeIRef].ty
val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t)
case TypePtr(t) => (true, t)
}
val uty = InternalTypePool.unmarkedOf(ty)
val lb = loc.vb.asInstanceOf[BoxIRef]
val iRef = lb.objRef + lb.offset
val addr = MemoryOperations.addressOf(ptr, loc.vb)
val nvb = newVal.vb
val nb = ValueBox.makeBoxForType(uty)
MemoryOperations.store(uty, iRef, nvb, nb)
MemoryOperations.store(ptr, uty, addr, nvb, nb)
}
def cmpXchg(ordSucc: MemoryOrder, ordFail: MemoryOrder, weak: Boolean, loc: Handle, expected: Handle, desired: Handle): (Boolean, Handle) = {
val ty = loc.ty.asInstanceOf[TypeIRef].ty
val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t)
case TypePtr(t) => (true, t)
}
val uty = InternalTypePool.unmarkedOf(ty)
val lb = loc.vb.asInstanceOf[BoxIRef]
val iRef = lb.objRef + lb.offset
val addr = MemoryOperations.addressOf(ptr, loc.vb)
val eb = expected.vb
val db = desired.vb
val br = ValueBox.makeBoxForType(uty)
val succ = MemoryOperations.cmpXchg(uty, iRef, eb, db, br)
val succ = MemoryOperations.cmpXchg(ptr, uty, addr, eb, db, br)
(succ, newHandle(uty, br))
}
def atomicRMW(ord: MemoryOrder, op: AtomicRMWOptr, loc: Handle, opnd: Handle): Handle = {
val ty = loc.ty.asInstanceOf[TypeIRef].ty
val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t)
case TypePtr(t) => (true, t)
}
val uty = InternalTypePool.unmarkedOf(ty)
val lb = loc.vb.asInstanceOf[BoxIRef]
val iRef = lb.objRef + lb.offset
val addr = MemoryOperations.addressOf(ptr, loc.vb)
val ob = opnd.vb
val br = ValueBox.makeBoxForType(uty)
MemoryOperations.atomicRMW(uty, op, iRef, ob, br)
MemoryOperations.atomicRMW(ptr, uty, op, addr, ob, br)
newHandle(uty, br)
}
......
......@@ -50,7 +50,9 @@ object InternalTypePool {
val refOf = LazyPool(TypeRef)
val irefOf = LazyPool(TypeIRef)
val ptrOf = LazyPool(TypePtr)
val funcOf = LazyPool(TypeFunc)
val funcPtrOf = LazyPool(TypeFuncPtr)
val vecOf = new LazyPool[(Type, Long), TypeVector]({ case (t, l) => TypeVector(t, l) })
def unmarkedOf(t: Type): Type = t match {
case TypeWeakRef(r) => refOf(r)
......@@ -61,6 +63,11 @@ object InternalTypePool {
object TypeInferer {
import InternalTypes._
import InternalTypePool._
def ptrOrIRefOf(ptr: Boolean, ty: Type): Type = {
if (ptr) ptrOf(ty) else irefOf(ty)
}
def inferType(v: SSAVariable): Type = v match {
case c: Constant => c.constTy
case g: GlobalCell => irefOf(g.cellTy)
......@@ -93,11 +100,11 @@ object TypeInferer {
case i: InstAlloca => irefOf(i.allocTy)
case i: InstAllocaHybrid => irefOf(i.allocTy)
case i: InstGetIRef => irefOf(i.referentTy)
case i: InstGetFieldIRef => irefOf(i.referentTy.fieldTy(i.index))
case i: InstGetElemIRef => irefOf(i.referentTy.elemTy)
case i: InstShiftIRef => irefOf(i.referentTy)
case i: InstGetFixedPartIRef => irefOf(i.referentTy.fixedTy)
case i: InstGetVarPartIRef => irefOf(i.referentTy.varTy)
case i: InstGetFieldIRef => ptrOrIRefOf(i.ptr, i.referentTy.fieldTy(i.index))
case i: InstGetElemIRef => ptrOrIRefOf(i.ptr, i.referentTy.elemTy)
case i: InstShiftIRef => ptrOrIRefOf(i.ptr, i.referentTy)
case i: InstGetFixedPartIRef => ptrOrIRefOf(i.ptr, i.referentTy.fixedTy)
case i: InstGetVarPartIRef => ptrOrIRefOf(i.ptr, i.referentTy.varTy)
case i: InstLoad => unmarkedOf(i.referentTy)
case i: InstStore => VOID
case i: InstCmpXchg => unmarkedOf(i.referentTy)
......
......@@ -17,10 +17,10 @@ object InterpreterThread {
class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, initialStack: InterpreterStack, val mutator: Mutator) {
import InterpreterThread._
// Injectable resources (used by memory access instructions)
implicit private val memorySupport = microVM.memoryManager.memorySupport
// Thread states
/** The underlying stack. */
......@@ -215,7 +215,7 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
}
writeBooleanResult(result, br)
}
def doIRef(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
val op1v = b1.asInstanceOf[BoxIRef].oo
val op2v = b2.asInstanceOf[BoxIRef].oo
......@@ -239,7 +239,7 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
}
writeBooleanResult(result, br)
}
def doStack(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
val op1v = b1.asInstanceOf[BoxStack].stack
val op2v = b2.asInstanceOf[BoxStack].stack
......@@ -358,6 +358,30 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
"REFCAST can only convert between two types both of which are ref, iref, or func. Found %s and %s.".format(scalarFromTy, scalarToTy))
}
def ptrcast(): Unit = {
(scalarFromTy, scalarToTy) match {
case (TypeInt(_), TypeInt(_)) => throw new UvmRuntimeException(ctx +
"PTRCAST cannot convert between two int types. Found %s and %s.".format(scalarFromTy, scalarToTy))
case _ =>
}
val srcAddr: Word = scalarFromTy match {
case TypeInt(n) => {
val od = bOpnd.asInstanceOf[BoxInt].value
val truncExt = if (n >= 64) OpHelper.trunc(od, 64) else OpHelper.zext(od, n, 64)
truncExt.toLong
}
case TypePtr(_) | TypeFuncPtr(_) => bOpnd.asInstanceOf[BoxPointer].addr
}
scalarToTy match {
case TypeInt(n) => {
val bi = BigInt(srcAddr)
val truncExt = if (n > 64) OpHelper.zext(bi, 64, n) else OpHelper.trunc(bi, n)
br.asInstanceOf[BoxInt].value = truncExt
}
case TypePtr(_) | TypeFuncPtr(_) => br.asInstanceOf[BoxPointer].addr = srcAddr
}
}
op match {
case ConvOptr.TRUNC => iToI()
case ConvOptr.ZEXT => iToI()
......@@ -378,6 +402,7 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
case ConvOptr.SITOFP => iToFP(signed = true)
case ConvOptr.BITCAST => bitcast()
case ConvOptr.REFCAST => refcast()
case ConvOptr.PTRCAST => ptrcast()
}
}
......@@ -634,105 +659,94 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
}
case i @ InstGetFieldIRef(ptr, referentTy, index, opnd) => {
val ob = boxOf(opnd).asInstanceOf[BoxIRef]
val ib = boxOf(i).asInstanceOf[BoxIRef]
ib.objRef = ob.objRef
ib.offset = ob.offset + TypeSizes.fieldOffsetOf(referentTy, index)
val addrIncr = TypeSizes.fieldOffsetOf(referentTy, index)
incrementBoxIRefOrPointer(ptr, opnd, i, addrIncr)
continueNormally()
}
case i @ InstGetElemIRef(ptr, referentTy, indTy, opnd, index) => {
val ob = boxOf(opnd).asInstanceOf[BoxIRef]
val indb = boxOf(index).asInstanceOf[BoxInt]
val ind = OpHelper.prepareSigned(indb.value, indTy.length)
val ib = boxOf(i).asInstanceOf[BoxIRef]
ib.objRef = ob.objRef
ib.offset = ob.offset + TypeSizes.elemOffsetOf(referentTy, ind.longValue())
val addrIncr = TypeSizes.elemOffsetOf(referentTy, ind.longValue())
incrementBoxIRefOrPointer(ptr, opnd, i, addrIncr)
continueNormally()
}
case i @ InstShiftIRef(ptr, referentTy, offTy, opnd, offset) => {
val ob = boxOf(opnd).asInstanceOf[BoxIRef]
val offb = boxOf(offset).asInstanceOf[BoxInt]
val off = OpHelper.prepareSigned(offb.value, offTy.length)
val ib = boxOf(i).asInstanceOf[BoxIRef]
ib.objRef = ob.objRef
ib.offset = ob.offset + TypeSizes.shiftOffsetOf(referentTy, off.longValue())
val addrIncr = TypeSizes.shiftOffsetOf(referentTy, off.longValue())
incrementBoxIRefOrPointer(ptr, opnd, i, addrIncr)
continueNormally()
}
case i @ InstGetFixedPartIRef(ptr, referentTy, opnd) => {
val ob = boxOf(opnd).asInstanceOf[BoxIRef]
val ib = boxOf(i).asInstanceOf[BoxIRef]
ib.objRef = ob.objRef
ib.offset = ob.offset
incrementBoxIRefOrPointer(ptr, opnd, i, 0L)
continueNormally()
}
case i @ InstGetVarPartIRef(ptr, referentTy, opnd) => {
val ob = boxOf(opnd).asInstanceOf[BoxIRef]
val ib = boxOf(i).asInstanceOf[BoxIRef]
ib.objRef = ob.objRef
ib.offset = ob.offset + TypeSizes.varPartOffsetOf(referentTy)
val addrIncr = TypeSizes.varPartOffsetOf(referentTy)
incrementBoxIRefOrPointer(ptr, opnd, i, addrIncr)
continueNormally()
}
case i @ InstLoad(ptr, ord, referentTy, loc, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy)
val lb = boxOf(loc).asInstanceOf[BoxIRef]
val ib = boxOf(i)
val la = lb.objRef + lb.offset
if (la == 0L) {
val addr = addressOf(ptr, loc)
if (addr == 0L) {
nullRefError(excClause)
} else {
MemoryOperations.load(uty, la, ib)
MemoryOperations.load(ptr, uty, addr, ib)
continueNormally()
}
}
case i @ InstStore(ptr, ord, referentTy, loc, newVal, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy)
val lb = boxOf(loc).asInstanceOf[BoxIRef]
val nvb = boxOf(newVal)
val ib = boxOf(i)
val la = lb.objRef + lb.offset
if (la == 0L) {
val addr = addressOf(ptr, loc)
if (addr == 0L) {
nullRefError(excClause)
} else {
MemoryOperations.store(uty, la, nvb, ib)
MemoryOperations.store(ptr, uty, addr, nvb, ib)
continueNormally()
}
}
case i @ InstCmpXchg(ptr, weak, ordSucc, ordFail, referentTy, loc, expected, desired, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy)
val lb = boxOf(loc).asInstanceOf[BoxIRef]
val eb = boxOf(expected)
val db = boxOf(desired)
val ib = boxOf(i)
val la = lb.objRef + lb.offset
if (la == 0L) {
val addr = addressOf(ptr, loc)
if (addr == 0L) {
nullRefError(excClause)
} else {
MemoryOperations.cmpXchg(uty, la, eb, db, ib)
MemoryOperations.cmpXchg(ptr, uty, addr, eb, db, ib)
continueNormally()
}
}
case i @ InstAtomicRMW(ptr, ord, op, referentTy, loc, opnd, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy)
val lb = boxOf(loc).asInstanceOf[BoxIRef]
val ob = boxOf(opnd)
val ib = boxOf(i)
val la = lb.objRef + lb.offset
if (la == 0L) {
val addr = addressOf(ptr, loc)
if (addr == 0L) {
nullRefError(excClause)
} else {
MemoryOperations.atomicRMW(uty, op, la, ob, ib)
MemoryOperations.atomicRMW(ptr, uty, op, addr, ob, ib)
continueNormally()
}
}
......@@ -1188,6 +1202,26 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
box.asInstanceOf[BoxInt].value = OpHelper.unprepare(result, len)
}
private def incrementBoxIRefOrPointer(ptr: Boolean, src: SSAVariable, dst: SSAVariable, addrIncr: Word): Unit = {
if (ptr) {
val sb = boxOf(src).asInstanceOf[BoxPointer]
val db = boxOf(dst).asInstanceOf[BoxPointer]
db.addr = sb.addr + addrIncr
} else {
val sb = boxOf(src).asInstanceOf[BoxIRef]
val db = boxOf(dst).asInstanceOf[BoxIRef]
db.objRef = sb.objRef
db.offset = sb.offset + addrIncr
}
}
private def addressOf(ptr: Boolean, v: SSAVariable): Word = {
MemoryOperations.addressOf(ptr, boxOf(v))
}
def incrementBoxPointer(src: BoxPointer, dst: BoxPointer, addrIncr: Word): Unit = {
}
// Thread termination
/** Terminate the thread. Please only let the thread terminate itself. */
......
......@@ -173,20 +173,20 @@ object PrimOpHelpers {
}
up(op match {
case BinOptr.ADD => pu(op1v) + pu(op2v)
case BinOptr.SUB => pu(op1v) - pu(op2v)
case BinOptr.MUL => pu(op1v) * pu(op2v)
case BinOptr.ADD => pu(op1v) + pu(op2v)
case BinOptr.SUB => pu(op1v) - pu(op2v)
case BinOptr.MUL => pu(op1v) * pu(op2v)
case BinOptr.UDIV => { checkDivByZero(); pu(op1v) / pu(op2v) }
case BinOptr.SDIV => { checkDivByZero(); ps(op1v) / ps(op2v) }
case BinOptr.UREM => { checkDivByZero(); pu(op1v) % pu(op2v) }
case BinOptr.SREM => { checkDivByZero(); ps(op1v) % ps(op2v) }
case BinOptr.SHL => pu(op1v) << (op2v.intValue & shiftMask)
case BinOptr.SHL => pu(op1v) << (op2v.intValue & shiftMask)
case BinOptr.LSHR => pu(op1v) >> (op2v.intValue & shiftMask)
case BinOptr.ASHR => ps(op1v) >> (op2v.intValue & shiftMask)
case BinOptr.AND => pu(op1v) & pu(op2v)
case BinOptr.OR => pu(op1v) | pu(op2v)
case BinOptr.XOR => pu(op1v) ^ pu(op2v)
case _ => throw new UvmRuntimeException(ctx + "Binary operator %s is not suitable for integer.".format(op))
case BinOptr.AND => pu(op1v) & pu(op2v)
case BinOptr.OR => pu(op1v) | pu(op2v)
case BinOptr.XOR => pu(op1v) ^ pu(op2v)
case _ => throw new UvmRuntimeException(ctx + "Binary operator %s is not suitable for integer.".format(op))
})
}
......@@ -197,7 +197,7 @@ object PrimOpHelpers {
case BinOptr.FMUL => op1v * op2v
case BinOptr.FDIV => op1v / op2v
case BinOptr.FREM => Math.IEEEremainder(op1v, op2v).toFloat
case _ => throw new UvmRuntimeException(ctx + "Binary operator %s is not suitable for float.".format(op))
case _ => throw new UvmRuntimeException(ctx + "Binary operator %s is not suitable for float.".format(op))
}
}
......@@ -208,7 +208,7 @@ object PrimOpHelpers {
case BinOptr.FMUL => op1v * op2v
case BinOptr.FDIV => op1v / op2v
case BinOptr.FREM => Math.IEEEremainder(op1v, op2v)
case _ => throw new UvmRuntimeException(ctx + "Binary operator %s is not suitable for double.".format(op))
case _ => throw new UvmRuntimeException(ctx + "Binary operator %s is not suitable for double.".format(op))
}
}
......@@ -217,8 +217,8 @@ object PrimOpHelpers {
def ps(v: BigInt): BigInt = OpHelper.prepareSigned(v, l)
op match {
case CmpOptr.EQ => pu(op1v) == pu(op2v)
case CmpOptr.NE => pu(op1v) != pu(op2v)
case CmpOptr.EQ => pu(op1v) == pu(op2v)
case CmpOptr.NE => pu(op1v) != pu(op2v)
case CmpOptr.UGT => pu(op1v) > pu(op2v)
case CmpOptr.UGE => pu(op1v) >= pu(op2v)
case CmpOptr.ULT => pu(op1v) < pu(op2v)
......@@ -227,7 +227,7 @@ object PrimOpHelpers {
case CmpOptr.SGE => ps(op1v) >= ps(op2v)
case CmpOptr.SLT => ps(op1v) < ps(op2v)
case CmpOptr.SLE => ps(op1v) <= ps(op2v)
case _ => throw new UvmRuntimeException(ctx + "Comparison operator %s not suitable for integers".format(op))
case _ => throw new UvmRuntimeException(ctx + "Comparison operator %s not suitable for integers".format(op))
}
}
......@@ -236,23 +236,23 @@ object PrimOpHelpers {
def ord = !isNaN(op1v) && !isNaN(op2v)
def uno = isNaN(op1v) || isNaN(op2v)
op match {
case CmpOptr.FTRUE => true
case CmpOptr.FTRUE => true
case CmpOptr.FFALSE => false
case CmpOptr.FOEQ => ord && op1v == op2v
case CmpOptr.FONE => ord && op1v != op2v
case CmpOptr.FOGT => ord && op1v > op2v
case CmpOptr.FOGE => ord && op1v >= op2v
case CmpOptr.FOLT => ord && op1v < op2v
case CmpOptr.FOLE => ord && op1v <= op2v
case CmpOptr.FORD => ord
case CmpOptr.FUEQ => uno || op1v == op2v
case CmpOptr.FUNE => uno || op1v != op2v
case CmpOptr.FUGT => uno || op1v > op2v
case CmpOptr.FUGE => uno || op1v >= op2v
case CmpOptr.FULT => uno || op1v < op2v
case CmpOptr.FULE => uno || op1v <= op2v
case CmpOptr.FUNO => uno
case _ => throw new UvmRuntimeException(ctx + "Comparison operator %s is not suitable for float.".format(op))
case CmpOptr.FOEQ => ord && op1v == op2v
case CmpOptr.FONE => ord && op1v != op2v
case CmpOptr.FOGT => ord && op1v > op2v
case CmpOptr.FOGE => ord && op1v >= op2v
case CmpOptr.FOLT => ord && op1v < op2v
case CmpOptr.FOLE => ord && op1v <= op2v
case CmpOptr.FORD => ord
case CmpOptr.FUEQ => uno || op1v == op2v
case CmpOptr.FUNE => uno || op1v != op2v
case CmpOptr.FUGT => uno || op1v > op2v
case CmpOptr.FUGE => uno || op1v >= op2v
case CmpOptr.FULT => uno || op1v < op2v
case CmpOptr.FULE => uno || op1v <= op2v
case CmpOptr.FUNO => uno
case _ => throw new UvmRuntimeException(ctx + "Comparison operator %s is not suitable for float.".format(op))
}
}
......@@ -261,67 +261,92 @@ object PrimOpHelpers {
def ord = !isNaN(op1v) && !isNaN(op2v)
def uno = isNaN(op1v) || isNaN(op2v)
op match {
case CmpOptr.FTRUE => true
case CmpOptr.FTRUE => true
case CmpOptr.FFALSE => false
case CmpOptr.FOEQ => ord && op1v == op2v
case CmpOptr.FONE => ord && op1v != op2v
case CmpOptr.FOGT => ord && op1v > op2v
case CmpOptr.FOGE => ord && op1v >= op2v
case CmpOptr.FOLT => ord && op1v < op2v
case CmpOptr.FOLE => ord && op1v <= op2v
case CmpOptr.FORD => ord
case CmpOptr.FUEQ => uno || op1v == op2v
case CmpOptr.FUNE => uno || op1v != op2v
case CmpOptr.FUGT => uno || op1v > op2v
case CmpOptr.FUGE => uno || op1v >= op2v
case CmpOptr.FULT => uno || op1v < op2v
case CmpOptr.FULE => uno || op1v <= op2v
case CmpOptr.FUNO => uno
case _ => throw new UvmRuntimeException(ctx + "Comparison operator %s is not suitable for double.".format(op))
case CmpOptr.FOEQ => ord && op1v == op2v
case CmpOptr.FONE => ord && op1v != op2v
case CmpOptr.FOGT => ord && op1v > op2v
case CmpOptr.FOGE => ord && op1v >= op2v
case CmpOptr.FOLT => ord && op1v < op2v
case CmpOptr.FOLE => ord && op1v <= op2v
case CmpOptr.FORD => ord
case CmpOptr.FUEQ => uno || op1v == op2v
case CmpOptr.FUNE => uno || op1v != op2v
case CmpOptr.FUGT => uno || op1v > op2v
case CmpOptr.FUGE => uno || op1v >= op2v
case CmpOptr.FULT => uno || op1v < op2v
case CmpOptr.FULE => uno || op1v <= op2v
case CmpOptr.FUNO => uno
case _ => throw new UvmRuntimeException(ctx + "Comparison operator %s is not suitable for double.".format(op))
}
}
}
object MemoryOperations {
def load(ty: Type, loc: Word, br: ValueBox)(implicit microVM: MicroVM, memorySupport: MemorySupport): Unit = {
def addressOf(ptr: Boolean, vb: ValueBox): Word = {
if (ptr) {
vb.asInstanceOf[BoxPointer].addr
} else {
val lb = vb.asInstanceOf[BoxIRef]
lb.objRef + lb.offset
}
}
def noAccessViaPointer(ptr: Boolean, ty: Type) {
if (ptr) {
throw new UvmIllegalMemoryAccessException("Cannot access type %s via pointer".format(ty.repr))
}
}
def load(ptr: Boolean, ty: Type, loc: Word, br: ValueBox)(implicit microVM: MicroVM, memorySupport: MemorySupport): Unit = {
def loadScalar(ty: Type, loc: Word, br: ValueBox): Unit = ty match {
case TypeInt(l) =>
val bi: BigInt = l match {
case 8 => memorySupport.loadByte(loc)
case 16 => memorySupport.loadShort(loc)
case 32 => memorySupport.loadInt(loc)
case 64 => memorySupport.loadLong(loc)
case _ => throw new UnimplementedOprationException("Loading int of length %d is not supported".format(l))
case 8 => memorySupport.loadByte(loc, !ptr)
case 16 => memorySupport.loadShort(loc, !ptr)
case 32 => memorySupport.loadInt(loc, !ptr)
case 64 => memorySupport.loadLong(loc, !ptr)
case _ => throw new UnimplementedOprationException("Loading int of length %d is not supported".format(l))
}
br.asInstanceOf[BoxInt].value = OpHelper.unprepare(bi, l)
case _: TypeFloat =>
val fv = memorySupport.loadFloat(loc)
val fv = memorySupport.loadFloat(loc, !ptr)
br.asInstanceOf[BoxFloat].value = fv
case _: TypeDouble =>
val dv = memorySupport.loadDouble(loc)
val dv = memorySupport.loadDouble(loc, !ptr)
br.asInstanceOf[BoxDouble].value = dv
case _: TypeRef =>
noAccessViaPointer(ptr, ty)
val addr = memorySupport.loadLong(loc)
br.asInstanceOf[BoxRef].objRef = addr
case _: TypeIRef =>
noAccessViaPointer(ptr, ty)
val base = memorySupport.loadLong(loc)
val offset = memorySupport.loadLong(loc + WORD_SIZE_BYTES)
br.asInstanceOf[BoxIRef].oo = (base, offset)
case _: TypeFunc =>
noAccessViaPointer(ptr, ty)
val fid = memorySupport.loadLong(loc).toInt
val func = microVM.globalBundle.funcNs.get(fid)
br.asInstanceOf[BoxFunc].func = func
case _: TypeThread =>
noAccessViaPointer(ptr, ty)
val tid = memorySupport.loadLong(loc).toInt
val thr = microVM.threadStackManager.getThreadByID(tid)
br.asInstanceOf[BoxThread].thread = thr
case _: TypeStack =>
noAccessViaPointer(ptr, ty)
val sid = memorySupport.loadLong(loc).toInt
val sta = microVM.threadStackManager.getStackByID(sid)
br.asInstanceOf[BoxStack].stack = sta
case _: TypeTagRef64 =>
noAccessViaPointer(ptr, ty)
val raw = memorySupport.loadLong(loc)
br.asInstanceOf[BoxTagRef64].raw = raw
case _: TypePtr | _: TypeFuncPtr =>
val addr = memorySupport.loadLong(loc, !ptr)
br.asInstanceOf[BoxPointer].addr = addr
case _ => throw new UnimplementedOprationException("Loading of type %s is not supporing".format(ty.getClass.getName))
}
......@@ -336,42 +361,51 @@ object MemoryOperations {
}
}
def store(ty: Type, loc: Word, nvb: ValueBox, br: ValueBox)(implicit memorySupport: MemorySupport): Unit = {
def store(ptr: Boolean, ty: Type, loc: Word, nvb: ValueBox, br: ValueBox)(implicit memorySupport: MemorySupport): Unit = {
def storeScalar(ty: Type, loc: Word, nvb: ValueBox, br: ValueBox): Unit = ty match {
case TypeInt(l) =>
val bi = nvb.asInstanceOf[BoxInt].value
l match {
case 8 => memorySupport.storeByte(loc, bi.byteValue)
case 16 => memorySupport.storeShort(loc, bi.shortValue)
case 32 => memorySupport.storeInt(loc, bi.intValue)
case 64 => memorySupport.storeLong(loc, bi.longValue)
case _ => throw new UnimplementedOprationException("Storing int of length %d is not supported".format(l))
case 8 => memorySupport.storeByte(loc, bi.byteValue, !ptr)
case 16 => memorySupport.storeShort(loc, bi.shortValue, !ptr)
case 32 => memorySupport.storeInt(loc, bi.intValue, !ptr)
case 64 => memorySupport.storeLong(loc, bi.longValue, !ptr)
case _ => throw new UnimplementedOprationException("Storing int of length %d is not supported".format(l))
}
case _: TypeFloat =>
val fv = nvb.asInstanceOf[BoxFloat].value
memorySupport.storeFloat(loc, fv)
memorySupport.storeFloat(loc, fv, !ptr)
case _: TypeDouble =>
val dv = nvb.asInstanceOf[BoxDouble].value
memorySupport.storeDouble(loc, dv)
memorySupport.storeDouble(loc, dv, !ptr)
case _: TypeRef =>
noAccessViaPointer(ptr, ty)
val addr = nvb.asInstanceOf[BoxRef].objRef
memorySupport.storeLong(loc, addr)
case _: TypeIRef =>
noAccessViaPointer(ptr, ty)
val BoxIRef(base, offset) = nvb.asInstanceOf[BoxIRef]
memorySupport.storeLong(loc, base)
memorySupport.storeLong(loc + WORD_SIZE_BYTES, offset)
case _: TypeFunc =>
noAccessViaPointer(ptr, ty)
val fid = nvb.asInstanceOf[BoxFunc].func.map(_.id).getOrElse(0)
memorySupport.storeLong(loc, fid.toLong & 0xFFFFFFFFL)
case _: TypeThread =>
noAccessViaPointer(ptr, ty)
val tid = nvb.asInstanceOf[BoxThread].thread.map(_.id).getOrElse(0)
memorySupport.storeLong(loc, tid.toLong & 0xFFFFFFFFL)
case _: TypeStack =>
noAccessViaPointer(ptr, ty)
val sid = nvb.asInstanceOf[BoxStack].stack.map(_.id).getOrElse(0)
memorySupport.storeLong(loc, sid.toLong & 0xFFFFFFFFL)
case _: TypeTagRef64 =>
noAccessViaPointer(ptr, ty)
val raw = nvb.asInstanceOf[BoxTagRef64].raw
memorySupport.storeLong(loc, raw)
case _: TypePtr | _: TypeFuncPtr =>
val addr = nvb.asInstanceOf[BoxPointer].addr
memorySupport.storeLong(loc, addr, !ptr)
case _ => throw new UnimplementedOprationException("Storing of type %s is not supporing".format(ty.getClass.getName))
}
......@@ -390,18 +424,18 @@ object MemoryOperations {
/**
* Compare exchange. The result (the old value) is written into br. Return true if successful, false otherwise.
*/
def cmpXchg(ty: Type, loc: Word, eb: ValueBox, db: ValueBox, br: ValueBox)(implicit microVM: MicroVM, memorySupport: MemorySupport): Boolean = {
def cmpXchg(ptr: Boolean, ty: Type, loc: Word, eb: ValueBox, db: ValueBox, br: ValueBox)(implicit microVM: MicroVM, memorySupport: MemorySupport): Boolean = {
ty match {
case TypeInt(l) =>
val ebi = eb.asInstanceOf[BoxInt].value
val dbi = db.asInstanceOf[BoxInt].value