Skip to content

Commit

Permalink
vm: implement local slot storage for fast lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
azenla committed Nov 29, 2023
1 parent f2ff23e commit 3dbf8f9
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 19 deletions.
1 change: 1 addition & 0 deletions tool/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies {
api(project(":compiler"))
api(project(":vm"))
api("com.github.ajalt.clikt:clikt:4.2.0")
api("com.charleskorn.kaml:kaml:0.55.0")

implementation(project(":common"))
}
Expand Down
14 changes: 6 additions & 8 deletions tool/src/main/kotlin/gay/pizza/pork/tool/CompileCommand.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package gay.pizza.pork.tool

import com.charleskorn.kaml.PolymorphismStyle
import com.charleskorn.kaml.Yaml
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import gay.pizza.dough.fs.PlatformFsProvider
Expand All @@ -8,10 +10,7 @@ import gay.pizza.pork.bir.IrWorld
import gay.pizza.pork.bytecode.CompiledWorld
import gay.pizza.pork.compiler.Compiler
import gay.pizza.pork.minimal.FileTool
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json

@OptIn(ExperimentalSerializationApi::class)
class CompileCommand : CliktCommand(help = "Compile Pork to Bytecode", name = "compile") {
val path by argument("file")

Expand All @@ -30,11 +29,10 @@ class CompileCommand : CliktCommand(help = "Compile Pork to Bytecode", name = "c
}

private fun printCompiledIr(irWorld: IrWorld) {
val json = Json {
prettyPrint = true
prettyPrintIndent = " "
}
println(json.encodeToString(IrWorld.serializer(), irWorld))
val yaml = Yaml(configuration = Yaml.default.configuration.copy(
polymorphismStyle = PolymorphismStyle.Property
))
println(yaml.encodeToString(IrWorld.serializer(), irWorld))
}

private fun printCompiledWorld(compiledWorld: CompiledWorld) {
Expand Down
15 changes: 7 additions & 8 deletions vm/src/main/kotlin/gay/pizza/pork/vm/InternalMachine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist

private var inst: UInt = 0u
private val stack = mutableListOf<Any>()
private val locals = mutableListOf<MutableMap<UInt, Any>>(
mutableMapOf()
private val locals = mutableListOf(
LocalSlots()
)
private val callStack = mutableListOf(0u)
private val returnAddressStack = mutableListOf<UInt>()
Expand All @@ -32,7 +32,7 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist
}

fun pushScope() {
locals.add(mutableMapOf())
locals.add(LocalSlots())
}

fun popScope() {
Expand All @@ -43,14 +43,13 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist
val constant = world.constantPool.constants[id.toInt()]
when (constant.tag) {
ConstantTag.String -> push(String(constant.value))
else -> throw VirtualMachineException("Unknown Constant Tag: ${constant.tag.name}")
else -> throw VirtualMachineException("Unknown constant tag: ${constant.tag.name}")
}
}

fun localAt(id: UInt): Any {
val localSet = locals.last()
return localSet[id] ?:
throw VirtualMachineException("Attempted to load local $id but it was not stored.")
return localSet.load(id)
}

fun loadLocal(id: UInt) {
Expand All @@ -60,7 +59,7 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist
fun storeLocal(id: UInt) {
val localSet = locals.last()
val value = popAnyValue()
localSet[id] = value
localSet.store(id, value)
}

fun setNextInst(value: UInt) {
Expand Down Expand Up @@ -106,7 +105,7 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist
callStack.clear()
callStack.add(0u)
locals.clear()
locals.add(mutableMapOf())
locals.add(LocalSlots())
inst = 0u
exitFlag = false
autoNextInst = true
Expand Down
25 changes: 25 additions & 0 deletions vm/src/main/kotlin/gay/pizza/pork/vm/LocalSlots.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package gay.pizza.pork.vm

class LocalSlots {
private var slots = arrayOfNulls<Any>(4)

fun load(index: UInt): Any {
return slots[index.toInt()]
?: throw VirtualMachineException("Attempted to access local $index that is not stored")
}

fun store(index: UInt, value: Any) {
if (index >= slots.size.toUInt()) {
resize(index + 4u)
}
slots[index.toInt()] = value
}

private fun resize(count: UInt) {
val values = arrayOfNulls<Any>(count.toInt())
for ((i, value) in slots.withIndex()) {
values[i] = value
}
slots = values
}
}
2 changes: 1 addition & 1 deletion vm/src/main/kotlin/gay/pizza/pork/vm/ops/AndOpHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import gay.pizza.pork.vm.OpHandler

object AndOpHandler : OpHandler(Opcode.And) {
override fun handle(machine: InternalMachine, op: Op) {
val left = machine.pop<Boolean>()
val right = machine.pop<Boolean>()
val left = machine.pop<Boolean>()
machine.push(left && right)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import gay.pizza.pork.vm.OpHandler

object MultiplyOpHandler : OpHandler(Opcode.Multiply) {
override fun handle(machine: InternalMachine, op: Op) {
val left = machine.pop<Int>()
val right = machine.pop<Int>()
val left = machine.pop<Int>()
machine.push(left * right)
}
}
2 changes: 1 addition & 1 deletion vm/src/main/kotlin/gay/pizza/pork/vm/ops/OrOpHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import gay.pizza.pork.vm.OpHandler

object OrOpHandler : OpHandler(Opcode.Or) {
override fun handle(machine: InternalMachine, op: Op) {
val left = machine.pop<Boolean>()
val right = machine.pop<Boolean>()
val left = machine.pop<Boolean>()
machine.push(left || right)
}
}

0 comments on commit 3dbf8f9

Please sign in to comment.