|  | // 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 | 
|  |  | 
|  | 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); | 
|  |  | 
|  | // Test that we deopt on failed bounds checks. | 
|  | var dictionary_map_array = new Int32Array(128); | 
|  | test_base(dictionary_map_array, 5, true); | 
|  | %PrepareFunctionForOptimization(test_base); | 
|  | test_base(dictionary_map_array, 6, true); | 
|  | test_base(dictionary_map_array, 5, false); | 
|  | test_base(dictionary_map_array, 6, false); | 
|  | %OptimizeFunctionOnNextCall(test_base); | 
|  | test_base(dictionary_map_array, -2, true); | 
|  | assertUnoptimized(test_base); | 
|  |  | 
|  | // Forget about the dictionary_map_array's map. | 
|  | %ClearFunctionFeedback(test_base); | 
|  | %PrepareFunctionForOptimization(test_base); | 
|  |  | 
|  | test_base(a, 5, true); | 
|  | test_base(a, 6, true); | 
|  | test_base(a, 5, false); | 
|  | test_base(a, 6, false); | 
|  | %OptimizeFunctionOnNextCall(test_base); | 
|  | test_base(a, 2048, true); | 
|  | assertUnoptimized(test_base); | 
|  |  | 
|  | 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); | 
|  | assertUnoptimized(test_base); | 
|  |  | 
|  |  | 
|  | // 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(); |