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}")