Fixed some C/C++ compiler errors due to stricter checks.
[rubinius.git] / machine / super-instruction / analyze.rb
blob81c4f42e9cc9c5b06e53ab95e6330ba874e140d0
1 require 'pp'
3 if defined?(RUBY_ENGINE) and RUBY_ENGINE == 'rbx'
4   Object.const_set(:Compiler, Compile.compiler)
5   require 'compiler/text'
6 else
7   $: << 'lib'
8   require File.join(File.dirname(__FILE__), '..', 'compiler', 'mri_shim')
9 end
11 def record_block(data, block)
12   record_seq data, block.dup
13   0.upto(block.size - 3) do |start|
14     2.upto(10) do |size|
15       seq = block[start, size]
16       record_seq data, seq if seq.size > 1
17     end
18   end
19 end
21 def record_seq(data, seq)
22   count = data[seq]
23   if count
24     data[seq] = count + 1
25   else
26     data[seq] = 1
27   end
28 end
30 Terms = [:goto, :goto_if_false, :goto_if_true]
32 def walk_stream(stream, data)
33   seq = []
34   stream.each do |inst|
35     seq << inst.first
36     if Terms.include? inst.first
37       if seq.size > 1
38         record_block data, seq
39       end
40       seq = []
41     end
42   end
44   record_block data, seq if seq.size > 1
45 end
47 def update_data(stream, data, extra)
48   stream.each_with_index do |inst, i|
49     combo = [inst.first]
50     extra.times do |x|
51       next_inst = stream[i + x + 1]
52       return unless next_inst
53       combo << next_inst.first
54     end
55     count = data[combo]
56     if count
57       data[combo] = count + 1
58     else
59       data[combo] = 1
60     end
61   end
62 end
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
71 =begin
72   2.upto(max) do |size|
73     update_data stream, data[size], size - 1
74   end
75 =end
77   until extra.empty?
78     sub = extra.shift
79     describe_compiled_code(sub, data, max)
80     extra += sub.literals.to_a.find_all { |l| l.kind_of? CompiledCode }
81   end
83 end
85 # Temporary workaround for Rubinius bug in __FILE__ paths
86 if __FILE__.include?($0) then
87   flags = []
88   file = nil
90   while arg = ARGV.shift
91     case arg
92     when /-I(.+)/ then
93       other_paths = $1[2..-1].split(":")
94       other_paths.each { |n| $:.unshift n }
95     when /-f(.+)/ then
96       flags << $1
97     else
98       file = arg
99       break
100     end
101   end
103   unless file
104     interactive()
105     exit 0
106   end
108   require 'yaml'
110   out = ARGV.shift or "analyze.yml"
112   max = 10
114   puts "Gathering data on #{file}..."
116   if File.exists?(out)
117     data = Marshal.load File.read(out)
118   else
119     data = Hash.new
120 =begin
121     2.upto(max) do |size|
122       data[size] = Hash.new
123     end
124 =end
125   end
127   begin
128     top = Compiler.compile_file(file, flags)
129     describe_compiled_code(top, data, max)
131   rescue SyntaxError
132     exit 1
133   end
135   File.open out, "w" do |f|
136     f << Marshal.dump(data)
137   end