Skip to content

Commit 67f2faa

Browse files
authored
Merge pull request #12 from udzura/parser-fixes
Faster binary parser
2 parents c9f4760 + 30777ce commit 67f2faa

27 files changed

+762
-287
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
wardite (0.8.2)
4+
wardite (0.9.0)
55

66
GEM
77
remote: https://rubygems.org/

examples/load_perf.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
require "wardite"
2+
require "optparse"
3+
require "ostruct"
4+
5+
$options = OpenStruct.new
6+
7+
opt = OptionParser.new
8+
opt.on('--wasm-file [FILE]') {|v| $options.wasm_file = v }
9+
opt.parse!
10+
11+
f = File.open($options.wasm_file)
12+
13+
require "vernier"
14+
RubyVM::YJIT.enable
15+
puts "YJIT enabled: #{RubyVM::YJIT.enabled?}"
16+
17+
Vernier.profile(out: "./tmp/load_perf.json") do
18+
start = Time.now
19+
_instance = Wardite::BinaryLoader::load_from_buffer(f);
20+
puts "Profile saved to ./tmp/load_perf.json"
21+
puts "Load time: #{Time.now.to_f - start.to_f} seconds"
22+
end
23+
24+
p "OK"

lib/wardite.rb

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ def execute!
425425
break
426426
end
427427
cur_frame.pc += 1
428-
insn = cur_frame.body[cur_frame.pc] #: Op
428+
insn = cur_frame.body[cur_frame.pc]
429429
if !insn
430430
break
431431
end
@@ -434,37 +434,38 @@ def execute!
434434
end
435435

436436
# @rbs frame: Frame
437-
# @rbs insn: Op
437+
# @rbs insn: [Symbol, Symbol, Array[operandItem], Integer?, Integer?]
438438
# @rbs return: void
439439
def eval_insn(frame, insn)
440-
case insn.namespace
440+
namespace, code, operand, else_pos, end_pos = *insn
441+
case namespace
441442
when :convert
442-
return Evaluator.convert_eval_insn(self, frame, insn)
443+
return Evaluator.convert_eval_insn(self, frame, code, operand)
443444
when :i32
444-
return Evaluator.i32_eval_insn(self, frame, insn)
445+
return Evaluator.i32_eval_insn(self, frame, code, operand)
445446
when :i64
446-
return Evaluator.i64_eval_insn(self, frame, insn)
447+
return Evaluator.i64_eval_insn(self, frame, code, operand)
447448
when :f32
448-
return Evaluator.f32_eval_insn(self, frame, insn)
449+
return Evaluator.f32_eval_insn(self, frame, code, operand)
449450
when :f64
450-
return Evaluator.f64_eval_insn(self, frame, insn)
451+
return Evaluator.f64_eval_insn(self, frame, code, operand)
451452
end
452453

453454
# unmached namespace...
454-
case insn.code
455+
case code
455456
when :unreachable
456457
raise Unreachable, "unreachable op"
457458
when :nop
458459
return
459460

460461
when :br
461-
level = insn.operand[0]
462+
level = operand[0]
462463
raise EvalError, "br op without level" if !level.is_a?(Integer)
463464
pc = do_branch(frame.labels, stack, level)
464465
frame.pc = pc
465466

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

477478
when :br_table
478-
level_vec = insn.operand[0]
479+
level_vec = operand[0]
479480
raise EvalError, "no level vector" if !level_vec.is_a?(Array)
480-
default = insn.operand[1]
481+
default = operand[1]
481482
raise EvalError, "no default specified" if !default.is_a?(Integer)
482483
idx = stack.pop
483484
raise EvalError, "idx not found" if !idx.is_a?(I32)
@@ -490,29 +491,29 @@ def eval_insn(frame, insn)
490491
frame.pc = pc
491492

492493
when :block
493-
block = insn.operand[0]
494+
block = operand[0]
494495
raise EvalError, "block op without block" if !block.is_a?(Block)
495-
next_pc = insn.meta[:end_pos]
496+
next_pc = end_pos || -1
496497
label = Label.new(:block, next_pc, stack.size, block.result_size)
497498
frame.labels.push(label)
498499

499500
when :loop
500-
block = insn.operand[0]
501+
block = operand[0]
501502
raise EvalError, "loop op without block" if !block.is_a?(Block)
502503
start = frame.pc
503-
next_pc = insn.meta[:end_pos]
504+
next_pc = end_pos || -1
504505
label = Label.new(:loop, next_pc, stack.size, block.result_size, start)
505506
frame.labels.push(label)
506507

507508
when :if
508-
block = insn.operand[0]
509+
block = operand[0]
509510
raise EvalError, "if op without block" if !block.is_a?(Block)
510511
cond = stack.pop
511512
raise EvalError, "cond not found" if !cond.is_a?(I32)
512-
next_pc = insn.meta[:end_pos]
513+
next_pc = end_pos || -1
513514

514515
if cond.value.zero?
515-
frame.pc = insn.meta[:else_pos]
516+
frame.pc = else_pos || -1
516517
end
517518

518519
if frame.pc == next_pc
@@ -532,7 +533,7 @@ def eval_insn(frame, insn)
532533
end
533534

534535
when :call
535-
idx = insn.operand[0]
536+
idx = operand[0]
536537
raise EvalError, "[BUG] local operand not found" if !idx.is_a?(Integer)
537538
fn = self.instance.store.funcs[idx]
538539
case fn
@@ -548,9 +549,9 @@ def eval_insn(frame, insn)
548549
when :call_indirect
549550
table = self.instance.store.tables[0]
550551
raise EvalError, "table required but not found" if !table
551-
type_idx = insn.operand[0]
552+
type_idx = operand[0]
552553
raise EvalError, "[BUG] index operand invalid" if !type_idx.is_a?(Integer)
553-
nullbyte = insn.operand[1]
554+
nullbyte = operand[1]
554555
raise EvalError, "[BUG] invalid bytearray of call_indirect" if nullbyte != 0x0
555556
table_idx = stack.pop
556557
raise EvalError, "[BUG] index stack invalid" if !table_idx.is_a?(I32)
@@ -618,7 +619,7 @@ def eval_insn(frame, insn)
618619
stack.push(cond.value != 0 ? left : right)
619620

620621
when :local_get
621-
idx = insn.operand[0]
622+
idx = operand[0]
622623
if !idx.is_a?(Integer)
623624
raise EvalError, "[BUG] invalid type of operand"
624625
end
@@ -630,7 +631,7 @@ def eval_insn(frame, insn)
630631
stack.push(local)
631632

632633
when :local_set
633-
idx = insn.operand[0]
634+
idx = operand[0]
634635
if !idx.is_a?(Integer)
635636
raise EvalError, "[BUG] invalid type of operand"
636637
end
@@ -641,7 +642,7 @@ def eval_insn(frame, insn)
641642
frame.locals[idx] = value
642643

643644
when :local_tee
644-
idx = insn.operand[0]
645+
idx = operand[0]
645646
if !idx.is_a?(Integer)
646647
raise EvalError, "[BUG] invalid type of operand"
647648
end
@@ -653,7 +654,7 @@ def eval_insn(frame, insn)
653654
stack.push value
654655

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

666667
when :global_set
667-
idx = insn.operand[0]
668+
idx = operand[0]
668669
if !idx.is_a?(Integer)
669670
raise EvalError, "[BUG] invalid type of operand"
670671
end
@@ -695,11 +696,11 @@ def eval_insn(frame, insn)
695696
stack.push(I32(memory.grow(delta.value)))
696697

697698
when :memory_init
698-
idx = insn.operand[0]
699+
idx = operand[0]
699700
if !idx.is_a?(Integer)
700701
raise EvalError, "[BUG] invalid type of operand"
701702
end
702-
if insn.operand[1] != 0x0
703+
if operand[1] != 0x0
703704
$stderr.puts "warning: :memory_init is not ending with 0x00"
704705
end
705706
data_sec = instance.data_section
@@ -721,7 +722,7 @@ def eval_insn(frame, insn)
721722
memory.data[dest_offset.value...(dest_offset.value+length.value)] = source
722723

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

736737
when :memory_fill
737-
if insn.operand[0] != 0x0
738+
if operand[0] != 0x0
738739
$stderr.puts "warning: :memory_fill is not ending with 0x00"
739740
end
740741
length, byte, dest_offset = stack.pop, stack.pop, stack.pop
@@ -857,7 +858,7 @@ class Frame
857858
attr_accessor :pc #: Integer
858859
attr_accessor :sp #: Integer
859860

860-
attr_accessor :body #: Array[Op]
861+
attr_accessor :body #: Array[[Symbol, Symbol, Array[Wardite::operandItem], Integer?, Integer?]]
861862

862863
attr_accessor :arity #: Integer
863864

@@ -869,7 +870,7 @@ class Frame
869870

870871
# @rbs pc: Integer
871872
# @rbs sp: Integer
872-
# @rbs body: Array[Op]
873+
# @rbs body: Array[[Symbol, Symbol, Array[Wardite::operandItem], Integer?, Integer?]]
873874
# @rbs arity: Integer
874875
# @rbs locals: Array[wasmValue]
875876
# @rbs returb: void
@@ -1263,15 +1264,15 @@ def initialize(callsig, retsig, code_body)
12631264
@default_locals = construct_default_locals
12641265
end
12651266

1266-
# @rbs return: Array[Op]
1267+
# @rbs return: Array[[Symbol, Symbol, Array[operandItem], Integer?, Integer?]]
12671268
def body
12681269
code_body.body
12691270
end
12701271

12711272
# @rbs return: Array[Symbol]
12721273
def locals_type
12731274
code_body.locals_type
1274-
end
1275+
end
12751276

12761277
# @rbs return: Array[Integer]
12771278
def locals_count

lib/wardite/alu_f32.generated.rb

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ module Wardite
55
module Evaluator
66
# @rbs runtime: Runtime
77
# @rbs frame: Frame
8-
# @rbs insn: Op
9-
# @rbs return: void
10-
def self.f32_eval_insn(runtime, frame, insn)
11-
case insn.code
8+
# @rbs code: Symbol
9+
# @rbs operand: Array[operandItem]
10+
# @rbs return: bool?
11+
def self.f32_eval_insn(runtime, frame, code, operand)
12+
case code
1213

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

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

3233

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

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

4950

5051
when :f32_const
51-
const = insn.operand[0]
52+
const = operand[0]
5253
if !const.is_a?(Float)
5354
raise EvalError, "invalid type of operand"
5455
end
@@ -243,8 +244,9 @@ def self.f32_eval_insn(runtime, frame, insn)
243244

244245

245246
else
246-
raise "Unknown opcode for namespace #{insn.namespace}: #{insn.code}"
247+
return
247248
end
249+
return true
248250
end
249251
end
250252
end

lib/wardite/alu_f64.generated.rb

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ module Wardite
55
module Evaluator
66
# @rbs runtime: Runtime
77
# @rbs frame: Frame
8-
# @rbs insn: Op
9-
# @rbs return: void
10-
def self.f64_eval_insn(runtime, frame, insn)
11-
case insn.code
8+
# @rbs code: Symbol
9+
# @rbs operand: Array[operandItem]
10+
# @rbs return: bool?
11+
def self.f64_eval_insn(runtime, frame, code, operand)
12+
case code
1213

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

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

3233

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

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

4950

5051
when :f64_const
51-
const = insn.operand[0]
52+
const = operand[0]
5253
if !const.is_a?(Float)
5354
raise EvalError, "invalid type of operand"
5455
end
@@ -243,8 +244,9 @@ def self.f64_eval_insn(runtime, frame, insn)
243244

244245

245246
else
246-
raise "Unknown opcode for namespace #{insn.namespace}: #{insn.code}"
247+
return
247248
end
249+
return true
248250
end
249251
end
250252
end

0 commit comments

Comments
 (0)