1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 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// Load source code files from <project root>/tools.
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Files: tools/splaytree.js tools/codemap.js tools/consarray.js tools/profile.js
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction stackToString(stack) {
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return stack.join(' -> ');
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction assertPathExists(root, path, opt_message) {
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var message = opt_message ? ' (' + opt_message + ')' : '';
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assertNotNull(root.descendToChild(path, function(node, pos) {
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertNotNull(node,
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stackToString(path.slice(0, pos)) + ' has no child ' +
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    path[pos] + message);
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }), opt_message);
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction assertNoPathExists(root, path, opt_message) {
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var message = opt_message ? ' (' + opt_message + ')' : '';
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assertNull(root.descendToChild(path), opt_message);
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction countNodes(profile, traverseFunc) {
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var count = 0;
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  traverseFunc.call(profile, function () { count++; });
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return count;
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ProfileTestDriver() {
611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  this.profile = new Profile();
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.stack_ = [];
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.addFunctions_();
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Addresses inside functions.
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockProfileTestDriver.prototype.funcAddrs_ = {
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    'lib1-f1': 0x11110, 'lib1-f2': 0x11210,
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    'lib2-f1': 0x21110, 'lib2-f2': 0x21210,
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    'T: F1': 0x50110, 'T: F2': 0x50210, 'T: F3': 0x50410 };
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockProfileTestDriver.prototype.addFunctions_ = function() {
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile.addLibrary('lib1', 0x11000, 0x12000);
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile.addStaticCode('lib1-f1', 0x11100, 0x11900);
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile.addStaticCode('lib1-f2', 0x11200, 0x11500);
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile.addLibrary('lib2', 0x21000, 0x22000);
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile.addStaticCode('lib2-f1', 0x21100, 0x21900);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile.addStaticCode('lib2-f2', 0x21200, 0x21500);
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile.addCode('T', 'F1', 0x50100, 0x100);
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile.addCode('T', 'F2', 0x50200, 0x100);
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile.addCode('T', 'F3', 0x50400, 0x100);
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockProfileTestDriver.prototype.enter = function(funcName) {
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stack looks like this: [pc, caller, ..., main].
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Therefore, we are adding entries at the beginning.
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.stack_.unshift(this.funcAddrs_[funcName]);
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile.recordTick(this.stack_);
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockProfileTestDriver.prototype.stay = function() {
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.profile.recordTick(this.stack_);
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockProfileTestDriver.prototype.leave = function() {
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.stack_.shift();
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockProfileTestDriver.prototype.execute = function() {
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.enter('lib1-f1');
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.enter('lib1-f2');
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.enter('T: F1');
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this.enter('T: F2');
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this.leave();
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.stay();
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this.enter('lib2-f1');
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          this.enter('lib2-f1');
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          this.leave();
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this.stay();
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this.leave();
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this.enter('T: F3');
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          this.enter('T: F3');
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            this.enter('T: F3');
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            this.leave();
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            this.enter('T: F2');
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            this.stay();
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            this.leave();
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          this.leave();
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this.leave();
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.leave();
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.enter('lib2-f1');
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this.enter('lib1-f1');
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this.leave();
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.leave();
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.stay();
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.leave();
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction Inherits(childCtor, parentCtor) {
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  function tempCtor() {};
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tempCtor.prototype = parentCtor.prototype;
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  childCtor.superClass_ = parentCtor.prototype;
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  childCtor.prototype = new tempCtor();
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  childCtor.prototype.constructor = childCtor;
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block(function testCallTreeBuilding() {
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  function Driver() {
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ProfileTestDriver.call(this);
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.namesTopDown = [];
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.namesBottomUp = [];
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Inherits(Driver, ProfileTestDriver);
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Driver.prototype.enter = function(func) {
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.namesTopDown.push(func);
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.namesBottomUp.unshift(func);
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertNoPathExists(this.profile.getTopDownProfile().getRoot(), this.namesTopDown,
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'pre enter/topDown');
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertNoPathExists(this.profile.getBottomUpProfile().getRoot(), this.namesBottomUp,
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'pre enter/bottomUp');
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Driver.superClass_.enter.call(this, func);
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertPathExists(this.profile.getTopDownProfile().getRoot(), this.namesTopDown,
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'post enter/topDown');
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertPathExists(this.profile.getBottomUpProfile().getRoot(), this.namesBottomUp,
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        'post enter/bottomUp');
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Driver.prototype.stay = function() {
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var preTopDownNodes = countNodes(this.profile, this.profile.traverseTopDownTree);
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var preBottomUpNodes = countNodes(this.profile, this.profile.traverseBottomUpTree);
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Driver.superClass_.stay.call(this);
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var postTopDownNodes = countNodes(this.profile, this.profile.traverseTopDownTree);
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var postBottomUpNodes = countNodes(this.profile, this.profile.traverseBottomUpTree);
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Must be no changes in tree layout.
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertEquals(preTopDownNodes, postTopDownNodes, 'stay/topDown');
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertEquals(preBottomUpNodes, postBottomUpNodes, 'stay/bottomUp');
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Driver.prototype.leave = function() {
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Driver.superClass_.leave.call(this);
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.namesTopDown.pop();
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.namesBottomUp.shift();
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var testDriver = new Driver();
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testDriver.execute();
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block})();
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction assertNodeWeights(root, path, selfTicks, totalTicks) {
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var node = root.descendToChild(path);
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var stack = stackToString(path);
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assertNotNull(node, 'node not found: ' + stack);
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assertEquals(selfTicks, node.selfWeight, 'self of ' + stack);
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assertEquals(totalTicks, node.totalWeight, 'total of ' + stack);
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block(function testTopDownRootProfileTicks() {
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var testDriver = new ProfileTestDriver();
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testDriver.execute();
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var pathWeights = [
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1'], 1, 16],
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1', 'lib1-f2'], 2, 15],
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1', 'lib1-f2', 'T: F1'], 2, 11],
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F2'], 1, 1],
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1', 'lib1-f2', 'T: F1', 'lib2-f1'], 2, 3],
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1', 'lib1-f2', 'T: F1', 'lib2-f1', 'lib2-f1'], 1, 1],
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3'], 1, 5],
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3', 'T: F3'], 1, 4],
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3', 'T: F3', 'T: F3'], 1, 1],
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3', 'T: F3', 'T: F2'], 2, 2],
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1', 'lib1-f2', 'lib2-f1'], 1, 2],
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib1-f1', 'lib1-f2', 'lib2-f1', 'lib1-f1'], 1, 1]
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ];
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var root = testDriver.profile.getTopDownProfile().getRoot();
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < pathWeights.length; ++i) {
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var data = pathWeights[i];
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertNodeWeights(root, data[0], data[1], data[2]);
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block})();
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block(function testRootFlatProfileTicks() {
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  function Driver() {
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ProfileTestDriver.call(this);
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.namesTopDown = [''];
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.counters = {};
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.root = null;
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Inherits(Driver, ProfileTestDriver);
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Driver.prototype.increment = function(func, self, total) {
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!(func in this.counters)) {
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.counters[func] = { self: 0, total: 0 };
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.counters[func].self += self;
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.counters[func].total += total;
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Driver.prototype.incrementTotals = function() {
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Only count each function in the stack once.
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var met = {};
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (var i = 0; i < this.namesTopDown.length; ++i) {
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var name = this.namesTopDown[i];
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!(name in met)) {
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this.increment(name, 0, 1);
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      met[name] = true;
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Driver.prototype.enter = function(func) {
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Driver.superClass_.enter.call(this, func);
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.namesTopDown.push(func);
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.increment(func, 1, 0);
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.incrementTotals();
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Driver.prototype.stay = function() {
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Driver.superClass_.stay.call(this);
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.increment(this.namesTopDown[this.namesTopDown.length - 1], 1, 0);
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.incrementTotals();
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Driver.prototype.leave = function() {
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Driver.superClass_.leave.call(this);
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.namesTopDown.pop();
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Driver.prototype.extractRoot = function() {
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertTrue('' in this.counters);
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.root = this.counters[''];
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    delete this.counters[''];
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var testDriver = new Driver();
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testDriver.execute();
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testDriver.extractRoot();
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var counted = 0;
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var c in testDriver.counters) {
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    counted++;
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var flatProfileRoot = testDriver.profile.getFlatProfile().getRoot();
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assertEquals(testDriver.root.self, flatProfileRoot.selfWeight);
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assertEquals(testDriver.root.total, flatProfileRoot.totalWeight);
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var flatProfile = flatProfileRoot.exportChildren();
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assertEquals(counted, flatProfile.length, 'counted vs. flatProfile');
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < flatProfile.length; ++i) {
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var rec = flatProfile[i];
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertTrue(rec.label in testDriver.counters, 'uncounted: ' + rec.label);
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var reference = testDriver.counters[rec.label];
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertEquals(reference.self, rec.selfWeight, 'self of ' + rec.label);
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertEquals(reference.total, rec.totalWeight, 'total of ' + rec.label);
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block})();
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block(function testFunctionCalleesProfileTicks() {
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var testDriver = new ProfileTestDriver();
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testDriver.execute();
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var pathWeights = [
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib2-f1'], 3, 5],
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib2-f1', 'lib2-f1'], 1, 1],
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    [['lib2-f1', 'lib1-f1'], 1, 1]
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ];
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var profile = testDriver.profile.getTopDownProfile('lib2-f1');
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var root = profile.getRoot();
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < pathWeights.length; ++i) {
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var data = pathWeights[i];
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertNodeWeights(root, data[0], data[1], data[2]);
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block})();
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block(function testFunctionFlatProfileTicks() {
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var testDriver = new ProfileTestDriver();
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testDriver.execute();
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var flatWeights = {
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    'lib2-f1': [1, 1],
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    'lib1-f1': [1, 1]
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var flatProfileRoot =
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     testDriver.profile.getFlatProfile('lib2-f1').findOrAddChild('lib2-f1');
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assertEquals(3, flatProfileRoot.selfWeight);
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assertEquals(5, flatProfileRoot.totalWeight);
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var flatProfile = flatProfileRoot.exportChildren();
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assertEquals(2, flatProfile.length, 'counted vs. flatProfile');
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < flatProfile.length; ++i) {
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var rec = flatProfile[i];
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertTrue(rec.label in flatWeights, 'uncounted: ' + rec.label);
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var reference = flatWeights[rec.label];
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertEquals(reference[0], rec.selfWeight, 'self of ' + rec.label);
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assertEquals(reference[1], rec.totalWeight, 'total of ' + rec.label);
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block})();
348