Commit 217ca466 authored by Kunshan Wang's avatar Kunshan Wang

Fixed a bug in object scanner. Partially implementing WATCHPOINT.

When an object is moved, the new address should be enqueued, not the old
address.
parent 64867984
...@@ -437,6 +437,14 @@ class ClientAgent(microVM: MicroVM) { ...@@ -437,6 +437,14 @@ class ClientAgent(microVM: MicroVM) {
val box = new BoxTagRef64(OpHelper.refToTr64(refv, tagv.longValue)) val box = new BoxTagRef64(OpHelper.refToTr64(refv, tagv.longValue))
newHandle(InternalTypes.TAGREF64, box) newHandle(InternalTypes.TAGREF64, box)
} }
def enableWatchPoint(wpID: Int): Unit = {
microVM.trapManager.enableWatchPoint(wpID)
}
def disableWatchPoint(wpID: Int): Unit = {
microVM.trapManager.disableWatchPoint(wpID)
}
// Internal methods for µVM // Internal methods for µVM
......
...@@ -577,7 +577,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -577,7 +577,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
val uty = InternalTypePool.unmarkedOf(referentTy) val uty = InternalTypePool.unmarkedOf(referentTy)
val lb = boxOf(loc).asInstanceOf[BoxIRef] val lb = boxOf(loc).asInstanceOf[BoxIRef]
val ib = boxOf(i) val ib = boxOf(i)
val la = lb.objRef + lb.offset val la = lb.objRef + lb.offset
if (la == 0L) { if (la == 0L) {
nullRefError(excClause) nullRefError(excClause)
...@@ -586,7 +586,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -586,7 +586,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
continueNormally() continueNormally()
} }
} }
case i @ InstStore(ord, referentTy, loc, newVal, excClause) => { case i @ InstStore(ord, referentTy, loc, newVal, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy) val uty = InternalTypePool.unmarkedOf(referentTy)
val lb = boxOf(loc).asInstanceOf[BoxIRef] val lb = boxOf(loc).asInstanceOf[BoxIRef]
...@@ -601,7 +601,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -601,7 +601,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
continueNormally() continueNormally()
} }
} }
case i @ InstCmpXchg(weak, ordSucc, ordFail, referentTy, loc, expected, desired, excClause) => { case i @ InstCmpXchg(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 lb = boxOf(loc).asInstanceOf[BoxIRef]
...@@ -617,7 +617,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -617,7 +617,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
continueNormally() continueNormally()
} }
} }
case i @ InstAtomicRMW(ord, op, referentTy, loc, opnd, excClause) => { case i @ InstAtomicRMW(ord, op, referentTy, loc, opnd, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy) val uty = InternalTypePool.unmarkedOf(referentTy)
val lb = boxOf(loc).asInstanceOf[BoxIRef] val lb = boxOf(loc).asInstanceOf[BoxIRef]
...@@ -632,14 +632,12 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -632,14 +632,12 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
continueNormally() continueNormally()
} }
} }
case i @ InstFence(ord) => { case i @ InstFence(ord) => {
// No-op in this interpreter // No-op in this interpreter
continueNormally() continueNormally()
} }
// Indentation guide: Insert more instructions here.
case i @ InstTrap(retTy, excClause, keepAlives) => { case i @ InstTrap(retTy, excClause, keepAlives) => {
val ca = microVM.newClientAgent() val ca = microVM.newClientAgent()
...@@ -668,6 +666,39 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -668,6 +666,39 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
ca.close() ca.close()
} }
case i @ InstWatchPoint(wpID, retTy, dis, ena, exc, keepAlives) => {
val isEnabled = microVM.trapManager.isWatchPointEnabled(wpID)
if (isEnabled) {
val ca = microVM.newClientAgent()
val hThread = ca.putThread(Some(this))
val hStack = ca.putStack(Some(curStack))
unbind(retTy)
val res = microVM.trapManager.trapHandler.handleTrap(ca, hThread, hStack, wpID)
res match {
case TrapExit() => {
isRunning = false
}
case TrapRebindPassValue(newStack, value) => {
rebindPassValue(newStack.vb.asInstanceOf[BoxStack].stack, value.vb)
}
case TrapRebindPassVoid(newStack) => {
rebindPassVoid(newStack.vb.asInstanceOf[BoxStack].stack)
}
case TrapRebindThrowExc(newStack, exc) => {
rebindThrowExc(newStack.vb.asInstanceOf[BoxStack].stack, exc.vb)
}
}
ca.close()
} else {
branchAndMovePC(dis)
}
}
// Indentation guide: Insert more instructions (after TRAP) here. // Indentation guide: Insert more instructions (after TRAP) here.
case i @ InstCommInst(ci, typeList, argList, excClause, keepAlives) => { case i @ InstCommInst(ci, typeList, argList, excClause, keepAlives) => {
...@@ -726,7 +757,11 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -726,7 +757,11 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
def continueNormally(): Unit = { def continueNormally(): Unit = {
curInst match { curInst match {
case wp: InstWatchPoint => { case wp: InstWatchPoint => {
throw new UvmRefImplException("Not Implemented") branchAndMovePC(wp.ena)
// NOTE: WatchPoint only "continue normally" when the current stack is rebound with value or void.
// This includes executing a watch point. In any case, this watch point must have been enabled. If the watch
// point is disabled during the course the stack is unbound, this watch point should still continue from the
// destination determined WHEN THIS INSTRUCTION IS EXECUTED.
} }
case h: HasExcClause => h.excClause match { case h: HasExcClause => h.excClause match {
case None => incPC() case None => incPC()
...@@ -797,6 +832,10 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -797,6 +832,10 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
val f = s.top val f = s.top
val (newFrame, newBB) = unwindUntilCatchable(f) val (newFrame, newBB) = unwindUntilCatchable(f)
s.top = newFrame s.top = newFrame
if (exc != 0L) {
logger.debug("Catching exception %d".format(exc))
}
branchAndMovePC(newBB, exc) branchAndMovePC(newBB, exc)
} }
......
...@@ -8,13 +8,15 @@ import scala.collection.mutable.ArrayBuffer ...@@ -8,13 +8,15 @@ import scala.collection.mutable.ArrayBuffer
class ThreadStackManager(microVM: MicroVM) { class ThreadStackManager(microVM: MicroVM) {
val stackRegistry = new HashMap[Int, InterpreterStack]() private val stackRegistry = new HashMap[Int, InterpreterStack]()
val threadRegistry = new HashMap[Int, InterpreterThread]() private val threadRegistry = new HashMap[Int, InterpreterThread]()
def getStackByID(id: Int): Option[InterpreterStack] = stackRegistry.get(id) def getStackByID(id: Int): Option[InterpreterStack] = stackRegistry.get(id)
def getThreadByID(id: Int): Option[InterpreterThread] = threadRegistry.get(id) def getThreadByID(id: Int): Option[InterpreterThread] = threadRegistry.get(id)
def iterateAllLiveStacks: Iterable[InterpreterStack] = stackRegistry.values.filter(_.state != StackState.Dead)
private var nextStackID: Int = 1 private var nextStackID: Int = 1
......
package uvm.refimpl.itpr package uvm.refimpl.itpr
import uvm.refimpl._ import uvm.refimpl._
import scala.collection.mutable.HashSet
class TrapManager(microVM: MicroVM) { class TrapManager(microVM: MicroVM) {
var trapHandler: TrapHandler = DefaultTrapHandler var trapHandler: TrapHandler = DefaultTrapHandler
var undefinedFunctionHandler: UndefinedFunctionHandler = DefaultUndefinedFunctionHandler var undefinedFunctionHandler: UndefinedFunctionHandler = DefaultUndefinedFunctionHandler
private val enabledWatchPoints = new HashSet[Int]()
def isWatchPointEnabled(wpID: Int): Boolean = enabledWatchPoints.contains(wpID)
def enableWatchPoint(wpID: Int): Unit = enabledWatchPoints.add(wpID)
def disableWatchPoint(wpID: Int): Unit = enabledWatchPoints.remove(wpID)
object DefaultTrapHandler extends TrapHandler { object DefaultTrapHandler extends TrapHandler {
def handleTrap(ca: ClientAgent, thread: Handle, stack: Handle, watchPointID: Int): TrapHandlerResult = { def handleTrap(ca: ClientAgent, thread: Handle, stack: Handle, watchPointID: Int): TrapHandlerResult = {
val thr = thread.vb.asInstanceOf[BoxThread].thread.get val thr = thread.vb.asInstanceOf[BoxThread].thread.get
......
...@@ -7,7 +7,7 @@ object MemUtils extends StrictLogging { ...@@ -7,7 +7,7 @@ object MemUtils extends StrictLogging {
def zeroRegion(start: Word, length: Word) { def zeroRegion(start: Word, length: Word) {
val end = start + length val end = start + length
logger.debug(s"Zeroing [${start} -> ${end}] ${length} bytes") 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, 0)
...@@ -16,7 +16,7 @@ object MemUtils extends StrictLogging { ...@@ -16,7 +16,7 @@ object MemUtils extends StrictLogging {
} }
def memcpy(src: Word, dst: Word, length: Word) { def memcpy(src: Word, dst: Word, length: Word) {
logger.debug("Copying [${src} -> ${dst}] ${length} bytes") 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)
......
...@@ -57,6 +57,10 @@ object TypeSizes { ...@@ -57,6 +57,10 @@ object TypeSizes {
val GC_HEADER_OFFSET_TAG: Word = -8L; val GC_HEADER_OFFSET_TAG: Word = -8L;
val GC_HEADER_OFFSET_HYBRID_LENGTH: Word = -16L; val GC_HEADER_OFFSET_HYBRID_LENGTH: Word = -16L;
val MARK_MASK = 0x4000000000000000L
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
......
...@@ -48,8 +48,7 @@ class AllScanner(val microVM: MicroVM, val handler: RefFieldHandler) extends Ref ...@@ -48,8 +48,7 @@ class AllScanner(val microVM: MicroVM, val handler: RefFieldHandler) extends Ref
} }
private def traceStacks() { private def traceStacks() {
val sr = microVM.threadStackManager.stackRegistry for (sta <- microVM.threadStackManager.iterateAllLiveStacks) {
for (sta <- sr.values if sta.state != StackState.Dead) {
logger.debug(s"Tracing stack ${sta.id} for registers...") logger.debug(s"Tracing stack ${sta.id} for registers...")
for (fra <- sta.frames; vb <- fra.boxes.values if vb.isInstanceOf[HasObjRef]) { for (fra <- sta.frames; vb <- fra.boxes.values if vb.isInstanceOf[HasObjRef]) {
...@@ -70,32 +69,27 @@ class AllScanner(val microVM: MicroVM, val handler: RefFieldHandler) extends Ref ...@@ -70,32 +69,27 @@ class AllScanner(val microVM: MicroVM, val handler: RefFieldHandler) extends Ref
private def doTransitiveClosure() { private def doTransitiveClosure() {
while (!queue.isEmpty) { while (!queue.isEmpty) {
val objRef = queue.pollFirst() val objRef = queue.pollFirst()
logger.debug("Scanning heap object 0x%x...".format(objRef))
MemoryDataScanner.scanAllocUnit(objRef, objRef, microVM, this) MemoryDataScanner.scanAllocUnit(objRef, objRef, microVM, this)
} }
} }
override def fromBox(box: HasObjRef): Boolean = { override def fromBox(box: HasObjRef): Option[Word] = {
val toEnqueue = handler.fromBox(box) val rv = handler.fromBox(box)
if (toEnqueue) { rv.foreach(queue.add)
queue.add(box.getObjRef()) rv
}
toEnqueue
} }
override def fromMem(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Boolean = { override def fromMem(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Option[Word] = {
val toEnqueue = handler.fromMem(objRef, iRef, toObj, isWeak, isTR64) val rv = handler.fromMem(objRef, iRef, toObj, isWeak, isTR64)
if (toEnqueue) { rv.foreach(queue.add)
queue.add(toObj) rv
}
toEnqueue
} }
override def fromInternal(toObj: Word): Boolean = { override def fromInternal(toObj: Word): Option[Word] = {
val toEnqueue = handler.fromInternal(toObj) val rv = handler.fromInternal(toObj)
if (toEnqueue) { rv.foreach(queue.add)
queue.add(toObj) rv
}
toEnqueue
} }
} }
\ No newline at end of file
...@@ -19,6 +19,7 @@ object MemoryDataScanner extends StrictLogging { ...@@ -19,6 +19,7 @@ object MemoryDataScanner extends StrictLogging {
*/ */
def scanAllocUnit(objRef: Word, iRef: Word, microVM: MicroVM, handler: RefFieldHandler) { def scanAllocUnit(objRef: Word, iRef: Word, microVM: MicroVM, handler: RefFieldHandler) {
val tag = HeaderUtils.getTag(objRef) val tag = HeaderUtils.getTag(objRef)
logger.debug("Obj 0x%x, tag 0x%x".format(objRef, tag))
val ty = HeaderUtils.getType(microVM, tag) val ty = HeaderUtils.getType(microVM, tag)
scanField(ty, objRef, objRef, handler) scanField(ty, objRef, objRef, handler)
} }
......
...@@ -8,22 +8,23 @@ import uvm.refimpl.itpr.OpHelper ...@@ -8,22 +8,23 @@ import uvm.refimpl.itpr.OpHelper
/** /**
* Handle reference fields or references in boxes. * Handle reference fields or references in boxes.
* <p> * <p>
* Both fromBox and fromMem method return true if and only if the scanner should follow the reference. * Both fromBox and fromMem method return Some(addr) if addr is to be enqueued by the scanner, or None otherwise. If an
* object is moved when scanning an object, the returned addr must be the new address.
* <p> * <p>
* The caller invokes the methods on all boxes/locations it finds. The Callee checks if the box/location * The caller invokes the methods on all boxes/locations it finds. The Callee checks if the box/location
* actually contain references or non-null references. * actually contain references or non-null references.
*/ */
trait RefFieldHandler { trait RefFieldHandler {
/** Scan a box. */ /** Scan a box. */
def fromBox(box: HasObjRef): Boolean def fromBox(box: HasObjRef): Option[Word]
/** Scan a memory location. */ /** Scan a memory location. */
def fromMem(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Boolean def fromMem(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Option[Word]
/** /**
* A reference from somewhere internal to the µVM. * A reference from somewhere internal to the µVM.
* For example, from the StackMemory to the memory byte array; * For example, from the StackMemory to the memory byte array;
* from a finaliser table to a finalisable object (to be added). * from a finaliser table to a finalisable object (to be added).
*/ */
def fromInternal(toObj: Word): Boolean def fromInternal(toObj: Word): Option[Word]
} }
object RefFieldUpdater { object RefFieldUpdater {
......
...@@ -5,7 +5,7 @@ import uvm.refimpl.itpr._ ...@@ -5,7 +5,7 @@ import uvm.refimpl.itpr._
import uvm.refimpl.mem._ import uvm.refimpl.mem._
import uvm.refimpl.mem.los.LargeObjectSpace import uvm.refimpl.mem.los.LargeObjectSpace
import uvm.refimpl.mem.scanning._ import uvm.refimpl.mem.scanning._
import TypeSizes.Word import TypeSizes._
import uvm.types._ import uvm.types._
import SimpleImmixCollector._ import SimpleImmixCollector._
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
...@@ -15,10 +15,6 @@ import uvm.refimpl.UvmRefImplException ...@@ -15,10 +15,6 @@ import uvm.refimpl.UvmRefImplException
object SimpleImmixCollector { object SimpleImmixCollector {
val logger = Logger(LoggerFactory.getLogger(getClass.getName)) val logger = Logger(LoggerFactory.getLogger(getClass.getName))
private val MARK_MASK = 0x4000000000000000L
private val MOVE_MASK = 0x8000000000000000L
} }
class SimpleImmixCollector(val heap: SimpleImmixHeap, class SimpleImmixCollector(val heap: SimpleImmixHeap,
...@@ -52,30 +48,43 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, ...@@ -52,30 +48,43 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap,
logger.debug("Marking and getting statistics....") logger.debug("Marking and getting statistics....")
val s1 = new AllScanner(microVM, new RefFieldHandler() { val s1 = new AllScanner(microVM, new RefFieldHandler() {
override def fromBox(box: HasObjRef): Boolean = box match { override def fromBox(box: HasObjRef): Option[Word] = box match {
case HasNonZeroRef(toObj) => maybeMarkAndStat(toObj) case HasNonZeroRef(toObj) => maybeMarkAndStat(toObj)
case _ => false case _ => None
} }
override def fromMem(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Boolean = { override def fromMem(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Option[Word] = {
if (toObj != 0L) { if (toObj != 0L) {
if (isWeak) { if (isWeak) {
logger.debug(s"Enqueued weak reference ${iRef} to ${toObj}") logger.debug(s"Enqueued weak reference ${iRef} to ${toObj}")
weakRefs.append(iRef) weakRefs.append(iRef)
false None
} else { } else {
maybeMarkAndStat(toObj) maybeMarkAndStat(toObj)
} }
} else { } else {
false None
} }
} }
override def fromInternal(toObj: Word): Boolean = if (toObj != 0L) maybeMarkAndStat(toObj) else false override def fromInternal(toObj: Word): Option[Word] = if (toObj != 0L) maybeMarkAndStat(toObj) else None
}) })
s1.scanAll() s1.scanAll()
logger.debug("Visit and clear weak references...")
for (iRefWR <- weakRefs) {
val toObj = MemorySupport.loadLong(iRefWR)
val tag = HeaderUtils.getTag(toObj)
val isMarked = (tag & MARK_MASK) != 0
if (!isMarked) {
logger.debug("WeakRef %d whose value was %d is zeroed.".format(iRefWR, toObj))
MemorySupport.storeLong(iRefWR, 0)
} else {
logger.debug("WeakRef %d whose value was %d is still marked. Do not zero.".format(iRefWR, toObj))
}
}
logger.debug("Stat finished. Unmarking....") logger.debug("Stat finished. Unmarking....")
val s2 = new AllScanner(microVM, clearMarkHandler) val s2 = new AllScanner(microVM, clearMarkHandler)
s2.scanAll() s2.scanAll()
...@@ -92,19 +101,6 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, ...@@ -92,19 +101,6 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap,
defragMutator.close() defragMutator.close()
logger.debug("Visit and clear weak references...")
for (iRefWR <- weakRefs) {
val toObj = MemorySupport.loadLong(iRefWR)
val tag = HeaderUtils.getTag(toObj)
val isMarked = (tag & MARK_MASK) != 0
if (!isMarked) {
logger.debug("WeakRef %d whose value was %d is zeroed.".format(iRefWR, toObj))
MemorySupport.storeLong(iRefWR, 0)
} else {
logger.debug("WeakRef %d whose value was %d is still marked. Do not zero.".format(iRefWR, toObj))
}
}
logger.debug("Marked. Collecting blocks....") logger.debug("Marked. Collecting blocks....")
val anyMemoryRecycled = collectBlocks() val anyMemoryRecycled = collectBlocks()
if (!anyMemoryRecycled && heap.getMustFreeSpace) { if (!anyMemoryRecycled && heap.getMustFreeSpace) {
...@@ -119,7 +115,7 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, ...@@ -119,7 +115,7 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap,
heap.untriggerGC() heap.untriggerGC()
} }
private def maybeMarkAndStat(addr: Word): Boolean = { private def maybeMarkAndStat(addr: Word): Option[Word] = {
assert(addr != 0L, "addr should be non-zero before calling this function") assert(addr != 0L, "addr should be non-zero before calling this function")
val oldHeader = HeaderUtils.getTag(addr) val oldHeader = HeaderUtils.getTag(addr)
logger.debug("GC header of 0x%x is 0x%x".format(addr, oldHeader)) logger.debug("GC header of 0x%x is 0x%x".format(addr, oldHeader))
...@@ -148,36 +144,32 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, ...@@ -148,36 +144,32 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap,
} else { } else {
throw new UvmRefImplException("Object ref %d not in any space".format(addr)) throw new UvmRefImplException("Object ref %d not in any space".format(addr))
} }
true Some(addr)
} else { } else {
false None
} }
} }
private val markMover = new RefFieldHandler { private val markMover = new RefFieldHandler {
override def fromBox(box: HasObjRef): Boolean = box match { override def fromBox(box: HasObjRef): Option[Word] = box match {
case HasNonZeroRef(toObj) => maybeMove(toObj, newObjRef => RefFieldUpdater.updateBox(box, newObjRef)) case HasNonZeroRef(toObj) => maybeMove(toObj, newObjRef => RefFieldUpdater.updateBox(box, newObjRef))
case _ => false case _ => None
} }
override def fromMem(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Boolean = { override def fromMem(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Option[Word] = {
if (toObj != 0L) { if (toObj != 0L) {
if (isWeak) { maybeMove(toObj, newObjRef => RefFieldUpdater.updateMemory(iRef, isTR64, newObjRef))
throw new UvmRefImplException("BUG: Weak references should have been cleared now.")
} else {
maybeMove(toObj, newObjRef => RefFieldUpdater.updateMemory(iRef, isTR64, newObjRef))
}
} else { } else {
false None
} }
} }
// Currently internally referenced objects (only the byte array for stacks) cannot move and does not transitively // Currently internally referenced objects (only the byte array for stacks) cannot move and does not transitively
// refer to other objects. // refer to other objects.
override def fromInternal(toObj: Word): Boolean = false override def fromInternal(toObj: Word): Option[Word] = None
private def maybeMove(toObj: Word, updateFunc: Word => Unit): Boolean = { private def maybeMove(toObj: Word, updateFunc: Word => Unit): Option[Word] = {
val oldHeader = HeaderUtils.getTag(toObj) val oldHeader = HeaderUtils.getTag(toObj)
logger.debug("GC header of 0x%x is 0x%x".format(toObj, oldHeader)) logger.debug("GC header of 0x%x is 0x%x".format(toObj, oldHeader))
val markBit = oldHeader & MARK_MASK val markBit = oldHeader & MARK_MASK
...@@ -187,10 +179,10 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, ...@@ -187,10 +179,10 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap,
if (wasMoved) { if (wasMoved) {
val dest = HeaderUtils.getForwardedDest(oldHeader) val dest = HeaderUtils.getForwardedDest(oldHeader)
updateFunc(dest) updateFunc(dest)
false None
} else { } else {
if (wasMarked) { if (wasMarked) {
false None
} else { } else {
val isInSmallObjectSpace = space.isInSpace(toObj) val isInSmallObjectSpace = space.isInSpace(toObj)
...@@ -223,7 +215,7 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, ...@@ -223,7 +215,7 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap,
} else { } else {
throw new UvmRefImplException("Object ref %x not in any space".format(actualObj)) throw new UvmRefImplException("Object ref %x not in any space".format(actualObj))
} }
true Some(actualObj)
} }
} }
} }
...@@ -281,28 +273,28 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, ...@@ -281,28 +273,28 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap,
} }
private val clearMarkHandler = new RefFieldHandler() { private val clearMarkHandler = new RefFieldHandler() {
override def fromBox(box: HasObjRef): Boolean = box match { override def fromBox(box: HasObjRef): Option[Word] = box match {
case HasNonZeroRef(toObj) => clearMark(toObj) case HasNonZeroRef(toObj) => clearMark(toObj)
case _ => false case _ => None
} }
override def fromMem(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Boolean = { override def fromMem(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Option[Word] = {
if (toObj != 0L) clearMark(toObj) else false if (toObj != 0L) clearMark(toObj) else None
} }
override def fromInternal(toObj: Word): Boolean = if (toObj != 0L) clearMark(toObj) else false override def fromInternal(toObj: Word): Option[Word] = if (toObj != 0L) clearMark(toObj) else None
} }
private def clearMark(objRef: Long): Boolean = { private def clearMark(objRef: Long): Option[Word] = {
val oldHeader = HeaderUtils.getTag(objRef) val oldHeader = HeaderUtils.getTag(objRef)
logger.debug("GC header of 0x%x is 0x%x".format(objRef, oldHeader)) logger.debug("GC header of 0x%x is 0x%x".format(objRef, oldHeader))
val markBit = oldHeader & MARK_MASK val markBit = oldHeader & MARK_MASK