1926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#!/usr/bin/env ruby
2926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
4926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#
5926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# Redistribution and use in source and binary forms, with or without
6926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# modification, are permitted provided that the following conditions
7926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# are met:
8926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# 1. Redistributions of source code must retain the above copyright
9926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#    notice, this list of conditions and the following disclaimer.
10926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# 2. Redistributions in binary form must reproduce the above copyright
11926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#    notice, this list of conditions and the following disclaimer in the
12926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#    documentation and/or other materials provided with the distribution.
13926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#
14926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)# THE POSSIBILITY OF SUCH DAMAGE.
25926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
26926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)require 'rubygems'
27926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
28926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)require 'readline'
29926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
30926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)begin
31926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    require 'json'
32926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    require 'highline'
33926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)rescue LoadError
34926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts "Error: some required gems are not installed!"
35926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts
36926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts "Try running:"
37926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts
38926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts "sudo gem install json"
39926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts "sudo gem install highline"
40926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    exit 1
41926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
42926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
43926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class Bytecode
44926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attr_accessor :bytecodes, :bytecodeIndex, :opcode, :description, :topCounts, :bottomCounts, :machineInlinees, :osrExits
45fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
46926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def initialize(bytecodes, bytecodeIndex, opcode, description)
47926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecodes = bytecodes
48926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecodeIndex = bytecodeIndex
49926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @opcode = opcode
50926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @description = description
51926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @topCounts = [] # "source" counts
52926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bottomCounts = {} # "machine" counts, maps compilations to counts
53926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @machineInlinees = {} # maps my compilation to a set of inlinees
54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @osrExits = []
55926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
56fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def shouldHaveCounts?
58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @opcode != "op_call_put_result"
59926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
60fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
61926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def addTopCount(count)
62926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @topCounts << count
63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
64fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def addBottomCountForCompilation(count, compilation)
66926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bottomCounts[compilation] = [] unless @bottomCounts[compilation]
67926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bottomCounts[compilation] << count
68926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
69fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def addMachineInlinee(compilation, inlinee)
71926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @machineInlinees[compilation] = {} unless @machineInlinees[compilation]
72926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @machineInlinees[compilation][inlinee] = true
73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
74fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
75926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def totalTopExecutionCount
76926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum = 0
77926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @topCounts.each {
78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | value |
79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            sum += value.count
80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
81926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum
82926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
83fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
84926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def topExecutionCount(engine)
85926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum = 0
86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @topCounts.each {
87926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | value |
88926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if value.engine == engine
89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                sum += value.count
90926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            end
91926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum
93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
94fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def totalBottomExecutionCount
96926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum = 0
97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bottomCounts.each_value {
98926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | counts |
99926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            max = 0
100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            counts.each {
101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                | value |
102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                max = [max, value.count].max
103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            sum += max
105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum
107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
108fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def bottomExecutionCount(engine)
110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum = 0
111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bottomCounts.each_pair {
112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | compilation, counts |
113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if compilation.engine == engine
114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                max = 0
115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                counts.each {
116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    | value |
117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    max = [max, value.count].max
118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                }
119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                sum += max
120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            end
121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum
123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
124fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def totalExitCount
126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum = 0
127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @osrExits.each {
128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | exit |
129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            sum += exit.count
130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum
132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class Bytecodes
136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attr_accessor :codeHash, :inferredName, :source, :instructionCount, :machineInlineSites, :compilations
137fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
138926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def initialize(json)
139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @codeHash = json["hash"].to_s
140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @inferredName = json["inferredName"].to_s
141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @source = json["sourceCode"].to_s
142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @instructionCount = json["instructionCount"].to_i
143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecode = {}
144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        json["bytecode"].each {
145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | subJson |
146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            index = subJson["bytecodeIndex"].to_i
147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            @bytecode[index] = Bytecode.new(self, index, subJson["opcode"].to_s, subJson["description"].to_s)
148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @machineInlineSites = {} # maps compilation to a set of origins
150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @compilations = []
151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
152fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def name(limit)
154926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if to_s.size > limit
155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            "\##{@codeHash}"
156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else
157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            to_s
158926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
160fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def to_s
162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        "#{@inferredName}\##{@codeHash}"
163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
164fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def matches(pattern)
166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if pattern =~ /^#/
167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            $~.post_match == @codeHash
168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        elsif pattern =~ /#/
169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            pattern == to_s
170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else
171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            pattern == @inferredName or pattern == @codeHash
172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
174fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def each
176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecode.values.sort{|a, b| a.bytecodeIndex <=> b.bytecodeIndex}.each {
177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | value |
178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            yield value
179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
181fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def bytecode(bytecodeIndex)
183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecode[bytecodeIndex]
184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
185fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def addMachineInlineSite(compilation, origin)
187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @machineInlineSites[compilation] = {} unless @machineInlineSites[compilation]
188926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @machineInlineSites[compilation][origin] = true
189926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
190fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def totalMachineInlineSites
192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum = 0
193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @machineInlineSites.each_value {
194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | set |
195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            sum += set.size
196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum
198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
199fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def sourceMachineInlineSites
201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        set = {}
202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @machineInlineSites.each_value {
203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | mySet |
204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            set.merge!(mySet)
205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        set.size
207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
208fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def totalMaxTopExecutionCount
210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        max = 0
211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecode.each_value {
212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | bytecode |
213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            max = [max, bytecode.totalTopExecutionCount].max
214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
215926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        max
216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
217fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def maxTopExecutionCount(engine)
219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        max = 0
220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecode.each_value {
221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | bytecode |
222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            max = [max, bytecode.topExecutionCount(engine)].max
223926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        max
225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
226fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def totalMaxBottomExecutionCount
228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        max = 0
229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecode.each_value {
230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | bytecode |
231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            max = [max, bytecode.totalBottomExecutionCount].max
232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        max
234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
235fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def maxBottomExecutionCount(engine)
237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        max = 0
238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecode.each_value {
239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | bytecode |
240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            max = [max, bytecode.bottomExecutionCount(engine)].max
241926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        max
243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
244fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def totalExitCount
246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum = 0
247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        each {
248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | bytecode |
249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            sum += bytecode.totalExitCount
250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sum
252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class ProfiledBytecode
256926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attr_reader :bytecodeIndex, :description
257fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
258926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def initialize(json)
259926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecodeIndex = json["bytecodeIndex"].to_i
260926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @description = json["description"].to_s
261926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
262926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
263926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class ProfiledBytecodes
265926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attr_reader :header, :bytecodes
266fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
267926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def initialize(json)
268926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @header = json["header"]
269926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecodes = $bytecodes[json["bytecodesID"].to_i]
270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @sequence = json["bytecode"].map {
271926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | subJson |
272926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            ProfiledBytecode.new(subJson)
273926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
274926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
275fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
276926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def each
277926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @sequence.each {
278926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | description |
279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            yield description
280926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
281926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
282926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
283926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
284926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)def originStackFromJSON(json)
285926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    json.map {
286926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        | subJson |
287926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        $bytecodes[subJson["bytecodesID"].to_i].bytecode(subJson["bytecodeIndex"].to_i)
288926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
289926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
291926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class CompiledBytecode
292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attr_accessor :origin, :description
293fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def initialize(json)
295926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @origin = originStackFromJSON(json["origin"])
296926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @description = json["description"].to_s
297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class ExecutionCounter
301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attr_accessor :origin, :engine, :count
302fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
303926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def initialize(origin, engine, count)
304926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @origin = origin
305926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @engine = engine
306926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @count = count
307926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
308926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
309926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
310926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class OSRExit
311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attr_reader :compilation, :origin, :codeAddresses, :exitKind, :isWatchpoint, :count
312fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def initialize(compilation, origin, codeAddresses, exitKind, isWatchpoint, count)
314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @compilation = compilation
315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @origin = origin
316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @codeAddresses = codeAddresses
317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @exitKind = exitKind
318926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @isWatchpoint = isWatchpoint
319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @count = count
320926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
321fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
322926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def dumpForDisplay(prefix)
323926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts(prefix + "EXIT: due to #{@exitKind}, #{@count} times")
324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class Compilation
328926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attr_accessor :bytecode, :engine, :descriptions, :counters, :compilationIndex
329926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attr_accessor :osrExits, :profiledBytecodes, :numInlinedGetByIds, :numInlinedPutByIds
330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attr_accessor :numInlinedCalls
331fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
332926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def initialize(json)
333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecode = $bytecodes[json["bytecodesID"].to_i]
334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @bytecode.compilations << self
335926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @compilationIndex = @bytecode.compilations.size
336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @engine = json["compilationKind"]
337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @descriptions = json["descriptions"].map {
338926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | subJson |
339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            CompiledBytecode.new(subJson)
340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
341926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @descriptions.each {
342926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | description |
343926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            next if description.origin.empty?
344926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            description.origin[1..-1].each_with_index {
345926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                | inlinee, index |
346926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                description.origin[0].addMachineInlinee(self, inlinee.bytecodes)
347926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                inlinee.bytecodes.addMachineInlineSite(self, description.origin[0...index])
348926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @counters = {}
351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        json["counters"].each {
352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | subJson |
353926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            origin = originStackFromJSON(subJson["origin"])
354926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            counter = ExecutionCounter.new(origin, @engine, subJson["executionCount"].to_i)
355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            @counters[origin] = counter
356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            origin[-1].addTopCount(counter)
357926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            origin[0].addBottomCountForCompilation(counter, self)
358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
359926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @osrExits = {}
360926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        json["osrExits"].each {
361926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | subJson |
362926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            osrExit = OSRExit.new(self, originStackFromJSON(subJson["origin"]),
363926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                  json["osrExitSites"][subJson["id"]].map {
364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                      | value |
365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                      value.hex
366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                  }, subJson["exitKind"], subJson["isWatchpoint"],
367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                  subJson["count"])
368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            osrExit.codeAddresses.each {
369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                | codeAddress |
370926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                osrExits[codeAddress] = [] unless osrExits[codeAddress]
371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                osrExits[codeAddress] << osrExit
372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            osrExit.origin[-1].osrExits << osrExit
374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @profiledBytecodes = []
376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        json["profiledBytecodes"].each {
377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | subJson |
378926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            @profiledBytecodes << ProfiledBytecodes.new(subJson)
379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @numInlinedGetByIds = json["numInlinedGetByIds"]
381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @numInlinedPutByIds = json["numInlinedPutByIds"]
382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @numInlinedCalls = json["numInlinedCalls"]
383926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
384fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
385926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def counter(origin)
386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @counters[origin]
387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
388fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
389926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def to_s
390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        "#{bytecode}-#{compilationIndex}-#{engine}"
391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class DescriptionLine
395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attr_reader :actualCountsString, :sourceCountsString, :disassembly, :shouldShow
396fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def initialize(actualCountsString, sourceCountsString, disassembly, shouldShow)
398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @actualCountsString = actualCountsString
399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @sourceCountsString = sourceCountsString
400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @disassembly = disassembly
401926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        @shouldShow = shouldShow
402926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
403fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
404926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def codeAddress
405926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if @disassembly =~ /^\s*(0x[0-9a-fA-F]+):/
406926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            $1.hex
407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else
408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            nil
409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
412fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
413926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)if ARGV.length != 1
414926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts "Usage: display-profiler-output <path to profiler output file>"
415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts
416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts "The typical usage pattern for the profiler currently looks something like:"
417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts
418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts "Path/To/jsc -p profile.json myprogram.js"
419926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $stderr.puts "display-profiler-output profile.json"
420926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    exit 1
421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
422926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)$json = JSON::parse(IO::read(ARGV[0]))
424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)$bytecodes = $json["bytecodes"].map {
425926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    | subJson |
426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Bytecodes.new(subJson)
427926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)$compilations = $json["compilations"].map {
429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    | subJson |
430926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Compilation.new(subJson)
431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
432926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)$engines = ["Baseline", "DFG"]
433926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
434926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)def lpad(str,chars)
435926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  if str.length>chars
436926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    str
437926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  else
438926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "%#{chars}s"%(str)
439926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  end
440926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
441926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
442926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)def rpad(str, chars)
443926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while str.length < chars
444926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        str += " "
445926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
446926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    str
447926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
448926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)def center(str, chars)
450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while str.length < chars
451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        str += " "
452926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if str.length < chars
453926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            str = " " + str
454926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
456926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    str
457926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
459926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)def mayBeHash(hash)
460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    hash =~ /#/ or hash.size == 6
461926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)def sourceOnOneLine(source, limit)
464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    source.gsub(/\s+/, ' ')[0...limit]
465926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)def screenWidth
468926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if $stdin.tty?
469926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        HighLine::SystemExtensions.terminal_size[0]
470926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
471926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        200
472926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
473926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
474926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
475926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)def summary(mode)
476926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    remaining = screenWidth
477fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
478926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    # Figure out how many columns we need for the code block names, and for counts
479926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    maxCount = 0
480926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    maxName = 0
481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $bytecodes.each {
482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        | bytecodes |
483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        maxCount = ([maxCount] + $engines.map {
484926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        | engine |
485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        bytecodes.maxTopExecutionCount(engine)
486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    } + $engines.map {
487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        | engine |
488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        bytecodes.maxBottomExecutionCount(engine)
489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    }).max
490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        maxName = [bytecodes.to_s.size, maxName].max
491926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
492926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    maxCountDigits = maxCount.to_s.size
493fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
494926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    hashCols = [[maxName, 30].min, "CodeBlock".size].max
495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    remaining -= hashCols + 1
496fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    countCols = [maxCountDigits * $engines.size, "Source Counts".size].max
498926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    remaining -= countCols + 1
499fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
500926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if mode == :full
501926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        instructionCountCols = 6
502926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        remaining -= instructionCountCols + 1
503fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
504926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        machineCountCols = [maxCountDigits * $engines.size, "Machine Counts".size].max
505926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        remaining -= machineCountCols + 1
506fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
507926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        compilationsCols = 7
508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        remaining -= compilationsCols + 1
509fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
510926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        inlinesCols = 9
511926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        remaining -= inlinesCols + 1
512fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
513926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        exitCountCols = 7
514926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        remaining -= exitCountCols + 1
515fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
516926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        recentOptsCols = 12
517926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        remaining -= recentOptsCols + 1
518926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
519fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
520926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if remaining > 0
521926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sourceCols = remaining
522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sourceCols = nil
524926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
525fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    print(center("CodeBlock", hashCols))
527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if mode == :full
528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + center("#Instr", instructionCountCols))
529926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
530926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    print(" " + center("Source Counts", countCols))
531926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if mode == :full
532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + center("Machine Counts", machineCountCols))
533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + center("#Compil", compilationsCols))
534926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + center("Inlines", inlinesCols))
535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + center("#Exits", exitCountCols))
536926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + center("Last Opts", recentOptsCols))
537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if sourceCols
539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + center("Source", sourceCols))
540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    puts
542fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    print(center("", hashCols))
544926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if mode == :full
545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + (" " * instructionCountCols))
546926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
547926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    print(" " + center("Base/DFG", countCols))
548926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if mode == :full
549926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + center("Base/DFG", machineCountCols))
550926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + (" " * compilationsCols))
551926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + center("Src/Total", inlinesCols))
552926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + (" " * exitCountCols))
553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " + center("Get/Put/Call", recentOptsCols))
554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    puts
556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    $bytecodes.sort {
557926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        | a, b |
558926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        b.totalMaxTopExecutionCount <=> a.totalMaxTopExecutionCount
559926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }.each {
560926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        | bytecode |
561926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(center(bytecode.name(hashCols), hashCols))
562926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if mode == :full
563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            print(" " + center(bytecode.instructionCount.to_s, instructionCountCols))
564926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        print(" " +
566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              center($engines.map {
567926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                         | engine |
568926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                         bytecode.maxTopExecutionCount(engine).to_s
569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                     }.join("/"), countCols))
570926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if mode == :full
571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            print(" " + center($engines.map {
572926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                   | engine |
573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                   bytecode.maxBottomExecutionCount(engine).to_s
574926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                               }.join("/"), machineCountCols))
575926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            print(" " + center(bytecode.compilations.size.to_s, compilationsCols))
576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            print(" " + center(bytecode.sourceMachineInlineSites.to_s + "/" + bytecode.totalMachineInlineSites.to_s, inlinesCols))
577926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            print(" " + center(bytecode.totalExitCount.to_s, exitCountCols))
578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            lastCompilation = bytecode.compilations[-1]
579926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if lastCompilation
580926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                optData = [lastCompilation.numInlinedGetByIds,
581926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                           lastCompilation.numInlinedPutByIds,
582926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                           lastCompilation.numInlinedCalls]
583926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            else
584926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                optData = ["N/A"]
585926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            end
586926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            print(" " + center(optData.join('/'), recentOptsCols))
587926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
588926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if sourceCols
589926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            print(" " + sourceOnOneLine(bytecode.source, sourceCols))
590926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
591926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts
592926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
593926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
594926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
595926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)def executeCommand(*commandArray)
596926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    command = commandArray[0]
597926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    args = commandArray[1..-1]
598926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case command
599926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    when "help", "h", "?"
600926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts "summary (s)     Print a summary of code block execution rates."
601926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts "full (f)        Same as summary, but prints more information."
602926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts "source          Show the source for a code block."
603926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts "bytecode (b)    Show the bytecode for a code block, with counts."
604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts "profiling (p)   Show the (internal) profiling data for a code block."
605926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts "display (d)     Display details for a code block."
606926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts "inlines         Show all inlining stacks that the code block was on."
607926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts "help (h)        Print this message."
608926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts "quit (q)        Quit."
609926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    when "quit", "q", "exit"
610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        exit 0
611926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    when "summary", "s"
612926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        summary(:summary)
613926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    when "full", "f"
614926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        summary(:full)
615926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    when "source"
616926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if args.length != 1
617926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            puts "Usage: source <code block hash>"
618926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return
619926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
620926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        $bytecodes.each {
621926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | bytecode |
622926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if bytecode.matches(args[0])
623926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                puts bytecode.source
624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            end
625926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
626926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    when "bytecode", "b"
627926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if args.length != 1
628926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            puts "Usage: source <code block hash>"
629926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return
630926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
631fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
632926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        hash = args[0]
633fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
634926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        countCols = 10 * $engines.size
635926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        machineCols = 10 * $engines.size
636926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        pad = 1
637926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        while (countCols + 1 + machineCols + pad) % 8 != 0
638926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            pad += 1
639926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
640fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
641926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        $bytecodes.each {
642926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | bytecodes |
643926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            next unless bytecodes.matches(hash)
644926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            puts(center("Source Counts", countCols) + " " + center("Machine Counts", machineCols) +
645926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                 (" " * pad) + center("Bytecode for #{bytecodes}", screenWidth - pad - countCols - 1 - machineCols))
646926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            puts(center("Base/DFG", countCols) + " " + center("Base/DFG", countCols))
647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            bytecodes.each {
648926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                | bytecode |
649926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if bytecode.shouldHaveCounts?
650926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    countsString = $engines.map {
651926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        | myEngine |
652926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        bytecode.topExecutionCount(myEngine)
653926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    }.join("/")
654926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    machineString = $engines.map {
655926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        | myEngine |
656926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        bytecode.bottomExecutionCount(myEngine)
657926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    }.join("/")
658926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                else
659926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    countsString = ""
660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    machineString = ""
661926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                end
662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                puts(center(countsString, countCols) + " " + center(machineString, machineCols) + (" " * pad) + bytecode.description.chomp)
663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                bytecode.osrExits.each {
664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    | exit |
665926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    puts(center("!!!!!", countCols) + " " + center("!!!!!", machineCols) + (" " * (pad + 10)) +
666926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                         "EXIT: in #{exit.compilation} due to #{exit.exitKind}, #{exit.count} times")
667926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                }
668926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
669926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    when "profiling", "p"
671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if args.length != 1
672926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            puts "Usage: profiling <code block hash>"
673926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return
674926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
675fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
676926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        hash = args[0]
677fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
678926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        first = true
679926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        $compilations.each {
680926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | compilation |
681fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
682926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            compilation.profiledBytecodes.each {
683926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                | profiledBytecodes |
684926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if profiledBytecodes.bytecodes.matches(hash)
685926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    if first
686926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        first = false
687926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    else
688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        puts
689926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    end
690fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
691926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    puts "Compilation #{compilation}:"
692926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    profiledBytecodes.header.each {
693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        | header |
694926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        puts(" " * 6 + header)
695926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    }
696926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    profiledBytecodes.each {
697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        | bytecode |
698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        puts(" " * 8 + bytecode.description)
699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        profiledBytecodes.bytecodes.bytecode(bytecode.bytecodeIndex).osrExits.each {
700926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            | exit |
701926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            if exit.compilation == compilation
702926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                puts(" !!!!!           EXIT: due to #{exit.exitKind}, #{exit.count} times")
703926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            end
704926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        }
705926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    }
706926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                end
707926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
708926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
709926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    when "inlines"
710926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if args.length != 1
711926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            puts "Usage: inlines <code block hash>"
712926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return
713926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
714fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
715926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        hash = args[0]
716fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
717926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        $bytecodes.each {
718926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | bytecodes |
719926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            next unless bytecodes.matches(hash)
720fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
721926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            # FIXME: print something useful to say more about which code block this is.
722fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
723926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            $compilations.each {
724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                | compilation |
725926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                myOrigins = []
726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                compilation.descriptions.each {
727926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    | description |
728926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    if description.origin.index {
729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            | myBytecode |
730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            bytecodes == myBytecode.bytecodes
731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        }
732926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        myOrigins << description.origin
733926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    end
734926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                }
735926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                myOrigins.uniq!
736926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                myOrigins.sort! {
737926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    | a, b |
738926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    result = 0
739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    [a.size, b.size].min.times {
740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        | index |
741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        result = a[index].bytecodeIndex <=> b[index].bytecodeIndex
742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        break if result != 0
743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    }
744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    result
745926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                }
746fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                next if myOrigins.empty?
748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
749926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                printArray = []
750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                lastPrintStack = []
751fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
752926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                def originToPrintStack(origin)
753926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    (0...(origin.size - 1)).map {
754926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        | index |
755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        "bc\##{origin[index].bytecodeIndex} --> #{origin[index + 1].bytecodes}"
756926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    }
757926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                end
758fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
759926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                def printStack(printArray, stack, lastStack)
760926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    stillCommon = true
761926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    stack.each_with_index {
762926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        | entry, index |
763926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        next if stillCommon and entry == lastStack[index]
764926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        printArray << ("    " * (index + 1) + entry)
765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        stillCommon = false
766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    }
767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                end
768fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
769926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                myOrigins.each {
770926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    | origin |
771926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    currentPrintStack = originToPrintStack(origin)
772926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    printStack(printArray, currentPrintStack, lastPrintStack)
773926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    lastPrintStack = currentPrintStack
774926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                }
775926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
776926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                next if printArray.empty?
777fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
778926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                puts "Compilation #{compilation}:"
779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                printArray.each {
780926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    | entry |
781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    puts entry
782926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                }
783926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
784926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
785926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    when "display", "d"
786926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        compilationIndex = nil
787fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
788926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        case args.length
789926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        when 1
790926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if args[0] == "*"
791926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                hash = nil
792926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            else
793926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                hash = args[0]
794926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            end
795926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            engine = nil
796926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        when 2
797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if mayBeHash(args[0])
798926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                hash = args[0]
799926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                engine = args[1]
800926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            else
801926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                engine = args[0]
802926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                hash = args[1]
803926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            end
804926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else
805926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            puts "Usage: summary <code block hash> <engine>"
806926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return
807926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
808fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
809926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if hash and hash =~ /-([0-9]+)-/
810926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            hash = $~.pre_match
811926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            engine = $~.post_match
812926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            compilationIndex = $1.to_i
813926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
814fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
815926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if engine and not $engines.index(engine)
816926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            pattern = Regexp.new(Regexp.escape(engine), "i")
817926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            trueEngine = nil
818926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            $engines.each {
819926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                | myEngine |
820926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if myEngine =~ pattern
821926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    trueEngine = myEngine
822926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    break
823926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                end
824926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
825926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            unless trueEngine
826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                puts "#{engine} is not a valid engine, try #{$engines.join(' or ')}."
827926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                return
828926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            end
829926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            engine = trueEngine
830926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        end
831fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
832926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        actualCountCols = 13
833926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sourceCountCols = 10 * $engines.size
834fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
835926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        first = true
836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        $compilations.each {
837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            | compilation |
838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            next if hash and not compilation.bytecode.matches(hash)
839926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            next if engine and compilation.engine != engine
840926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            next if compilationIndex and compilation.compilationIndex != compilationIndex
841fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
842926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if first
843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                first = false
844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            else
845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                puts
846926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            end
847fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
848926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            puts("Compilation #{compilation}:")
849926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            puts("    Num inlined: GetByIds: #{compilation.numInlinedGetByIds}  PutByIds: #{compilation.numInlinedPutByIds}  Calls: #{compilation.numInlinedCalls}")
850926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            puts(center("Actual Counts", actualCountCols) + " " + center("Source Counts", sourceCountCols) + " " + center("Disassembly in #{compilation.engine}", screenWidth - 1 - sourceCountCols - 1 - actualCountCols))
851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            puts((" " * actualCountCols) + " " + center("Base/DFG", sourceCountCols))
852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            lines = []
854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            compilation.descriptions.each {
856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                | description |
857926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                # FIXME: We should have a better way of detecting things like CountExecution nodes
858926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                # and slow path entries in the baseline JIT.
859926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if description.description =~ /CountExecution\(/ and compilation.engine == "DFG"
860926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    shouldShow = false
861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                else
862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    shouldShow = true
863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                end
864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if description.origin.empty? or not description.origin[-1].shouldHaveCounts? or (compilation.engine == "Baseline" and description.description =~ /^\s*\(S\)/)
865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    actualCountsString = ""
866926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    sourceCountsString = ""
867926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                else
868926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    actualCountsString = compilation.counter(description.origin).count.to_s
869926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    sourceCountsString = $engines.map {
870926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        | myEngine |
871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        description.origin[-1].topExecutionCount(myEngine)
872926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    }.join("/")
873926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                end
874926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                description.description.split("\n").each {
875926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    | line |
876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    lines << DescriptionLine.new(actualCountsString, sourceCountsString, line.chomp, shouldShow)
877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                }
878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
879fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
880926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            exitPrefix = center("!!!!!", actualCountCols) + " " + center("!!!!!", sourceCountCols) + (" " * 25)
881fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            lines.each_with_index {
883926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                | line, index |
884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                codeAddress = line.codeAddress
885926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if codeAddress
886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    list = compilation.osrExits[codeAddress]
887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    if list
888926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        list.each {
889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            | exit |
890926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            if exit.isWatchpoint
891926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                exit.dumpForDisplay(exitPrefix)
892926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            end
893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        }
894926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    end
895926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                end
896926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if line.shouldShow
897926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    puts(center(line.actualCountsString, actualCountCols) + " " + center(line.sourceCountsString, sourceCountCols) + " " + line.disassembly)
898926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                end
899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if codeAddress
900926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    # Find the next disassembly address.
901926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    endIndex = index + 1
902926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    endAddress = nil
903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    while endIndex < lines.size
904926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        myAddress = lines[endIndex].codeAddress
905926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        if myAddress
906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            endAddress = myAddress
907926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            break
908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        end
909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        endIndex += 1
910926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    end
911fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
912926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    if endAddress
913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        list = compilation.osrExits[endAddress]
914926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        if list
915926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            list.each {
916926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                | exit |
917926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                unless exit.isWatchpoint
918926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                    exit.dumpForDisplay(exitPrefix)
919926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                end
920926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            }
921926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        end
922926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    end
923926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                end
924926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
926926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        puts "Invalid command: #{command}"
928926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    end
929926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
930926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
931926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)if $stdin.tty?
932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    executeCommand("full")
933926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
934926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
935926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)while commandLine = Readline.readline("> ", true)
936926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    executeCommand(*commandLine.split)
937926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)end
938926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
939