| 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 // version is cheaper than having another bailout case. This is true, | 95 // version is cheaper than having another bailout case. This is true, |
| 96 // because the integer check will simply throw if it fails. | 96 // because the integer check will simply throw if it fails. |
| 97 return HType.UNKNOWN; | 97 return HType.UNKNOWN; |
| 98 } | 98 } |
| 99 | 99 |
| 100 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 100 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 101 Compiler compiler) { | 101 Compiler compiler) { |
| 102 if (instruction.inputs[1].isMutableArray()) { | 102 if (instruction.inputs[1].isMutableArray()) { |
| 103 return new HIndexAssign(instruction.inputs[1], | 103 return new HIndexAssign(instruction.inputs[1], |
| 104 instruction.inputs[2], | 104 instruction.inputs[2], |
| 105 instruction.inputs[3]); | 105 instruction.inputs[3], |
| 106 instruction.selector); |
| 106 } | 107 } |
| 107 return null; | 108 return null; |
| 108 } | 109 } |
| 109 } | 110 } |
| 110 | 111 |
| 111 class IndexSpecializer extends InvokeDynamicSpecializer { | 112 class IndexSpecializer extends InvokeDynamicSpecializer { |
| 112 const IndexSpecializer(); | 113 const IndexSpecializer(); |
| 113 | 114 |
| 114 HType computeDesiredTypeForInput(HInvokeDynamic instruction, | 115 HType computeDesiredTypeForInput(HInvokeDynamic instruction, |
| 115 HInstruction input, | 116 HInstruction input, |
| 116 Compiler compiler) { | 117 Compiler compiler) { |
| 117 HInstruction index = instruction.inputs[2]; | 118 HInstruction index = instruction.inputs[2]; |
| 118 if (input == instruction.inputs[1] && | 119 if (input == instruction.inputs[1] && |
| 119 index.instructionType.canBePrimitiveNumber(compiler)) { | 120 index.instructionType.canBePrimitiveNumber(compiler)) { |
| 120 return HType.INDEXABLE_PRIMITIVE; | 121 return HType.INDEXABLE_PRIMITIVE; |
| 121 } | 122 } |
| 122 // The index should be an int when the receiver is a string or array. | 123 // The index should be an int when the receiver is a string or array. |
| 123 // However it turns out that inserting an integer check in the optimized | 124 // However it turns out that inserting an integer check in the optimized |
| 124 // version is cheaper than having another bailout case. This is true, | 125 // version is cheaper than having another bailout case. This is true, |
| 125 // because the integer check will simply throw if it fails. | 126 // because the integer check will simply throw if it fails. |
| 126 return HType.UNKNOWN; | 127 return HType.UNKNOWN; |
| 127 } | 128 } |
| 128 | 129 |
| 129 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 130 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 130 Compiler compiler) { | 131 Compiler compiler) { |
| 131 if (instruction.inputs[1].isIndexablePrimitive()) { | 132 if (instruction.inputs[1].isIndexablePrimitive()) { |
| 132 return new HIndex(instruction.inputs[1], instruction.inputs[2]); | 133 return new HIndex( |
| 134 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 133 } | 135 } |
| 134 return null; | 136 return null; |
| 135 } | 137 } |
| 136 } | 138 } |
| 137 | 139 |
| 138 class BitNotSpecializer extends InvokeDynamicSpecializer { | 140 class BitNotSpecializer extends InvokeDynamicSpecializer { |
| 139 const BitNotSpecializer(); | 141 const BitNotSpecializer(); |
| 140 | 142 |
| 141 UnaryOperation operation(ConstantSystem constantSystem) { | 143 UnaryOperation operation(ConstantSystem constantSystem) { |
| 142 return constantSystem.bitNot; | 144 return constantSystem.bitNot; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 158 Compiler compiler) { | 160 Compiler compiler) { |
| 159 // All bitwise operations on primitive types either produce an | 161 // All bitwise operations on primitive types either produce an |
| 160 // integer or throw an error. | 162 // integer or throw an error. |
| 161 if (instruction.inputs[1].isPrimitive()) return HType.INTEGER; | 163 if (instruction.inputs[1].isPrimitive()) return HType.INTEGER; |
| 162 return instruction.instructionType; | 164 return instruction.instructionType; |
| 163 } | 165 } |
| 164 | 166 |
| 165 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 167 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 166 Compiler compiler) { | 168 Compiler compiler) { |
| 167 HInstruction input = instruction.inputs[1]; | 169 HInstruction input = instruction.inputs[1]; |
| 168 if (input.isNumber()) return new HBitNot(input); | 170 if (input.isNumber()) return new HBitNot(input, instruction.selector); |
| 169 return null; | 171 return null; |
| 170 } | 172 } |
| 171 } | 173 } |
| 172 | 174 |
| 173 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { | 175 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { |
| 174 const UnaryNegateSpecializer(); | 176 const UnaryNegateSpecializer(); |
| 175 | 177 |
| 176 UnaryOperation operation(ConstantSystem constantSystem) { | 178 UnaryOperation operation(ConstantSystem constantSystem) { |
| 177 return constantSystem.negate; | 179 return constantSystem.negate; |
| 178 } | 180 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 194 HType computeTypeFromInputTypes(HInvokeDynamic instruction, | 196 HType computeTypeFromInputTypes(HInvokeDynamic instruction, |
| 195 Compiler compiler) { | 197 Compiler compiler) { |
| 196 HType operandType = instruction.inputs[1].instructionType; | 198 HType operandType = instruction.inputs[1].instructionType; |
| 197 if (operandType.isNumber()) return operandType; | 199 if (operandType.isNumber()) return operandType; |
| 198 return instruction.instructionType; | 200 return instruction.instructionType; |
| 199 } | 201 } |
| 200 | 202 |
| 201 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 203 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 202 Compiler compiler) { | 204 Compiler compiler) { |
| 203 HInstruction input = instruction.inputs[1]; | 205 HInstruction input = instruction.inputs[1]; |
| 204 if (input.isNumber()) return new HNegate(input); | 206 if (input.isNumber()) return new HNegate(input, instruction.selector); |
| 205 return null; | 207 return null; |
| 206 } | 208 } |
| 207 } | 209 } |
| 208 | 210 |
| 209 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { | 211 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { |
| 210 const BinaryArithmeticSpecializer(); | 212 const BinaryArithmeticSpecializer(); |
| 211 | 213 |
| 212 HType computeTypeFromInputTypes(HInvokeDynamic instruction, | 214 HType computeTypeFromInputTypes(HInvokeDynamic instruction, |
| 213 Compiler compiler) { | 215 Compiler compiler) { |
| 214 HInstruction left = instruction.inputs[1]; | 216 HInstruction left = instruction.inputs[1]; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 } | 252 } |
| 251 | 253 |
| 252 bool isBuiltin(HInvokeDynamic instruction) { | 254 bool isBuiltin(HInvokeDynamic instruction) { |
| 253 return instruction.inputs[1].isNumber() | 255 return instruction.inputs[1].isNumber() |
| 254 && instruction.inputs[2].isNumber(); | 256 && instruction.inputs[2].isNumber(); |
| 255 } | 257 } |
| 256 | 258 |
| 257 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 259 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 258 Compiler compiler) { | 260 Compiler compiler) { |
| 259 if (isBuiltin(instruction)) { | 261 if (isBuiltin(instruction)) { |
| 260 HInstruction builtin = | 262 HInstruction builtin = newBuiltinVariant(instruction); |
| 261 newBuiltinVariant(instruction.inputs[1], instruction.inputs[2]); | |
| 262 if (builtin != null) return builtin; | 263 if (builtin != null) return builtin; |
| 263 // Even if there is no builtin equivalent instruction, we know | 264 // Even if there is no builtin equivalent instruction, we know |
| 264 // the instruction does not have any side effect, and that it | 265 // the instruction does not have any side effect, and that it |
| 265 // can be GVN'ed. | 266 // can be GVN'ed. |
| 266 instruction.clearAllSideEffects(); | 267 instruction.clearAllSideEffects(); |
| 267 instruction.clearAllDependencies(); | 268 instruction.clearAllDependencies(); |
| 268 instruction.setUseGvn(); | 269 instruction.setUseGvn(); |
| 269 } | 270 } |
| 270 return null; | 271 return null; |
| 271 } | 272 } |
| 272 | 273 |
| 273 HInstruction newBuiltinVariant(HInstruction left, HInstruction right); | 274 HInstruction newBuiltinVariant(HInvokeDynamic instruction); |
| 274 } | 275 } |
| 275 | 276 |
| 276 class AddSpecializer extends BinaryArithmeticSpecializer { | 277 class AddSpecializer extends BinaryArithmeticSpecializer { |
| 277 const AddSpecializer(); | 278 const AddSpecializer(); |
| 278 | 279 |
| 279 BinaryOperation operation(ConstantSystem constantSystem) { | 280 BinaryOperation operation(ConstantSystem constantSystem) { |
| 280 return constantSystem.add; | 281 return constantSystem.add; |
| 281 } | 282 } |
| 282 | 283 |
| 283 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 284 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 284 return new HAdd(left, right); | 285 return new HAdd( |
| 286 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 285 } | 287 } |
| 286 } | 288 } |
| 287 | 289 |
| 288 class DivideSpecializer extends BinaryArithmeticSpecializer { | 290 class DivideSpecializer extends BinaryArithmeticSpecializer { |
| 289 const DivideSpecializer(); | 291 const DivideSpecializer(); |
| 290 | 292 |
| 291 BinaryOperation operation(ConstantSystem constantSystem) { | 293 BinaryOperation operation(ConstantSystem constantSystem) { |
| 292 return constantSystem.divide; | 294 return constantSystem.divide; |
| 293 } | 295 } |
| 294 | 296 |
| 295 HType computeTypeFromInputTypes(HInstruction instruction, | 297 HType computeTypeFromInputTypes(HInstruction instruction, |
| 296 Compiler compiler) { | 298 Compiler compiler) { |
| 297 HInstruction left = instruction.inputs[1]; | 299 HInstruction left = instruction.inputs[1]; |
| 298 if (left.isNumber()) return HType.DOUBLE; | 300 if (left.isNumber()) return HType.DOUBLE; |
| 299 return instruction.instructionType; | 301 return instruction.instructionType; |
| 300 } | 302 } |
| 301 | 303 |
| 302 HType computeDesiredTypeForInput(HInstruction instruction, | 304 HType computeDesiredTypeForInput(HInstruction instruction, |
| 303 HInstruction input, | 305 HInstruction input, |
| 304 Compiler compiler) { | 306 Compiler compiler) { |
| 305 if (input == instruction.inputs[0]) return HType.UNKNOWN; | 307 if (input == instruction.inputs[0]) return HType.UNKNOWN; |
| 306 // A division can never return an integer. So don't ask for integer inputs. | 308 // A division can never return an integer. So don't ask for integer inputs. |
| 307 if (instruction.isInteger()) return HType.UNKNOWN; | 309 if (instruction.isInteger()) return HType.UNKNOWN; |
| 308 return super.computeDesiredTypeForInput( | 310 return super.computeDesiredTypeForInput( |
| 309 instruction, input, compiler); | 311 instruction, input, compiler); |
| 310 } | 312 } |
| 311 | 313 |
| 312 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 314 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 313 return new HDivide(left, right); | 315 return new HDivide( |
| 316 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 314 } | 317 } |
| 315 } | 318 } |
| 316 | 319 |
| 317 class ModuloSpecializer extends BinaryArithmeticSpecializer { | 320 class ModuloSpecializer extends BinaryArithmeticSpecializer { |
| 318 const ModuloSpecializer(); | 321 const ModuloSpecializer(); |
| 319 | 322 |
| 320 BinaryOperation operation(ConstantSystem constantSystem) { | 323 BinaryOperation operation(ConstantSystem constantSystem) { |
| 321 return constantSystem.modulo; | 324 return constantSystem.modulo; |
| 322 } | 325 } |
| 323 | 326 |
| 324 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 327 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 325 // Modulo cannot be mapped to the native operator (different semantics). | 328 // Modulo cannot be mapped to the native operator (different semantics). |
| 326 return null; | 329 return null; |
| 327 } | 330 } |
| 328 } | 331 } |
| 329 | 332 |
| 330 class MultiplySpecializer extends BinaryArithmeticSpecializer { | 333 class MultiplySpecializer extends BinaryArithmeticSpecializer { |
| 331 const MultiplySpecializer(); | 334 const MultiplySpecializer(); |
| 332 | 335 |
| 333 BinaryOperation operation(ConstantSystem constantSystem) { | 336 BinaryOperation operation(ConstantSystem constantSystem) { |
| 334 return constantSystem.multiply; | 337 return constantSystem.multiply; |
| 335 } | 338 } |
| 336 | 339 |
| 337 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 340 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 338 return new HMultiply(left, right); | 341 return new HMultiply( |
| 342 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 339 } | 343 } |
| 340 } | 344 } |
| 341 | 345 |
| 342 class SubtractSpecializer extends BinaryArithmeticSpecializer { | 346 class SubtractSpecializer extends BinaryArithmeticSpecializer { |
| 343 const SubtractSpecializer(); | 347 const SubtractSpecializer(); |
| 344 | 348 |
| 345 BinaryOperation operation(ConstantSystem constantSystem) { | 349 BinaryOperation operation(ConstantSystem constantSystem) { |
| 346 return constantSystem.subtract; | 350 return constantSystem.subtract; |
| 347 } | 351 } |
| 348 | 352 |
| 349 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 353 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 350 return new HSubtract(left, right); | 354 return new HSubtract( |
| 355 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 351 } | 356 } |
| 352 } | 357 } |
| 353 | 358 |
| 354 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { | 359 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { |
| 355 const TruncatingDivideSpecializer(); | 360 const TruncatingDivideSpecializer(); |
| 356 | 361 |
| 357 BinaryOperation operation(ConstantSystem constantSystem) { | 362 BinaryOperation operation(ConstantSystem constantSystem) { |
| 358 return constantSystem.truncatingDivide; | 363 return constantSystem.truncatingDivide; |
| 359 } | 364 } |
| 360 | 365 |
| 361 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 366 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 362 // Truncating divide does not have a JS equivalent. | 367 // Truncating divide does not have a JS equivalent. |
| 363 return null; | 368 return null; |
| 364 } | 369 } |
| 365 } | 370 } |
| 366 | 371 |
| 367 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { | 372 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { |
| 368 const BinaryBitOpSpecializer(); | 373 const BinaryBitOpSpecializer(); |
| 369 | 374 |
| 370 HType computeTypeFromInputTypes(HInvokeDynamic instruction, | 375 HType computeTypeFromInputTypes(HInvokeDynamic instruction, |
| 371 Compiler compiler) { | 376 Compiler compiler) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 400 | 405 |
| 401 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 406 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 402 Compiler compiler) { | 407 Compiler compiler) { |
| 403 HInstruction left = instruction.inputs[1]; | 408 HInstruction left = instruction.inputs[1]; |
| 404 HInstruction right = instruction.inputs[2]; | 409 HInstruction right = instruction.inputs[2]; |
| 405 if (!left.isNumber() || !right.isConstantInteger()) return null; | 410 if (!left.isNumber() || !right.isConstantInteger()) return null; |
| 406 HConstant rightConstant = right; | 411 HConstant rightConstant = right; |
| 407 IntConstant intConstant = rightConstant.constant; | 412 IntConstant intConstant = rightConstant.constant; |
| 408 int count = intConstant.value; | 413 int count = intConstant.value; |
| 409 if (count >= 0 && count <= 31) { | 414 if (count >= 0 && count <= 31) { |
| 410 return newBuiltinVariant(left, right); | 415 return newBuiltinVariant(instruction); |
| 411 } | 416 } |
| 412 return null; | 417 return null; |
| 413 } | 418 } |
| 414 | 419 |
| 415 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 420 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 416 return new HShiftLeft(left, right); | 421 return new HShiftLeft( |
| 422 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 417 } | 423 } |
| 418 } | 424 } |
| 419 | 425 |
| 420 class ShiftRightSpecializer extends BinaryBitOpSpecializer { | 426 class ShiftRightSpecializer extends BinaryBitOpSpecializer { |
| 421 const ShiftRightSpecializer(); | 427 const ShiftRightSpecializer(); |
| 422 | 428 |
| 423 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 429 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 424 // Shift right cannot be mapped to the native operator easily. | 430 // Shift right cannot be mapped to the native operator easily. |
| 425 return null; | 431 return null; |
| 426 } | 432 } |
| 427 | 433 |
| 428 BinaryOperation operation(ConstantSystem constantSystem) { | 434 BinaryOperation operation(ConstantSystem constantSystem) { |
| 429 return constantSystem.shiftRight; | 435 return constantSystem.shiftRight; |
| 430 } | 436 } |
| 431 } | 437 } |
| 432 | 438 |
| 433 class BitOrSpecializer extends BinaryBitOpSpecializer { | 439 class BitOrSpecializer extends BinaryBitOpSpecializer { |
| 434 const BitOrSpecializer(); | 440 const BitOrSpecializer(); |
| 435 | 441 |
| 436 BinaryOperation operation(ConstantSystem constantSystem) { | 442 BinaryOperation operation(ConstantSystem constantSystem) { |
| 437 return constantSystem.bitOr; | 443 return constantSystem.bitOr; |
| 438 } | 444 } |
| 439 | 445 |
| 440 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 446 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 441 return new HBitOr(left, right); | 447 return new HBitOr( |
| 448 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 442 } | 449 } |
| 443 } | 450 } |
| 444 | 451 |
| 445 class BitAndSpecializer extends BinaryBitOpSpecializer { | 452 class BitAndSpecializer extends BinaryBitOpSpecializer { |
| 446 const BitAndSpecializer(); | 453 const BitAndSpecializer(); |
| 447 | 454 |
| 448 BinaryOperation operation(ConstantSystem constantSystem) { | 455 BinaryOperation operation(ConstantSystem constantSystem) { |
| 449 return constantSystem.bitAnd; | 456 return constantSystem.bitAnd; |
| 450 } | 457 } |
| 451 | 458 |
| 452 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 459 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 453 return new HBitAnd(left, right); | 460 return new HBitAnd( |
| 461 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 454 } | 462 } |
| 455 } | 463 } |
| 456 | 464 |
| 457 class BitXorSpecializer extends BinaryBitOpSpecializer { | 465 class BitXorSpecializer extends BinaryBitOpSpecializer { |
| 458 const BitXorSpecializer(); | 466 const BitXorSpecializer(); |
| 459 | 467 |
| 460 BinaryOperation operation(ConstantSystem constantSystem) { | 468 BinaryOperation operation(ConstantSystem constantSystem) { |
| 461 return constantSystem.bitXor; | 469 return constantSystem.bitXor; |
| 462 } | 470 } |
| 463 | 471 |
| 464 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 472 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 465 return new HBitXor(left, right); | 473 return new HBitXor( |
| 474 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 466 } | 475 } |
| 467 } | 476 } |
| 468 | 477 |
| 469 abstract class RelationalSpecializer extends InvokeDynamicSpecializer { | 478 abstract class RelationalSpecializer extends InvokeDynamicSpecializer { |
| 470 const RelationalSpecializer(); | 479 const RelationalSpecializer(); |
| 471 | 480 |
| 472 HType computeTypeFromInputTypes(HInvokeDynamic instruction, | 481 HType computeTypeFromInputTypes(HInvokeDynamic instruction, |
| 473 Compiler compiler) { | 482 Compiler compiler) { |
| 474 if (instruction.inputs[1].instructionType.isPrimitiveOrNull()) { | 483 if (instruction.inputs[1].instructionType.isPrimitiveOrNull()) { |
| 475 return HType.BOOLEAN; | 484 return HType.BOOLEAN; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 492 } | 501 } |
| 493 } | 502 } |
| 494 return HType.UNKNOWN; | 503 return HType.UNKNOWN; |
| 495 } | 504 } |
| 496 | 505 |
| 497 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 506 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 498 Compiler compiler) { | 507 Compiler compiler) { |
| 499 HInstruction left = instruction.inputs[1]; | 508 HInstruction left = instruction.inputs[1]; |
| 500 HInstruction right = instruction.inputs[2]; | 509 HInstruction right = instruction.inputs[2]; |
| 501 if (left.isNumber() && right.isNumber()) { | 510 if (left.isNumber() && right.isNumber()) { |
| 502 return newBuiltinVariant(left, right); | 511 return newBuiltinVariant(instruction); |
| 503 } | 512 } |
| 504 return null; | 513 return null; |
| 505 } | 514 } |
| 506 | 515 |
| 507 HInstruction newBuiltinVariant(HInstruction left, HInstruction right); | 516 HInstruction newBuiltinVariant(HInvokeDynamic instruction); |
| 508 } | 517 } |
| 509 | 518 |
| 510 class EqualsSpecializer extends RelationalSpecializer { | 519 class EqualsSpecializer extends RelationalSpecializer { |
| 511 const EqualsSpecializer(); | 520 const EqualsSpecializer(); |
| 512 | 521 |
| 513 HType computeDesiredTypeForInput(HInvokeDynamic instruction, | 522 HType computeDesiredTypeForInput(HInvokeDynamic instruction, |
| 514 HInstruction input, | 523 HInstruction input, |
| 515 Compiler compiler) { | 524 Compiler compiler) { |
| 516 HInstruction left = instruction.inputs[1]; | 525 HInstruction left = instruction.inputs[1]; |
| 517 HInstruction right = instruction.inputs[2]; | 526 HInstruction right = instruction.inputs[2]; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 535 } | 544 } |
| 536 return HType.UNKNOWN; | 545 return HType.UNKNOWN; |
| 537 } | 546 } |
| 538 | 547 |
| 539 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 548 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 540 Compiler compiler) { | 549 Compiler compiler) { |
| 541 HInstruction left = instruction.inputs[1]; | 550 HInstruction left = instruction.inputs[1]; |
| 542 HInstruction right = instruction.inputs[2]; | 551 HInstruction right = instruction.inputs[2]; |
| 543 HType instructionType = left.instructionType; | 552 HType instructionType = left.instructionType; |
| 544 if (right.isConstantNull() || instructionType.isPrimitiveOrNull()) { | 553 if (right.isConstantNull() || instructionType.isPrimitiveOrNull()) { |
| 545 return newBuiltinVariant(left, right); | 554 return newBuiltinVariant(instruction); |
| 546 } | 555 } |
| 547 TypeMask mask = instructionType.computeMask(compiler); | 556 TypeMask mask = instructionType.computeMask(compiler); |
| 548 Selector selector = new TypedSelector(mask, instruction.selector); | 557 Selector selector = new TypedSelector(mask, instruction.selector); |
| 549 World world = compiler.world; | 558 World world = compiler.world; |
| 550 JavaScriptBackend backend = compiler.backend; | 559 JavaScriptBackend backend = compiler.backend; |
| 551 Iterable<Element> matches = world.allFunctions.filter(selector); | 560 Iterable<Element> matches = world.allFunctions.filter(selector); |
| 552 // This test relies the on `Object.==` and `Interceptor.==` always being | 561 // This test relies the on `Object.==` and `Interceptor.==` always being |
| 553 // implemented because if the selector matches by subtype, it still will be | 562 // implemented because if the selector matches by subtype, it still will be |
| 554 // a regular object or an interceptor. | 563 // a regular object or an interceptor. |
| 555 if (matches.every(backend.isDefaultEqualityImplementation)) { | 564 if (matches.every(backend.isDefaultEqualityImplementation)) { |
| 556 return newBuiltinVariant(left, right); | 565 return newBuiltinVariant(instruction); |
| 557 } | 566 } |
| 558 return null; | 567 return null; |
| 559 } | 568 } |
| 560 | 569 |
| 561 BinaryOperation operation(ConstantSystem constantSystem) { | 570 BinaryOperation operation(ConstantSystem constantSystem) { |
| 562 return constantSystem.equal; | 571 return constantSystem.equal; |
| 563 } | 572 } |
| 564 | 573 |
| 565 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 574 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 566 return new HIdentity(left, right); | 575 return new HIdentity( |
| 576 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 567 } | 577 } |
| 568 } | 578 } |
| 569 | 579 |
| 570 class LessSpecializer extends RelationalSpecializer { | 580 class LessSpecializer extends RelationalSpecializer { |
| 571 const LessSpecializer(); | 581 const LessSpecializer(); |
| 572 | 582 |
| 573 BinaryOperation operation(ConstantSystem constantSystem) { | 583 BinaryOperation operation(ConstantSystem constantSystem) { |
| 574 return constantSystem.less; | 584 return constantSystem.less; |
| 575 } | 585 } |
| 576 | 586 |
| 577 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 587 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 578 return new HLess(left, right); | 588 return new HLess( |
| 589 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 579 } | 590 } |
| 580 } | 591 } |
| 581 | 592 |
| 582 class GreaterSpecializer extends RelationalSpecializer { | 593 class GreaterSpecializer extends RelationalSpecializer { |
| 583 const GreaterSpecializer(); | 594 const GreaterSpecializer(); |
| 584 | 595 |
| 585 BinaryOperation operation(ConstantSystem constantSystem) { | 596 BinaryOperation operation(ConstantSystem constantSystem) { |
| 586 return constantSystem.greater; | 597 return constantSystem.greater; |
| 587 } | 598 } |
| 588 | 599 |
| 589 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 600 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 590 return new HGreater(left, right); | 601 return new HGreater( |
| 602 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 591 } | 603 } |
| 592 } | 604 } |
| 593 | 605 |
| 594 class GreaterEqualSpecializer extends RelationalSpecializer { | 606 class GreaterEqualSpecializer extends RelationalSpecializer { |
| 595 const GreaterEqualSpecializer(); | 607 const GreaterEqualSpecializer(); |
| 596 | 608 |
| 597 BinaryOperation operation(ConstantSystem constantSystem) { | 609 BinaryOperation operation(ConstantSystem constantSystem) { |
| 598 return constantSystem.greaterEqual; | 610 return constantSystem.greaterEqual; |
| 599 } | 611 } |
| 600 | 612 |
| 601 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 613 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 602 return new HGreaterEqual(left, right); | 614 return new HGreaterEqual( |
| 615 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 603 } | 616 } |
| 604 } | 617 } |
| 605 | 618 |
| 606 class LessEqualSpecializer extends RelationalSpecializer { | 619 class LessEqualSpecializer extends RelationalSpecializer { |
| 607 const LessEqualSpecializer(); | 620 const LessEqualSpecializer(); |
| 608 | 621 |
| 609 BinaryOperation operation(ConstantSystem constantSystem) { | 622 BinaryOperation operation(ConstantSystem constantSystem) { |
| 610 return constantSystem.lessEqual; | 623 return constantSystem.lessEqual; |
| 611 } | 624 } |
| 612 | 625 |
| 613 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 626 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { |
| 614 return new HLessEqual(left, right); | 627 return new HLessEqual( |
| 628 instruction.inputs[1], instruction.inputs[2], instruction.selector); |
| 615 } | 629 } |
| 616 } | 630 } |
| OLD | NEW |