| 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 |