Optimize cmd VM with scoped slot addressing
This commit is contained in:
1 parent
7de856fc62
commit
bef94d3bc5
30 files changed
+2829
-1721
No files matched your search
+29
-29
@@ -19,10 +19,10 @@ import net.sergeych.lyng.IfStatement
|
||||
import net.sergeych.lyng.Pos
|
||||
import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.Statement
|
||||
import net.sergeych.lyng.bytecode.BytecodeBuilder
|
||||
import net.sergeych.lyng.bytecode.CmdBuilder
|
||||
import net.sergeych.lyng.bytecode.BytecodeCompiler
|
||||
import net.sergeych.lyng.bytecode.BytecodeConst
|
||||
import net.sergeych.lyng.bytecode.BytecodeVm
|
||||
import net.sergeych.lyng.bytecode.CmdVm
|
||||
import net.sergeych.lyng.bytecode.Opcode
|
||||
import net.sergeych.lyng.obj.BinaryOpRef
|
||||
import net.sergeych.lyng.obj.BinOp
|
||||
@@ -45,10 +45,10 @@ import net.sergeych.lyng.obj.toLong
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class BytecodeVmTest {
|
||||
class CmdVmTest {
|
||||
@Test
|
||||
fun addsIntConstants() = kotlinx.coroutines.test.runTest {
|
||||
val builder = BytecodeBuilder()
|
||||
val builder = CmdBuilder()
|
||||
val k0 = builder.addConst(BytecodeConst.IntVal(2))
|
||||
val k1 = builder.addConst(BytecodeConst.IntVal(3))
|
||||
builder.emit(Opcode.CONST_INT, k0, 0)
|
||||
@@ -56,7 +56,7 @@ class BytecodeVmTest {
|
||||
builder.emit(Opcode.ADD_INT, 0, 1, 2)
|
||||
builder.emit(Opcode.RET, 2)
|
||||
val fn = builder.build("addInts", localCount = 3)
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(5, result.toInt())
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ class BytecodeVmTest {
|
||||
)
|
||||
val ifStmt = IfStatement(cond, thenStmt, elseStmt, net.sergeych.lyng.Pos.builtIn)
|
||||
val fn = BytecodeCompiler().compileStatement("ifTest", ifStmt) ?: error("bytecode compile failed")
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(10, result.toInt())
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ class BytecodeVmTest {
|
||||
error("bytecode compile failed for ifNoElse")
|
||||
}
|
||||
}!!
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(ObjVoid, result)
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val fn = BytecodeCompiler().compileExpression("andShort", expr) ?: error("bytecode compile failed")
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(false, result.toBool())
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val fn = BytecodeCompiler().compileExpression("orShort", expr) ?: error("bytecode compile failed")
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(true, result.toBool())
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val fn = BytecodeCompiler().compileExpression("realPlus", expr) ?: error("bytecode compile failed")
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(5.75, result.toDouble())
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ class BytecodeVmTest {
|
||||
scope.args[0].toLong() + scope.args[1].toLong()
|
||||
)
|
||||
}
|
||||
val builder = BytecodeBuilder()
|
||||
val builder = CmdBuilder()
|
||||
val fnId = builder.addConst(BytecodeConst.ObjRef(callable))
|
||||
val arg0 = builder.addConst(BytecodeConst.IntVal(2L))
|
||||
val arg1 = builder.addConst(BytecodeConst.IntVal(3L))
|
||||
@@ -173,7 +173,7 @@ class BytecodeVmTest {
|
||||
builder.emit(Opcode.CALL_SLOT, 0, 1, 2, 3)
|
||||
builder.emit(Opcode.RET, 3)
|
||||
val fn = builder.build("callSlot", localCount = 4)
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(5, result.toInt())
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val ltFn = BytecodeCompiler().compileExpression("mixedLt", ltExpr) ?: error("bytecode compile failed")
|
||||
val ltResult = BytecodeVm().execute(ltFn, Scope(), emptyList())
|
||||
val ltResult = CmdVm().execute(ltFn, Scope(), emptyList())
|
||||
assertEquals(true, ltResult.toBool())
|
||||
|
||||
val eqExpr = ExpressionStatement(
|
||||
@@ -200,7 +200,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val eqFn = BytecodeCompiler().compileExpression("mixedEq", eqExpr) ?: error("bytecode compile failed")
|
||||
val eqResult = BytecodeVm().execute(eqFn, Scope(), emptyList())
|
||||
val eqResult = CmdVm().execute(eqFn, Scope(), emptyList())
|
||||
assertEquals(true, eqResult.toBool())
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ class BytecodeVmTest {
|
||||
)
|
||||
val expr = ExpressionStatement(callRef, Pos.builtIn)
|
||||
val fn = BytecodeCompiler().compileExpression("tailBlockArgs", expr) ?: error("bytecode compile failed")
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(true, result.toBool())
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ class BytecodeVmTest {
|
||||
)
|
||||
val expr = ExpressionStatement(callRef, Pos.builtIn)
|
||||
val fn = BytecodeCompiler().compileExpression("namedArgs", expr) ?: error("bytecode compile failed")
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(5, result.toInt())
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ class BytecodeVmTest {
|
||||
)
|
||||
val expr = ExpressionStatement(callRef, Pos.builtIn)
|
||||
val fn = BytecodeCompiler().compileExpression("splatArgs", expr) ?: error("bytecode compile failed")
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(3, result.toInt())
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val fn = BytecodeCompiler().compileExpression("mixedPlus", expr) ?: error("bytecode compile failed")
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(5.5, result.toDouble())
|
||||
}
|
||||
|
||||
@@ -305,13 +305,13 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val fn = BytecodeCompiler().compileExpression("mixedNeq", expr) ?: error("bytecode compile failed")
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(true, result.toBool())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun localSlotTypeTrackingEnablesArithmetic() = kotlinx.coroutines.test.runTest {
|
||||
val slotRef = LocalSlotRef("a", 0, 0, true, false, net.sergeych.lyng.Pos.builtIn)
|
||||
val slotRef = LocalSlotRef("a", 0, 0, 0, true, false, net.sergeych.lyng.Pos.builtIn)
|
||||
val assign = AssignRef(
|
||||
slotRef,
|
||||
ConstRef(ObjInt.of(2).asReadonly),
|
||||
@@ -327,13 +327,13 @@ class BytecodeVmTest {
|
||||
)
|
||||
val fn = BytecodeCompiler().compileExpression("localSlotAdd", expr) ?: error("bytecode compile failed")
|
||||
val scope = Scope().apply { applySlotPlan(mapOf("a" to 0)) }
|
||||
val result = BytecodeVm().execute(fn, scope, emptyList())
|
||||
val result = CmdVm().execute(fn, scope, emptyList())
|
||||
assertEquals(4, result.toInt())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parentScopeSlotAccessWorks() = kotlinx.coroutines.test.runTest {
|
||||
val parentRef = LocalSlotRef("a", 0, 1, true, false, net.sergeych.lyng.Pos.builtIn)
|
||||
val parentRef = LocalSlotRef("a", 0, 1, 0, true, false, net.sergeych.lyng.Pos.builtIn)
|
||||
val expr = ExpressionStatement(
|
||||
BinaryOpRef(
|
||||
BinOp.PLUS,
|
||||
@@ -348,7 +348,7 @@ class BytecodeVmTest {
|
||||
setSlotValue(0, ObjInt.of(3))
|
||||
}
|
||||
val child = Scope(parent)
|
||||
val result = BytecodeVm().execute(fn, child, emptyList())
|
||||
val result = CmdVm().execute(fn, child, emptyList())
|
||||
assertEquals(5, result.toInt())
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val fn = BytecodeCompiler().compileExpression("objEq", expr) ?: error("bytecode compile failed")
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals(true, result.toBool())
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val eqFn = BytecodeCompiler().compileExpression("objRefEq", eqExpr) ?: error("bytecode compile failed")
|
||||
val eqResult = BytecodeVm().execute(eqFn, Scope(), emptyList())
|
||||
val eqResult = CmdVm().execute(eqFn, Scope(), emptyList())
|
||||
assertEquals(true, eqResult.toBool())
|
||||
|
||||
val neqExpr = ExpressionStatement(
|
||||
@@ -391,7 +391,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val neqFn = BytecodeCompiler().compileExpression("objRefNeq", neqExpr) ?: error("bytecode compile failed")
|
||||
val neqResult = BytecodeVm().execute(neqFn, Scope(), emptyList())
|
||||
val neqResult = CmdVm().execute(neqFn, Scope(), emptyList())
|
||||
assertEquals(true, neqResult.toBool())
|
||||
}
|
||||
|
||||
@@ -406,7 +406,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val ltFn = BytecodeCompiler().compileExpression("objLt", ltExpr) ?: error("bytecode compile failed")
|
||||
val ltResult = BytecodeVm().execute(ltFn, Scope(), emptyList())
|
||||
val ltResult = CmdVm().execute(ltFn, Scope(), emptyList())
|
||||
assertEquals(true, ltResult.toBool())
|
||||
|
||||
val gteExpr = ExpressionStatement(
|
||||
@@ -418,7 +418,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val gteFn = BytecodeCompiler().compileExpression("objGte", gteExpr) ?: error("bytecode compile failed")
|
||||
val gteResult = BytecodeVm().execute(gteFn, Scope(), emptyList())
|
||||
val gteResult = CmdVm().execute(gteFn, Scope(), emptyList())
|
||||
assertEquals(true, gteResult.toBool())
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ class BytecodeVmTest {
|
||||
net.sergeych.lyng.Pos.builtIn
|
||||
)
|
||||
val fn = BytecodeCompiler().compileExpression("objPlus", expr) ?: error("bytecode compile failed")
|
||||
val result = BytecodeVm().execute(fn, Scope(), emptyList())
|
||||
val result = CmdVm().execute(fn, Scope(), emptyList())
|
||||
assertEquals("ab", (result as ObjString).value)
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import net.sergeych.lyng.Compiler
|
||||
import net.sergeych.lyng.ForInStatement
|
||||
import net.sergeych.lyng.Script
|
||||
import net.sergeych.lyng.Statement
|
||||
import net.sergeych.lyng.bytecode.BytecodeDisassembler
|
||||
import net.sergeych.lyng.bytecode.CmdDisassembler
|
||||
import net.sergeych.lyng.bytecode.BytecodeStatement
|
||||
import net.sergeych.lyng.obj.ObjInt
|
||||
import kotlin.time.TimeSource
|
||||
@@ -56,8 +56,11 @@ class NestedRangeBenchmarkTest {
|
||||
val scope = Script.newScope()
|
||||
scope.eval(script)
|
||||
val fnDisasm = scope.disassembleSymbol("naiveCountHappyNumbers")
|
||||
println("[DEBUG_LOG] [BENCH] nested-happy function naiveCountHappyNumbers bytecode:\n$fnDisasm")
|
||||
println("[DEBUG_LOG] [BENCH] nested-happy function naiveCountHappyNumbers cmd:\n$fnDisasm")
|
||||
runMode(scope)
|
||||
}
|
||||
|
||||
private suspend fun runMode(scope: net.sergeych.lyng.Scope) {
|
||||
val start = TimeSource.Monotonic.markNow()
|
||||
val result = scope.eval("naiveCountHappyNumbers()") as ObjInt
|
||||
val elapsedMs = start.elapsedNow().inWholeMilliseconds
|
||||
@@ -83,13 +86,13 @@ class NestedRangeBenchmarkTest {
|
||||
"$slotName@${fn.scopeSlotDepths[idx]}:${fn.scopeSlotIndices[idx]}"
|
||||
}
|
||||
println("[DEBUG_LOG] [BENCH] nested-happy slots depth=$depth: ${slots.joinToString(", ")}")
|
||||
val disasm = BytecodeDisassembler.disassemble(fn)
|
||||
println("[DEBUG_LOG] [BENCH] nested-happy bytecode depth=$depth:\n$disasm")
|
||||
val disasm = CmdDisassembler.disassemble(fn)
|
||||
println("[DEBUG_LOG] [BENCH] nested-happy cmd depth=$depth:\n$disasm")
|
||||
current = original.body
|
||||
depth += 1
|
||||
}
|
||||
if (depth == 1) {
|
||||
println("[DEBUG_LOG] [BENCH] nested-happy bytecode: <not found>")
|
||||
println("[DEBUG_LOG] [BENCH] nested-happy cmd: <not found>")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2822,10 +2822,10 @@ class ScriptTest {
|
||||
x
|
||||
}
|
||||
|
||||
(1..100).map { launch { dosomething() } }.forEach {
|
||||
(1..50).map { launch { dosomething() } }.forEach {
|
||||
assertEquals(5050, it.await())
|
||||
}
|
||||
assertEquals( 100, ac.getCounter() )
|
||||
assertEquals( 50, ac.getCounter() )
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user