WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

Commit 63af3f1e authored by Kunshan Wang's avatar Kunshan Wang
Browse files

Reworked memory scanner to support bootimg

parent 1958f150
......@@ -6,23 +6,29 @@ import java.nio.charset.StandardCharsets
import java.nio.file._
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.HashMap
import org.slf4j.LoggerFactory
import com.typesafe.scalalogging.Logger
import uvm._
import uvm.ir.irbuilder.IRNode
import uvm.ir.textoutput.BundleSerializer
import uvm.ir.textoutput.EntityUtils
import uvm.refimpl._
import uvm.refimpl.itpr.FrameCursor
import uvm.refimpl.itpr.InterpreterStack
import uvm.refimpl.itpr.InterpreterThread
import uvm.refimpl.mem.HeaderUtils
import uvm.refimpl.mem.Space
import uvm.refimpl.mem.TypeSizes
import uvm.refimpl.mem.scanning.MemoryDataScanner
import uvm.refimpl.mem.scanning.MemoryFieldHandler
import uvm.refimpl.nat.NativeSupport
import uvm.refimpl.nat.PlatformConstants.Word
import uvm.types._
import uvm.utils.WithUtils.tryWithResource
import uvm.ir.textoutput.EntityUtils
import uvm.ir.textoutput.BundleSerializer
import scala.collection.mutable.HashMap
class BootImageBuilder(implicit microVM: MicroVM) {
def makeBootImage(whiteList: Seq[TopLevel], outputFile: String): Unit = {
......@@ -175,12 +181,27 @@ class BootImageWriter(tcb: TransitiveClosureBuilder, outputFile: String)(implici
private def scanForRelocs(group: FileGroup): Unit = {
for (alloc <- group.allocRecs) {
???
val num = alloc.num
val begin = alloc.addr
MemoryDataScanner.scanAllocUnit(begin, new MemoryFieldHandler {
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 visitIRNodeRefField(objRef: Word, iRef: Word, toIRNode: Option[IRNode]): Unit = {}
})
}
}
private def writeRelocRecs(group: FileGroup): Unit = {
???
//???
}
private def writeIDNameMap(): Unit = {
......
......@@ -15,9 +15,10 @@ import uvm.refimpl.mem.Space
import uvm.refimpl.mem.TypeSizes
import uvm.refimpl.mem.TypeSizes.Word
import uvm.refimpl.mem.scanning.MemoryDataScanner
import uvm.refimpl.mem.scanning.RefFieldHandler
import uvm.ssavariables._
import uvm.types._
import uvm.refimpl.mem.scanning.MemoryFieldHandler
import uvm.ir.irbuilder.IRNode
object TransitiveClosure {
def apply[T](initialElems: T*) = new TransitiveClosure(initialElems)
......@@ -63,7 +64,7 @@ object TransitiveClosureBuilder {
case class GlobalCellRec(begin: Word, end: Word, g: GlobalCell)
}
class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: MicroVM) extends RefFieldHandler {
class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: MicroVM) extends MemoryFieldHandler {
import TransitiveClosureBuilder._
private val globalMemory: Space = microVM.memoryManager.globalMemory
......@@ -291,48 +292,55 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel])(implicit microVM: Micr
MemoryDataScanner.scanAllocUnit(begin, this)
}
def boxToHeap(box: HasObjRef): Option[Word] =
throw new BootImageBuilderException("BUG: Box should not have been scanned during boot image building.")
def boxToStack(box: BoxStack): Option[InterpreterStack] =
throw new BootImageBuilderException("BUG: Box should not have been scanned during boot image building.")
def memToHeap(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean, isTR64: Boolean): Option[Word] = {
override def visitRefField(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean): Unit = {
if (toObj != 0L) {
allocs += toObj
Some(toObj)
} else {
None
}
}
override def memToNonHeap(objRef: Word, iRef: Word, addr: Word): Unit = {
require(globalMemory.isInSpace(addr), {
val inLOS = largeObjectSpace.isInSpace(addr)
("Error: Non-heap internal reference not referring to global space. objRef: 0x%x, iref: 0x%x, target: 0x%x, inLOS: %s. " +
"If the address is in the large object space, it may refer to a stack cell (ALLOCA)").format(
objRef, iRef, addr, inLOS)
})
val gr = getGlobalCellRec(addr)
override def visitIRefField(objRef: Word, iRef: Word, toObj: Word, toOffset: Word): Unit = {
if (toObj == 0L) {
if (globalMemory.isInSpace(toOffset)) {
val gr = getGlobalCellRec(toOffset)
tls += gr.g
} else {
if (largeObjectSpace.isInSpace(toOffset)) {
throw new BootImageBuilderException(("Error: non-object iref to LOS found. This is probably a reference to " +
"a stack cell (ALLOCA). It should not exist during boot image building. source: [0x%x + 0x%x] -> dest 0x%x").format(
objRef, iRef, toOffset))
} else {
throw new BootImageBuilderException(("Error: non-object iref not referring to global. source: [0x%x + 0x%x] -> dest 0x%x").format(
objRef, iRef, toOffset))
}
}
} else {
if (toObj != 0L) {
allocs += toObj
}
}
}
def memToStack(objRef: Word, iRef: Word, toStack: Option[InterpreterStack]): Option[InterpreterStack] = {
if (toStack.isDefined) {
throw new BootImageBuilderException(
"Error: Stack reachable during boot image building. From: obj 0x%x, iref 0x%x. To stack id: %d".format(
objRef, iRef, toStack.get.id))
override def visitTagRefField(objRef: Word, iRef: Word, toObj: Word): Unit = {
if (toObj != 0L) {
allocs += toObj
}
None
}
def stackToStackMem(stack: InterpreterStack, toObj: Word): Option[Word] =
throw new BootImageBuilderException("BUG: Stack should not have been scanned during boot image building.")
override def visitFuncRefField(objRef: Word, iRef: Word, toFunc: Option[Function]): Unit = {
toFunc.foreach(tls+=)
}
def threadToStack(thread: InterpreterThread, toStack: Option[InterpreterStack]): Option[InterpreterStack] =
throw new BootImageBuilderException("BUG: Thread should not have been scanned during boot image building.")
override def visitStackRefField(objRef: Word, iRef: Word, toStack: Option[InterpreterStack]): Unit =
toStack.foreach(o => throw noReach("stack", objRef, iRef, o))
override def visitThreadRefField(objRef: Word, iRef: Word, toThread: Option[InterpreterThread]): Unit =
toThread.foreach(o => throw noReach("thread", objRef, iRef, o))
override def visitFCRefField(objRef: Word, iRef: Word, toFCRef: Option[FrameCursor]): Unit =
toFCRef.foreach(o => throw noReach("frame cursor", objRef, iRef, o))
override def visitIRNodeRefField(objRef: Word, iRef: Word, toIRNode: Option[IRNode]): Unit =
toIRNode.foreach(o => throw noReach("IR node", objRef, iRef, o))
def pinSetToMem(toObj: Word): Option[Word] =
throw new BootImageBuilderException("BUG: Pin set should not have been scanned during boot image building.")
private def noReach(kind: String, objRef: Word, iRef: Word, obj: AnyRef) =
new BootImageBuilderException(
"Error: Non-null %s field is not allowed in boot image. From: obj 0x%x, iref 0x%x. To stack id: %s".format(
objRef, iRef, obj))
}
\ No newline at end of file
......@@ -35,3 +35,6 @@ class UvmIllegalMemoryAccessException(message: String = null, cause: Throwable =
/** Thrown on syntax errors in HAIL scripts. */
class UvmHailParsingException(message: String = null, cause: Throwable = null) extends UvmRefImplException(message, cause)
/** Thrown if a number does not match any entity when using ObjectKeepers. */
class UvmUnknownIDException(message: String = null, cause: Throwable = null) extends UvmRuntimeException(message, cause)
......@@ -10,6 +10,7 @@ import com.typesafe.scalalogging.Logger
import uvm.refimpl.nat.NativeCallHelper
import uvm.utils.IDFactory
import uvm.refimpl.UvmRuntimeException
import uvm.refimpl.UvmUnknownIDException
/**
* An object with this trait can be uniquely identified within a MicroVM using an Int ID.
......@@ -32,7 +33,12 @@ class IDObjectKeeper[T <: HasID](val kind: String) {
val idFactory = new IDFactory(1)
/** Get an object by its ID. */
def apply(id: Int) = registry.apply(id)
def apply(id: Int) = try {
registry.apply(id)
} catch {
case e: NoSuchElementException => throw new UvmUnknownIDException(
"Attempted to lookup %s object by ID %d, but it is not found".format(kind, id))
}
/** Get an object by its ID, handle non-existing cases. */
def get(id: Int) = registry.get(id)
......
......@@ -665,17 +665,14 @@ object MemoryOperations {
* Load irnoderef value from the memory. Use fake value from microVM.irNodeRegistry
*/
def loadIRNode(loc: Word)(implicit microVM: MicroVM, memorySupport: MemorySupport): Option[IRNode] = {
val irNodeLong = memorySupport.loadLong(loc).toInt
val maybeIRNode = microVM.irNodeRegistry.longToObj(irNodeLong)
maybeIRNode
memorySupport.loadEntity[IRNode](loc)
}
/**
* Store irnoderef value into the memory. Use fake value from microVM.irNodeRegistry
*/
def storeIRNode(loc: Word, maybeIRNode: Option[IRNode])(implicit microVM: MicroVM, memorySupport: MemorySupport): Unit = {
val irNodeLong = microVM.irNodeRegistry.objGetLong(maybeIRNode)
memorySupport.storeLong(loc, irNodeLong)
memorySupport.storeEntity(loc, maybeIRNode)
}
def loadInt32Array(base: Word, len: Word)(implicit memorySupport: MemorySupport): IndexedSeq[Int] = {
......
......@@ -7,11 +7,22 @@ import jnr.ffi.{ Runtime, Memory, Pointer }
import uvm.refimpl.UvmRuntimeException
import uvm.refimpl.UvmIllegalMemoryAccessException
import uvm.refimpl.nat.NativeSupport
import scala.annotation.implicitNotFound
import uvm.refimpl.MicroVM
import uvm.Function
import uvm.refimpl.itpr.InterpreterThread
import uvm.refimpl.itpr.InterpreterStack
import uvm.ir.irbuilder.IRNode
import uvm.refimpl.UvmUnknownIDException
import uvm.refimpl.UvmRefImplException
import uvm.refimpl.itpr.FrameCursor
/**
* Support for native memory access. Backed by JNR-FFI.
*/
class MemorySupport(val muMemorySize: Word) {
import EntityAccessors._
val jnrRuntime = NativeSupport.jnrRuntime
val theMemory = NativeSupport.theMemory
......@@ -130,6 +141,42 @@ class MemorySupport(val muMemorySize: Word) {
return oldVal
}
def loadEntity[T: CanBeIntegerized](addr: Word)(implicit microVM: MicroVM): Option[T] = {
val num = loadLong(addr, inMu = true)
val obj = try {
implicitly[CanBeIntegerized[T]].deIntegerize(num)
} catch {
case e: UvmUnknownIDException =>
throw new UvmRefImplException("Memory location 0x%x referring to non-existing entity %d".format(addr, num), e)
}
obj
}
def storeEntity[T: CanBeIntegerized](addr: Word, obj: Option[T])(implicit microVM: MicroVM): Unit = {
val num = implicitly[CanBeIntegerized[T]].integerize(obj)
storeLong(addr, num, inMu = true)
}
def cmpXchgEntity[T: CanBeIntegerized](addr: Word, expected: Option[T], desired: Option[T])(
implicit microVM: MicroVM): (Boolean, Option[T]) = {
val numExpected = implicitly[CanBeIntegerized[T]].integerize(expected)
val numDesired = implicitly[CanBeIntegerized[T]].integerize(expected)
val (succ, oldNum) = cmpXchgLong(addr, numExpected, numDesired, inMu = true)
val oldObj = try {
implicitly[CanBeIntegerized[T]].deIntegerize(oldNum)
} catch {
case e: UvmUnknownIDException =>
throw new UvmRefImplException("Memory location 0x%x referring to non-existing entity %d".format(addr, oldNum), e)
}
(succ, oldObj)
}
def xchgEntity[T: CanBeIntegerized](addr: Word, desired: Option[T])(implicit microVM: MicroVM): Option[T] = {
val oldVal = loadEntity[T](addr)
storeEntity[T](addr, desired)
return oldVal
}
def memset(addr: Word, size: Word, value: Byte): Unit = {
theMemory.setMemory(addr, size, value)
}
......@@ -150,3 +197,46 @@ class MemorySupport(val muMemorySize: Word) {
theMemory.put(addr, dest, 0, len.toInt)
}
}
object EntityAccessors {
@implicitNotFound("Mu entity type ${T} cannot be represented as an integer, thus cannot be loaded/stored from the memory.")
trait CanBeIntegerized[T] {
protected def _integerize(obj: T)(implicit microVM: MicroVM): Word
protected def _deIntegerize(num: Word)(implicit microVM: MicroVM): T
def integerize(obj: Option[T])(implicit microVM: MicroVM): Word =
obj.map(_integerize).getOrElse(0L)
def deIntegerize(num: Word)(implicit microVM: MicroVM): Option[T] = {
if (num == 0L) {
None
} else {
Some(_deIntegerize(num))
}
}
}
implicit object FunctionIntegerizer extends CanBeIntegerized[Function] {
def _integerize(obj: Function)(implicit microVM: MicroVM): Word = obj.id.toLong
def _deIntegerize(num: Word)(implicit microVM: MicroVM): Function = microVM.globalBundle.funcNs(num.toInt)
}
implicit object ThreadIntegerizer extends CanBeIntegerized[InterpreterThread] {
def _integerize(obj: InterpreterThread)(implicit microVM: MicroVM): Word = obj.id.toLong
def _deIntegerize(num: Word)(implicit microVM: MicroVM): InterpreterThread = microVM.threadStackManager.threadRegistry(num.toInt)
}
implicit object StackIntegerizer extends CanBeIntegerized[InterpreterStack] {
def _integerize(obj: InterpreterStack)(implicit microVM: MicroVM): Word = obj.id.toLong
def _deIntegerize(num: Word)(implicit microVM: MicroVM): InterpreterStack = microVM.threadStackManager.stackRegistry(num.toInt)
}
implicit object FrameCursorIntegerizer extends CanBeIntegerized[FrameCursor] {
def _integerize(obj: FrameCursor)(implicit microVM: MicroVM): Word = obj.id.toLong
def _deIntegerize(num: Word)(implicit microVM: MicroVM): FrameCursor = microVM.threadStackManager.frameCursorRegistry(num.toInt)
}
implicit object IRNodeIntegerizer extends CanBeIntegerized[IRNode] {
def _integerize(obj: IRNode)(implicit microVM: MicroVM): Word = microVM.irNodeRegistry.objGetLong(obj)
def _deIntegerize(num: Word)(implicit microVM: MicroVM): IRNode = microVM.irNodeRegistry.longToObj(num)
}
}
......@@ -9,29 +9,25 @@ import scala.collection.mutable.HashMap
* Similar to JFFI's object exposer.
*/
class SequentialObjectKeeper[T] {
private val longToObj = new HashMap[Long, T]()
private val objToLong = new HashMap[T, Long]()
private val longToObjMap = new HashMap[Long, T]()
private val objToLongMap = new HashMap[T, Long]()
var nextLong = 1L
def objGetLong(maybeObj: Option[T]): Long = {
maybeObj match {
case None => 0L
case Some(obj) =>
objToLong.getOrElseUpdate(obj, {
def objGetLong(obj: T): Long = {
objToLongMap.getOrElseUpdate(obj, {
val myLong = nextLong
nextLong += 1
longToObj(myLong) = obj
longToObjMap(myLong) = obj
myLong
})
}
}
def longToObj(l: Long): Option[T] = longToObj.get(l)
def longToObj(l: Long): T = longToObjMap.apply(l)
def maybeRemoveObj(obj: T): Unit = {
objToLong.remove(obj).foreach { l =>
longToObj.remove(l)
objToLongMap.remove(obj).foreach { l =>
longToObjMap.remove(l)
}
}
}
\ No newline at end of file
......@@ -8,6 +8,8 @@ import com.typesafe.scalalogging.StrictLogging
import TypeSizes._
import com.typesafe.scalalogging.Logger
import org.slf4j.LoggerFactory
import uvm.Function
import uvm.ir.irbuilder.IRNode
object MemoryDataScanner extends StrictLogging {
......@@ -17,7 +19,7 @@ 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, handler: RefFieldHandler)(implicit microVM: MicroVM, memorySupport: MemorySupport) {
def scanAllocUnit(objRef: Word, handler: MemoryFieldHandler)(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)
......@@ -33,7 +35,7 @@ object MemoryDataScanner extends StrictLogging {
scanField(ty, objRef, objRef, handler)
}
def scanField(ty: Type, objRef: Word, iRef: Word, handler: RefFieldHandler)(implicit microVM: MicroVM, memorySupport: MemorySupport) {
def scanField(ty: Type, objRef: Word, iRef: Word, handler: MemoryFieldHandler)(implicit microVM: MicroVM, memorySupport: MemorySupport) {
def logField(kind: String, toObj: Word): String = "%s field [0x%x + 0x%x] = 0x%x -> 0x%x".format(kind, objRef, iRef - objRef, iRef, toObj)
def logIRefField(kind: String, toObj: Word, offset: Word): String = "%s field [0x%x + 0x%x] = 0x%x -> 0x%x + 0x%x = 0x%x".format(
kind, objRef, iRef - objRef, iRef, toObj, offset, toObj + offset)
......@@ -41,22 +43,18 @@ object MemoryDataScanner extends StrictLogging {
case t: TypeRef => {
val toObj = memorySupport.loadLong(iRef)
logger.debug(logField("Ref", toObj))
handler.memToHeap(objRef, iRef, toObj, false, false)
handler.visitRefField(objRef, iRef, toObj, false)
}
case t: TypeIRef => {
val toObj = memorySupport.loadLong(iRef)
val offset = memorySupport.loadLong(iRef + WORD_SIZE_BYTES)
logger.debug(logIRefField("IRef", toObj, offset))
if (toObj == 0L && offset != 0L) {
handler.memToNonHeap(objRef, iRef, offset)
} else {
handler.memToHeap(objRef, iRef, toObj, false, false)
}
handler.visitIRefField(objRef, iRef, toObj, offset)
}
case t: TypeWeakRef => {
val toObj = memorySupport.loadLong(iRef)
logger.debug(logField("WeakRef", toObj))
handler.memToHeap(objRef, iRef, toObj, true, false)
handler.visitRefField(objRef, iRef, toObj, true)
}
case t: TypeTagRef64 => {
val bits = memorySupport.loadLong(iRef)
......@@ -73,7 +71,7 @@ object MemoryDataScanner extends StrictLogging {
if (OpHelper.tr64IsRef(bits)) {
val toObj = OpHelper.tr64ToRef(bits)
logger.debug(logField("TagRef64", toObj))
handler.memToHeap(objRef, iRef, toObj, false, true)
handler.visitTagRefField(objRef, iRef, toObj)
}
}
case t: TypeStruct => {
......@@ -115,28 +113,24 @@ object MemoryDataScanner extends StrictLogging {
}
}
case t: TypeStackRef => {
val toStackID = memorySupport.loadLong(iRef)
val maybeToStack = if (toStackID == 0) {
None
} else {
val toStack = microVM.threadStackManager.stackRegistry.get(toStackID.toInt).getOrElse {
throw new UvmRefImplException("Memory location 0x%x referring to non-existing stack %d".format(iRef, toStackID))
}
Some(toStack)
}
handler.memToStack(objRef, iRef, maybeToStack)
val obj = memorySupport.loadEntity[InterpreterStack](iRef)
handler.visitStackRefField(objRef, iRef, obj)
}
case t: TypeFuncRef => {
val toFuncID = memorySupport.loadLong(iRef)
val maybeToFunc = if (toFuncID == 0) {
None
} else {
val toFunc = microVM.globalBundle.funcNs.get(toFuncID.toInt).getOrElse {
throw new UvmRefImplException("Memory location 0x%x referring to non-existing function %d".format(iRef, toFuncID))
val obj = memorySupport.loadEntity[Function](iRef)
handler.visitFuncRefField(objRef, iRef, obj)
}
case t: TypeThreadRef => {
val obj = memorySupport.loadEntity[InterpreterThread](iRef)
handler.visitThreadRefField(objRef, iRef, obj)
}
Some(toFunc)
case t: TypeFrameCursorRef => {
val obj = memorySupport.loadEntity[FrameCursor](iRef)
handler.visitFCRefField(objRef, iRef, obj)
}
handler.memToFunc(objRef, iRef, maybeToFunc)
case t: TypeIRNodeRef => {
val obj = memorySupport.loadEntity[IRNode](iRef)
handler.visitIRNodeRefField(objRef, iRef, obj)
}
case _ => // Ignore non-reference fields.
}
......
......@@ -11,6 +11,28 @@ import uvm.refimpl.UvmRefImplException
import org.slf4j.LoggerFactory
import com.typesafe.scalalogging.Logger
import uvm.Function
import uvm.refimpl.itpr.FrameCursor
import uvm.ir.irbuilder.IRNode
/**
* Handle general reference fields in the memory. This trait is mostly useful for the boot image builder.
* <p>
* 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 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 visitIRNodeRefField(objRef: Word, iRef: Word, toIRNode: Option[IRNode]): Unit
}
/**
* Handle references in the memory, value boxes or other Micro VM structures such as threads and stacks.
......@@ -22,7 +44,7 @@ import uvm.Function
* 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 {
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. */
......@@ -38,17 +60,27 @@ trait RefFieldHandler {
/** Pin set referring to the memory. Pinned objects cannot be moved. */
def pinSetToMem(toObj: Word): Option[Word]
/**
* A memory location referring to non-heap Mu memory. For GC, such fields do not need to be traced. But
* boot image writers need them to track other global cells.
*/
def memToNonHeap(objRef: Word, iRef: Word, addr: Word): Unit = ()
def visitRefField(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean): Unit = {
memToHeap(objRef, iRef, toObj, isWeak, false)
}
/**
* A memory location referring to a Mu function. GC does not need to care about function references, but
* boot image builders need to find them so that functions can be relocated.
*/
def memToFunc(objRef: Word, iRef: Word, toFunc: Option[Function]): Unit = ()
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 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 visitIRNodeRefField(objRef: Word, iRef: Word, toIRNode: Option[IRNode]): Unit = {}
}
object RefFieldUpdater {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment