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" |
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 if (reduction.Changed()) { | 779 if (reduction.Changed()) { |
780 ReplaceWithValue(node, reduction.replacement()); | 780 ReplaceWithValue(node, reduction.replacement()); |
781 return reduction; | 781 return reduction; |
782 } | 782 } |
783 return NoChange(); | 783 return NoChange(); |
784 } | 784 } |
785 | 785 |
786 | 786 |
787 Reduction JSTypedLowering::ReduceJSLoadGlobal(Node* node) { | 787 Reduction JSTypedLowering::ReduceJSLoadGlobal(Node* node) { |
788 // Optimize global constants like "undefined", "Infinity", and "NaN". | 788 // Optimize global constants like "undefined", "Infinity", and "NaN". |
789 Handle<Name> name = LoadGlobalParametersOf(node->op()).name().handle(); | 789 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); |
790 Handle<Object> constant_value = factory()->GlobalConstantFor(name); | 790 Handle<Object> constant_value = factory()->GlobalConstantFor(name); |
791 if (!constant_value.is_null()) { | 791 if (!constant_value.is_null()) { |
792 Node* constant = jsgraph()->Constant(constant_value); | 792 Node* constant = jsgraph()->Constant(constant_value); |
793 ReplaceWithValue(node, constant); | 793 ReplaceWithValue(node, constant); |
794 return Replace(constant); | 794 return Replace(constant); |
795 } | 795 } |
796 return NoChange(); | 796 return NoChange(); |
797 } | 797 } |
798 | 798 |
799 | 799 |
800 Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) { | 800 Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) { |
801 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); | 801 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); |
802 Node* receiver = NodeProperties::GetValueInput(node, 0); | 802 Node* receiver = NodeProperties::GetValueInput(node, 0); |
803 Type* receiver_type = NodeProperties::GetBounds(receiver).upper; | 803 Type* receiver_type = NodeProperties::GetBounds(receiver).upper; |
804 Node* effect = NodeProperties::GetEffectInput(node); | 804 Node* effect = NodeProperties::GetEffectInput(node); |
805 Node* control = NodeProperties::GetControlInput(node); | 805 Node* control = NodeProperties::GetControlInput(node); |
806 Handle<Name> name = LoadNamedParametersOf(node->op()).name().handle(); | 806 Handle<Name> name = LoadNamedParametersOf(node->op()).name(); |
807 // Optimize "length" property of strings. | 807 // Optimize "length" property of strings. |
808 if (name.is_identical_to(factory()->length_string()) && | 808 if (name.is_identical_to(factory()->length_string()) && |
809 receiver_type->Is(Type::String())) { | 809 receiver_type->Is(Type::String())) { |
810 Node* value = effect = | 810 Node* value = effect = |
811 graph()->NewNode(simplified()->LoadField( | 811 graph()->NewNode(simplified()->LoadField( |
812 AccessBuilder::ForStringLength(graph()->zone())), | 812 AccessBuilder::ForStringLength(graph()->zone())), |
813 receiver, effect, control); | 813 receiver, effect, control); |
814 ReplaceWithValue(node, value, effect); | 814 ReplaceWithValue(node, value, effect); |
815 return Replace(value); | 815 return Replace(value); |
816 } | 816 } |
817 return NoChange(); | 817 return NoChange(); |
818 } | 818 } |
819 | 819 |
820 | 820 |
821 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { | 821 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { |
822 Node* key = NodeProperties::GetValueInput(node, 1); | 822 Node* key = NodeProperties::GetValueInput(node, 1); |
823 Node* base = NodeProperties::GetValueInput(node, 0); | 823 Node* base = NodeProperties::GetValueInput(node, 0); |
824 Type* key_type = NodeProperties::GetBounds(key).upper; | 824 Type* key_type = NodeProperties::GetBounds(key).upper; |
825 HeapObjectMatcher mbase(base); | 825 HeapObjectMatcher mbase(base); |
826 if (mbase.HasValue() && mbase.Value().handle()->IsJSTypedArray()) { | 826 if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) { |
827 Handle<JSTypedArray> const array = | 827 Handle<JSTypedArray> const array = |
828 Handle<JSTypedArray>::cast(mbase.Value().handle()); | 828 Handle<JSTypedArray>::cast(mbase.Value()); |
829 if (!array->GetBuffer()->was_neutered()) { | 829 if (!array->GetBuffer()->was_neutered()) { |
830 array->GetBuffer()->set_is_neuterable(false); | 830 array->GetBuffer()->set_is_neuterable(false); |
831 BufferAccess const access(array->type()); | 831 BufferAccess const access(array->type()); |
832 size_t const k = ElementSizeLog2Of(access.machine_type()); | 832 size_t const k = ElementSizeLog2Of(access.machine_type()); |
833 double const byte_length = array->byte_length()->Number(); | 833 double const byte_length = array->byte_length()->Number(); |
834 CHECK_LT(k, arraysize(shifted_int32_ranges_)); | 834 CHECK_LT(k, arraysize(shifted_int32_ranges_)); |
835 if (key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { | 835 if (key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { |
836 // JSLoadProperty(typed-array, int32) | 836 // JSLoadProperty(typed-array, int32) |
837 Handle<FixedTypedArrayBase> elements = | 837 Handle<FixedTypedArrayBase> elements = |
838 Handle<FixedTypedArrayBase>::cast(handle(array->elements())); | 838 Handle<FixedTypedArrayBase>::cast(handle(array->elements())); |
(...skipping 23 matching lines...) Expand all Loading... |
862 } | 862 } |
863 | 863 |
864 | 864 |
865 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) { | 865 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) { |
866 Node* key = NodeProperties::GetValueInput(node, 1); | 866 Node* key = NodeProperties::GetValueInput(node, 1); |
867 Node* base = NodeProperties::GetValueInput(node, 0); | 867 Node* base = NodeProperties::GetValueInput(node, 0); |
868 Node* value = NodeProperties::GetValueInput(node, 2); | 868 Node* value = NodeProperties::GetValueInput(node, 2); |
869 Type* key_type = NodeProperties::GetBounds(key).upper; | 869 Type* key_type = NodeProperties::GetBounds(key).upper; |
870 Type* value_type = NodeProperties::GetBounds(value).upper; | 870 Type* value_type = NodeProperties::GetBounds(value).upper; |
871 HeapObjectMatcher mbase(base); | 871 HeapObjectMatcher mbase(base); |
872 if (mbase.HasValue() && mbase.Value().handle()->IsJSTypedArray()) { | 872 if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) { |
873 Handle<JSTypedArray> const array = | 873 Handle<JSTypedArray> const array = |
874 Handle<JSTypedArray>::cast(mbase.Value().handle()); | 874 Handle<JSTypedArray>::cast(mbase.Value()); |
875 if (!array->GetBuffer()->was_neutered()) { | 875 if (!array->GetBuffer()->was_neutered()) { |
876 array->GetBuffer()->set_is_neuterable(false); | 876 array->GetBuffer()->set_is_neuterable(false); |
877 BufferAccess const access(array->type()); | 877 BufferAccess const access(array->type()); |
878 size_t const k = ElementSizeLog2Of(access.machine_type()); | 878 size_t const k = ElementSizeLog2Of(access.machine_type()); |
879 double const byte_length = array->byte_length()->Number(); | 879 double const byte_length = array->byte_length()->Number(); |
880 CHECK_LT(k, arraysize(shifted_int32_ranges_)); | 880 CHECK_LT(k, arraysize(shifted_int32_ranges_)); |
881 if (access.external_array_type() != kExternalUint8ClampedArray && | 881 if (access.external_array_type() != kExternalUint8ClampedArray && |
882 key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { | 882 key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { |
883 // JSLoadProperty(typed-array, int32) | 883 // JSLoadProperty(typed-array, int32) |
884 Handle<FixedTypedArrayBase> elements = | 884 Handle<FixedTypedArrayBase> elements = |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), check, | 1009 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), check, |
1010 check_true); | 1010 check_true); |
1011 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 1011 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
1012 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 1012 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
1013 check_false->set_op(common()->Merge(check_false->InputCount() + 1)); | 1013 check_false->set_op(common()->Merge(check_false->InputCount() + 1)); |
1014 check_false->AppendInput(graph()->zone(), if_false); | 1014 check_false->AppendInput(graph()->zone(), if_false); |
1015 check_true = if_true; | 1015 check_true = if_true; |
1016 } | 1016 } |
1017 | 1017 |
1018 // Fast case, because variable is not shadowed. Perform global object load. | 1018 // Fast case, because variable is not shadowed. Perform global object load. |
1019 Unique<Name> name = Unique<Name>::CreateUninitialized(access.name()); | |
1020 Node* global = graph()->NewNode( | 1019 Node* global = graph()->NewNode( |
1021 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true), context, | 1020 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true), context, |
1022 context, effect); | 1021 context, effect); |
1023 Node* fast = graph()->NewNode( | 1022 Node* fast = graph()->NewNode( |
1024 javascript()->LoadGlobal(name, access.feedback(), access.typeof_mode()), | 1023 javascript()->LoadGlobal(access.name(), access.feedback(), |
| 1024 access.typeof_mode()), |
1025 context, global, vector, context, state1, state2, global, check_true); | 1025 context, global, vector, context, state1, state2, global, check_true); |
1026 | 1026 |
1027 // Slow case, because variable potentially shadowed. Perform dynamic lookup. | 1027 // Slow case, because variable potentially shadowed. Perform dynamic lookup. |
1028 uint32_t check_bitset = DynamicGlobalAccess::kFullCheckRequired; | 1028 uint32_t check_bitset = DynamicGlobalAccess::kFullCheckRequired; |
1029 Node* slow = graph()->NewNode( | 1029 Node* slow = graph()->NewNode( |
1030 javascript()->LoadDynamicGlobal(access.name(), check_bitset, | 1030 javascript()->LoadDynamicGlobal(access.name(), check_bitset, |
1031 access.feedback(), access.typeof_mode()), | 1031 access.feedback(), access.typeof_mode()), |
1032 vector, context, context, state1, state2, effect, check_false); | 1032 vector, context, context, state1, state2, effect, check_false); |
1033 | 1033 |
1034 // Replace value, effect and control uses accordingly. | 1034 // Replace value, effect and control uses accordingly. |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1122 return Changed(node); | 1122 return Changed(node); |
1123 } | 1123 } |
1124 | 1124 |
1125 return NoChange(); | 1125 return NoChange(); |
1126 } | 1126 } |
1127 | 1127 |
1128 | 1128 |
1129 Reduction JSTypedLowering::ReduceJSCreateLiteralArray(Node* node) { | 1129 Reduction JSTypedLowering::ReduceJSCreateLiteralArray(Node* node) { |
1130 DCHECK_EQ(IrOpcode::kJSCreateLiteralArray, node->opcode()); | 1130 DCHECK_EQ(IrOpcode::kJSCreateLiteralArray, node->opcode()); |
1131 HeapObjectMatcher mconst(NodeProperties::GetValueInput(node, 2)); | 1131 HeapObjectMatcher mconst(NodeProperties::GetValueInput(node, 2)); |
1132 int length = Handle<FixedArray>::cast(mconst.Value().handle())->length(); | 1132 int length = Handle<FixedArray>::cast(mconst.Value())->length(); |
1133 int flags = OpParameter<int>(node->op()); | 1133 int flags = OpParameter<int>(node->op()); |
1134 | 1134 |
1135 // Use the FastCloneShallowArrayStub only for shallow boilerplates up to the | 1135 // Use the FastCloneShallowArrayStub only for shallow boilerplates up to the |
1136 // initial length limit for arrays with "fast" elements kind. | 1136 // initial length limit for arrays with "fast" elements kind. |
1137 // TODO(rossberg): Teach strong mode to FastCloneShallowArrayStub. | 1137 // TODO(rossberg): Teach strong mode to FastCloneShallowArrayStub. |
1138 if ((flags & ArrayLiteral::kShallowElements) != 0 && | 1138 if ((flags & ArrayLiteral::kShallowElements) != 0 && |
1139 (flags & ArrayLiteral::kIsStrong) == 0 && | 1139 (flags & ArrayLiteral::kIsStrong) == 0 && |
1140 length < JSObject::kInitialMaxFastElementArray) { | 1140 length < JSObject::kInitialMaxFastElementArray) { |
1141 Isolate* isolate = jsgraph()->isolate(); | 1141 Isolate* isolate = jsgraph()->isolate(); |
1142 Callable callable = CodeFactory::FastCloneShallowArray(isolate); | 1142 Callable callable = CodeFactory::FastCloneShallowArray(isolate); |
(...skipping 10 matching lines...) Expand all Loading... |
1153 } | 1153 } |
1154 | 1154 |
1155 return NoChange(); | 1155 return NoChange(); |
1156 } | 1156 } |
1157 | 1157 |
1158 | 1158 |
1159 Reduction JSTypedLowering::ReduceJSCreateLiteralObject(Node* node) { | 1159 Reduction JSTypedLowering::ReduceJSCreateLiteralObject(Node* node) { |
1160 DCHECK_EQ(IrOpcode::kJSCreateLiteralObject, node->opcode()); | 1160 DCHECK_EQ(IrOpcode::kJSCreateLiteralObject, node->opcode()); |
1161 HeapObjectMatcher mconst(NodeProperties::GetValueInput(node, 2)); | 1161 HeapObjectMatcher mconst(NodeProperties::GetValueInput(node, 2)); |
1162 // Constants are pairs, see ObjectLiteral::properties_count(). | 1162 // Constants are pairs, see ObjectLiteral::properties_count(). |
1163 int length = Handle<FixedArray>::cast(mconst.Value().handle())->length() / 2; | 1163 int length = Handle<FixedArray>::cast(mconst.Value())->length() / 2; |
1164 int flags = OpParameter<int>(node->op()); | 1164 int flags = OpParameter<int>(node->op()); |
1165 | 1165 |
1166 // Use the FastCloneShallowObjectStub only for shallow boilerplates without | 1166 // Use the FastCloneShallowObjectStub only for shallow boilerplates without |
1167 // elements up to the number of properties that the stubs can handle. | 1167 // elements up to the number of properties that the stubs can handle. |
1168 if ((flags & ObjectLiteral::kShallowProperties) != 0 && | 1168 if ((flags & ObjectLiteral::kShallowProperties) != 0 && |
1169 length <= FastCloneShallowObjectStub::kMaximumClonedProperties) { | 1169 length <= FastCloneShallowObjectStub::kMaximumClonedProperties) { |
1170 Isolate* isolate = jsgraph()->isolate(); | 1170 Isolate* isolate = jsgraph()->isolate(); |
1171 Callable callable = CodeFactory::FastCloneShallowObject(isolate, length); | 1171 Callable callable = CodeFactory::FastCloneShallowObject(isolate, length); |
1172 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1172 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
1173 isolate, graph()->zone(), callable.descriptor(), 0, | 1173 isolate, graph()->zone(), callable.descriptor(), 0, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1218 } | 1218 } |
1219 return NoChange(); | 1219 return NoChange(); |
1220 } | 1220 } |
1221 | 1221 |
1222 | 1222 |
1223 Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) { | 1223 Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) { |
1224 DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode()); | 1224 DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode()); |
1225 Node* const input = NodeProperties::GetValueInput(node, 0); | 1225 Node* const input = NodeProperties::GetValueInput(node, 0); |
1226 HeapObjectMatcher minput(input); | 1226 HeapObjectMatcher minput(input); |
1227 DCHECK(minput.HasValue()); // TODO(mstarzinger): Make ScopeInfo static. | 1227 DCHECK(minput.HasValue()); // TODO(mstarzinger): Make ScopeInfo static. |
1228 int context_length = | 1228 int context_length = Handle<ScopeInfo>::cast(minput.Value())->ContextLength(); |
1229 Handle<ScopeInfo>::cast(minput.Value().handle())->ContextLength(); | |
1230 if (FLAG_turbo_allocate && context_length < kBlockContextAllocationLimit) { | 1229 if (FLAG_turbo_allocate && context_length < kBlockContextAllocationLimit) { |
1231 // JSCreateBlockContext(s:scope[length < limit], f) | 1230 // JSCreateBlockContext(s:scope[length < limit], f) |
1232 Node* const effect = NodeProperties::GetEffectInput(node); | 1231 Node* const effect = NodeProperties::GetEffectInput(node); |
1233 Node* const control = NodeProperties::GetControlInput(node); | 1232 Node* const control = NodeProperties::GetControlInput(node); |
1234 Node* const closure = NodeProperties::GetValueInput(node, 1); | 1233 Node* const closure = NodeProperties::GetValueInput(node, 1); |
1235 Node* const context = NodeProperties::GetContextInput(node); | 1234 Node* const context = NodeProperties::GetContextInput(node); |
1236 Node* const load = graph()->NewNode( | 1235 Node* const load = graph()->NewNode( |
1237 simplified()->LoadField( | 1236 simplified()->LoadField( |
1238 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), | 1237 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
1239 context, effect, control); | 1238 context, effect, control); |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1707 } | 1706 } |
1708 | 1707 |
1709 | 1708 |
1710 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1709 MachineOperatorBuilder* JSTypedLowering::machine() const { |
1711 return jsgraph()->machine(); | 1710 return jsgraph()->machine(); |
1712 } | 1711 } |
1713 | 1712 |
1714 } // namespace compiler | 1713 } // namespace compiler |
1715 } // namespace internal | 1714 } // namespace internal |
1716 } // namespace v8 | 1715 } // namespace v8 |
OLD | NEW |