UvmOSRTests.scala 6.69 KB
Newer Older
Kunshan Wang's avatar
Kunshan Wang committed
1
package uvm.refimpl.osr
Kunshan Wang's avatar
Kunshan Wang committed
2 3 4 5 6 7 8 9 10 11 12

import org.scalatest._
import java.io.FileReader
import uvm._
import uvm.types._
import uvm.ssavariables._
import uvm.refimpl._
import uvm.refimpl.itpr._
import uvm.refimpl.mem._
import MemoryOrder._
import AtomicRMWOptr._
13
import uvm.refimpl.Word
14 15
import uvm.refimpl.TrapHandlerResult.{ ThreadExit, Rebind }
import uvm.refimpl.HowToResume.{ PassValues, ThrowExc }
Kunshan Wang's avatar
Kunshan Wang committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29

import ch.qos.logback.classic.Level._

class UvmOSRTests extends UvmBundleTesterBase {

  setLogLevels(
    ROOT_LOGGER_NAME -> INFO,
    //"uvm.refimpl.mem" -> DEBUG,
    "uvm.refimpl.itpr" -> DEBUG)

  preloadBundles("tests/uvm-refimpl-test/primitives.uir",
    "tests/uvm-refimpl-test/osr-tests.uir")

  "Stack introspection" should "see functions and keepalive value in all frames" in {
30
    val ctx = microVM.newContext()
Kunshan Wang's avatar
Kunshan Wang committed
31

32
    val func = ctx.handleFromFunc("@intro_test_base")
Kunshan Wang's avatar
Kunshan Wang committed
33

34
    val arg0 = ctx.handleFromInt64(3)
Kunshan Wang's avatar
Kunshan Wang committed
35

36
    testFunc(ctx, func, Seq(arg0)) { (ctx, th, st, wp) =>
37 38
      val fc = ctx.newCursor(st)
      nameOf(ctx.curInst(fc)) match {
39
        case "@intro_rec_v1.zero.trap_rec" => {
40 41 42
          val Seq(n0: MuIntValue) = ctx.dumpKeepalives(fc)

          ctx.handleToUInt(n0) shouldBe 0
Kunshan Wang's avatar
Kunshan Wang committed
43 44

          for (i <- 1 to 3) {
45 46 47 48 49 50 51
            ctx.nextFrame(fc)
            nameOf(ctx.curFunc(fc)) shouldBe "@intro_rec"
            nameOf(ctx.curFuncVer(fc)) shouldBe "@intro_rec_v1"
            nameOf(ctx.curInst(fc)) shouldBe "@intro_rec_v1.nz.call"
            val Seq(ni: MuIntValue, nm1i: MuIntValue) = ctx.dumpKeepalives(st, i)
            ctx.handleToUInt(ni) shouldBe i
            ctx.handleToUInt(nm1i) shouldBe (i - 1)
Kunshan Wang's avatar
Kunshan Wang committed
52 53
          }

54 55 56 57
          ctx.nextFrame(fc)
          nameOf(ctx.curInst(fc)) shouldBe "@intro_test_base_v1.entry.call"

          ctx.closeCursor(fc)
Kunshan Wang's avatar
Kunshan Wang committed
58

59
          Rebind(st, PassValues(Seq(n0)))
Kunshan Wang's avatar
Kunshan Wang committed
60 61 62 63
        }
      }
    }

64
    ctx.closeContext()
Kunshan Wang's avatar
Kunshan Wang committed
65 66 67
  }

  "@sum" should "give the sum when n < 5" in {
68
    val ctx = microVM.newContext()
Kunshan Wang's avatar
Kunshan Wang committed
69

70
    val func = ctx.handleFromFunc("@osr_test_base")
Kunshan Wang's avatar
Kunshan Wang committed
71

72
    val arg0 = ctx.handleFromInt64(4)
Kunshan Wang's avatar
Kunshan Wang committed
73

74
    testFunc(ctx, func, Seq(arg0)) { (ctx, th, st, wp) =>
75 76
      val fc = ctx.newCursor(st)
      nameOf(ctx.curInst(fc)) match {
77
        case "@osr_test_base_v1.entry.trap_base_exit" => {
78 79 80 81
          val Seq(rv: MuIntValue) = ctx.dumpKeepalives(fc)
          ctx.closeCursor(fc)

          ctx.handleToUInt(rv) shouldBe 6
Kunshan Wang's avatar
Kunshan Wang committed
82

83
          returnFromTrap(st)
Kunshan Wang's avatar
Kunshan Wang committed
84 85 86 87
        }
      }
    }

88
    ctx.closeContext()
Kunshan Wang's avatar
Kunshan Wang committed
89 90 91
  }

  "@sum" should "trigger trap when n >= 5 and work with OSR" in {
92
    val ctx = microVM.newContext()
Kunshan Wang's avatar
Kunshan Wang committed
93

94
    val func = ctx.handleFromFunc("@osr_test_base")
Kunshan Wang's avatar
Kunshan Wang committed
95

96
    val arg0 = ctx.handleFromInt64(8)
Kunshan Wang's avatar
Kunshan Wang committed
97

98
    testFunc(ctx, func, Seq(arg0)) { (ctx, th, st, wp) =>
99 100
      val fc = ctx.newCursor(st)
      nameOf(ctx.curInst(fc)) match {
101
        case "@sum_v1.opt.trap_opt" => {
102 103
          val Seq(n:MuIntValue, i:MuIntValue, s:MuIntValue) = ctx.dumpKeepalives(fc)
          ctx.closeCursor(fc)
104

105 106 107
          ctx.handleToUInt(s) shouldBe 10
          ctx.handleToUInt(i) shouldBe 5
          ctx.handleToUInt(n) shouldBe 8
Kunshan Wang's avatar
Kunshan Wang committed
108 109 110 111

          // Emulate optimising compiling by loading a pre-optimised version.
          val r = new FileReader("tests/uvm-refimpl-test/osr-tests-part2.uir")
          try {
112
            ctx.loadBundle(r)
Kunshan Wang's avatar
Kunshan Wang committed
113 114 115
          } finally {
            r.close()
          }
116

Kunshan Wang's avatar
Kunshan Wang committed
117
          // OSR
118 119
          ctx.nextFrame(fc)
          ctx.popFramesTo(fc)
120 121

          val oneShotFunc = ctx.handleFromFunc("@sum_osr_oneshot")
122 123 124
          ctx.pushFrame(fc, oneShotFunc)

          ctx.closeCursor(fc)
Kunshan Wang's avatar
Kunshan Wang committed
125 126

          // Continue
127
          Rebind(st, PassValues(Seq(s, i, n)))
Kunshan Wang's avatar
Kunshan Wang committed
128
        }
129
        case "@osr_test_base_v1.entry.trap_base_exit" => {
130 131 132 133
          val Seq(rv: MuIntValue) = ctx.dumpKeepalives(fc)
          ctx.closeCursor(fc)

          ctx.handleToUInt(rv) shouldBe 28
Kunshan Wang's avatar
Kunshan Wang committed
134

135
          returnFromTrap(st)
Kunshan Wang's avatar
Kunshan Wang committed
136 137 138
        }
      }
    }
139

Kunshan Wang's avatar
Kunshan Wang committed
140 141
    // The second time when it is called, it should call the second version
    // and OSR should be unnecessary.
142
    testFunc(ctx, func, Seq(arg0)) { (ctx, th, st, wp) =>
143 144
      val fc = ctx.newCursor(st)
      nameOf(ctx.curInst(fc)) match {
145
        case "@osr_test_base_v1.entry.trap_base_exit" => {
146 147 148 149
          val Seq(rv: MuIntValue) = ctx.dumpKeepalives(fc)
          ctx.closeCursor(fc)

          ctx.handleToUInt(rv) shouldBe 28
Kunshan Wang's avatar
Kunshan Wang committed
150

151
          returnFromTrap(st)
Kunshan Wang's avatar
Kunshan Wang committed
152 153 154
        }
      }
    }
155 156

    ctx.closeContext()
Kunshan Wang's avatar
Kunshan Wang committed
157
  }
158 159 160 161 162 163 164 165

  /**
   * @param funcs many functions. funcs(0) is the bottom function.
   * @param args arguments to the top function
   */
  def testFuncMulti(ctx: MuCtx, funcs: Seq[MuFuncRefValue], args: Seq[MuValue])(handler: TrapHandlerFunction): Unit = {
    microVM.setTrapHandler(new MockTrapHandler(handler))
    val hStack = ctx.newStack(funcs(0))
166
    val fc = ctx.newCursor(hStack)
167
    for (f <- funcs.tail) {
168
      ctx.pushFrame(fc, f)
169
    }
170
    ctx.closeCursor(fc)
171
    val hThread = ctx.newThread(hStack, None, uvm.refimpl.HowToResume.PassValues(args))
172 173 174 175 176 177 178 179 180 181 182 183
    microVM.execute()
  }

  "The return values" should "become the parameters of the previous frame" in {
    val ctx = microVM.newContext()

    val func1 = ctx.handleFromFunc("@consecutive_push_main")
    val func2 = ctx.handleFromFunc("@forty_two_returner")

    val arg0 = ctx.handleFromInt64(8)

    testFuncMulti(ctx, Seq(func1, func2), Seq()) { (ctx, th, st, wp) =>
184 185
      val fc = ctx.newCursor(st)
      nameOf(ctx.curInst(fc)) match {
186
        case "@consecutive_push_main.v1.entry.trap" => {
187 188
          val Seq(n: MuIntValue) = ctx.dumpKeepalives(fc)
          ctx.closeCursor(fc)
189 190

          ctx.handleToUInt(n) shouldBe 42
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211

          returnFromTrap(st)
        }
      }
    }

    ctx.closeContext()
  }

  "Multiple consecutively pushed frames" should "pass return values to their respective parent frames" in {
    val ctx = microVM.newContext()

    val func1 = ctx.handleFromFunc("@consecutive_push_main")
    val func2 = ctx.handleFromFunc("@forty_two_returner")
    val func3 = ctx.handleFromFunc("@add_one")

    val arg0 = ctx.handleFromInt64(8)

    var addOneReachCount = 0L

    testFuncMulti(ctx, Seq(func1, func3, func3, func3, func2), Seq()) { (ctx, th, st, wp) =>
212 213
      val fc = ctx.newCursor(st)
      nameOf(ctx.curInst(fc)) match {
214
        case "@add_one.v1.entry.trap" => {
215 216 217
          val Seq(n: MuIntValue, n2: MuIntValue) = ctx.dumpKeepalives(fc)
          ctx.closeCursor(fc)

218 219 220
          ctx.handleToSInt(n).toLong shouldBe (42L + addOneReachCount)
          ctx.handleToSInt(n2) shouldBe (42L + addOneReachCount + 1L)
          addOneReachCount += 1L
221

222 223 224
          returnFromTrap(st)
        }
        case "@consecutive_push_main.v1.entry.trap" => {
225 226
          val Seq(n: MuIntValue) = ctx.dumpKeepalives(fc)
          ctx.closeCursor(fc)
227 228 229

          ctx.handleToSInt(n).toLong shouldBe 45L

230 231 232 233
          returnFromTrap(st)
        }
      }
    }
234

235
    addOneReachCount shouldBe 3L
236 237 238

    ctx.closeContext()
  }
Kunshan Wang's avatar
Kunshan Wang committed
239
}