| 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 22 matching lines...) Expand all Loading... |
| 33 compiler.world.getSideEffectsOfSelector(refined); | 33 compiler.world.getSideEffectsOfSelector(refined); |
| 34 } | 34 } |
| 35 return type; | 35 return type; |
| 36 } | 36 } |
| 37 | 37 |
| 38 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 38 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 39 Compiler compiler) { | 39 Compiler compiler) { |
| 40 return null; | 40 return null; |
| 41 } | 41 } |
| 42 | 42 |
| 43 bool hasBuiltinVariant(HInvokeDynamic instruction, Compiler compiler) { |
| 44 return false; |
| 45 } |
| 46 |
| 43 Operation operation(ConstantSystem constantSystem) => null; | 47 Operation operation(ConstantSystem constantSystem) => null; |
| 44 | 48 |
| 45 static InvokeDynamicSpecializer lookupSpecializer(Selector selector) { | 49 static InvokeDynamicSpecializer lookupSpecializer(Selector selector) { |
| 46 if (selector.kind == SelectorKind.INDEX) { | 50 if (selector.kind == SelectorKind.INDEX) { |
| 47 return selector.name == const SourceString('[]') | 51 return selector.name == const SourceString('[]') |
| 48 ? const IndexSpecializer() | 52 ? const IndexSpecializer() |
| 49 : const IndexAssignSpecializer(); | 53 : const IndexAssignSpecializer(); |
| 50 } else if (selector.kind == SelectorKind.OPERATOR) { | 54 } else if (selector.kind == SelectorKind.OPERATOR) { |
| 51 if (selector.name == const SourceString('unary-')) { | 55 if (selector.name == const SourceString('unary-')) { |
| 52 return const UnaryNegateSpecializer(); | 56 return const UnaryNegateSpecializer(); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 // We want the right checked mode error. | 120 // We want the right checked mode error. |
| 117 return null; | 121 return null; |
| 118 } | 122 } |
| 119 return new HIndexAssign(instruction.inputs[1], | 123 return new HIndexAssign(instruction.inputs[1], |
| 120 instruction.inputs[2], | 124 instruction.inputs[2], |
| 121 instruction.inputs[3], | 125 instruction.inputs[3], |
| 122 instruction.selector); | 126 instruction.selector); |
| 123 } | 127 } |
| 124 return null; | 128 return null; |
| 125 } | 129 } |
| 130 |
| 131 bool hasBuiltinVariant(HInvokeDynamic instruction, Compiler compiler) { |
| 132 return true; |
| 133 } |
| 126 } | 134 } |
| 127 | 135 |
| 128 class IndexSpecializer extends InvokeDynamicSpecializer { | 136 class IndexSpecializer extends InvokeDynamicSpecializer { |
| 129 const IndexSpecializer(); | 137 const IndexSpecializer(); |
| 130 | 138 |
| 131 HType computeDesiredTypeForInput(HInvokeDynamic instruction, | 139 HType computeDesiredTypeForInput(HInvokeDynamic instruction, |
| 132 HInstruction input, | 140 HInstruction input, |
| 133 Compiler compiler) { | 141 Compiler compiler) { |
| 134 HInstruction index = instruction.inputs[2]; | 142 HInstruction index = instruction.inputs[2]; |
| 135 if (input == instruction.inputs[1] && | 143 if (input == instruction.inputs[1] && |
| (...skipping 16 matching lines...) Expand all Loading... |
| 152 return null; | 160 return null; |
| 153 } | 161 } |
| 154 HInstruction index = new HIndex( | 162 HInstruction index = new HIndex( |
| 155 instruction.inputs[1], instruction.inputs[2], instruction.selector); | 163 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 156 index.instructionType = | 164 index.instructionType = |
| 157 new HType.inferredTypeForSelector(instruction.selector, compiler); | 165 new HType.inferredTypeForSelector(instruction.selector, compiler); |
| 158 return index; | 166 return index; |
| 159 } | 167 } |
| 160 return null; | 168 return null; |
| 161 } | 169 } |
| 170 |
| 171 bool hasBuiltinVariant(HInvokeDynamic instruction, Compiler compiler) { |
| 172 return true; |
| 173 } |
| 162 } | 174 } |
| 163 | 175 |
| 164 class BitNotSpecializer extends InvokeDynamicSpecializer { | 176 class BitNotSpecializer extends InvokeDynamicSpecializer { |
| 165 const BitNotSpecializer(); | 177 const BitNotSpecializer(); |
| 166 | 178 |
| 167 UnaryOperation operation(ConstantSystem constantSystem) { | 179 UnaryOperation operation(ConstantSystem constantSystem) { |
| 168 return constantSystem.bitNot; | 180 return constantSystem.bitNot; |
| 169 } | 181 } |
| 170 | 182 |
| 171 HType computeDesiredTypeForInput(HInvokeDynamic instruction, | 183 HType computeDesiredTypeForInput(HInvokeDynamic instruction, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 187 if (instruction.inputs[1].isPrimitiveOrNull(compiler)) return HType.INTEGER; | 199 if (instruction.inputs[1].isPrimitiveOrNull(compiler)) return HType.INTEGER; |
| 188 return super.computeTypeFromInputTypes(instruction, compiler); | 200 return super.computeTypeFromInputTypes(instruction, compiler); |
| 189 } | 201 } |
| 190 | 202 |
| 191 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 203 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 192 Compiler compiler) { | 204 Compiler compiler) { |
| 193 HInstruction input = instruction.inputs[1]; | 205 HInstruction input = instruction.inputs[1]; |
| 194 if (input.isNumber()) return new HBitNot(input, instruction.selector); | 206 if (input.isNumber()) return new HBitNot(input, instruction.selector); |
| 195 return null; | 207 return null; |
| 196 } | 208 } |
| 209 |
| 210 bool hasBuiltinVariant(HInvokeDynamic instruction, Compiler compiler) { |
| 211 return true; |
| 212 } |
| 197 } | 213 } |
| 198 | 214 |
| 199 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { | 215 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { |
| 200 const UnaryNegateSpecializer(); | 216 const UnaryNegateSpecializer(); |
| 201 | 217 |
| 202 UnaryOperation operation(ConstantSystem constantSystem) { | 218 UnaryOperation operation(ConstantSystem constantSystem) { |
| 203 return constantSystem.negate; | 219 return constantSystem.negate; |
| 204 } | 220 } |
| 205 | 221 |
| 206 HType computeDesiredTypeForInput(HInvokeDynamic instruction, | 222 HType computeDesiredTypeForInput(HInvokeDynamic instruction, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 223 if (operandType.isNumberOrNull()) return operandType; | 239 if (operandType.isNumberOrNull()) return operandType; |
| 224 return super.computeTypeFromInputTypes(instruction, compiler); | 240 return super.computeTypeFromInputTypes(instruction, compiler); |
| 225 } | 241 } |
| 226 | 242 |
| 227 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 243 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 228 Compiler compiler) { | 244 Compiler compiler) { |
| 229 HInstruction input = instruction.inputs[1]; | 245 HInstruction input = instruction.inputs[1]; |
| 230 if (input.isNumber()) return new HNegate(input, instruction.selector); | 246 if (input.isNumber()) return new HNegate(input, instruction.selector); |
| 231 return null; | 247 return null; |
| 232 } | 248 } |
| 249 |
| 250 bool hasBuiltinVariant(HInvokeDynamic instruction, Compiler compiler) { |
| 251 return true; |
| 252 } |
| 233 } | 253 } |
| 234 | 254 |
| 235 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { | 255 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { |
| 236 const BinaryArithmeticSpecializer(); | 256 const BinaryArithmeticSpecializer(); |
| 237 | 257 |
| 238 HType computeTypeFromInputTypes(HInvokeDynamic instruction, | 258 HType computeTypeFromInputTypes(HInvokeDynamic instruction, |
| 239 Compiler compiler) { | 259 Compiler compiler) { |
| 240 HInstruction left = instruction.inputs[1]; | 260 HInstruction left = instruction.inputs[1]; |
| 241 HInstruction right = instruction.inputs[2]; | 261 HInstruction right = instruction.inputs[2]; |
| 242 if (left.isIntegerOrNull() && right.isIntegerOrNull()) return HType.INTEGER; | 262 if (left.isIntegerOrNull() && right.isIntegerOrNull()) return HType.INTEGER; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 // Even if there is no builtin equivalent instruction, we know | 308 // Even if there is no builtin equivalent instruction, we know |
| 289 // the instruction does not have any side effect, and that it | 309 // the instruction does not have any side effect, and that it |
| 290 // can be GVN'ed. | 310 // can be GVN'ed. |
| 291 instruction.sideEffects.clearAllSideEffects(); | 311 instruction.sideEffects.clearAllSideEffects(); |
| 292 instruction.sideEffects.clearAllDependencies(); | 312 instruction.sideEffects.clearAllDependencies(); |
| 293 instruction.setUseGvn(); | 313 instruction.setUseGvn(); |
| 294 } | 314 } |
| 295 return null; | 315 return null; |
| 296 } | 316 } |
| 297 | 317 |
| 318 bool hasBuiltinVariant(HInvokeDynamic instruction, Compiler compiler) { |
| 319 return true; |
| 320 } |
| 321 |
| 298 HInstruction newBuiltinVariant(HInvokeDynamic instruction); | 322 HInstruction newBuiltinVariant(HInvokeDynamic instruction); |
| 299 } | 323 } |
| 300 | 324 |
| 301 class AddSpecializer extends BinaryArithmeticSpecializer { | 325 class AddSpecializer extends BinaryArithmeticSpecializer { |
| 302 const AddSpecializer(); | 326 const AddSpecializer(); |
| 303 | 327 |
| 304 BinaryOperation operation(ConstantSystem constantSystem) { | 328 BinaryOperation operation(ConstantSystem constantSystem) { |
| 305 return constantSystem.add; | 329 return constantSystem.add; |
| 306 } | 330 } |
| 307 | 331 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 const ModuloSpecializer(); | 369 const ModuloSpecializer(); |
| 346 | 370 |
| 347 BinaryOperation operation(ConstantSystem constantSystem) { | 371 BinaryOperation operation(ConstantSystem constantSystem) { |
| 348 return constantSystem.modulo; | 372 return constantSystem.modulo; |
| 349 } | 373 } |
| 350 | 374 |
| 351 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { | 375 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 352 // Modulo cannot be mapped to the native operator (different semantics). | 376 // Modulo cannot be mapped to the native operator (different semantics). |
| 353 return null; | 377 return null; |
| 354 } | 378 } |
| 379 |
| 380 bool hasBuiltinVariant(HInvokeDynamic instruction, Compiler compiler) { |
| 381 return false; |
| 382 } |
| 355 } | 383 } |
| 356 | 384 |
| 357 class MultiplySpecializer extends BinaryArithmeticSpecializer { | 385 class MultiplySpecializer extends BinaryArithmeticSpecializer { |
| 358 const MultiplySpecializer(); | 386 const MultiplySpecializer(); |
| 359 | 387 |
| 360 BinaryOperation operation(ConstantSystem constantSystem) { | 388 BinaryOperation operation(ConstantSystem constantSystem) { |
| 361 return constantSystem.multiply; | 389 return constantSystem.multiply; |
| 362 } | 390 } |
| 363 | 391 |
| 364 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { | 392 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 384 const TruncatingDivideSpecializer(); | 412 const TruncatingDivideSpecializer(); |
| 385 | 413 |
| 386 BinaryOperation operation(ConstantSystem constantSystem) { | 414 BinaryOperation operation(ConstantSystem constantSystem) { |
| 387 return constantSystem.truncatingDivide; | 415 return constantSystem.truncatingDivide; |
| 388 } | 416 } |
| 389 | 417 |
| 390 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { | 418 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 391 // Truncating divide does not have a JS equivalent. | 419 // Truncating divide does not have a JS equivalent. |
| 392 return null; | 420 return null; |
| 393 } | 421 } |
| 422 |
| 423 bool hasBuiltinVariant(HInvokeDynamic instruction, Compiler compiler) { |
| 424 return false; |
| 425 } |
| 394 } | 426 } |
| 395 | 427 |
| 396 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { | 428 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { |
| 397 const BinaryBitOpSpecializer(); | 429 const BinaryBitOpSpecializer(); |
| 398 | 430 |
| 399 HType computeTypeFromInputTypes(HInvokeDynamic instruction, | 431 HType computeTypeFromInputTypes(HInvokeDynamic instruction, |
| 400 Compiler compiler) { | 432 Compiler compiler) { |
| 401 // All bitwise operations on primitive types either produce an | 433 // All bitwise operations on primitive types either produce an |
| 402 // integer or throw an error. | 434 // integer or throw an error. |
| 403 HInstruction left = instruction.inputs[1]; | 435 HInstruction left = instruction.inputs[1]; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 424 const ShiftLeftSpecializer(); | 456 const ShiftLeftSpecializer(); |
| 425 | 457 |
| 426 BinaryOperation operation(ConstantSystem constantSystem) { | 458 BinaryOperation operation(ConstantSystem constantSystem) { |
| 427 return constantSystem.shiftLeft; | 459 return constantSystem.shiftLeft; |
| 428 } | 460 } |
| 429 | 461 |
| 430 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 462 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 431 Compiler compiler) { | 463 Compiler compiler) { |
| 432 HInstruction left = instruction.inputs[1]; | 464 HInstruction left = instruction.inputs[1]; |
| 433 HInstruction right = instruction.inputs[2]; | 465 HInstruction right = instruction.inputs[2]; |
| 434 if (!left.isNumber() || !right.isConstantInteger()) return null; | 466 if (!left.isNumber()) return null; |
| 435 HConstant rightConstant = right; | 467 if (argumentLessThan32(right)) { |
| 436 IntConstant intConstant = rightConstant.constant; | |
| 437 int count = intConstant.value; | |
| 438 if (count >= 0 && count <= 31) { | |
| 439 return newBuiltinVariant(instruction); | 468 return newBuiltinVariant(instruction); |
| 440 } | 469 } |
| 441 return null; | 470 return null; |
| 442 } | 471 } |
| 443 | 472 |
| 444 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { | 473 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 445 return new HShiftLeft( | 474 return new HShiftLeft( |
| 446 instruction.inputs[1], instruction.inputs[2], instruction.selector); | 475 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 447 } | 476 } |
| 477 |
| 478 bool argumentLessThan32(HInstruction instruction) { |
| 479 if (!instruction.isConstantInteger()) return false; |
| 480 HConstant rightConstant = instruction; |
| 481 IntConstant intConstant = rightConstant.constant; |
| 482 int count = intConstant.value; |
| 483 return count >= 0 && count <= 31; |
| 484 } |
| 485 |
| 486 bool hasBuiltinVariant(HInvokeDynamic instruction, Compiler compiler) { |
| 487 return argumentLessThan32(instruction.inputs[2]); |
| 488 } |
| 448 } | 489 } |
| 449 | 490 |
| 450 class ShiftRightSpecializer extends BinaryBitOpSpecializer { | 491 class ShiftRightSpecializer extends BinaryBitOpSpecializer { |
| 451 const ShiftRightSpecializer(); | 492 const ShiftRightSpecializer(); |
| 452 | 493 |
| 453 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { | 494 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 454 // Shift right cannot be mapped to the native operator easily. | 495 // Shift right cannot be mapped to the native operator easily. |
| 455 return null; | 496 return null; |
| 456 } | 497 } |
| 457 | 498 |
| 458 BinaryOperation operation(ConstantSystem constantSystem) { | 499 BinaryOperation operation(ConstantSystem constantSystem) { |
| 459 return constantSystem.shiftRight; | 500 return constantSystem.shiftRight; |
| 460 } | 501 } |
| 502 |
| 503 bool hasBuiltinVariant(HInvokeDynamic instruction, Compiler compiler) { |
| 504 return true; |
| 505 } |
| 461 } | 506 } |
| 462 | 507 |
| 463 class BitOrSpecializer extends BinaryBitOpSpecializer { | 508 class BitOrSpecializer extends BinaryBitOpSpecializer { |
| 464 const BitOrSpecializer(); | 509 const BitOrSpecializer(); |
| 465 | 510 |
| 466 BinaryOperation operation(ConstantSystem constantSystem) { | 511 BinaryOperation operation(ConstantSystem constantSystem) { |
| 467 return constantSystem.bitOr; | 512 return constantSystem.bitOr; |
| 468 } | 513 } |
| 469 | 514 |
| 470 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { | 515 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 575 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 531 Compiler compiler) { | 576 Compiler compiler) { |
| 532 HInstruction left = instruction.inputs[1]; | 577 HInstruction left = instruction.inputs[1]; |
| 533 HInstruction right = instruction.inputs[2]; | 578 HInstruction right = instruction.inputs[2]; |
| 534 if (left.isNumber() && right.isNumber()) { | 579 if (left.isNumber() && right.isNumber()) { |
| 535 return newBuiltinVariant(instruction); | 580 return newBuiltinVariant(instruction); |
| 536 } | 581 } |
| 537 return null; | 582 return null; |
| 538 } | 583 } |
| 539 | 584 |
| 585 bool hasBuiltinVariant(HInvokeDynamic instruction, Compiler compiler) { |
| 586 return true; |
| 587 } |
| 588 |
| 540 HInstruction newBuiltinVariant(HInvokeDynamic instruction); | 589 HInstruction newBuiltinVariant(HInvokeDynamic instruction); |
| 541 } | 590 } |
| 542 | 591 |
| 543 class EqualsSpecializer extends RelationalSpecializer { | 592 class EqualsSpecializer extends RelationalSpecializer { |
| 544 const EqualsSpecializer(); | 593 const EqualsSpecializer(); |
| 545 | 594 |
| 546 HType computeDesiredTypeForInput(HInvokeDynamic instruction, | 595 HType computeDesiredTypeForInput(HInvokeDynamic instruction, |
| 547 HInstruction input, | 596 HInstruction input, |
| 548 Compiler compiler) { | 597 Compiler compiler) { |
| 549 HInstruction left = instruction.inputs[1]; | 598 HInstruction left = instruction.inputs[1]; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 | 694 |
| 646 BinaryOperation operation(ConstantSystem constantSystem) { | 695 BinaryOperation operation(ConstantSystem constantSystem) { |
| 647 return constantSystem.lessEqual; | 696 return constantSystem.lessEqual; |
| 648 } | 697 } |
| 649 | 698 |
| 650 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { | 699 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 651 return new HLessEqual( | 700 return new HLessEqual( |
| 652 instruction.inputs[1], instruction.inputs[2], instruction.selector); | 701 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 653 } | 702 } |
| 654 } | 703 } |
| OLD | NEW |