Commit e4fdc4b2 authored by Kunshan Wang's avatar Kunshan Wang

Switched to JNR-FFI-based native memory access.

parent 1d03dfae
...@@ -17,12 +17,15 @@ object MicroVM { ...@@ -17,12 +17,15 @@ object MicroVM {
class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE, class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE,
globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE, globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE,
stackSize: Word = MicroVM.DEFAULT_STACK_SIZE) { stackSize: Word = MicroVM.DEFAULT_STACK_SIZE) {
// implicitly injected resources
private implicit val microVM = this
val globalBundle = new Bundle() val globalBundle = new Bundle()
val constantPool = new ConstantPool(this) val constantPool = new ConstantPool()
val memoryManager = new MemoryManager(heapSize, globalSize, stackSize, this) val memoryManager = new MemoryManager(heapSize, globalSize, stackSize)
val threadStackManager = new ThreadStackManager(this) val threadStackManager = new ThreadStackManager()
val trapManager = new TrapManager(this) val trapManager = new TrapManager()
val clientAgents = new HashSet[ClientAgent]() val clientAgents = new HashSet[ClientAgent]()
val irReader = new UIRTextReader(new IDFactory()) val irReader = new UIRTextReader(new IDFactory())
......
...@@ -27,6 +27,11 @@ trait UndefinedFunctionHandler { ...@@ -27,6 +27,11 @@ trait UndefinedFunctionHandler {
} }
class ClientAgent(microVM: MicroVM) { class ClientAgent(microVM: MicroVM) {
// Injectable resources (used by memory access operations)
private implicit val microVM_ = microVM
private implicit val memorySupport = microVM.memoryManager.memorySupport
val handles = new HashSet[Handle]() val handles = new HashSet[Handle]()
microVM.clientAgents.add(this) microVM.clientAgents.add(this)
...@@ -252,7 +257,7 @@ class ClientAgent(microVM: MicroVM) { ...@@ -252,7 +257,7 @@ class ClientAgent(microVM: MicroVM) {
val iRef = b.objRef + b.offset val iRef = b.objRef + b.offset
val nb = ValueBox.makeBoxForType(uty) val nb = ValueBox.makeBoxForType(uty)
MemoryOperations.load(uty, iRef, nb, microVM) MemoryOperations.load(uty, iRef, nb)
newHandle(uty, nb) newHandle(uty, nb)
} }
...@@ -265,7 +270,7 @@ class ClientAgent(microVM: MicroVM) { ...@@ -265,7 +270,7 @@ class ClientAgent(microVM: MicroVM) {
val nvb = newVal.vb val nvb = newVal.vb
val nb = ValueBox.makeBoxForType(uty) val nb = ValueBox.makeBoxForType(uty)
MemoryOperations.store(uty, iRef, nvb, nb, microVM) MemoryOperations.store(uty, iRef, 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) = {
...@@ -276,7 +281,7 @@ class ClientAgent(microVM: MicroVM) { ...@@ -276,7 +281,7 @@ class ClientAgent(microVM: MicroVM) {
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, microVM) val succ = MemoryOperations.cmpXchg(uty, iRef, eb, db, br)
(succ, newHandle(uty, br)) (succ, newHandle(uty, br))
} }
...@@ -287,7 +292,7 @@ class ClientAgent(microVM: MicroVM) { ...@@ -287,7 +292,7 @@ class ClientAgent(microVM: MicroVM) {
val iRef = lb.objRef + lb.offset 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, microVM) MemoryOperations.atomicRMW(uty, op, iRef, ob, br)
newHandle(uty, br) newHandle(uty, br)
} }
......
...@@ -19,4 +19,7 @@ class UnimplementedOprationException(message: String = null, cause: Throwable = ...@@ -19,4 +19,7 @@ class UnimplementedOprationException(message: String = null, cause: Throwable =
class UvmRuntimeException(message: String = null, cause: Throwable = null) extends UvmRefImplException(message, cause) class UvmRuntimeException(message: String = null, cause: Throwable = null) extends UvmRefImplException(message, cause)
/** Thrown when a division by zero is executed and the exception clause is not present. */ /** Thrown when a division by zero is executed and the exception clause is not present. */
class UvmDivisionByZeroException(message: String = null, cause: Throwable = null) extends UvmRuntimeException(message, cause) class UvmDivisionByZeroException(message: String = null, cause: Throwable = null) extends UvmRuntimeException(message, cause)
\ No newline at end of file
/** Thrown when accessing Mu memory but the address is outside the allocated region. */
class UvmIllegalMemoryAccessException(message: String = null, cause: Throwable = null) extends UvmRuntimeException(message, cause)
...@@ -6,7 +6,7 @@ import uvm.ssavariables._ ...@@ -6,7 +6,7 @@ import uvm.ssavariables._
import uvm.refimpl.MicroVM import uvm.refimpl.MicroVM
import scala.collection.mutable.HashMap import scala.collection.mutable.HashMap
class ConstantPool(microVM: MicroVM) { class ConstantPool(implicit microVM: MicroVM) {
val globalVarBoxes = HashMap[GlobalVariable, ValueBox]() val globalVarBoxes = HashMap[GlobalVariable, ValueBox]()
def addGlobalVar(g: GlobalVariable) { def addGlobalVar(g: GlobalVariable) {
......
...@@ -15,9 +15,12 @@ object InterpreterThread { ...@@ -15,9 +15,12 @@ object InterpreterThread {
val logger = Logger(LoggerFactory.getLogger(getClass.getName)) val logger = Logger(LoggerFactory.getLogger(getClass.getName))
} }
class InterpreterThread(val id: Int, 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)
implicit private val memorySupport = microVM.memoryManager.memorySupport
// Thread states // Thread states
/** The underlying stack. */ /** The underlying stack. */
...@@ -683,7 +686,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -683,7 +686,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
if (la == 0L) { if (la == 0L) {
nullRefError(excClause) nullRefError(excClause)
} else { } else {
MemoryOperations.load(uty, la, ib, microVM) MemoryOperations.load(uty, la, ib)
continueNormally() continueNormally()
} }
} }
...@@ -698,7 +701,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -698,7 +701,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
if (la == 0L) { if (la == 0L) {
nullRefError(excClause) nullRefError(excClause)
} else { } else {
MemoryOperations.store(uty, la, nvb, ib, microVM) MemoryOperations.store(uty, la, nvb, ib)
continueNormally() continueNormally()
} }
} }
...@@ -714,7 +717,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -714,7 +717,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
if (la == 0L) { if (la == 0L) {
nullRefError(excClause) nullRefError(excClause)
} else { } else {
MemoryOperations.cmpXchg(uty, la, eb, db, ib, microVM) MemoryOperations.cmpXchg(uty, la, eb, db, ib)
continueNormally() continueNormally()
} }
} }
...@@ -729,7 +732,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -729,7 +732,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
if (la == 0L) { if (la == 0L) {
nullRefError(excClause) nullRefError(excClause)
} else { } else {
MemoryOperations.atomicRMW(uty, op, la, ob, ib, microVM) MemoryOperations.atomicRMW(uty, op, la, ob, ib)
continueNormally() continueNormally()
} }
} }
......
...@@ -12,7 +12,7 @@ object ThreadStackManager { ...@@ -12,7 +12,7 @@ object ThreadStackManager {
val logger = Logger(LoggerFactory.getLogger(getClass.getName)) val logger = Logger(LoggerFactory.getLogger(getClass.getName))
} }
class ThreadStackManager(microVM: MicroVM) { class ThreadStackManager(implicit microVM: MicroVM) {
import ThreadStackManager._ import ThreadStackManager._
private val stackRegistry = new HashMap[Int, InterpreterStack]() private val stackRegistry = new HashMap[Int, InterpreterStack]()
......
...@@ -3,7 +3,7 @@ package uvm.refimpl.itpr ...@@ -3,7 +3,7 @@ package uvm.refimpl.itpr
import uvm.refimpl._ import uvm.refimpl._
import scala.collection.mutable.HashSet import scala.collection.mutable.HashSet
class TrapManager(microVM: MicroVM) { class TrapManager(implicit microVM: MicroVM) {
var trapHandler: TrapHandler = DefaultTrapHandler var trapHandler: TrapHandler = DefaultTrapHandler
var undefinedFunctionHandler: UndefinedFunctionHandler = DefaultUndefinedFunctionHandler var undefinedFunctionHandler: UndefinedFunctionHandler = DefaultUndefinedFunctionHandler
......
...@@ -7,9 +7,11 @@ import uvm.refimpl.mem.TypeSizes._ ...@@ -7,9 +7,11 @@ import uvm.refimpl.mem.TypeSizes._
import uvm.refimpl.mem.bumppointer.RewindableBumpPointerAllocator import uvm.refimpl.mem.bumppointer.RewindableBumpPointerAllocator
import java.util.HashMap import java.util.HashMap
class GlobalMemory(begin: Word, size: Word, microVM: MicroVM) extends Space("GlobalSpace", begin, size) { class GlobalMemory(begin: Word, size: Word)(
implicit microVM: MicroVM, memorySupport: MemorySupport)
extends Space("GlobalSpace", begin, size) {
val allocator = new RewindableBumpPointerAllocator(begin, size, microVM) val allocator = new RewindableBumpPointerAllocator(begin, size)
private val locationMap = new HashMap[GlobalCell, Word]() private val locationMap = new HashMap[GlobalCell, Word]()
......
...@@ -6,32 +6,35 @@ import uvm.refimpl.mem.TypeSizes.Word ...@@ -6,32 +6,35 @@ import uvm.refimpl.mem.TypeSizes.Word
import com.typesafe.scalalogging._ import com.typesafe.scalalogging._
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
/**
* Accessors to object headers. Require MemorySupport.
*/
object HeaderUtils extends StrictLogging { object HeaderUtils extends StrictLogging {
def postAllocScalar(addr: Word, tag: Word) { def postAllocScalar(addr: Word, tag: Word)(implicit memorySupport: MemorySupport) {
setTag(addr, tag) setTag(addr, tag)
} }
def postAllocHybrid(addr: Word, tag: Word, len: Word) { def postAllocHybrid(addr: Word, tag: Word, len: Word)(implicit memorySupport: MemorySupport) {
postAllocScalar(addr, tag) postAllocScalar(addr, tag)
setVarLength(addr, len) setVarLength(addr, len)
} }
def getTag(objRef: Word): Word = { def getTag(objRef: Word)(implicit memorySupport: MemorySupport): Word = {
MemorySupport.loadLong(objRef + TypeSizes.GC_HEADER_OFFSET_TAG) memorySupport.loadLong(objRef + TypeSizes.GC_HEADER_OFFSET_TAG)
} }
def getVarLength(objRef: Word): Word = { def getVarLength(objRef: Word)(implicit memorySupport: MemorySupport): Word = {
MemorySupport.loadLong(objRef + TypeSizes.GC_HEADER_OFFSET_HYBRID_LENGTH) memorySupport.loadLong(objRef + TypeSizes.GC_HEADER_OFFSET_HYBRID_LENGTH)
} }
def setTag(objRef: Word, tag: Word) { def setTag(objRef: Word, tag: Word)(implicit memorySupport: MemorySupport) {
logger.debug("Storing tag 0x%x at addr 0x%x".format(tag, objRef + TypeSizes.GC_HEADER_OFFSET_TAG)) logger.debug("Storing tag 0x%x at addr 0x%x".format(tag, objRef + TypeSizes.GC_HEADER_OFFSET_TAG))
MemorySupport.storeLong(objRef + TypeSizes.GC_HEADER_OFFSET_TAG, tag) memorySupport.storeLong(objRef + TypeSizes.GC_HEADER_OFFSET_TAG, tag)
} }
def setVarLength(objRef: Word, len: Word) { def setVarLength(objRef: Word, len: Word)(implicit memorySupport: MemorySupport) {
MemorySupport.storeLong(objRef + TypeSizes.GC_HEADER_OFFSET_HYBRID_LENGTH, len) memorySupport.storeLong(objRef + TypeSizes.GC_HEADER_OFFSET_HYBRID_LENGTH, len)
} }
def getTypeID(tag: Word): Int = (tag & 0x00000000ffffffffL).toInt def getTypeID(tag: Word): Int = (tag & 0x00000000ffffffffL).toInt
......
...@@ -5,22 +5,22 @@ import TypeSizes._ ...@@ -5,22 +5,22 @@ import TypeSizes._
object MemUtils extends StrictLogging { object MemUtils extends StrictLogging {
def zeroRegion(start: Word, length: Word) { def zeroRegion(start: Word, length: Word)(implicit memorySupport: MemorySupport) {
val end = start + length val end = start + length
logger.debug("Zeroing [0x%x -> 0x%x] %d bytes".format(start, end, length)) logger.debug("Zeroing [0x%x -> 0x%x] %d bytes".format(start, end, length))
var a = start var a = start
while (a < end) { while (a < end) {
MemorySupport.storeLong(a, 0) memorySupport.storeLong(a, 0L)
a += WORD_SIZE_BYTES a += WORD_SIZE_BYTES
} }
} }
def memcpy(src: Word, dst: Word, length: Word) { def memcpy(src: Word, dst: Word, length: Word)(implicit memorySupport: MemorySupport) {
logger.debug("Copying [0x%x -> 0x%x] %d bytes".format(src, dst, length)) logger.debug("Copying [0x%x -> 0x%x] %d bytes".format(src, dst, length))
var a: Word = 0 var a: Word = 0
while (a < length) { while (a < length) {
val oldWord = MemorySupport.loadLong(src + a) val oldWord = memorySupport.loadLong(src + a)
MemorySupport.storeLong(dst + a, oldWord) memorySupport.storeLong(dst + a, oldWord)
a += WORD_SIZE_BYTES a += WORD_SIZE_BYTES
} }
} }
......
...@@ -3,23 +3,24 @@ package uvm.refimpl.mem ...@@ -3,23 +3,24 @@ package uvm.refimpl.mem
import uvm.refimpl._ import uvm.refimpl._
import TypeSizes._ import TypeSizes._
import uvm.refimpl.mem.simpleimmix._ import uvm.refimpl.mem.simpleimmix._
import MemoryManager._
object MemoryManager { class MemoryManager(val heapSize: Word, val globalSize: Word, val stackSize: Word)(implicit microVM: MicroVM) {
val MEMORY_BEGIN = 0x100000L
} val totalMemorySize = heapSize + globalSize
class MemoryManager(val heapSize: Word, val globalSize: Word, val stackSize: Word, microVM: MicroVM) { implicit val memorySupport = new MemorySupport(totalMemorySize)
val heap = new SimpleImmixHeap(MEMORY_BEGIN, heapSize, microVM) val memoryBegin = memorySupport.muMemoryBegin
val heapBegin = TypeSizes.alignUp(memoryBegin, SimpleImmixSpace.BLOCK_SIZE)
val globalMemory = new GlobalMemory(MEMORY_BEGIN + heapSize, globalSize, microVM)
val heap = new SimpleImmixHeap(heapBegin, heapSize)
val globalMemory = new GlobalMemory(heapBegin + heapSize, globalSize)
def makeMutator(): Mutator = heap.makeMutator() def makeMutator(): Mutator = heap.makeMutator()
def makeStackMemory(mutator: Mutator): StackMemory = { def makeStackMemory(mutator: Mutator): StackMemory = {
val objRef = mutator.newHybrid(InternalTypes.BYTE_ARRAY, stackSize) val objRef = mutator.newHybrid(InternalTypes.BYTE_ARRAY, stackSize)
val stackMemory = new StackMemory(objRef, stackSize, microVM) val stackMemory = new StackMemory(objRef, stackSize)
stackMemory stackMemory
} }
} }
...@@ -3,100 +3,129 @@ package uvm.refimpl.mem ...@@ -3,100 +3,129 @@ package uvm.refimpl.mem
import uvm.refimpl.mem.TypeSizes.Word import uvm.refimpl.mem.TypeSizes.Word
import java.nio.ByteBuffer import java.nio.ByteBuffer
import uvm.ssavariables.AtomicRMWOptr._ import uvm.ssavariables.AtomicRMWOptr._
import jnr.ffi.{ Runtime, Memory, Pointer }
import uvm.refimpl.UvmRuntimeException
import uvm.refimpl.UvmIllegalMemoryAccessException
object MemorySupport { /**
val MEMORY_SIZE: Word = 1024L * 1024L * 1024L * Support for native memory access. Backed by JNR-FFI.
*/
class MemorySupport(val muMemorySize: Word) {
val SIZE_LIMIT: Word = Int.MaxValue.toLong
val bb: ByteBuffer = ByteBuffer.allocateDirect(MEMORY_SIZE.toInt) if (muMemorySize > SIZE_LIMIT) {
bb.order(java.nio.ByteOrder.LITTLE_ENDIAN) throw new UvmRuntimeException("Memory too large (%d bytes requested)." +
" Due to the limitation of JNR-FFI, the maximum available memory size is %d bytes.".format(muMemorySize, SIZE_LIMIT))
}
val jnrRuntime = Runtime.getSystemRuntime
val muMemory = Memory.allocateDirect(jnrRuntime, muMemorySize.toInt, true)
val muMemoryBegin = muMemory.address()
val muMemoryEnd = muMemoryBegin + muMemorySize
val theMemory = Pointer.wrap(jnrRuntime, 0L)
def isInMuMemory(addr: Word): Boolean = muMemoryBegin <= addr && addr < muMemoryEnd
def assertInMuMemory(inMu: Boolean, addr: Word): Unit = {
if (inMu && !isInMuMemory(addr)) {
throw new UvmIllegalMemoryAccessException("Accessed address 0x%x outside the Mu memory [0x%x-0x%x].".format(addr, muMemoryBegin, muMemoryEnd))
}
}
def loadByte(loc: Word): Byte = bb.get(loc.toInt) def loadByte(addr: Word, inMu: Boolean = true): Byte = { assertInMuMemory(inMu, addr); theMemory.getByte(addr) }
def loadShort(loc: Word): Short = bb.getShort(loc.toInt) def loadShort(addr: Word, inMu: Boolean = true): Short = { assertInMuMemory(inMu, addr); theMemory.getShort(addr) }
def loadInt(loc: Word): Int = bb.getInt(loc.toInt) def loadInt(addr: Word, inMu: Boolean = true): Int = { assertInMuMemory(inMu, addr); theMemory.getInt(addr) }
def loadLong(loc: Word): Long = bb.getLong(loc.toInt) def loadLong(addr: Word, inMu: Boolean = true): Long = { assertInMuMemory(inMu, addr); theMemory.getLong(addr) }
def loadI128(loc: Word): (Long, Long) = (bb.getLong(loc.toInt), bb.getLong(loc.toInt + 8)) def loadI128(addr: Word, inMu: Boolean = true): (Long, Long) = { assertInMuMemory(inMu, addr); (theMemory.getLong(addr), theMemory.getLong(addr + 8)) }
def loadFloat(loc: Word): Float = bb.getFloat(loc.toInt) def loadFloat(addr: Word, inMu: Boolean = true): Float = { assertInMuMemory(inMu, addr); theMemory.getFloat(addr) }
def loadDouble(loc: Word): Double = bb.getDouble(loc.toInt) def loadDouble(addr: Word, inMu: Boolean = true): Double = { assertInMuMemory(inMu, addr); theMemory.getDouble(addr) }
def storeByte(loc: Word, v: Byte): Unit = bb.put(loc.toInt, v) def storeByte(addr: Word, v: Byte, inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); theMemory.putByte(addr, v) }
def storeShort(loc: Word, v: Short): Unit = bb.putShort(loc.toInt, v) def storeShort(addr: Word, v: Short, inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); theMemory.putShort(addr, v) }
def storeInt(loc: Word, v: Int): Unit = bb.putInt(loc.toInt, v) def storeInt(addr: Word, v: Int, inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); theMemory.putInt(addr, v) }
def storeLong(loc: Word, v: Long): Unit = bb.putLong(loc.toInt, v) def storeLong(addr: Word, v: Long, inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); theMemory.putLong(addr, v) }
def storeI128(loc: Word, v: (Long, Long)): Unit = { val (low, high) = v; bb.putLong(loc.toInt, low); bb.putLong(loc.toInt + 8, high) } def storeI128(addr: Word, v: (Long, Long), inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); val (low, high) = v; theMemory.putLong(addr, low); theMemory.putLong(addr + 8, high) }
def storeFloat(loc: Word, v: Float): Unit = bb.putFloat(loc.toInt, v) def storeFloat(addr: Word, v: Float, inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); theMemory.putFloat(addr, v) }
def storeDouble(loc: Word, v: Double): Unit = bb.putDouble(loc.toInt, v) def storeDouble(addr: Word, v: Double, inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); theMemory.putDouble(addr, v) }
def cmpXchgInt(loc: Word, expected: Int, desired: Int): (Boolean, Int) = { def cmpXchgInt(addr: Word, expected: Int, desired: Int, inMu: Boolean = true): (Boolean, Int) = {
val oldVal = loadInt(loc) assertInMuMemory(inMu, addr)
val oldVal = loadInt(addr)
if (oldVal == expected) { if (oldVal == expected) {
storeInt(loc, desired) storeInt(addr, desired)
return (true, oldVal) return (true, oldVal)
} else { } else {
return (false, oldVal) return (false, oldVal)
} }
} }
def cmpXchgLong(loc: Word, expected: Long, desired: Long): (Boolean, Long) = { def cmpXchgLong(addr: Word, expected: Long, desired: Long, inMu: Boolean = true): (Boolean, Long) = {
val oldVal = loadLong(loc) assertInMuMemory(inMu, addr)
val oldVal = loadLong(addr)
if (oldVal == expected) { if (oldVal == expected) {
storeLong(loc, desired) storeLong(addr, desired)
return (true, oldVal) return (true, oldVal)
} else { } else {
return (false, oldVal) return (false, oldVal)
} }
} }
def cmpXchgI128(loc: Word, expected: (Long, Long), desired: (Long, Long)): (Boolean, (Long, Long)) = { def cmpXchgI128(addr: Word, expected: (Long, Long), desired: (Long, Long), inMu: Boolean = true): (Boolean, (Long, Long)) = {
val oldVal = loadI128(loc) assertInMuMemory(inMu, addr)
val oldVal = loadI128(addr)
if (oldVal == expected) { if (oldVal == expected) {
storeI128(loc, desired) storeI128(addr, desired)
return (true, oldVal) return (true, oldVal)
} else { } else {
return (false, oldVal) return (false, oldVal)
} }
} }
def atomicRMWInt(optr: AtomicRMWOptr, loc: Word, opnd: Int): Int = { def atomicRMWInt(optr: AtomicRMWOptr, addr: Word, opnd: Int, inMu: Boolean = true): Int = {
val oldVal = loadInt(loc) assertInMuMemory(inMu, addr)
val oldVal = loadInt(addr)
val newVal = optr match { val newVal = optr match {
case XCHG => opnd case XCHG => opnd
case ADD => oldVal + opnd case ADD => oldVal + opnd
case SUB => oldVal - opnd case SUB => oldVal - opnd
case AND => oldVal & opnd case AND => oldVal & opnd
case NAND => ~(oldVal & opnd) case NAND => ~(oldVal & opnd)
case OR => oldVal | opnd case OR => oldVal | opnd
case XOR => oldVal ^ opnd case XOR => oldVal ^ opnd
case MAX => Math.max(oldVal, opnd) case MAX => Math.max(oldVal, opnd)
case MIN => Math.min(oldVal, opnd) case MIN => Math.min(oldVal, opnd)
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(loc, newVal) storeInt(addr, newVal)
return oldVal return oldVal
} }
def atomicRMWLong(optr: AtomicRMWOptr, loc: Word, opnd: Long): Long = { def atomicRMWLong(optr: AtomicRMWOptr, addr: Word, opnd: Long, inMu: Boolean = true): Long = {
val oldVal = loadLong(loc) assertInMuMemory(inMu, addr)
val oldVal = loadLong(addr)
val newVal = optr match { val newVal = optr match {
case XCHG => opnd case XCHG => opnd
case ADD => oldVal + opnd case ADD => oldVal + opnd
case SUB => oldVal - opnd case SUB => oldVal - opnd
case AND => oldVal & opnd case AND => oldVal & opnd
case NAND => ~(oldVal & opnd) case NAND => ~(oldVal & opnd)
case OR => oldVal | opnd case OR => oldVal | opnd
case XOR => oldVal ^ opnd case XOR => oldVal ^ opnd
case MAX => Math.max(oldVal, opnd) case MAX => Math.max(oldVal, opnd)
case MIN => Math.min(oldVal, opnd) case MIN => Math.min(oldVal, opnd)
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(loc, newVal) storeLong(addr, newVal)
return oldVal return oldVal
} }
def xchgI128(loc: Word, desired: (Long, Long)): (Long, Long) = { def xchgI128(addr: Word, desired: (Long, Long), inMu: Boolean = true): (Long, Long) = {
val oldVal = loadI128(loc) assertInMuMemory(inMu, addr)
storeI128(loc, desired) val oldVal = loadI128(addr)
storeI128(addr, desired)
return oldVal return oldVal
} }
} }
\ No newline at end of file
...@@ -3,7 +3,7 @@ package uvm.refimpl.mem ...@@ -3,7 +3,7 @@ package uvm.refimpl.mem
import uvm.types._ import uvm.types._
import TypeSizes._ import TypeSizes._
abstract class Mutator { abstract class Mutator(implicit memorySupport: MemorySupport) {
def alloc(size: Word, align: Word, headerSize: Word): Word def alloc(size: Word, align: Word, headerSize: Word): Word
......
...@@ -9,5 +9,6 @@ import TypeSizes.Word ...@@ -9,5 +9,6 @@ import TypeSizes.Word
* <p> * <p>
* If the stack is Dead, the stackObjRef will be a dangling pointer. * If the stack is Dead, the stackObjRef will be a dangling pointer.
*/ */
class StackMemory(val stackObjRef: Word, extend: Word, microVM: MicroVM) class StackMemory(val stackObjRef: Word, extend: Word)(
extends RewindableBumpPointerAllocator(stackObjRef, extend, microVM) implicit microVM: MicroVM, memorySupport: MemorySupport)
extends RewindableBumpPointerAllocator(stackObjRef, extend)
...@@ -14,8 +14,9 @@ object RewindableBumpPointerAllocator { ...@@ -14,8 +14,9 @@ object RewindableBumpPointerAllocator {
val logger: Logger = Logger(LoggerFactory.getLogger(getClass.getName))