3 if defined?(RUBY_ENGINE) and RUBY_ENGINE == 'rbx'
4 Object.const_set(:Compiler, Compile.compiler)
5 require 'compiler/text'
8 require File.join(File.dirname(__FILE__), '..', 'compiler', 'mri_shim')
11 def record_block(data, block)
12 record_seq data, block.dup
13 0.upto(block.size - 3) do |start|
15 seq = block[start, size]
16 record_seq data, seq if seq.size > 1
21 def record_seq(data, seq)
30 Terms = [:goto, :goto_if_false, :goto_if_true]
32 def walk_stream(stream, data)
36 if Terms.include? inst.first
38 record_block data, seq
44 record_block data, seq if seq.size > 1
47 def update_data(stream, data, extra)
48 stream.each_with_index do |inst, i|
51 next_inst = stream[i + x + 1]
52 return unless next_inst
53 combo << next_inst.first
57 data[combo] = count + 1
64 def describe_compiled_code(code, data, max)
65 extra = code.literals.to_a.find_all { |l| l.kind_of? CompiledCode }
67 name = code.name ? code.name.inspect : 'anonymous'
68 stream = code.iseq.decode
70 walk_stream stream, data
73 update_data stream, data[size], size - 1
79 describe_compiled_code(sub, data, max)
80 extra += sub.literals.to_a.find_all { |l| l.kind_of? CompiledCode }
85 # Temporary workaround for Rubinius bug in __FILE__ paths
86 if __FILE__.include?($0) then
90 while arg = ARGV.shift
93 other_paths = $1[2..-1].split(":")
94 other_paths.each { |n| $:.unshift n }
110 out = ARGV.shift or "analyze.yml"
114 puts "Gathering data on #{file}..."
117 data = Marshal.load File.read(out)
121 2.upto(max) do |size|
122 data[size] = Hash.new
128 top = Compiler.compile_file(file, flags)
129 describe_compiled_code(top, data, max)
135 File.open out, "w" do |f|
136 f << Marshal.dump(data)