implement a new native call bytecode mechanism that can be optimized by the vm

This commit is contained in:
Alex Zenla
2025-03-18 19:57:27 -07:00
parent 10308eae5c
commit d2eaffafcc
8 changed files with 83 additions and 38 deletions

View File

@ -6,9 +6,9 @@ import gay.pizza.pork.execution.NativeRegistry
class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegistry, val handlers: List<OpHandler>) {
private val inlined = world.code.map { op ->
val handler = handlers.firstOrNull { it.code == op.code } ?:
throw VirtualMachineException("Opcode ${op.code.name} does not have a handler.")
op to handler
val handler = handlers.firstOrNull { it.code == op.code }
?: throw VirtualMachineException("Opcode ${op.code.name} does not have a handler.")
op to (handler.optimize(machine = this, op) ?: handler)
}
private var inst: UInt = 0u

View File

@ -5,4 +5,6 @@ import gay.pizza.pork.bytecode.Opcode
abstract class OpHandler(val code: Opcode) {
abstract fun handle(machine: InternalMachine, op: Op)
open fun optimize(machine: InternalMachine, op: Op): OpHandler? = null
}

View File

@ -8,23 +8,15 @@ import gay.pizza.pork.vm.OpHandler
object NativeOpHandler : OpHandler(Opcode.Native) {
override fun handle(machine: InternalMachine, op: Op) {
val argumentCount = op.args[2]
val arguments = mutableListOf<Any>()
var x = argumentCount
while (x > 0u) {
x--
arguments.add(machine.localAt(x))
}
val formConstant = machine.world.constantPool.read(op.args[0])
val form = formConstant.readAsString()
val handler = optimize(machine, op)
handler.handle(machine, op)
}
override fun optimize(machine: InternalMachine, op: Op): OpHandler {
val nativeDefinition = machine.world.constantPool.read(op.args[0]).readAsNativeDefinition()
val form = nativeDefinition[0]
val provider = machine.nativeRegistry.of(form)
val countOfNativeDefs = op.args[1].toInt()
val defs = mutableListOf<String>()
for (i in 0 until countOfNativeDefs) {
defs.add(machine.pop())
}
val function = provider.provideNativeFunction(defs)
val result = function.invoke(arguments)
machine.push(if (result == Unit) None else result)
val function = provider.provideNativeFunction(nativeDefinition.subList(1, nativeDefinition.size))
return OptimizedNativeOpHandler(function)
}
}

View File

@ -0,0 +1,22 @@
package gay.pizza.pork.vm.ops
import gay.pizza.pork.bytecode.Op
import gay.pizza.pork.bytecode.Opcode
import gay.pizza.pork.execution.NativeFunction
import gay.pizza.pork.execution.None
import gay.pizza.pork.vm.InternalMachine
import gay.pizza.pork.vm.OpHandler
class OptimizedNativeOpHandler(val function: NativeFunction) : OpHandler(Opcode.Native) {
override fun handle(machine: InternalMachine, op: Op) {
val argumentCount = op.args[1]
val arguments = mutableListOf<Any>()
var x = argumentCount
while (x > 0u) {
x--
arguments.add(machine.localAt(x))
}
val result = function.invoke(arguments)
machine.push(if (result == Unit) None else result)
}
}