Commit b2e215ec authored by Kunshan Wang's avatar Kunshan Wang

Memory operations via pointers.

parent 31a531fe
...@@ -94,6 +94,11 @@ class ClientAgent(microVM: MicroVM) { ...@@ -94,6 +94,11 @@ class ClientAgent(microVM: MicroVM) {
val et = t.elemTy.asInstanceOf[TypeDouble] val et = t.elemTy.asInstanceOf[TypeDouble]
newHandle(t, BoxVector(vs.map(BoxDouble))) 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 = { def putConstant(id: Int): Handle = {
val c = microVM.globalBundle.constantNs(id) val c = microVM.globalBundle.constantNs(id)
...@@ -152,6 +157,10 @@ class ClientAgent(microVM: MicroVM) { ...@@ -152,6 +157,10 @@ class ClientAgent(microVM: MicroVM) {
def toDoubleVec(h: Handle): Seq[Double] = { def toDoubleVec(h: Handle): Seq[Double] = {
h.vb.asInstanceOf[BoxVector].values.map(b => b.asInstanceOf[BoxDouble].value) 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 = { def extractValue(str: Handle, index: Int): Handle = {
val st = str.ty.asInstanceOf[TypeStruct] val st = str.ty.asInstanceOf[TypeStruct]
...@@ -251,48 +260,56 @@ class ClientAgent(microVM: MicroVM) { ...@@ -251,48 +260,56 @@ class ClientAgent(microVM: MicroVM) {
} }
def load(ord: MemoryOrder, loc: Handle): Handle = { 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 uty = InternalTypePool.unmarkedOf(ty)
val b = loc.vb.asInstanceOf[BoxIRef] val addr = MemoryOperations.addressOf(ptr, loc.vb)
val iRef = b.objRef + b.offset
val nb = ValueBox.makeBoxForType(uty) val nb = ValueBox.makeBoxForType(uty)
MemoryOperations.load(uty, iRef, nb) MemoryOperations.load(ptr, uty, addr, nb)
newHandle(uty, nb) newHandle(uty, nb)
} }
def store(ord: MemoryOrder, loc: Handle, newVal: Handle): Unit = { 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 uty = InternalTypePool.unmarkedOf(ty)
val lb = loc.vb.asInstanceOf[BoxIRef] val addr = MemoryOperations.addressOf(ptr, loc.vb)
val iRef = lb.objRef + lb.offset
val nvb = newVal.vb val nvb = newVal.vb
val nb = ValueBox.makeBoxForType(uty) 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) = { 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 uty = InternalTypePool.unmarkedOf(ty)
val lb = loc.vb.asInstanceOf[BoxIRef] val addr = MemoryOperations.addressOf(ptr, loc.vb)
val iRef = lb.objRef + lb.offset
val eb = expected.vb val eb = expected.vb
val db = desired.vb val db = desired.vb
val br = ValueBox.makeBoxForType(uty) 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)) (succ, newHandle(uty, br))
} }
def atomicRMW(ord: MemoryOrder, op: AtomicRMWOptr, loc: Handle, opnd: Handle): Handle = { 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 uty = InternalTypePool.unmarkedOf(ty)
val lb = loc.vb.asInstanceOf[BoxIRef] val addr = MemoryOperations.addressOf(ptr, loc.vb)
val iRef = lb.objRef + lb.offset
val ob = opnd.vb val ob = opnd.vb
val br = ValueBox.makeBoxForType(uty) val br = ValueBox.makeBoxForType(uty)
MemoryOperations.atomicRMW(uty, op, iRef, ob, br) MemoryOperations.atomicRMW(ptr, uty, op, addr, ob, br)
newHandle(uty, br) newHandle(uty, br)
} }
......
...@@ -50,7 +50,9 @@ object InternalTypePool { ...@@ -50,7 +50,9 @@ object InternalTypePool {
val refOf = LazyPool(TypeRef) val refOf = LazyPool(TypeRef)
val irefOf = LazyPool(TypeIRef) val irefOf = LazyPool(TypeIRef)
val ptrOf = LazyPool(TypePtr)
val funcOf = LazyPool(TypeFunc) val funcOf = LazyPool(TypeFunc)
val funcPtrOf = LazyPool(TypeFuncPtr)
val vecOf = new LazyPool[(Type, Long), TypeVector]({ case (t, l) => TypeVector(t, l) }) val vecOf = new LazyPool[(Type, Long), TypeVector]({ case (t, l) => TypeVector(t, l) })
def unmarkedOf(t: Type): Type = t match { def unmarkedOf(t: Type): Type = t match {
case TypeWeakRef(r) => refOf(r) case TypeWeakRef(r) => refOf(r)
...@@ -61,6 +63,11 @@ object InternalTypePool { ...@@ -61,6 +63,11 @@ object InternalTypePool {
object TypeInferer { object TypeInferer {
import InternalTypes._ import InternalTypes._
import InternalTypePool._ import InternalTypePool._
def ptrOrIRefOf(ptr: Boolean, ty: Type): Type = {
if (ptr) ptrOf(ty) else irefOf(ty)
}
def inferType(v: SSAVariable): Type = v match { def inferType(v: SSAVariable): Type = v match {
case c: Constant => c.constTy case c: Constant => c.constTy
case g: GlobalCell => irefOf(g.cellTy) case g: GlobalCell => irefOf(g.cellTy)
...@@ -93,11 +100,11 @@ object TypeInferer { ...@@ -93,11 +100,11 @@ object TypeInferer {
case i: InstAlloca => irefOf(i.allocTy) case i: InstAlloca => irefOf(i.allocTy)
case i: InstAllocaHybrid => irefOf(i.allocTy) case i: InstAllocaHybrid => irefOf(i.allocTy)
case i: InstGetIRef => irefOf(i.referentTy) case i: InstGetIRef => irefOf(i.referentTy)
case i: InstGetFieldIRef => irefOf(i.referentTy.fieldTy(i.index)) case i: InstGetFieldIRef => ptrOrIRefOf(i.ptr, i.referentTy.fieldTy(i.index))
case i: InstGetElemIRef => irefOf(i.referentTy.elemTy) case i: InstGetElemIRef => ptrOrIRefOf(i.ptr, i.referentTy.elemTy)
case i: InstShiftIRef => irefOf(i.referentTy) case i: InstShiftIRef => ptrOrIRefOf(i.ptr, i.referentTy)
case i: InstGetFixedPartIRef => irefOf(i.referentTy.fixedTy) case i: InstGetFixedPartIRef => ptrOrIRefOf(i.ptr, i.referentTy.fixedTy)
case i: InstGetVarPartIRef => irefOf(i.referentTy.varTy) case i: InstGetVarPartIRef => ptrOrIRefOf(i.ptr, i.referentTy.varTy)
case i: InstLoad => unmarkedOf(i.referentTy) case i: InstLoad => unmarkedOf(i.referentTy)
case i: InstStore => VOID case i: InstStore => VOID
case i: InstCmpXchg => unmarkedOf(i.referentTy) case i: InstCmpXchg => unmarkedOf(i.referentTy)
......
...@@ -17,10 +17,10 @@ object InterpreterThread { ...@@ -17,10 +17,10 @@ object InterpreterThread {
class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, initialStack: InterpreterStack, val mutator: Mutator) { class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, initialStack: InterpreterStack, val mutator: Mutator) {
import InterpreterThread._ import InterpreterThread._
// Injectable resources (used by memory access instructions) // Injectable resources (used by memory access instructions)
implicit private val memorySupport = microVM.memoryManager.memorySupport implicit private val memorySupport = microVM.memoryManager.memorySupport
// Thread states // Thread states
/** The underlying stack. */ /** The underlying stack. */
...@@ -215,7 +215,7 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init ...@@ -215,7 +215,7 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
} }
writeBooleanResult(result, br) writeBooleanResult(result, br)
} }
def doIRef(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = { def doIRef(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
val op1v = b1.asInstanceOf[BoxIRef].oo val op1v = b1.asInstanceOf[BoxIRef].oo
val op2v = b2.asInstanceOf[BoxIRef].oo val op2v = b2.asInstanceOf[BoxIRef].oo
...@@ -239,7 +239,7 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init ...@@ -239,7 +239,7 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
} }
writeBooleanResult(result, br) writeBooleanResult(result, br)
} }
def doStack(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = { def doStack(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
val op1v = b1.asInstanceOf[BoxStack].stack val op1v = b1.asInstanceOf[BoxStack].stack
val op2v = b2.asInstanceOf[BoxStack].stack val op2v = b2.asInstanceOf[BoxStack].stack
...@@ -358,6 +358,30 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init ...@@ -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)) "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 { op match {
case ConvOptr.TRUNC => iToI() case ConvOptr.TRUNC => iToI()
case ConvOptr.ZEXT => iToI() case ConvOptr.ZEXT => iToI()
...@@ -378,6 +402,7 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init ...@@ -378,6 +402,7 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
case ConvOptr.SITOFP => iToFP(signed = true) case ConvOptr.SITOFP => iToFP(signed = true)
case ConvOptr.BITCAST => bitcast() case ConvOptr.BITCAST => bitcast()
case ConvOptr.REFCAST => refcast() case ConvOptr.REFCAST => refcast()
case ConvOptr.PTRCAST => ptrcast()
} }
} }
...@@ -634,105 +659,94 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init ...@@ -634,105 +659,94 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
} }
case i @ InstGetFieldIRef(ptr, referentTy, index, opnd) => { case i @ InstGetFieldIRef(ptr, referentTy, index, opnd) => {
val ob = boxOf(opnd).asInstanceOf[BoxIRef] val addrIncr = TypeSizes.fieldOffsetOf(referentTy, index)
val ib = boxOf(i).asInstanceOf[BoxIRef]
ib.objRef = ob.objRef incrementBoxIRefOrPointer(ptr, opnd, i, addrIncr)
ib.offset = ob.offset + TypeSizes.fieldOffsetOf(referentTy, index)
continueNormally() continueNormally()
} }
case i @ InstGetElemIRef(ptr, referentTy, indTy, opnd, index) => { case i @ InstGetElemIRef(ptr, referentTy, indTy, opnd, index) => {
val ob = boxOf(opnd).asInstanceOf[BoxIRef]
val indb = boxOf(index).asInstanceOf[BoxInt] val indb = boxOf(index).asInstanceOf[BoxInt]
val ind = OpHelper.prepareSigned(indb.value, indTy.length) val ind = OpHelper.prepareSigned(indb.value, indTy.length)
val ib = boxOf(i).asInstanceOf[BoxIRef] val addrIncr = TypeSizes.elemOffsetOf(referentTy, ind.longValue())
ib.objRef = ob.objRef
ib.offset = ob.offset + TypeSizes.elemOffsetOf(referentTy, ind.longValue()) incrementBoxIRefOrPointer(ptr, opnd, i, addrIncr)
continueNormally() continueNormally()
} }
case i @ InstShiftIRef(ptr, referentTy, offTy, opnd, offset) => { case i @ InstShiftIRef(ptr, referentTy, offTy, opnd, offset) => {
val ob = boxOf(opnd).asInstanceOf[BoxIRef]
val offb = boxOf(offset).asInstanceOf[BoxInt] val offb = boxOf(offset).asInstanceOf[BoxInt]
val off = OpHelper.prepareSigned(offb.value, offTy.length) val off = OpHelper.prepareSigned(offb.value, offTy.length)
val ib = boxOf(i).asInstanceOf[BoxIRef] val addrIncr = TypeSizes.shiftOffsetOf(referentTy, off.longValue())
ib.objRef = ob.objRef
ib.offset = ob.offset + TypeSizes.shiftOffsetOf(referentTy, off.longValue()) incrementBoxIRefOrPointer(ptr, opnd, i, addrIncr)
continueNormally() continueNormally()
} }
case i @ InstGetFixedPartIRef(ptr, referentTy, opnd) => { case i @ InstGetFixedPartIRef(ptr, referentTy, opnd) => {
val ob = boxOf(opnd).asInstanceOf[BoxIRef] incrementBoxIRefOrPointer(ptr, opnd, i, 0L)
val ib = boxOf(i).asInstanceOf[BoxIRef]
ib.objRef = ob.objRef
ib.offset = ob.offset
continueNormally() continueNormally()
} }
case i @ InstGetVarPartIRef(ptr, referentTy, opnd) => { case i @ InstGetVarPartIRef(ptr, referentTy, opnd) => {
val ob = boxOf(opnd).asInstanceOf[BoxIRef] val addrIncr = TypeSizes.varPartOffsetOf(referentTy)
val ib = boxOf(i).asInstanceOf[BoxIRef]
ib.objRef = ob.objRef incrementBoxIRefOrPointer(ptr, opnd, i, addrIncr)
ib.offset = ob.offset + TypeSizes.varPartOffsetOf(referentTy)
continueNormally() continueNormally()
} }
case i @ InstLoad(ptr, ord, referentTy, loc, excClause) => { case i @ InstLoad(ptr, ord, referentTy, loc, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy) val uty = InternalTypePool.unmarkedOf(referentTy)
val lb = boxOf(loc).asInstanceOf[BoxIRef]
val ib = boxOf(i) val ib = boxOf(i)
val la = lb.objRef + lb.offset val addr = addressOf(ptr, loc)
if (la == 0L) { if (addr == 0L) {
nullRefError(excClause) nullRefError(excClause)
} else { } else {
MemoryOperations.load(uty, la, ib) MemoryOperations.load(ptr, uty, addr, ib)
continueNormally() continueNormally()
} }
} }
case i @ InstStore(ptr, ord, referentTy, loc, newVal, excClause) => { case i @ InstStore(ptr, ord, referentTy, loc, newVal, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy) val uty = InternalTypePool.unmarkedOf(referentTy)
val lb = boxOf(loc).asInstanceOf[BoxIRef]
val nvb = boxOf(newVal) val nvb = boxOf(newVal)
val ib = boxOf(i) val ib = boxOf(i)
val la = lb.objRef + lb.offset val addr = addressOf(ptr, loc)
if (la == 0L) { if (addr == 0L) {
nullRefError(excClause) nullRefError(excClause)
} else { } else {
MemoryOperations.store(uty, la, nvb, ib) MemoryOperations.store(ptr, uty, addr, nvb, ib)
continueNormally() continueNormally()
} }
} }
case i @ InstCmpXchg(ptr, weak, ordSucc, ordFail, referentTy, loc, expected, desired, excClause) => { case i @ InstCmpXchg(ptr, weak, ordSucc, ordFail, referentTy, loc, expected, desired, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy) val uty = InternalTypePool.unmarkedOf(referentTy)
val lb = boxOf(loc).asInstanceOf[BoxIRef]
val eb = boxOf(expected) val eb = boxOf(expected)
val db = boxOf(desired) val db = boxOf(desired)
val ib = boxOf(i) val ib = boxOf(i)
val la = lb.objRef + lb.offset val addr = addressOf(ptr, loc)
if (la == 0L) { if (addr == 0L) {
nullRefError(excClause) nullRefError(excClause)
} else { } else {
MemoryOperations.cmpXchg(uty, la, eb, db, ib) MemoryOperations.cmpXchg(ptr, uty, addr, eb, db, ib)
continueNormally() continueNormally()
} }
} }
case i @ InstAtomicRMW(ptr, ord, op, referentTy, loc, opnd, excClause) => { case i @ InstAtomicRMW(ptr, ord, op, referentTy, loc, opnd, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy) val uty = InternalTypePool.unmarkedOf(referentTy)
val lb = boxOf(loc).asInstanceOf[BoxIRef]
val ob = boxOf(opnd) val ob = boxOf(opnd)
val ib = boxOf(i) val ib = boxOf(i)
val la = lb.objRef + lb.offset val addr = addressOf(ptr, loc)
if (la == 0L) { if (addr == 0L) {
nullRefError(excClause) nullRefError(excClause)
} else { } else {
MemoryOperations.atomicRMW(uty, op, la, ob, ib) MemoryOperations.atomicRMW(ptr, uty, op, addr, ob, ib)
continueNormally() continueNormally()
} }
} }
...@@ -1188,6 +1202,26 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init ...@@ -1188,6 +1202,26 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
box.asInstanceOf[BoxInt].value = OpHelper.unprepare(result, len) 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 // Thread termination
/** Terminate the thread. Please only let the thread terminate itself. */ /** Terminate the thread. Please only let the thread terminate itself. */
......
...@@ -51,9 +51,9 @@ class MemorySupport(val muMemorySize: Word) { ...@@ -51,9 +51,9 @@ class MemorySupport(val muMemorySize: Word) {
def cmpXchgInt(addr: Word, expected: Int, desired: Int, inMu: Boolean = true): (Boolean, Int) = { def cmpXchgInt(addr: Word, expected: Int, desired: Int, inMu: Boolean = true): (Boolean, Int) = {
assertInMuMemory(inMu, addr) assertInMuMemory(inMu, addr)
val oldVal = loadInt(addr) val oldVal = loadInt(addr, inMu)
if (oldVal == expected) { if (oldVal == expected) {
storeInt(addr, desired) storeInt(addr, desired, inMu)
return (true, oldVal) return (true, oldVal)
} else { } else {
return (false, oldVal) return (false, oldVal)
...@@ -62,9 +62,9 @@ class MemorySupport(val muMemorySize: Word) { ...@@ -62,9 +62,9 @@ class MemorySupport(val muMemorySize: Word) {
def cmpXchgLong(addr: Word, expected: Long, desired: Long, inMu: Boolean = true): (Boolean, Long) = { def cmpXchgLong(addr: Word, expected: Long, desired: Long, inMu: Boolean = true): (Boolean, Long) = {
assertInMuMemory(inMu, addr) assertInMuMemory(inMu, addr)
val oldVal = loadLong(addr) val oldVal = loadLong(addr, inMu)
if (oldVal == expected) { if (oldVal == expected) {
storeLong(addr, desired) storeLong(addr, desired, inMu)
return (true, oldVal) return (true, oldVal)
} else { } else {
return (false, oldVal) return (false, oldVal)
...@@ -73,9 +73,9 @@ class MemorySupport(val muMemorySize: Word) { ...@@ -73,9 +73,9 @@ class MemorySupport(val muMemorySize: Word) {
def cmpXchgI128(addr: Word, expected: (Long, Long), desired: (Long, Long), inMu: Boolean = true): (Boolean, (Long, Long)) = { def cmpXchgI128(addr: Word, expected: (Long, Long), desired: (Long, Long), inMu: Boolean = true): (Boolean, (Long, Long)) = {
assertInMuMemory(inMu, addr) assertInMuMemory(inMu, addr)
val oldVal = loadI128(addr) val oldVal = loadI128(addr, inMu)
if (oldVal == expected) { if (oldVal == expected) {
storeI128(addr, desired) storeI128(addr, desired, inMu)
return (true, oldVal) return (true, oldVal)
} else { } else {
return (false, oldVal) return (false, oldVal)
...@@ -84,7 +84,7 @@ class MemorySupport(val muMemorySize: Word) { ...@@ -84,7 +84,7 @@ class MemorySupport(val muMemorySize: Word) {
def atomicRMWInt(optr: AtomicRMWOptr, addr: Word, opnd: Int, inMu: Boolean = true): Int = { def atomicRMWInt(optr: AtomicRMWOptr, addr: Word, opnd: Int, inMu: Boolean = true): Int = {
assertInMuMemory(inMu, addr) assertInMuMemory(inMu, addr)
val oldVal = loadInt(addr) val oldVal = loadInt(addr, inMu)
val newVal = optr match { val newVal = optr match {
case XCHG => opnd case XCHG => opnd
case ADD => oldVal + opnd case ADD => oldVal + opnd
...@@ -98,13 +98,13 @@ class MemorySupport(val muMemorySize: Word) { ...@@ -98,13 +98,13 @@ class MemorySupport(val muMemorySize: Word) {
case UMAX => Math.max(oldVal - Int.MinValue, opnd - Int.MinValue) + Int.MinValue case UMAX => Math.max(oldVal - Int.MinValue, opnd - Int.MinValue) + Int.MinValue
case UMIN => Math.min(oldVal - Int.MinValue, opnd - Int.MinValue) + Int.MinValue case UMIN => Math.min(oldVal - Int.MinValue, opnd - Int.MinValue) + Int.MinValue
} }
storeInt(addr, newVal) storeInt(addr, newVal, inMu)
return oldVal return oldVal
} }
def atomicRMWLong(optr: AtomicRMWOptr, addr: Word, opnd: Long, inMu: Boolean = true): Long = { def atomicRMWLong(optr: AtomicRMWOptr, addr: Word, opnd: Long, inMu: Boolean = true): Long = {
assertInMuMemory(inMu, addr) assertInMuMemory(inMu, addr)
val oldVal = loadLong(addr) val oldVal = loadLong(addr, inMu)
val newVal = optr match { val newVal = optr match {
case XCHG => opnd case XCHG => opnd
case ADD => oldVal + opnd case ADD => oldVal + opnd
...@@ -118,14 +118,14 @@ class MemorySupport(val muMemorySize: Word) { ...@@ -118,14 +118,14 @@ class MemorySupport(val muMemorySize: Word) {
case UMAX => Math.max(oldVal - Long.MinValue, opnd - Long.MinValue) + Long.MinValue case UMAX => Math.max(oldVal - Long.MinValue, opnd - Long.MinValue) + Long.MinValue
case UMIN => Math.min(oldVal - Long.MinValue, opnd - Long.MinValue) + Long.MinValue case UMIN => Math.min(oldVal - Long.MinValue, opnd - Long.MinValue) + Long.MinValue
} }
storeLong(addr, newVal) storeLong(addr, newVal, inMu)
return oldVal return oldVal
} }
def xchgI128(addr: Word, desired: (Long, Long), inMu: Boolean = true): (Long, Long) = { def xchgI128(addr: Word, desired: (Long, Long), inMu: Boolean = true): (Long, Long) = {
assertInMuMemory(inMu, addr) assertInMuMemory(inMu, addr)
val oldVal = loadI128(addr) val oldVal = loadI128(addr, inMu)
storeI128(addr, desired) storeI128(addr, desired, inMu)
return oldVal return oldVal
} }
} }
...@@ -62,29 +62,31 @@ object TypeSizes { ...@@ -62,29 +62,31 @@ object TypeSizes {
val MOVE_MASK = 0x8000000000000000L val MOVE_MASK = 0x8000000000000000L
def sizeOf(ty: Type): Word = ty match { def sizeOf(ty: Type): Word = ty match {
case TypeInt(l) => intBitsToBytes(l) case TypeInt(l) => intBitsToBytes(l)
case _:TypeFloat => 4L case _: TypeFloat => 4L
case _:TypeDouble => 8L case _: TypeDouble => 8L
case _:TypeRef => WORD_SIZE_BYTES case _: TypeRef => WORD_SIZE_BYTES
case _:TypeIRef => 2L * WORD_SIZE_BYTES case _: TypeIRef => 2L * WORD_SIZE_BYTES
case _:TypeWeakRef => WORD_SIZE_BYTES case _: TypeWeakRef => WORD_SIZE_BYTES
case t @ TypeStruct(ftys) => structPrefixSizeOf(t, ftys.size) case t @ TypeStruct(ftys) => structPrefixSizeOf(t, ftys.size)
case t @ TypeArray(et,l) => seqPrefixSizeOf(t, l) case t @ TypeArray(et, l) => seqPrefixSizeOf(t, l)
case _:TypeHybrid => throw new IllegalArgumentException("Hybrid should use hybridSizeOf to probe size") case _: TypeHybrid => throw new IllegalArgumentException("Hybrid should use hybridSizeOf to probe size")
case _:TypeVoid => 0L case _: TypeVoid => 0L
case _:TypeFunc => WORD_SIZE_BYTES case _: TypeFunc => WORD_SIZE_BYTES
case _:TypeThread => WORD_SIZE_BYTES case _: TypeThread => WORD_SIZE_BYTES
case _:TypeStack => WORD_SIZE_BYTES case _: TypeStack => WORD_SIZE_BYTES
case _:TypeTagRef64 => 8L case _: TypeTagRef64 => 8L
case t @ TypeVector(et,l) => seqPrefixSizeOf(t, l) case t @ TypeVector(et, l) => seqPrefixSizeOf(t, l)
case _: TypePtr => WORD_SIZE_BYTES
case _: TypeFuncPtr => WORD_SIZE_BYTES
} }
def alignOf(ty: Type): Word = ty match { def alignOf(ty: Type): Word = ty match {
case TypeStruct(ftys) => ftys.map(sizeOf).max case TypeStruct(ftys) => ftys.map(sizeOf).max
case TypeArray(et,_) => alignOf(et) case TypeArray(et, _) =>