OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import '../compiler.dart' show Compiler; | 5 import '../compiler.dart' show Compiler; |
6 import '../constants/constant_system.dart'; | 6 import '../constants/constant_system.dart'; |
7 import '../constants/values.dart'; | 7 import '../constants/values.dart'; |
8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
9 import '../js_backend/js_backend.dart'; | 9 import '../js_backend/js_backend.dart'; |
10 import '../types/types.dart'; | 10 import '../types/types.dart'; |
11 import '../universe/call_structure.dart'; | 11 import '../universe/call_structure.dart'; |
12 import '../universe/selector.dart'; | 12 import '../universe/selector.dart'; |
13 import '../world.dart' show ClosedWorld; | 13 import '../world.dart' show ClosedWorld; |
14 import 'nodes.dart'; | 14 import 'nodes.dart'; |
15 import 'types.dart'; | 15 import 'types.dart'; |
16 | 16 |
17 /** | 17 /** |
18 * [InvokeDynamicSpecializer] and its subclasses are helpers to | 18 * [InvokeDynamicSpecializer] and its subclasses are helpers to |
19 * optimize intercepted dynamic calls. It knows what input types | 19 * optimize intercepted dynamic calls. It knows what input types |
20 * would be beneficial for performance, and how to change a invoke | 20 * would be beneficial for performance, and how to change a invoke |
21 * dynamic to a builtin instruction (e.g. HIndex, HBitNot). | 21 * dynamic to a builtin instruction (e.g. HIndex, HBitNot). |
22 */ | 22 */ |
23 class InvokeDynamicSpecializer { | 23 class InvokeDynamicSpecializer { |
24 const InvokeDynamicSpecializer(); | 24 const InvokeDynamicSpecializer(); |
25 | 25 |
26 TypeMask computeTypeFromInputTypes( | 26 TypeMask computeTypeFromInputTypes( |
27 HInvokeDynamic instruction, Compiler compiler) { | 27 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
28 return TypeMaskFactory.inferredTypeForSelector( | 28 return TypeMaskFactory.inferredTypeForSelector( |
29 instruction.selector, instruction.mask, compiler); | 29 instruction.selector, instruction.mask, compiler); |
30 } | 30 } |
31 | 31 |
32 HInstruction tryConvertToBuiltin( | 32 HInstruction tryConvertToBuiltin( |
33 HInvokeDynamic instruction, Compiler compiler) { | 33 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
34 return null; | 34 return null; |
35 } | 35 } |
36 | 36 |
37 void clearAllSideEffects(HInstruction instruction) { | 37 void clearAllSideEffects(HInstruction instruction) { |
38 instruction.sideEffects.clearAllSideEffects(); | 38 instruction.sideEffects.clearAllSideEffects(); |
39 instruction.sideEffects.clearAllDependencies(); | 39 instruction.sideEffects.clearAllDependencies(); |
40 instruction.setUseGvn(); | 40 instruction.setUseGvn(); |
41 } | 41 } |
42 | 42 |
43 Operation operation(ConstantSystem constantSystem) => null; | 43 Operation operation(ConstantSystem constantSystem) => null; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 } | 78 } |
79 } | 79 } |
80 return const InvokeDynamicSpecializer(); | 80 return const InvokeDynamicSpecializer(); |
81 } | 81 } |
82 } | 82 } |
83 | 83 |
84 class IndexAssignSpecializer extends InvokeDynamicSpecializer { | 84 class IndexAssignSpecializer extends InvokeDynamicSpecializer { |
85 const IndexAssignSpecializer(); | 85 const IndexAssignSpecializer(); |
86 | 86 |
87 HInstruction tryConvertToBuiltin( | 87 HInstruction tryConvertToBuiltin( |
88 HInvokeDynamic instruction, Compiler compiler) { | 88 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
89 if (instruction.inputs[1].isMutableIndexable(compiler)) { | 89 if (instruction.inputs[1].isMutableIndexable(closedWorld)) { |
90 if (!instruction.inputs[2].isInteger(compiler) && | 90 if (!instruction.inputs[2].isInteger(closedWorld) && |
91 compiler.options.enableTypeAssertions) { | 91 compiler.options.enableTypeAssertions) { |
92 // We want the right checked mode error. | 92 // We want the right checked mode error. |
93 return null; | 93 return null; |
94 } | 94 } |
95 return new HIndexAssign(instruction.inputs[1], instruction.inputs[2], | 95 return new HIndexAssign(instruction.inputs[1], instruction.inputs[2], |
96 instruction.inputs[3], instruction.selector); | 96 instruction.inputs[3], instruction.selector); |
97 } | 97 } |
98 return null; | 98 return null; |
99 } | 99 } |
100 } | 100 } |
101 | 101 |
102 class IndexSpecializer extends InvokeDynamicSpecializer { | 102 class IndexSpecializer extends InvokeDynamicSpecializer { |
103 const IndexSpecializer(); | 103 const IndexSpecializer(); |
104 | 104 |
105 HInstruction tryConvertToBuiltin( | 105 HInstruction tryConvertToBuiltin( |
106 HInvokeDynamic instruction, Compiler compiler) { | 106 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
107 if (!instruction.inputs[1].isIndexablePrimitive(compiler)) return null; | 107 if (!instruction.inputs[1].isIndexablePrimitive(closedWorld)) return null; |
108 if (!instruction.inputs[2].isInteger(compiler) && | 108 if (!instruction.inputs[2].isInteger(closedWorld) && |
109 compiler.options.enableTypeAssertions) { | 109 compiler.options.enableTypeAssertions) { |
110 // We want the right checked mode error. | 110 // We want the right checked mode error. |
111 return null; | 111 return null; |
112 } | 112 } |
113 TypeMask receiverType = | 113 TypeMask receiverType = |
114 instruction.getDartReceiver(compiler).instructionType; | 114 instruction.getDartReceiver(compiler).instructionType; |
115 TypeMask type = TypeMaskFactory.inferredTypeForSelector( | 115 TypeMask type = TypeMaskFactory.inferredTypeForSelector( |
116 instruction.selector, receiverType, compiler); | 116 instruction.selector, receiverType, compiler); |
117 return new HIndex(instruction.inputs[1], instruction.inputs[2], | 117 return new HIndex(instruction.inputs[1], instruction.inputs[2], |
118 instruction.selector, type); | 118 instruction.selector, type); |
119 } | 119 } |
120 } | 120 } |
121 | 121 |
122 class BitNotSpecializer extends InvokeDynamicSpecializer { | 122 class BitNotSpecializer extends InvokeDynamicSpecializer { |
123 const BitNotSpecializer(); | 123 const BitNotSpecializer(); |
124 | 124 |
125 UnaryOperation operation(ConstantSystem constantSystem) { | 125 UnaryOperation operation(ConstantSystem constantSystem) { |
126 return constantSystem.bitNot; | 126 return constantSystem.bitNot; |
127 } | 127 } |
128 | 128 |
129 TypeMask computeTypeFromInputTypes( | 129 TypeMask computeTypeFromInputTypes( |
130 HInvokeDynamic instruction, Compiler compiler) { | 130 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
131 // All bitwise operations on primitive types either produce an | 131 // All bitwise operations on primitive types either produce an |
132 // integer or throw an error. | 132 // integer or throw an error. |
133 JavaScriptBackend backend = compiler.backend; | 133 if (instruction.inputs[1].isPrimitiveOrNull(closedWorld)) { |
134 if (instruction.inputs[1].isPrimitiveOrNull(compiler)) { | 134 return closedWorld.commonMasks.uint32Type; |
135 return backend.uint32Type; | |
136 } | 135 } |
137 return super.computeTypeFromInputTypes(instruction, compiler); | 136 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
138 } | 137 } |
139 | 138 |
140 HInstruction tryConvertToBuiltin( | 139 HInstruction tryConvertToBuiltin( |
141 HInvokeDynamic instruction, Compiler compiler) { | 140 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
142 HInstruction input = instruction.inputs[1]; | 141 HInstruction input = instruction.inputs[1]; |
143 if (input.isNumber(compiler)) { | 142 if (input.isNumber(closedWorld)) { |
144 return new HBitNot(input, instruction.selector, | 143 return new HBitNot(input, instruction.selector, |
145 computeTypeFromInputTypes(instruction, compiler)); | 144 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
146 } | 145 } |
147 return null; | 146 return null; |
148 } | 147 } |
149 } | 148 } |
150 | 149 |
151 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { | 150 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { |
152 const UnaryNegateSpecializer(); | 151 const UnaryNegateSpecializer(); |
153 | 152 |
154 UnaryOperation operation(ConstantSystem constantSystem) { | 153 UnaryOperation operation(ConstantSystem constantSystem) { |
155 return constantSystem.negate; | 154 return constantSystem.negate; |
156 } | 155 } |
157 | 156 |
158 TypeMask computeTypeFromInputTypes( | 157 TypeMask computeTypeFromInputTypes( |
159 HInvokeDynamic instruction, Compiler compiler) { | 158 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
160 TypeMask operandType = instruction.inputs[1].instructionType; | 159 TypeMask operandType = instruction.inputs[1].instructionType; |
161 if (instruction.inputs[1].isNumberOrNull(compiler)) return operandType; | 160 if (instruction.inputs[1].isNumberOrNull(closedWorld)) return operandType; |
162 return super.computeTypeFromInputTypes(instruction, compiler); | 161 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
163 } | 162 } |
164 | 163 |
165 HInstruction tryConvertToBuiltin( | 164 HInstruction tryConvertToBuiltin( |
166 HInvokeDynamic instruction, Compiler compiler) { | 165 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
167 HInstruction input = instruction.inputs[1]; | 166 HInstruction input = instruction.inputs[1]; |
168 if (input.isNumber(compiler)) { | 167 if (input.isNumber(closedWorld)) { |
169 return new HNegate(input, instruction.selector, input.instructionType); | 168 return new HNegate(input, instruction.selector, input.instructionType); |
170 } | 169 } |
171 return null; | 170 return null; |
172 } | 171 } |
173 } | 172 } |
174 | 173 |
175 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { | 174 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { |
176 const BinaryArithmeticSpecializer(); | 175 const BinaryArithmeticSpecializer(); |
177 | 176 |
178 TypeMask computeTypeFromInputTypes( | 177 TypeMask computeTypeFromInputTypes( |
179 HInvokeDynamic instruction, Compiler compiler) { | 178 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
180 HInstruction left = instruction.inputs[1]; | 179 HInstruction left = instruction.inputs[1]; |
181 HInstruction right = instruction.inputs[2]; | 180 HInstruction right = instruction.inputs[2]; |
182 JavaScriptBackend backend = compiler.backend; | 181 if (left.isIntegerOrNull(closedWorld) && |
183 if (left.isIntegerOrNull(compiler) && right.isIntegerOrNull(compiler)) { | 182 right.isIntegerOrNull(closedWorld)) { |
184 return backend.intType; | 183 return closedWorld.commonMasks.intType; |
185 } | 184 } |
186 if (left.isNumberOrNull(compiler)) { | 185 if (left.isNumberOrNull(closedWorld)) { |
187 if (left.isDoubleOrNull(compiler) || right.isDoubleOrNull(compiler)) { | 186 if (left.isDoubleOrNull(closedWorld) || |
188 return backend.doubleType; | 187 right.isDoubleOrNull(closedWorld)) { |
| 188 return closedWorld.commonMasks.doubleType; |
189 } | 189 } |
190 return backend.numType; | 190 return closedWorld.commonMasks.numType; |
191 } | 191 } |
192 return super.computeTypeFromInputTypes(instruction, compiler); | 192 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
193 } | 193 } |
194 | 194 |
195 bool isBuiltin(HInvokeDynamic instruction, Compiler compiler) { | 195 bool isBuiltin(HInvokeDynamic instruction, ClosedWorld closedWorld) { |
196 return instruction.inputs[1].isNumber(compiler) && | 196 return instruction.inputs[1].isNumber(closedWorld) && |
197 instruction.inputs[2].isNumber(compiler); | 197 instruction.inputs[2].isNumber(closedWorld); |
198 } | 198 } |
199 | 199 |
200 HInstruction tryConvertToBuiltin( | 200 HInstruction tryConvertToBuiltin( |
201 HInvokeDynamic instruction, Compiler compiler) { | 201 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
202 if (isBuiltin(instruction, compiler)) { | 202 if (isBuiltin(instruction, closedWorld)) { |
203 HInstruction builtin = newBuiltinVariant(instruction, compiler); | 203 HInstruction builtin = |
| 204 newBuiltinVariant(instruction, compiler, closedWorld); |
204 if (builtin != null) return builtin; | 205 if (builtin != null) return builtin; |
205 // Even if there is no builtin equivalent instruction, we know | 206 // Even if there is no builtin equivalent instruction, we know |
206 // the instruction does not have any side effect, and that it | 207 // the instruction does not have any side effect, and that it |
207 // can be GVN'ed. | 208 // can be GVN'ed. |
208 clearAllSideEffects(instruction); | 209 clearAllSideEffects(instruction); |
209 } | 210 } |
210 return null; | 211 return null; |
211 } | 212 } |
212 | 213 |
213 bool inputsArePositiveIntegers(HInstruction instruction, Compiler compiler) { | 214 bool inputsArePositiveIntegers( |
| 215 HInstruction instruction, ClosedWorld closedWorld) { |
214 HInstruction left = instruction.inputs[1]; | 216 HInstruction left = instruction.inputs[1]; |
215 HInstruction right = instruction.inputs[2]; | 217 HInstruction right = instruction.inputs[2]; |
216 return left.isPositiveIntegerOrNull(compiler) && | 218 return left.isPositiveIntegerOrNull(closedWorld) && |
217 right.isPositiveIntegerOrNull(compiler); | 219 right.isPositiveIntegerOrNull(closedWorld); |
218 } | 220 } |
219 | 221 |
220 bool inputsAreUInt31(HInstruction instruction, Compiler compiler) { | 222 bool inputsAreUInt31(HInstruction instruction, ClosedWorld closedWorld) { |
221 HInstruction left = instruction.inputs[1]; | 223 HInstruction left = instruction.inputs[1]; |
222 HInstruction right = instruction.inputs[2]; | 224 HInstruction right = instruction.inputs[2]; |
223 return left.isUInt31(compiler) && right.isUInt31(compiler); | 225 return left.isUInt31(closedWorld) && right.isUInt31(closedWorld); |
224 } | 226 } |
225 | 227 |
226 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); | 228 HInstruction newBuiltinVariant( |
| 229 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld); |
227 | 230 |
228 Selector renameToOptimizedSelector( | 231 Selector renameToOptimizedSelector( |
229 String name, Selector selector, Compiler compiler) { | 232 String name, Selector selector, Compiler compiler) { |
230 if (selector.name == name) return selector; | 233 if (selector.name == name) return selector; |
231 JavaScriptBackend backend = compiler.backend; | 234 JavaScriptBackend backend = compiler.backend; |
232 return new Selector.call( | 235 return new Selector.call( |
233 new Name(name, backend.helpers.interceptorsLibrary), | 236 new Name(name, backend.helpers.interceptorsLibrary), |
234 new CallStructure(selector.argumentCount)); | 237 new CallStructure(selector.argumentCount)); |
235 } | 238 } |
236 } | 239 } |
237 | 240 |
238 class AddSpecializer extends BinaryArithmeticSpecializer { | 241 class AddSpecializer extends BinaryArithmeticSpecializer { |
239 const AddSpecializer(); | 242 const AddSpecializer(); |
240 | 243 |
241 TypeMask computeTypeFromInputTypes( | 244 TypeMask computeTypeFromInputTypes( |
242 HInvokeDynamic instruction, Compiler compiler) { | 245 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
243 if (inputsAreUInt31(instruction, compiler)) { | 246 if (inputsAreUInt31(instruction, closedWorld)) { |
244 JavaScriptBackend backend = compiler.backend; | 247 return closedWorld.commonMasks.uint32Type; |
245 return backend.uint32Type; | |
246 } | 248 } |
247 if (inputsArePositiveIntegers(instruction, compiler)) { | 249 if (inputsArePositiveIntegers(instruction, closedWorld)) { |
248 JavaScriptBackend backend = compiler.backend; | 250 return closedWorld.commonMasks.positiveIntType; |
249 return backend.positiveIntType; | |
250 } | 251 } |
251 return super.computeTypeFromInputTypes(instruction, compiler); | 252 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
252 } | 253 } |
253 | 254 |
254 BinaryOperation operation(ConstantSystem constantSystem) { | 255 BinaryOperation operation(ConstantSystem constantSystem) { |
255 return constantSystem.add; | 256 return constantSystem.add; |
256 } | 257 } |
257 | 258 |
258 HInstruction newBuiltinVariant( | 259 HInstruction newBuiltinVariant( |
259 HInvokeDynamic instruction, Compiler compiler) { | 260 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
260 return new HAdd(instruction.inputs[1], instruction.inputs[2], | 261 return new HAdd( |
261 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 262 instruction.inputs[1], |
| 263 instruction.inputs[2], |
| 264 instruction.selector, |
| 265 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
262 } | 266 } |
263 } | 267 } |
264 | 268 |
265 class DivideSpecializer extends BinaryArithmeticSpecializer { | 269 class DivideSpecializer extends BinaryArithmeticSpecializer { |
266 const DivideSpecializer(); | 270 const DivideSpecializer(); |
267 | 271 |
268 BinaryOperation operation(ConstantSystem constantSystem) { | 272 BinaryOperation operation(ConstantSystem constantSystem) { |
269 return constantSystem.divide; | 273 return constantSystem.divide; |
270 } | 274 } |
271 | 275 |
272 TypeMask computeTypeFromInputTypes( | 276 TypeMask computeTypeFromInputTypes( |
273 HInstruction instruction, Compiler compiler) { | 277 HInstruction instruction, Compiler compiler, ClosedWorld closedWorld) { |
274 HInstruction left = instruction.inputs[1]; | 278 HInstruction left = instruction.inputs[1]; |
275 JavaScriptBackend backend = compiler.backend; | 279 if (left.isNumberOrNull(closedWorld)) { |
276 if (left.isNumberOrNull(compiler)) { | 280 return closedWorld.commonMasks.doubleType; |
277 return backend.doubleType; | |
278 } | 281 } |
279 return super.computeTypeFromInputTypes(instruction, compiler); | 282 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
280 } | 283 } |
281 | 284 |
282 HInstruction newBuiltinVariant( | 285 HInstruction newBuiltinVariant( |
283 HInvokeDynamic instruction, Compiler compiler) { | 286 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
284 JavaScriptBackend backend = compiler.backend; | |
285 return new HDivide(instruction.inputs[1], instruction.inputs[2], | 287 return new HDivide(instruction.inputs[1], instruction.inputs[2], |
286 instruction.selector, backend.doubleType); | 288 instruction.selector, closedWorld.commonMasks.doubleType); |
287 } | 289 } |
288 } | 290 } |
289 | 291 |
290 class ModuloSpecializer extends BinaryArithmeticSpecializer { | 292 class ModuloSpecializer extends BinaryArithmeticSpecializer { |
291 const ModuloSpecializer(); | 293 const ModuloSpecializer(); |
292 | 294 |
293 TypeMask computeTypeFromInputTypes( | 295 TypeMask computeTypeFromInputTypes( |
294 HInvokeDynamic instruction, Compiler compiler) { | 296 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
295 if (inputsArePositiveIntegers(instruction, compiler)) { | 297 if (inputsArePositiveIntegers(instruction, closedWorld)) { |
296 JavaScriptBackend backend = compiler.backend; | 298 return closedWorld.commonMasks.positiveIntType; |
297 return backend.positiveIntType; | |
298 } | 299 } |
299 return super.computeTypeFromInputTypes(instruction, compiler); | 300 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
300 } | 301 } |
301 | 302 |
302 BinaryOperation operation(ConstantSystem constantSystem) { | 303 BinaryOperation operation(ConstantSystem constantSystem) { |
303 return constantSystem.modulo; | 304 return constantSystem.modulo; |
304 } | 305 } |
305 | 306 |
306 HInstruction newBuiltinVariant( | 307 HInstruction newBuiltinVariant( |
307 HInvokeDynamic instruction, Compiler compiler) { | 308 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
308 // Modulo cannot be mapped to the native operator (different semantics). | 309 // Modulo cannot be mapped to the native operator (different semantics). |
309 // TODO(sra): For non-negative values we can use JavaScript's %. | 310 // TODO(sra): For non-negative values we can use JavaScript's %. |
310 return null; | 311 return null; |
311 } | 312 } |
312 } | 313 } |
313 | 314 |
314 class MultiplySpecializer extends BinaryArithmeticSpecializer { | 315 class MultiplySpecializer extends BinaryArithmeticSpecializer { |
315 const MultiplySpecializer(); | 316 const MultiplySpecializer(); |
316 | 317 |
317 BinaryOperation operation(ConstantSystem constantSystem) { | 318 BinaryOperation operation(ConstantSystem constantSystem) { |
318 return constantSystem.multiply; | 319 return constantSystem.multiply; |
319 } | 320 } |
320 | 321 |
321 TypeMask computeTypeFromInputTypes( | 322 TypeMask computeTypeFromInputTypes( |
322 HInvokeDynamic instruction, Compiler compiler) { | 323 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
323 if (inputsArePositiveIntegers(instruction, compiler)) { | 324 if (inputsArePositiveIntegers(instruction, closedWorld)) { |
324 JavaScriptBackend backend = compiler.backend; | 325 return closedWorld.commonMasks.positiveIntType; |
325 return backend.positiveIntType; | |
326 } | 326 } |
327 return super.computeTypeFromInputTypes(instruction, compiler); | 327 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
328 } | 328 } |
329 | 329 |
330 HInstruction newBuiltinVariant( | 330 HInstruction newBuiltinVariant( |
331 HInvokeDynamic instruction, Compiler compiler) { | 331 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
332 return new HMultiply(instruction.inputs[1], instruction.inputs[2], | 332 return new HMultiply( |
333 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 333 instruction.inputs[1], |
| 334 instruction.inputs[2], |
| 335 instruction.selector, |
| 336 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
334 } | 337 } |
335 } | 338 } |
336 | 339 |
337 class SubtractSpecializer extends BinaryArithmeticSpecializer { | 340 class SubtractSpecializer extends BinaryArithmeticSpecializer { |
338 const SubtractSpecializer(); | 341 const SubtractSpecializer(); |
339 | 342 |
340 BinaryOperation operation(ConstantSystem constantSystem) { | 343 BinaryOperation operation(ConstantSystem constantSystem) { |
341 return constantSystem.subtract; | 344 return constantSystem.subtract; |
342 } | 345 } |
343 | 346 |
344 HInstruction newBuiltinVariant( | 347 HInstruction newBuiltinVariant( |
345 HInvokeDynamic instruction, Compiler compiler) { | 348 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
346 return new HSubtract(instruction.inputs[1], instruction.inputs[2], | 349 return new HSubtract( |
347 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 350 instruction.inputs[1], |
| 351 instruction.inputs[2], |
| 352 instruction.selector, |
| 353 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
348 } | 354 } |
349 } | 355 } |
350 | 356 |
351 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { | 357 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { |
352 const TruncatingDivideSpecializer(); | 358 const TruncatingDivideSpecializer(); |
353 | 359 |
354 BinaryOperation operation(ConstantSystem constantSystem) { | 360 BinaryOperation operation(ConstantSystem constantSystem) { |
355 return constantSystem.truncatingDivide; | 361 return constantSystem.truncatingDivide; |
356 } | 362 } |
357 | 363 |
358 TypeMask computeTypeFromInputTypes( | 364 TypeMask computeTypeFromInputTypes( |
359 HInvokeDynamic instruction, Compiler compiler) { | 365 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
360 JavaScriptBackend backend = compiler.backend; | 366 if (hasUint31Result(instruction, closedWorld)) { |
361 if (hasUint31Result(instruction, compiler)) { | 367 return closedWorld.commonMasks.uint31Type; |
362 return backend.uint31Type; | |
363 } | 368 } |
364 if (inputsArePositiveIntegers(instruction, compiler)) { | 369 if (inputsArePositiveIntegers(instruction, closedWorld)) { |
365 return backend.positiveIntType; | 370 return closedWorld.commonMasks.positiveIntType; |
366 } | 371 } |
367 return super.computeTypeFromInputTypes(instruction, compiler); | 372 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
368 } | 373 } |
369 | 374 |
370 bool isNotZero(HInstruction instruction, Compiler compiler) { | 375 bool isNotZero(HInstruction instruction) { |
371 if (!instruction.isConstantInteger()) return false; | 376 if (!instruction.isConstantInteger()) return false; |
372 HConstant rightConstant = instruction; | 377 HConstant rightConstant = instruction; |
373 IntConstantValue intConstant = rightConstant.constant; | 378 IntConstantValue intConstant = rightConstant.constant; |
374 int count = intConstant.primitiveValue; | 379 int count = intConstant.primitiveValue; |
375 return count != 0; | 380 return count != 0; |
376 } | 381 } |
377 | 382 |
378 bool isTwoOrGreater(HInstruction instruction, Compiler compiler) { | 383 bool isTwoOrGreater(HInstruction instruction) { |
379 if (!instruction.isConstantInteger()) return false; | 384 if (!instruction.isConstantInteger()) return false; |
380 HConstant rightConstant = instruction; | 385 HConstant rightConstant = instruction; |
381 IntConstantValue intConstant = rightConstant.constant; | 386 IntConstantValue intConstant = rightConstant.constant; |
382 int count = intConstant.primitiveValue; | 387 int count = intConstant.primitiveValue; |
383 return count >= 2; | 388 return count >= 2; |
384 } | 389 } |
385 | 390 |
386 bool hasUint31Result(HInstruction instruction, Compiler compiler) { | 391 bool hasUint31Result(HInstruction instruction, ClosedWorld closedWorld) { |
387 HInstruction left = instruction.inputs[1]; | 392 HInstruction left = instruction.inputs[1]; |
388 HInstruction right = instruction.inputs[2]; | 393 HInstruction right = instruction.inputs[2]; |
389 if (right.isPositiveInteger(compiler)) { | 394 if (right.isPositiveInteger(closedWorld)) { |
390 if (left.isUInt31(compiler) && isNotZero(right, compiler)) { | 395 if (left.isUInt31(closedWorld) && isNotZero(right)) { |
391 return true; | 396 return true; |
392 } | 397 } |
393 if (left.isUInt32(compiler) && isTwoOrGreater(right, compiler)) { | 398 if (left.isUInt32(closedWorld) && isTwoOrGreater(right)) { |
394 return true; | 399 return true; |
395 } | 400 } |
396 } | 401 } |
397 return false; | 402 return false; |
398 } | 403 } |
399 | 404 |
400 HInstruction tryConvertToBuiltin( | 405 HInstruction tryConvertToBuiltin( |
401 HInvokeDynamic instruction, Compiler compiler) { | 406 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
402 HInstruction right = instruction.inputs[2]; | 407 HInstruction right = instruction.inputs[2]; |
403 if (isBuiltin(instruction, compiler)) { | 408 if (isBuiltin(instruction, closedWorld)) { |
404 if (right.isPositiveInteger(compiler) && isNotZero(right, compiler)) { | 409 if (right.isPositiveInteger(closedWorld) && isNotZero(right)) { |
405 if (hasUint31Result(instruction, compiler)) { | 410 if (hasUint31Result(instruction, closedWorld)) { |
406 return newBuiltinVariant(instruction, compiler); | 411 return newBuiltinVariant(instruction, compiler, closedWorld); |
407 } | 412 } |
408 // We can call _tdivFast because the rhs is a 32bit integer | 413 // We can call _tdivFast because the rhs is a 32bit integer |
409 // and not 0, nor -1. | 414 // and not 0, nor -1. |
410 instruction.selector = renameToOptimizedSelector( | 415 instruction.selector = renameToOptimizedSelector( |
411 '_tdivFast', instruction.selector, compiler); | 416 '_tdivFast', instruction.selector, compiler); |
412 } | 417 } |
413 clearAllSideEffects(instruction); | 418 clearAllSideEffects(instruction); |
414 } | 419 } |
415 return null; | 420 return null; |
416 } | 421 } |
417 | 422 |
418 HInstruction newBuiltinVariant( | 423 HInstruction newBuiltinVariant( |
419 HInvokeDynamic instruction, Compiler compiler) { | 424 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
420 return new HTruncatingDivide(instruction.inputs[1], instruction.inputs[2], | 425 return new HTruncatingDivide( |
421 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 426 instruction.inputs[1], |
| 427 instruction.inputs[2], |
| 428 instruction.selector, |
| 429 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
422 } | 430 } |
423 } | 431 } |
424 | 432 |
425 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { | 433 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { |
426 const BinaryBitOpSpecializer(); | 434 const BinaryBitOpSpecializer(); |
427 | 435 |
428 TypeMask computeTypeFromInputTypes( | 436 TypeMask computeTypeFromInputTypes( |
429 HInvokeDynamic instruction, Compiler compiler) { | 437 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
430 // All bitwise operations on primitive types either produce an | 438 // All bitwise operations on primitive types either produce an |
431 // integer or throw an error. | 439 // integer or throw an error. |
432 HInstruction left = instruction.inputs[1]; | 440 HInstruction left = instruction.inputs[1]; |
433 JavaScriptBackend backend = compiler.backend; | 441 if (left.isPrimitiveOrNull(closedWorld)) { |
434 if (left.isPrimitiveOrNull(compiler)) { | 442 return closedWorld.commonMasks.uint32Type; |
435 return backend.uint32Type; | |
436 } | 443 } |
437 return super.computeTypeFromInputTypes(instruction, compiler); | 444 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
438 } | 445 } |
439 | 446 |
440 bool argumentLessThan32(HInstruction instruction) { | 447 bool argumentLessThan32(HInstruction instruction) { |
441 if (!instruction.isConstantInteger()) return false; | 448 if (!instruction.isConstantInteger()) return false; |
442 HConstant rightConstant = instruction; | 449 HConstant rightConstant = instruction; |
443 IntConstantValue intConstant = rightConstant.constant; | 450 IntConstantValue intConstant = rightConstant.constant; |
444 int count = intConstant.primitiveValue; | 451 int count = intConstant.primitiveValue; |
445 return count >= 0 && count <= 31; | 452 return count >= 0 && count <= 31; |
446 } | 453 } |
447 | 454 |
448 bool isPositive(HInstruction instruction, Compiler compiler) { | 455 bool isPositive(HInstruction instruction, ClosedWorld closedWorld) { |
449 // TODO: We should use the value range analysis. Currently, ranges | 456 // TODO: We should use the value range analysis. Currently, ranges |
450 // are discarded just after the analysis. | 457 // are discarded just after the analysis. |
451 return instruction.isPositiveInteger(compiler); | 458 return instruction.isPositiveInteger(closedWorld); |
452 } | 459 } |
453 } | 460 } |
454 | 461 |
455 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { | 462 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { |
456 const ShiftLeftSpecializer(); | 463 const ShiftLeftSpecializer(); |
457 | 464 |
458 BinaryOperation operation(ConstantSystem constantSystem) { | 465 BinaryOperation operation(ConstantSystem constantSystem) { |
459 return constantSystem.shiftLeft; | 466 return constantSystem.shiftLeft; |
460 } | 467 } |
461 | 468 |
462 HInstruction tryConvertToBuiltin( | 469 HInstruction tryConvertToBuiltin( |
463 HInvokeDynamic instruction, Compiler compiler) { | 470 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
464 HInstruction left = instruction.inputs[1]; | 471 HInstruction left = instruction.inputs[1]; |
465 HInstruction right = instruction.inputs[2]; | 472 HInstruction right = instruction.inputs[2]; |
466 if (left.isNumber(compiler)) { | 473 if (left.isNumber(closedWorld)) { |
467 if (argumentLessThan32(right)) { | 474 if (argumentLessThan32(right)) { |
468 return newBuiltinVariant(instruction, compiler); | 475 return newBuiltinVariant(instruction, compiler, closedWorld); |
469 } | 476 } |
470 // Even if there is no builtin equivalent instruction, we know | 477 // Even if there is no builtin equivalent instruction, we know |
471 // the instruction does not have any side effect, and that it | 478 // the instruction does not have any side effect, and that it |
472 // can be GVN'ed. | 479 // can be GVN'ed. |
473 clearAllSideEffects(instruction); | 480 clearAllSideEffects(instruction); |
474 if (isPositive(right, compiler)) { | 481 if (isPositive(right, closedWorld)) { |
475 instruction.selector = renameToOptimizedSelector( | 482 instruction.selector = renameToOptimizedSelector( |
476 '_shlPositive', instruction.selector, compiler); | 483 '_shlPositive', instruction.selector, compiler); |
477 } | 484 } |
478 } | 485 } |
479 return null; | 486 return null; |
480 } | 487 } |
481 | 488 |
482 HInstruction newBuiltinVariant( | 489 HInstruction newBuiltinVariant( |
483 HInvokeDynamic instruction, Compiler compiler) { | 490 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
484 return new HShiftLeft(instruction.inputs[1], instruction.inputs[2], | 491 return new HShiftLeft( |
485 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 492 instruction.inputs[1], |
| 493 instruction.inputs[2], |
| 494 instruction.selector, |
| 495 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
486 } | 496 } |
487 } | 497 } |
488 | 498 |
489 class ShiftRightSpecializer extends BinaryBitOpSpecializer { | 499 class ShiftRightSpecializer extends BinaryBitOpSpecializer { |
490 const ShiftRightSpecializer(); | 500 const ShiftRightSpecializer(); |
491 | 501 |
492 TypeMask computeTypeFromInputTypes( | 502 TypeMask computeTypeFromInputTypes( |
493 HInvokeDynamic instruction, Compiler compiler) { | 503 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
494 HInstruction left = instruction.inputs[1]; | 504 HInstruction left = instruction.inputs[1]; |
495 if (left.isUInt32(compiler)) return left.instructionType; | 505 if (left.isUInt32(closedWorld)) return left.instructionType; |
496 return super.computeTypeFromInputTypes(instruction, compiler); | 506 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
497 } | 507 } |
498 | 508 |
499 HInstruction tryConvertToBuiltin( | 509 HInstruction tryConvertToBuiltin( |
500 HInvokeDynamic instruction, Compiler compiler) { | 510 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
501 HInstruction left = instruction.inputs[1]; | 511 HInstruction left = instruction.inputs[1]; |
502 HInstruction right = instruction.inputs[2]; | 512 HInstruction right = instruction.inputs[2]; |
503 if (left.isNumber(compiler)) { | 513 if (left.isNumber(closedWorld)) { |
504 if (argumentLessThan32(right) && isPositive(left, compiler)) { | 514 if (argumentLessThan32(right) && isPositive(left, closedWorld)) { |
505 return newBuiltinVariant(instruction, compiler); | 515 return newBuiltinVariant(instruction, compiler, closedWorld); |
506 } | 516 } |
507 // Even if there is no builtin equivalent instruction, we know | 517 // Even if there is no builtin equivalent instruction, we know |
508 // the instruction does not have any side effect, and that it | 518 // the instruction does not have any side effect, and that it |
509 // can be GVN'ed. | 519 // can be GVN'ed. |
510 clearAllSideEffects(instruction); | 520 clearAllSideEffects(instruction); |
511 if (isPositive(right, compiler) && isPositive(left, compiler)) { | 521 if (isPositive(right, closedWorld) && isPositive(left, closedWorld)) { |
512 instruction.selector = renameToOptimizedSelector( | 522 instruction.selector = renameToOptimizedSelector( |
513 '_shrBothPositive', instruction.selector, compiler); | 523 '_shrBothPositive', instruction.selector, compiler); |
514 } else if (isPositive(left, compiler) && right.isNumber(compiler)) { | 524 } else if (isPositive(left, closedWorld) && right.isNumber(closedWorld)) { |
515 instruction.selector = renameToOptimizedSelector( | 525 instruction.selector = renameToOptimizedSelector( |
516 '_shrReceiverPositive', instruction.selector, compiler); | 526 '_shrReceiverPositive', instruction.selector, compiler); |
517 } else if (isPositive(right, compiler)) { | 527 } else if (isPositive(right, closedWorld)) { |
518 instruction.selector = renameToOptimizedSelector( | 528 instruction.selector = renameToOptimizedSelector( |
519 '_shrOtherPositive', instruction.selector, compiler); | 529 '_shrOtherPositive', instruction.selector, compiler); |
520 } | 530 } |
521 } | 531 } |
522 return null; | 532 return null; |
523 } | 533 } |
524 | 534 |
525 HInstruction newBuiltinVariant( | 535 HInstruction newBuiltinVariant( |
526 HInvokeDynamic instruction, Compiler compiler) { | 536 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
527 return new HShiftRight(instruction.inputs[1], instruction.inputs[2], | 537 return new HShiftRight( |
528 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 538 instruction.inputs[1], |
| 539 instruction.inputs[2], |
| 540 instruction.selector, |
| 541 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
529 } | 542 } |
530 | 543 |
531 BinaryOperation operation(ConstantSystem constantSystem) { | 544 BinaryOperation operation(ConstantSystem constantSystem) { |
532 return constantSystem.shiftRight; | 545 return constantSystem.shiftRight; |
533 } | 546 } |
534 } | 547 } |
535 | 548 |
536 class BitOrSpecializer extends BinaryBitOpSpecializer { | 549 class BitOrSpecializer extends BinaryBitOpSpecializer { |
537 const BitOrSpecializer(); | 550 const BitOrSpecializer(); |
538 | 551 |
539 BinaryOperation operation(ConstantSystem constantSystem) { | 552 BinaryOperation operation(ConstantSystem constantSystem) { |
540 return constantSystem.bitOr; | 553 return constantSystem.bitOr; |
541 } | 554 } |
542 | 555 |
543 TypeMask computeTypeFromInputTypes( | 556 TypeMask computeTypeFromInputTypes( |
544 HInvokeDynamic instruction, Compiler compiler) { | 557 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
545 HInstruction left = instruction.inputs[1]; | 558 HInstruction left = instruction.inputs[1]; |
546 HInstruction right = instruction.inputs[2]; | 559 HInstruction right = instruction.inputs[2]; |
547 JavaScriptBackend backend = compiler.backend; | 560 if (left.isUInt31(closedWorld) && right.isUInt31(closedWorld)) { |
548 if (left.isUInt31(compiler) && right.isUInt31(compiler)) { | 561 return closedWorld.commonMasks.uint31Type; |
549 return backend.uint31Type; | |
550 } | 562 } |
551 return super.computeTypeFromInputTypes(instruction, compiler); | 563 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
552 } | 564 } |
553 | 565 |
554 HInstruction newBuiltinVariant( | 566 HInstruction newBuiltinVariant( |
555 HInvokeDynamic instruction, Compiler compiler) { | 567 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
556 return new HBitOr(instruction.inputs[1], instruction.inputs[2], | 568 return new HBitOr( |
557 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 569 instruction.inputs[1], |
| 570 instruction.inputs[2], |
| 571 instruction.selector, |
| 572 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
558 } | 573 } |
559 } | 574 } |
560 | 575 |
561 class BitAndSpecializer extends BinaryBitOpSpecializer { | 576 class BitAndSpecializer extends BinaryBitOpSpecializer { |
562 const BitAndSpecializer(); | 577 const BitAndSpecializer(); |
563 | 578 |
564 BinaryOperation operation(ConstantSystem constantSystem) { | 579 BinaryOperation operation(ConstantSystem constantSystem) { |
565 return constantSystem.bitAnd; | 580 return constantSystem.bitAnd; |
566 } | 581 } |
567 | 582 |
568 TypeMask computeTypeFromInputTypes( | 583 TypeMask computeTypeFromInputTypes( |
569 HInvokeDynamic instruction, Compiler compiler) { | 584 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
570 HInstruction left = instruction.inputs[1]; | 585 HInstruction left = instruction.inputs[1]; |
571 HInstruction right = instruction.inputs[2]; | 586 HInstruction right = instruction.inputs[2]; |
572 JavaScriptBackend backend = compiler.backend; | 587 if (left.isPrimitiveOrNull(closedWorld) && |
573 if (left.isPrimitiveOrNull(compiler) && | 588 (left.isUInt31(closedWorld) || right.isUInt31(closedWorld))) { |
574 (left.isUInt31(compiler) || right.isUInt31(compiler))) { | 589 return closedWorld.commonMasks.uint31Type; |
575 return backend.uint31Type; | |
576 } | 590 } |
577 return super.computeTypeFromInputTypes(instruction, compiler); | 591 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
578 } | 592 } |
579 | 593 |
580 HInstruction newBuiltinVariant( | 594 HInstruction newBuiltinVariant( |
581 HInvokeDynamic instruction, Compiler compiler) { | 595 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
582 return new HBitAnd(instruction.inputs[1], instruction.inputs[2], | 596 return new HBitAnd( |
583 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 597 instruction.inputs[1], |
| 598 instruction.inputs[2], |
| 599 instruction.selector, |
| 600 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
584 } | 601 } |
585 } | 602 } |
586 | 603 |
587 class BitXorSpecializer extends BinaryBitOpSpecializer { | 604 class BitXorSpecializer extends BinaryBitOpSpecializer { |
588 const BitXorSpecializer(); | 605 const BitXorSpecializer(); |
589 | 606 |
590 BinaryOperation operation(ConstantSystem constantSystem) { | 607 BinaryOperation operation(ConstantSystem constantSystem) { |
591 return constantSystem.bitXor; | 608 return constantSystem.bitXor; |
592 } | 609 } |
593 | 610 |
594 TypeMask computeTypeFromInputTypes( | 611 TypeMask computeTypeFromInputTypes( |
595 HInvokeDynamic instruction, Compiler compiler) { | 612 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
596 HInstruction left = instruction.inputs[1]; | 613 HInstruction left = instruction.inputs[1]; |
597 HInstruction right = instruction.inputs[2]; | 614 HInstruction right = instruction.inputs[2]; |
598 JavaScriptBackend backend = compiler.backend; | 615 if (left.isUInt31(closedWorld) && right.isUInt31(closedWorld)) { |
599 if (left.isUInt31(compiler) && right.isUInt31(compiler)) { | 616 return closedWorld.commonMasks.uint31Type; |
600 return backend.uint31Type; | |
601 } | 617 } |
602 return super.computeTypeFromInputTypes(instruction, compiler); | 618 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
603 } | 619 } |
604 | 620 |
605 HInstruction newBuiltinVariant( | 621 HInstruction newBuiltinVariant( |
606 HInvokeDynamic instruction, Compiler compiler) { | 622 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
607 return new HBitXor(instruction.inputs[1], instruction.inputs[2], | 623 return new HBitXor( |
608 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 624 instruction.inputs[1], |
| 625 instruction.inputs[2], |
| 626 instruction.selector, |
| 627 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
609 } | 628 } |
610 } | 629 } |
611 | 630 |
612 abstract class RelationalSpecializer extends InvokeDynamicSpecializer { | 631 abstract class RelationalSpecializer extends InvokeDynamicSpecializer { |
613 const RelationalSpecializer(); | 632 const RelationalSpecializer(); |
614 | 633 |
615 TypeMask computeTypeFromInputTypes( | 634 TypeMask computeTypeFromInputTypes( |
616 HInvokeDynamic instruction, Compiler compiler) { | 635 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
617 JavaScriptBackend backend = compiler.backend; | 636 if (instruction.inputs[1].isPrimitiveOrNull(closedWorld)) { |
618 if (instruction.inputs[1].isPrimitiveOrNull(compiler)) { | 637 return closedWorld.commonMasks.boolType; |
619 return backend.boolType; | |
620 } | 638 } |
621 return super.computeTypeFromInputTypes(instruction, compiler); | 639 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
622 } | 640 } |
623 | 641 |
624 HInstruction tryConvertToBuiltin( | 642 HInstruction tryConvertToBuiltin( |
625 HInvokeDynamic instruction, Compiler compiler) { | 643 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
626 HInstruction left = instruction.inputs[1]; | 644 HInstruction left = instruction.inputs[1]; |
627 HInstruction right = instruction.inputs[2]; | 645 HInstruction right = instruction.inputs[2]; |
628 if (left.isNumber(compiler) && right.isNumber(compiler)) { | 646 if (left.isNumber(closedWorld) && right.isNumber(closedWorld)) { |
629 return newBuiltinVariant(instruction, compiler); | 647 return newBuiltinVariant(instruction, closedWorld); |
630 } | 648 } |
631 return null; | 649 return null; |
632 } | 650 } |
633 | 651 |
634 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); | 652 HInstruction newBuiltinVariant( |
| 653 HInvokeDynamic instruction, ClosedWorld closedWorld); |
635 } | 654 } |
636 | 655 |
637 class EqualsSpecializer extends RelationalSpecializer { | 656 class EqualsSpecializer extends RelationalSpecializer { |
638 const EqualsSpecializer(); | 657 const EqualsSpecializer(); |
639 | 658 |
640 HInstruction tryConvertToBuiltin( | 659 HInstruction tryConvertToBuiltin( |
641 HInvokeDynamic instruction, Compiler compiler) { | 660 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
642 HInstruction left = instruction.inputs[1]; | 661 HInstruction left = instruction.inputs[1]; |
643 HInstruction right = instruction.inputs[2]; | 662 HInstruction right = instruction.inputs[2]; |
644 TypeMask instructionType = left.instructionType; | 663 TypeMask instructionType = left.instructionType; |
645 if (right.isConstantNull() || left.isPrimitiveOrNull(compiler)) { | 664 if (right.isConstantNull() || left.isPrimitiveOrNull(closedWorld)) { |
646 return newBuiltinVariant(instruction, compiler); | 665 return newBuiltinVariant(instruction, closedWorld); |
647 } | 666 } |
648 ClosedWorld world = compiler.closedWorld; | |
649 JavaScriptBackend backend = compiler.backend; | |
650 Iterable<Element> matches = | 667 Iterable<Element> matches = |
651 world.allFunctions.filter(instruction.selector, instructionType); | 668 closedWorld.allFunctions.filter(instruction.selector, instructionType); |
652 // This test relies the on `Object.==` and `Interceptor.==` always being | 669 // This test relies the on `Object.==` and `Interceptor.==` always being |
653 // implemented because if the selector matches by subtype, it still will be | 670 // implemented because if the selector matches by subtype, it still will be |
654 // a regular object or an interceptor. | 671 // a regular object or an interceptor. |
655 if (matches.every(backend.isDefaultEqualityImplementation)) { | 672 if (matches |
656 return newBuiltinVariant(instruction, compiler); | 673 .every(closedWorld.backendClasses.isDefaultEqualityImplementation)) { |
| 674 return newBuiltinVariant(instruction, closedWorld); |
657 } | 675 } |
658 return null; | 676 return null; |
659 } | 677 } |
660 | 678 |
661 BinaryOperation operation(ConstantSystem constantSystem) { | 679 BinaryOperation operation(ConstantSystem constantSystem) { |
662 return constantSystem.equal; | 680 return constantSystem.equal; |
663 } | 681 } |
664 | 682 |
665 HInstruction newBuiltinVariant( | 683 HInstruction newBuiltinVariant( |
666 HInvokeDynamic instruction, Compiler compiler) { | 684 HInvokeDynamic instruction, ClosedWorld closedWorld) { |
667 JavaScriptBackend backend = compiler.backend; | |
668 return new HIdentity(instruction.inputs[1], instruction.inputs[2], | 685 return new HIdentity(instruction.inputs[1], instruction.inputs[2], |
669 instruction.selector, backend.boolType); | 686 instruction.selector, closedWorld.commonMasks.boolType); |
670 } | 687 } |
671 } | 688 } |
672 | 689 |
673 class LessSpecializer extends RelationalSpecializer { | 690 class LessSpecializer extends RelationalSpecializer { |
674 const LessSpecializer(); | 691 const LessSpecializer(); |
675 | 692 |
676 BinaryOperation operation(ConstantSystem constantSystem) { | 693 BinaryOperation operation(ConstantSystem constantSystem) { |
677 return constantSystem.less; | 694 return constantSystem.less; |
678 } | 695 } |
679 | 696 |
680 HInstruction newBuiltinVariant( | 697 HInstruction newBuiltinVariant( |
681 HInvokeDynamic instruction, Compiler compiler) { | 698 HInvokeDynamic instruction, ClosedWorld closedWorld) { |
682 JavaScriptBackend backend = compiler.backend; | |
683 return new HLess(instruction.inputs[1], instruction.inputs[2], | 699 return new HLess(instruction.inputs[1], instruction.inputs[2], |
684 instruction.selector, backend.boolType); | 700 instruction.selector, closedWorld.commonMasks.boolType); |
685 } | 701 } |
686 } | 702 } |
687 | 703 |
688 class GreaterSpecializer extends RelationalSpecializer { | 704 class GreaterSpecializer extends RelationalSpecializer { |
689 const GreaterSpecializer(); | 705 const GreaterSpecializer(); |
690 | 706 |
691 BinaryOperation operation(ConstantSystem constantSystem) { | 707 BinaryOperation operation(ConstantSystem constantSystem) { |
692 return constantSystem.greater; | 708 return constantSystem.greater; |
693 } | 709 } |
694 | 710 |
695 HInstruction newBuiltinVariant( | 711 HInstruction newBuiltinVariant( |
696 HInvokeDynamic instruction, Compiler compiler) { | 712 HInvokeDynamic instruction, ClosedWorld closedWorld) { |
697 JavaScriptBackend backend = compiler.backend; | |
698 return new HGreater(instruction.inputs[1], instruction.inputs[2], | 713 return new HGreater(instruction.inputs[1], instruction.inputs[2], |
699 instruction.selector, backend.boolType); | 714 instruction.selector, closedWorld.commonMasks.boolType); |
700 } | 715 } |
701 } | 716 } |
702 | 717 |
703 class GreaterEqualSpecializer extends RelationalSpecializer { | 718 class GreaterEqualSpecializer extends RelationalSpecializer { |
704 const GreaterEqualSpecializer(); | 719 const GreaterEqualSpecializer(); |
705 | 720 |
706 BinaryOperation operation(ConstantSystem constantSystem) { | 721 BinaryOperation operation(ConstantSystem constantSystem) { |
707 return constantSystem.greaterEqual; | 722 return constantSystem.greaterEqual; |
708 } | 723 } |
709 | 724 |
710 HInstruction newBuiltinVariant( | 725 HInstruction newBuiltinVariant( |
711 HInvokeDynamic instruction, Compiler compiler) { | 726 HInvokeDynamic instruction, ClosedWorld closedWorld) { |
712 JavaScriptBackend backend = compiler.backend; | |
713 return new HGreaterEqual(instruction.inputs[1], instruction.inputs[2], | 727 return new HGreaterEqual(instruction.inputs[1], instruction.inputs[2], |
714 instruction.selector, backend.boolType); | 728 instruction.selector, closedWorld.commonMasks.boolType); |
715 } | 729 } |
716 } | 730 } |
717 | 731 |
718 class LessEqualSpecializer extends RelationalSpecializer { | 732 class LessEqualSpecializer extends RelationalSpecializer { |
719 const LessEqualSpecializer(); | 733 const LessEqualSpecializer(); |
720 | 734 |
721 BinaryOperation operation(ConstantSystem constantSystem) { | 735 BinaryOperation operation(ConstantSystem constantSystem) { |
722 return constantSystem.lessEqual; | 736 return constantSystem.lessEqual; |
723 } | 737 } |
724 | 738 |
725 HInstruction newBuiltinVariant( | 739 HInstruction newBuiltinVariant( |
726 HInvokeDynamic instruction, Compiler compiler) { | 740 HInvokeDynamic instruction, ClosedWorld closedWorld) { |
727 JavaScriptBackend backend = compiler.backend; | |
728 return new HLessEqual(instruction.inputs[1], instruction.inputs[2], | 741 return new HLessEqual(instruction.inputs[1], instruction.inputs[2], |
729 instruction.selector, backend.boolType); | 742 instruction.selector, closedWorld.commonMasks.boolType); |
730 } | 743 } |
731 } | 744 } |
732 | 745 |
733 class CodeUnitAtSpecializer extends InvokeDynamicSpecializer { | 746 class CodeUnitAtSpecializer extends InvokeDynamicSpecializer { |
734 const CodeUnitAtSpecializer(); | 747 const CodeUnitAtSpecializer(); |
735 | 748 |
736 BinaryOperation operation(ConstantSystem constantSystem) { | 749 BinaryOperation operation(ConstantSystem constantSystem) { |
737 return constantSystem.codeUnitAt; | 750 return constantSystem.codeUnitAt; |
738 } | 751 } |
739 | 752 |
740 HInstruction tryConvertToBuiltin( | 753 HInstruction tryConvertToBuiltin( |
741 HInvokeDynamic instruction, Compiler compiler) { | 754 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
742 // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index | 755 // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index |
743 // bounds checking optimizations as for HIndex. | 756 // bounds checking optimizations as for HIndex. |
744 HInstruction receiver = instruction.getDartReceiver(compiler); | 757 HInstruction receiver = instruction.getDartReceiver(compiler); |
745 if (receiver.isStringOrNull(compiler)) { | 758 if (receiver.isStringOrNull(closedWorld)) { |
746 // Even if there is no builtin equivalent instruction, we know | 759 // Even if there is no builtin equivalent instruction, we know |
747 // String.codeUnitAt does not have any side effect (other than throwing), | 760 // String.codeUnitAt does not have any side effect (other than throwing), |
748 // and that it can be GVN'ed. | 761 // and that it can be GVN'ed. |
749 clearAllSideEffects(instruction); | 762 clearAllSideEffects(instruction); |
750 } | 763 } |
751 return null; | 764 return null; |
752 } | 765 } |
753 } | 766 } |
754 | 767 |
755 class RoundSpecializer extends InvokeDynamicSpecializer { | 768 class RoundSpecializer extends InvokeDynamicSpecializer { |
756 const RoundSpecializer(); | 769 const RoundSpecializer(); |
757 | 770 |
758 UnaryOperation operation(ConstantSystem constantSystem) { | 771 UnaryOperation operation(ConstantSystem constantSystem) { |
759 return constantSystem.round; | 772 return constantSystem.round; |
760 } | 773 } |
761 | 774 |
762 HInstruction tryConvertToBuiltin( | 775 HInstruction tryConvertToBuiltin( |
763 HInvokeDynamic instruction, Compiler compiler) { | 776 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
764 HInstruction receiver = instruction.getDartReceiver(compiler); | 777 HInstruction receiver = instruction.getDartReceiver(compiler); |
765 if (receiver.isNumberOrNull(compiler)) { | 778 if (receiver.isNumberOrNull(closedWorld)) { |
766 // Even if there is no builtin equivalent instruction, we know the | 779 // Even if there is no builtin equivalent instruction, we know the |
767 // instruction does not have any side effect, and that it can be GVN'ed. | 780 // instruction does not have any side effect, and that it can be GVN'ed. |
768 clearAllSideEffects(instruction); | 781 clearAllSideEffects(instruction); |
769 } | 782 } |
770 return null; | 783 return null; |
771 } | 784 } |
772 } | 785 } |
OLD | NEW |