| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/js-typed-lowering.h" |
| 6 |
| 5 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 6 #include "src/compilation-dependencies.h" | 8 #include "src/compilation-dependencies.h" |
| 7 #include "src/compiler/access-builder.h" | 9 #include "src/compiler/access-builder.h" |
| 8 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
| 9 #include "src/compiler/js-typed-lowering.h" | |
| 10 #include "src/compiler/linkage.h" | 11 #include "src/compiler/linkage.h" |
| 11 #include "src/compiler/node-matchers.h" | 12 #include "src/compiler/node-matchers.h" |
| 12 #include "src/compiler/node-properties.h" | 13 #include "src/compiler/node-properties.h" |
| 13 #include "src/compiler/operator-properties.h" | 14 #include "src/compiler/operator-properties.h" |
| 14 #include "src/type-cache.h" | 15 #include "src/type-cache.h" |
| 15 #include "src/types.h" | 16 #include "src/types.h" |
| 16 | 17 |
| 17 namespace v8 { | 18 namespace v8 { |
| 18 namespace internal { | 19 namespace internal { |
| 19 namespace compiler { | 20 namespace compiler { |
| 20 | 21 |
| 21 // A helper class to simplify the process of reducing a single binop node with a | 22 // A helper class to simplify the process of reducing a single binop node with a |
| 22 // JSOperator. This class manages the rewriting of context, control, and effect | 23 // JSOperator. This class manages the rewriting of context, control, and effect |
| 23 // dependencies during lowering of a binop and contains numerous helper | 24 // dependencies during lowering of a binop and contains numerous helper |
| 24 // functions for matching the types of inputs to an operation. | 25 // functions for matching the types of inputs to an operation. |
| 25 class JSBinopReduction final { | 26 class JSBinopReduction final { |
| 26 public: | 27 public: |
| 27 JSBinopReduction(JSTypedLowering* lowering, Node* node) | 28 JSBinopReduction(JSTypedLowering* lowering, Node* node) |
| 28 : lowering_(lowering), node_(node) {} | 29 : lowering_(lowering), node_(node) {} |
| 29 | 30 |
| 30 BinaryOperationHints::Hint GetNumberBinaryOperationFeedback() { | 31 bool GetBinaryNumberOperationHint(NumberOperationHint* hint) { |
| 31 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { | 32 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { |
| 32 DCHECK_NE(0, node_->op()->ControlOutputCount()); | 33 DCHECK_NE(0, node_->op()->ControlOutputCount()); |
| 33 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 34 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
| 34 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); | 35 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); |
| 35 BinaryOperationHints hints = BinaryOperationHintsOf(node_->op()); | 36 BinaryOperationHints hints = BinaryOperationHintsOf(node_->op()); |
| 36 BinaryOperationHints::Hint combined = hints.combined(); | 37 switch (hints.combined()) { |
| 37 if (combined == BinaryOperationHints::kSignedSmall || | 38 case BinaryOperationHints::kSignedSmall: |
| 38 combined == BinaryOperationHints::kSigned32 || | 39 *hint = NumberOperationHint::kSignedSmall; |
| 39 combined == BinaryOperationHints::kNumberOrOddball) { | 40 return true; |
| 40 return combined; | 41 case BinaryOperationHints::kSigned32: |
| 42 *hint = NumberOperationHint::kSigned32; |
| 43 return true; |
| 44 case BinaryOperationHints::kNumberOrOddball: |
| 45 *hint = NumberOperationHint::kNumberOrOddball; |
| 46 return true; |
| 47 case BinaryOperationHints::kAny: |
| 48 case BinaryOperationHints::kNone: |
| 49 case BinaryOperationHints::kString: |
| 50 break; |
| 41 } | 51 } |
| 42 } | 52 } |
| 43 return BinaryOperationHints::kAny; | 53 return false; |
| 44 } | 54 } |
| 45 | 55 |
| 46 CompareOperationHints::Hint GetNumberCompareOperationFeedback() { | 56 bool GetCompareNumberOperationHint(NumberOperationHint* hint) { |
| 47 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { | 57 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { |
| 48 DCHECK_NE(0, node_->op()->ControlOutputCount()); | 58 DCHECK_NE(0, node_->op()->ControlOutputCount()); |
| 49 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 59 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
| 50 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); | 60 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); |
| 51 CompareOperationHints hints = CompareOperationHintsOf(node_->op()); | 61 CompareOperationHints hints = CompareOperationHintsOf(node_->op()); |
| 52 CompareOperationHints::Hint combined = hints.combined(); | 62 switch (hints.combined()) { |
| 53 if (combined == CompareOperationHints::kSignedSmall || | 63 case CompareOperationHints::kSignedSmall: |
| 54 combined == CompareOperationHints::kNumberOrOddball) { | 64 *hint = NumberOperationHint::kSignedSmall; |
| 55 return combined; | 65 return true; |
| 66 case CompareOperationHints::kNumberOrOddball: |
| 67 *hint = NumberOperationHint::kNumberOrOddball; |
| 68 return true; |
| 69 case CompareOperationHints::kAny: |
| 70 case CompareOperationHints::kNone: |
| 71 case CompareOperationHints::kString: |
| 72 case CompareOperationHints::kBoolean: |
| 73 case CompareOperationHints::kUniqueName: |
| 74 case CompareOperationHints::kInternalizedString: |
| 75 case CompareOperationHints::kReceiver: |
| 76 break; |
| 56 } | 77 } |
| 57 } | 78 } |
| 58 return CompareOperationHints::kAny; | 79 return false; |
| 59 } | 80 } |
| 60 | 81 |
| 61 void ConvertInputsToNumber() { | 82 void ConvertInputsToNumber() { |
| 62 // To convert the inputs to numbers, we have to provide frame states | 83 // To convert the inputs to numbers, we have to provide frame states |
| 63 // for lazy bailouts in the ToNumber conversions. | 84 // for lazy bailouts in the ToNumber conversions. |
| 64 // We use a little hack here: we take the frame state before the binary | 85 // We use a little hack here: we take the frame state before the binary |
| 65 // operation and use it to construct the frame states for the conversion | 86 // operation and use it to construct the frame states for the conversion |
| 66 // so that after the deoptimization, the binary operation IC gets | 87 // so that after the deoptimization, the binary operation IC gets |
| 67 // already converted values from full code. This way we are sure that we | 88 // already converted values from full code. This way we are sure that we |
| 68 // will not re-do any of the side effects. | 89 // will not re-do any of the side effects. |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { | 368 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { |
| 348 double min = kMinInt / (1 << k); | 369 double min = kMinInt / (1 << k); |
| 349 double max = kMaxInt / (1 << k); | 370 double max = kMaxInt / (1 << k); |
| 350 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); | 371 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); |
| 351 } | 372 } |
| 352 } | 373 } |
| 353 | 374 |
| 354 | 375 |
| 355 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { | 376 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
| 356 JSBinopReduction r(this, node); | 377 JSBinopReduction r(this, node); |
| 357 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 378 NumberOperationHint hint; |
| 358 if (feedback == BinaryOperationHints::kNumberOrOddball && | 379 if (r.GetBinaryNumberOperationHint(&hint)) { |
| 359 r.BothInputsAre(Type::PlainPrimitive()) && | 380 if (hint == NumberOperationHint::kNumberOrOddball && |
| 360 r.NeitherInputCanBe(Type::StringOrReceiver())) { | 381 r.BothInputsAre(Type::PlainPrimitive()) && |
| 361 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 382 r.NeitherInputCanBe(Type::StringOrReceiver())) { |
| 362 r.ConvertInputsToNumber(); | 383 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
| 363 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 384 r.ConvertInputsToNumber(); |
| 364 } | 385 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
| 365 if (feedback != BinaryOperationHints::kAny) { | 386 } |
| 366 // Lower to the optimistic number binop. | |
| 367 return r.ChangeToSpeculativeOperator( | 387 return r.ChangeToSpeculativeOperator( |
| 368 simplified()->SpeculativeNumberAdd(feedback), Type::Number()); | 388 simplified()->SpeculativeNumberAdd(hint), Type::Number()); |
| 369 } | 389 } |
| 370 if (r.BothInputsAre(Type::Number())) { | 390 if (r.BothInputsAre(Type::Number())) { |
| 371 // JSAdd(x:number, y:number) => NumberAdd(x, y) | 391 // JSAdd(x:number, y:number) => NumberAdd(x, y) |
| 372 r.ConvertInputsToNumber(); | 392 r.ConvertInputsToNumber(); |
| 373 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 393 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
| 374 } | 394 } |
| 375 if ((r.BothInputsAre(Type::PlainPrimitive()) || | 395 if ((r.BothInputsAre(Type::PlainPrimitive()) || |
| 376 !(flags() & kDeoptimizationEnabled)) && | 396 !(flags() & kDeoptimizationEnabled)) && |
| 377 r.NeitherInputCanBe(Type::StringOrReceiver())) { | 397 r.NeitherInputCanBe(Type::StringOrReceiver())) { |
| 378 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 398 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 395 CallDescriptor::kNeedsFrameState, node->op()->properties()); | 415 CallDescriptor::kNeedsFrameState, node->op()->properties()); |
| 396 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); | 416 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); |
| 397 node->InsertInput(graph()->zone(), 0, | 417 node->InsertInput(graph()->zone(), 0, |
| 398 jsgraph()->HeapConstant(callable.code())); | 418 jsgraph()->HeapConstant(callable.code())); |
| 399 NodeProperties::ChangeOp(node, common()->Call(desc)); | 419 NodeProperties::ChangeOp(node, common()->Call(desc)); |
| 400 return Changed(node); | 420 return Changed(node); |
| 401 } | 421 } |
| 402 return NoChange(); | 422 return NoChange(); |
| 403 } | 423 } |
| 404 | 424 |
| 405 | |
| 406 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) { | 425 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) { |
| 407 JSBinopReduction r(this, node); | 426 JSBinopReduction r(this, node); |
| 408 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 427 NumberOperationHint hint; |
| 409 if (feedback == BinaryOperationHints::kNumberOrOddball && | 428 if (r.GetBinaryNumberOperationHint(&hint)) { |
| 410 r.BothInputsAre(Type::PlainPrimitive())) { | 429 if (hint == NumberOperationHint::kNumberOrOddball && |
| 411 // JSSubtract(x:plain-primitive, y:plain-primitive) | 430 r.BothInputsAre(Type::PlainPrimitive())) { |
| 412 // => NumberSubtract(ToNumber(x), ToNumber(y)) | 431 // JSSubtract(x:plain-primitive, y:plain-primitive) |
| 413 r.ConvertInputsToNumber(); | 432 // => NumberSubtract(ToNumber(x), ToNumber(y)) |
| 414 return r.ChangeToPureOperator(simplified()->NumberSubtract(), | 433 r.ConvertInputsToNumber(); |
| 415 Type::Number()); | 434 return r.ChangeToPureOperator(simplified()->NumberSubtract(), |
| 435 Type::Number()); |
| 436 } |
| 437 return r.ChangeToSpeculativeOperator( |
| 438 simplified()->SpeculativeNumberSubtract(hint), Type::Number()); |
| 416 } | 439 } |
| 417 if (feedback != BinaryOperationHints::kAny) { | |
| 418 // Lower to the optimistic number binop. | |
| 419 return r.ChangeToSpeculativeOperator( | |
| 420 simplified()->SpeculativeNumberSubtract(feedback), Type::Number()); | |
| 421 } | |
| 422 | |
| 423 // If deoptimization is enabled we rely on type feedback. | |
| 424 if (r.BothInputsAre(Type::PlainPrimitive()) || | 440 if (r.BothInputsAre(Type::PlainPrimitive()) || |
| 425 !(flags() & kDeoptimizationEnabled)) { | 441 !(flags() & kDeoptimizationEnabled)) { |
| 426 r.ConvertInputsToNumber(); | 442 r.ConvertInputsToNumber(); |
| 427 return r.ChangeToPureOperator(simplified()->NumberSubtract(), | 443 return r.ChangeToPureOperator(simplified()->NumberSubtract(), |
| 428 Type::Number()); | 444 Type::Number()); |
| 429 } | 445 } |
| 430 | |
| 431 return NoChange(); | 446 return NoChange(); |
| 432 } | 447 } |
| 433 | 448 |
| 434 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { | 449 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { |
| 435 JSBinopReduction r(this, node); | 450 JSBinopReduction r(this, node); |
| 436 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 451 NumberOperationHint hint; |
| 437 if (feedback == BinaryOperationHints::kNumberOrOddball && | 452 if (r.GetBinaryNumberOperationHint(&hint)) { |
| 438 r.BothInputsAre(Type::PlainPrimitive())) { | 453 if (hint == NumberOperationHint::kNumberOrOddball && |
| 439 // JSMultiply(x:plain-primitive, | 454 r.BothInputsAre(Type::PlainPrimitive())) { |
| 440 // y:plain-primitive) => NumberMultiply(ToNumber(x), ToNumber(y)) | 455 // JSMultiply(x:plain-primitive, |
| 441 r.ConvertInputsToNumber(); | 456 // y:plain-primitive) => NumberMultiply(ToNumber(x), |
| 442 return r.ChangeToPureOperator(simplified()->NumberMultiply(), | 457 // ToNumber(y)) |
| 443 Type::Number()); | 458 r.ConvertInputsToNumber(); |
| 459 return r.ChangeToPureOperator(simplified()->NumberMultiply(), |
| 460 Type::Number()); |
| 461 } |
| 462 return r.ChangeToSpeculativeOperator( |
| 463 simplified()->SpeculativeNumberMultiply(hint), Type::Number()); |
| 444 } | 464 } |
| 445 if (feedback != BinaryOperationHints::kAny) { | |
| 446 return r.ChangeToSpeculativeOperator( | |
| 447 simplified()->SpeculativeNumberMultiply(feedback), Type::Number()); | |
| 448 } | |
| 449 | |
| 450 // If deoptimization is enabled we rely on type feedback. | |
| 451 if (r.BothInputsAre(Type::PlainPrimitive()) || | 465 if (r.BothInputsAre(Type::PlainPrimitive()) || |
| 452 !(flags() & kDeoptimizationEnabled)) { | 466 !(flags() & kDeoptimizationEnabled)) { |
| 453 r.ConvertInputsToNumber(); | 467 r.ConvertInputsToNumber(); |
| 454 return r.ChangeToPureOperator(simplified()->NumberMultiply(), | 468 return r.ChangeToPureOperator(simplified()->NumberMultiply(), |
| 455 Type::Number()); | 469 Type::Number()); |
| 456 } | 470 } |
| 457 | |
| 458 return NoChange(); | 471 return NoChange(); |
| 459 } | 472 } |
| 460 | 473 |
| 461 Reduction JSTypedLowering::ReduceJSDivide(Node* node) { | 474 Reduction JSTypedLowering::ReduceJSDivide(Node* node) { |
| 462 JSBinopReduction r(this, node); | 475 JSBinopReduction r(this, node); |
| 463 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 476 NumberOperationHint hint; |
| 464 if (feedback == BinaryOperationHints::kNumberOrOddball && | 477 if (r.GetBinaryNumberOperationHint(&hint)) { |
| 465 r.BothInputsAre(Type::PlainPrimitive())) { | 478 if (hint == NumberOperationHint::kNumberOrOddball && |
| 466 // JSDivide(x:plain-primitive, | 479 r.BothInputsAre(Type::PlainPrimitive())) { |
| 467 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) | 480 // JSDivide(x:plain-primitive, |
| 468 r.ConvertInputsToNumber(); | 481 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) |
| 469 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); | 482 r.ConvertInputsToNumber(); |
| 470 } | 483 return r.ChangeToPureOperator(simplified()->NumberDivide(), |
| 471 if (feedback != BinaryOperationHints::kAny) { | 484 Type::Number()); |
| 485 } |
| 472 return r.ChangeToSpeculativeOperator( | 486 return r.ChangeToSpeculativeOperator( |
| 473 simplified()->SpeculativeNumberDivide(feedback), Type::Number()); | 487 simplified()->SpeculativeNumberDivide(hint), Type::Number()); |
| 474 } | 488 } |
| 475 if (r.BothInputsAre(Type::PlainPrimitive())) { | 489 if (r.BothInputsAre(Type::PlainPrimitive())) { |
| 476 // JSDivide(x:plain-primitive, | 490 // JSDivide(x:plain-primitive, |
| 477 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) | 491 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) |
| 478 r.ConvertInputsToNumber(); | 492 r.ConvertInputsToNumber(); |
| 479 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); | 493 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); |
| 480 } | 494 } |
| 481 return NoChange(); | 495 return NoChange(); |
| 482 } | 496 } |
| 483 | 497 |
| 484 Reduction JSTypedLowering::ReduceJSModulus(Node* node) { | 498 Reduction JSTypedLowering::ReduceJSModulus(Node* node) { |
| 485 JSBinopReduction r(this, node); | 499 JSBinopReduction r(this, node); |
| 486 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 500 NumberOperationHint hint; |
| 487 if (feedback == BinaryOperationHints::kNumberOrOddball && | 501 if (r.GetBinaryNumberOperationHint(&hint)) { |
| 488 r.BothInputsAre(Type::PlainPrimitive())) { | 502 if (hint == NumberOperationHint::kNumberOrOddball && |
| 489 // JSModulus(x:plain-primitive, | 503 r.BothInputsAre(Type::PlainPrimitive())) { |
| 490 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) | 504 // JSModulus(x:plain-primitive, |
| 491 r.ConvertInputsToNumber(); | 505 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) |
| 492 return r.ChangeToPureOperator(simplified()->NumberModulus(), | 506 r.ConvertInputsToNumber(); |
| 493 Type::Number()); | 507 return r.ChangeToPureOperator(simplified()->NumberModulus(), |
| 494 } | 508 Type::Number()); |
| 495 if (feedback != BinaryOperationHints::kAny) { | 509 } |
| 496 return r.ChangeToSpeculativeOperator( | 510 return r.ChangeToSpeculativeOperator( |
| 497 simplified()->SpeculativeNumberModulus(feedback), Type::Number()); | 511 simplified()->SpeculativeNumberModulus(hint), Type::Number()); |
| 498 } | 512 } |
| 499 if (r.BothInputsAre(Type::PlainPrimitive())) { | 513 if (r.BothInputsAre(Type::PlainPrimitive())) { |
| 500 // JSModulus(x:plain-primitive, | 514 // JSModulus(x:plain-primitive, |
| 501 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) | 515 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) |
| 502 r.ConvertInputsToNumber(); | 516 r.ConvertInputsToNumber(); |
| 503 return r.ChangeToPureOperator(simplified()->NumberModulus(), | 517 return r.ChangeToPureOperator(simplified()->NumberModulus(), |
| 504 Type::Number()); | 518 Type::Number()); |
| 505 } | 519 } |
| 506 return NoChange(); | 520 return NoChange(); |
| 507 } | 521 } |
| 508 | 522 |
| 509 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, | 523 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, |
| 510 const Operator* int_op) { | 524 const Operator* int_op) { |
| 511 JSBinopReduction r(this, node); | 525 JSBinopReduction r(this, node); |
| 512 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 526 NumberOperationHint hint; |
| 513 if (feedback != BinaryOperationHints::kAny) { | 527 if (r.GetBinaryNumberOperationHint(&hint)) { |
| 514 Operator const* speculative_op; | 528 Operator const* speculative_op; |
| 515 if (int_op->opcode() == IrOpcode::kNumberBitwiseAnd) { | 529 if (int_op->opcode() == IrOpcode::kNumberBitwiseAnd) { |
| 516 speculative_op = simplified()->SpeculativeNumberBitwiseAnd(feedback); | 530 speculative_op = simplified()->SpeculativeNumberBitwiseAnd(hint); |
| 517 } else if (int_op->opcode() == IrOpcode::kNumberBitwiseOr) { | 531 } else if (int_op->opcode() == IrOpcode::kNumberBitwiseOr) { |
| 518 speculative_op = simplified()->SpeculativeNumberBitwiseOr(feedback); | 532 speculative_op = simplified()->SpeculativeNumberBitwiseOr(hint); |
| 519 } else { | 533 } else { |
| 520 DCHECK_EQ(IrOpcode::kNumberBitwiseXor, int_op->opcode()); | 534 DCHECK_EQ(IrOpcode::kNumberBitwiseXor, int_op->opcode()); |
| 521 speculative_op = simplified()->SpeculativeNumberBitwiseXor(feedback); | 535 speculative_op = simplified()->SpeculativeNumberBitwiseXor(hint); |
| 522 } | 536 } |
| 523 return r.ChangeToSpeculativeOperator(speculative_op, Type::Signed32()); | 537 return r.ChangeToSpeculativeOperator(speculative_op, Type::Signed32()); |
| 524 } | 538 } |
| 525 | |
| 526 // If deoptimization is enabled we rely on type feedback. | |
| 527 if (r.BothInputsAre(Type::PlainPrimitive()) || | 539 if (r.BothInputsAre(Type::PlainPrimitive()) || |
| 528 !(flags() & kDeoptimizationEnabled)) { | 540 !(flags() & kDeoptimizationEnabled)) { |
| 529 r.ConvertInputsToNumber(); | 541 r.ConvertInputsToNumber(); |
| 530 r.ConvertInputsToUI32(kSigned, kSigned); | 542 r.ConvertInputsToUI32(kSigned, kSigned); |
| 531 return r.ChangeToPureOperator(int_op, Type::Signed32()); | 543 return r.ChangeToPureOperator(int_op, Type::Signed32()); |
| 532 } | 544 } |
| 533 return NoChange(); | 545 return NoChange(); |
| 534 } | 546 } |
| 535 | 547 |
| 536 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, | 548 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, Signedness signedness, |
| 537 Signedness left_signedness, | |
| 538 const Operator* shift_op) { | 549 const Operator* shift_op) { |
| 539 JSBinopReduction r(this, node); | 550 JSBinopReduction r(this, node); |
| 540 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 551 NumberOperationHint hint; |
| 541 if (feedback != BinaryOperationHints::kAny) { | 552 if (r.GetBinaryNumberOperationHint(&hint)) { |
| 542 Operator const* speculative_op; | 553 Operator const* speculative_op; |
| 543 if (shift_op->opcode() == IrOpcode::kNumberShiftLeft) { | 554 if (shift_op->opcode() == IrOpcode::kNumberShiftLeft) { |
| 544 speculative_op = simplified()->SpeculativeNumberShiftLeft(feedback); | 555 speculative_op = simplified()->SpeculativeNumberShiftLeft(hint); |
| 545 } else if (shift_op->opcode() == IrOpcode::kNumberShiftRightLogical) { | 556 } else if (shift_op->opcode() == IrOpcode::kNumberShiftRightLogical) { |
| 546 speculative_op = | 557 speculative_op = simplified()->SpeculativeNumberShiftRightLogical(hint); |
| 547 simplified()->SpeculativeNumberShiftRightLogical(feedback); | |
| 548 } else { | 558 } else { |
| 549 DCHECK_EQ(IrOpcode::kNumberShiftRight, shift_op->opcode()); | 559 DCHECK_EQ(IrOpcode::kNumberShiftRight, shift_op->opcode()); |
| 550 speculative_op = simplified()->SpeculativeNumberShiftRight(feedback); | 560 speculative_op = simplified()->SpeculativeNumberShiftRight(hint); |
| 551 } | 561 } |
| 552 return r.ChangeToSpeculativeOperator( | 562 return r.ChangeToSpeculativeOperator( |
| 553 speculative_op, shift_op->opcode() == IrOpcode::kNumberShiftRightLogical | 563 speculative_op, |
| 554 ? Type::Unsigned32() | 564 signedness == kUnsigned ? Type::Unsigned32() : Type::Signed32()); |
| 555 : Type::Signed32()); | |
| 556 } | 565 } |
| 557 | |
| 558 // If deoptimization is enabled we rely on type feedback. | |
| 559 if (r.BothInputsAre(Type::PlainPrimitive()) || | 566 if (r.BothInputsAre(Type::PlainPrimitive()) || |
| 560 !(flags() & kDeoptimizationEnabled)) { | 567 !(flags() & kDeoptimizationEnabled)) { |
| 561 r.ConvertInputsToNumber(); | 568 r.ConvertInputsToNumber(); |
| 562 r.ConvertInputsToUI32(left_signedness, kUnsigned); | 569 r.ConvertInputsToUI32(signedness, kUnsigned); |
| 563 return r.ChangeToPureOperator(shift_op); | 570 return r.ChangeToPureOperator(shift_op); |
| 564 } | 571 } |
| 565 return NoChange(); | 572 return NoChange(); |
| 566 } | 573 } |
| 567 | 574 |
| 568 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { | 575 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { |
| 569 JSBinopReduction r(this, node); | 576 JSBinopReduction r(this, node); |
| 570 if (r.BothInputsAre(Type::String())) { | 577 if (r.BothInputsAre(Type::String())) { |
| 571 // If both inputs are definitely strings, perform a string comparison. | 578 // If both inputs are definitely strings, perform a string comparison. |
| 572 const Operator* stringOp; | 579 const Operator* stringOp; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 585 stringOp = simplified()->StringLessThanOrEqual(); | 592 stringOp = simplified()->StringLessThanOrEqual(); |
| 586 r.SwapInputs(); // a >= b => b <= a | 593 r.SwapInputs(); // a >= b => b <= a |
| 587 break; | 594 break; |
| 588 default: | 595 default: |
| 589 return NoChange(); | 596 return NoChange(); |
| 590 } | 597 } |
| 591 r.ChangeToPureOperator(stringOp); | 598 r.ChangeToPureOperator(stringOp); |
| 592 return Changed(node); | 599 return Changed(node); |
| 593 } | 600 } |
| 594 | 601 |
| 595 CompareOperationHints::Hint hint = r.GetNumberCompareOperationFeedback(); | 602 NumberOperationHint hint; |
| 596 if (hint != CompareOperationHints::kAny || | 603 const Operator* less_than; |
| 597 r.OneInputCannotBe(Type::StringOrReceiver())) { | 604 const Operator* less_than_or_equal; |
| 598 const Operator* less_than; | 605 if (r.BothInputsAre(Type::Signed32()) || |
| 599 const Operator* less_than_or_equal; | 606 r.BothInputsAre(Type::Unsigned32())) { |
| 600 if (r.BothInputsAre(Type::Signed32()) || | 607 less_than = simplified()->NumberLessThan(); |
| 601 r.BothInputsAre(Type::Unsigned32())) { | 608 less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
| 602 less_than = simplified()->NumberLessThan(); | 609 } else if (r.GetCompareNumberOperationHint(&hint)) { |
| 603 less_than_or_equal = simplified()->NumberLessThanOrEqual(); | 610 less_than = simplified()->SpeculativeNumberLessThan(hint); |
| 604 } else if (hint != CompareOperationHints::kAny) { | 611 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint); |
| 605 less_than = simplified()->SpeculativeNumberLessThan(hint); | 612 } else if (r.OneInputCannotBe(Type::StringOrReceiver()) && |
| 606 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint); | 613 (r.BothInputsAre(Type::PlainPrimitive()) || |
| 607 } else if (r.BothInputsAre(Type::PlainPrimitive()) || | 614 !(flags() & kDeoptimizationEnabled))) { |
| 608 !(flags() & kDeoptimizationEnabled)) { | 615 r.ConvertInputsToNumber(); |
| 609 r.ConvertInputsToNumber(); | 616 less_than = simplified()->NumberLessThan(); |
| 610 less_than = simplified()->NumberLessThan(); | 617 less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
| 611 less_than_or_equal = simplified()->NumberLessThanOrEqual(); | 618 } else { |
| 612 } else { | 619 return NoChange(); |
| 620 } |
| 621 const Operator* comparison; |
| 622 switch (node->opcode()) { |
| 623 case IrOpcode::kJSLessThan: |
| 624 comparison = less_than; |
| 625 break; |
| 626 case IrOpcode::kJSGreaterThan: |
| 627 comparison = less_than; |
| 628 r.SwapInputs(); // a > b => b < a |
| 629 break; |
| 630 case IrOpcode::kJSLessThanOrEqual: |
| 631 comparison = less_than_or_equal; |
| 632 break; |
| 633 case IrOpcode::kJSGreaterThanOrEqual: |
| 634 comparison = less_than_or_equal; |
| 635 r.SwapInputs(); // a >= b => b <= a |
| 636 break; |
| 637 default: |
| 613 return NoChange(); | 638 return NoChange(); |
| 614 } | |
| 615 const Operator* comparison; | |
| 616 switch (node->opcode()) { | |
| 617 case IrOpcode::kJSLessThan: | |
| 618 comparison = less_than; | |
| 619 break; | |
| 620 case IrOpcode::kJSGreaterThan: | |
| 621 comparison = less_than; | |
| 622 r.SwapInputs(); // a > b => b < a | |
| 623 break; | |
| 624 case IrOpcode::kJSLessThanOrEqual: | |
| 625 comparison = less_than_or_equal; | |
| 626 break; | |
| 627 case IrOpcode::kJSGreaterThanOrEqual: | |
| 628 comparison = less_than_or_equal; | |
| 629 r.SwapInputs(); // a >= b => b <= a | |
| 630 break; | |
| 631 default: | |
| 632 return NoChange(); | |
| 633 } | |
| 634 if (comparison->EffectInputCount() > 0) { | |
| 635 return r.ChangeToSpeculativeOperator(comparison, Type::Boolean()); | |
| 636 } else { | |
| 637 return r.ChangeToPureOperator(comparison); | |
| 638 } | |
| 639 } | 639 } |
| 640 // TODO(turbofan): relax/remove effects of this operator in other cases. | 640 if (comparison->EffectInputCount() > 0) { |
| 641 return NoChange(); // Keep a generic comparison. | 641 return r.ChangeToSpeculativeOperator(comparison, Type::Boolean()); |
| 642 } else { |
| 643 return r.ChangeToPureOperator(comparison); |
| 644 } |
| 642 } | 645 } |
| 643 | 646 |
| 644 Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) { | 647 Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) { |
| 645 HeapObjectBinopMatcher m(node); | 648 HeapObjectBinopMatcher m(node); |
| 646 if (m.left().IsJSTypeOf() && m.right().HasValue() && | 649 if (m.left().IsJSTypeOf() && m.right().HasValue() && |
| 647 m.right().Value()->IsString()) { | 650 m.right().Value()->IsString()) { |
| 648 Node* replacement; | 651 Node* replacement; |
| 649 Node* input = m.left().InputAt(0); | 652 Node* input = m.left().InputAt(0); |
| 650 Handle<String> value = Handle<String>::cast(m.right().Value()); | 653 Handle<String> value = Handle<String>::cast(m.right().Value()); |
| 651 if (String::Equals(value, factory()->boolean_string())) { | 654 if (String::Equals(value, factory()->boolean_string())) { |
| (...skipping 1444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2096 } | 2099 } |
| 2097 | 2100 |
| 2098 | 2101 |
| 2099 CompilationDependencies* JSTypedLowering::dependencies() const { | 2102 CompilationDependencies* JSTypedLowering::dependencies() const { |
| 2100 return dependencies_; | 2103 return dependencies_; |
| 2101 } | 2104 } |
| 2102 | 2105 |
| 2103 } // namespace compiler | 2106 } // namespace compiler |
| 2104 } // namespace internal | 2107 } // namespace internal |
| 2105 } // namespace v8 | 2108 } // namespace v8 |
| OLD | NEW |