GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

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 {
class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE,
globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE,
stackSize: Word = MicroVM.DEFAULT_STACK_SIZE) {
// implicitly injected resources
private implicit val microVM = this
val globalBundle = new Bundle()
val constantPool = new ConstantPool(this)
val memoryManager = new MemoryManager(heapSize, globalSize, stackSize, this)
val threadStackManager = new ThreadStackManager(this)
val trapManager = new TrapManager(this)
val constantPool = new ConstantPool()
val memoryManager = new MemoryManager(heapSize, globalSize, stackSize)
val threadStackManager = new ThreadStackManager()
val trapManager = new TrapManager()
val clientAgents = new HashSet[ClientAgent]()
val irReader = new UIRTextReader(new IDFactory())
......
......@@ -27,6 +27,11 @@ trait UndefinedFunctionHandler {
}
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]()
microVM.clientAgents.add(this)
......@@ -252,7 +257,7 @@ class ClientAgent(microVM: MicroVM) {
val iRef = b.objRef + b.offset
val nb = ValueBox.makeBoxForType(uty)
MemoryOperations.load(uty, iRef, nb, microVM)
MemoryOperations.load(uty, iRef, nb)
newHandle(uty, nb)
}
......@@ -265,7 +270,7 @@ class ClientAgent(microVM: MicroVM) {
val nvb = newVal.vb
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) = {
......@@ -276,7 +281,7 @@ class ClientAgent(microVM: MicroVM) {
val eb = expected.vb
val db = desired.vb
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))
}
......@@ -287,7 +292,7 @@ class ClientAgent(microVM: MicroVM) {
val iRef = lb.objRef + lb.offset
val ob = opnd.vb
val br = ValueBox.makeBoxForType(uty)
MemoryOperations.atomicRMW(uty, op, iRef, ob, br, microVM)
MemoryOperations.atomicRMW(uty, op, iRef, ob, br)
newHandle(uty, br)
}
......
......@@ -19,4 +19,7 @@ class UnimplementedOprationException(message: String = null, cause: Throwable =
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. */
class UvmDivisionByZeroException(message: String = null, cause: Throwable = null) extends UvmRuntimeException(message, cause)
\ No newline at end of file
class UvmDivisionByZeroException(message: String = null, cause: Throwable = null) extends UvmRuntimeException(message, cause)
/** 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._
import uvm.refimpl.MicroVM
import scala.collection.mutable.HashMap
class ConstantPool(microVM: MicroVM) {
class ConstantPool(implicit microVM: MicroVM) {
val globalVarBoxes = HashMap[GlobalVariable, ValueBox]()
def addGlobalVar(g: GlobalVariable) {
......
......@@ -15,9 +15,12 @@ object InterpreterThread {
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._
// Injectable resources (used by memory access instructions)
implicit private val memorySupport = microVM.memoryManager.memorySupport
// Thread states
/** The underlying stack. */
......@@ -683,7 +686,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
if (la == 0L) {
nullRefError(excClause)
} else {
MemoryOperations.load(uty, la, ib, microVM)
MemoryOperations.load(uty, la, ib)
continueNormally()
}
}
......@@ -698,7 +701,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
if (la == 0L) {
nullRefError(excClause)
} else {
MemoryOperations.store(uty, la, nvb, ib, microVM)
MemoryOperations.store(uty, la, nvb, ib)
continueNormally()
}
}
......@@ -714,7 +717,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
if (la == 0L) {
nullRefError(excClause)
} else {
MemoryOperations.cmpXchg(uty, la, eb, db, ib, microVM)
MemoryOperations.cmpXchg(uty, la, eb, db, ib)
continueNormally()
}
}
......@@ -729,7 +732,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
if (la == 0L) {
nullRefError(excClause)
} else {
MemoryOperations.atomicRMW(uty, op, la, ob, ib, microVM)
MemoryOperations.atomicRMW(uty, op, la, ob, ib)
continueNormally()
}
}
......
......@@ -12,7 +12,7 @@ object ThreadStackManager {
val logger = Logger(LoggerFactory.getLogger(getClass.getName))
}
class ThreadStackManager(microVM: MicroVM) {
class ThreadStackManager(implicit microVM: MicroVM) {
import ThreadStackManager._
private val stackRegistry = new HashMap[Int, InterpreterStack]()
......
......@@ -3,7 +3,7 @@ package uvm.refimpl.itpr
import uvm.refimpl._
import scala.collection.mutable.HashSet
class TrapManager(microVM: MicroVM) {
class TrapManager(implicit microVM: MicroVM) {
var trapHandler: TrapHandler = DefaultTrapHandler
var undefinedFunctionHandler: UndefinedFunctionHandler = DefaultUndefinedFunctionHandler
......
......@@ -7,9 +7,11 @@ import uvm.refimpl.mem.TypeSizes._
import uvm.refimpl.mem.bumppointer.RewindableBumpPointerAllocator
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]()
......
......@@ -6,32 +6,35 @@ import uvm.refimpl.mem.TypeSizes.Word
import com.typesafe.scalalogging._
import org.slf4j.LoggerFactory
/**
* Accessors to object headers. Require MemorySupport.
*/
object HeaderUtils extends StrictLogging {
def postAllocScalar(addr: Word, tag: Word) {
def postAllocScalar(addr: Word, tag: Word)(implicit memorySupport: MemorySupport) {
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)
setVarLength(addr, len)
}
def getTag(objRef: Word): Word = {
MemorySupport.loadLong(objRef + TypeSizes.GC_HEADER_OFFSET_TAG)
def getTag(objRef: Word)(implicit memorySupport: MemorySupport): Word = {
memorySupport.loadLong(objRef + TypeSizes.GC_HEADER_OFFSET_TAG)
}
def getVarLength(objRef: Word): Word = {
MemorySupport.loadLong(objRef + TypeSizes.GC_HEADER_OFFSET_HYBRID_LENGTH)
def getVarLength(objRef: Word)(implicit memorySupport: MemorySupport): Word = {
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))
MemorySupport.storeLong(objRef + TypeSizes.GC_HEADER_OFFSET_TAG, tag)
memorySupport.storeLong(objRef + TypeSizes.GC_HEADER_OFFSET_TAG, tag)
}
def setVarLength(objRef: Word, len: Word) {
MemorySupport.storeLong(objRef + TypeSizes.GC_HEADER_OFFSET_HYBRID_LENGTH, len)
def setVarLength(objRef: Word, len: Word)(implicit memorySupport: MemorySupport) {
memorySupport.storeLong(objRef + TypeSizes.GC_HEADER_OFFSET_HYBRID_LENGTH, len)
}
def getTypeID(tag: Word): Int = (tag & 0x00000000ffffffffL).toInt
......
......@@ -5,22 +5,22 @@ import TypeSizes._
object MemUtils extends StrictLogging {
def zeroRegion(start: Word, length: Word) {
def zeroRegion(start: Word, length: Word)(implicit memorySupport: MemorySupport) {
val end = start + length
logger.debug("Zeroing [0x%x -> 0x%x] %d bytes".format(start, end, length))
var a = start
while (a < end) {
MemorySupport.storeLong(a, 0)
memorySupport.storeLong(a, 0L)
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))
var a: Word = 0
while (a < length) {
val oldWord = MemorySupport.loadLong(src + a)
MemorySupport.storeLong(dst + a, oldWord)
val oldWord = memorySupport.loadLong(src + a)
memorySupport.storeLong(dst + a, oldWord)
a += WORD_SIZE_BYTES
}
}
......
......@@ -3,23 +3,24 @@ package uvm.refimpl.mem
import uvm.refimpl._
import TypeSizes._
import uvm.refimpl.mem.simpleimmix._
import MemoryManager._
object MemoryManager {
val MEMORY_BEGIN = 0x100000L
}
class MemoryManager(val heapSize: Word, val globalSize: Word, val stackSize: Word, microVM: MicroVM) {
val heap = new SimpleImmixHeap(MEMORY_BEGIN, heapSize, microVM)
val globalMemory = new GlobalMemory(MEMORY_BEGIN + heapSize, globalSize, microVM)
class MemoryManager(val heapSize: Word, val globalSize: Word, val stackSize: Word)(implicit microVM: MicroVM) {
val totalMemorySize = heapSize + globalSize
implicit val memorySupport = new MemorySupport(totalMemorySize)
val memoryBegin = memorySupport.muMemoryBegin
val heapBegin = TypeSizes.alignUp(memoryBegin, SimpleImmixSpace.BLOCK_SIZE)
val heap = new SimpleImmixHeap(heapBegin, heapSize)
val globalMemory = new GlobalMemory(heapBegin + heapSize, globalSize)
def makeMutator(): Mutator = heap.makeMutator()
def makeStackMemory(mutator: Mutator): StackMemory = {
val objRef = mutator.newHybrid(InternalTypes.BYTE_ARRAY, stackSize)
val stackMemory = new StackMemory(objRef, stackSize, microVM)
val stackMemory = new StackMemory(objRef, stackSize)
stackMemory
}
}
......@@ -3,100 +3,129 @@ package uvm.refimpl.mem
import uvm.refimpl.mem.TypeSizes.Word
import java.nio.ByteBuffer
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)
bb.order(java.nio.ByteOrder.LITTLE_ENDIAN)
if (muMemorySize > SIZE_LIMIT) {
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 loadShort(loc: Word): Short = bb.getShort(loc.toInt)
def loadInt(loc: Word): Int = bb.getInt(loc.toInt)
def loadLong(loc: Word): Long = bb.getLong(loc.toInt)
def loadI128(loc: Word): (Long, Long) = (bb.getLong(loc.toInt), bb.getLong(loc.toInt + 8))
def loadFloat(loc: Word): Float = bb.getFloat(loc.toInt)
def loadDouble(loc: Word): Double = bb.getDouble(loc.toInt)
def loadByte(addr: Word, inMu: Boolean = true): Byte = { assertInMuMemory(inMu, addr); theMemory.getByte(addr) }
def loadShort(addr: Word, inMu: Boolean = true): Short = { assertInMuMemory(inMu, addr); theMemory.getShort(addr) }
def loadInt(addr: Word, inMu: Boolean = true): Int = { assertInMuMemory(inMu, addr); theMemory.getInt(addr) }
def loadLong(addr: Word, inMu: Boolean = true): Long = { assertInMuMemory(inMu, addr); theMemory.getLong(addr) }
def loadI128(addr: Word, inMu: Boolean = true): (Long, Long) = { assertInMuMemory(inMu, addr); (theMemory.getLong(addr), theMemory.getLong(addr + 8)) }
def loadFloat(addr: Word, inMu: Boolean = true): Float = { assertInMuMemory(inMu, addr); theMemory.getFloat(addr) }
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 storeShort(loc: Word, v: Short): Unit = bb.putShort(loc.toInt, v)
def storeInt(loc: Word, v: Int): Unit = bb.putInt(loc.toInt, v)
def storeLong(loc: Word, v: Long): Unit = bb.putLong(loc.toInt, 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 storeFloat(loc: Word, v: Float): Unit = bb.putFloat(loc.toInt, v)
def storeDouble(loc: Word, v: Double): Unit = bb.putDouble(loc.toInt, v)
def storeByte(addr: Word, v: Byte, inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); theMemory.putByte(addr, v) }
def storeShort(addr: Word, v: Short, inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); theMemory.putShort(addr, v) }
def storeInt(addr: Word, v: Int, inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); theMemory.putInt(addr, v) }
def storeLong(addr: Word, v: Long, inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); theMemory.putLong(addr, v) }
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(addr: Word, v: Float, inMu: Boolean = true): Unit = { assertInMuMemory(inMu, addr); theMemory.putFloat(addr, 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) = {
val oldVal = loadInt(loc)
def cmpXchgInt(addr: Word, expected: Int, desired: Int, inMu: Boolean = true): (Boolean, Int) = {
assertInMuMemory(inMu, addr)
val oldVal = loadInt(addr)
if (oldVal == expected) {
storeInt(loc, desired)
storeInt(addr, desired)
return (true, oldVal)
} else {
return (false, oldVal)
}
}
def cmpXchgLong(loc: Word, expected: Long, desired: Long): (Boolean, Long) = {
val oldVal = loadLong(loc)
def cmpXchgLong(addr: Word, expected: Long, desired: Long, inMu: Boolean = true): (Boolean, Long) = {
assertInMuMemory(inMu, addr)
val oldVal = loadLong(addr)
if (oldVal == expected) {
storeLong(loc, desired)
storeLong(addr, desired)
return (true, oldVal)
} else {
return (false, oldVal)
}
}
def cmpXchgI128(loc: Word, expected: (Long, Long), desired: (Long, Long)): (Boolean, (Long, Long)) = {
val oldVal = loadI128(loc)
def cmpXchgI128(addr: Word, expected: (Long, Long), desired: (Long, Long), inMu: Boolean = true): (Boolean, (Long, Long)) = {
assertInMuMemory(inMu, addr)
val oldVal = loadI128(addr)
if (oldVal == expected) {
storeI128(loc, desired)
storeI128(addr, desired)
return (true, oldVal)
} else {
return (false, oldVal)
}
}
def atomicRMWInt(optr: AtomicRMWOptr, loc: Word, opnd: Int): Int = {
val oldVal = loadInt(loc)
def atomicRMWInt(optr: AtomicRMWOptr, addr: Word, opnd: Int, inMu: Boolean = true): Int = {
assertInMuMemory(inMu, addr)
val oldVal = loadInt(addr)
val newVal = optr match {
case XCHG => opnd
case ADD => oldVal + opnd
case SUB => oldVal - opnd
case AND => oldVal & opnd
case ADD => oldVal + opnd
case SUB => oldVal - opnd
case AND => oldVal & opnd
case NAND => ~(oldVal & opnd)
case OR => oldVal | opnd
case XOR => oldVal ^ opnd
case MAX => Math.max(oldVal, opnd)
case MIN => Math.min(oldVal, opnd)
case OR => oldVal | opnd
case XOR => oldVal ^ opnd
case MAX => Math.max(oldVal, opnd)
case MIN => Math.min(oldVal, opnd)
case UMAX => Math.max(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
}
def atomicRMWLong(optr: AtomicRMWOptr, loc: Word, opnd: Long): Long = {
val oldVal = loadLong(loc)
def atomicRMWLong(optr: AtomicRMWOptr, addr: Word, opnd: Long, inMu: Boolean = true): Long = {
assertInMuMemory(inMu, addr)
val oldVal = loadLong(addr)
val newVal = optr match {
case XCHG => opnd
case ADD => oldVal + opnd
case SUB => oldVal - opnd
case AND => oldVal & opnd
case ADD => oldVal + opnd
case SUB => oldVal - opnd
case AND => oldVal & opnd
case NAND => ~(oldVal & opnd)
case OR => oldVal | opnd
case XOR => oldVal ^ opnd
case MAX => Math.max(oldVal, opnd)
case MIN => Math.min(oldVal, opnd)
case OR => oldVal | opnd
case XOR => oldVal ^ opnd
case MAX => Math.max(oldVal, opnd)
case MIN => Math.min(oldVal, opnd)
case UMAX => Math.max(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
}
def xchgI128(loc: Word, desired: (Long, Long)): (Long, Long) = {
val oldVal = loadI128(loc)
storeI128(loc, desired)
def xchgI128(addr: Word, desired: (Long, Long), inMu: Boolean = true): (Long, Long) = {
assertInMuMemory(inMu, addr)
val oldVal = loadI128(addr)
storeI128(addr, desired)
return oldVal
}
}
\ No newline at end of file
}
......@@ -3,7 +3,7 @@ package uvm.refimpl.mem
import uvm.types._
import TypeSizes._
abstract class Mutator {
abstract class Mutator(implicit memorySupport: MemorySupport) {
def alloc(size: Word, align: Word, headerSize: Word): Word
......
......@@ -9,5 +9,6 @@ import TypeSizes.Word
* <p>
* If the stack is Dead, the stackObjRef will be a dangling pointer.
*/
class StackMemory(val stackObjRef: Word, extend: Word, microVM: MicroVM)
extends RewindableBumpPointerAllocator(stackObjRef, extend, microVM)
class StackMemory(val stackObjRef: Word, extend: Word)(
implicit microVM: MicroVM, memorySupport: MemorySupport)
extends RewindableBumpPointerAllocator(stackObjRef, extend)
......@@ -14,8 +14,9 @@ object RewindableBumpPointerAllocator {
val logger: Logger = Logger(LoggerFactory.getLogger(getClass.getName))
}
class RewindableBumpPointerAllocator(val begin: Word, val extend: Word, val microVM: MicroVM)
extends Allocator {
class RewindableBumpPointerAllocator(val begin: Word, val extend: Word)(
implicit microVM: MicroVM, memorySupport: MemorySupport)
extends Allocator {
import RewindableBumpPointerAllocator._
var top: Word = begin
......@@ -30,7 +31,7 @@ class RewindableBumpPointerAllocator(val begin: Word, val extend: Word, val micr
}
logger.debug(s"alloc(${size}, ${align}, ${headerSize}) top=${top} iRef=${iRef} nextTop=${nextTop}")
MemUtils.zeroRegion(dataStart, nextTop - dataStart)
MemorySupport.storeLong(nextTop, iRef)
memorySupport.storeLong(nextTop, iRef)
top = nextTop
iRef
}
......@@ -45,7 +46,7 @@ class RewindableBumpPointerAllocator(val begin: Word, val extend: Word, val micr
var reachBottom = false
while (!reachBottom) {
logger.debug("curTopLoc is 0x%x".format(curTopLoc))
val iRef = MemorySupport.loadLong(curTopLoc)
val iRef = memorySupport.loadLong(curTopLoc)
logger.debug("iRef is 0x%x".format(iRef))
if (iRef != 0) {
val hdr = HeaderUtils.getTag(iRef)
......@@ -53,7 +54,7 @@ class RewindableBumpPointerAllocator(val begin: Word, val extend: Word, val micr
logger.debug("hdr=0x%x, typeID=0x%x".format(hdr, typeID))
val ty = microVM.globalBundle.typeNs(typeID)
logger.debug("type=%s: %s".format(ty.repr, ty.toString))
MemoryDataScanner.scanField(ty, 0, iRef, microVM, handler)
MemoryDataScanner.scanField(ty, 0, iRef, handler)
var prevTopLoc: Word = 0L
prevTopLoc = if (ty.isInstanceOf[TypeHybrid]) {
iRef - TypeSizes.GC_HEADER_SIZE_HYBRID - WORD_SIZE_BYTES
......
......@@ -38,10 +38,9 @@ object LargeObjectSpace {
* <p>
* Objects in this space are never moved.
*/
class LargeObjectSpace(val heap: SimpleImmixHeap,
name: String,
begin: Long,
extend: Word) extends Space(name, begin, extend) {
class LargeObjectSpace(val heap: SimpleImmixHeap, name: String, begin: Long, extend: Word)(
implicit memorySupport: MemorySupport)
extends Space(name, begin, extend) {
if (extend % BLOCK_SIZE != 0)
throw new UvmRefImplException("extend %d should be a multiple of BLOCK_SIZE %d".format(
......@@ -148,15 +147,15 @@ class LargeObjectSpace(val heap: SimpleImmixHeap,
}
private def markBlock(blockAddr: Word) {
MemorySupport.storeLong(blockAddr + OFFSET_MARK, MARK_BIT)
memorySupport.storeLong(blockAddr + OFFSET_MARK, MARK_BIT)
}
private def unmarkBlock(blockAddr: Word) {
MemorySupport.storeLong(blockAddr + OFFSET_MARK, 0)
memorySupport.storeLong(blockAddr + OFFSET_MARK, 0)
}
private def getBlockMark(blockAddr: Word): Word = {
MemorySupport.loadLong(blockAddr + OFFSET_MARK)
memorySupport.loadLong(blockAddr + OFFSET_MARK)
}
private def link(blockAddr: Word) {
......@@ -186,18 +185,18 @@ class LargeObjectSpace(val heap: SimpleImmixHeap,
}
private def getPrev(blockAddr: Word): Word = {
MemorySupport.loadLong(blockAddr + OFFSET_PREV)
memorySupport.loadLong(blockAddr + OFFSET_PREV)
}
private def getNext(blockAddr: Word): Word = {
MemorySupport.loadLong(blockAddr + OFFSET_NEXT)
memorySupport.loadLong(blockAddr + OFFSET_NEXT)
}
private def setPrev(blockAddr: Word, toBlock: Word) {
MemorySupport.storeLong(blockAddr + OFFSET_PREV, toBlock)
memorySupport.storeLong(blockAddr + OFFSET_PREV, toBlock)
}
private def setNext(blockAddr: Word, toBlock: Word) {
MemorySupport.storeLong(blockAddr + OFFSET_NEXT, toBlock)
memorySupport.storeLong(blockAddr + OFFSET_NEXT, toBlock)
}
}
......@@ -15,7 +15,8 @@ object AllScanner {
/**
* Traverse through all references in the micro VM.
*/
class AllScanner(val microVM: MicroVM, val handler: RefFieldHandler) extends RefFieldHandler {
class AllScanner(val handler: RefFieldHandler)(
implicit microVM: MicroVM, memorySupport: MemorySupport) extends RefFieldHandler {
import AllScanner._
private val addrQueue = new ArrayDeque[Word]()
......@@ -89,7 +90,7 @@ class AllScanner(val microVM: MicroVM, val handler: RefFieldHandler) extends Ref
allEmpty = false
val objRef = addrQueue.pollFirst()
logger.debug("Scanning heap object 0x%x...".format(objRef))
MemoryDataScanner.scanAllocUnit(objRef, objRef, microVM, this)
MemoryDataScanner.scanAllocUnit(objRef, objRef, this)
}
}
}
......
......@@ -17,33 +17,33 @@ object MemoryDataScanner extends StrictLogging {
* Scan an allocation unit. In this implementation, heap objects, alloca cells and global
* cells all have the same layout.
*/
def scanAllocUnit(objRef: Word, iRef: Word, microVM: MicroVM, handler: RefFieldHandler) {
def scanAllocUnit(objRef: Word, iRef: Word, handler: RefFieldHandler)(implicit microVM: MicroVM, memorySupport: MemorySupport) {
val tag = HeaderUtils.getTag(objRef)
logger.debug("Obj 0x%x, tag 0x%x".format(objRef, tag))
val ty = HeaderUtils.getType(microVM, tag)
logger.debug("Type: %s".format(ty.repr))
scanField(ty, objRef, objRef, microVM, handler)
scanField(ty, objRef, objRef, handler)
}
def scanField(ty: Type, objRef: Word, iRef: Word, microVM: MicroVM, handler: RefFieldHandler) {
def scanField(ty: Type, objRef: Word, iRef: Word, handler: RefFieldHandler)(implicit microVM: MicroVM, memorySupport: MemorySupport) {
ty match {
case t: TypeRef => {
val toObj = MemorySupport.loadLong(iRef)
val toObj = memorySupport.loadLong(iRef)
logger.debug(s"Ref field ${iRef} -> ${toObj}")
handler.memToHeap(objRef, iRef, toObj, false, false)
}
case t: TypeIRef => {
val toObj = MemorySupport.loadLong(iRef)
val toObj = memorySupport.loadLong(iRef)
logger.debug(s"IRef field ${iRef} -> ${toObj}")
handler.memToHeap(objRef, iRef, toObj, false, false)
}
case t: TypeWeakRef => {
val toObj = MemorySupport.loadLong(iRef)
val toObj = memorySupport.loadLong(iRef)
logger.debug(s"WeakRef field ${iRef} -> ${toObj}")
handler.memToHeap(objRef, iRef, toObj, true, false)
}
case t: TypeTagRef64 => {
val bits = MemorySupport.loadLong(iRef)
val bits = memorySupport.loadLong(iRef)
if (paranoiaLogger.underlying.isDebugEnabled()) {