1 // Copyright 2008 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 // Flags: --allow-natives-syntax 29 30 // Test Math.min(). 31 32 assertEquals(Infinity, Math.min()); 33 assertEquals(1, Math.min(1)); 34 assertEquals(1, Math.min(1, 2)); 35 assertEquals(1, Math.min(2, 1)); 36 assertEquals(1, Math.min(1, 2, 3)); 37 assertEquals(1, Math.min(3, 2, 1)); 38 assertEquals(1, Math.min(2, 3, 1)); 39 assertEquals(1.1, Math.min(1.1, 2.2, 3.3)); 40 assertEquals(1.1, Math.min(3.3, 2.2, 1.1)); 41 assertEquals(1.1, Math.min(2.2, 3.3, 1.1)); 42 43 // Prepare a non-Smi zero value. 44 function returnsNonSmi(){ return 0.25; } 45 var ZERO = (function() { 46 var z; 47 // We have to have a loop here because the first time we get a Smi from the 48 // runtime system. After a while the binary op IC settles down and we get 49 // a non-Smi from the generated code. 50 for (var i = 0; i < 10; i++) { 51 z = returnsNonSmi() - returnsNonSmi(); 52 } 53 return z; 54 })(); 55 assertEquals(0, ZERO); 56 assertEquals(Infinity, 1/ZERO); 57 assertEquals(-Infinity, 1/-ZERO); 58 // Here we would like to have assertFalse(%_IsSmi(ZERO)); This is, however, 59 // unreliable, since a new space exhaustion at a critical moment could send 60 // us into the runtime system, which would quite legitimately put a Smi zero 61 // here. 62 assertFalse(%_IsSmi(-ZERO)); 63 64 var o = {}; 65 o.valueOf = function() { return 1; }; 66 assertEquals(1, Math.min(2, 3, '1')); 67 assertEquals(1, Math.min(3, o, 2)); 68 assertEquals(1, Math.min(o, 2)); 69 assertEquals(-Infinity, Infinity / Math.min(-0, +0)); 70 assertEquals(-Infinity, Infinity / Math.min(+0, -0)); 71 assertEquals(-Infinity, Infinity / Math.min(+0, -0, 1)); 72 assertEquals(-Infinity, Infinity / Math.min(-0, ZERO)); 73 assertEquals(-Infinity, Infinity / Math.min(ZERO, -0)); 74 assertEquals(-Infinity, Infinity / Math.min(ZERO, -0, 1)); 75 assertEquals(-1, Math.min(+0, -0, -1)); 76 assertEquals(-1, Math.min(-1, +0, -0)); 77 assertEquals(-1, Math.min(+0, -1, -0)); 78 assertEquals(-1, Math.min(-0, -1, +0)); 79 assertEquals(NaN, Math.min('oxen')); 80 assertEquals(NaN, Math.min('oxen', 1)); 81 assertEquals(NaN, Math.min(1, 'oxen')); 82 83 84 // Test Math.max(). 85 86 assertEquals(Number.NEGATIVE_INFINITY, Math.max()); 87 assertEquals(1, Math.max(1)); 88 assertEquals(2, Math.max(1, 2)); 89 assertEquals(2, Math.max(2, 1)); 90 assertEquals(3, Math.max(1, 2, 3)); 91 assertEquals(3, Math.max(3, 2, 1)); 92 assertEquals(3, Math.max(2, 3, 1)); 93 assertEquals(3.3, Math.max(1.1, 2.2, 3.3)); 94 assertEquals(3.3, Math.max(3.3, 2.2, 1.1)); 95 assertEquals(3.3, Math.max(2.2, 3.3, 1.1)); 96 97 var o = {}; 98 o.valueOf = function() { return 3; }; 99 assertEquals(3, Math.max(2, '3', 1)); 100 assertEquals(3, Math.max(1, o, 2)); 101 assertEquals(3, Math.max(o, 1)); 102 assertEquals(Infinity, Infinity / Math.max(-0, +0)); 103 assertEquals(Infinity, Infinity / Math.max(+0, -0)); 104 assertEquals(Infinity, Infinity / Math.max(+0, -0, -1)); 105 assertEquals(Infinity, Infinity / Math.max(-0, ZERO)); 106 assertEquals(Infinity, Infinity / Math.max(ZERO, -0)); 107 assertEquals(Infinity, Infinity / Math.max(ZERO, -0, -1)); 108 assertEquals(1, Math.max(+0, -0, +1)); 109 assertEquals(1, Math.max(+1, +0, -0)); 110 assertEquals(1, Math.max(+0, +1, -0)); 111 assertEquals(1, Math.max(-0, +1, +0)); 112 assertEquals(NaN, Math.max('oxen')); 113 assertEquals(NaN, Math.max('oxen', 1)); 114 assertEquals(NaN, Math.max(1, 'oxen')); 115 116 assertEquals(Infinity, 1/Math.max(ZERO, -0)); 117 assertEquals(Infinity, 1/Math.max(-0, ZERO)); 118 119 function run(crankshaft_test) { 120 crankshaft_test(1); 121 crankshaft_test(1); 122 %OptimizeFunctionOnNextCall(crankshaft_test); 123 crankshaft_test(-0); 124 } 125 126 function crankshaft_test_1(arg) { 127 var v1 = 1; 128 var v2 = 5; 129 var v3 = 1.5; 130 var v4 = 5.5; 131 var v5 = 2; 132 var v6 = 6; 133 var v7 = 0; 134 var v8 = -0; 135 136 var v9 = 9.9; 137 var v0 = 10.1; 138 // Integer32 representation. 139 assertEquals(v2, Math.max(v1++, v2++)); 140 assertEquals(v1, Math.min(v1++, v2++)); 141 // Tagged representation. 142 assertEquals(v4, Math.max(v3, v4)); 143 assertEquals(v3, Math.min(v3, v4)); 144 assertEquals(v6, Math.max(v5, v6)); 145 assertEquals(v5, Math.min(v5, v6)); 146 // Double representation. 147 assertEquals(v0, Math.max(v0++, v9++)); 148 assertEquals(v9, Math.min(v0++, v9++)); 149 // Mixed representation. 150 assertEquals(v1, Math.min(v1++, v9++)); // int32, double 151 assertEquals(v0, Math.max(v0++, v2++)); // double, int32 152 assertEquals(v1, Math.min(v1++, v6)); // int32, tagged 153 assertEquals(v2, Math.max(v5, v2++)); // tagged, int32 154 assertEquals(v6, Math.min(v6, v9++)); // tagged, double 155 assertEquals(v0, Math.max(v0++, v5)); // double, tagged 156 157 // Minus zero. 158 assertEquals(Infinity, 1/Math.max(v7, v8)); 159 assertEquals(-Infinity, 1/Math.min(v7, v8)); 160 // NaN. 161 assertEquals(NaN, Math.max(NaN, v8)); 162 assertEquals(NaN, Math.min(NaN, v9)); 163 assertEquals(NaN, Math.max(v8, NaN)); 164 assertEquals(NaN, Math.min(v9, NaN)); 165 // Minus zero as Integer32. 166 assertEquals((arg === -0) ? -Infinity : 1, 1/Math.min(arg, v2)); 167 } 168 169 run(crankshaft_test_1); 170 171 function crankshaft_test_2() { 172 var v9 = {}; 173 v9.valueOf = function() { return 6; } 174 // Deopt expected due to non-heapnumber objects. 175 assertEquals(6, Math.min(v9, 12)); 176 } 177 178 run(crankshaft_test_2); 179 180 var o = { a: 1, b: 2 }; 181 182 // Test smi-based Math.min. 183 function f(o) { 184 return Math.min(o.a, o.b); 185 } 186 187 assertEquals(1, f(o)); 188 assertEquals(1, f(o)); 189 %OptimizeFunctionOnNextCall(f); 190 assertEquals(1, f(o)); 191 o.a = 5; 192 o.b = 4; 193 assertEquals(4, f(o)); 194 195 // Test overriding Math.min and Math.max 196 Math.min = function(a, b) { return a + b; } 197 Math.max = function(a, b) { return a - b; } 198 199 function crankshaft_test_3() { 200 assertEquals(8, Math.min(3, 5)); 201 assertEquals(3, Math.max(5, 2)); 202 } 203 204 run(crankshaft_test_3); 205