2 require "src/dispatcher.rb"
8 def do_blah src, expected, expected_counts = nil
10 tempfile = Tempfile.new "rblex_test"
29 @data = [string.length]
30 string.each_byte { |b| @data << b }
44 expected = `bash -c "ruby #{tempfile.path} 2>&1"`
48 machine = EvalMachine.new t, src
56 method(meth).call(machine)
59 if expected.is_a? Regexp
60 assert_equal [expected, !(expected =~ $str_buffer).nil?], [expected, true]
62 assert_equal expected, $str_buffer
65 actual = "actual: [#{machine.number_of_instructions_executed}, #{machine.number_of_generated_instructions}]"
66 fail "no expected counts given!, #{actual}" \
67 if expected_counts.nil?
68 diff = (machine.number_of_instructions_executed-expected_counts[0]).abs
69 error_ratio = diff.to_f / machine.number_of_instructions_executed.to_f
71 fail "error perc.: #{(error_ratio * 100).to_i}%, #{actual} vs expected #{expected_counts.inspect}"
73 fail "number_of_generated_instructions did not match! #{actual}" \
74 if expected_counts[1] != machine.number_of_generated_instructions
77 def do_test ctx, string, should_be
78 execute_string ctx, string
79 assert_equal should_be, $str_buffer
82 def fmt machine, tuple, func
83 return "initial" if tuple.nil?
84 node = machine.crawler.find_path machine.crawler.id2path(tuple[1])
88 "#{tuple[0]} - #{tuple[1]} [#{desc[0..20]}]"
91 # TODO items - word ( => ) wrap the hashes / which will eventualy be structs, so, figure out word wrapping for those too
96 def dump_summary machine
98 puts "Total number of instructions in all functions: #{machine.number_of_generated_instructions}"
99 puts "Total number of instructions executed: #{machine.number_of_instructions_executed}"
103 def self.metadata_dump machine
104 puts "Reporting on in cached function metadata"
105 machine.func_cache.each_pair {
107 next unless id.is_a? Integer
108 print "IS : #{machine.crawler.paths2orderdesc atom.func.metadata[:path_range].map { |id| machine.crawler.id2path id }}"
109 print "JUMPS TO : #{machine.crawler.paths2orderdesc atom.func.metadata[:statically_dispatches_to].map { |(id, pos)| machine.crawler.id2path id }}" if atom.func.metadata[:statically_dispatches_to]
111 pp machine.metadata_inspect(atom.func.metadata)
116 def self.dump_max_point machine
117 self.metadata_dump machine
119 shifted_log = machine.time_vs_instructions_log.slice(1..-1)
121 machine.time_vs_instructions_log.zip(shifted_log) { |arr| a,b = *arr; diffs << (b[1]-a[1]).abs unless b.nil? }
122 max_point = diffs.max
123 puts "non unique max point! o_O" if diffs.index(max_point) != diffs.rindex(max_point)
124 idx = diffs.index max_point
126 p machine.time_vs_instructions_log
132 p machine.time_vs_instructions_log[idx]
137 machine.old_functions.each {
139 dump_instructions func
143 def dump_profile machine
144 line2count = Hash.new { 0 }
145 machine.old_functions.each {
147 next if func.profile_hash.nil?
148 func.profile_hash.each_pair {
150 line = func.metadata[:caller_map][key]
151 line2count[line] += val
155 line2count.inject([]) { |a,(k,d)| a << [k, d] }
156 pp line2count.sort_by { |(a,b)| b }
160 def dump_graph machine
162 machine.func_cache.each_pair {
164 next unless id.is_a? Integer
165 atom.func.metadata[:path_range].each {
167 curr = [atom.func.object_id, sid]
168 nodes << "\"#{fmt machine, curr, atom.func}\" [color=green];"
171 machine.import_from_trace_stack
172 first_iteration = true
176 execution_log << func
178 machine.trace_stack_history.each {
180 machine.trace_stack_iterator(trace_stack.dat) {
182 boo.call old_func if first_iteration
184 first_iteration = false
191 curr = [t.object_id, machine.md_get_id(t)]
192 nodes << "\"#{fmt machine, prev, t}\" -> \"#{fmt machine, curr, t}\" [color=green label=\"#{idx}\"];"
196 tf = File.open "/tmp/blah.dot", "w"
197 desc = "\"#{machine.crawler.paths2orderdesc(machine.ast_order).gsub(/\n\s*#/m,"#").gsub("\n","\\n")}\" [color=blue shape=plaintext];"
200 node [ style = filled ];
203 \"#{machine.source.gsub("\n","\\n")} [shape=plaintext]\"