optimizations
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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},
|
||||
|
||||
Reference in New Issue
Block a user