1// Copyright 2012 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 --expose-gc 29// Flags: --noalways-opt 30 31// Test element kind of objects. 32 33var elements_kind = { 34 fast_smi_only : 'fast smi only elements', 35 fast : 'fast elements', 36 fast_double : 'fast double elements', 37 dictionary : 'dictionary elements', 38 external_byte : 'external byte elements', 39 external_unsigned_byte : 'external unsigned byte elements', 40 external_short : 'external short elements', 41 external_unsigned_short : 'external unsigned short elements', 42 external_int : 'external int elements', 43 external_unsigned_int : 'external unsigned int elements', 44 external_float : 'external float elements', 45 external_double : 'external double elements', 46 external_pixel : 'external pixel elements' 47} 48 49function getKind(obj) { 50 if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only; 51 if (%HasFastObjectElements(obj)) return elements_kind.fast; 52 if (%HasFastDoubleElements(obj)) return elements_kind.fast_double; 53 if (%HasDictionaryElements(obj)) return elements_kind.dictionary; 54} 55 56function isHoley(obj) { 57 if (%HasFastHoleyElements(obj)) return true; 58 return false; 59} 60 61function assertKind(expected, obj, name_opt) { 62 assertEquals(expected, getKind(obj), name_opt); 63} 64 65// Test: If a call site goes megamorphic, it retains the ability to 66// use allocation site feedback (if FLAG_allocation_site_pretenuring 67// is on). 68(function() { 69 function bar(t, len) { 70 return new t(len); 71 } 72 73 a = bar(Array, 10); 74 a[0] = 3.5; 75 b = bar(Array, 1); 76 assertKind(elements_kind.fast_double, b); 77 c = bar(Object, 3); 78 b = bar(Array, 10); 79 // TODO(mvstanton): re-enable when FLAG_allocation_site_pretenuring 80 // is on in the build. 81 // assertKind(elements_kind.fast_double, b); 82})(); 83 84 85// Test: ensure that crankshafted array constructor sites are deopted 86// if another function is used. 87(function() { 88 function bar0(t) { 89 return new t(); 90 } 91 a = bar0(Array); 92 a[0] = 3.5; 93 b = bar0(Array); 94 assertKind(elements_kind.fast_double, b); 95 %OptimizeFunctionOnNextCall(bar0); 96 b = bar0(Array); 97 assertKind(elements_kind.fast_double, b); 98 assertOptimized(bar0); 99 // bar0 should deopt 100 b = bar0(Object); 101 assertUnoptimized(bar0) 102 // When it's re-optimized, we should call through the full stub 103 bar0(Array); 104 %OptimizeFunctionOnNextCall(bar0); 105 b = bar0(Array); 106 // This only makes sense to test if we allow crankshafting 107 if (4 != %GetOptimizationStatus(bar0)) { 108 // We also lost our ability to record kind feedback, as the site 109 // is megamorphic now. 110 assertKind(elements_kind.fast_smi_only, b); 111 assertOptimized(bar0); 112 b[0] = 3.5; 113 c = bar0(Array); 114 assertKind(elements_kind.fast_smi_only, c); 115 } 116})(); 117 118 119// Test: Ensure that inlined array calls in crankshaft learn from deopts 120// based on the move to a dictionary for the array. 121(function() { 122 function bar(len) { 123 return new Array(len); 124 } 125 a = bar(10); 126 a[0] = "a string"; 127 a = bar(10); 128 assertKind(elements_kind.fast, a); 129 %OptimizeFunctionOnNextCall(bar); 130 a = bar(10); 131 assertKind(elements_kind.fast, a); 132 assertOptimized(bar); 133 bar(100000); 134 assertOptimized(bar); 135 136 // If the argument isn't a smi, things should still work. 137 a = bar("oops"); 138 assertOptimized(bar); 139 assertKind(elements_kind.fast, a); 140 141 function barn(one, two, three) { 142 return new Array(one, two, three); 143 } 144 145 barn(1, 2, 3); 146 barn(1, 2, 3); 147 %OptimizeFunctionOnNextCall(barn); 148 barn(1, 2, 3); 149 assertOptimized(barn); 150 a = barn(1, "oops", 3); 151 assertOptimized(barn); 152})(); 153 154 155// Test: When a method with array constructor is crankshafted, the type 156// feedback for elements kind is baked in. Verify that transitions don't 157// change it anymore 158(function() { 159 function bar() { 160 return new Array(); 161 } 162 a = bar(); 163 bar(); 164 %OptimizeFunctionOnNextCall(bar); 165 b = bar(); 166 // This only makes sense to test if we allow crankshafting 167 if (4 != %GetOptimizationStatus(bar)) { 168 assertOptimized(bar); 169 %DebugPrint(3); 170 b[0] = 3.5; 171 c = bar(); 172 assertKind(elements_kind.fast_smi_only, c); 173 assertOptimized(bar); 174 } 175})(); 176 177 178// Test: create arrays in two contexts, verifying that the correct 179// map for Array in that context will be used. 180(function() { 181 function bar() { return new Array(); } 182 bar(); 183 bar(); 184 %OptimizeFunctionOnNextCall(bar); 185 a = bar(); 186 assertTrue(a instanceof Array); 187 188 var contextB = Realm.create(); 189 Realm.eval(contextB, "function bar2() { return new Array(); };"); 190 Realm.eval(contextB, "bar2(); bar2();"); 191 Realm.eval(contextB, "%OptimizeFunctionOnNextCall(bar2);"); 192 Realm.eval(contextB, "bar2();"); 193 assertFalse(Realm.eval(contextB, "bar2();") instanceof Array); 194 assertTrue(Realm.eval(contextB, "bar2() instanceof Array")); 195})(); 196 197// Test: create array with packed feedback, then optimize function, which 198// should deal with arguments that create holey arrays. 199(function() { 200 function bar(len) { return new Array(len); } 201 bar(0); 202 bar(0); 203 %OptimizeFunctionOnNextCall(bar); 204 a = bar(0); 205 assertOptimized(bar); 206 assertFalse(isHoley(a)); 207 a = bar(1); // ouch! 208 assertOptimized(bar); 209 assertTrue(isHoley(a)); 210 a = bar(100); 211 assertTrue(isHoley(a)); 212 a = bar(0); 213 assertOptimized(bar); 214 // Crankshafted functions don't use mementos, so feedback still 215 // indicates a packed array is desired. (unless --nocrankshaft is in use). 216 if (4 != %GetOptimizationStatus(bar)) { 217 assertFalse(isHoley(a)); 218 } 219})(); 220