| 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/js-graph.h" | 6 #include "src/compiler/js-graph.h" |
| 7 #include "src/compiler/js-typed-lowering.h" | 7 #include "src/compiler/js-typed-lowering.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
| 10 #include "src/compiler/operator-properties.h" | 10 #include "src/compiler/operator-properties.h" |
| 11 #include "src/types.h" | 11 #include "src/types.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 namespace compiler { | 15 namespace compiler { |
| 16 | 16 |
| 17 // TODO(turbofan): js-typed-lowering improvements possible | 17 // TODO(turbofan): js-typed-lowering improvements possible |
| 18 // - immediately put in type bounds for all new nodes | 18 // - immediately put in type bounds for all new nodes |
| 19 // - relax effects from generic but not-side-effecting operations | 19 // - relax effects from generic but not-side-effecting operations |
| 20 | 20 |
| 21 | 21 |
| 22 // Relax the effects of {node} by immediately replacing effect uses of {node} | 22 // Relax the effects of {node} by immediately replacing effect and control uses |
| 23 // with the effect input to {node}. | 23 // of {node} with the effect and control input to {node}. |
| 24 // TODO(turbofan): replace the effect input to {node} with {graph->start()}. | 24 // TODO(turbofan): replace the effect input to {node} with {graph->start()}. |
| 25 // TODO(titzer): move into a GraphEditor? | 25 // TODO(titzer): move into a GraphEditor? |
| 26 static void RelaxEffects(Node* node) { | 26 static void RelaxEffectsAndControls(Node* node) { |
| 27 NodeProperties::ReplaceWithValue(node, node, NULL); | 27 NodeProperties::ReplaceWithValue(node, node, NULL); |
| 28 } | 28 } |
| 29 | 29 |
| 30 | 30 |
| 31 // Relax the control uses of {node} by immediately replacing them with the |
| 32 // control input to {node}. |
| 33 // TODO(titzer): move into a GraphEditor? |
| 34 static void RelaxControls(Node* node) { |
| 35 NodeProperties::ReplaceWithValue(node, node, node); |
| 36 } |
| 37 |
| 38 |
| 31 JSTypedLowering::JSTypedLowering(JSGraph* jsgraph, Zone* zone) | 39 JSTypedLowering::JSTypedLowering(JSGraph* jsgraph, Zone* zone) |
| 32 : jsgraph_(jsgraph), simplified_(graph()->zone()), conversions_(zone) { | 40 : jsgraph_(jsgraph), simplified_(graph()->zone()), conversions_(zone) { |
| 33 zero_range_ = Type::Range(0.0, 1.0, graph()->zone()); | 41 zero_range_ = Type::Range(0.0, 1.0, graph()->zone()); |
| 34 one_range_ = Type::Range(1.0, 1.0, graph()->zone()); | 42 one_range_ = Type::Range(1.0, 1.0, graph()->zone()); |
| 35 zero_thirtyone_range_ = Type::Range(0.0, 31.0, graph()->zone()); | 43 zero_thirtyone_range_ = Type::Range(0.0, 31.0, graph()->zone()); |
| 36 // TODO(jarin): Can we have a correctification of the stupid type system? | 44 // TODO(jarin): Can we have a correctification of the stupid type system? |
| 37 // These stupid work-arounds are just stupid! | 45 // These stupid work-arounds are just stupid! |
| 38 shifted_int32_ranges_[0] = Type::Signed32(); | 46 shifted_int32_ranges_[0] = Type::Signed32(); |
| 39 if (SmiValuesAre31Bits()) { | 47 if (SmiValuesAre31Bits()) { |
| 40 shifted_int32_ranges_[1] = Type::SignedSmall(); | 48 shifted_int32_ranges_[1] = Type::SignedSmall(); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 | 117 |
| 110 // Remove all effect and control inputs and outputs to this node and change | 118 // Remove all effect and control inputs and outputs to this node and change |
| 111 // to the pure operator {op}, possibly inserting a boolean inversion. | 119 // to the pure operator {op}, possibly inserting a boolean inversion. |
| 112 Reduction ChangeToPureOperator(const Operator* op, bool invert = false, | 120 Reduction ChangeToPureOperator(const Operator* op, bool invert = false, |
| 113 Type* type = Type::Any()) { | 121 Type* type = Type::Any()) { |
| 114 DCHECK_EQ(0, op->EffectInputCount()); | 122 DCHECK_EQ(0, op->EffectInputCount()); |
| 115 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); | 123 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); |
| 116 DCHECK_EQ(0, op->ControlInputCount()); | 124 DCHECK_EQ(0, op->ControlInputCount()); |
| 117 DCHECK_EQ(2, op->ValueInputCount()); | 125 DCHECK_EQ(2, op->ValueInputCount()); |
| 118 | 126 |
| 119 // Remove the effects from the node, if any, and update its effect usages. | 127 // Remove the effects from the node, and update its effect/control usages. |
| 120 if (node_->op()->EffectInputCount() > 0) { | 128 if (node_->op()->EffectInputCount() > 0) { |
| 121 RelaxEffects(node_); | 129 RelaxEffectsAndControls(node_); |
| 122 } | 130 } |
| 123 // Remove the inputs corresponding to context, effect, and control. | 131 // Remove the inputs corresponding to context, effect, and control. |
| 124 NodeProperties::RemoveNonValueInputs(node_); | 132 NodeProperties::RemoveNonValueInputs(node_); |
| 125 // Finally, update the operator to the new one. | 133 // Finally, update the operator to the new one. |
| 126 node_->set_op(op); | 134 node_->set_op(op); |
| 127 | 135 |
| 128 // TODO(jarin): Replace the explicit typing hack with a call to some method | 136 // TODO(jarin): Replace the explicit typing hack with a call to some method |
| 129 // that encapsulates changing the operator and re-typing. | 137 // that encapsulates changing the operator and re-typing. |
| 130 Bounds const bounds = NodeProperties::GetBounds(node_); | 138 Bounds const bounds = NodeProperties::GetBounds(node_); |
| 131 NodeProperties::SetBounds(node_, Bounds::NarrowUpper(bounds, type, zone())); | 139 NodeProperties::SetBounds(node_, Bounds::NarrowUpper(bounds, type, zone())); |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 // JSToNumber(phi(x1,...,xn,control):plain-primitive,context) | 585 // JSToNumber(phi(x1,...,xn,control):plain-primitive,context) |
| 578 // => phi(JSToNumber(x1,no-context), | 586 // => phi(JSToNumber(x1,no-context), |
| 579 // ..., | 587 // ..., |
| 580 // JSToNumber(xn,no-context),control) | 588 // JSToNumber(xn,no-context),control) |
| 581 int const input_count = input->InputCount() - 1; | 589 int const input_count = input->InputCount() - 1; |
| 582 Node* const control = input->InputAt(input_count); | 590 Node* const control = input->InputAt(input_count); |
| 583 DCHECK_LE(0, input_count); | 591 DCHECK_LE(0, input_count); |
| 584 DCHECK(NodeProperties::IsControl(control)); | 592 DCHECK(NodeProperties::IsControl(control)); |
| 585 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); | 593 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); |
| 586 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); | 594 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); |
| 587 RelaxEffects(node); | 595 RelaxEffectsAndControls(node); |
| 588 node->set_op(common()->Phi(kMachAnyTagged, input_count)); | 596 node->set_op(common()->Phi(kMachAnyTagged, input_count)); |
| 589 for (int i = 0; i < input_count; ++i) { | 597 for (int i = 0; i < input_count; ++i) { |
| 590 // We must be very careful not to introduce cycles when pushing | 598 // We must be very careful not to introduce cycles when pushing |
| 591 // operations into phis. It is safe for {value}, since it appears | 599 // operations into phis. It is safe for {value}, since it appears |
| 592 // as input to the phi that we are replacing, but it's not safe | 600 // as input to the phi that we are replacing, but it's not safe |
| 593 // to simply reuse the context of the {node}. However, ToNumber() | 601 // to simply reuse the context of the {node}. However, ToNumber() |
| 594 // does not require a context anyways, so it's safe to discard it | 602 // does not require a context anyways, so it's safe to discard it |
| 595 // here and pass the dummy context. | 603 // here and pass the dummy context. |
| 596 Node* const value = ConvertToNumber(input->InputAt(i)); | 604 Node* const value = ConvertToNumber(input->InputAt(i)); |
| 597 if (i < node->InputCount()) { | 605 if (i < node->InputCount()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 609 return Changed(node); | 617 return Changed(node); |
| 610 } | 618 } |
| 611 if (input->opcode() == IrOpcode::kSelect) { | 619 if (input->opcode() == IrOpcode::kSelect) { |
| 612 // JSToNumber(select(c,x1,x2):plain-primitive,context) | 620 // JSToNumber(select(c,x1,x2):plain-primitive,context) |
| 613 // => select(c,JSToNumber(x1,no-context),JSToNumber(x2,no-context)) | 621 // => select(c,JSToNumber(x1,no-context),JSToNumber(x2,no-context)) |
| 614 int const input_count = input->InputCount(); | 622 int const input_count = input->InputCount(); |
| 615 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); | 623 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); |
| 616 DCHECK_EQ(3, input_count); | 624 DCHECK_EQ(3, input_count); |
| 617 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); | 625 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); |
| 618 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); | 626 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); |
| 619 RelaxEffects(node); | 627 RelaxEffectsAndControls(node); |
| 620 node->set_op(common()->Select(kMachAnyTagged, input_hint)); | 628 node->set_op(common()->Select(kMachAnyTagged, input_hint)); |
| 621 node->ReplaceInput(0, input->InputAt(0)); | 629 node->ReplaceInput(0, input->InputAt(0)); |
| 622 for (int i = 1; i < input_count; ++i) { | 630 for (int i = 1; i < input_count; ++i) { |
| 623 // We must be very careful not to introduce cycles when pushing | 631 // We must be very careful not to introduce cycles when pushing |
| 624 // operations into selects. It is safe for {value}, since it appears | 632 // operations into selects. It is safe for {value}, since it appears |
| 625 // as input to the select that we are replacing, but it's not safe | 633 // as input to the select that we are replacing, but it's not safe |
| 626 // to simply reuse the context of the {node}. However, ToNumber() | 634 // to simply reuse the context of the {node}. However, ToNumber() |
| 627 // does not require a context anyways, so it's safe to discard it | 635 // does not require a context anyways, so it's safe to discard it |
| 628 // here and pass the dummy context. | 636 // here and pass the dummy context. |
| 629 Node* const value = ConvertToNumber(input->InputAt(i)); | 637 Node* const value = ConvertToNumber(input->InputAt(i)); |
| 630 node->ReplaceInput(i, value); | 638 node->ReplaceInput(i, value); |
| 631 } | 639 } |
| 632 node->TrimInputCount(input_count); | 640 node->TrimInputCount(input_count); |
| 633 return Changed(node); | 641 return Changed(node); |
| 634 } | 642 } |
| 635 // Remember this conversion. | 643 // Remember this conversion. |
| 636 InsertConversion(node); | 644 InsertConversion(node); |
| 637 if (NodeProperties::GetContextInput(node) != | 645 if (NodeProperties::GetContextInput(node) != |
| 638 jsgraph()->NoContextConstant() || | 646 jsgraph()->NoContextConstant() || |
| 639 NodeProperties::GetEffectInput(node) != graph()->start() || | 647 NodeProperties::GetEffectInput(node) != graph()->start() || |
| 640 NodeProperties::GetControlInput(node) != graph()->start()) { | 648 NodeProperties::GetControlInput(node) != graph()->start()) { |
| 641 // JSToNumber(x:plain-primitive,context,effect,control) | 649 // JSToNumber(x:plain-primitive,context,effect,control) |
| 642 // => JSToNumber(x,no-context,start,start) | 650 // => JSToNumber(x,no-context,start,start) |
| 643 RelaxEffects(node); | 651 RelaxEffectsAndControls(node); |
| 644 NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); | 652 NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); |
| 645 NodeProperties::ReplaceControlInput(node, graph()->start()); | 653 NodeProperties::ReplaceControlInput(node, graph()->start()); |
| 646 NodeProperties::ReplaceEffectInput(node, graph()->start()); | 654 NodeProperties::ReplaceEffectInput(node, graph()->start()); |
| 647 if (OperatorProperties::HasFrameStateInput(node->op())) { | 655 if (OperatorProperties::HasFrameStateInput(node->op())) { |
| 648 NodeProperties::ReplaceFrameStateInput(node, | 656 NodeProperties::ReplaceFrameStateInput(node, |
| 649 jsgraph()->EmptyFrameState()); | 657 jsgraph()->EmptyFrameState()); |
| 650 } | 658 } |
| 651 return Changed(node); | 659 return Changed(node); |
| 652 } | 660 } |
| 653 } | 661 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 789 // Check if we can avoid the bounds check. | 797 // Check if we can avoid the bounds check. |
| 790 if (key_type->Min() >= 0 && key_type->Max() < array->length()->Number()) { | 798 if (key_type->Min() >= 0 && key_type->Max() < array->length()->Number()) { |
| 791 node->set_op(simplified()->StoreElement( | 799 node->set_op(simplified()->StoreElement( |
| 792 AccessBuilder::ForTypedArrayElement(array->type(), true))); | 800 AccessBuilder::ForTypedArrayElement(array->type(), true))); |
| 793 node->ReplaceInput(0, buffer); | 801 node->ReplaceInput(0, buffer); |
| 794 DCHECK_EQ(key, node->InputAt(1)); | 802 DCHECK_EQ(key, node->InputAt(1)); |
| 795 node->ReplaceInput(2, value); | 803 node->ReplaceInput(2, value); |
| 796 node->ReplaceInput(3, effect); | 804 node->ReplaceInput(3, effect); |
| 797 node->ReplaceInput(4, control); | 805 node->ReplaceInput(4, control); |
| 798 node->TrimInputCount(5); | 806 node->TrimInputCount(5); |
| 807 RelaxControls(node); |
| 799 return Changed(node); | 808 return Changed(node); |
| 800 } | 809 } |
| 801 // Compute byte offset. | 810 // Compute byte offset. |
| 802 Node* offset = Word32Shl(key, static_cast<int>(k)); | 811 Node* offset = Word32Shl(key, static_cast<int>(k)); |
| 803 // Turn into a StoreBuffer operation. | 812 // Turn into a StoreBuffer operation. |
| 804 node->set_op(simplified()->StoreBuffer(access)); | 813 node->set_op(simplified()->StoreBuffer(access)); |
| 805 node->ReplaceInput(0, buffer); | 814 node->ReplaceInput(0, buffer); |
| 806 node->ReplaceInput(1, offset); | 815 node->ReplaceInput(1, offset); |
| 807 node->ReplaceInput(2, length); | 816 node->ReplaceInput(2, length); |
| 808 node->ReplaceInput(3, value); | 817 node->ReplaceInput(3, value); |
| 809 node->ReplaceInput(4, effect); | 818 node->ReplaceInput(4, effect); |
| 810 node->ReplaceInput(5, control); | 819 node->ReplaceInput(5, control); |
| 811 node->TrimInputCount(6); | 820 node->TrimInputCount(6); |
| 821 RelaxControls(node); |
| 812 return Changed(node); | 822 return Changed(node); |
| 813 } | 823 } |
| 814 } | 824 } |
| 815 return NoChange(); | 825 return NoChange(); |
| 816 } | 826 } |
| 817 | 827 |
| 818 | 828 |
| 819 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { | 829 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { |
| 820 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); | 830 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); |
| 821 ContextAccess const& access = ContextAccessOf(node->op()); | 831 ContextAccess const& access = ContextAccessOf(node->op()); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1014 } | 1024 } |
| 1015 | 1025 |
| 1016 | 1026 |
| 1017 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1027 MachineOperatorBuilder* JSTypedLowering::machine() const { |
| 1018 return jsgraph()->machine(); | 1028 return jsgraph()->machine(); |
| 1019 } | 1029 } |
| 1020 | 1030 |
| 1021 } // namespace compiler | 1031 } // namespace compiler |
| 1022 } // namespace internal | 1032 } // namespace internal |
| 1023 } // namespace v8 | 1033 } // namespace v8 |
| OLD | NEW |