1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Redistribution and use in source and binary forms, with or without
3257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// modification, are permitted provided that the following conditions are
4257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// met:
5257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//
6257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//     * Redistributions of source code must retain the above copyright
7257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       notice, this list of conditions and the following disclaimer.
8257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//     * Redistributions in binary form must reproduce the above
9257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       copyright notice, this list of conditions and the following
10257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       disclaimer in the documentation and/or other materials provided
11257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       with the distribution.
12257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//     * Neither the name of Google Inc. nor the names of its
13257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       contributors may be used to endorse or promote products derived
14257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       from this software without specific prior written permission.
15257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//
16257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
28257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Flags: --allow-natives-syntax
29257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
30257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch/**
31257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * This class shows how to use %GetOptimizationCount() and
32257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * %GetOptimizationStatus() to infer information about opts and deopts.
33257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * Might be nice to put this into mjsunit.js, but that doesn't depend on
34257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * the --allow-natives-syntax flag so far.
35257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch */
36257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochfunction OptTracker() {
37257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  this.opt_counts_ = {};
38257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
39257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
40257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch/**
41257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * The possible optimization states of a function. Must be in sync with the
42257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * return values of Runtime_GetOptimizationStatus() in runtime.cc!
43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * @enum {int}
44257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch */
45257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochOptTracker.OptimizationState = {
46257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    YES: 1,
47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    NO: 2,
48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ALWAYS: 3,
49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    NEVER: 4
50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
51257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
52257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch/**
53257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * Always call this at the beginning of your test, once for each function
54257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * that you later want to track de/optimizations for. It is necessary because
55257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * tests are sometimes executed several times in a row, and you want to
56257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * disregard counts from previous runs.
5769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch */
58257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochOptTracker.prototype.CheckpointOptCount = function(func) {
59257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  this.opt_counts_[func] = %GetOptimizationCount(func);
60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
62257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochOptTracker.prototype.AssertOptCount = function(func, optcount) {
63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (this.DisableAsserts_(func)) {
64257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return;
65257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
66257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  assertEquals(optcount, this.GetOptCount_(func));
67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
68257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
69257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochOptTracker.prototype.AssertDeoptCount = function(func, deopt_count) {
70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (this.DisableAsserts_(func)) {
71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return;
72257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
73257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  assertEquals(deopt_count, this.GetDeoptCount_(func));
74257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
75257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
76257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochOptTracker.prototype.AssertDeoptHappened = function(func, expect_deopt) {
77257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (this.DisableAsserts_(func)) {
78257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return;
79257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
80257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (expect_deopt) {
81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    assertTrue(this.GetDeoptCount_(func) > 0);
82257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
83257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    assertEquals(0, this.GetDeoptCount_(func));
84257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
85257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
86257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
87257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochOptTracker.prototype.AssertIsOptimized = function(func, expect_optimized) {
88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (this.DisableAsserts_(func)) {
89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return;
90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  var raw_optimized = %GetOptimizationStatus(func);
92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (expect_optimized) {
93257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    assertEquals(OptTracker.OptimizationState.YES, raw_optimized);
94257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    assertEquals(OptTracker.OptimizationState.NO, raw_optimized);
96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch/**
100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * @private
101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch */
102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochOptTracker.prototype.GetOptCount_ = function(func) {
103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  var raw_count = %GetOptimizationCount(func);
104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (func in this.opt_counts_) {
105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    var checkpointed_count = this.opt_counts_[func];
106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return raw_count - checkpointed_count;
107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return raw_count;
109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch/**
112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * @private
113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch */
114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochOptTracker.prototype.GetDeoptCount_ = function(func) {
115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  var count = this.GetOptCount_(func);
116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (%GetOptimizationStatus(func) == OptTracker.OptimizationState.YES) {
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    count -= 1;
118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return count;
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch/**
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch * @private
124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch */
125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochOptTracker.prototype.DisableAsserts_ = function(func) {
126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  switch(%GetOptimizationStatus(func)) {
127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case OptTracker.OptimizationState.YES:
128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case OptTracker.OptimizationState.NO:
129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return false;
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case OptTracker.OptimizationState.ALWAYS:
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case OptTracker.OptimizationState.NEVER:
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return true;
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return false;
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// (End of class OptTracker.)
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Example function used by the test below.
139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochfunction f(a) {
140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return a+1;
141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvar tracker = new OptTracker();
144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.CheckpointOptCount(f);
145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertOptCount(f, 0);
147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertIsOptimized(f, false);
148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertDeoptHappened(f, false);
149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertDeoptCount(f, 0);
150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
15169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochf(1);
152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch%OptimizeFunctionOnNextCall(f);
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochf(1);
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertOptCount(f, 1);
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertIsOptimized(f, true);
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertDeoptHappened(f, false);
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertDeoptCount(f, 0);
160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch%DeoptimizeFunction(f);
162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertOptCount(f, 1);
164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertIsOptimized(f, false);
165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertDeoptHappened(f, true);
166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertDeoptCount(f, 1);
167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Let's trigger optimization for another type.
169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochfor (var i = 0; i < 5; i++) f("a");
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch%OptimizeFunctionOnNextCall(f);
172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochf("b");
173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertOptCount(f, 2);
175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertIsOptimized(f, true);
176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertDeoptHappened(f, true);
177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtracker.AssertDeoptCount(f, 1);
178