// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Flags: --allow-natives-syntax
// Flags: --noconcurrent-recompilation --noconcurrent-osr

if (%IsConcurrentRecompilationSupported()) {
  print("Concurrent recompilation is turned on after all. Skipping this test.");
  quit();
}

/**
 * This class shows how to use %GetOptimizationCount() and
 * %GetOptimizationStatus() to infer information about opts and deopts.
 * Might be nice to put this into mjsunit.js, but that doesn't depend on
 * the --allow-natives-syntax flag so far.
 */
function OptTracker() {
  this.opt_counts_ = {};
}

/**
 * The possible optimization states of a function. Must be in sync with the
 * return values of Runtime_GetOptimizationStatus() in runtime.cc!
 * @enum {int}
 */
OptTracker.OptimizationState = {
    YES: 1,
    NO: 2,
    ALWAYS: 3,
    NEVER: 4
};

/**
 * Always call this at the beginning of your test, once for each function
 * that you later want to track de/optimizations for. It is necessary because
 * tests are sometimes executed several times in a row, and you want to
 * disregard counts from previous runs.
 */
OptTracker.prototype.CheckpointOptCount = function(func) {
  this.opt_counts_[func] = %GetOptimizationCount(func);
};

OptTracker.prototype.AssertOptCount = function(func, optcount) {
  if (this.DisableAsserts_(func)) {
    return;
  }
  assertEquals(optcount, this.GetOptCount_(func));
};

OptTracker.prototype.AssertDeoptCount = function(func, deopt_count) {
  if (this.DisableAsserts_(func)) {
    return;
  }
  assertEquals(deopt_count, this.GetDeoptCount_(func));
};

OptTracker.prototype.AssertDeoptHappened = function(func, expect_deopt) {
  if (this.DisableAsserts_(func)) {
    return;
  }
  if (expect_deopt) {
    assertTrue(this.GetDeoptCount_(func) > 0);
  } else {
    assertEquals(0, this.GetDeoptCount_(func));
  }
}

OptTracker.prototype.AssertIsOptimized = function(func, expect_optimized) {
  if (this.DisableAsserts_(func)) {
    return;
  }
  var raw_optimized = %GetOptimizationStatus(func);
  if (expect_optimized) {
    assertEquals(OptTracker.OptimizationState.YES, raw_optimized);
  } else {
    assertEquals(OptTracker.OptimizationState.NO, raw_optimized);
  }
}

/**
 * @private
 */
OptTracker.prototype.GetOptCount_ = function(func) {
  var raw_count = %GetOptimizationCount(func);
  if (func in this.opt_counts_) {
    var checkpointed_count = this.opt_counts_[func];
    return raw_count - checkpointed_count;
  }
  return raw_count;
}

/**
 * @private
 */
OptTracker.prototype.GetDeoptCount_ = function(func) {
  var count = this.GetOptCount_(func);
  if (%GetOptimizationStatus(func) == OptTracker.OptimizationState.YES) {
    count -= 1;
  }
  return count;
}

/**
 * @private
 */
OptTracker.prototype.DisableAsserts_ = function(func) {
  switch(%GetOptimizationStatus(func)) {
    case OptTracker.OptimizationState.YES:
    case OptTracker.OptimizationState.NO:
      return false;
    case OptTracker.OptimizationState.ALWAYS:
    case OptTracker.OptimizationState.NEVER:
      return true;
  }
  return true;
}
// (End of class OptTracker.)

// Example function used by the test below.
function f(a) {
  return a+1;
}

var tracker = new OptTracker();
tracker.CheckpointOptCount(f);

tracker.AssertOptCount(f, 0);
tracker.AssertIsOptimized(f, false);
tracker.AssertDeoptHappened(f, false);
tracker.AssertDeoptCount(f, 0);

f(1);

%OptimizeFunctionOnNextCall(f);
f(1);

tracker.AssertOptCount(f, 1);
tracker.AssertIsOptimized(f, true);
tracker.AssertDeoptHappened(f, false);
tracker.AssertDeoptCount(f, 0);

%DeoptimizeFunction(f);

tracker.AssertOptCount(f, 1);
tracker.AssertIsOptimized(f, false);
tracker.AssertDeoptHappened(f, true);
tracker.AssertDeoptCount(f, 1);

// Let's trigger optimization for another type.
for (var i = 0; i < 5; i++) f("a");

%OptimizeFunctionOnNextCall(f);
f("b");

tracker.AssertOptCount(f, 2);
tracker.AssertIsOptimized(f, true);
tracker.AssertDeoptHappened(f, true);
tracker.AssertDeoptCount(f, 1);
