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.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.6% of users enabled 2FA.

Commit fea12c70 authored by Kunshan Wang's avatar Kunshan Wang
Browse files

Fixed gc, sum, big tests.

parent 76a66fcf
...@@ -7,5 +7,10 @@ $SED -i 's/NEWSTACK\s*<\(@\w\+\)>\s*\(@\w\+\)/COMMINST @uvm.new_stack <[\1]> (\2 ...@@ -7,5 +7,10 @@ $SED -i 's/NEWSTACK\s*<\(@\w\+\)>\s*\(@\w\+\)/COMMINST @uvm.new_stack <[\1]> (\2
$SED -i 's/COMMINST\s*@uvm\.new_thread\s*(\([@%]\w\+\))/NEWTHREAD \1 PASS_VALUES /g' $FN $SED -i 's/COMMINST\s*@uvm\.new_thread\s*(\([@%]\w\+\))/NEWTHREAD \1 PASS_VALUES /g' $FN
$SED -i 's/TRAP\s*<@void>/TRAP <>/g' $FN $SED -i 's/TRAP\s*<@void>/TRAP <>/g' $FN
$SED -i 's/noparamsnoret/v_v/g' $FN $SED -i 's/noparamsnoret/v_v/g' $FN
$SED -i 's/@void\s*(\([^)]*\))/(\1) -> ()/g' $FN #$SED -i 's/@void\s*(\([^)]*\))/(\1) -> ()/g' $FN
$SED -i '/\.funcsig/ {s/=\s*\(@\w\+\)\s*(\([^)]*\))/= (\2) -> (\1)/}' $FN
$SED -i 's/@funcdumb/@frv_v/g' $FN
$SED -i 's/@i_ii/@ii_i/g' $FN
$SED -i 's/RET @VOID/RET ()/g' $FN
$SED -i 's/hybrid\s*<@void\s*/hybrid</g' $FN
...@@ -84,7 +84,7 @@ class GlobalBundle extends Bundle { ...@@ -84,7 +84,7 @@ class GlobalBundle extends Bundle {
case e: NameConflictException => case e: NameConflictException =>
throw new IllegalRedefinitionException( throw new IllegalRedefinitionException(
"Redefinition of type, function signature, constant or" + "Redefinition of type, function signature, constant or" +
" global cell is not allowed", e); " global cell is not allowed: %s".format(cand.repr), e);
} }
} }
} }
......
...@@ -116,7 +116,13 @@ trait InterpreterThreadState { ...@@ -116,7 +116,13 @@ trait InterpreterThreadState {
protected def resultBoxes: Seq[ValueBox] = curInst.results.map(boxOf) protected def resultBoxes: Seq[ValueBox] = curInst.results.map(boxOf)
/** Get one result box of the current instruction. */ /** Get one result box of the current instruction. */
protected def resultBox(index: Int): ValueBox = boxOf(curInst.results(index)) protected def resultBox(index: Int): ValueBox = try {
boxOf(curInst.results(index))
} catch {
case e: IndexOutOfBoundsException => throw new UvmRefImplException(
"Instruction %s is declared to have only %d results. Result %d is requested.".format(
curInst, curInst.results.length, index), e)
}
} }
/** /**
......
...@@ -21,25 +21,34 @@ object MemoryDataScanner extends StrictLogging { ...@@ -21,25 +21,34 @@ object MemoryDataScanner extends StrictLogging {
val tag = HeaderUtils.getTag(objRef) val tag = HeaderUtils.getTag(objRef)
logger.debug("Obj 0x%x, tag 0x%x".format(objRef, tag)) logger.debug("Obj 0x%x, tag 0x%x".format(objRef, tag))
val ty = HeaderUtils.getType(microVM, tag) val ty = HeaderUtils.getType(microVM, tag)
logger.debug("Type: %s".format(ty.repr)) logger.debug {
if (ty.isInstanceOf[TypeHybrid]) {
val len = HeaderUtils.getVarLength(objRef)
val size = TypeSizes.hybridSizeOf(ty.asInstanceOf[TypeHybrid], len)
"Type: %s, varLen: %d, hybridSizeOf: %d".format(ty.repr, len, size)
} else {
"Type: %s".format(ty.repr)
}
}
scanField(ty, objRef, objRef, handler) 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: RefFieldHandler)(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)
ty match { ty match {
case t: TypeRef => { case t: TypeRef => {
val toObj = memorySupport.loadLong(iRef) val toObj = memorySupport.loadLong(iRef)
logger.debug(s"Ref field ${iRef} -> ${toObj}") logger.debug(logField("Ref", toObj))
handler.memToHeap(objRef, iRef, toObj, false, false) handler.memToHeap(objRef, iRef, toObj, false, false)
} }
case t: TypeIRef => { case t: TypeIRef => {
val toObj = memorySupport.loadLong(iRef) val toObj = memorySupport.loadLong(iRef)
logger.debug(s"IRef field ${iRef} -> ${toObj}") logger.debug(logField("IRef", toObj))
handler.memToHeap(objRef, iRef, toObj, false, false) handler.memToHeap(objRef, iRef, toObj, false, false)
} }
case t: TypeWeakRef => { case t: TypeWeakRef => {
val toObj = memorySupport.loadLong(iRef) val toObj = memorySupport.loadLong(iRef)
logger.debug(s"WeakRef field ${iRef} -> ${toObj}") logger.debug(logField("WeakRef", toObj))
handler.memToHeap(objRef, iRef, toObj, true, false) handler.memToHeap(objRef, iRef, toObj, true, false)
} }
case t: TypeTagRef64 => { case t: TypeTagRef64 => {
...@@ -47,16 +56,16 @@ object MemoryDataScanner extends StrictLogging { ...@@ -47,16 +56,16 @@ object MemoryDataScanner extends StrictLogging {
if (paranoiaLogger.underlying.isDebugEnabled()) { if (paranoiaLogger.underlying.isDebugEnabled()) {
paranoiaLogger.debug(s"Tagref bits ${bits}") paranoiaLogger.debug(s"Tagref bits ${bits}")
if (OpHelper.tr64IsFp(bits)) { if (OpHelper.tr64IsFp(bits)) {
paranoiaLogger.debug(s"Tagref is FP: ${OpHelper.tr64ToFp(bits)}") paranoiaLogger.debug("Tagref is FP: %f".format(OpHelper.tr64ToFp(bits)))
} else if (OpHelper.tr64IsInt(bits)) { } else if (OpHelper.tr64IsInt(bits)) {
paranoiaLogger.debug(s"Tagref is Int: ${OpHelper.tr64ToInt(bits)}") paranoiaLogger.debug("Tagref is Int: %d".format(OpHelper.tr64ToInt(bits)))
} else if (OpHelper.tr64IsRef(bits)) { } else if (OpHelper.tr64IsRef(bits)) {
paranoiaLogger.debug(s"Tagref is Ref: ${OpHelper.tr64ToRef(bits)} tag: ${OpHelper.tr64ToTag(bits)}") paranoiaLogger.debug("Tagref is Ref: 0x%x tag: %d".format(OpHelper.tr64ToRef(bits), OpHelper.tr64ToTag(bits)))
} }
} }
if (OpHelper.tr64IsRef(bits)) { if (OpHelper.tr64IsRef(bits)) {
val toObj = OpHelper.tr64ToRef(bits) val toObj = OpHelper.tr64ToRef(bits)
logger.debug(s"TagRef64 field ${iRef} -> ${toObj} tag: ${OpHelper.tr64ToTag(bits)}") logger.debug(logField("TagRef64", toObj))
handler.memToHeap(objRef, iRef, toObj, false, true) handler.memToHeap(objRef, iRef, toObj, false, true)
} }
} }
...@@ -92,9 +101,10 @@ object MemoryDataScanner extends StrictLogging { ...@@ -92,9 +101,10 @@ object MemoryDataScanner extends StrictLogging {
scanField(fieldTy, objRef, curAddr, handler) scanField(fieldTy, objRef, curAddr, handler)
curAddr += TypeSizes.sizeOf(fieldTy) curAddr += TypeSizes.sizeOf(fieldTy)
} }
curAddr = TypeSizes.alignUp(curAddr, varAlign)
for (i <- 0L until varLength) { for (i <- 0L until varLength) {
curAddr = TypeSizes.alignUp(curAddr + varSize, varAlign)
scanField(varTy, objRef, curAddr, handler) scanField(varTy, objRef, curAddr, handler)
curAddr = TypeSizes.alignUp(curAddr + varSize, varAlign)
} }
} }
case t: TypeStackRef => { case t: TypeStackRef => {
......
...@@ -45,6 +45,8 @@ case class InstResult(inst: Instruction, index: Int) extends LocalVariable ...@@ -45,6 +45,8 @@ case class InstResult(inst: Instruction, index: Int) extends LocalVariable
abstract class Instruction extends IdentifiedSettable { abstract class Instruction extends IdentifiedSettable {
var results: Seq[InstResult] = Seq() var results: Seq[InstResult] = Seq()
override def toString = "%s %s".format(this.repr, this.getClass.getSimpleName)
} }
/// enumerations /// enumerations
......
...@@ -19,7 +19,7 @@ class UvmInterpreterGCTests extends UvmBundleTesterBase { ...@@ -19,7 +19,7 @@ class UvmInterpreterGCTests extends UvmBundleTesterBase {
"uvm.refimpl.itpr" -> DEBUG, "uvm.refimpl.itpr" -> DEBUG,
"uvm.refimpl.mem" -> DEBUG) "uvm.refimpl.mem" -> DEBUG)
preloadBundles("tests/uvm-refimpl-test/gc-tests.uir") preloadBundles("tests/uvm-refimpl-test/primitives.uir", "tests/uvm-refimpl-test/gc-tests.uir")
def gc() = microVM.memoryManager.heap.mutatorTriggerAndWaitForGCEnd(false) def gc() = microVM.memoryManager.heap.mutatorTriggerAndWaitForGCEnd(false)
...@@ -40,176 +40,176 @@ class UvmInterpreterGCTests extends UvmBundleTesterBase { ...@@ -40,176 +40,176 @@ class UvmInterpreterGCTests extends UvmBundleTesterBase {
} }
"The memory manager" should "retain global reference between gc." in { "The memory manager" should "retain global reference between gc." in {
val ca = microVM.newClientAgent() val ctx = microVM.newContext()
val func = ca.putFunction("@keepglobal") val func = ctx.handleFromFunc("@keepglobal")
testFunc(ca, func, Seq()) { (ca, th, st, wp) => testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match { nameOf(ctx.curInst(st, 0)) match {
case "@keepglobal_v1.entry.gctrap" => { case "@keepglobal_v1.entry.gctrap" => {
gc() gc()
TrapRebindPassVoid(st) returnFromTrap(st)
} }
case "@keepglobal_v1.entry.checktrap" => { case "@keepglobal_v1.entry.checktrap" => {
val Seq(obj2, obj2val) = ca.dumpKeepalives(st, 0) val Seq(obj2, obj2val) = ctx.dumpKeepalives(st, 0)
obj2.vb.asRef shouldNot be(0L) obj2.vb.asRef shouldNot be(0L)
obj2val.vb.asSInt(64) shouldBe 42 obj2val.vb.asSInt(64) shouldBe 42
TrapRebindPassVoid(st) returnFromTrap(st)
} }
} }
} }
ca.close() ctx.closeContext()
} }
"The memory manager" should "not retain references in dead alloca cells between gc." in { "The memory manager" should "not retain references in dead alloca cells between gc." in {
val ca = microVM.newClientAgent() val ctx = microVM.newContext()
val func = ca.putFunction("@nokeepalloca") val func = ctx.handleFromFunc("@nokeepalloca")
testFunc(ca, func, Seq()) { (ca, th, st, wp) => testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match { nameOf(ctx.curInst(st, 0)) match {
case "@nokeepalloca_v1.entry.gctrap" => { case "@nokeepalloca_v1.entry.gctrap" => {
gc() gc()
TrapRebindPassVoid(st) returnFromTrap(st)
} }
case "@allocatest_v1.entry.gctrap" => { case "@allocatest_v1.entry.gctrap" => {
gc() gc()
TrapRebindPassVoid(st) returnFromTrap(st)
} }
} }
} }
ca.close() ctx.closeContext()
} }
"The large object space" should "withstand repeated non-retained allocations" in { "The large object space" should "withstand repeated non-retained allocations" in {
val ca = microVM.newClientAgent() val ctx = microVM.newContext()
quiet { quiet {
val func = ca.putFunction("@crazy_allocation_test") val func = ctx.handleFromFunc("@crazy_allocation_test")
testFunc(ca, func, Seq()) { (ca, th, st, wp) => testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
fail("No traps in this test") fail("No traps in this test")
} }
} }
ca.close() ctx.closeContext()
gc() gc()
} }
"The small object space" should "withstand repeated fragmented allocations" in { "The small object space" should "withstand repeated fragmented allocations" in {
val ca = microVM.newClientAgent() val ctx = microVM.newContext()
quiet { quiet {
val func = ca.putFunction("@breadcrumbs") val func = ctx.handleFromFunc("@breadcrumbs")
testFunc(ca, func, Seq()) { (ca, th, st, wp) => testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
fail("No traps in this test") fail("No traps in this test")
} }
} }
ca.close() ctx.closeContext()
gc() gc()
} }
"The garbage collector" should "nullify weak references if there is no strong references to the referent" in { "The garbage collector" should "nullify weak references if there is no strong references to the referent" in {
val ca = microVM.newClientAgent() val ctx = microVM.newContext()
val func = ca.putFunction("@testweakref") val func = ctx.handleFromFunc("@testweakref")
testFunc(ca, func, Seq()) { (ca, th, st, wp) => testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match { nameOf(ctx.curInst(st, 0)) match {
case "@testweakref_v1.entry.gctrap" => { case "@testweakref_v1.entry.gctrap" => {
gc() gc()
TrapRebindPassVoid(st) returnFromTrap(st)
} }
case "@peekweakref_v1.entry.checknztrap" => { case "@peekweakref_v1.entry.checknztrap" => {
val Seq(refval) = ca.dumpKeepalives(st, 0) val Seq(refval) = ctx.dumpKeepalives(st, 0)
refval.vb.asRef shouldNot be(0L) refval.vb.asRef shouldNot be(0L)
TrapRebindPassVoid(st) returnFromTrap(st)
} }
case "@testweakref_v1.entry.checkztrap" => { case "@testweakref_v1.entry.checkztrap" => {
val Seq(refval) = ca.dumpKeepalives(st, 0) val Seq(refval) = ctx.dumpKeepalives(st, 0)
refval.vb.asRef should be(0L) refval.vb.asRef should be(0L)
TrapRebindPassVoid(st) returnFromTrap(st)
} }
} }
} }
ca.close() ctx.closeContext()
gc() gc()
} }
"The garbage collector" should "treat tagref64 as reference when it actually is" in { "The garbage collector" should "treat tagref64 as reference when it actually is" in {
val ca = microVM.newClientAgent() val ctx = microVM.newContext()
val func = ca.putFunction("@testtagrefgc") val func = ctx.handleFromFunc("@testtagrefgc")
testFunc(ca, func, Seq()) { (ca, th, st, wp) => testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match { nameOf(ctx.curInst(st, 0)) match {
case "@testtagrefgc_v1.entry.gctrap" => { case "@testtagrefgc_v1.entry.gctrap" => {
gc() gc()
TrapRebindPassVoid(st) returnFromTrap(st)
} }
case "@testtagrefgc_v1.entry.checktrap" => { case "@testtagrefgc_v1.entry.checktrap" => {
val Seq(tr, refv, tagv, iv) = ca.dumpKeepalives(st, 0) val Seq(tr, refv, tagv, iv) = ctx.dumpKeepalives(st, 0)
ca.toInt(tagv) shouldBe 13 ctx.handleToUInt(tagv.asInstanceOf[MuIntValue]) shouldBe 13
ca.toInt(iv) shouldBe 42 ctx.handleToUInt(iv.asInstanceOf[MuIntValue]) shouldBe 42
TrapRebindPassVoid(st) returnFromTrap(st)
} }
} }
} }
ca.close() ctx.closeContext()
gc() gc()
} }
"The garbage collector" should "scan tagref64 references in the memory" in { "The garbage collector" should "scan tagref64 references in the memory" in {
val ca = microVM.newClientAgent() val ctx = microVM.newContext()
val func = ca.putFunction("@testtagrefgcmem") val func = ctx.handleFromFunc("@testtagrefgcmem")
testFunc(ca, func, Seq()) { (ca, th, st, wp) => testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match { nameOf(ctx.curInst(st, 0)) match {
case "@testtagrefgcmem_v1.entry.gctrap" => { case "@testtagrefgcmem_v1.entry.gctrap" => {
gc() gc()
TrapRebindPassVoid(st) returnFromTrap(st)
} }
case "@testtagrefgcmem_v1.entry.checktrap" => { case "@testtagrefgcmem_v1.entry.checktrap" => {
val Seq(tr, refv, tagv, iv) = ca.dumpKeepalives(st, 0) val Seq(tr, refv, tagv, iv) = ctx.dumpKeepalives(st, 0)
ca.toInt(tagv) shouldBe 13 ctx.handleToUInt(tagv.asInstanceOf[MuIntValue]) shouldBe 13
ca.toInt(iv) shouldBe 42 ctx.handleToUInt(iv.asInstanceOf[MuIntValue]) shouldBe 42
TrapRebindPassVoid(st) returnFromTrap(st)
} }
} }
} }
ca.close() ctx.closeContext()
gc() gc()
} }
"The small object space" should "withstand repeated fragmented allocations when objects are referred by tagref64" in { "The small object space" should "withstand repeated fragmented allocations when objects are referred by tagref64" in {
val ca = microVM.newClientAgent() val ctx = microVM.newContext()
quiet { quiet {
val func = ca.putFunction("@breadcrumbstr64") val func = ctx.handleFromFunc("@breadcrumbstr64")
testFunc(ca, func, Seq()) { (ca, th, st, wp) => testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
fail("No traps in this test") fail("No traps in this test")
} }
} }
ca.close() ctx.closeContext()
gc() gc()
} }
......
package uvm.refimpl.itpr package uvm.refimpl.itpr
import org.scalatest._ import org.scalatest._
import java.io.FileReader
import ch.qos.logback.classic.Level._
import uvm._ import uvm._
import uvm.types._
import uvm.ssavariables._
import uvm.refimpl._ import uvm.refimpl._
import uvm.refimpl.itpr._
import MemoryOrder._
import AtomicRMWOptr._
import uvm.refimpl.mem.TypeSizes.Word
import ch.qos.logback.classic.Level._
import uvm.refimpl.UvmBundleTesterBase import uvm.refimpl.UvmBundleTesterBase
import uvm.refimpl.itpr._
import uvm.ssavariables._
import uvm.ssavariables.AtomicRMWOptr._
import uvm.ssavariables.MemoryOrder._
import uvm.types._
class UvmInterpreterSimpleSumTest extends UvmBundleTesterBase { class UvmInterpreterSimpleSumTest extends UvmBundleTesterBase {
setLogLevels( setLogLevels(
...@@ -22,39 +21,39 @@ class UvmInterpreterSimpleSumTest extends UvmBundleTesterBase { ...@@ -22,39 +21,39 @@ class UvmInterpreterSimpleSumTest extends UvmBundleTesterBase {
"tests/uvm-refimpl-test/simple-sum.uir") "tests/uvm-refimpl-test/simple-sum.uir")
"Simple sum" should "work" in { "Simple sum" should "work" in {
val ca = microVM.newClientAgent() val ctx = microVM.newContext()
val from = 1L val from = 1L
val to = 1000000L val to = 1000000L
val expectedSum = (from + to) * (to - from + 1L) / 2L val expectedSum = (from + to) * (to - from + 1L) / 2L
val hFrom = ca.putInt("@i64", from) val hFrom = ctx.handleFromInt64(from)
val hTo = ca.putInt("@i64", to) val hTo = ctx.handleFromInt64(to)
val func = ca.putFunction("@simplesum") val func = ctx.handleFromFunc("@simplesum")
var t1: Long = 0L var t1: Long = 0L
var t2: Long = 0L var t2: Long = 0L
testFunc(ca, func, Seq(hFrom, hTo)) { (ca, th, st, wp) => testFunc(ctx, func, Seq(hFrom, hTo)) { (ctx, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match { nameOf(ctx.curInst(st, 0)) match {
case "@simplesum_v1.entry.starttrap" => { case "@simplesum_v1.entry.starttrap" => {
t1 = System.currentTimeMillis()