Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve vm perf #3

Merged
merged 3 commits into from Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 20 additions & 21 deletions src/objects.cr
Expand Up @@ -53,23 +53,11 @@ module Objects
abstract def inspect : String

def if_not_error(& : MObject -> MObject?) : MObject?
case self
when MError
return self
else
return yield self
end
yield self
end

def is_truthy? : Bool
case self
when MBoolean
return self.value
when MNull
return false
else
return true
end
true
end
end

Expand Down Expand Up @@ -149,6 +137,10 @@ module Objects
def initialize(@message : String)
end

def if_not_error(& : MObject -> MObject?) : MObject?
self
end

def inspect : String
return "ERROR: #{@message}"
end
Expand All @@ -162,20 +154,23 @@ module Objects
def inspect : String
return "null"
end

def is_truthy? : Bool
false
end
end

class MBoolean < MValue(Bool)
def hash_type : HashType
return HashType::Boolean
HashType::Boolean
end

def same?(other : self)
other.value == @value
end

def same?(other)
case other
when MBoolean
return other.value == @value
else
return false
end
false
end

# def object_id
Expand All @@ -185,6 +180,10 @@ module Objects
def hash_key : HashKey
return HashKey.new(hash_type, (@value ? 1 : 0).to_u64)
end

def is_truthy? : Bool
value
end
end

class MString < MValue(String)
Expand Down
41 changes: 21 additions & 20 deletions src/vm.cr
Expand Up @@ -4,7 +4,7 @@ require "./objects"

macro execute_build_and_push(col)
num_elements = Code.read_int(ins, ip + 1)
current_frame.ip += 2
current_frame.ip &+= 2
{{col}} = build_{{col}}(@sp - num_elements, @sp)
@sp -= num_elements
push({{col}})
Expand Down Expand Up @@ -41,6 +41,9 @@ module Vm
@frames = Array(Vm::Frame?).new(MAX_FRAME_SIZE) { nil }
@frame_index = 1
@globals = [] of MObject
private getter current_frame : Frame do
@frames[@frame_index - 1].not_nil!
end

def initialize(@bytecode : Bytecode)
@constants = @bytecode.constants
Expand All @@ -60,14 +63,14 @@ module Vm
ins : Instructions
op : Opcode
while current_frame.ip < current_frame.instructions.size - 1
current_frame.ip += 1
current_frame.ip &+= 1
ip = current_frame.ip
ins = current_frame.instructions
op = Opcode.new(ins[ip].to_i)
case op
when Opcode::OpConstant
const_index = Code.read_int(ins, ip + 1)
current_frame.ip += 2
current_frame.ip &+= 2
push(@constants[const_index])
when Opcode::OpPop
pop
Expand All @@ -85,7 +88,7 @@ module Vm
execute_bang_operator
when Opcode::OpJumpNotTruthy
pos = Code.read_int(ins, ip + 1)
current_frame.ip += 2
current_frame.ip &+= 2
condition = pop
if !condition.is_truthy?
current_frame.ip = pos - 1
Expand All @@ -97,15 +100,15 @@ module Vm
current_frame.ip = pos - 1
when Opcode::OpSetGlobal
global_index = Code.read_int(ins, ip + 1)
current_frame.ip += 2
current_frame.ip &+= 2
if global_index == @globals.size
@globals << pop.not_nil!
else
@globals[global_index] = pop.not_nil!
end
when Opcode::OpGetGlobal
global_index = Code.read_int(ins, ip + 1)
current_frame.ip += 2
current_frame.ip &+= 2
push(@globals[global_index])
when Opcode::OpArray
execute_build_and_push array
Expand All @@ -118,11 +121,11 @@ module Vm
when Opcode::OpClosure
const_index = Code.read_int(ins, ip + 1)
num_free = Code.read_byte(ins, ip + 3)
current_frame.ip += 3
current_frame.ip &+= 3
push_closure(const_index, num_free.to_i)
when Opcode::OpCall
num_args = Code.read_byte(ins, ip + 1)
current_frame.ip += 1
current_frame.ip &+= 1
execute_call(num_args.to_i)
when Opcode::OpReturnValue
return_value = pop
Expand All @@ -135,21 +138,21 @@ module Vm
push(VM_NULL)
when Opcode::OpSetLocal
local_index = Code.read_byte(ins, ip + 1)
current_frame.ip += 1
current_frame.ip &+= 1
frame = current_frame
@stack[frame.base_pointer + local_index.to_i] = pop
when Opcode::OpGetLocal
local_index = Code.read_byte(ins, ip + 1)
current_frame.ip += 1
current_frame.ip &+= 1
frame = current_frame
push(@stack[frame.base_pointer + local_index.to_i].not_nil!)
when Opcode::OpGetBuiltin
built_index = Code.read_byte(ins, ip + 1)
current_frame.ip += 1
current_frame.ip &+= 1
push(Objects::BUILTINS[built_index.to_i][1])
when Opcode::OpGetFree
free_index = Code.read_byte(ins, ip + 1)
current_frame.ip += 1
current_frame.ip &+= 1
current_closure = current_frame.cl
push(current_closure.free[free_index.to_i])
when Opcode::OpCurrentClosure
Expand All @@ -164,16 +167,12 @@ module Vm
return @stack[@sp]?
end

private def current_frame : Vm::Frame
return @frames[@frame_index - 1].not_nil!
end

private def push(obj : MObject)
if @sp > STACK_SIZE
raise VMException.new("stack overflow")
end
@stack[@sp] = obj
@sp += 1
@sp &+= 1
end

private def pop : MObject?
Expand Down Expand Up @@ -282,7 +281,7 @@ module Vm
i = start_index
while i < end_index
elements[i - start_index] = @stack[i]
i += 1
i &+= 1
end
return MArray.new(elements)
end
Expand Down Expand Up @@ -385,12 +384,14 @@ module Vm

private def push_frame(frame : Frame)
@frames[@frame_index] = frame
@frame_index += 1
@current_frame = nil
@frame_index &+= 1
end

private def pop_frame : Frame
@frame_index -= 1
return @frames[@frame_index].not_nil!
@current_frame = nil
@frames[@frame_index].not_nil!
end
end

Expand Down