OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/effect-control-linearizer.h" | 5 #include "src/compiler/effect-control-linearizer.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 break; | 719 break; |
720 case IrOpcode::kPlainPrimitiveToWord32: | 720 case IrOpcode::kPlainPrimitiveToWord32: |
721 state = LowerPlainPrimitiveToWord32(node, *effect, *control); | 721 state = LowerPlainPrimitiveToWord32(node, *effect, *control); |
722 break; | 722 break; |
723 case IrOpcode::kPlainPrimitiveToFloat64: | 723 case IrOpcode::kPlainPrimitiveToFloat64: |
724 state = LowerPlainPrimitiveToFloat64(node, *effect, *control); | 724 state = LowerPlainPrimitiveToFloat64(node, *effect, *control); |
725 break; | 725 break; |
726 case IrOpcode::kEnsureWritableFastElements: | 726 case IrOpcode::kEnsureWritableFastElements: |
727 state = LowerEnsureWritableFastElements(node, *effect, *control); | 727 state = LowerEnsureWritableFastElements(node, *effect, *control); |
728 break; | 728 break; |
| 729 case IrOpcode::kMaybeGrowFastElements: |
| 730 state = LowerMaybeGrowFastElements(node, frame_state, *effect, *control); |
| 731 break; |
729 case IrOpcode::kTransitionElementsKind: | 732 case IrOpcode::kTransitionElementsKind: |
730 state = LowerTransitionElementsKind(node, *effect, *control); | 733 state = LowerTransitionElementsKind(node, *effect, *control); |
731 break; | 734 break; |
732 case IrOpcode::kLoadTypedElement: | 735 case IrOpcode::kLoadTypedElement: |
733 state = LowerLoadTypedElement(node, *effect, *control); | 736 state = LowerLoadTypedElement(node, *effect, *control); |
734 break; | 737 break; |
735 case IrOpcode::kStoreTypedElement: | 738 case IrOpcode::kStoreTypedElement: |
736 state = LowerStoreTypedElement(node, *effect, *control); | 739 state = LowerStoreTypedElement(node, *effect, *control); |
737 break; | 740 break; |
738 case IrOpcode::kFloat64RoundUp: | 741 case IrOpcode::kFloat64RoundUp: |
(...skipping 1886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2625 Node* etrue = effect; | 2628 Node* etrue = effect; |
2626 Node* vtrue = elements; | 2629 Node* vtrue = elements; |
2627 | 2630 |
2628 // We need to take a copy of the {elements} and set them up for {object}. | 2631 // We need to take a copy of the {elements} and set them up for {object}. |
2629 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 2632 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
2630 Node* efalse = effect; | 2633 Node* efalse = effect; |
2631 Node* vfalse; | 2634 Node* vfalse; |
2632 { | 2635 { |
2633 // We need to create a copy of the {elements} for {object}. | 2636 // We need to create a copy of the {elements} for {object}. |
2634 Operator::Properties properties = Operator::kEliminatable; | 2637 Operator::Properties properties = Operator::kEliminatable; |
2635 Callable callable = CodeFactory::CopyFixedArray(isolate()); | 2638 Callable callable = CodeFactory::CopyFastSmiOrObjectElements(isolate()); |
2636 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 2639 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
2637 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( | 2640 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( |
2638 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 2641 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
2639 properties); | 2642 properties); |
2640 vfalse = efalse = graph()->NewNode( | 2643 vfalse = efalse = graph()->NewNode( |
2641 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), | 2644 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), object, |
2642 elements, jsgraph()->NoContextConstant(), efalse); | 2645 jsgraph()->NoContextConstant(), efalse); |
2643 | |
2644 // Store the new {elements} into {object}. | |
2645 efalse = graph()->NewNode( | |
2646 simplified()->StoreField(AccessBuilder::ForJSObjectElements()), object, | |
2647 vfalse, efalse, if_false); | |
2648 } | 2646 } |
2649 | 2647 |
2650 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | 2648 control = graph()->NewNode(common()->Merge(2), if_true, if_false); |
2651 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | 2649 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); |
2652 Node* value = graph()->NewNode( | 2650 Node* value = graph()->NewNode( |
2653 common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control); | 2651 common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control); |
2654 | 2652 |
2655 return ValueEffectControl(value, effect, control); | 2653 return ValueEffectControl(value, effect, control); |
2656 } | 2654 } |
2657 | 2655 |
2658 EffectControlLinearizer::ValueEffectControl | 2656 EffectControlLinearizer::ValueEffectControl |
| 2657 EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node, |
| 2658 Node* frame_state, |
| 2659 Node* effect, |
| 2660 Node* control) { |
| 2661 GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op()); |
| 2662 Node* object = node->InputAt(0); |
| 2663 Node* elements = node->InputAt(1); |
| 2664 Node* index = node->InputAt(2); |
| 2665 Node* length = node->InputAt(3); |
| 2666 |
| 2667 Node* check0 = graph()->NewNode((flags & GrowFastElementsFlag::kHoleyElements) |
| 2668 ? machine()->Uint32LessThanOrEqual() |
| 2669 : machine()->Word32Equal(), |
| 2670 length, index); |
| 2671 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); |
| 2672 |
| 2673 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 2674 Node* etrue0 = effect; |
| 2675 Node* vtrue0 = elements; |
| 2676 { |
| 2677 // Load the length of the {elements} backing store. |
| 2678 Node* elements_length = etrue0 = graph()->NewNode( |
| 2679 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), elements, |
| 2680 etrue0, if_true0); |
| 2681 elements_length = ChangeSmiToInt32(elements_length); |
| 2682 |
| 2683 // Check if we need to grow the {elements} backing store. |
| 2684 Node* check1 = |
| 2685 graph()->NewNode(machine()->Uint32LessThan(), index, elements_length); |
| 2686 Node* branch1 = |
| 2687 graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0); |
| 2688 |
| 2689 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 2690 Node* etrue1 = etrue0; |
| 2691 Node* vtrue1 = vtrue0; |
| 2692 |
| 2693 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 2694 Node* efalse1 = etrue0; |
| 2695 Node* vfalse1 = vtrue0; |
| 2696 { |
| 2697 // We need to grow the {elements} for {object}. |
| 2698 Operator::Properties properties = Operator::kEliminatable; |
| 2699 Callable callable = |
| 2700 (flags & GrowFastElementsFlag::kDoubleElements) |
| 2701 ? CodeFactory::GrowFastDoubleElements(isolate()) |
| 2702 : CodeFactory::GrowFastSmiOrObjectElements(isolate()); |
| 2703 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
| 2704 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( |
| 2705 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 2706 properties); |
| 2707 vfalse1 = efalse1 = graph()->NewNode( |
| 2708 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), |
| 2709 object, ChangeInt32ToSmi(index), jsgraph()->NoContextConstant(), |
| 2710 efalse1); |
| 2711 |
| 2712 // Ensure that we were able to grow the {elements}. |
| 2713 // TODO(turbofan): We use kSmi as reason here similar to Crankshaft, |
| 2714 // but maybe we should just introduce a reason that makes sense. |
| 2715 efalse1 = if_false1 = graph()->NewNode( |
| 2716 common()->DeoptimizeIf(DeoptimizeReason::kSmi), ObjectIsSmi(vfalse1), |
| 2717 frame_state, efalse1, if_false1); |
| 2718 } |
| 2719 |
| 2720 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 2721 etrue0 = |
| 2722 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); |
| 2723 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
| 2724 vtrue1, vfalse1, if_true0); |
| 2725 |
| 2726 // For JSArray {object}s we also need to update the "length". |
| 2727 if (flags & GrowFastElementsFlag::kArrayObject) { |
| 2728 // Compute the new {length}. |
| 2729 Node* object_length = ChangeInt32ToSmi(graph()->NewNode( |
| 2730 machine()->Int32Add(), index, jsgraph()->Int32Constant(1))); |
| 2731 |
| 2732 // Update the "length" property of the {object}. |
| 2733 etrue0 = |
| 2734 graph()->NewNode(simplified()->StoreField( |
| 2735 AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)), |
| 2736 object, object_length, etrue0, if_true0); |
| 2737 } |
| 2738 } |
| 2739 |
| 2740 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
| 2741 Node* efalse0 = effect; |
| 2742 Node* vfalse0 = elements; |
| 2743 { |
| 2744 // In case of non-holey {elements}, we need to verify that the {index} is |
| 2745 // in-bounds, otherwise for holey {elements}, the check above already |
| 2746 // guards the index (and the operator forces {index} to be unsigned). |
| 2747 if (!(flags & GrowFastElementsFlag::kHoleyElements)) { |
| 2748 Node* check1 = |
| 2749 graph()->NewNode(machine()->Uint32LessThan(), index, length); |
| 2750 efalse0 = if_false0 = graph()->NewNode( |
| 2751 common()->DeoptimizeUnless(DeoptimizeReason::kOutOfBounds), check1, |
| 2752 frame_state, efalse0, if_false0); |
| 2753 } |
| 2754 } |
| 2755 |
| 2756 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 2757 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); |
| 2758 Node* value = |
| 2759 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), vtrue0, |
| 2760 vfalse0, control); |
| 2761 |
| 2762 return ValueEffectControl(value, effect, control); |
| 2763 } |
| 2764 |
| 2765 EffectControlLinearizer::ValueEffectControl |
2659 EffectControlLinearizer::LowerTransitionElementsKind(Node* node, Node* effect, | 2766 EffectControlLinearizer::LowerTransitionElementsKind(Node* node, Node* effect, |
2660 Node* control) { | 2767 Node* control) { |
2661 ElementsTransition const transition = ElementsTransitionOf(node->op()); | 2768 ElementsTransition const transition = ElementsTransitionOf(node->op()); |
2662 Node* object = node->InputAt(0); | 2769 Node* object = node->InputAt(0); |
2663 Node* source_map = node->InputAt(1); | 2770 Node* source_map = node->InputAt(1); |
2664 Node* target_map = node->InputAt(2); | 2771 Node* target_map = node->InputAt(2); |
2665 | 2772 |
2666 // Load the current map of {object}. | 2773 // Load the current map of {object}. |
2667 Node* object_map = effect = | 2774 Node* object_map = effect = |
2668 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), object, | 2775 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), object, |
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3167 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3274 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
3168 Operator::kNoThrow); | 3275 Operator::kNoThrow); |
3169 to_number_operator_.set(common()->Call(desc)); | 3276 to_number_operator_.set(common()->Call(desc)); |
3170 } | 3277 } |
3171 return to_number_operator_.get(); | 3278 return to_number_operator_.get(); |
3172 } | 3279 } |
3173 | 3280 |
3174 } // namespace compiler | 3281 } // namespace compiler |
3175 } // namespace internal | 3282 } // namespace internal |
3176 } // namespace v8 | 3283 } // namespace v8 |
OLD | NEW |