optimizations
Some checks failed
Build / build (push) Successful in 9m47s
Publish Image / publish (push) Failing after 49s
Test / build (push) Failing after 6m19s

This commit is contained in:
Chuck Smith
2024-04-02 14:32:03 -04:00
parent 07fd82b261
commit 88e3330856
18 changed files with 510 additions and 31 deletions

View File

@@ -55,7 +55,3 @@ func (f *frame) ReadUint16() uint16 {
f.ip += 2
return n
}
func (f frame) Instructions() code.Instructions {
return f.cl.Fn.Instructions
}

View File

@@ -2,6 +2,7 @@ package vm
import (
"fmt"
"log"
"monkey/internal/builtins"
"monkey/internal/code"
"monkey/internal/compiler"
@@ -12,6 +13,8 @@ import (
"monkey/internal/utils"
"os"
"path/filepath"
"sort"
"time"
"unicode"
)
@@ -335,6 +338,12 @@ func (vm *VM) executeAdd() error {
return err
}
return vm.push(val)
case object.Float:
val, err := obj.Add(right)
if err != nil {
return err
}
return vm.push(val)
case object.String:
val, err := obj.Add(right)
if err != nil {
@@ -368,6 +377,12 @@ func (vm *VM) executeSub() error {
return err
}
return vm.push(val)
case object.Float:
val, err := obj.Sub(right)
if err != nil {
return err
}
return vm.push(val)
default:
return fmt.Errorf("unsupported types for unary operation: -%s", left.Type())
}
@@ -389,6 +404,12 @@ func (vm *VM) executeMul() error {
return err
}
return vm.push(val)
case object.Float:
val, err := obj.Mul(right)
if err != nil {
return err
}
return vm.push(val)
case object.String:
val, err := obj.Mul(right)
if err != nil {
@@ -410,6 +431,12 @@ func (vm *VM) executeDiv() error {
return err
}
return vm.push(val)
case object.Float:
val, err := obj.Div(right)
if err != nil {
return err
}
return vm.push(val)
default:
return object.NewBinaryOpError(left, right, "/")
}
@@ -591,6 +618,8 @@ func (vm *VM) executeNot() error {
return vm.push(obj.LogicalNot())
case object.Integer:
return vm.push(obj.LogicalNot())
case object.Float:
return vm.push(obj.LogicalNot())
case object.Null:
return vm.push(obj.LogicalNot())
default:
@@ -604,6 +633,8 @@ func (vm *VM) executeMinus() error {
switch obj := left.(type) {
case object.Integer:
return vm.push(obj.Negate())
case object.Float:
return vm.push(obj.Negate())
default:
return fmt.Errorf("unsupported types for unary operation: -%s", left.Type())
}
@@ -714,6 +745,7 @@ func (vm *VM) callClosure(cl *object.Closure, numArgs int) error {
func (vm *VM) callBuiltin(builtin object.Builtin, numArgs int) error {
args := vm.stack[vm.sp-numArgs : vm.sp]
log.Printf("args: %+v", args)
result := builtin.Fn(vm.ctx, args...)
vm.sp = vm.sp - numArgs - 1
@@ -764,10 +796,29 @@ func (vm *VM) LastPoppedStackElem() object.Object {
}
func (vm *VM) Run() (err error) {
start := time.Now()
freqs := make([]int, 255)
for err == nil {
op := vm.currentFrame().ReadNextOp()
if vm.debug {
freqs[op]++
}
if vm.trace {
log.Printf(
"%-25s M:%-20s\n",
fmt.Sprintf(
"%04d %s", vm.currentFrame().ip, op,
),
fmt.Sprintf(
"[ip=%02d fp=%02d, sp=%02d]",
vm.currentFrame().ip, vm.fp-1, vm.sp,
),
)
}
switch op {
case code.OpConstant:
constIndex := vm.currentFrame().ReadUint16()
@@ -925,6 +976,45 @@ func (vm *VM) Run() (err error) {
default:
err = fmt.Errorf("unhandled opcode: %s", op)
}
if vm.trace {
log.Printf(
"%-25s [ip=%02d fp=%02d, sp=%02d]",
"", vm.currentFrame().ip, vm.fp-1, vm.sp,
)
var globals []object.Object
for _, obj := range vm.state.Globals {
if obj != nil {
globals = append(globals, obj)
}
}
log.Printf("%-25s G:%+v", "", globals)
log.Printf("%-25s S:%+v", "", vm.stack[:vm.sp])
log.Printf("%-25s E:%+v", "", err)
}
}
if vm.debug {
end := time.Now().Sub(start)
total := 0
opcodes := make([]code.Opcode, 0, len(freqs))
for i, count := range freqs {
opcode := code.Opcode(i)
opcodes = append(opcodes, opcode)
total += count
}
sort.SliceStable(opcodes, func(i, j int) bool {
return freqs[opcodes[i]] > freqs[opcodes[j]]
})
log.Printf("%d instructions executed in %s %d/µs", total, end, total/int(end.Microseconds()))
log.Print("Top Instructions:")
for _, opcode := range opcodes[:min(len(opcodes), 10)] {
log.Printf("%10d %s", freqs[opcode], opcode)
}
}
return

View File

@@ -242,6 +242,21 @@ func TestIntegerArithmetic(t *testing.T) {
runVmTests(t, tests)
}
func TestFloatingPointArithmetic(t *testing.T) {
tests := []vmTestCase{
{"1.2", 1.2},
{"2.3", 2.3},
{"1.2 + 2.3", 3.5},
{"1.2 - 2.4", -1.2},
{"1.2 * 2.4", 2.88},
{"5.0 / 2.0", 2.5},
{"-2.5", -2.5},
{"!1.0", false},
}
runVmTests(t, tests)
}
func TestBooleanExpressions(t *testing.T) {
tests := []vmTestCase{
{"true", true},