| 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 void clearAllSideEffects(HInstruction instruction) { |
| 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 // TODO: We should use the value range analysis. Currently, ranges |
| 349 // are discarded just after the analysis. |
| 350 return instruction is HBinaryBitOp; |
| 351 } |
| 334 } | 352 } |
| 335 | 353 |
| 336 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { | 354 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { |
| 337 const ShiftLeftSpecializer(); | 355 const ShiftLeftSpecializer(); |
| 338 | 356 |
| 339 BinaryOperation operation(ConstantSystem constantSystem) { | 357 BinaryOperation operation(ConstantSystem constantSystem) { |
| 340 return constantSystem.shiftLeft; | 358 return constantSystem.shiftLeft; |
| 341 } | 359 } |
| 342 | 360 |
| 343 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 361 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 344 Compiler compiler) { | 362 Compiler compiler) { |
| 345 HInstruction left = instruction.inputs[1]; | 363 HInstruction left = instruction.inputs[1]; |
| 346 HInstruction right = instruction.inputs[2]; | 364 HInstruction right = instruction.inputs[2]; |
| 347 if (!left.isNumber(compiler)) return null; | 365 if (left.isNumber(compiler)) { |
| 348 if (argumentLessThan32(right)) { | 366 if (argumentLessThan32(right)) { |
| 349 return newBuiltinVariant(instruction, compiler); | 367 return newBuiltinVariant(instruction, compiler); |
| 368 } |
| 369 // Even if there is no builtin equivalent instruction, we know |
| 370 // the instruction does not have any side effect, and that it |
| 371 // can be GVN'ed. |
| 372 clearAllSideEffects(instruction); |
| 350 } | 373 } |
| 351 return null; | 374 return null; |
| 352 } | 375 } |
| 353 | 376 |
| 354 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 377 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
| 355 Compiler compiler) { | 378 Compiler compiler) { |
| 356 JavaScriptBackend backend = compiler.backend; | 379 JavaScriptBackend backend = compiler.backend; |
| 357 return new HShiftLeft( | 380 return new HShiftLeft( |
| 358 instruction.inputs[1], instruction.inputs[2], | 381 instruction.inputs[1], instruction.inputs[2], |
| 359 instruction.selector, backend.intType); | 382 instruction.selector, backend.intType); |
| 360 } | 383 } |
| 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 } | 384 } |
| 370 | 385 |
| 371 class ShiftRightSpecializer extends BinaryBitOpSpecializer { | 386 class ShiftRightSpecializer extends BinaryBitOpSpecializer { |
| 372 const ShiftRightSpecializer(); | 387 const ShiftRightSpecializer(); |
| 373 | 388 |
| 374 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 389 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 375 Compiler compiler) { | 390 Compiler compiler) { |
| 376 // Shift right cannot be mapped to the native operator easily. | 391 HInstruction left = instruction.inputs[1]; |
| 392 HInstruction right = instruction.inputs[2]; |
| 393 if (left.isNumber(compiler)) { |
| 394 if (argumentLessThan32(right) && isPositive(left)) { |
| 395 return newBuiltinVariant(instruction, compiler); |
| 396 } |
| 397 // Even if there is no builtin equivalent instruction, we know |
| 398 // the instruction does not have any side effect, and that it |
| 399 // can be GVN'ed. |
| 400 clearAllSideEffects(instruction); |
| 401 } |
| 377 return null; | 402 return null; |
| 378 } | 403 } |
| 379 | 404 |
| 405 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
| 406 Compiler compiler) { |
| 407 JavaScriptBackend backend = compiler.backend; |
| 408 return new HShiftRight( |
| 409 instruction.inputs[1], instruction.inputs[2], |
| 410 instruction.selector, backend.intType); |
| 411 } |
| 412 |
| 380 BinaryOperation operation(ConstantSystem constantSystem) { | 413 BinaryOperation operation(ConstantSystem constantSystem) { |
| 381 return constantSystem.shiftRight; | 414 return constantSystem.shiftRight; |
| 382 } | 415 } |
| 383 } | 416 } |
| 384 | 417 |
| 385 class BitOrSpecializer extends BinaryBitOpSpecializer { | 418 class BitOrSpecializer extends BinaryBitOpSpecializer { |
| 386 const BitOrSpecializer(); | 419 const BitOrSpecializer(); |
| 387 | 420 |
| 388 BinaryOperation operation(ConstantSystem constantSystem) { | 421 BinaryOperation operation(ConstantSystem constantSystem) { |
| 389 return constantSystem.bitOr; | 422 return constantSystem.bitOr; |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 } | 582 } |
| 550 | 583 |
| 551 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 584 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
| 552 Compiler compiler) { | 585 Compiler compiler) { |
| 553 JavaScriptBackend backend = compiler.backend; | 586 JavaScriptBackend backend = compiler.backend; |
| 554 return new HLessEqual( | 587 return new HLessEqual( |
| 555 instruction.inputs[1], instruction.inputs[2], | 588 instruction.inputs[1], instruction.inputs[2], |
| 556 instruction.selector, backend.boolType); | 589 instruction.selector, backend.boolType); |
| 557 } | 590 } |
| 558 } | 591 } |
| OLD | NEW |