Module: Optimize::Codec::ArgPositions
- Defined in:
- lib/optimize/codec/arg_positions.rb
Overview
Decode/encode the param opt_table for a single iseq.
On-disk format (from research/cruby/ibf-format.md §4.1 “param opt table”):
VALUE[] — (param_opt_num + 1) entries, each a native uint64 (little-endian on x86-64)
holding the YARV slot index where execution begins for each entry count of supplied args.
Entry semantics:
opt_table[i] = YARV slot at which execution begins when exactly
(param_lead_num + i) positional arguments were supplied.
opt_table[param_opt_num] = YARV slot after all default-eval code (start of method body).
The section is 8-byte aligned (VALUE-aligned) and the absolute offset is stored in the body record as param_opt_table_offset_rel (relative = body_offset - opt_table_abs).
The keyword param struct (param_keyword_offset) stores only counts and object-table indices (no instruction-position data), so it is left as raw bytes in misc.
Class Method Summary collapse
-
.decode(binary, opt_table_abs, opt_num, slot_to_inst) ⇒ IR::ArgPositions
Decode opt_table from the binary.
-
.encode(region, region_start, opt_table_abs, arg_positions, inst_to_slot) ⇒ Object
Encode opt_table into the iseq data region (splice-into-region form).
-
.encode_to_writer(writer, arg_positions, inst_to_slot) ⇒ String
Encode opt_table into
writer(sequential write form).
Class Method Details
.decode(binary, opt_table_abs, opt_num, slot_to_inst) ⇒ IR::ArgPositions
Decode opt_table from the binary.
33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/optimize/codec/arg_positions.rb', line 33 def decode(binary, opt_table_abs, opt_num, slot_to_inst) count = opt_num + 1 # opt_num entries + 1 terminating entry opt_table = Array.new(count) do |i| slot = binary[opt_table_abs + i * 8, 8].unpack1("Q<") inst = slot_to_inst[slot] raise MalformedBinary, "opt_table[#{i}] slot #{slot} does not align with any instruction" unless inst inst end IR::ArgPositions.new(opt_table: opt_table) end |
.encode(region, region_start, opt_table_abs, arg_positions, inst_to_slot) ⇒ Object
Encode opt_table into the iseq data region (splice-into-region form).
Writes (opt_num + 1) native uint64 values (little-endian) at the current position of region (which already has space reserved from the original binary). Call this with the same absolute offset used during decode so that the bytes land in the right place.
57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/optimize/codec/arg_positions.rb', line 57 def encode(region, region_start, opt_table_abs, arg_positions, inst_to_slot) opt_table = arg_positions.opt_table region_offset = opt_table_abs - region_start opt_table.each_with_index do |inst, i| slot = inst_to_slot.fetch(inst) do raise "opt_table[#{i}] instruction #{inst.opcode.inspect} not found in inst_to_slot map" end # Write as native uint64 little-endian (VALUE on 64-bit). region[region_offset + i * 8, 8] = [slot].pack("Q<") end end |
.encode_to_writer(writer, arg_positions, inst_to_slot) ⇒ String
Encode opt_table into writer (sequential write form).
Writes (opt_num + 1) native uint64 values (little-endian) to the writer at its current position. Returns the encoded bytes for assertion purposes.
78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/optimize/codec/arg_positions.rb', line 78 def encode_to_writer(writer, arg_positions, inst_to_slot) opt_table = arg_positions.opt_table bytes = "".b opt_table.each_with_index do |inst, i| slot = inst_to_slot.fetch(inst) do raise "opt_table[#{i}] instruction #{inst.opcode.inspect} not found in inst_to_slot map" end bytes << [slot].pack("Q<") end writer.write_bytes(bytes) bytes end |