GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

Commit 25c803ec authored by Kunshan Wang's avatar Kunshan Wang

Object pinning

parent b2e215ec
...@@ -15,21 +15,24 @@ object MicroVM { ...@@ -15,21 +15,24 @@ object MicroVM {
} }
class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE, class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE,
globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE, globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE,
stackSize: Word = MicroVM.DEFAULT_STACK_SIZE) { stackSize: Word = MicroVM.DEFAULT_STACK_SIZE) {
// implicitly injected resources // implicitly injected resources
private implicit val microVM = this private implicit val microVM = this
val globalBundle = new Bundle() val globalBundle = new Bundle()
val constantPool = new ConstantPool() val constantPool = new ConstantPool()
val memoryManager = new MemoryManager(heapSize, globalSize, stackSize) val memoryManager = new MemoryManager(heapSize, globalSize, stackSize)
private implicit val memorySupport = memoryManager.memorySupport
val threadStackManager = new ThreadStackManager() val threadStackManager = new ThreadStackManager()
val trapManager = new TrapManager() val trapManager = new TrapManager()
val clientAgents = new HashSet[ClientAgent]() val clientAgents = new HashSet[ClientAgent]()
val irReader = new UIRTextReader(new IDFactory()) val irReader = new UIRTextReader(new IDFactory())
{ {
// The micro VM allocates stacks on the heap in the large object space. It is represented as a bug chunk of byte array. // The micro VM allocates stacks on the heap in the large object space. It is represented as a bug chunk of byte array.
// So the GC must know about this type because the GC looks up the globalBundle for types. // So the GC must know about this type because the GC looks up the globalBundle for types.
...@@ -54,17 +57,21 @@ class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE, ...@@ -54,17 +57,21 @@ class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE,
constantPool.addGlobalVar(g) constantPool.addGlobalVar(g)
} }
} }
/** /**
* Create a new ClientAgent. * Create a new ClientAgent.
*/ */
def newClientAgent(): ClientAgent = new ClientAgent(this) def newClientAgent(): ClientAgent = {
val mutator = microVM.memoryManager.heap.makeMutator() // This may trigger GC
val ca = new ClientAgent(mutator)
clientAgents.add(ca)
ca
}
/** /**
* Given a name, get the ID of an identified entity. * Given a name, get the ID of an identified entity.
*/ */
def idOf(name: String): Int = globalBundle.allNs(name).id def idOf(name: String): Int = globalBundle.allNs(name).id
/** /**
* Given an ID, get the name of an identified entity. * Given an ID, get the name of an identified entity.
*/ */
......
...@@ -9,6 +9,7 @@ import uvm.ssavariables.MemoryOrder._ ...@@ -9,6 +9,7 @@ import uvm.ssavariables.MemoryOrder._
import uvm.ssavariables.AtomicRMWOptr._ import uvm.ssavariables.AtomicRMWOptr._
import uvm.refimpl.mem._ import uvm.refimpl.mem._
import uvm.ssavariables.HasKeepAliveClause import uvm.ssavariables.HasKeepAliveClause
import scala.collection.mutable.ArrayBuffer
case class Handle(ty: Type, vb: ValueBox) case class Handle(ty: Type, vb: ValueBox)
...@@ -26,17 +27,11 @@ trait UndefinedFunctionHandler { ...@@ -26,17 +27,11 @@ trait UndefinedFunctionHandler {
def handleUndefinedFunction(functionID: Int): Unit def handleUndefinedFunction(functionID: Int): Unit
} }
class ClientAgent(microVM: MicroVM) { class ClientAgent(mutator: Mutator)(
implicit microVM: MicroVM, memorySupport: MemorySupport) extends ObjectPinner {
// Injectable resources (used by memory access operations)
private implicit val microVM_ = microVM
private implicit val memorySupport = microVM.memoryManager.memorySupport
val handles = new HashSet[Handle]() val handles = new HashSet[Handle]()
microVM.clientAgents.add(this) val pinSet = new ArrayBuffer[Word]
val mutator = microVM.memoryManager.heap.makeMutator()
def close(): Unit = { def close(): Unit = {
handles.clear() handles.clear()
...@@ -48,7 +43,7 @@ class ClientAgent(microVM: MicroVM) { ...@@ -48,7 +43,7 @@ class ClientAgent(microVM: MicroVM) {
val bundle = microVM.irReader.read(r, microVM.globalBundle) val bundle = microVM.irReader.read(r, microVM.globalBundle)
microVM.addBundle(bundle) microVM.addBundle(bundle)
} }
def loadBundle(s: String): Unit = { def loadBundle(s: String): Unit = {
val bundle = microVM.irReader.read(s, microVM.globalBundle) val bundle = microVM.irReader.read(s, microVM.globalBundle)
microVM.addBundle(bundle) microVM.addBundle(bundle)
...@@ -94,7 +89,7 @@ class ClientAgent(microVM: MicroVM) { ...@@ -94,7 +89,7 @@ class ClientAgent(microVM: MicroVM) {
val et = t.elemTy.asInstanceOf[TypeDouble] val et = t.elemTy.asInstanceOf[TypeDouble]
newHandle(t, BoxVector(vs.map(BoxDouble))) newHandle(t, BoxVector(vs.map(BoxDouble)))
} }
def putPointer(typeID: Int, v: Word): Handle = { def putPointer(typeID: Int, v: Word): Handle = {
val t = microVM.globalBundle.typeNs(typeID) val t = microVM.globalBundle.typeNs(typeID)
newHandle(t, BoxPointer(v)) newHandle(t, BoxPointer(v))
...@@ -157,7 +152,7 @@ class ClientAgent(microVM: MicroVM) { ...@@ -157,7 +152,7 @@ class ClientAgent(microVM: MicroVM) {
def toDoubleVec(h: Handle): Seq[Double] = { def toDoubleVec(h: Handle): Seq[Double] = {
h.vb.asInstanceOf[BoxVector].values.map(b => b.asInstanceOf[BoxDouble].value) h.vb.asInstanceOf[BoxVector].values.map(b => b.asInstanceOf[BoxDouble].value)
} }
def toPointer(h: Handle): Word = { def toPointer(h: Handle): Word = {
h.vb.asInstanceOf[BoxPointer].addr h.vb.asInstanceOf[BoxPointer].addr
} }
...@@ -262,12 +257,12 @@ class ClientAgent(microVM: MicroVM) { ...@@ -262,12 +257,12 @@ class ClientAgent(microVM: MicroVM) {
def load(ord: MemoryOrder, loc: Handle): Handle = { def load(ord: MemoryOrder, loc: Handle): Handle = {
val (ptr, ty) = loc.ty match { val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t) case TypeIRef(t) => (false, t)
case TypePtr(t) => (true, t) case TypePtr(t) => (true, t)
} }
val uty = InternalTypePool.unmarkedOf(ty) val uty = InternalTypePool.unmarkedOf(ty)
val addr = MemoryOperations.addressOf(ptr, loc.vb) val addr = MemoryOperations.addressOf(ptr, loc.vb)
val nb = ValueBox.makeBoxForType(uty) val nb = ValueBox.makeBoxForType(uty)
MemoryOperations.load(ptr, uty, addr, nb) MemoryOperations.load(ptr, uty, addr, nb)
newHandle(uty, nb) newHandle(uty, nb)
...@@ -276,11 +271,11 @@ class ClientAgent(microVM: MicroVM) { ...@@ -276,11 +271,11 @@ class ClientAgent(microVM: MicroVM) {
def store(ord: MemoryOrder, loc: Handle, newVal: Handle): Unit = { def store(ord: MemoryOrder, loc: Handle, newVal: Handle): Unit = {
val (ptr, ty) = loc.ty match { val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t) case TypeIRef(t) => (false, t)
case TypePtr(t) => (true, t) case TypePtr(t) => (true, t)
} }
val uty = InternalTypePool.unmarkedOf(ty) val uty = InternalTypePool.unmarkedOf(ty)
val addr = MemoryOperations.addressOf(ptr, loc.vb) val addr = MemoryOperations.addressOf(ptr, loc.vb)
val nvb = newVal.vb val nvb = newVal.vb
val nb = ValueBox.makeBoxForType(uty) val nb = ValueBox.makeBoxForType(uty)
MemoryOperations.store(ptr, uty, addr, nvb, nb) MemoryOperations.store(ptr, uty, addr, nvb, nb)
...@@ -289,7 +284,7 @@ class ClientAgent(microVM: MicroVM) { ...@@ -289,7 +284,7 @@ class ClientAgent(microVM: MicroVM) {
def cmpXchg(ordSucc: MemoryOrder, ordFail: MemoryOrder, weak: Boolean, loc: Handle, expected: Handle, desired: Handle): (Boolean, Handle) = { def cmpXchg(ordSucc: MemoryOrder, ordFail: MemoryOrder, weak: Boolean, loc: Handle, expected: Handle, desired: Handle): (Boolean, Handle) = {
val (ptr, ty) = loc.ty match { val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t) case TypeIRef(t) => (false, t)
case TypePtr(t) => (true, t) case TypePtr(t) => (true, t)
} }
val uty = InternalTypePool.unmarkedOf(ty) val uty = InternalTypePool.unmarkedOf(ty)
val addr = MemoryOperations.addressOf(ptr, loc.vb) val addr = MemoryOperations.addressOf(ptr, loc.vb)
...@@ -303,7 +298,7 @@ class ClientAgent(microVM: MicroVM) { ...@@ -303,7 +298,7 @@ class ClientAgent(microVM: MicroVM) {
def atomicRMW(ord: MemoryOrder, op: AtomicRMWOptr, loc: Handle, opnd: Handle): Handle = { def atomicRMW(ord: MemoryOrder, op: AtomicRMWOptr, loc: Handle, opnd: Handle): Handle = {
val (ptr, ty) = loc.ty match { val (ptr, ty) = loc.ty match {
case TypeIRef(t) => (false, t) case TypeIRef(t) => (false, t)
case TypePtr(t) => (true, t) case TypePtr(t) => (true, t)
} }
val uty = InternalTypePool.unmarkedOf(ty) val uty = InternalTypePool.unmarkedOf(ty)
val addr = MemoryOperations.addressOf(ptr, loc.vb) val addr = MemoryOperations.addressOf(ptr, loc.vb)
...@@ -320,7 +315,7 @@ class ClientAgent(microVM: MicroVM) { ...@@ -320,7 +315,7 @@ class ClientAgent(microVM: MicroVM) {
val funcVal = func.vb.asInstanceOf[BoxFunc].func.getOrElse { val funcVal = func.vb.asInstanceOf[BoxFunc].func.getOrElse {
throw new UvmRuntimeException("Stack-bottom function must not be NULL") throw new UvmRuntimeException("Stack-bottom function must not be NULL")
} }
val funcVer = funcVal.versions.headOption.getOrElse { val funcVer = funcVal.versions.headOption.getOrElse {
throw new UvmRuntimeException("Stack-bottom function %s is not defined.".format(funcVal.repr)) throw new UvmRuntimeException("Stack-bottom function %s is not defined.".format(funcVal.repr))
} }
...@@ -406,12 +401,12 @@ class ClientAgent(microVM: MicroVM) { ...@@ -406,12 +401,12 @@ class ClientAgent(microVM: MicroVM) {
val st = getStackNotNull(stack) val st = getStackNotNull(stack)
val top = st.top val top = st.top
top.prev match { top.prev match {
case None => throw new UvmRuntimeException("Attempting to pop the last frame of a stack.") case None => throw new UvmRuntimeException("Attempting to pop the last frame of a stack.")
case Some(prev) => st.top = prev case Some(prev) => st.top = prev
} }
} }
def pushFrame(stack: Handle, func: Handle, argList: Seq[Handle]): Unit = { def pushFrame(stack: Handle, func: Handle, argList: Seq[Handle]): Unit = {
val sta = stack.vb.asInstanceOf[BoxStack].stack.getOrElse { val sta = stack.vb.asInstanceOf[BoxStack].stack.getOrElse {
throw new UvmRuntimeException("Stack must not be NULL") throw new UvmRuntimeException("Stack must not be NULL")
} }
...@@ -419,13 +414,13 @@ class ClientAgent(microVM: MicroVM) { ...@@ -419,13 +414,13 @@ class ClientAgent(microVM: MicroVM) {
val funcVal = func.vb.asInstanceOf[BoxFunc].func.getOrElse { val funcVal = func.vb.asInstanceOf[BoxFunc].func.getOrElse {
throw new UvmRuntimeException("Stack-bottom function must not be NULL") throw new UvmRuntimeException("Stack-bottom function must not be NULL")
} }
val funcVer = funcVal.versions.headOption.getOrElse { val funcVer = funcVal.versions.headOption.getOrElse {
throw new UvmRuntimeException("Stack-bottom function %s is not defined.".format(funcVal.repr)) throw new UvmRuntimeException("Stack-bottom function %s is not defined.".format(funcVal.repr))
} }
val argBoxes = argList.map(_.vb) val argBoxes = argList.map(_.vb)
sta.pushFrame(funcVer, argBoxes) sta.pushFrame(funcVer, argBoxes)
} }
...@@ -483,7 +478,7 @@ class ClientAgent(microVM: MicroVM) { ...@@ -483,7 +478,7 @@ 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 = { def enableWatchPoint(wpID: Int): Unit = {
microVM.trapManager.enableWatchPoint(wpID) microVM.trapManager.enableWatchPoint(wpID)
} }
...@@ -492,6 +487,42 @@ class ClientAgent(microVM: MicroVM) { ...@@ -492,6 +487,42 @@ class ClientAgent(microVM: MicroVM) {
microVM.trapManager.disableWatchPoint(wpID) microVM.trapManager.disableWatchPoint(wpID)
} }
def ptrcast(handle: Handle, newType: Type): Handle = {
require(handle.ty.isInstanceOf[AbstractPointerType] || handle.ty.isInstanceOf[TypeInt], "handle must have type int, ptr or funcptr. %s found".format(handle.ty.repr))
require(newType.isInstanceOf[AbstractPointerType] || newType.isInstanceOf[TypeInt], "can only convert to int, ptr or funcptr. %s found".format(newType.repr))
val addr = handle.ty match {
case TypeInt(n) => OpHelper.trunc(handle.vb.asInstanceOf[BoxInt].value, 64).toLong
case _: AbstractPointerType => handle.vb.asInstanceOf[BoxPointer].addr
}
val box = newType match {
case TypeInt(n) => new BoxInt(OpHelper.trunc(BigInt(addr), n))
case _: AbstractPointerType => new BoxPointer(addr)
}
newHandle(newType, box)
}
def pin(handle: Handle): Handle = {
val (objTy, objRef) = handle.ty match {
case TypeRef(t) => (t, handle.vb.asInstanceOf[BoxRef].objRef)
case TypeIRef(t) => (t, handle.vb.asInstanceOf[BoxIRef].objRef)
}
pin(objRef)
val ptrTy = InternalTypePool.ptrOf(objTy)
val box = new BoxPointer(objRef)
newHandle(ptrTy, box)
}
def unpin(handle: Handle): Unit = {
val (objTy, objRef) = handle.ty match {
case TypeRef(t) => (t, handle.vb.asInstanceOf[BoxRef].objRef)
case TypeIRef(t) => (t, handle.vb.asInstanceOf[BoxIRef].objRef)
}
unpin(objRef)
}
// Internal methods for the micro VM // Internal methods for the micro VM
def putThread(thr: Option[InterpreterThread]): Handle = { def putThread(thr: Option[InterpreterThread]): Handle = {
......
...@@ -138,6 +138,14 @@ object TypeInferer { ...@@ -138,6 +138,14 @@ object TypeInferer {
case "@uvm.futex.wake" => I32 case "@uvm.futex.wake" => I32
case "@uvm.futex.cmp_requeue" => I32 case "@uvm.futex.cmp_requeue" => I32
case "@uvm.kill_dependency" => i.typeList(0) case "@uvm.kill_dependency" => i.typeList(0)
case "@uvm.native.pin" => i.typeList(0) match{
case TypeRef(t) => ptrOf(t)
case TypeIRef(t) => ptrOf(t)
}
case "@uvm.native.unpin" => VOID
case "@uvm.native.expose" => funcPtrOf(i.funcSigList(0))
case "@uvm.native.unexpose" => VOID
case "@uvm.native.get_cookie" => I64
} }
} }
} }
\ No newline at end of file
package uvm.refimpl.itpr package uvm.refimpl.itpr
import scala.annotation.tailrec
import scala.collection.mutable.ArrayBuffer
import org.slf4j.LoggerFactory
import com.typesafe.scalalogging.Logger
import uvm._ import uvm._
import uvm.types._
import uvm.ssavariables._
import uvm.comminsts._ import uvm.comminsts._
import uvm.refimpl._ import uvm.refimpl._
import uvm.refimpl.mem._ import uvm.refimpl.mem._
import TypeSizes.Word import uvm.refimpl.mem.TypeSizes.Word
import scala.annotation.tailrec import uvm.ssavariables._
import org.slf4j.LoggerFactory import uvm.types._
import com.typesafe.scalalogging.Logger
object InterpreterThread { object InterpreterThread {
val logger = Logger(LoggerFactory.getLogger(getClass.getName)) val logger = Logger(LoggerFactory.getLogger(getClass.getName))
} }
class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, initialStack: InterpreterStack, val mutator: Mutator) { class InterpreterThread(val id: Int, initialStack: InterpreterStack, val mutator: Mutator)(
implicit microVM: MicroVM) extends ObjectPinner {
import InterpreterThread._ import InterpreterThread._
// Injectable resources (used by memory access instructions) // Injectable resources (used by memory access instructions)
...@@ -32,6 +37,9 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init ...@@ -32,6 +37,9 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
/** True if the thread is waiting in a Futex waiting queue. */ /** True if the thread is waiting in a Futex waiting queue. */
var isFutexWaiting: Boolean = false var isFutexWaiting: Boolean = false
/** Object-pinnning multiset. */
val pinSet = new ArrayBuffer[Word]
// Initialisation // Initialisation
rebindPassVoid(initialStack) rebindPassVoid(initialStack)
...@@ -1053,6 +1061,34 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init ...@@ -1053,6 +1061,34 @@ class InterpreterThread(val id: Int, implicit private val microVM: MicroVM, init
continueNormally() continueNormally()
} }
case "@uvm.native.pin" => {
val Seq(ty) = typeList
val Seq(r) = argList
val addr = ty match {
case TypeRef(_) => boxOf(r).asInstanceOf[BoxRef].objRef
case TypeIRef(_) => boxOf(r).asInstanceOf[BoxIRef].objRef
}
pin(addr)
boxOf(i).asInstanceOf[BoxPointer].addr = addr
continueNormally()
}
case "@uvm.native.unpin" => {
val Seq(ty) = typeList
val Seq(r) = argList
val addr = ty match {
case TypeRef(_) => boxOf(r).asInstanceOf[BoxRef].objRef
case TypeIRef(_) => boxOf(r).asInstanceOf[BoxIRef].objRef
}
unpin(addr)
continueNormally()
}
// Insert more CommInsts here. // Insert more CommInsts here.
case ciName => { case ciName => {
......
package uvm.refimpl.itpr
import scala.collection.mutable.ArrayBuffer
import uvm.refimpl.mem.Mutator
import uvm.refimpl.mem.TypeSizes.Word
import uvm.refimpl.UvmRuntimeException
/**
* Trait for entities (threads and client agents) that can pin objects. GC can also scan such entities.
*/
trait ObjectPinner {
/** Multi-set of pinned object references. May contain NULL. */
def pinSet: ArrayBuffer[Word]
def pin(addr: Word) {
pinSet += addr
}
def unpin(addr: Word) {
val index = pinSet.lastIndexOf(addr)
if (index == -1) {
throw new UvmRuntimeException("Attempt to unpin object at %d (0x%x), which is not pinned.".format(addr, addr))
}
pinSet.remove(index)
}
}
\ No newline at end of file
...@@ -59,7 +59,7 @@ class ThreadStackManager(implicit microVM: MicroVM) { ...@@ -59,7 +59,7 @@ class ThreadStackManager(implicit microVM: MicroVM) {
def newThread(stack: InterpreterStack): InterpreterThread = { def newThread(stack: InterpreterStack): InterpreterThread = {
val mutator = microVM.memoryManager.makeMutator() val mutator = microVM.memoryManager.makeMutator()
val id = makeThreadID() val id = makeThreadID()
val thr = new InterpreterThread(id, microVM, stack, mutator) val thr = new InterpreterThread(id, stack, mutator)
threadRegistry.put(id, thr) threadRegistry.put(id, thr)
thr thr
} }
......
...@@ -4,15 +4,10 @@ import com.typesafe.scalalogging.StrictLogging ...@@ -4,15 +4,10 @@ import com.typesafe.scalalogging.StrictLogging
import TypeSizes._ import TypeSizes._
object MemUtils extends StrictLogging { object MemUtils extends StrictLogging {
def zeroRegion(start: Word, length: Word)(implicit memorySupport: MemorySupport) { def zeroRegion(start: Word, length: Word)(implicit memorySupport: MemorySupport) {
val end = start + length val end = start + length
logger.debug("Zeroing [0x%x -> 0x%x] %d bytes".format(start, end, length)) logger.debug("Zeroing [0x%x -> 0x%x] %d bytes".format(start, end, length))
var a = start memorySupport.memset(start, length, 0)
while (a < end) {
memorySupport.storeLong(a, 0L)
a += WORD_SIZE_BYTES
}
} }
def memcpy(src: Word, dst: Word, length: Word)(implicit memorySupport: MemorySupport) { def memcpy(src: Word, dst: Word, length: Word)(implicit memorySupport: MemorySupport) {
......
...@@ -128,4 +128,8 @@ class MemorySupport(val muMemorySize: Word) { ...@@ -128,4 +128,8 @@ class MemorySupport(val muMemorySize: Word) {
storeI128(addr, desired, inMu) storeI128(addr, desired, inMu)
return oldVal return oldVal
} }
def memset(addr: Word, size: Word, value: Byte): Unit = {
theMemory.setMemory(addr, size, value)
}
} }
...@@ -28,6 +28,8 @@ class AllScanner(val handler: RefFieldHandler)( ...@@ -28,6 +28,8 @@ class AllScanner(val handler: RefFieldHandler)(
} }
private def traceRoots() { private def traceRoots() {
logger.debug("Tracing pin sets...")
tracePinSets()
logger.debug("Tracing external roots...") logger.debug("Tracing external roots...")
traceClientAgents() traceClientAgents()
logger.debug("Tracing globals...") logger.debug("Tracing globals...")
...@@ -36,6 +38,23 @@ class AllScanner(val handler: RefFieldHandler)( ...@@ -36,6 +38,23 @@ class AllScanner(val handler: RefFieldHandler)(
traceThreads() traceThreads()
} }
private def tracePinSets() {
logger.debug(s"Tracing client agents for pinned objects")
for (ca <- microVM.clientAgents) {
assert(ca != null)
assert(ca.pinSet != null)
for (addr <- ca.pinSet) {
this.pinSetToMem(addr)
}
}
for (thr <- microVM.threadStackManager.iterateAllLiveThreads) {
logger.debug(s"Tracing live thread ${thr.id} for pined objects")
for (addr <- thr.pinSet) {
this.pinSetToMem(addr)
}
}
}
private def traceClientAgents() { private def traceClientAgents() {
for (ca <- microVM.clientAgents; h <- ca.handles) { for (ca <- microVM.clientAgents; h <- ca.handles) {
h.vb match { h.vb match {
...@@ -131,4 +150,10 @@ class AllScanner(val handler: RefFieldHandler)( ...@@ -131,4 +150,10 @@ class AllScanner(val handler: RefFieldHandler)(
rv rv
} }
override def pinSetToMem(toObj: Word): Option[Word] = {
val rv = handler.pinSetToMem(toObj)
rv.foreach(addrQueue.add)
rv
}
} }
\ No newline at end of file
...@@ -32,6 +32,8 @@ trait RefFieldHandler { ...@@ -32,6 +32,8 @@ trait RefFieldHandler {
def stackToStackMem(stack: InterpreterStack, toObj: Word): Option[Word] def stackToStackMem(stack: InterpreterStack, toObj: Word): Option[Word]
/** An InterpreterThread referring to its stack. GC cannot rebind stacks. */ /** An InterpreterThread referring to its stack. GC cannot rebind stacks. */
def threadToStack(thread: InterpreterThread, toStack: Option[InterpreterStack]): Option[InterpreterStack] 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]
} }
object RefFieldUpdater { object RefFieldUpdater {
......
...@@ -81,6 +81,9 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, val space: SimpleImmixSpac ...@@ -81,6 +81,9 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, val space: SimpleImmixSpac
maybeMarkStackIfSome(toStack) maybeMarkStackIfSome(toStack)
} }
override def pinSetToMem(toObj: Word): Option[Word] = {
maybeMarkAndStatIfNotNull(toObj)
}
}) })
s1.scanAll() s1.scanAll()
...@@ -220,6 +223,14 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, val space: SimpleImmixSpac ...@@ -220,6 +223,14 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, val space: SimpleImmixSpac
maybeMarkStackIfSome(toStack) maybeMarkStackIfSome(toStack)
} }
override def pinSetToMem(toObj: Word): Option[Word] = {
if (space.isInSpace(toObj)) {
logger.debug("Object 0x%x is in small object space and is pinned. Marking block %d".format(toObj, space.objRefToBlockIndex(toObj)))
space.markBlockByObjRef(toObj, true)
}
maybeMoveIfNotNull(toObj, _ => throw new UvmRefImplException("Pinned object cannot move."))
}
private def maybeMoveIfNotNull(toObj: Word, updateFunc: Word => Unit): Option[Word] = { private def maybeMoveIfNotNull(toObj: Word, updateFunc: Word => Unit): Option[Word] = {
if (toObj != 0L) maybeMove(toObj, updateFunc) else None if (toObj != 0L) maybeMove(toObj, updateFunc) else None
} }
...@@ -243,8 +254,13 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, val space: SimpleImmixSpac ...@@ -243,8 +254,13 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, val space: SimpleImmixSpac
val isMovable = if (isInSmallObjectSpace) { val isMovable = if (isInSmallObjectSpace) {
val pageNum = space.objRefToBlockIndex(toObj) val pageNum = space.objRefToBlockIndex(toObj)
val stat = space.getStat(pageNum) if (space.isPinned(pageNum)) {
if (stat < threshold) true else false logger.debug("Object 0x%x is in pinned page %d, cannot move.".format(toObj, pageNum))
false
} else {
val stat = space.getStat(pageNum)
if (stat < threshold) true else false
}
} else { } else {
false false
} }
...@@ -351,6 +367,10 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, val space: SimpleImmixSpac ...@@ -351,6 +367,10 @@ class SimpleImmixCollector(val heap: SimpleImmixHeap, val space: SimpleImmixSpac
override def threadToStack(thread: InterpreterThread, toStack: Option[InterpreterStack]): Option[InterpreterStack] = { override def threadToStack(thread: InterpreterThread, toStack: Option[InterpreterStack]): Option[InterpreterStack] = {
clearStackMarkIfSome(toStack) clearStackMarkIfSome(toStack)
} }
override def pinSetToMem(toObj: Word): Option[Word] = {
clearMarkIfNotNull(toObj)
}
} }
private def clearMarkIfNotNull(objRef: Long): Option[Word] = { private def clearMarkIfNotNull(objRef: Long): Option[Word] = {
......
...@@ -13,6 +13,7 @@ object SimpleImmixSpace { ...@@ -13,6 +13,7 @@ object SimpleImmixSpace {
val BLOCK_MARKED = 0x1 val BLOCK_MARKED = 0x1
val BLOCK_RESERVED = 0x2