Commit 1e77a314 authored by Kunshan Wang's avatar Kunshan Wang

Auto relocate "reasonable" uptrs and symbols.

Need testing...
parent a6c7f08c
......@@ -220,6 +220,32 @@ class BootImageWriter(tcb: TransitiveClosureBuilder, syms: Seq[FieldAndSymbol],
val begin = alloc.addr
MemoryDataScanner.scanAllocUnit(begin, new MemoryFieldHandler {
def visitUPtrField(objRef: Word, iRef: Word, toAddr: Word): Unit = if (toAddr != 0L) {
relocsMap.get(toAddr) match {
case Some(symbol) => {
// by symbol
val fieldOffset = iRef - objRef
val reloc = FieldRelocRecord(num, fieldOffset, AS_UPTR, TO_SYM, 0, 0, symbol)
group.relocRecs += reloc
}
case None => {
// maybe a "reasonable" pointer to a mu global cell. Relocate it too.
val fieldOffset = iRef - objRef
val maybeGlobalCell = tcb.maybeGetGlobalCellRec(toAddr)
maybeGlobalCell match {
case Some(gcr) =>
val targetNum = gcr.g.id.toLong
val targetAddr = gcr.begin
val targetOffset = toAddr - targetAddr
val reloc = FieldRelocRecord(num, fieldOffset, AS_UPTR, TO_GLOBAL, targetNum, targetOffset, NO_SYM)
group.relocRecs += reloc
case None => logger.info("UPtr field not pointing to Mu global cell: %d 0x%x -> %d 0x%x".format(
iRef, iRef, toAddr, toAddr))
}
}
}
}
def visitRefField(objRef: Word, iRef: Word, toObj: Word, isWeak: Boolean): Unit = if (toObj != 0L) {
val fieldOffset = iRef - objRef
val targetNum = addrToHeapObjNum(toObj)
......@@ -266,13 +292,14 @@ class BootImageWriter(tcb: TransitiveClosureBuilder, syms: Seq[FieldAndSymbol],
}
private def addPointerRelocs(): Unit = {
???
// Seems uptrs are already handled when scanning fields. No further processing is needed at this moment.
}
private def writeRelocRecs(group: FileGroup): Unit = {
tryWithResource(Files.newBufferedWriter(group.relocFile, StandardCharsets.UTF_8)) { writer =>
for (rr <- group.relocRecs) {
writer.write("%d,%d,%s,%s,%d,%d\n".format(rr.num, rr.fieldOffset, rr.fieldKind, rr.targetKind, rr.targetNum, rr.targetOffset))
writer.write("%d,%d,%s,%s,%d,%d,%s\n".format(
rr.num, rr.fieldOffset, rr.fieldKind, rr.targetKind, rr.targetNum, rr.targetOffset, rr.targetString))
}
}
}
......
......@@ -188,45 +188,58 @@ class BootImageLoader(file: String)(implicit microVM: MicroVM) extends AutoClose
private def relocate(): Unit = {
forEachReloc("global") { rr =>
val FieldRelocRecord(num, fieldOffset, fieldKind, targetKind, targetNum, targetOffset) = rr
val FieldRelocRecord(num, fieldOffset, fieldKind, targetKind, targetNum, targetOffset, targetString) = rr
val base = globalNumToAddr(num)
relocField(base, fieldOffset, fieldKind, targetKind, targetNum, targetOffset)
relocField(base, fieldOffset, fieldKind, targetKind, targetNum, targetOffset, targetString)
}
forEachReloc("heap") { rr =>
val FieldRelocRecord(num, fieldOffset, fieldKind, targetKind, targetNum, targetOffset) = rr
val FieldRelocRecord(num, fieldOffset, fieldKind, targetKind, targetNum, targetOffset, targetString) = rr
val base = objNumToAddr(num)
relocField(base, fieldOffset, fieldKind, targetKind, targetNum, targetOffset)
relocField(base, fieldOffset, fieldKind, targetKind, targetNum, targetOffset, targetString)
}
}
private def forEachReloc(groupName: String)(f: FieldRelocRecord => Unit): Unit = {
tryWithResource(zipFileTextBuf(groupName + FILEEXT_RELOC)) { relocIS =>
forEachLine(relocIS) { line =>
val elems = line.split(",")
val elems = line.split(",", -1) // include the trailing empty string
val num = elems(0).toLong
val fieldOffset = elems(1).toLong
val fieldKind = elems(2)
val targetKind = elems(3)
val targetNum = elems(4).toLong
val targetOffset = elems(5).toLong
val rr = FieldRelocRecord(num, fieldOffset, fieldKind, targetKind, targetNum, targetOffset)
val targetString = elems(6)
val rr = FieldRelocRecord(num, fieldOffset, fieldKind, targetKind, targetNum, targetOffset, targetString)
f(rr)
}
}
}
private def relocField(srcBase: Word, srcOffset: Word, fieldKind: String, targetKind: String, targetNum: Long, targetOffset: Word): Unit = {
private def relocField(srcBase: Word, srcOffset: Word, fieldKind: String,
targetKind: String, targetNum: Long, targetOffset: Word, targetSymbol: String): Unit = {
val srcFieldAddr = srcBase + srcOffset
fieldKind match {
case AS_UPTR => {
assert(targetKind != TO_FUNC, "BUG: uptr field referring to func")
assert(targetKind != TO_HEAP, "BUG: uptr field referring to obj")
val targetAddr = targetKind match {
case TO_GLOBAL => getTargetMemBase(targetKind, targetNum) + targetOffset
case TO_SYM => getSymbolAddr(targetSymbol)
}
memorySupport.storeLong(srcFieldAddr, targetAddr)
}
case AS_REF => {
assert(targetOffset == 0L)
assert(targetKind != TO_FUNC, "BUG: ref field referring to function")
assert(targetKind != TO_SYM, "BUG: ref field referring to symbol")
val targetBase = getTargetMemBase(targetKind, targetNum)
memorySupport.storeLong(srcFieldAddr, targetBase)
}
case AS_IREF => {
assert(targetKind != TO_FUNC, "BUG: iref field referring to function")
assert(targetKind != TO_SYM, "BUG: iref field referring to symbol")
val targetBase = getTargetMemBase(targetKind, targetNum)
val (irefBase, irefOffset) = targetKind match {
case TO_GLOBAL => (0L, targetBase + targetOffset)
......@@ -238,6 +251,7 @@ class BootImageLoader(file: String)(implicit microVM: MicroVM) extends AutoClose
case AS_TAGREF => {
assert(targetOffset == 0L)
assert(targetKind != TO_FUNC, "BUG: tagref64 field referring to function")
assert(targetKind != TO_SYM, "BUG: tagref64 field referring to symbol")
val targetBase = getTargetMemBase(targetKind, targetNum)
val oldTR64 = memorySupport.loadLong(srcFieldAddr)
val oldTag = OpHelper.tr64ToTag(oldTR64)
......@@ -259,6 +273,10 @@ class BootImageLoader(file: String)(implicit microVM: MicroVM) extends AutoClose
case TO_HEAP => objNumToAddr(targetNum)
}
}
private def getSymbolAddr(targetSymbol: String): Word = {
microVM.nativeLibraryHolder.getSymbolAddress(targetSymbol)
}
}
class AlignedInputStream(is: InputStream) extends Closeable {
......
......@@ -164,6 +164,19 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel], val primordial: Primor
gcr
}
def maybeGetGlobalCellRec(iref: Word): Option[GlobalCellRec] = {
require(microVM.memoryManager.globalMemory.isInSpace(iref),
"Address %d 0x%x is not in the global space".format(iref, iref))
for ((begin, gcr) <- globalCellMap.to(iref).lastOption) yield {
assert(begin <= iref && iref < gcr.end,
"Address %d 0x%x is in the global space, but the previous global cell's address range is %d 0x%x - %d 0x%x".format(
iref, iref, begin, begin, gcr.end, gcr.end))
gcr
}
}
def doTransitiveClosure(): Unit = {
while (tls.hasPending || allocs.hasPending) {
while (tls.hasPending) {
......@@ -370,6 +383,7 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel], val primordial: Primor
toFunc.foreach(tls+=)
}
override def visitUPtrField(objRef: Word, iRef: Word, toAddr: Word): Unit = {}
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 =
......
......@@ -42,6 +42,11 @@ object MemoryDataScanner extends StrictLogging {
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)
ty match {
case t: TypeUPtr => {
val toAddr = memorySupport.loadLong(iRef, false)
logger.debug(logField("UPtr", toAddr))
handler.visitUPtrField(objRef, iRef, toAddr)
}
case t: TypeRef => {
val toObj = memorySupport.loadLong(iRef)
logger.debug(logField("Ref", toObj))
......
......@@ -22,6 +22,8 @@ import uvm.refimpl.mem.MemorySupport
* object; "iRef" is the address of the field itself.
*/
trait MemoryFieldHandler {
def visitUPtrField(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
......@@ -78,6 +80,7 @@ trait RefFieldHandler extends MemoryFieldHandler {
memToStack(objRef, iRef, toStack)
}
def visitUPtrField(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 = {}
......
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