1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockfunction inherits(childCtor, parentCtor) {
301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  childCtor.prototype.__proto__ = parentCtor.prototype;
311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockfunction V8Profile(separateIc) {
351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Profile.call(this);
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!separateIc) {
371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    this.skipThisFunction = function(name) { return V8Profile.IC_RE.test(name); };
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockinherits(V8Profile, Profile);
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
431e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockV8Profile.IC_RE =
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /^(?:CallIC|LoadIC|StoreIC)|(?:Builtin: (?:Keyed)?(?:Call|Load|Store)IC_)/;
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * A thin wrapper around shell's 'read' function showing a file name on error.
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction readFile(fileName) {
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try {
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return read(fileName);
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } catch (e) {
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    print(fileName + ': ' + (e.message || e));
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw e;
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch/**
61e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * Parser for dynamic code optimization state.
62e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch */
63e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochfunction parseState(s) {
64e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  switch (s) {
65e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  case "": return Profile.CodeState.COMPILED;
66e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  case "~": return Profile.CodeState.OPTIMIZABLE;
67e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  case "*": return Profile.CodeState.OPTIMIZED;
68e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
69e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  throw new Error("unknown code state: " + s);
70e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
71e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
72e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
73e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkefunction SnapshotLogProcessor() {
741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LogReader.call(this, {
75e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      'code-creation': {
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'],
77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          processor: this.processCodeCreation },
78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      'code-move': { parsers: [parseInt, parseInt],
79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          processor: this.processCodeMove },
80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      'code-delete': { parsers: [parseInt],
81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          processor: this.processCodeDelete },
823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      'function-creation': null,
833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      'function-move': null,
843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      'function-delete': null,
85e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      'sfi-move': null,
86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      'snapshot-pos': { parsers: [parseInt, parseInt],
87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          processor: this.processSnapshotPosition }});
88e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  V8Profile.prototype.handleUnknownCode = function(operation, addr) {
901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    var op = Profile.Operation;
91e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    switch (operation) {
92e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case op.MOVE:
93e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        print('Snapshot: Code move event for unknown code: 0x' +
94e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              addr.toString(16));
95e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
96e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case op.DELETE:
97e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        print('Snapshot: Code delete event for unknown code: 0x' +
98e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              addr.toString(16));
99e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  };
102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  this.profile_ = new V8Profile();
104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  this.serializedEntries_ = [];
105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockinherits(SnapshotLogProcessor, LogReader);
107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeSnapshotLogProcessor.prototype.processCodeCreation = function(
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    type, kind, start, size, name, maybe_func) {
111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_func.length) {
112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    var funcAddr = parseInt(maybe_func[0]);
113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    var state = parseState(maybe_func[1]);
114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    this.profile_.addFuncCode(type, name, start, size, funcAddr, state);
115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    this.profile_.addCode(type, name, start, size);
117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeSnapshotLogProcessor.prototype.processCodeMove = function(from, to) {
122e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  this.profile_.moveCode(from, to);
123e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
124e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeSnapshotLogProcessor.prototype.processCodeDelete = function(start) {
127e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  this.profile_.deleteCode(start);
128e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
131e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeSnapshotLogProcessor.prototype.processSnapshotPosition = function(addr, pos) {
132e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  this.serializedEntries_[pos] = this.profile_.findEntry(addr);
133e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
134e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
135e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeSnapshotLogProcessor.prototype.processLogFile = function(fileName) {
137e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  var contents = readFile(fileName);
138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  this.processLogChunk(contents);
139e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeSnapshotLogProcessor.prototype.getSerializedEntryName = function(pos) {
143e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  var entry = this.serializedEntries_[pos];
144e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return entry ? entry.getRawName() : null;
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction TickProcessor(
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cppEntriesProvider,
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    separateIc,
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    callGraphSize,
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ignoreUnknown,
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    stateFilter,
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    snapshotLogProcessor,
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    distortion,
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    range,
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sourceMap) {
1581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LogReader.call(this, {
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      'shared-library': { parsers: [null, parseInt, parseInt],
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          processor: this.processSharedLibrary },
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      'code-creation': {
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'],
163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          processor: this.processCodeCreation },
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      'code-move': { parsers: [parseInt, parseInt],
165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          processor: this.processCodeMove },
166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      'code-delete': { parsers: [parseInt],
167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          processor: this.processCodeDelete },
168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      'sfi-move': { parsers: [parseInt, parseInt],
169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          processor: this.processFunctionMove },
170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      'snapshot-pos': { parsers: [parseInt, parseInt],
171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          processor: this.processSnapshotPosition },
17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      'tick': {
17344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          parsers: [parseInt, parseInt, parseInt,
17444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    parseInt, parseInt, 'var-args'],
175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          processor: this.processTick },
1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      'heap-sample-begin': { parsers: [null, null, parseInt],
1773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          processor: this.processHeapSampleBegin },
1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      'heap-sample-end': { parsers: [null, null],
1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          processor: this.processHeapSampleEnd },
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'timer-event-start' : { parsers: [null, null, null],
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              processor: this.advanceDistortion },
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'timer-event-end' : { parsers: [null, null, null],
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            processor: this.advanceDistortion },
1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Ignored events.
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      'profiler': null,
186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      'function-creation': null,
187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      'function-move': null,
188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      'function-delete': null,
1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      'heap-sample-item': null,
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Obsolete row types.
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      'code-allocate': null,
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      'begin-code-region': null,
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      'end-code-region': null });
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.cppEntriesProvider_ = cppEntriesProvider;
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  this.callGraphSize_ = callGraphSize;
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.ignoreUnknown_ = ignoreUnknown;
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.stateFilter_ = stateFilter;
199e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  this.snapshotLogProcessor_ = snapshotLogProcessor;
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.sourceMap = sourceMap;
201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  this.deserializedEntriesNames_ = [];
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var ticks = this.ticks_ =
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    { total: 0, unaccounted: 0, excluded: 0, gc: 0 };
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  distortion = parseInt(distortion);
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Convert picoseconds to nanoseconds.
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.distortion_per_entry = isNaN(distortion) ? 0 : (distortion / 1000);
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.distortion = 0;
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var rangelimits = range ? range.split(",") : [];
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var range_start = parseInt(rangelimits[0]);
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var range_end = parseInt(rangelimits[1]);
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Convert milliseconds to nanoseconds.
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.range_start = isNaN(range_start) ? -Infinity : (range_start * 1000);
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.range_end = isNaN(range_end) ? Infinity : (range_end * 1000)
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  V8Profile.prototype.handleUnknownCode = function(
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      operation, addr, opt_stackPos) {
2181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    var op = Profile.Operation;
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (operation) {
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case op.MOVE:
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        print('Code move event for unknown code: 0x' + addr.toString(16));
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case op.DELETE:
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        print('Code delete event for unknown code: 0x' + addr.toString(16));
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case op.TICK:
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Only unknown PCs (the first frame) are reported as unaccounted,
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // otherwise tick balance will be corrupted (this behavior is compatible
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // with the original tickprocessor.py script.)
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (opt_stackPos == 0) {
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ticks.unaccounted++;
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  this.profile_ = new V8Profile(separateIc);
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.codeTypes_ = {};
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Count each tick as a time unit.
2401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  this.viewBuilder_ = new ViewBuilder(1);
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.lastLogFileName_ = null;
2423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  this.generation_ = 1;
2443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  this.currentProducerProfile_ = null;
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockinherits(TickProcessor, LogReader);
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.VmStates = {
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JS: 0,
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GC: 1,
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  COMPILER: 2,
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OTHER: 3,
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EXTERNAL: 4,
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IDLE: 5
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.CodeTypes = {
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CPP: 0,
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SHARED_LIB: 1
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Otherwise, this is JS-related code. We are not adding it to
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// codeTypes_ map because there can be zillions of them.
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.CALL_PROFILE_CUTOFF_PCT = 2.0;
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTickProcessor.CALL_GRAPH_SIZE = 5;
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @override
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.printError = function(str) {
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  print(str);
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.setCodeType = function(name, type) {
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.codeTypes_[name] = TickProcessor.CodeTypes[type];
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.isSharedLibrary = function(name) {
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this.codeTypes_[name] == TickProcessor.CodeTypes.SHARED_LIB;
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.isCppCode = function(name) {
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this.codeTypes_[name] == TickProcessor.CodeTypes.CPP;
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.isJsCode = function(name) {
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return !(name in this.codeTypes_);
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.processLogFile = function(fileName) {
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.lastLogFileName_ = fileName;
3013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  var line;
3023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  while (line = readline()) {
3033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    this.processLogLine(line);
3043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
3053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu};
3063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuTickProcessor.prototype.processLogFileInTest = function(fileName) {
3093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu   // Hack file name to avoid dealing with platform specifics.
3103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  this.lastLogFileName_ = 'v8.log';
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var contents = readFile(fileName);
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.processLogChunk(contents);
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.processSharedLibrary = function(
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    name, startAddr, endAddr) {
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var entry = this.profile_.addLibrary(name, startAddr, endAddr);
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.setCodeType(entry.getName(), 'SHARED_LIB');
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var self = this;
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var libFuncs = this.cppEntriesProvider_.parseVmSymbols(
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      name, startAddr, endAddr, function(fName, fStart, fEnd) {
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    self.profile_.addStaticCode(fName, fStart, fEnd);
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    self.setCodeType(fName, 'CPP');
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  });
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.processCodeCreation = function(
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    type, kind, start, size, name, maybe_func) {
332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  name = this.deserializedEntriesNames_[start] || name;
333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_func.length) {
334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    var funcAddr = parseInt(maybe_func[0]);
335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    var state = parseState(maybe_func[1]);
336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    this.profile_.addFuncCode(type, name, start, size, funcAddr, state);
337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    this.profile_.addCode(type, name, start, size);
339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.processCodeMove = function(from, to) {
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile_.moveCode(from, to);
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.processCodeDelete = function(start) {
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile_.deleteCode(start);
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
353d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeTickProcessor.prototype.processFunctionMove = function(from, to) {
354e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  this.profile_.moveFunc(from, to);
355d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
356d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
357d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeTickProcessor.prototype.processSnapshotPosition = function(addr, pos) {
359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (this.snapshotLogProcessor_) {
360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    this.deserializedEntriesNames_[addr] =
361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      this.snapshotLogProcessor_.getSerializedEntryName(pos);
362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.includeTick = function(vmState) {
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this.stateFilter_ == null || this.stateFilter_ == vmState;
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTickProcessor.prototype.processTick = function(pc,
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               ns_since_start,
37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               is_external_callback,
37344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               tos_or_external_callback,
37444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               vmState,
37544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               stack) {
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.distortion += this.distortion_per_entry;
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ns_since_start -= this.distortion;
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (ns_since_start < this.range_start || ns_since_start > this.range_end) {
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.ticks_.total++;
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (vmState == TickProcessor.VmStates.GC) this.ticks_.gc++;
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!this.includeTick(vmState)) {
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.ticks_.excluded++;
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
38744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_external_callback) {
38844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Don't use PC when in external callback code, as it can point
38944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // inside callback's code, and we will erroneously report
3908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // that a callback calls itself. Instead we use tos_or_external_callback,
3918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // as simply resetting PC will produce unaccounted ticks.
3928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    pc = tos_or_external_callback;
3938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    tos_or_external_callback = 0;
39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (tos_or_external_callback) {
39544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Find out, if top of stack was pointing inside a JS function
39644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // meaning that we have encountered a frameless invocation.
39744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    var funcEntry = this.profile_.findEntry(tos_or_external_callback);
398d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (!funcEntry || !funcEntry.isJSFunction || !funcEntry.isJSFunction()) {
39944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      tos_or_external_callback = 0;
400d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
401d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
402d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
40344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  this.profile_.recordTick(this.processStack(pc, tos_or_external_callback, stack));
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTickProcessor.prototype.advanceDistortion = function() {
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.distortion += this.distortion_per_entry;
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTickProcessor.prototype.processHeapSampleBegin = function(space, state, ticks) {
4133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (space != 'Heap') return;
4141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  this.currentProducerProfile_ = new CallTree();
4153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block};
4163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTickProcessor.prototype.processHeapSampleEnd = function(space, state) {
4193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (space != 'Heap' || !this.currentProducerProfile_) return;
4203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  print('Generation ' + this.generation_ + ':');
4223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  var tree = this.currentProducerProfile_;
4233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  tree.computeTotalWeights();
4243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  var producersView = this.viewBuilder_.buildView(tree);
4253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Sort by total time, desc, then by name, desc.
4263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  producersView.sort(function(rec1, rec2) {
4273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      return rec2.totalTime - rec1.totalTime ||
4283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          (rec2.internalFuncName < rec1.internalFuncName ? -1 : 1); });
4293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  this.printHeavyProfile(producersView.head.children);
4303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  this.currentProducerProfile_ = null;
4323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  this.generation_++;
4333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block};
4343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.printStatistics = function() {
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  print('Statistical profiling result from ' + this.lastLogFileName_ +
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ', (' + this.ticks_.total +
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ' ticks, ' + this.ticks_.unaccounted + ' unaccounted, ' +
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this.ticks_.excluded + ' excluded).');
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (this.ticks_.total == 0) return;
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var flatProfile = this.profile_.getFlatProfile();
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var flatView = this.viewBuilder_.buildView(flatProfile);
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sort by self time, desc, then by name, desc.
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  flatView.sort(function(rec1, rec2) {
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return rec2.selfTime - rec1.selfTime ||
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          (rec2.internalFuncName < rec1.internalFuncName ? -1 : 1); });
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var totalTicks = this.ticks_.total;
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (this.ignoreUnknown_) {
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    totalTicks -= this.ticks_.unaccounted;
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Count library ticks
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var flatViewNodes = flatView.head.children;
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var self = this;
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var libraryTicks = 0;
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.printHeader('Shared libraries');
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.printEntries(flatViewNodes, totalTicks, null,
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      function(name) { return self.isSharedLibrary(name); },
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      function(rec) { libraryTicks += rec.selfTime; });
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var nonLibraryTicks = totalTicks - libraryTicks;
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var jsTicks = 0;
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.printHeader('JavaScript');
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.printEntries(flatViewNodes, totalTicks, nonLibraryTicks,
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      function(name) { return self.isJsCode(name); },
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      function(rec) { jsTicks += rec.selfTime; });
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var cppTicks = 0;
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.printHeader('C++');
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.printEntries(flatViewNodes, totalTicks, nonLibraryTicks,
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      function(name) { return self.isCppCode(name); },
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      function(rec) { cppTicks += rec.selfTime; });
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.printHeader('Summary');
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.printLine('JavaScript', jsTicks, totalTicks, nonLibraryTicks);
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.printLine('C++', cppTicks, totalTicks, nonLibraryTicks);
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.printLine('GC', this.ticks_.gc, totalTicks, nonLibraryTicks);
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.printLine('Shared libraries', libraryTicks, totalTicks, null);
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!this.ignoreUnknown_ && this.ticks_.unaccounted > 0) {
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    this.printLine('Unaccounted', this.ticks_.unaccounted,
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   this.ticks_.total, null);
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.printHeavyProfHeader();
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var heavyProfile = this.profile_.getBottomUpProfile();
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var heavyView = this.viewBuilder_.buildView(heavyProfile);
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // To show the same percentages as in the flat profile.
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  heavyView.head.totalTime = totalTicks;
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sort by total time, desc, then by name, desc.
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  heavyView.sort(function(rec1, rec2) {
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return rec2.totalTime - rec1.totalTime ||
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          (rec2.internalFuncName < rec1.internalFuncName ? -1 : 1); });
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.printHeavyProfile(heavyView.head.children);
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction padLeft(s, len) {
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  s = s.toString();
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (s.length < len) {
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var padLength = len - s.length;
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!(padLength in padLeft)) {
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      padLeft[padLength] = new Array(padLength + 1).join(' ');
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    s = padLeft[padLength] + s;
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return s;
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.printHeader = function(headerTitle) {
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  print('\n [' + headerTitle + ']:');
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  print('   ticks  total  nonlib   name');
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTickProcessor.prototype.printLine = function(
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    entry, ticks, totalTicks, nonLibTicks) {
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var pct = ticks * 100 / totalTicks;
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var nonLibPct = nonLibTicks != null
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? padLeft((ticks * 100 / nonLibTicks).toFixed(1), 5) + '%  '
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : '        ';
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  print('  ' + padLeft(ticks, 5) + '  ' +
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        padLeft(pct.toFixed(1), 5) + '%  ' +
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        nonLibPct +
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        entry);
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.printHeavyProfHeader = function() {
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  print('\n [Bottom up (heavy) profile]:');
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  print('  Note: percentage shows a share of a particular caller in the ' +
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'total\n' +
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        '  amount of its parent calls.');
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  print('  Callers occupying less than ' +
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        TickProcessor.CALL_PROFILE_CUTOFF_PCT.toFixed(1) +
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        '% are not shown.\n');
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  print('   ticks parent  name');
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.processProfile = function(
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    profile, filterP, func) {
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0, n = profile.length; i < n; ++i) {
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var rec = profile[i];
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!filterP(rec.internalFuncName)) {
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    func(rec);
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTickProcessor.prototype.getLineAndColumn = function(name) {
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var re = /:([0-9]+):([0-9]+)$/;
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var array = re.exec(name);
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!array) {
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return null;
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return {line: array[1], column: array[2]};
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTickProcessor.prototype.hasSourceMap = function() {
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return this.sourceMap != null;
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTickProcessor.prototype.formatFunctionName = function(funcName) {
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!this.hasSourceMap()) {
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return funcName;
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var lc = this.getLineAndColumn(funcName);
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (lc == null) {
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return funcName;
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in source maps lines and columns are zero based
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var lineNumber = lc.line - 1;
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var column = lc.column - 1;
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var entry = this.sourceMap.findEntry(lineNumber, column);
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var sourceFile = entry[2];
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var sourceLine = entry[3] + 1;
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var sourceColumn = entry[4] + 1;
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return sourceFile + ':' + sourceLine + ':' + sourceColumn + ' -> ' + funcName;
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.printEntries = function(
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    profile, totalTicks, nonLibTicks, filterP, callback) {
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var that = this;
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.processProfile(profile, filterP, function (rec) {
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (rec.selfTime == 0) return;
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    callback(rec);
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    var funcName = that.formatFunctionName(rec.internalFuncName);
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    that.printLine(funcName, rec.selfTime, totalTicks, nonLibTicks);
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  });
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTickProcessor.prototype.printHeavyProfile = function(profile, opt_indent) {
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var self = this;
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var indent = opt_indent || 0;
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var indentStr = padLeft('', indent);
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.processProfile(profile, function() { return true; }, function (rec) {
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Cut off too infrequent callers.
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (rec.parentTotalPercent < TickProcessor.CALL_PROFILE_CUTOFF_PCT) return;
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    var funcName = self.formatFunctionName(rec.internalFuncName);
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    print('  ' + padLeft(rec.totalTime, 5) + '  ' +
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          padLeft(rec.parentTotalPercent.toFixed(1), 5) + '%  ' +
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          indentStr + funcName);
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Limit backtrace depth.
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (indent < 2 * self.callGraphSize_) {
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      self.printHeavyProfile(rec.children, indent + 2);
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Delimit top-level functions.
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (indent == 0) {
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      print('');
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  });
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction CppEntriesProvider() {
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCppEntriesProvider.prototype.parseVmSymbols = function(
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    libName, libStart, libEnd, processorFunc) {
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.loadSymbols(libName);
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var prevEntry;
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  function addEntry(funcInfo) {
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Several functions can be mapped onto the same address. To avoid
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // creating zero-sized entries, skip such duplicates.
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Also double-check that function belongs to the library address space.
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (prevEntry && !prevEntry.end &&
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        prevEntry.start < funcInfo.start &&
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        prevEntry.start >= libStart && funcInfo.start <= libEnd) {
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      processorFunc(prevEntry.name, prevEntry.start, funcInfo.start);
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (funcInfo.end &&
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        (!prevEntry || prevEntry.start != funcInfo.start) &&
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        funcInfo.start >= libStart && funcInfo.end <= libEnd) {
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      processorFunc(funcInfo.name, funcInfo.start, funcInfo.end);
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    prevEntry = funcInfo;
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var funcInfo = this.parseNextLine();
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (funcInfo === null) {
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (funcInfo === false) {
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (funcInfo.start < libStart && funcInfo.start < libEnd - libStart) {
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      funcInfo.start += libStart;
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (funcInfo.size) {
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      funcInfo.end = funcInfo.start + funcInfo.size;
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addEntry(funcInfo);
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addEntry({name: '', start: libEnd});
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCppEntriesProvider.prototype.loadSymbols = function(libName) {
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCppEntriesProvider.prototype.parseNextLine = function() {
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction UnixCppEntriesProvider(nmExec, targetRootFS) {
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.symbols = [];
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.parsePos = 0;
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.nmExec = nmExec;
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.targetRootFS = targetRootFS;
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.FUNC_RE = /^([0-9a-fA-F]{8,16}) ([0-9a-fA-F]{8,16} )?[tTwW] (.*)$/;
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinherits(UnixCppEntriesProvider, CppEntriesProvider);
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockUnixCppEntriesProvider.prototype.loadSymbols = function(libName) {
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.parsePos = 0;
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  libName = this.targetRootFS + libName;
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try {
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.symbols = [
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      os.system(this.nmExec, ['-C', '-n', '-S', libName], -1, -1),
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      os.system(this.nmExec, ['-C', '-n', '-S', '-D', libName], -1, -1)
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ];
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } catch (e) {
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If the library cannot be found on this system let's not panic.
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.symbols = ['', ''];
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockUnixCppEntriesProvider.prototype.parseNextLine = function() {
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (this.symbols.length == 0) {
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var lineEndPos = this.symbols[0].indexOf('\n', this.parsePos);
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (lineEndPos == -1) {
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.symbols.shift();
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.parsePos = 0;
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return this.parseNextLine();
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var line = this.symbols[0].substring(this.parsePos, lineEndPos);
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.parsePos = lineEndPos + 1;
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var fields = line.match(this.FUNC_RE);
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var funcInfo = null;
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (fields) {
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    funcInfo = { name: fields[3], start: parseInt(fields[1], 16) };
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (fields[2]) {
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      funcInfo.size = parseInt(fields[2], 16);
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return funcInfo;
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction MacCppEntriesProvider(nmExec, targetRootFS) {
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UnixCppEntriesProvider.call(this, nmExec, targetRootFS);
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note an empty group. It is required, as UnixCppEntriesProvider expects 3 groups.
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.FUNC_RE = /^([0-9a-fA-F]{8,16}) ()[iItT] (.*)$/;
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinherits(MacCppEntriesProvider, UnixCppEntriesProvider);
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMacCppEntriesProvider.prototype.loadSymbols = function(libName) {
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.parsePos = 0;
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  libName = this.targetRootFS + libName;
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try {
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.symbols = [os.system(this.nmExec, ['-n', '-f', libName], -1, -1), ''];
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } catch (e) {
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If the library cannot be found on this system let's not panic.
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.symbols = '';
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction WindowsCppEntriesProvider(_ignored_nmExec, targetRootFS) {
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this.targetRootFS = targetRootFS;
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.symbols = '';
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.parsePos = 0;
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinherits(WindowsCppEntriesProvider, CppEntriesProvider);
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockWindowsCppEntriesProvider.FILENAME_RE = /^(.*)\.([^.]+)$/;
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockWindowsCppEntriesProvider.FUNC_RE =
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /^\s+0001:[0-9a-fA-F]{8}\s+([_\?@$0-9a-zA-Z]+)\s+([0-9a-fA-F]{8}).*$/;
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockWindowsCppEntriesProvider.IMAGE_BASE_RE =
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /^\s+0000:00000000\s+___ImageBase\s+([0-9a-fA-F]{8}).*$/;
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This is almost a constant on Windows.
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockWindowsCppEntriesProvider.EXE_IMAGE_BASE = 0x00400000;
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockWindowsCppEntriesProvider.prototype.loadSymbols = function(libName) {
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  libName = this.targetRootFS + libName;
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var fileNameFields = libName.match(WindowsCppEntriesProvider.FILENAME_RE);
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!fileNameFields) return;
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var mapFileName = fileNameFields[1] + '.map';
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.moduleType_ = fileNameFields[2].toLowerCase();
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try {
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.symbols = read(mapFileName);
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } catch (e) {
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If .map file cannot be found let's not panic.
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.symbols = '';
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockWindowsCppEntriesProvider.prototype.parseNextLine = function() {
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var lineEndPos = this.symbols.indexOf('\r\n', this.parsePos);
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (lineEndPos == -1) {
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var line = this.symbols.substring(this.parsePos, lineEndPos);
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.parsePos = lineEndPos + 2;
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Image base entry is above all other symbols, so we can just
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // terminate parsing.
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var imageBaseFields = line.match(WindowsCppEntriesProvider.IMAGE_BASE_RE);
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (imageBaseFields) {
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var imageBase = parseInt(imageBaseFields[1], 16);
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((this.moduleType_ == 'exe') !=
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        (imageBase == WindowsCppEntriesProvider.EXE_IMAGE_BASE)) {
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var fields = line.match(WindowsCppEntriesProvider.FUNC_RE);
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return fields ?
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      { name: this.unmangleName(fields[1]), start: parseInt(fields[2], 16) } :
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      null;
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Performs very simple unmangling of C++ names.
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Does not handle arguments and template arguments. The mangled names have
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * the form:
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   ?LookupInDescriptor@JSObject@internal@v8@@...arguments info...
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockWindowsCppEntriesProvider.prototype.unmangleName = function(name) {
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Empty or non-mangled name.
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (name.length < 1 || name.charAt(0) != '?') return name;
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var nameEndPos = name.indexOf('@@');
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var components = name.substring(1, nameEndPos).split('@');
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  components.reverse();
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return components.join('::');
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArgumentsProcessor(args) {
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.args_ = args;
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.result_ = ArgumentsProcessor.DEFAULTS;
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.argsDispatch_ = {
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    '-j': ['stateFilter', TickProcessor.VmStates.JS,
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'Show only ticks from JS VM state'],
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    '-g': ['stateFilter', TickProcessor.VmStates.GC,
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'Show only ticks from GC VM state'],
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    '-c': ['stateFilter', TickProcessor.VmStates.COMPILER,
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'Show only ticks from COMPILER VM state'],
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    '-o': ['stateFilter', TickProcessor.VmStates.OTHER,
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'Show only ticks from OTHER VM state'],
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    '-e': ['stateFilter', TickProcessor.VmStates.EXTERNAL,
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'Show only ticks from EXTERNAL VM state'],
8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    '--call-graph-size': ['callGraphSize', TickProcessor.CALL_GRAPH_SIZE,
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        'Set the call graph size'],
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    '--ignore-unknown': ['ignoreUnknown', true,
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'Exclude ticks of unknown code entries from processing'],
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    '--separate-ic': ['separateIc', true,
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'Separate IC entries'],
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    '--unix': ['platform', 'unix',
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'Specify that we are running on *nix platform'],
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    '--windows': ['platform', 'windows',
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'Specify that we are running on Windows platform'],
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    '--mac': ['platform', 'mac',
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'Specify that we are running on Mac OS X platform'],
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    '--nm': ['nm', 'nm',
859e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        'Specify the \'nm\' executable to use (e.g. --nm=/my_dir/nm)'],
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    '--target': ['targetRootFS', '',
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        'Specify the target root directory for cross environment'],
862e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    '--snapshot-log': ['snapshotLogFileName', 'snapshot.log',
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        'Specify snapshot log file to use (e.g. --snapshot-log=snapshot.log)'],
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    '--range': ['range', 'auto,auto',
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        'Specify the range limit as [start],[end]'],
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    '--distortion': ['distortion', 0,
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        'Specify the logging overhead in picoseconds'],
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    '--source-map': ['sourceMap', null,
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        'Specify the source map that should be used for output']
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.argsDispatch_['--js'] = this.argsDispatch_['-j'];
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.argsDispatch_['--gc'] = this.argsDispatch_['-g'];
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.argsDispatch_['--compiler'] = this.argsDispatch_['-c'];
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.argsDispatch_['--other'] = this.argsDispatch_['-o'];
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.argsDispatch_['--external'] = this.argsDispatch_['-e'];
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockArgumentsProcessor.DEFAULTS = {
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  logFileName: 'v8.log',
881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  snapshotLogFileName: null,
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  platform: 'unix',
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stateFilter: null,
8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  callGraphSize: 5,
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ignoreUnknown: false,
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  separateIc: false,
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  targetRootFS: '',
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nm: 'nm',
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  range: 'auto,auto',
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  distortion: 0
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockArgumentsProcessor.prototype.parse = function() {
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (this.args_.length) {
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var arg = this.args_[0];
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (arg.charAt(0) != '-') {
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.args_.shift();
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var userValue = null;
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var eqPos = arg.indexOf('=');
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (eqPos != -1) {
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      userValue = arg.substr(eqPos + 1);
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      arg = arg.substr(0, eqPos);
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (arg in this.argsDispatch_) {
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var dispatch = this.argsDispatch_[arg];
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.result_[dispatch[0]] = userValue == null ? dispatch[1] : userValue;
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (this.args_.length >= 1) {
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.result_.logFileName = this.args_.shift();
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockArgumentsProcessor.prototype.result = function() {
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this.result_;
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockArgumentsProcessor.prototype.printUsageAndExit = function() {
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  function padRight(s, len) {
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    s = s.toString();
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (s.length < len) {
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      s = s + (new Array(len - s.length + 1).join(' '));
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return s;
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  print('Cmdline args: [options] [log-file-name]\n' +
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'Default log file name is "' +
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ArgumentsProcessor.DEFAULTS.logFileName + '".\n');
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  print('Options:');
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var arg in this.argsDispatch_) {
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var synonims = [arg];
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var dispatch = this.argsDispatch_[arg];
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (var synArg in this.argsDispatch_) {
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (arg !== synArg && dispatch === this.argsDispatch_[synArg]) {
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        synonims.push(synArg);
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        delete this.argsDispatch_[synArg];
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    print('  ' + padRight(synonims.join(', '), 20) + dispatch[2]);
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  quit(2);
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
954