package uvm.refimpl.mem.scanning import org.slf4j.LoggerFactory import com.typesafe.scalalogging.Logger import uvm.Function import uvm.ir.irbuilder.IRBuilder import uvm.refimpl.Word import uvm.refimpl.itpr.BoxStack import uvm.refimpl.itpr.FrameCursor import uvm.refimpl.itpr.HasObjRef import uvm.refimpl.itpr.InterpreterStack import uvm.refimpl.itpr.InterpreterThread import uvm.refimpl.itpr.OpHelper import uvm.refimpl.mem.MemorySupport /** * Handle general reference fields in the memory. This trait is mostly useful for the boot image builder. *

* As a convention, the parameter name "objRef" means the "beginning of an allocation unit", not limited to heap * object; "iRef" is the address of the field itself. */ trait MemoryFieldHandler { def visitUPtrField(objRef: Word, iRef: Word, toAddr: Word): Unit def visitUFPField(objRef: Word, iRef: Word, toAddr: Word): Unit def visitRefField(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean): Unit def visitIRefField(objRef: Word, iRef: Word, toObj: Word, toOffset: Word): Unit /** This function is called only when the tagref is holding a reference. */ def visitTagRefField(objRef: Word, iRef: Word, toObj: Word): Unit def visitFuncRefField(objRef: Word, iRef: Word, toFunc: Option[Function]): Unit def visitStackRefField(objRef: Word, iRef: Word, toStack: Option[InterpreterStack]): Unit def visitThreadRefField(objRef: Word, iRef: Word, toThread: Option[InterpreterThread]): Unit def visitFCRefField(objRef: Word, iRef: Word, toFCRef: Option[FrameCursor]): Unit def visitIRBuilderRefField(objRef: Word, iRef: Word, toIRNode: Option[IRBuilder]): Unit } /** * Handle references in the memory, value boxes or other Micro VM structures such as threads and stacks. *

*

* The return value of the methods will be queued for recursive traversing. They should be the old value, * the updated value by the copying GC, or None if the reference should not be followed. */ trait RefFieldHandler extends MemoryFieldHandler { /** A stack value box referring to a heap object. */ def boxToHeap(box: HasObjRef): Option[Word] /** A stack value box referring to a "stack"-typed value. */ def boxToStack(box: BoxStack): Option[InterpreterStack] /** A memory location referring to a heap object. */ def memToHeap(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Option[Word] /** A memory location referring to a heap object. Return the new stack ID or 0. */ def memToStack(objRef: Word, iRef: Word, toStack: Option[InterpreterStack]): Option[InterpreterStack] /** An InterpreterStack object referring to its stackMemory field. Stack memory cannot move. */ def stackToStackMem(stack: InterpreterStack, toObj: Word): Option[Word] /** An InterpreterThread referring to its stack. GC cannot rebind stacks. */ def threadToStack(thread: InterpreterThread, toStack: Option[InterpreterStack]): Option[InterpreterStack] /** Pin set referring to the memory. Pinned objects cannot be moved. */ def pinSetToMem(toObj: Word): Option[Word] def visitRefField(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean): Unit = { memToHeap(objRef, iRef, toObj, isWeak, false) } def visitIRefField(objRef: Word, iRef: Word, toObj: Word, toOffset: Word): Unit = { memToHeap(objRef, iRef, toObj, false, false) } /** This function is called only when the tagref is holding a reference. */ def visitTagRefField(objRef: Word, iRef: Word, toObj: Word): Unit = { memToHeap(objRef, iRef, toObj, false, true) } def visitStackRefField(objRef: Word, iRef: Word, toStack: Option[InterpreterStack]): Unit = { memToStack(objRef, iRef, toStack) } def visitUPtrField(objRef: Word, iRef: Word, toAddr: Word): Unit = {} def visitUFPField(objRef: Word, iRef: Word, toAddr: Word): Unit = {} def visitFuncRefField(objRef: Word, iRef: Word, toFunc: Option[Function]): Unit = {} def visitThreadRefField(objRef: Word, iRef: Word, toThread: Option[InterpreterThread]): Unit = {} def visitFCRefField(objRef: Word, iRef: Word, toFCRef: Option[FrameCursor]): Unit = {} def visitIRBuilderRefField(objRef: Word, iRef: Word, toIRNode: Option[IRBuilder]): Unit = {} } object RefFieldUpdater { val logger = Logger(LoggerFactory.getLogger(getClass.getName)) def updateBoxToHeap(box: HasObjRef, newObjRef: Word): Unit = box.setObjRef(newObjRef) def updateBoxToStack(box: BoxStack, newStack: Option[InterpreterStack]) = box.obj = newStack def updateMemToHeap(iRef: Word, isTR64: Boolean, newObjRef: Word)(implicit memorySupport: MemorySupport): Unit = { if (isTR64) { val oldRaw = memorySupport.loadLong(iRef) val oldTag = OpHelper.tr64ToTag(oldRaw) val newRaw = OpHelper.refToTr64(newObjRef, oldTag) logger.debug { val oldObjRef = OpHelper.tr64ToRef(oldRaw) "Updating tagref field [0x%x] = 0x%x -> 0x%x; ref: 0x%x -> 0x%x".format( iRef, oldRaw, newRaw, oldObjRef, newObjRef) } memorySupport.storeLong(iRef, newRaw) } else { logger.debug { val oldObjRef = memorySupport.loadLong(iRef) "Updating ref field [0x%x] = 0x%x -> 0x%x".format(iRef, oldObjRef, newObjRef) } memorySupport.storeLong(iRef, newObjRef) } } def updateMemToStack(iRef: Word, newStack: Option[InterpreterStack])(implicit memorySupport: MemorySupport): Unit = { memorySupport.storeLong(iRef, newStack.map(_.id).getOrElse(0).toLong) } }