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/access-builder.h" | 5 #include "src/compiler/access-builder.h" |
6 #include "src/compiler/graph-inl.h" | 6 #include "src/compiler/graph-inl.h" |
7 #include "src/compiler/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
8 #include "src/compiler/js-typed-lowering.h" | 8 #include "src/compiler/js-typed-lowering.h" |
9 #include "src/compiler/node-aux-data-inl.h" | 9 #include "src/compiler/node-aux-data-inl.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 | 22 |
23 // Relax the effects of {node} by immediately replacing effect uses of {node} | 23 // Relax the effects of {node} by immediately replacing effect uses of {node} |
24 // with the effect input to {node}. | 24 // with the effect input to {node}. |
25 // TODO(turbofan): replace the effect input to {node} with {graph->start()}. | 25 // TODO(turbofan): replace the effect input to {node} with {graph->start()}. |
26 // TODO(titzer): move into a GraphEditor? | 26 // TODO(titzer): move into a GraphEditor? |
27 static void RelaxEffects(Node* node) { | 27 static void RelaxEffects(Node* node) { |
28 NodeProperties::ReplaceWithValue(node, node, NULL); | 28 NodeProperties::ReplaceWithValue(node, node, NULL); |
29 } | 29 } |
30 | 30 |
31 | 31 |
32 JSTypedLowering::JSTypedLowering(JSGraph* jsgraph) | 32 JSTypedLowering::JSTypedLowering(JSGraph* jsgraph, Zone* zone) |
33 : jsgraph_(jsgraph), simplified_(jsgraph->zone()) { | 33 : jsgraph_(jsgraph), simplified_(graph()->zone()), conversions_(zone) { |
34 Handle<Object> zero = factory()->NewNumber(0.0); | 34 Handle<Object> zero = factory()->NewNumber(0.0); |
35 Handle<Object> one = factory()->NewNumber(1.0); | 35 Handle<Object> one = factory()->NewNumber(1.0); |
36 zero_range_ = Type::Range(zero, zero, graph()->zone()); | 36 zero_range_ = Type::Range(zero, zero, graph()->zone()); |
37 one_range_ = Type::Range(one, one, graph()->zone()); | 37 one_range_ = Type::Range(one, one, graph()->zone()); |
38 Handle<Object> thirtyone = factory()->NewNumber(31.0); | 38 Handle<Object> thirtyone = factory()->NewNumber(31.0); |
39 zero_thirtyone_range_ = Type::Range(zero, thirtyone, graph()->zone()); | 39 zero_thirtyone_range_ = Type::Range(zero, thirtyone, graph()->zone()); |
40 // TODO(jarin): Can we have a correctification of the stupid type system? | 40 // TODO(jarin): Can we have a correctification of the stupid type system? |
41 // These stupid work-arounds are just stupid! | 41 // These stupid work-arounds are just stupid! |
42 shifted_int32_ranges_[0] = Type::Signed32(); | 42 shifted_int32_ranges_[0] = Type::Signed32(); |
43 if (SmiValuesAre31Bits()) { | 43 if (SmiValuesAre31Bits()) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 // Avoid introducing too many eager ToString() operations. | 188 // Avoid introducing too many eager ToString() operations. |
189 Reduction reduced = lowering_->ReduceJSToStringInput(node); | 189 Reduction reduced = lowering_->ReduceJSToStringInput(node); |
190 if (reduced.Changed()) return reduced.replacement(); | 190 if (reduced.Changed()) return reduced.replacement(); |
191 Node* n = graph()->NewNode(javascript()->ToString(), node, context(), | 191 Node* n = graph()->NewNode(javascript()->ToString(), node, context(), |
192 effect(), control()); | 192 effect(), control()); |
193 update_effect(n); | 193 update_effect(n); |
194 return n; | 194 return n; |
195 } | 195 } |
196 | 196 |
197 Node* ConvertToNumber(Node* node) { | 197 Node* ConvertToNumber(Node* node) { |
198 // Avoid introducing too many eager ToNumber() operations. | 198 if (NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())) { |
199 Reduction reduced = lowering_->ReduceJSToNumberInput(node); | 199 return lowering_->ConvertToNumber(node); |
200 if (reduced.Changed()) return reduced.replacement(); | 200 } |
201 Node* n = graph()->NewNode(javascript()->ToNumber(), node, context(), | 201 Node* n = graph()->NewNode(javascript()->ToNumber(), node, context(), |
202 effect(), control()); | 202 effect(), control()); |
203 update_effect(n); | 203 update_effect(n); |
204 return n; | 204 return n; |
205 } | 205 } |
206 | 206 |
207 Node* ConvertToUI32(Node* node, Signedness signedness) { | 207 Node* ConvertToUI32(Node* node, Signedness signedness) { |
208 // Avoid introducing too many eager NumberToXXnt32() operations. | 208 // Avoid introducing too many eager NumberToXXnt32() operations. |
209 node = ConvertToNumber(node); | 209 node = ConvertToNumber(node); |
210 Type* type = NodeProperties::GetBounds(node).upper; | 210 Type* type = NodeProperties::GetBounds(node).upper; |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 } | 490 } |
491 | 491 |
492 | 492 |
493 Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) { | 493 Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) { |
494 if (input->opcode() == IrOpcode::kJSToBoolean) { | 494 if (input->opcode() == IrOpcode::kJSToBoolean) { |
495 // Recursively try to reduce the input first. | 495 // Recursively try to reduce the input first. |
496 Reduction result = ReduceJSToBoolean(input); | 496 Reduction result = ReduceJSToBoolean(input); |
497 if (result.Changed()) return result; | 497 if (result.Changed()) return result; |
498 return Changed(input); // JSToBoolean(JSToBoolean(x)) => JSToBoolean(x) | 498 return Changed(input); // JSToBoolean(JSToBoolean(x)) => JSToBoolean(x) |
499 } | 499 } |
| 500 // Check if we have a cached conversion. |
| 501 Node* conversion = FindConversion<IrOpcode::kJSToBoolean>(input); |
| 502 if (conversion) return Replace(conversion); |
500 Type* input_type = NodeProperties::GetBounds(input).upper; | 503 Type* input_type = NodeProperties::GetBounds(input).upper; |
501 if (input_type->Is(Type::Boolean())) { | 504 if (input_type->Is(Type::Boolean())) { |
502 return Changed(input); // JSToBoolean(x:boolean) => x | 505 return Changed(input); // JSToBoolean(x:boolean) => x |
503 } | 506 } |
504 if (input_type->Is(Type::Undefined())) { | 507 if (input_type->Is(Type::Undefined())) { |
505 // JSToBoolean(undefined) => #false | 508 // JSToBoolean(undefined) => #false |
506 return Replace(jsgraph()->FalseConstant()); | 509 return Replace(jsgraph()->FalseConstant()); |
507 } | 510 } |
508 if (input_type->Is(Type::Null())) { | 511 if (input_type->Is(Type::Null())) { |
509 // JSToBoolean(null) => #false | 512 // JSToBoolean(null) => #false |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 // JSToBoolean(phi(x1,...,xn,control),context) | 550 // JSToBoolean(phi(x1,...,xn,control),context) |
548 // => phi(JSToBoolean(x1,no-context),...,JSToBoolean(xn,no-context)) | 551 // => phi(JSToBoolean(x1,no-context),...,JSToBoolean(xn,no-context)) |
549 int const input_count = input->InputCount() - 1; | 552 int const input_count = input->InputCount() - 1; |
550 Node* const control = input->InputAt(input_count); | 553 Node* const control = input->InputAt(input_count); |
551 DCHECK_LE(0, input_count); | 554 DCHECK_LE(0, input_count); |
552 DCHECK(NodeProperties::IsControl(control)); | 555 DCHECK(NodeProperties::IsControl(control)); |
553 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); | 556 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); |
554 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); | 557 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); |
555 node->set_op(common()->Phi(kMachAnyTagged, input_count)); | 558 node->set_op(common()->Phi(kMachAnyTagged, input_count)); |
556 for (int i = 0; i < input_count; ++i) { | 559 for (int i = 0; i < input_count; ++i) { |
557 Node* value = input->InputAt(i); | 560 // We must be very careful not to introduce cycles when pushing |
558 // Recursively try to reduce the value first. | 561 // operations into phis. It is safe for {value}, since it appears |
559 Reduction reduction = ReduceJSToBooleanInput(value); | 562 // as input to the phi that we are replacing, but it's not safe |
560 if (reduction.Changed()) { | 563 // to simply reuse the context of the {node}. However, ToBoolean() |
561 value = reduction.replacement(); | 564 // does not require a context anyways, so it's safe to discard it |
562 } else { | 565 // here and pass the dummy context. |
563 // We must be very careful not to introduce cycles when pushing | 566 Node* const value = ConvertToBoolean(input->InputAt(i)); |
564 // operations into phis. It is safe for {value}, since it appears | |
565 // as input to the phi that we are replacing, but it's not safe | |
566 // to simply reuse the context of the {node}. However, ToBoolean() | |
567 // does not require a context anyways, so it's safe to discard it | |
568 // here and pass the dummy context. | |
569 value = graph()->NewNode(javascript()->ToBoolean(), value, | |
570 jsgraph()->NoContextConstant()); | |
571 } | |
572 if (i < node->InputCount()) { | 567 if (i < node->InputCount()) { |
573 node->ReplaceInput(i, value); | 568 node->ReplaceInput(i, value); |
574 } else { | 569 } else { |
575 node->AppendInput(graph()->zone(), value); | 570 node->AppendInput(graph()->zone(), value); |
576 } | 571 } |
577 } | 572 } |
578 if (input_count < node->InputCount()) { | 573 if (input_count < node->InputCount()) { |
579 node->ReplaceInput(input_count, control); | 574 node->ReplaceInput(input_count, control); |
580 } else { | 575 } else { |
581 node->AppendInput(graph()->zone(), control); | 576 node->AppendInput(graph()->zone(), control); |
582 } | 577 } |
583 node->TrimInputCount(input_count + 1); | 578 node->TrimInputCount(input_count + 1); |
584 return Changed(node); | 579 return Changed(node); |
585 } | 580 } |
586 if (input->opcode() == IrOpcode::kSelect) { | 581 if (input->opcode() == IrOpcode::kSelect) { |
587 // JSToBoolean(select(c,x1,x2),context) | 582 // JSToBoolean(select(c,x1,x2),context) |
588 // => select(c,JSToBoolean(x1,no-context),...,JSToBoolean(x2,no-context)) | 583 // => select(c,JSToBoolean(x1,no-context),...,JSToBoolean(x2,no-context)) |
589 int const input_count = input->InputCount(); | 584 int const input_count = input->InputCount(); |
590 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); | 585 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); |
591 DCHECK_EQ(3, input_count); | 586 DCHECK_EQ(3, input_count); |
592 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); | 587 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); |
593 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); | 588 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); |
594 node->set_op(common()->Select(kMachAnyTagged, input_hint)); | 589 node->set_op(common()->Select(kMachAnyTagged, input_hint)); |
595 node->InsertInput(graph()->zone(), 0, input->InputAt(0)); | 590 node->InsertInput(graph()->zone(), 0, input->InputAt(0)); |
596 for (int i = 1; i < input_count; ++i) { | 591 for (int i = 1; i < input_count; ++i) { |
597 Node* value = input->InputAt(i); | 592 // We must be very careful not to introduce cycles when pushing |
598 // Recursively try to reduce the value first. | 593 // operations into selects. It is safe for {value}, since it appears |
599 Reduction reduction = ReduceJSToBooleanInput(value); | 594 // as input to the select that we are replacing, but it's not safe |
600 if (reduction.Changed()) { | 595 // to simply reuse the context of the {node}. However, ToBoolean() |
601 value = reduction.replacement(); | 596 // does not require a context anyways, so it's safe to discard it |
602 } else { | 597 // here and pass the dummy context. |
603 // We must be very careful not to introduce cycles when pushing | 598 Node* const value = ConvertToBoolean(input->InputAt(i)); |
604 // operations into selects. It is safe for {value}, since it appears | |
605 // as input to the select that we are replacing, but it's not safe | |
606 // to simply reuse the context of the {node}. However, ToBoolean() | |
607 // does not require a context anyways, so it's safe to discard it | |
608 // here and pass the dummy context. | |
609 value = graph()->NewNode(javascript()->ToBoolean(), value, | |
610 jsgraph()->NoContextConstant()); | |
611 } | |
612 node->ReplaceInput(i, value); | 599 node->ReplaceInput(i, value); |
613 } | 600 } |
614 DCHECK_EQ(3, node->InputCount()); | 601 DCHECK_EQ(3, node->InputCount()); |
615 return Changed(node); | 602 return Changed(node); |
616 } | 603 } |
| 604 InsertConversion(node); |
| 605 if (node->InputAt(1) != jsgraph()->NoContextConstant()) { |
| 606 // JSToBoolean(x,context) => JSToBoolean(x,no-context) |
| 607 node->ReplaceInput(1, jsgraph()->NoContextConstant()); |
| 608 return Changed(node); |
| 609 } |
617 return NoChange(); | 610 return NoChange(); |
618 } | 611 } |
619 | 612 |
620 | 613 |
621 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { | 614 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { |
622 if (input->opcode() == IrOpcode::kJSToNumber) { | 615 if (input->opcode() == IrOpcode::kJSToNumber) { |
623 // Recursively try to reduce the input first. | 616 // Recursively try to reduce the input first. |
624 Reduction result = ReduceJSToNumber(input); | 617 Reduction result = ReduceJSToNumber(input); |
625 if (result.Changed()) return result; | 618 if (result.Changed()) return result; |
626 return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x) | 619 return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x) |
627 } | 620 } |
| 621 // Check if we have a cached conversion. |
| 622 Node* conversion = FindConversion<IrOpcode::kJSToNumber>(input); |
| 623 if (conversion) return Replace(conversion); |
628 Type* input_type = NodeProperties::GetBounds(input).upper; | 624 Type* input_type = NodeProperties::GetBounds(input).upper; |
629 if (input_type->Is(Type::Number())) { | 625 if (input_type->Is(Type::Number())) { |
630 // JSToNumber(x:number) => x | 626 // JSToNumber(x:number) => x |
631 return Changed(input); | 627 return Changed(input); |
632 } | 628 } |
633 if (input_type->Is(Type::Undefined())) { | 629 if (input_type->Is(Type::Undefined())) { |
634 // JSToNumber(undefined) => #NaN | 630 // JSToNumber(undefined) => #NaN |
635 return Replace(jsgraph()->NaNConstant()); | 631 return Replace(jsgraph()->NaNConstant()); |
636 } | 632 } |
637 if (input_type->Is(Type::Null())) { | 633 if (input_type->Is(Type::Null())) { |
(...skipping 26 matching lines...) Expand all Loading... |
664 // JSToNumber(xn,no-context),control) | 660 // JSToNumber(xn,no-context),control) |
665 int const input_count = input->InputCount() - 1; | 661 int const input_count = input->InputCount() - 1; |
666 Node* const control = input->InputAt(input_count); | 662 Node* const control = input->InputAt(input_count); |
667 DCHECK_LE(0, input_count); | 663 DCHECK_LE(0, input_count); |
668 DCHECK(NodeProperties::IsControl(control)); | 664 DCHECK(NodeProperties::IsControl(control)); |
669 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); | 665 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); |
670 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); | 666 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); |
671 RelaxEffects(node); | 667 RelaxEffects(node); |
672 node->set_op(common()->Phi(kMachAnyTagged, input_count)); | 668 node->set_op(common()->Phi(kMachAnyTagged, input_count)); |
673 for (int i = 0; i < input_count; ++i) { | 669 for (int i = 0; i < input_count; ++i) { |
674 Node* value = input->InputAt(i); | 670 // We must be very careful not to introduce cycles when pushing |
675 // Recursively try to reduce the value first. | 671 // operations into phis. It is safe for {value}, since it appears |
676 Reduction reduction = ReduceJSToNumberInput(value); | 672 // as input to the phi that we are replacing, but it's not safe |
677 if (reduction.Changed()) { | 673 // to simply reuse the context of the {node}. However, ToNumber() |
678 value = reduction.replacement(); | 674 // does not require a context anyways, so it's safe to discard it |
679 } else { | 675 // here and pass the dummy context. |
680 // We must be very careful not to introduce cycles when pushing | 676 Node* const value = ConvertToNumber(input->InputAt(i)); |
681 // operations into phis. It is safe for {value}, since it appears | |
682 // as input to the phi that we are replacing, but it's not safe | |
683 // to simply reuse the context of the {node}. However, ToNumber() | |
684 // does not require a context anyways, so it's safe to discard it | |
685 // here and pass the dummy context. | |
686 value = graph()->NewNode(javascript()->ToNumber(), value, | |
687 jsgraph()->NoContextConstant(), | |
688 graph()->start(), graph()->start()); | |
689 } | |
690 if (i < node->InputCount()) { | 677 if (i < node->InputCount()) { |
691 node->ReplaceInput(i, value); | 678 node->ReplaceInput(i, value); |
692 } else { | 679 } else { |
693 node->AppendInput(graph()->zone(), value); | 680 node->AppendInput(graph()->zone(), value); |
694 } | 681 } |
695 } | 682 } |
696 if (input_count < node->InputCount()) { | 683 if (input_count < node->InputCount()) { |
697 node->ReplaceInput(input_count, control); | 684 node->ReplaceInput(input_count, control); |
698 } else { | 685 } else { |
699 node->AppendInput(graph()->zone(), control); | 686 node->AppendInput(graph()->zone(), control); |
700 } | 687 } |
701 node->TrimInputCount(input_count + 1); | 688 node->TrimInputCount(input_count + 1); |
702 return Changed(node); | 689 return Changed(node); |
703 } | 690 } |
704 if (input->opcode() == IrOpcode::kSelect) { | 691 if (input->opcode() == IrOpcode::kSelect) { |
705 // JSToNumber(select(c,x1,x2):plain-primitive,context) | 692 // JSToNumber(select(c,x1,x2):plain-primitive,context) |
706 // => select(c,JSToNumber(x1,no-context),JSToNumber(x2,no-context)) | 693 // => select(c,JSToNumber(x1,no-context),JSToNumber(x2,no-context)) |
707 int const input_count = input->InputCount(); | 694 int const input_count = input->InputCount(); |
708 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); | 695 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); |
709 DCHECK_EQ(3, input_count); | 696 DCHECK_EQ(3, input_count); |
710 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); | 697 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); |
711 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); | 698 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); |
712 RelaxEffects(node); | 699 RelaxEffects(node); |
713 node->set_op(common()->Select(kMachAnyTagged, input_hint)); | 700 node->set_op(common()->Select(kMachAnyTagged, input_hint)); |
714 node->ReplaceInput(0, input->InputAt(0)); | 701 node->ReplaceInput(0, input->InputAt(0)); |
715 for (int i = 1; i < input_count; ++i) { | 702 for (int i = 1; i < input_count; ++i) { |
716 Node* value = input->InputAt(i); | 703 // We must be very careful not to introduce cycles when pushing |
717 // Recursively try to reduce the value first. | 704 // operations into selects. It is safe for {value}, since it appears |
718 Reduction reduction = ReduceJSToNumberInput(value); | 705 // as input to the select that we are replacing, but it's not safe |
719 if (reduction.Changed()) { | 706 // to simply reuse the context of the {node}. However, ToNumber() |
720 value = reduction.replacement(); | 707 // does not require a context anyways, so it's safe to discard it |
721 } else { | 708 // here and pass the dummy context. |
722 // We must be very careful not to introduce cycles when pushing | 709 Node* const value = ConvertToNumber(input->InputAt(i)); |
723 // operations into selects. It is safe for {value}, since it appears | |
724 // as input to the select that we are replacing, but it's not safe | |
725 // to simply reuse the context of the {node}. However, ToNumber() | |
726 // does not require a context anyways, so it's safe to discard it | |
727 // here and pass the dummy context. | |
728 value = graph()->NewNode(javascript()->ToNumber(), value, | |
729 jsgraph()->NoContextConstant(), | |
730 graph()->start(), graph()->start()); | |
731 } | |
732 node->ReplaceInput(i, value); | 710 node->ReplaceInput(i, value); |
733 } | 711 } |
734 node->TrimInputCount(input_count); | 712 node->TrimInputCount(input_count); |
735 return Changed(node); | 713 return Changed(node); |
736 } | 714 } |
| 715 // Remember this conversion. |
| 716 InsertConversion(node); |
737 if (node->InputAt(1) != jsgraph()->NoContextConstant() || | 717 if (node->InputAt(1) != jsgraph()->NoContextConstant() || |
738 node->InputAt(2) != graph()->start()) { | 718 node->InputAt(2) != graph()->start() || |
739 // JSToNumber(x:plain-primitive,context) => JSToNumber(x,no-context) | 719 node->InputAt(3) != graph()->start()) { |
| 720 // JSToNumber(x:plain-primitive,context,effect,control) |
| 721 // => JSToNumber(x,no-context,start,start) |
| 722 RelaxEffects(node); |
740 node->ReplaceInput(1, jsgraph()->NoContextConstant()); | 723 node->ReplaceInput(1, jsgraph()->NoContextConstant()); |
741 RelaxEffects(node); | 724 node->ReplaceInput(2, graph()->start()); |
| 725 node->ReplaceInput(3, graph()->start()); |
742 return Changed(node); | 726 return Changed(node); |
743 } | 727 } |
744 } | 728 } |
745 return NoChange(); | 729 return NoChange(); |
746 } | 730 } |
747 | 731 |
748 | 732 |
749 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { | 733 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { |
750 if (input->opcode() == IrOpcode::kJSToString) { | 734 if (input->opcode() == IrOpcode::kJSToString) { |
751 // Recursively try to reduce the input first. | 735 // Recursively try to reduce the input first. |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 return ReduceJSLoadContext(node); | 999 return ReduceJSLoadContext(node); |
1016 case IrOpcode::kJSStoreContext: | 1000 case IrOpcode::kJSStoreContext: |
1017 return ReduceJSStoreContext(node); | 1001 return ReduceJSStoreContext(node); |
1018 default: | 1002 default: |
1019 break; | 1003 break; |
1020 } | 1004 } |
1021 return NoChange(); | 1005 return NoChange(); |
1022 } | 1006 } |
1023 | 1007 |
1024 | 1008 |
| 1009 Node* JSTypedLowering::ConvertToBoolean(Node* input) { |
| 1010 // Avoid inserting too many eager ToBoolean() operations. |
| 1011 Reduction const reduction = ReduceJSToBooleanInput(input); |
| 1012 if (reduction.Changed()) return reduction.replacement(); |
| 1013 Node* const conversion = graph()->NewNode(javascript()->ToBoolean(), input, |
| 1014 jsgraph()->NoContextConstant()); |
| 1015 InsertConversion(conversion); |
| 1016 return conversion; |
| 1017 } |
| 1018 |
| 1019 |
| 1020 Node* JSTypedLowering::ConvertToNumber(Node* input) { |
| 1021 DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive())); |
| 1022 // Avoid inserting too many eager ToNumber() operations. |
| 1023 Reduction const reduction = ReduceJSToNumberInput(input); |
| 1024 if (reduction.Changed()) return reduction.replacement(); |
| 1025 Node* const conversion = graph()->NewNode(javascript()->ToNumber(), input, |
| 1026 jsgraph()->NoContextConstant(), |
| 1027 graph()->start(), graph()->start()); |
| 1028 InsertConversion(conversion); |
| 1029 return conversion; |
| 1030 } |
| 1031 |
| 1032 |
| 1033 template <IrOpcode::Value kOpcode> |
| 1034 Node* JSTypedLowering::FindConversion(Node* input) { |
| 1035 size_t const input_id = input->id(); |
| 1036 if (input_id < conversions_.size()) { |
| 1037 Node* const conversion = conversions_[input_id]; |
| 1038 if (conversion && conversion->opcode() == kOpcode) { |
| 1039 return conversion; |
| 1040 } |
| 1041 } |
| 1042 return nullptr; |
| 1043 } |
| 1044 |
| 1045 |
| 1046 void JSTypedLowering::InsertConversion(Node* conversion) { |
| 1047 DCHECK(conversion->opcode() == IrOpcode::kJSToBoolean || |
| 1048 conversion->opcode() == IrOpcode::kJSToNumber); |
| 1049 size_t const input_id = conversion->InputAt(0)->id(); |
| 1050 if (input_id >= conversions_.size()) { |
| 1051 conversions_.resize(2 * input_id + 1); |
| 1052 } |
| 1053 conversions_[input_id] = conversion; |
| 1054 } |
| 1055 |
| 1056 |
1025 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { | 1057 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { |
1026 if (rhs == 0) return lhs; | 1058 if (rhs == 0) return lhs; |
1027 return graph()->NewNode(machine()->Word32Shl(), lhs, | 1059 return graph()->NewNode(machine()->Word32Shl(), lhs, |
1028 jsgraph()->Int32Constant(rhs)); | 1060 jsgraph()->Int32Constant(rhs)); |
1029 } | 1061 } |
1030 | 1062 |
1031 | 1063 |
1032 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } | 1064 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } |
1033 | 1065 |
1034 | 1066 |
(...skipping 10 matching lines...) Expand all Loading... |
1045 } | 1077 } |
1046 | 1078 |
1047 | 1079 |
1048 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1080 MachineOperatorBuilder* JSTypedLowering::machine() const { |
1049 return jsgraph()->machine(); | 1081 return jsgraph()->machine(); |
1050 } | 1082 } |
1051 | 1083 |
1052 } // namespace compiler | 1084 } // namespace compiler |
1053 } // namespace internal | 1085 } // namespace internal |
1054 } // namespace v8 | 1086 } // namespace v8 |
OLD | NEW |