Skip to content
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
wardite (0.8.2)
wardite (0.9.0)

GEM
remote: https://rubygems.org/
Expand Down
24 changes: 24 additions & 0 deletions examples/load_perf.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require "wardite"
require "optparse"
require "ostruct"

$options = OpenStruct.new

opt = OptionParser.new
opt.on('--wasm-file [FILE]') {|v| $options.wasm_file = v }
opt.parse!

f = File.open($options.wasm_file)

require "vernier"
RubyVM::YJIT.enable
puts "YJIT enabled: #{RubyVM::YJIT.enabled?}"

Vernier.profile(out: "./tmp/load_perf.json") do
start = Time.now
_instance = Wardite::BinaryLoader::load_from_buffer(f);
puts "Profile saved to ./tmp/load_perf.json"
puts "Load time: #{Time.now.to_f - start.to_f} seconds"
end

p "OK"
73 changes: 37 additions & 36 deletions lib/wardite.rb
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ def execute!
break
end
cur_frame.pc += 1
insn = cur_frame.body[cur_frame.pc] #: Op
insn = cur_frame.body[cur_frame.pc]
if !insn
break
end
Expand All @@ -434,37 +434,38 @@ def execute!
end

# @rbs frame: Frame
# @rbs insn: Op
# @rbs insn: [Symbol, Symbol, Array[operandItem], Integer?, Integer?]
# @rbs return: void
def eval_insn(frame, insn)
case insn.namespace
namespace, code, operand, else_pos, end_pos = *insn
case namespace
when :convert
return Evaluator.convert_eval_insn(self, frame, insn)
return Evaluator.convert_eval_insn(self, frame, code, operand)
when :i32
return Evaluator.i32_eval_insn(self, frame, insn)
return Evaluator.i32_eval_insn(self, frame, code, operand)
when :i64
return Evaluator.i64_eval_insn(self, frame, insn)
return Evaluator.i64_eval_insn(self, frame, code, operand)
when :f32
return Evaluator.f32_eval_insn(self, frame, insn)
return Evaluator.f32_eval_insn(self, frame, code, operand)
when :f64
return Evaluator.f64_eval_insn(self, frame, insn)
return Evaluator.f64_eval_insn(self, frame, code, operand)
end

# unmached namespace...
case insn.code
case code
when :unreachable
raise Unreachable, "unreachable op"
when :nop
return

when :br
level = insn.operand[0]
level = operand[0]
raise EvalError, "br op without level" if !level.is_a?(Integer)
pc = do_branch(frame.labels, stack, level)
frame.pc = pc

when :br_if
level = insn.operand[0]
level = operand[0]
raise EvalError, "br op without level" if !level.is_a?(Integer)
cond = stack.pop
raise EvalError, "cond not found" if !cond.is_a?(I32)
Expand All @@ -475,9 +476,9 @@ def eval_insn(frame, insn)
frame.pc = pc

when :br_table
level_vec = insn.operand[0]
level_vec = operand[0]
raise EvalError, "no level vector" if !level_vec.is_a?(Array)
default = insn.operand[1]
default = operand[1]
raise EvalError, "no default specified" if !default.is_a?(Integer)
idx = stack.pop
raise EvalError, "idx not found" if !idx.is_a?(I32)
Expand All @@ -490,29 +491,29 @@ def eval_insn(frame, insn)
frame.pc = pc

when :block
block = insn.operand[0]
block = operand[0]
raise EvalError, "block op without block" if !block.is_a?(Block)
next_pc = insn.meta[:end_pos]
next_pc = end_pos || -1
label = Label.new(:block, next_pc, stack.size, block.result_size)
frame.labels.push(label)

when :loop
block = insn.operand[0]
block = operand[0]
raise EvalError, "loop op without block" if !block.is_a?(Block)
start = frame.pc
next_pc = insn.meta[:end_pos]
next_pc = end_pos || -1
label = Label.new(:loop, next_pc, stack.size, block.result_size, start)
frame.labels.push(label)

when :if
block = insn.operand[0]
block = operand[0]
raise EvalError, "if op without block" if !block.is_a?(Block)
cond = stack.pop
raise EvalError, "cond not found" if !cond.is_a?(I32)
next_pc = insn.meta[:end_pos]
next_pc = end_pos || -1

if cond.value.zero?
frame.pc = insn.meta[:else_pos]
frame.pc = else_pos || -1
end

if frame.pc == next_pc
Expand All @@ -532,7 +533,7 @@ def eval_insn(frame, insn)
end

when :call
idx = insn.operand[0]
idx = operand[0]
raise EvalError, "[BUG] local operand not found" if !idx.is_a?(Integer)
fn = self.instance.store.funcs[idx]
case fn
Expand All @@ -548,9 +549,9 @@ def eval_insn(frame, insn)
when :call_indirect
table = self.instance.store.tables[0]
raise EvalError, "table required but not found" if !table
type_idx = insn.operand[0]
type_idx = operand[0]
raise EvalError, "[BUG] index operand invalid" if !type_idx.is_a?(Integer)
nullbyte = insn.operand[1]
nullbyte = operand[1]
raise EvalError, "[BUG] invalid bytearray of call_indirect" if nullbyte != 0x0
table_idx = stack.pop
raise EvalError, "[BUG] index stack invalid" if !table_idx.is_a?(I32)
Expand Down Expand Up @@ -618,7 +619,7 @@ def eval_insn(frame, insn)
stack.push(cond.value != 0 ? left : right)

when :local_get
idx = insn.operand[0]
idx = operand[0]
if !idx.is_a?(Integer)
raise EvalError, "[BUG] invalid type of operand"
end
Expand All @@ -630,7 +631,7 @@ def eval_insn(frame, insn)
stack.push(local)

when :local_set
idx = insn.operand[0]
idx = operand[0]
if !idx.is_a?(Integer)
raise EvalError, "[BUG] invalid type of operand"
end
Expand All @@ -641,7 +642,7 @@ def eval_insn(frame, insn)
frame.locals[idx] = value

when :local_tee
idx = insn.operand[0]
idx = operand[0]
if !idx.is_a?(Integer)
raise EvalError, "[BUG] invalid type of operand"
end
Expand All @@ -653,7 +654,7 @@ def eval_insn(frame, insn)
stack.push value

when :global_get
idx = insn.operand[0]
idx = operand[0]
if !idx.is_a?(Integer)
raise EvalError, "[BUG] invalid type of operand"
end
Expand All @@ -664,7 +665,7 @@ def eval_insn(frame, insn)
stack.push(global.value)

when :global_set
idx = insn.operand[0]
idx = operand[0]
if !idx.is_a?(Integer)
raise EvalError, "[BUG] invalid type of operand"
end
Expand Down Expand Up @@ -695,11 +696,11 @@ def eval_insn(frame, insn)
stack.push(I32(memory.grow(delta.value)))

when :memory_init
idx = insn.operand[0]
idx = operand[0]
if !idx.is_a?(Integer)
raise EvalError, "[BUG] invalid type of operand"
end
if insn.operand[1] != 0x0
if operand[1] != 0x0
$stderr.puts "warning: :memory_init is not ending with 0x00"
end
data_sec = instance.data_section
Expand All @@ -721,7 +722,7 @@ def eval_insn(frame, insn)
memory.data[dest_offset.value...(dest_offset.value+length.value)] = source

when :memory_copy
if insn.operand[0] != 0x0 || insn.operand[1] != 0x0
if operand[0] != 0x0 || operand[1] != 0x0
$stderr.puts "warning: :memory_copy is not ending with 0x00"
end
length, src_offset, dest_offset = stack.pop, stack.pop, stack.pop
Expand All @@ -734,7 +735,7 @@ def eval_insn(frame, insn)
memory.data[dest_offset.value...(dest_offset.value+length.value)] = source

when :memory_fill
if insn.operand[0] != 0x0
if operand[0] != 0x0
$stderr.puts "warning: :memory_fill is not ending with 0x00"
end
length, byte, dest_offset = stack.pop, stack.pop, stack.pop
Expand Down Expand Up @@ -857,7 +858,7 @@ class Frame
attr_accessor :pc #: Integer
attr_accessor :sp #: Integer

attr_accessor :body #: Array[Op]
attr_accessor :body #: Array[[Symbol, Symbol, Array[Wardite::operandItem], Integer?, Integer?]]

attr_accessor :arity #: Integer

Expand All @@ -869,7 +870,7 @@ class Frame

# @rbs pc: Integer
# @rbs sp: Integer
# @rbs body: Array[Op]
# @rbs body: Array[[Symbol, Symbol, Array[Wardite::operandItem], Integer?, Integer?]]
# @rbs arity: Integer
# @rbs locals: Array[wasmValue]
# @rbs returb: void
Expand Down Expand Up @@ -1263,15 +1264,15 @@ def initialize(callsig, retsig, code_body)
@default_locals = construct_default_locals
end

# @rbs return: Array[Op]
# @rbs return: Array[[Symbol, Symbol, Array[operandItem], Integer?, Integer?]]
def body
code_body.body
end

# @rbs return: Array[Symbol]
def locals_type
code_body.locals_type
end
end

# @rbs return: Array[Integer]
def locals_count
Expand Down
22 changes: 12 additions & 10 deletions lib/wardite/alu_f32.generated.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ module Wardite
module Evaluator
# @rbs runtime: Runtime
# @rbs frame: Frame
# @rbs insn: Op
# @rbs return: void
def self.f32_eval_insn(runtime, frame, insn)
case insn.code
# @rbs code: Symbol
# @rbs operand: Array[operandItem]
# @rbs return: bool?
def self.f32_eval_insn(runtime, frame, code, operand)
case code

when :f32_load
_align = insn.operand[0] # TODO: alignment support?
offset = insn.operand[1]
_align = operand[0] # TODO: alignment support?
offset = operand[1]
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)

addr = runtime.stack.pop
Expand All @@ -31,8 +32,8 @@ def self.f32_eval_insn(runtime, frame, insn)


when :f32_store
_align = insn.operand[0] # TODO: alignment support?
offset = insn.operand[1]
_align = operand[0] # TODO: alignment support?
offset = operand[1]
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)

value = runtime.stack.pop
Expand All @@ -48,7 +49,7 @@ def self.f32_eval_insn(runtime, frame, insn)


when :f32_const
const = insn.operand[0]
const = operand[0]
if !const.is_a?(Float)
raise EvalError, "invalid type of operand"
end
Expand Down Expand Up @@ -243,8 +244,9 @@ def self.f32_eval_insn(runtime, frame, insn)


else
raise "Unknown opcode for namespace #{insn.namespace}: #{insn.code}"
return
end
return true
end
end
end
22 changes: 12 additions & 10 deletions lib/wardite/alu_f64.generated.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ module Wardite
module Evaluator
# @rbs runtime: Runtime
# @rbs frame: Frame
# @rbs insn: Op
# @rbs return: void
def self.f64_eval_insn(runtime, frame, insn)
case insn.code
# @rbs code: Symbol
# @rbs operand: Array[operandItem]
# @rbs return: bool?
def self.f64_eval_insn(runtime, frame, code, operand)
case code

when :f64_load
_align = insn.operand[0] # TODO: alignment support?
offset = insn.operand[1]
_align = operand[0] # TODO: alignment support?
offset = operand[1]
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)

addr = runtime.stack.pop
Expand All @@ -31,8 +32,8 @@ def self.f64_eval_insn(runtime, frame, insn)


when :f64_store
_align = insn.operand[0] # TODO: alignment support?
offset = insn.operand[1]
_align = operand[0] # TODO: alignment support?
offset = operand[1]
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)

value = runtime.stack.pop
Expand All @@ -48,7 +49,7 @@ def self.f64_eval_insn(runtime, frame, insn)


when :f64_const
const = insn.operand[0]
const = operand[0]
if !const.is_a?(Float)
raise EvalError, "invalid type of operand"
end
Expand Down Expand Up @@ -243,8 +244,9 @@ def self.f64_eval_insn(runtime, frame, insn)


else
raise "Unknown opcode for namespace #{insn.namespace}: #{insn.code}"
return
end
return true
end
end
end
Loading