Class: Optimize::Harness::LoadIseqHook

Inherits:
Object
  • Object
show all
Defined in:
lib/optimize/harness.rb

Overview

Intercepts RubyVM::InstructionSequence.load_iseq, runs the configured pipeline on every loaded iseq, and falls back to the built-in compiler on any failure.

Constant Summary collapse

HOOKS =
{}

Instance Method Summary collapse

Constructor Details

#initialize(passes:) ⇒ LoadIseqHook

Returns a new instance of LoadIseqHook.



40
41
42
43
44
# File 'lib/optimize/harness.rb', line 40

def initialize(passes:)
  @pipeline = Pipeline.new(passes)
  @id = object_id
  @installed = false
end

Instance Method Details

#__transform(path) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/optimize/harness.rb', line 67

def __transform(path)
  source = File.read(path)
  return nil if Harness.opted_out?(source)

  iseq = RubyVM::InstructionSequence.compile(source, path, path)
  binary = iseq.to_binary
  ir = Codec.decode(binary)
  type_env = TypeEnv.from_source(source, path)
  @pipeline.run(ir, type_env: type_env)
  modified = Codec.encode(ir)
  RubyVM::InstructionSequence.load_from_binary(modified)
rescue => e
  warn "[optimize] harness fell back on #{path}: #{e.class}: #{e.message}"
  nil
end

#installObject



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/optimize/harness.rb', line 46

def install
  return if @installed
  HOOKS[@id] = self
  id = @id
  meta = class << RubyVM::InstructionSequence; self; end
  meta.class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
    def load_iseq(path)
      Optimize::Harness::LoadIseqHook::HOOKS[#{id}].__transform(path)
    end
  RUBY
  @installed = true
end

#uninstallObject



59
60
61
62
63
64
65
# File 'lib/optimize/harness.rb', line 59

def uninstall
  return unless @installed
  HOOKS.delete(@id)
  meta = class << RubyVM::InstructionSequence; self; end
  meta.remove_method(:load_iseq)
  @installed = false
end