Chromium Code Reviews| 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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 } | 201 } |
| 202 | 202 |
| 203 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 203 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 204 Compiler compiler) { | 204 Compiler compiler) { |
| 205 if (isBuiltin(instruction, compiler)) { | 205 if (isBuiltin(instruction, compiler)) { |
| 206 HInstruction builtin = newBuiltinVariant(instruction, compiler); | 206 HInstruction builtin = newBuiltinVariant(instruction, compiler); |
| 207 if (builtin != null) return builtin; | 207 if (builtin != null) return builtin; |
| 208 // Even if there is no builtin equivalent instruction, we know | 208 // Even if there is no builtin equivalent instruction, we know |
| 209 // the instruction does not have any side effect, and that it | 209 // the instruction does not have any side effect, and that it |
| 210 // can be GVN'ed. | 210 // can be GVN'ed. |
| 211 instruction.sideEffects.clearAllSideEffects(); | 211 clearAllSideEffects(instruction); |
| 212 instruction.sideEffects.clearAllDependencies(); | |
| 213 instruction.setUseGvn(); | |
| 214 } | 212 } |
| 215 return null; | 213 return null; |
| 216 } | 214 } |
| 215 | |
| 216 bool clearAllSideEffects(HInstruction instruction) { | |
|
kasperl
2013/11/26 08:29:29
bool -> void
ngeoffray
2013/11/26 08:36:35
Done.
| |
| 217 instruction.sideEffects.clearAllSideEffects(); | |
| 218 instruction.sideEffects.clearAllDependencies(); | |
| 219 instruction.setUseGvn(); | |
| 220 } | |
| 217 | 221 |
| 218 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); | 222 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); |
| 219 } | 223 } |
| 220 | 224 |
| 221 class AddSpecializer extends BinaryArithmeticSpecializer { | 225 class AddSpecializer extends BinaryArithmeticSpecializer { |
| 222 const AddSpecializer(); | 226 const AddSpecializer(); |
| 223 | 227 |
| 224 BinaryOperation operation(ConstantSystem constantSystem) { | 228 BinaryOperation operation(ConstantSystem constantSystem) { |
| 225 return constantSystem.add; | 229 return constantSystem.add; |
| 226 } | 230 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 Compiler compiler) { | 328 Compiler compiler) { |
| 325 // All bitwise operations on primitive types either produce an | 329 // All bitwise operations on primitive types either produce an |
| 326 // integer or throw an error. | 330 // integer or throw an error. |
| 327 HInstruction left = instruction.inputs[1]; | 331 HInstruction left = instruction.inputs[1]; |
| 328 JavaScriptBackend backend = compiler.backend; | 332 JavaScriptBackend backend = compiler.backend; |
| 329 if (left.isPrimitiveOrNull(compiler)) { | 333 if (left.isPrimitiveOrNull(compiler)) { |
| 330 return backend.intType; | 334 return backend.intType; |
| 331 } | 335 } |
| 332 return super.computeTypeFromInputTypes(instruction, compiler); | 336 return super.computeTypeFromInputTypes(instruction, compiler); |
| 333 } | 337 } |
| 338 | |
| 339 bool argumentLessThan32(HInstruction instruction) { | |
| 340 if (!instruction.isConstantInteger()) return false; | |
| 341 HConstant rightConstant = instruction; | |
| 342 IntConstant intConstant = rightConstant.constant; | |
| 343 int count = intConstant.value; | |
| 344 return count >= 0 && count <= 31; | |
| 345 } | |
| 346 | |
| 347 bool isPositive(HInstruction instruction) { | |
| 348 return instruction is HBinaryBitOp; | |
|
kasperl
2013/11/26 08:29:29
No way of using value range information here? Add
ngeoffray
2013/11/26 08:36:35
I have added a TODO for the range analysis. I have
| |
| 349 } | |
| 334 } | 350 } |
| 335 | 351 |
| 336 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { | 352 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { |
| 337 const ShiftLeftSpecializer(); | 353 const ShiftLeftSpecializer(); |
| 338 | 354 |
| 339 BinaryOperation operation(ConstantSystem constantSystem) { | 355 BinaryOperation operation(ConstantSystem constantSystem) { |
| 340 return constantSystem.shiftLeft; | 356 return constantSystem.shiftLeft; |
| 341 } | 357 } |
| 342 | 358 |
| 343 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 359 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 344 Compiler compiler) { | 360 Compiler compiler) { |
| 345 HInstruction left = instruction.inputs[1]; | 361 HInstruction left = instruction.inputs[1]; |
| 346 HInstruction right = instruction.inputs[2]; | 362 HInstruction right = instruction.inputs[2]; |
| 347 if (!left.isNumber(compiler)) return null; | 363 if (left.isNumber(compiler)) { |
| 348 if (argumentLessThan32(right)) { | 364 if (argumentLessThan32(right)) { |
| 349 return newBuiltinVariant(instruction, compiler); | 365 return newBuiltinVariant(instruction, compiler); |
| 366 } | |
| 367 // Even if there is no builtin equivalent instruction, we know | |
| 368 // the instruction does not have any side effect, and that it | |
| 369 // can be GVN'ed. | |
| 370 clearAllSideEffects(instruction); | |
| 350 } | 371 } |
| 351 return null; | 372 return null; |
| 352 } | 373 } |
| 353 | 374 |
| 354 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 375 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
| 355 Compiler compiler) { | 376 Compiler compiler) { |
| 356 JavaScriptBackend backend = compiler.backend; | 377 JavaScriptBackend backend = compiler.backend; |
| 357 return new HShiftLeft( | 378 return new HShiftLeft( |
| 358 instruction.inputs[1], instruction.inputs[2], | 379 instruction.inputs[1], instruction.inputs[2], |
| 359 instruction.selector, backend.intType); | 380 instruction.selector, backend.intType); |
| 360 } | 381 } |
| 361 | |
| 362 bool argumentLessThan32(HInstruction instruction) { | |
| 363 if (!instruction.isConstantInteger()) return false; | |
| 364 HConstant rightConstant = instruction; | |
| 365 IntConstant intConstant = rightConstant.constant; | |
| 366 int count = intConstant.value; | |
| 367 return count >= 0 && count <= 31; | |
| 368 } | |
| 369 } | 382 } |
| 370 | 383 |
| 371 class ShiftRightSpecializer extends BinaryBitOpSpecializer { | 384 class ShiftRightSpecializer extends BinaryBitOpSpecializer { |
| 372 const ShiftRightSpecializer(); | 385 const ShiftRightSpecializer(); |
| 373 | 386 |
| 374 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 387 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 375 Compiler compiler) { | 388 Compiler compiler) { |
| 376 // Shift right cannot be mapped to the native operator easily. | 389 HInstruction left = instruction.inputs[1]; |
| 390 HInstruction right = instruction.inputs[2]; | |
| 391 if (left.isNumber(compiler)) { | |
| 392 if (argumentLessThan32(right) && isPositive(left)) { | |
| 393 return newBuiltinVariant(instruction, compiler); | |
| 394 } | |
| 395 // Even if there is no builtin equivalent instruction, we know | |
| 396 // the instruction does not have any side effect, and that it | |
| 397 // can be GVN'ed. | |
| 398 clearAllSideEffects(instruction); | |
| 399 } | |
| 377 return null; | 400 return null; |
| 378 } | 401 } |
| 379 | 402 |
| 403 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | |
| 404 Compiler compiler) { | |
| 405 JavaScriptBackend backend = compiler.backend; | |
| 406 return new HShiftRight( | |
| 407 instruction.inputs[1], instruction.inputs[2], | |
| 408 instruction.selector, backend.intType); | |
| 409 } | |
| 410 | |
| 380 BinaryOperation operation(ConstantSystem constantSystem) { | 411 BinaryOperation operation(ConstantSystem constantSystem) { |
| 381 return constantSystem.shiftRight; | 412 return constantSystem.shiftRight; |
| 382 } | 413 } |
| 383 } | 414 } |
| 384 | 415 |
| 385 class BitOrSpecializer extends BinaryBitOpSpecializer { | 416 class BitOrSpecializer extends BinaryBitOpSpecializer { |
| 386 const BitOrSpecializer(); | 417 const BitOrSpecializer(); |
| 387 | 418 |
| 388 BinaryOperation operation(ConstantSystem constantSystem) { | 419 BinaryOperation operation(ConstantSystem constantSystem) { |
| 389 return constantSystem.bitOr; | 420 return constantSystem.bitOr; |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 549 } | 580 } |
| 550 | 581 |
| 551 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 582 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
| 552 Compiler compiler) { | 583 Compiler compiler) { |
| 553 JavaScriptBackend backend = compiler.backend; | 584 JavaScriptBackend backend = compiler.backend; |
| 554 return new HLessEqual( | 585 return new HLessEqual( |
| 555 instruction.inputs[1], instruction.inputs[2], | 586 instruction.inputs[1], instruction.inputs[2], |
| 556 instruction.selector, backend.boolType); | 587 instruction.selector, backend.boolType); |
| 557 } | 588 } |
| 558 } | 589 } |
| OLD | NEW |