| 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/code-factory.h" | 5 #include "src/code-factory.h" |
| 6 #include "src/compiler/access-builder.h" | 6 #include "src/compiler/access-builder.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/linkage.h" | 9 #include "src/compiler/linkage.h" |
| 10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| 11 #include "src/compiler/node-properties.h" | 11 #include "src/compiler/node-properties.h" |
| 12 #include "src/compiler/operator-properties.h" | 12 #include "src/compiler/operator-properties.h" |
| 13 #include "src/types.h" | 13 #include "src/types.h" |
| 14 | 14 |
| 15 namespace v8 { | 15 namespace v8 { |
| 16 namespace internal { | 16 namespace internal { |
| 17 namespace compiler { | 17 namespace compiler { |
| 18 | 18 |
| 19 // TODO(turbofan): js-typed-lowering improvements possible | 19 // TODO(turbofan): js-typed-lowering improvements possible |
| 20 // - immediately put in type bounds for all new nodes | 20 // - immediately put in type bounds for all new nodes |
| 21 // - relax effects from generic but not-side-effecting operations | 21 // - relax effects from generic but not-side-effecting operations |
| 22 | 22 |
| 23 | 23 |
| 24 // Relax the effects of {node} by immediately replacing effect and control uses | 24 JSTypedLowering::JSTypedLowering(Editor* editor, JSGraph* jsgraph, Zone* zone) |
| 25 // of {node} with the effect and control input to {node}. | 25 : AdvancedReducer(editor), jsgraph_(jsgraph), simplified_(graph()->zone()) { |
| 26 // TODO(turbofan): replace the effect input to {node} with {graph->start()}. | |
| 27 // TODO(titzer): move into a GraphEditor? | |
| 28 static void RelaxEffectsAndControls(Node* node) { | |
| 29 NodeProperties::ReplaceWithValue(node, node, NULL); | |
| 30 } | |
| 31 | |
| 32 | |
| 33 // Relax the control uses of {node} by immediately replacing them with the | |
| 34 // control input to {node}. | |
| 35 // TODO(titzer): move into a GraphEditor? | |
| 36 static void RelaxControls(Node* node) { | |
| 37 NodeProperties::ReplaceWithValue(node, node, node); | |
| 38 } | |
| 39 | |
| 40 | |
| 41 JSTypedLowering::JSTypedLowering(JSGraph* jsgraph, Zone* zone) | |
| 42 : jsgraph_(jsgraph), simplified_(graph()->zone()) { | |
| 43 zero_range_ = Type::Range(0.0, 0.0, graph()->zone()); | 26 zero_range_ = Type::Range(0.0, 0.0, graph()->zone()); |
| 44 one_range_ = Type::Range(1.0, 1.0, graph()->zone()); | 27 one_range_ = Type::Range(1.0, 1.0, graph()->zone()); |
| 45 zero_thirtyone_range_ = Type::Range(0.0, 31.0, graph()->zone()); | 28 zero_thirtyone_range_ = Type::Range(0.0, 31.0, graph()->zone()); |
| 46 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { | 29 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { |
| 47 double min = kMinInt / (1 << k); | 30 double min = kMinInt / (1 << k); |
| 48 double max = kMaxInt / (1 << k); | 31 double max = kMaxInt / (1 << k); |
| 49 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); | 32 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); |
| 50 } | 33 } |
| 51 } | 34 } |
| 52 | 35 |
| 53 | 36 |
| 54 Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) { | |
| 55 NodeProperties::ReplaceWithValue(old, node, node); | |
| 56 return Changed(node); | |
| 57 } | |
| 58 | |
| 59 | |
| 60 // A helper class to construct inline allocations on the simplified operator | 37 // A helper class to construct inline allocations on the simplified operator |
| 61 // level. This keeps track of the effect chain for initial stores on a newly | 38 // level. This keeps track of the effect chain for initial stores on a newly |
| 62 // allocated object and also provides helpers for commonly allocated objects. | 39 // allocated object and also provides helpers for commonly allocated objects. |
| 63 class AllocationBuilder final { | 40 class AllocationBuilder final { |
| 64 public: | 41 public: |
| 65 AllocationBuilder(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified, | 42 AllocationBuilder(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified, |
| 66 Node* effect, Node* control) | 43 Node* effect, Node* control) |
| 67 : jsgraph_(jsgraph), | 44 : jsgraph_(jsgraph), |
| 68 simplified_(simplified), | 45 simplified_(simplified), |
| 69 allocation_(nullptr), | 46 allocation_(nullptr), |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 // to the pure operator {op}, possibly inserting a boolean inversion. | 159 // to the pure operator {op}, possibly inserting a boolean inversion. |
| 183 Reduction ChangeToPureOperator(const Operator* op, bool invert = false, | 160 Reduction ChangeToPureOperator(const Operator* op, bool invert = false, |
| 184 Type* type = Type::Any()) { | 161 Type* type = Type::Any()) { |
| 185 DCHECK_EQ(0, op->EffectInputCount()); | 162 DCHECK_EQ(0, op->EffectInputCount()); |
| 186 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); | 163 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); |
| 187 DCHECK_EQ(0, op->ControlInputCount()); | 164 DCHECK_EQ(0, op->ControlInputCount()); |
| 188 DCHECK_EQ(2, op->ValueInputCount()); | 165 DCHECK_EQ(2, op->ValueInputCount()); |
| 189 | 166 |
| 190 // Remove the effects from the node, and update its effect/control usages. | 167 // Remove the effects from the node, and update its effect/control usages. |
| 191 if (node_->op()->EffectInputCount() > 0) { | 168 if (node_->op()->EffectInputCount() > 0) { |
| 192 RelaxEffectsAndControls(node_); | 169 lowering_->RelaxEffectsAndControls(node_); |
| 193 } | 170 } |
| 194 // Remove the inputs corresponding to context, effect, and control. | 171 // Remove the inputs corresponding to context, effect, and control. |
| 195 NodeProperties::RemoveNonValueInputs(node_); | 172 NodeProperties::RemoveNonValueInputs(node_); |
| 196 // Finally, update the operator to the new one. | 173 // Finally, update the operator to the new one. |
| 197 node_->set_op(op); | 174 node_->set_op(op); |
| 198 | 175 |
| 199 // TODO(jarin): Replace the explicit typing hack with a call to some method | 176 // TODO(jarin): Replace the explicit typing hack with a call to some method |
| 200 // that encapsulates changing the operator and re-typing. | 177 // that encapsulates changing the operator and re-typing. |
| 201 Bounds const bounds = NodeProperties::GetBounds(node_); | 178 Bounds const bounds = NodeProperties::GetBounds(node_); |
| 202 NodeProperties::SetBounds(node_, Bounds::NarrowUpper(bounds, type, zone())); | 179 NodeProperties::SetBounds(node_, Bounds::NarrowUpper(bounds, type, zone())); |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 // TODO(turbofan): js-typed-lowering of Equal(boolean) | 520 // TODO(turbofan): js-typed-lowering of Equal(boolean) |
| 544 return NoChange(); | 521 return NoChange(); |
| 545 } | 522 } |
| 546 | 523 |
| 547 | 524 |
| 548 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { | 525 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { |
| 549 JSBinopReduction r(this, node); | 526 JSBinopReduction r(this, node); |
| 550 if (r.left() == r.right()) { | 527 if (r.left() == r.right()) { |
| 551 // x === x is always true if x != NaN | 528 // x === x is always true if x != NaN |
| 552 if (!r.left_type()->Maybe(Type::NaN())) { | 529 if (!r.left_type()->Maybe(Type::NaN())) { |
| 553 return ReplaceEagerly(node, jsgraph()->BooleanConstant(!invert)); | 530 Node* replacement = jsgraph()->BooleanConstant(!invert); |
| 531 Replace(node, replacement); |
| 532 return Replace(replacement); |
| 554 } | 533 } |
| 555 } | 534 } |
| 556 if (r.OneInputCannotBe(Type::NumberOrString())) { | 535 if (r.OneInputCannotBe(Type::NumberOrString())) { |
| 557 // For values with canonical representation (i.e. not string nor number) an | 536 // For values with canonical representation (i.e. not string nor number) an |
| 558 // empty type intersection means the values cannot be strictly equal. | 537 // empty type intersection means the values cannot be strictly equal. |
| 559 if (!r.left_type()->Maybe(r.right_type())) { | 538 if (!r.left_type()->Maybe(r.right_type())) { |
| 560 return ReplaceEagerly(node, jsgraph()->BooleanConstant(invert)); | 539 Node* replacement = jsgraph()->BooleanConstant(invert); |
| 540 Replace(node, replacement); |
| 541 return Replace(replacement); |
| 561 } | 542 } |
| 562 } | 543 } |
| 563 if (r.OneInputIs(Type::Undefined())) { | 544 if (r.OneInputIs(Type::Undefined())) { |
| 564 return r.ChangeToPureOperator( | 545 return r.ChangeToPureOperator( |
| 565 simplified()->ReferenceEqual(Type::Undefined()), invert); | 546 simplified()->ReferenceEqual(Type::Undefined()), invert); |
| 566 } | 547 } |
| 567 if (r.OneInputIs(Type::Null())) { | 548 if (r.OneInputIs(Type::Null())) { |
| 568 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Null()), | 549 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Null()), |
| 569 invert); | 550 invert); |
| 570 } | 551 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 } else if (input_type->Is(Type::String())) { | 589 } else if (input_type->Is(Type::String())) { |
| 609 // JSUnaryNot(x:string) => NumberEqual(x.length,#0) | 590 // JSUnaryNot(x:string) => NumberEqual(x.length,#0) |
| 610 FieldAccess const access = AccessBuilder::ForStringLength(graph()->zone()); | 591 FieldAccess const access = AccessBuilder::ForStringLength(graph()->zone()); |
| 611 // It is safe for the load to be effect-free (i.e. not linked into effect | 592 // It is safe for the load to be effect-free (i.e. not linked into effect |
| 612 // chain) because we assume String::length to be immutable. | 593 // chain) because we assume String::length to be immutable. |
| 613 Node* length = graph()->NewNode(simplified()->LoadField(access), input, | 594 Node* length = graph()->NewNode(simplified()->LoadField(access), input, |
| 614 graph()->start(), graph()->start()); | 595 graph()->start(), graph()->start()); |
| 615 node->set_op(simplified()->NumberEqual()); | 596 node->set_op(simplified()->NumberEqual()); |
| 616 node->ReplaceInput(0, length); | 597 node->ReplaceInput(0, length); |
| 617 node->ReplaceInput(1, jsgraph()->ZeroConstant()); | 598 node->ReplaceInput(1, jsgraph()->ZeroConstant()); |
| 618 NodeProperties::ReplaceWithValue(node, node, length); | 599 ReplaceWithValue(node, node, length); |
| 619 DCHECK_EQ(2, node->InputCount()); | 600 DCHECK_EQ(2, node->InputCount()); |
| 620 return Changed(node); | 601 return Changed(node); |
| 621 } | 602 } |
| 622 return NoChange(); | 603 return NoChange(); |
| 623 } | 604 } |
| 624 | 605 |
| 625 | 606 |
| 626 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { | 607 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { |
| 627 Node* const input = node->InputAt(0); | 608 Node* const input = node->InputAt(0); |
| 628 Type* const input_type = NodeProperties::GetBounds(input).upper; | 609 Type* const input_type = NodeProperties::GetBounds(input).upper; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 // TODO(turbofan): js-typed-lowering of ToNumber(x:string) | 662 // TODO(turbofan): js-typed-lowering of ToNumber(x:string) |
| 682 return NoChange(); | 663 return NoChange(); |
| 683 } | 664 } |
| 684 | 665 |
| 685 | 666 |
| 686 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) { | 667 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) { |
| 687 // Try to reduce the input first. | 668 // Try to reduce the input first. |
| 688 Node* const input = node->InputAt(0); | 669 Node* const input = node->InputAt(0); |
| 689 Reduction reduction = ReduceJSToNumberInput(input); | 670 Reduction reduction = ReduceJSToNumberInput(input); |
| 690 if (reduction.Changed()) { | 671 if (reduction.Changed()) { |
| 691 NodeProperties::ReplaceWithValue(node, reduction.replacement()); | 672 ReplaceWithValue(node, reduction.replacement()); |
| 692 return reduction; | 673 return reduction; |
| 693 } | 674 } |
| 694 Type* const input_type = NodeProperties::GetBounds(input).upper; | 675 Type* const input_type = NodeProperties::GetBounds(input).upper; |
| 695 if (input_type->Is(Type::PlainPrimitive())) { | 676 if (input_type->Is(Type::PlainPrimitive())) { |
| 696 if (NodeProperties::GetContextInput(node) != | 677 if (NodeProperties::GetContextInput(node) != |
| 697 jsgraph()->NoContextConstant() || | 678 jsgraph()->NoContextConstant() || |
| 698 NodeProperties::GetEffectInput(node) != graph()->start() || | 679 NodeProperties::GetEffectInput(node) != graph()->start() || |
| 699 NodeProperties::GetControlInput(node) != graph()->start()) { | 680 NodeProperties::GetControlInput(node) != graph()->start()) { |
| 700 // JSToNumber(x:plain-primitive,context,effect,control) | 681 // JSToNumber(x:plain-primitive,context,effect,control) |
| 701 // => JSToNumber(x,no-context,start,start) | 682 // => JSToNumber(x,no-context,start,start) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 // TODO(turbofan): js-typed-lowering of ToString(x:number) | 715 // TODO(turbofan): js-typed-lowering of ToString(x:number) |
| 735 return NoChange(); | 716 return NoChange(); |
| 736 } | 717 } |
| 737 | 718 |
| 738 | 719 |
| 739 Reduction JSTypedLowering::ReduceJSToString(Node* node) { | 720 Reduction JSTypedLowering::ReduceJSToString(Node* node) { |
| 740 // Try to reduce the input first. | 721 // Try to reduce the input first. |
| 741 Node* const input = node->InputAt(0); | 722 Node* const input = node->InputAt(0); |
| 742 Reduction reduction = ReduceJSToStringInput(input); | 723 Reduction reduction = ReduceJSToStringInput(input); |
| 743 if (reduction.Changed()) { | 724 if (reduction.Changed()) { |
| 744 NodeProperties::ReplaceWithValue(node, reduction.replacement()); | 725 ReplaceWithValue(node, reduction.replacement()); |
| 745 return reduction; | 726 return reduction; |
| 746 } | 727 } |
| 747 return NoChange(); | 728 return NoChange(); |
| 748 } | 729 } |
| 749 | 730 |
| 750 | 731 |
| 751 Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) { | 732 Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) { |
| 752 Node* object = NodeProperties::GetValueInput(node, 0); | 733 Node* object = NodeProperties::GetValueInput(node, 0); |
| 753 Type* object_type = NodeProperties::GetBounds(object).upper; | 734 Type* object_type = NodeProperties::GetBounds(object).upper; |
| 754 if (object_type->Is(Type::GlobalObject())) { | 735 if (object_type->Is(Type::GlobalObject())) { |
| 755 // Optimize global constants like "undefined", "Infinity", and "NaN". | 736 // Optimize global constants like "undefined", "Infinity", and "NaN". |
| 756 Handle<Name> name = LoadNamedParametersOf(node->op()).name().handle(); | 737 Handle<Name> name = LoadNamedParametersOf(node->op()).name().handle(); |
| 757 Handle<Object> constant_value = factory()->GlobalConstantFor(name); | 738 Handle<Object> constant_value = factory()->GlobalConstantFor(name); |
| 758 if (!constant_value.is_null()) { | 739 if (!constant_value.is_null()) { |
| 759 Node* constant = jsgraph()->Constant(constant_value); | 740 Node* constant = jsgraph()->Constant(constant_value); |
| 760 NodeProperties::ReplaceWithValue(node, constant); | 741 ReplaceWithValue(node, constant); |
| 761 return Replace(constant); | 742 return Replace(constant); |
| 762 } | 743 } |
| 763 } | 744 } |
| 764 return NoChange(); | 745 return NoChange(); |
| 765 } | 746 } |
| 766 | 747 |
| 767 | 748 |
| 768 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { | 749 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { |
| 769 Node* key = NodeProperties::GetValueInput(node, 1); | 750 Node* key = NodeProperties::GetValueInput(node, 1); |
| 770 Node* base = NodeProperties::GetValueInput(node, 0); | 751 Node* base = NodeProperties::GetValueInput(node, 0); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 788 Node* length = jsgraph()->Constant(byte_length); | 769 Node* length = jsgraph()->Constant(byte_length); |
| 789 Node* effect = NodeProperties::GetEffectInput(node); | 770 Node* effect = NodeProperties::GetEffectInput(node); |
| 790 Node* control = NodeProperties::GetControlInput(node); | 771 Node* control = NodeProperties::GetControlInput(node); |
| 791 // Check if we can avoid the bounds check. | 772 // Check if we can avoid the bounds check. |
| 792 if (key_type->Min() >= 0 && | 773 if (key_type->Min() >= 0 && |
| 793 key_type->Max() < array->length()->Number()) { | 774 key_type->Max() < array->length()->Number()) { |
| 794 Node* load = graph()->NewNode( | 775 Node* load = graph()->NewNode( |
| 795 simplified()->LoadElement( | 776 simplified()->LoadElement( |
| 796 AccessBuilder::ForTypedArrayElement(array->type(), true)), | 777 AccessBuilder::ForTypedArrayElement(array->type(), true)), |
| 797 buffer, key, effect, control); | 778 buffer, key, effect, control); |
| 798 return ReplaceEagerly(node, load); | 779 ReplaceWithValue(node, load, load); |
| 780 return Replace(load); |
| 799 } | 781 } |
| 800 // Compute byte offset. | 782 // Compute byte offset. |
| 801 Node* offset = Word32Shl(key, static_cast<int>(k)); | 783 Node* offset = Word32Shl(key, static_cast<int>(k)); |
| 802 Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer, | 784 Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer, |
| 803 offset, length, effect, control); | 785 offset, length, effect, control); |
| 804 return ReplaceEagerly(node, load); | 786 ReplaceWithValue(node, load, load); |
| 787 return Replace(load); |
| 805 } | 788 } |
| 806 } | 789 } |
| 807 } | 790 } |
| 808 return NoChange(); | 791 return NoChange(); |
| 809 } | 792 } |
| 810 | 793 |
| 811 | 794 |
| 812 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) { | 795 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) { |
| 813 Node* key = NodeProperties::GetValueInput(node, 1); | 796 Node* key = NodeProperties::GetValueInput(node, 1); |
| 814 Node* base = NodeProperties::GetValueInput(node, 0); | 797 Node* base = NodeProperties::GetValueInput(node, 0); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1032 context, effect, control); | 1015 context, effect, control); |
| 1033 AllocationBuilder a(jsgraph(), simplified(), effect, control); | 1016 AllocationBuilder a(jsgraph(), simplified(), effect, control); |
| 1034 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | 1017 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. |
| 1035 a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map()); | 1018 a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map()); |
| 1036 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | 1019 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); |
| 1037 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | 1020 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); |
| 1038 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); | 1021 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); |
| 1039 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); | 1022 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); |
| 1040 // TODO(mstarzinger): We could mutate {node} into the allocation instead. | 1023 // TODO(mstarzinger): We could mutate {node} into the allocation instead. |
| 1041 NodeProperties::SetBounds(a.allocation(), NodeProperties::GetBounds(node)); | 1024 NodeProperties::SetBounds(a.allocation(), NodeProperties::GetBounds(node)); |
| 1042 NodeProperties::ReplaceWithValue(node, node, a.effect()); | 1025 ReplaceWithValue(node, node, a.effect()); |
| 1043 node->ReplaceInput(0, a.allocation()); | 1026 node->ReplaceInput(0, a.allocation()); |
| 1044 node->ReplaceInput(1, a.effect()); | 1027 node->ReplaceInput(1, a.effect()); |
| 1045 node->set_op(common()->Finish(1)); | 1028 node->set_op(common()->Finish(1)); |
| 1046 node->TrimInputCount(2); | 1029 node->TrimInputCount(2); |
| 1047 return Changed(node); | 1030 return Changed(node); |
| 1048 } | 1031 } |
| 1049 return NoChange(); | 1032 return NoChange(); |
| 1050 } | 1033 } |
| 1051 | 1034 |
| 1052 | 1035 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1071 a.AllocateArray(context_length, factory()->block_context_map()); | 1054 a.AllocateArray(context_length, factory()->block_context_map()); |
| 1072 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | 1055 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); |
| 1073 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | 1056 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); |
| 1074 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); | 1057 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); |
| 1075 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); | 1058 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); |
| 1076 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { | 1059 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { |
| 1077 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant()); | 1060 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant()); |
| 1078 } | 1061 } |
| 1079 // TODO(mstarzinger): We could mutate {node} into the allocation instead. | 1062 // TODO(mstarzinger): We could mutate {node} into the allocation instead. |
| 1080 NodeProperties::SetBounds(a.allocation(), NodeProperties::GetBounds(node)); | 1063 NodeProperties::SetBounds(a.allocation(), NodeProperties::GetBounds(node)); |
| 1081 NodeProperties::ReplaceWithValue(node, node, a.effect()); | 1064 ReplaceWithValue(node, node, a.effect()); |
| 1082 node->ReplaceInput(0, a.allocation()); | 1065 node->ReplaceInput(0, a.allocation()); |
| 1083 node->ReplaceInput(1, a.effect()); | 1066 node->ReplaceInput(1, a.effect()); |
| 1084 node->set_op(common()->Finish(1)); | 1067 node->set_op(common()->Finish(1)); |
| 1085 node->TrimInputCount(2); | 1068 node->TrimInputCount(2); |
| 1086 return Changed(node); | 1069 return Changed(node); |
| 1087 } | 1070 } |
| 1088 return NoChange(); | 1071 return NoChange(); |
| 1089 } | 1072 } |
| 1090 | 1073 |
| 1091 | 1074 |
| 1092 Reduction JSTypedLowering::Reduce(Node* node) { | 1075 Reduction JSTypedLowering::Reduce(Node* node) { |
| 1093 // Check if the output type is a singleton. In that case we already know the | 1076 // Check if the output type is a singleton. In that case we already know the |
| 1094 // result value and can simply replace the node if it's eliminable. | 1077 // result value and can simply replace the node if it's eliminable. |
| 1095 if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) && | 1078 if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) && |
| 1096 node->op()->HasProperty(Operator::kEliminatable)) { | 1079 node->op()->HasProperty(Operator::kEliminatable)) { |
| 1097 Type* upper = NodeProperties::GetBounds(node).upper; | 1080 Type* upper = NodeProperties::GetBounds(node).upper; |
| 1098 if (upper->IsConstant()) { | 1081 if (upper->IsConstant()) { |
| 1099 Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value()); | 1082 Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value()); |
| 1100 NodeProperties::ReplaceWithValue(node, replacement); | 1083 ReplaceWithValue(node, replacement); |
| 1101 return Changed(replacement); | 1084 return Changed(replacement); |
| 1102 } else if (upper->Is(Type::MinusZero())) { | 1085 } else if (upper->Is(Type::MinusZero())) { |
| 1103 Node* replacement = jsgraph()->Constant(factory()->minus_zero_value()); | 1086 Node* replacement = jsgraph()->Constant(factory()->minus_zero_value()); |
| 1104 NodeProperties::ReplaceWithValue(node, replacement); | 1087 ReplaceWithValue(node, replacement); |
| 1105 return Changed(replacement); | 1088 return Changed(replacement); |
| 1106 } else if (upper->Is(Type::NaN())) { | 1089 } else if (upper->Is(Type::NaN())) { |
| 1107 Node* replacement = jsgraph()->NaNConstant(); | 1090 Node* replacement = jsgraph()->NaNConstant(); |
| 1108 NodeProperties::ReplaceWithValue(node, replacement); | 1091 ReplaceWithValue(node, replacement); |
| 1109 return Changed(replacement); | 1092 return Changed(replacement); |
| 1110 } else if (upper->Is(Type::Null())) { | 1093 } else if (upper->Is(Type::Null())) { |
| 1111 Node* replacement = jsgraph()->NullConstant(); | 1094 Node* replacement = jsgraph()->NullConstant(); |
| 1112 NodeProperties::ReplaceWithValue(node, replacement); | 1095 ReplaceWithValue(node, replacement); |
| 1113 return Changed(replacement); | 1096 return Changed(replacement); |
| 1114 } else if (upper->Is(Type::PlainNumber()) && upper->Min() == upper->Max()) { | 1097 } else if (upper->Is(Type::PlainNumber()) && upper->Min() == upper->Max()) { |
| 1115 Node* replacement = jsgraph()->Constant(upper->Min()); | 1098 Node* replacement = jsgraph()->Constant(upper->Min()); |
| 1116 NodeProperties::ReplaceWithValue(node, replacement); | 1099 ReplaceWithValue(node, replacement); |
| 1117 return Changed(replacement); | 1100 return Changed(replacement); |
| 1118 } else if (upper->Is(Type::Undefined())) { | 1101 } else if (upper->Is(Type::Undefined())) { |
| 1119 Node* replacement = jsgraph()->UndefinedConstant(); | 1102 Node* replacement = jsgraph()->UndefinedConstant(); |
| 1120 NodeProperties::ReplaceWithValue(node, replacement); | 1103 ReplaceWithValue(node, replacement); |
| 1121 return Changed(replacement); | 1104 return Changed(replacement); |
| 1122 } | 1105 } |
| 1123 } | 1106 } |
| 1124 switch (node->opcode()) { | 1107 switch (node->opcode()) { |
| 1125 case IrOpcode::kJSEqual: | 1108 case IrOpcode::kJSEqual: |
| 1126 return ReduceJSEqual(node, false); | 1109 return ReduceJSEqual(node, false); |
| 1127 case IrOpcode::kJSNotEqual: | 1110 case IrOpcode::kJSNotEqual: |
| 1128 return ReduceJSEqual(node, true); | 1111 return ReduceJSEqual(node, true); |
| 1129 case IrOpcode::kJSStrictEqual: | 1112 case IrOpcode::kJSStrictEqual: |
| 1130 return ReduceJSStrictEqual(node, false); | 1113 return ReduceJSStrictEqual(node, false); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1215 } | 1198 } |
| 1216 | 1199 |
| 1217 | 1200 |
| 1218 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1201 MachineOperatorBuilder* JSTypedLowering::machine() const { |
| 1219 return jsgraph()->machine(); | 1202 return jsgraph()->machine(); |
| 1220 } | 1203 } |
| 1221 | 1204 |
| 1222 } // namespace compiler | 1205 } // namespace compiler |
| 1223 } // namespace internal | 1206 } // namespace internal |
| 1224 } // namespace v8 | 1207 } // namespace v8 |
| OLD | NEW |