text: // 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 --expose-gc --no-always-opt --opt
  
  var a = new Int32Array(1024);
  
  // Test that we do not assert if the accessed index has not an int32 rep.
  var v = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  function test_do_not_assert_on_non_int32(vector, base) {
    var r = 0;
    var a1 = base + 1;
    var a2 = base + 2;
    var a3 = base + 3;
    var a4 = base + 4;
    if (a1 == 2) {
      r += vector[a1];
      r += vector[a4];
      r += vector[a2];
      r += vector[a3];
    }
    return r;
  }
  %PrepareFunctionForOptimization(test_do_not_assert_on_non_int32);
  test_do_not_assert_on_non_int32(v,1);
  test_do_not_assert_on_non_int32(v,1);
  test_do_not_assert_on_non_int32(v,"a");
  test_do_not_assert_on_non_int32(v,"a");
  %OptimizeFunctionOnNextCall(test_do_not_assert_on_non_int32);
  test_do_not_assert_on_non_int32(v,0);
  
  function test_base(a, base, condition) {
    a[base + 1] = 1;
    a[base + 4] = 2;
    a[base + 3] = 3;
    a[base + 2] = 4;
    a[base + 4] = base + 4;
    if (condition) {
      a[base + 1] = 1;
      a[base + 2] = 2;
      a[base + 2] = 3;
      a[base + 2] = 4;
      a[base + 4] = base + 4;
    } else {
      a[base + 6] = 1;
      a[base + 4] = 2;
      a[base + 3] = 3;
      a[base + 2] = 4;
      a[base + 4] = base - 4;
    }
  }
  
  function check_test_base(a, base, condition) {
    if (condition) {
      assertEquals(1, a[base + 1]);
      assertEquals(4, a[base + 2]);
      assertEquals(base + 4, a[base + 4]);
    } else {
      assertEquals(1, a[base + 6]);
      assertEquals(3, a[base + 3]);
      assertEquals(4, a[base + 2]);
      assertEquals(base - 4, a[base + 4]);
    }
  }
  
  %PrepareFunctionForOptimization(test_base);
  test_base(a, 1, true);
  test_base(a, 2, true);
  test_base(a, 1, false);
  test_base(a, 2, false);
  %OptimizeFunctionOnNextCall(test_base);
  test_base(a, 3, true);
  check_test_base(a, 3, true);
  test_base(a, 3, false);
  check_test_base(a, 3, false);
  assertOptimized(test_base);
  
  function test_base_for_dictionary_map(a, base, condition) {
    a[base + 1] = 1;
    a[base + 4] = 2;
    a[base + 3] = 3;
    a[base + 2] = 4;
    a[base + 4] = base + 4;
    if (condition) {
      a[base + 1] = 1;
      a[base + 2] = 2;
      a[base + 2] = 3;
      a[base + 2] = 4;
      a[base + 4] = base + 4;
    } else {
      a[base + 6] = 1;
      a[base + 4] = 2;
      a[base + 3] = 3;
      a[base + 2] = 4;
      a[base + 4] = base - 4;
    }
  }
  
  // Test that we deopt on failed bounds checks.
  var dictionary_map_array = new Int32Array(128);
  test_base_for_dictionary_map(dictionary_map_array, 5, true);
  %PrepareFunctionForOptimization(test_base_for_dictionary_map);
  test_base_for_dictionary_map(dictionary_map_array, 6, true);
  test_base_for_dictionary_map(dictionary_map_array, 5, false);
  test_base_for_dictionary_map(dictionary_map_array, 6, false);
  %OptimizeFunctionOnNextCall(test_base_for_dictionary_map);
  test_base_for_dictionary_map(dictionary_map_array, -2, true);
  assertUnoptimized(test_base_for_dictionary_map);
  
  function test_base_for_oob(a, base, condition) {
    a[base + 1] = 1;
    a[base + 4] = 2;
    a[base + 3] = 3;
    a[base + 2] = 4;
    a[base + 4] = base + 4;
    if (condition) {
      a[base + 1] = 1;
      a[base + 2] = 2;
      a[base + 2] = 3;
      a[base + 2] = 4;
      a[base + 4] = base + 4;
    } else {
      a[base + 6] = 1;
      a[base + 4] = 2;
      a[base + 3] = 3;
      a[base + 2] = 4;
      a[base + 4] = base - 4;
    }
  }
  
  %PrepareFunctionForOptimization(test_base_for_oob);
  test_base_for_oob(a, 5, true);
  test_base_for_oob(a, 6, true);
  test_base_for_oob(a, 5, false);
  test_base_for_oob(a, 6, false);
  %OptimizeFunctionOnNextCall(test_base_for_oob);
  test_base_for_oob(a, 2048, true);
  assertUnoptimized(test_base_for_oob);
  
  function test_minus(base,cond) {
    a[base - 1] = 1;
    a[base - 2] = 2;
    a[base + 4] = 3;
    a[base] = 4;
    a[base + 4] = base + 4;
    if (cond) {
      a[base - 4] = 1;
      a[base + 5] = 2;
      a[base + 3] = 3;
      a[base + 2] = 4;
      a[base + 4] = base + 4;
    } else {
      a[base + 6] = 1;
      a[base + 4] = 2;
      a[base + 3] = 3;
      a[base + 2] = 4;
      a[base + 4] = base - 4;
    }
  }
  
  function check_test_minus(base,cond) {
    if (cond) {
      assertEquals(2, a[base + 5]);
      assertEquals(3, a[base + 3]);
      assertEquals(4, a[base + 2]);
      assertEquals(base + 4, a[base + 4]);
    } else {
      assertEquals(1, a[base + 6]);
      assertEquals(3, a[base + 3]);
      assertEquals(4, a[base + 2]);
      assertEquals(base - 4, a[base + 4]);
    }
  }
  
  %PrepareFunctionForOptimization(test_minus);
  test_minus(5,true);
  test_minus(6,true);
  %OptimizeFunctionOnNextCall(test_minus);
  test_minus(7,true);
  check_test_minus(7,true);
  test_minus(7,false);
  check_test_minus(7,false);
  
  // Specific test on negative offsets.
  var short_a = new Array(100);
  for (var i = 0; i < short_a.length; i++) short_a[i] = 0;
  function short_test(a, i) {
    a[i + 9] = 0;
    a[i - 10] = 0;
  }
  %PrepareFunctionForOptimization(short_test);
  short_test(short_a, 50);
  short_test(short_a, 50);
  %OptimizeFunctionOnNextCall(short_test);
  short_a.length = 10;
  short_test(short_a, 0);
  // TODO(v8:11457) Currently, we cannot inline stores if there is a dictionary
  // mode prototype on the prototype chain. Therefore, if
  // v8_dict_property_const_tracking is enabled, the optimized code only contains
  // a call to the IC handler and doesn't get deopted.
  assertEquals(%IsDictPropertyConstTrackingEnabled(), isOptimized(short_test));
  
  
  // A test for when we would modify a phi index.
  var data_phi = [0, 1, 2, 3, 4, 5, 6, 7, 8];
  function test_phi(a, base, check) {
    var index;
    if (check) {
      index = base + 1;
    } else {
      index = base + 2;
    }
    var result = a[index];
    result += a[index + 1];
    result += a[index - 1];
    return result;
  }
  %PrepareFunctionForOptimization(test_phi);
  var result_phi = 0;
  result_phi = test_phi(data_phi, 3,  true);
  assertEquals(12, result_phi);
  result_phi = test_phi(data_phi, 3,  true);
  assertEquals(12, result_phi);
  %OptimizeFunctionOnNextCall(test_phi);
  result_phi = test_phi(data_phi, 3,  true);
  assertEquals(12, result_phi);
  
  
  // A test for recursive decomposition
  var data_composition_long = [0, 1, 2, 3, 4, 5, 6, 7, 8];
  var data_composition_short = [0, 1, 2, 3, 4];
  function test_composition(a, base0, check) {
    var base1 = ((base0 + 2));
    var base2 = ((base1 + 8) >> 2);
    var base3 = ((base2 + 6) >> 1);
    var base4 = ((base3 + 8) >> 1);
  
    var result = 0;
    result += a[base0];
    result += a[base1];
    result += a[base2];
    result += a[base3];
    result += a[base4];
  
    return result;
  }
  %PrepareFunctionForOptimization(test_composition);
  var result_composition = 0;
  result_composition = test_composition(data_composition_long, 2);
  assertEquals(19, result_composition);
  result_composition = test_composition(data_composition_long, 2);
  assertEquals(19, result_composition);
  %OptimizeFunctionOnNextCall(test_composition);
  result_composition = test_composition(data_composition_short, 2);
  assertEquals(NaN, result_composition);
  
  
  gc();
  