OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // Flags: --turbo --turbo-escape --allow-natives-syntax |
| 6 |
| 7 "use strict"; |
| 8 |
| 9 const kDeoptimized = 2; |
| 10 const kTurbofanned = 7; |
| 11 const kInterpreted = 8; |
| 12 |
| 13 function GetOptimizationStatus(fn) { |
| 14 let status = %GetOptimizationStatus(fn); |
| 15 switch (status) { |
| 16 case kInterpreted: // Treat interpreted frames as unoptimized |
| 17 status = kDeoptimized; |
| 18 break; |
| 19 } |
| 20 |
| 21 return status; |
| 22 } |
| 23 |
| 24 let global = this; |
| 25 let tests = { |
| 26 FastElementsKind() { |
| 27 let runners = { |
| 28 FAST_SMI_ELEMENTS(array) { |
| 29 let sum = 0; |
| 30 for (let x of array) sum += x; |
| 31 return sum; |
| 32 }, |
| 33 |
| 34 FAST_HOLEY_SMI_ELEMENTS(array) { |
| 35 let sum = 0; |
| 36 for (let x of array) { |
| 37 if (x) sum += x; |
| 38 } |
| 39 return sum; |
| 40 }, |
| 41 |
| 42 FAST_ELEMENTS(array) { |
| 43 let ret = ""; |
| 44 for (let str of array) ret += `> ${str}`; |
| 45 return ret; |
| 46 }, |
| 47 |
| 48 FAST_HOLEY_ELEMENTS(array) { |
| 49 let ret = ""; |
| 50 for (let str of array) ret += `> ${str}`; |
| 51 return ret; |
| 52 }, |
| 53 |
| 54 FAST_DOUBLE_ELEMENTS(array) { |
| 55 let sum = 0.0; |
| 56 for (let x of array) sum += x; |
| 57 return sum; |
| 58 }, |
| 59 |
| 60 FAST_HOLEY_DOUBLE_ELEMENTS(array) { |
| 61 let sum = 0.0; |
| 62 for (let x of array) { |
| 63 if (x) sum += x; |
| 64 } |
| 65 return sum; |
| 66 } |
| 67 }; |
| 68 |
| 69 let tests = { |
| 70 FAST_SMI_ELEMENTS: { |
| 71 array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], |
| 72 expected: 55, |
| 73 array2: [1, 2, 3], |
| 74 expected2: 6 |
| 75 }, |
| 76 FAST_HOLEY_SMI_ELEMENTS: { |
| 77 array: [1, , 3, , 5, , 7, , 9, ,], |
| 78 expected: 25, |
| 79 array2: [1, , 3], |
| 80 expected2: 4 |
| 81 }, |
| 82 FAST_ELEMENTS: { |
| 83 array: ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"], |
| 84 expected: "> a> b> c> d> e> f> g> h> i> j", |
| 85 array2: ["a", "b", "c"], |
| 86 expected2: "> a> b> c" |
| 87 }, |
| 88 FAST_HOLEY_ELEMENTS: { |
| 89 array: ["a", , "c", , "e", , "g", , "i", ,], |
| 90 expected: "> a> undefined> c> undefined> e> undefined> g" + |
| 91 "> undefined> i> undefined", |
| 92 array2: ["a", , "c"], |
| 93 expected2: "> a> undefined> c" |
| 94 }, |
| 95 FAST_DOUBLE_ELEMENTS: { |
| 96 array: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], |
| 97 expected: 5.5, |
| 98 array2: [0.6, 0.4, 0.2], |
| 99 expected2: 1.2 |
| 100 }, |
| 101 FAST_HOLEY_DOUBLE_ELEMENTS: { |
| 102 array: [0.1, , 0.3, , 0.5, , 0.7, , 0.9, ,], |
| 103 expected: 2.5, |
| 104 array2: [0.1, , 0.3], |
| 105 expected2: 0.4 |
| 106 } |
| 107 }; |
| 108 |
| 109 for (let key of Object.keys(runners)) { |
| 110 let fn = runners[key]; |
| 111 let { array, expected, array2, expected2 } = tests[key]; |
| 112 |
| 113 // Warmup: |
| 114 fn(array); |
| 115 fn(array); |
| 116 %OptimizeFunctionOnNextCall(fn); |
| 117 fn(array); |
| 118 |
| 119 // TODO(bmeurer): FAST_HOLEY_DOUBLE_ELEMENTS maps generally deopt when |
| 120 // a hole is encountered. Test should be fixed once that is corrected. |
| 121 let status = /HOLEY_DOUBLE/.test(key) ? kDeoptimized : kTurbofanned; |
| 122 |
| 123 assertEquals(status, GetOptimizationStatus(fn), key); |
| 124 assertEquals(expected, fn(array), key); |
| 125 assertEquals(status, GetOptimizationStatus(fn), key); |
| 126 |
| 127 // Check no deopt when another arra with the same map is used |
| 128 assertTrue(%HaveSameMap(array, array2), key); |
| 129 assertEquals(status, GetOptimizationStatus(fn), key); |
| 130 assertEquals(expected2, fn(array2), key); |
| 131 |
| 132 // CheckMaps bailout |
| 133 let newArray = Object.defineProperty( |
| 134 [1, 2, 3], 2, { enumerable: false, configurable: false, |
| 135 get() { return 7; } }); |
| 136 fn(newArray); |
| 137 assertEquals(kDeoptimized, GetOptimizationStatus(fn), key); |
| 138 } |
| 139 }, |
| 140 |
| 141 TypedArrays() { |
| 142 let tests = { |
| 143 Uint8Array: { |
| 144 array: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, -1, 256]), |
| 145 expected: 291, |
| 146 array2: new Uint8Array([1, 2, 3]), |
| 147 expected2: 6 |
| 148 }, |
| 149 |
| 150 Int8Array: { |
| 151 array: new Int8Array([1, 2, 3, 4, 5, 6, 7, 8, -129, 128]), |
| 152 expected: 35, |
| 153 array2: new Int8Array([1, 2, 3]), |
| 154 expected2: 6 |
| 155 }, |
| 156 |
| 157 Uint16Array: { |
| 158 array: new Uint16Array([1, 2, 3, 4, 5, 6, 7, 8, -1, 0x10000]), |
| 159 expected: 65571, |
| 160 array2: new Uint16Array([1, 2, 3]), |
| 161 expected2: 6 |
| 162 }, |
| 163 |
| 164 Int16Array: { |
| 165 array: new Int16Array([1, 2, 3, 4, 5, 6, 7, 8, -32769, 0x7FFF]), |
| 166 expected: 65570, |
| 167 array2: new Int16Array([1, 2, 3]), |
| 168 expected2: 6 |
| 169 }, |
| 170 |
| 171 Uint32Array: { |
| 172 array: new Uint32Array([1, 2, 3, 4, 5, 6, 7, 8, -1, 0x100000000]), |
| 173 expected: 4294967331, |
| 174 array2: new Uint32Array([1, 2, 3]), |
| 175 expected2: 6 |
| 176 }, |
| 177 |
| 178 Int32Array: { |
| 179 array: new Int32Array([1, 2, 3, 4, 5, 6, 7, 8, |
| 180 -2147483649, 0x7FFFFFFF]), |
| 181 expected: 4294967330, |
| 182 array2: new Int32Array([1, 2, 3]), |
| 183 expected2: 6 |
| 184 }, |
| 185 |
| 186 Float32Array: { |
| 187 array: new Float32Array([9.5, 8.0, 7.0, 7.0, 5.0, 4.0, 3.0, 2.0]), |
| 188 expected: 45.5, |
| 189 array2: new Float32Array([10.5, 5.5, 1.5]), |
| 190 expected2: 17.5 |
| 191 }, |
| 192 |
| 193 Float64Array: { |
| 194 array: new Float64Array([9.5, 8.0, 7.0, 7.0, 5.0, 4.0, 3.0, 2.0]), |
| 195 expected: 45.5, |
| 196 array2: new Float64Array([10.5, 5.5, 1.5]), |
| 197 expected2: 17.5 |
| 198 }, |
| 199 |
| 200 Uint8ClampedArray: { |
| 201 array: new Uint8ClampedArray([4.3, 7.45632, 3.14, 4.61, 5.0004, 6.493, |
| 202 7.12, 8, 1.7, 3.6]), |
| 203 expected: 51, |
| 204 array2: new Uint8ClampedArray([1, 2, 3]), |
| 205 expected2: 6 |
| 206 } |
| 207 }; |
| 208 |
| 209 for (let key of Object.keys(tests)) { |
| 210 let test = tests[key]; |
| 211 let { array, expected, array2, expected2 } = test; |
| 212 |
| 213 let sum = function(array) { |
| 214 let ret = 0; |
| 215 for (let x of array) ret += x; |
| 216 return ret; |
| 217 }; |
| 218 |
| 219 // Warmup |
| 220 sum(array); |
| 221 sum(array); |
| 222 %OptimizeFunctionOnNextCall(sum); |
| 223 assertEquals(expected, sum(array), key); |
| 224 |
| 225 assertEquals(kTurbofanned, GetOptimizationStatus(sum), key); |
| 226 |
| 227 // Not deoptimized when called on typed array of same type / map |
| 228 assertTrue(%HaveSameMap(array, array2)); |
| 229 assertEquals(expected2, sum(array2), key); |
| 230 assertEquals(kTurbofanned, GetOptimizationStatus(sum), key); |
| 231 |
| 232 // Throw when detached |
| 233 let clone = new array.constructor(array); |
| 234 %ArrayBufferNeuter(clone.buffer); |
| 235 assertThrows(() => sum(clone), TypeError); |
| 236 } |
| 237 } |
| 238 }; |
| 239 |
| 240 for (let name of Object.keys(tests)) { |
| 241 let test = tests[name]; |
| 242 test(); |
| 243 } |
OLD | NEW |