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 part of ssa; | 5 part of ssa; |
6 | 6 |
7 /** | 7 /** |
8 * [InvokeDynamicSpecializer] and its subclasses are helpers to | 8 * [InvokeDynamicSpecializer] and its subclasses are helpers to |
9 * optimize intercepted dynamic calls. It knows what input types | 9 * optimize intercepted dynamic calls. It knows what input types |
10 * would be beneficial for performance, and how to change a invoke | 10 * would be beneficial for performance, and how to change a invoke |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 | 216 |
217 void clearAllSideEffects(HInstruction instruction) { | 217 void clearAllSideEffects(HInstruction instruction) { |
218 instruction.sideEffects.clearAllSideEffects(); | 218 instruction.sideEffects.clearAllSideEffects(); |
219 instruction.sideEffects.clearAllDependencies(); | 219 instruction.sideEffects.clearAllDependencies(); |
220 instruction.setUseGvn(); | 220 instruction.setUseGvn(); |
221 } | 221 } |
222 | 222 |
223 bool inputsArePositiveIntegers(HInstruction instruction, Compiler compiler) { | 223 bool inputsArePositiveIntegers(HInstruction instruction, Compiler compiler) { |
224 HInstruction left = instruction.inputs[1]; | 224 HInstruction left = instruction.inputs[1]; |
225 HInstruction right = instruction.inputs[2]; | 225 HInstruction right = instruction.inputs[2]; |
226 JavaScriptBackend backend = compiler.backend; | |
227 return left.isPositiveIntegerOrNull(compiler) | 226 return left.isPositiveIntegerOrNull(compiler) |
228 && right.isPositiveIntegerOrNull(compiler); | 227 && right.isPositiveIntegerOrNull(compiler); |
229 } | 228 } |
230 | 229 |
| 230 bool inputsAreUInt31(HInstruction instruction, Compiler compiler) { |
| 231 HInstruction left = instruction.inputs[1]; |
| 232 HInstruction right = instruction.inputs[2]; |
| 233 return left.isUInt31(compiler) && right.isUInt31(compiler); |
| 234 } |
| 235 |
231 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); | 236 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); |
232 | 237 |
233 Selector renameToOptimizedSelector(String name, | 238 Selector renameToOptimizedSelector(String name, |
234 Selector selector, | 239 Selector selector, |
235 Compiler compiler) { | 240 Compiler compiler) { |
236 if (selector.name == name) return selector; | 241 if (selector.name == name) return selector; |
237 JavaScriptBackend backend = compiler.backend; | 242 JavaScriptBackend backend = compiler.backend; |
238 Selector newSelector = new Selector( | 243 Selector newSelector = new Selector( |
239 SelectorKind.CALL, new Name(name, backend.interceptorsLibrary), | 244 SelectorKind.CALL, new Name(name, backend.interceptorsLibrary), |
240 new CallStructure(selector.argumentCount)); | 245 new CallStructure(selector.argumentCount)); |
241 return selector.mask == null | 246 return selector.mask == null |
242 ? newSelector | 247 ? newSelector |
243 : new TypedSelector(selector.mask, newSelector, compiler.world); | 248 : new TypedSelector(selector.mask, newSelector, compiler.world); |
244 } | 249 } |
245 } | 250 } |
246 | 251 |
247 class AddSpecializer extends BinaryArithmeticSpecializer { | 252 class AddSpecializer extends BinaryArithmeticSpecializer { |
248 const AddSpecializer(); | 253 const AddSpecializer(); |
249 | 254 |
250 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, | 255 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, |
251 Compiler compiler) { | 256 Compiler compiler) { |
| 257 if (inputsAreUInt31(instruction, compiler)) { |
| 258 JavaScriptBackend backend = compiler.backend; |
| 259 return backend.uint32Type; |
| 260 } |
252 if (inputsArePositiveIntegers(instruction, compiler)) { | 261 if (inputsArePositiveIntegers(instruction, compiler)) { |
253 JavaScriptBackend backend = compiler.backend; | 262 JavaScriptBackend backend = compiler.backend; |
254 return backend.positiveIntType; | 263 return backend.positiveIntType; |
255 } | 264 } |
256 return super.computeTypeFromInputTypes(instruction, compiler); | 265 return super.computeTypeFromInputTypes(instruction, compiler); |
257 } | 266 } |
258 | 267 |
259 BinaryOperation operation(ConstantSystem constantSystem) { | 268 BinaryOperation operation(ConstantSystem constantSystem) { |
260 return constantSystem.add; | 269 return constantSystem.add; |
261 } | 270 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 return super.computeTypeFromInputTypes(instruction, compiler); | 315 return super.computeTypeFromInputTypes(instruction, compiler); |
307 } | 316 } |
308 | 317 |
309 BinaryOperation operation(ConstantSystem constantSystem) { | 318 BinaryOperation operation(ConstantSystem constantSystem) { |
310 return constantSystem.modulo; | 319 return constantSystem.modulo; |
311 } | 320 } |
312 | 321 |
313 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 322 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
314 Compiler compiler) { | 323 Compiler compiler) { |
315 // Modulo cannot be mapped to the native operator (different semantics). | 324 // Modulo cannot be mapped to the native operator (different semantics). |
| 325 // TODO(sra): For non-negative values we can use JavaScript's %. |
316 return null; | 326 return null; |
317 } | 327 } |
318 } | 328 } |
319 | 329 |
320 class MultiplySpecializer extends BinaryArithmeticSpecializer { | 330 class MultiplySpecializer extends BinaryArithmeticSpecializer { |
321 const MultiplySpecializer(); | 331 const MultiplySpecializer(); |
322 | 332 |
323 BinaryOperation operation(ConstantSystem constantSystem) { | 333 BinaryOperation operation(ConstantSystem constantSystem) { |
324 return constantSystem.multiply; | 334 return constantSystem.multiply; |
325 } | 335 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 | 368 |
359 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { | 369 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { |
360 const TruncatingDivideSpecializer(); | 370 const TruncatingDivideSpecializer(); |
361 | 371 |
362 BinaryOperation operation(ConstantSystem constantSystem) { | 372 BinaryOperation operation(ConstantSystem constantSystem) { |
363 return constantSystem.truncatingDivide; | 373 return constantSystem.truncatingDivide; |
364 } | 374 } |
365 | 375 |
366 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, | 376 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, |
367 Compiler compiler) { | 377 Compiler compiler) { |
| 378 JavaScriptBackend backend = compiler.backend; |
| 379 if (hasUint31Result(instruction, compiler)) { |
| 380 return backend.uint31Type; |
| 381 } |
368 if (inputsArePositiveIntegers(instruction, compiler)) { | 382 if (inputsArePositiveIntegers(instruction, compiler)) { |
369 JavaScriptBackend backend = compiler.backend; | |
370 return backend.positiveIntType; | 383 return backend.positiveIntType; |
371 } | 384 } |
372 return super.computeTypeFromInputTypes(instruction, compiler); | 385 return super.computeTypeFromInputTypes(instruction, compiler); |
373 } | 386 } |
374 | 387 |
375 bool isNotZero(HInstruction instruction, Compiler compiler) { | 388 bool isNotZero(HInstruction instruction, Compiler compiler) { |
376 if (!instruction.isConstantInteger()) return false; | 389 if (!instruction.isConstantInteger()) return false; |
377 HConstant rightConstant = instruction; | 390 HConstant rightConstant = instruction; |
378 IntConstantValue intConstant = rightConstant.constant; | 391 IntConstantValue intConstant = rightConstant.constant; |
379 int count = intConstant.primitiveValue; | 392 int count = intConstant.primitiveValue; |
380 return count != 0; | 393 return count != 0; |
381 } | 394 } |
382 | 395 |
| 396 bool isTwoOrGreater(HInstruction instruction, Compiler compiler) { |
| 397 if (!instruction.isConstantInteger()) return false; |
| 398 HConstant rightConstant = instruction; |
| 399 IntConstantValue intConstant = rightConstant.constant; |
| 400 int count = intConstant.primitiveValue; |
| 401 return count >= 2; |
| 402 } |
| 403 |
| 404 bool hasUint31Result(HInstruction instruction, Compiler compiler) { |
| 405 HInstruction left = instruction.inputs[1]; |
| 406 HInstruction right = instruction.inputs[2]; |
| 407 if (right.isPositiveInteger(compiler)) { |
| 408 if (left.isUInt31(compiler) && isNotZero(right, compiler)) { |
| 409 return true; |
| 410 } |
| 411 if (left.isUInt32(compiler) && isTwoOrGreater(right, compiler)) { |
| 412 return true; |
| 413 } |
| 414 } |
| 415 return false; |
| 416 } |
| 417 |
383 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 418 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
384 Compiler compiler) { | 419 Compiler compiler) { |
385 HInstruction left = instruction.inputs[1]; | 420 HInstruction left = instruction.inputs[1]; |
386 HInstruction right = instruction.inputs[2]; | 421 HInstruction right = instruction.inputs[2]; |
387 if (isBuiltin(instruction, compiler)) { | 422 if (isBuiltin(instruction, compiler)) { |
388 if (right.isPositiveInteger(compiler) && isNotZero(right, compiler)) { | 423 if (right.isPositiveInteger(compiler) && isNotZero(right, compiler)) { |
389 if (left.isUInt31(compiler)) { | 424 if (hasUint31Result(instruction, compiler)) { |
390 return newBuiltinVariant(instruction, compiler); | 425 return newBuiltinVariant(instruction, compiler); |
391 } | 426 } |
392 // We can call _tdivFast because the rhs is a 32bit integer | 427 // We can call _tdivFast because the rhs is a 32bit integer |
393 // and not 0, nor -1. | 428 // and not 0, nor -1. |
394 instruction.selector = renameToOptimizedSelector( | 429 instruction.selector = renameToOptimizedSelector( |
395 '_tdivFast', instruction.selector, compiler); | 430 '_tdivFast', instruction.selector, compiler); |
396 } | 431 } |
397 clearAllSideEffects(instruction); | 432 clearAllSideEffects(instruction); |
398 } | 433 } |
399 return null; | 434 return null; |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 return constantSystem.codeUnitAt; | 776 return constantSystem.codeUnitAt; |
742 } | 777 } |
743 | 778 |
744 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 779 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
745 Compiler compiler) { | 780 Compiler compiler) { |
746 // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index | 781 // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index |
747 // bounds checking optimizations as for HIndex. | 782 // bounds checking optimizations as for HIndex. |
748 return null; | 783 return null; |
749 } | 784 } |
750 } | 785 } |
OLD | NEW |