| 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 |