class Mirrors::ISeqVisitor

ISeqVisitor is an abstract class that knows how to walk methods and call the visit() method for each instruction. Internally it tracks the state of the current @pc, @line, and @label during the walk.

Attributes

class_refs[R]
field_refs[R]
iseq[R]
method_refs[R]

Public Instance Methods

call(method) click to toggle source

visit all the instructions in the supplied method

# File lib/mirrors/visitors/iseq_visitor.rb, line 13
def call(method)
  @method = method
  @iseq = method.native_code

  # extract fields from iseq
  @magic,
  @major_version,
  @minor_version,
  @format_type,
  @misc,
  @label,
  @path,
  @absolute_path,
  @first_lineno,
  @type,
  @locals,
  @params,
  @catch_table,
  @bytecode = @iseq.to_a

  # walk state
  @pc = 0 # program counter
  @label  # current label
  walk
  self
end
visit(_bytecode) click to toggle source

iterator call once for each opcode

# File lib/mirrors/visitors/iseq_visitor.rb, line 41
def visit(_bytecode)
  raise NotImplementedError, "subclass responsibility"
end

Private Instance Methods

unrecognized_bytecode(bc) click to toggle source

emit diagnostics and signal that an unrecognized opcode was encountered

# File lib/mirrors/visitors/iseq_visitor.rb, line 74
def unrecognized_bytecode(bc)
  puts "-----------------bytecode ---------------------"
  puts "bytecode=#{bc}  clazz=#{bc.class}"
  puts "---------------- disassembly ------------------"
  puts @iseq.disasm
  puts "---------------- bytecode ------------------"
  pp @bytecode
  raise "Urecognized bytecode:#{bc} at index:#{@pc}"
end
walk() click to toggle source

walk the opcodes

# File lib/mirrors/visitors/iseq_visitor.rb, line 48
def walk
  return unless @bytecode # C extensions have no bytecode

  @pc = 0
  @label = nil
  @bytecode.each_with_index do |bc|
    if (bc.class == Integer || bc.class == Fixnum)
      @line = bc # bare line number
      next # line numbers are not executable
    elsif bc.class == Symbol
      @label = bc
      next # labels are not executable
    elsif bc.class == Array
      @opcode = VM::InstructionSequence::Instruction.id2insn_no(bc.first)
      unrecognized_bytecode(bc) unless @opcode
      visit(bc)
      @pc += VM::InstructionSequence::Instruction.insn_no2size(@opcode)
    else
      unrecognized_bytecode(bc)
    end
  end
end