Commit fea12c70 authored by Kunshan Wang's avatar Kunshan Wang

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
$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/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 {
case e: NameConflictException =>
throw new IllegalRedefinitionException(
"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 {
protected def resultBoxes: Seq[ValueBox] = curInst.results.map(boxOf)
/** 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 {
val tag = HeaderUtils.getTag(objRef)
logger.debug("Obj 0x%x, tag 0x%x".format(objRef, 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)
}
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 {
case t: TypeRef => {
val toObj = memorySupport.loadLong(iRef)
logger.debug(s"Ref field ${iRef} -> ${toObj}")
logger.debug(logField("Ref", toObj))
handler.memToHeap(objRef, iRef, toObj, false, false)
}
case t: TypeIRef => {
val toObj = memorySupport.loadLong(iRef)
logger.debug(s"IRef field ${iRef} -> ${toObj}")
logger.debug(logField("IRef", toObj))
handler.memToHeap(objRef, iRef, toObj, false, false)
}
case t: TypeWeakRef => {
val toObj = memorySupport.loadLong(iRef)
logger.debug(s"WeakRef field ${iRef} -> ${toObj}")
logger.debug(logField("WeakRef", toObj))
handler.memToHeap(objRef, iRef, toObj, true, false)
}
case t: TypeTagRef64 => {
......@@ -47,16 +56,16 @@ object MemoryDataScanner extends StrictLogging {
if (paranoiaLogger.underlying.isDebugEnabled()) {
paranoiaLogger.debug(s"Tagref bits ${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)) {
paranoiaLogger.debug(s"Tagref is Int: ${OpHelper.tr64ToInt(bits)}")
paranoiaLogger.debug("Tagref is Int: %d".format(OpHelper.tr64ToInt(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)) {
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)
}
}
......@@ -92,9 +101,10 @@ object MemoryDataScanner extends StrictLogging {
scanField(fieldTy, objRef, curAddr, handler)
curAddr += TypeSizes.sizeOf(fieldTy)
}
curAddr = TypeSizes.alignUp(curAddr, varAlign)
for (i <- 0L until varLength) {
curAddr = TypeSizes.alignUp(curAddr + varSize, varAlign)
scanField(varTy, objRef, curAddr, handler)
curAddr = TypeSizes.alignUp(curAddr + varSize, varAlign)
}
}
case t: TypeStackRef => {
......
......@@ -45,6 +45,8 @@ case class InstResult(inst: Instruction, index: Int) extends LocalVariable
abstract class Instruction extends IdentifiedSettable {
var results: Seq[InstResult] = Seq()
override def toString = "%s %s".format(this.repr, this.getClass.getSimpleName)
}
/// enumerations
......
......@@ -19,7 +19,7 @@ class UvmInterpreterGCTests extends UvmBundleTesterBase {
"uvm.refimpl.itpr" -> 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)
......@@ -40,176 +40,176 @@ class UvmInterpreterGCTests extends UvmBundleTesterBase {
}
"The memory manager" should "retain global reference between gc." in {
val ca = microVM.newClientAgent()
val ctx = microVM.newContext()
val func = ca.putFunction("@keepglobal")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match {
val func = ctx.handleFromFunc("@keepglobal")
testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
nameOf(ctx.curInst(st, 0)) match {
case "@keepglobal_v1.entry.gctrap" => {
gc()
TrapRebindPassVoid(st)
returnFromTrap(st)
}
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)
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 {
val ca = microVM.newClientAgent()
val ctx = microVM.newContext()
val func = ca.putFunction("@nokeepalloca")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match {
val func = ctx.handleFromFunc("@nokeepalloca")
testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
nameOf(ctx.curInst(st, 0)) match {
case "@nokeepalloca_v1.entry.gctrap" => {
gc()
TrapRebindPassVoid(st)
returnFromTrap(st)
}
case "@allocatest_v1.entry.gctrap" => {
gc()
TrapRebindPassVoid(st)
returnFromTrap(st)
}
}
}
ca.close()
ctx.closeContext()
}
"The large object space" should "withstand repeated non-retained allocations" in {
val ca = microVM.newClientAgent()
val ctx = microVM.newContext()
quiet {
val func = ca.putFunction("@crazy_allocation_test")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
val func = ctx.handleFromFunc("@crazy_allocation_test")
testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
fail("No traps in this test")
}
}
ca.close()
ctx.closeContext()
gc()
}
"The small object space" should "withstand repeated fragmented allocations" in {
val ca = microVM.newClientAgent()
val ctx = microVM.newContext()
quiet {
val func = ca.putFunction("@breadcrumbs")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
val func = ctx.handleFromFunc("@breadcrumbs")
testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
fail("No traps in this test")
}
}
ca.close()
ctx.closeContext()
gc()
}
"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")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match {
val func = ctx.handleFromFunc("@testweakref")
testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
nameOf(ctx.curInst(st, 0)) match {
case "@testweakref_v1.entry.gctrap" => {
gc()
TrapRebindPassVoid(st)
returnFromTrap(st)
}
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)
TrapRebindPassVoid(st)
returnFromTrap(st)
}
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)
TrapRebindPassVoid(st)
returnFromTrap(st)
}
}
}
ca.close()
ctx.closeContext()
gc()
}
"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")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match {
val func = ctx.handleFromFunc("@testtagrefgc")
testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
nameOf(ctx.curInst(st, 0)) match {
case "@testtagrefgc_v1.entry.gctrap" => {
gc()
TrapRebindPassVoid(st)
returnFromTrap(st)
}
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
ca.toInt(iv) shouldBe 42
ctx.handleToUInt(tagv.asInstanceOf[MuIntValue]) shouldBe 13
ctx.handleToUInt(iv.asInstanceOf[MuIntValue]) shouldBe 42
TrapRebindPassVoid(st)
returnFromTrap(st)
}
}
}
ca.close()
ctx.closeContext()
gc()
}
"The garbage collector" should "scan tagref64 references in the memory" in {
val ca = microVM.newClientAgent()
val ctx = microVM.newContext()
val func = ca.putFunction("@testtagrefgcmem")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match {
val func = ctx.handleFromFunc("@testtagrefgcmem")
testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
nameOf(ctx.curInst(st, 0)) match {
case "@testtagrefgcmem_v1.entry.gctrap" => {
gc()
TrapRebindPassVoid(st)
returnFromTrap(st)
}
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
ca.toInt(iv) shouldBe 42
ctx.handleToUInt(tagv.asInstanceOf[MuIntValue]) shouldBe 13
ctx.handleToUInt(iv.asInstanceOf[MuIntValue]) shouldBe 42
TrapRebindPassVoid(st)
returnFromTrap(st)
}
}
}
ca.close()
ctx.closeContext()
gc()
}
"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 {
val func = ca.putFunction("@breadcrumbstr64")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
val func = ctx.handleFromFunc("@breadcrumbstr64")
testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
fail("No traps in this test")
}
}
ca.close()
ctx.closeContext()
gc()
}
......
package uvm.refimpl.itpr
import org.scalatest._
import java.io.FileReader
import ch.qos.logback.classic.Level._
import uvm._
import uvm.types._
import uvm.ssavariables._
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.itpr._
import uvm.ssavariables._
import uvm.ssavariables.AtomicRMWOptr._
import uvm.ssavariables.MemoryOrder._
import uvm.types._
class UvmInterpreterSimpleSumTest extends UvmBundleTesterBase {
setLogLevels(
......@@ -22,39 +21,39 @@ class UvmInterpreterSimpleSumTest extends UvmBundleTesterBase {
"tests/uvm-refimpl-test/simple-sum.uir")
"Simple sum" should "work" in {
val ca = microVM.newClientAgent()
val ctx = microVM.newContext()
val from = 1L
val to = 1000000L
val expectedSum = (from + to) * (to - from + 1L) / 2L
val hFrom = ca.putInt("@i64", from)
val hTo = ca.putInt("@i64", to)
val hFrom = ctx.handleFromInt64(from)
val hTo = ctx.handleFromInt64(to)
val func = ca.putFunction("@simplesum")
val func = ctx.handleFromFunc("@simplesum")
var t1: Long = 0L
var t2: Long = 0L
testFunc(ca, func, Seq(hFrom, hTo)) { (ca, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match {
testFunc(ctx, func, Seq(hFrom, hTo)) { (ctx, th, st, wp) =>
nameOf(ctx.curInst(st, 0)) match {
case "@simplesum_v1.entry.starttrap" => {
t1 = System.currentTimeMillis()
TrapRebindPassVoid(st)
returnFromTrap(st)
}
case "@simplesum_v1.exit.exittrap" => {
t2 = System.currentTimeMillis()
val Seq(sum) = ca.dumpKeepalives(st, 0)
val Seq(sum) = ctx.dumpKeepalives(st, 0)
sum.vb.asSInt(64) shouldBe expectedSum
TrapRebindPassVoid(st)
returnFromTrap(st)
}
}
}
ca.close()
ctx.closeContext()
val timeDiff = t2 - t1
printf("Time: %d ms".format(timeDiff))
......
......@@ -19,7 +19,7 @@ class UvmInterpreterStackGCTests extends UvmBundleTesterBase {
"uvm.refimpl.itpr" -> 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)
......@@ -43,20 +43,20 @@ class UvmInterpreterStackGCTests extends UvmBundleTesterBase {
override def makeMicroVM = new MicroVM(heapSize = 2L * 1024L * 1024L, stackSize = 63L * 1024L)
"The memory manager" should "collect unreachable stacks." in {
val ca = microVM.newClientAgent()
val ctx = microVM.newContext()
val nStacks = ca.putInt("@i64", 13)
val nStacks = ctx.handleFromInt64( 13)
val func = ca.putFunction("@stackcollecttest")
testFunc(ca, func, Seq(nStacks)) { (ca, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match {
val func = ctx.handleFromFunc("@stackcollecttest")
testFunc(ctx, func, Seq(nStacks)) { (ctx, th, st, wp) =>
nameOf(ctx.curInst(st, 0)) match {
case "@stackcollecttest_v1.endloop.trap" => {
gc()
TrapRebindPassVoid(st)
returnFromTrap(st)
}
}
}
ca.close()
ctx.closeContext()
}
}
\ No newline at end of file
......@@ -22,56 +22,55 @@ class UvmInterpreterTestBigFunc extends UvmBundleTesterBase {
preloadBundles("tests/uvm-refimpl-test/extra-big-func.uir")
"The extra big function" should "execute properly" in {
val ca = microVM.newClientAgent()
val ctx = microVM.newContext()
val func = ca.putFunction("@big")
val hParam = ca.putInt("@i64", 0)
val func = ctx.handleFromFunc("@big")
val hParam = ctx.handleFromInt64(0)
testFunc(ca, func, Seq(hParam)) { (ca, th, st, wp) =>
val Seq(i) = ca.dumpKeepalives(st, 0)
testFunc(ctx, func, Seq(hParam)) { (ctx, th, st, wp) =>
val Seq(i) = ctx.dumpKeepalives(st, 0)
ca.toInt(i, true) shouldEqual 200
ctx.handleToSInt(i.asInstanceOf[MuIntValue]) shouldEqual 200
TrapRebindPassVoid(st)
returnFromTrap(st)
}
ca.close()
ctx.closeContext()
}
"The Micro VM" should "sustain frequent bundle loading" in {
val ca = microVM.newClientAgent()
for(i <- 0 until 1000) {
val ctx = microVM.newContext()
for (i <- 0 until 1000) {
val miniBundle = s".global @h${i} <@i64>"
ca.loadBundle(miniBundle)
ctx.loadBundle(miniBundle)
}
val sb = new StringBuilder()
sb ++= ".funcdef @bigger VERSION @bigger.v1 <@big.sig> {\n"
sb ++= " %entry(<@i64> %p):\n"
for(i <- 0 until 1000) {
sb ++= s" %r${i} = STORE <@i64> @h${i} %p\n"
for (i <- 0 until 1000) {
sb ++= s" [%s${i}] STORE <@i64> @h${i} %p\n"
}
sb ++= " TRAP <@void>\n"
sb ++= " TRAP <>\n"
sb ++= " COMMINST @uvm.thread_exit\n"
sb ++= "}"
ca.loadBundle(sb.toString())
val func = ca.putFunction("@bigger")
val hParam = ca.putInt("@i64", 42)
testFunc(ca, func, Seq(hParam)) { (ca, th, st, wp) =>
val hr = ca.putGlobal("@h12")
val hv = ca.load(MemoryOrder.NOT_ATOMIC, hr)
val v = ca.toInt(hv, true).toInt
ctx.loadBundle(sb.toString())
val func = ctx.handleFromFunc("@bigger")
val hParam = ctx.handleFromInt64(42)
testFunc(ctx, func, Seq(hParam)) { (ctx, th, st, wp) =>
val hr = ctx.handleFromGlobal("@h12")
val hv = ctx.load(MemoryOrder.NOT_ATOMIC, hr)
val v = ctx.handleToSInt(hv.asInstanceOf[MuIntValue]).toInt
v shouldEqual 42
TrapRebindPassVoid(st)
returnFromTrap(st)
}
ca.close()
ctx.closeContext()
}
}
\ No newline at end of file
.typedef @i64 = int<64>
.typedef @void = void
.const @I64_1 <@i64> = 1
......@@ -105,7 +104,7 @@
.global @g99 <@i64>
.funcsig @big.sig = @void (@i64)
.funcsig @big.sig = (@i64) -> ()
.funcdef @big VERSION @big_v1 <@big.sig> {
%entry(<@i64> %p):
%i0 = ADD <@i64> %p @I64_1
......@@ -339,6 +338,6 @@
%r28 = LOAD <@i64> @g28
%r29 = LOAD <@i64> @g29
%trap = TRAP <@void> KEEPALIVE (%i199)
[%trap] TRAP <> KEEPALIVE (%i199)
COMMINST @uvm.thread_exit
}
This diff is collapsed.
// require "primitives.uir"
.funcsig @simplesum_sig = @void (@i64 @i64)
.funcsig @simplesum_sig = (@i64 @i64) -> (@void)
.funcdef @simplesum VERSION @simplesum_v1 <@simplesum_sig> {
%entry (<@i64> %from <@i64> %to):
%starttrap = TRAP <@void>
[%starttrap] TRAP <>
BRANCH %head(@I64_0 %from %to)
%head(<@i64> %sum <@i64> %i <@i64> %to):
......@@ -14,9 +14,9 @@
%sum2 = ADD <@i64> %sum %i
%i2 = ADD <@i64> %i @I64_1
BRANCH %head(%sum2 %i2 %to)
//%montrap = TRAP <@void> %head %head KEEPALIVE (%from %to %sum %i %le %sum2 %i2)
//[%montrap] TRAP <> %head %head KEEPALIVE (%from %to %sum %i %le %sum2 %i2)
%exit(<@i64> %sum):
%exittrap = TRAP <@void> KEEPALIVE (%sum)
[%exittrap] TRAP <> KEEPALIVE (%sum)
COMMINST @uvm.thread_exit
}
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