| 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 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 } | 822 } |
| 823 } | 823 } |
| 824 return NoChange(); | 824 return NoChange(); |
| 825 } | 825 } |
| 826 | 826 |
| 827 | 827 |
| 828 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { | 828 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { |
| 829 Node* key = NodeProperties::GetValueInput(node, 1); | 829 Node* key = NodeProperties::GetValueInput(node, 1); |
| 830 Node* base = NodeProperties::GetValueInput(node, 0); | 830 Node* base = NodeProperties::GetValueInput(node, 0); |
| 831 Type* key_type = NodeProperties::GetBounds(key).upper; | 831 Type* key_type = NodeProperties::GetBounds(key).upper; |
| 832 // TODO(mstarzinger): This lowering is not correct if: | |
| 833 // a) The typed array or it's buffer is neutered. | |
| 834 HeapObjectMatcher<Object> mbase(base); | 832 HeapObjectMatcher<Object> mbase(base); |
| 835 if (mbase.HasValue() && mbase.Value().handle()->IsJSTypedArray()) { | 833 if (mbase.HasValue() && mbase.Value().handle()->IsJSTypedArray()) { |
| 836 Handle<JSTypedArray> const array = | 834 Handle<JSTypedArray> const array = |
| 837 Handle<JSTypedArray>::cast(mbase.Value().handle()); | 835 Handle<JSTypedArray>::cast(mbase.Value().handle()); |
| 838 array->GetBuffer()->set_is_neuterable(false); | 836 if (!array->GetBuffer()->was_neutered()) { |
| 839 BufferAccess const access(array->type()); | 837 array->GetBuffer()->set_is_neuterable(false); |
| 840 size_t const k = ElementSizeLog2Of(access.machine_type()); | 838 BufferAccess const access(array->type()); |
| 841 double const byte_length = array->byte_length()->Number(); | 839 size_t const k = ElementSizeLog2Of(access.machine_type()); |
| 842 CHECK_LT(k, arraysize(shifted_int32_ranges_)); | 840 double const byte_length = array->byte_length()->Number(); |
| 843 if (IsExternalArrayElementsKind(array->map()->elements_kind()) && | 841 CHECK_LT(k, arraysize(shifted_int32_ranges_)); |
| 844 key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { | 842 if (IsExternalArrayElementsKind(array->map()->elements_kind()) && |
| 845 // JSLoadProperty(typed-array, int32) | 843 key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { |
| 846 Handle<ExternalArray> elements = | 844 // JSLoadProperty(typed-array, int32) |
| 847 Handle<ExternalArray>::cast(handle(array->elements())); | 845 Handle<ExternalArray> elements = |
| 848 Node* buffer = jsgraph()->PointerConstant(elements->external_pointer()); | 846 Handle<ExternalArray>::cast(handle(array->elements())); |
| 849 Node* length = jsgraph()->Constant(byte_length); | 847 Node* buffer = jsgraph()->PointerConstant(elements->external_pointer()); |
| 850 Node* effect = NodeProperties::GetEffectInput(node); | 848 Node* length = jsgraph()->Constant(byte_length); |
| 851 Node* control = NodeProperties::GetControlInput(node); | 849 Node* effect = NodeProperties::GetEffectInput(node); |
| 852 // Check if we can avoid the bounds check. | 850 Node* control = NodeProperties::GetControlInput(node); |
| 853 if (key_type->Min() >= 0 && key_type->Max() < array->length()->Number()) { | 851 // Check if we can avoid the bounds check. |
| 854 Node* load = graph()->NewNode( | 852 if (key_type->Min() >= 0 && |
| 855 simplified()->LoadElement( | 853 key_type->Max() < array->length()->Number()) { |
| 856 AccessBuilder::ForTypedArrayElement(array->type(), true)), | 854 Node* load = graph()->NewNode( |
| 857 buffer, key, effect, control); | 855 simplified()->LoadElement( |
| 856 AccessBuilder::ForTypedArrayElement(array->type(), true)), |
| 857 buffer, key, effect, control); |
| 858 return ReplaceEagerly(node, load); |
| 859 } |
| 860 // Compute byte offset. |
| 861 Node* offset = Word32Shl(key, static_cast<int>(k)); |
| 862 Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer, |
| 863 offset, length, effect, control); |
| 858 return ReplaceEagerly(node, load); | 864 return ReplaceEagerly(node, load); |
| 859 } | 865 } |
| 860 // Compute byte offset. | |
| 861 Node* offset = Word32Shl(key, static_cast<int>(k)); | |
| 862 Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer, | |
| 863 offset, length, effect, control); | |
| 864 return ReplaceEagerly(node, load); | |
| 865 } | 866 } |
| 866 } | 867 } |
| 867 return NoChange(); | 868 return NoChange(); |
| 868 } | 869 } |
| 869 | 870 |
| 870 | 871 |
| 871 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) { | 872 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) { |
| 872 Node* key = NodeProperties::GetValueInput(node, 1); | 873 Node* key = NodeProperties::GetValueInput(node, 1); |
| 873 Node* base = NodeProperties::GetValueInput(node, 0); | 874 Node* base = NodeProperties::GetValueInput(node, 0); |
| 874 Node* value = NodeProperties::GetValueInput(node, 2); | 875 Node* value = NodeProperties::GetValueInput(node, 2); |
| 875 Type* key_type = NodeProperties::GetBounds(key).upper; | 876 Type* key_type = NodeProperties::GetBounds(key).upper; |
| 876 Type* value_type = NodeProperties::GetBounds(value).upper; | 877 Type* value_type = NodeProperties::GetBounds(value).upper; |
| 877 // TODO(mstarzinger): This lowering is not correct if: | |
| 878 // a) The typed array or its buffer is neutered. | |
| 879 HeapObjectMatcher<Object> mbase(base); | 878 HeapObjectMatcher<Object> mbase(base); |
| 880 if (mbase.HasValue() && mbase.Value().handle()->IsJSTypedArray()) { | 879 if (mbase.HasValue() && mbase.Value().handle()->IsJSTypedArray()) { |
| 881 Handle<JSTypedArray> const array = | 880 Handle<JSTypedArray> const array = |
| 882 Handle<JSTypedArray>::cast(mbase.Value().handle()); | 881 Handle<JSTypedArray>::cast(mbase.Value().handle()); |
| 883 array->GetBuffer()->set_is_neuterable(false); | 882 if (!array->GetBuffer()->was_neutered()) { |
| 884 BufferAccess const access(array->type()); | 883 array->GetBuffer()->set_is_neuterable(false); |
| 885 size_t const k = ElementSizeLog2Of(access.machine_type()); | 884 BufferAccess const access(array->type()); |
| 886 double const byte_length = array->byte_length()->Number(); | 885 size_t const k = ElementSizeLog2Of(access.machine_type()); |
| 887 CHECK_LT(k, arraysize(shifted_int32_ranges_)); | 886 double const byte_length = array->byte_length()->Number(); |
| 888 if (IsExternalArrayElementsKind(array->map()->elements_kind()) && | 887 CHECK_LT(k, arraysize(shifted_int32_ranges_)); |
| 889 access.external_array_type() != kExternalUint8ClampedArray && | 888 if (IsExternalArrayElementsKind(array->map()->elements_kind()) && |
| 890 key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { | 889 access.external_array_type() != kExternalUint8ClampedArray && |
| 891 // JSLoadProperty(typed-array, int32) | 890 key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { |
| 892 Handle<ExternalArray> elements = | 891 // JSLoadProperty(typed-array, int32) |
| 893 Handle<ExternalArray>::cast(handle(array->elements())); | 892 Handle<ExternalArray> elements = |
| 894 Node* buffer = jsgraph()->PointerConstant(elements->external_pointer()); | 893 Handle<ExternalArray>::cast(handle(array->elements())); |
| 895 Node* length = jsgraph()->Constant(byte_length); | 894 Node* buffer = jsgraph()->PointerConstant(elements->external_pointer()); |
| 896 Node* context = NodeProperties::GetContextInput(node); | 895 Node* length = jsgraph()->Constant(byte_length); |
| 897 Node* effect = NodeProperties::GetEffectInput(node); | 896 Node* context = NodeProperties::GetContextInput(node); |
| 898 Node* control = NodeProperties::GetControlInput(node); | 897 Node* effect = NodeProperties::GetEffectInput(node); |
| 899 // Convert to a number first. | 898 Node* control = NodeProperties::GetControlInput(node); |
| 900 if (!value_type->Is(Type::Number())) { | 899 // Convert to a number first. |
| 901 Reduction number_reduction = ReduceJSToNumberInput(value); | 900 if (!value_type->Is(Type::Number())) { |
| 902 if (number_reduction.Changed()) { | 901 Reduction number_reduction = ReduceJSToNumberInput(value); |
| 903 value = number_reduction.replacement(); | 902 if (number_reduction.Changed()) { |
| 904 } else { | 903 value = number_reduction.replacement(); |
| 905 Node* frame_state_for_to_number = | 904 } else { |
| 906 NodeProperties::GetFrameStateInput(node, 1); | 905 Node* frame_state_for_to_number = |
| 907 value = effect = | 906 NodeProperties::GetFrameStateInput(node, 1); |
| 908 graph()->NewNode(javascript()->ToNumber(), value, context, | 907 value = effect = |
| 909 frame_state_for_to_number, effect, control); | 908 graph()->NewNode(javascript()->ToNumber(), value, context, |
| 909 frame_state_for_to_number, effect, control); |
| 910 } |
| 910 } | 911 } |
| 911 } | 912 // For integer-typed arrays, convert to the integer type. |
| 912 // For integer-typed arrays, convert to the integer type. | 913 if (TypeOf(access.machine_type()) == kTypeInt32 && |
| 913 if (TypeOf(access.machine_type()) == kTypeInt32 && | 914 !value_type->Is(Type::Signed32())) { |
| 914 !value_type->Is(Type::Signed32())) { | 915 value = graph()->NewNode(simplified()->NumberToInt32(), value); |
| 915 value = graph()->NewNode(simplified()->NumberToInt32(), value); | 916 } else if (TypeOf(access.machine_type()) == kTypeUint32 && |
| 916 } else if (TypeOf(access.machine_type()) == kTypeUint32 && | 917 !value_type->Is(Type::Unsigned32())) { |
| 917 !value_type->Is(Type::Unsigned32())) { | 918 value = graph()->NewNode(simplified()->NumberToUint32(), value); |
| 918 value = graph()->NewNode(simplified()->NumberToUint32(), value); | 919 } |
| 919 } | 920 // Check if we can avoid the bounds check. |
| 920 // Check if we can avoid the bounds check. | 921 if (key_type->Min() >= 0 && |
| 921 if (key_type->Min() >= 0 && key_type->Max() < array->length()->Number()) { | 922 key_type->Max() < array->length()->Number()) { |
| 922 node->set_op(simplified()->StoreElement( | 923 node->set_op(simplified()->StoreElement( |
| 923 AccessBuilder::ForTypedArrayElement(array->type(), true))); | 924 AccessBuilder::ForTypedArrayElement(array->type(), true))); |
| 925 node->ReplaceInput(0, buffer); |
| 926 DCHECK_EQ(key, node->InputAt(1)); |
| 927 node->ReplaceInput(2, value); |
| 928 node->ReplaceInput(3, effect); |
| 929 node->ReplaceInput(4, control); |
| 930 node->TrimInputCount(5); |
| 931 RelaxControls(node); |
| 932 return Changed(node); |
| 933 } |
| 934 // Compute byte offset. |
| 935 Node* offset = Word32Shl(key, static_cast<int>(k)); |
| 936 // Turn into a StoreBuffer operation. |
| 937 node->set_op(simplified()->StoreBuffer(access)); |
| 924 node->ReplaceInput(0, buffer); | 938 node->ReplaceInput(0, buffer); |
| 925 DCHECK_EQ(key, node->InputAt(1)); | 939 node->ReplaceInput(1, offset); |
| 926 node->ReplaceInput(2, value); | 940 node->ReplaceInput(2, length); |
| 927 node->ReplaceInput(3, effect); | 941 node->ReplaceInput(3, value); |
| 928 node->ReplaceInput(4, control); | 942 node->ReplaceInput(4, effect); |
| 929 node->TrimInputCount(5); | 943 node->ReplaceInput(5, control); |
| 944 node->TrimInputCount(6); |
| 930 RelaxControls(node); | 945 RelaxControls(node); |
| 931 return Changed(node); | 946 return Changed(node); |
| 932 } | 947 } |
| 933 // Compute byte offset. | |
| 934 Node* offset = Word32Shl(key, static_cast<int>(k)); | |
| 935 // Turn into a StoreBuffer operation. | |
| 936 node->set_op(simplified()->StoreBuffer(access)); | |
| 937 node->ReplaceInput(0, buffer); | |
| 938 node->ReplaceInput(1, offset); | |
| 939 node->ReplaceInput(2, length); | |
| 940 node->ReplaceInput(3, value); | |
| 941 node->ReplaceInput(4, effect); | |
| 942 node->ReplaceInput(5, control); | |
| 943 node->TrimInputCount(6); | |
| 944 RelaxControls(node); | |
| 945 return Changed(node); | |
| 946 } | 948 } |
| 947 } | 949 } |
| 948 return NoChange(); | 950 return NoChange(); |
| 949 } | 951 } |
| 950 | 952 |
| 951 | 953 |
| 952 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { | 954 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { |
| 953 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); | 955 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); |
| 954 ContextAccess const& access = ContextAccessOf(node->op()); | 956 ContextAccess const& access = ContextAccessOf(node->op()); |
| 955 Node* const effect = NodeProperties::GetEffectInput(node); | 957 Node* const effect = NodeProperties::GetEffectInput(node); |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1310 } | 1312 } |
| 1311 | 1313 |
| 1312 | 1314 |
| 1313 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1315 MachineOperatorBuilder* JSTypedLowering::machine() const { |
| 1314 return jsgraph()->machine(); | 1316 return jsgraph()->machine(); |
| 1315 } | 1317 } |
| 1316 | 1318 |
| 1317 } // namespace compiler | 1319 } // namespace compiler |
| 1318 } // namespace internal | 1320 } // namespace internal |
| 1319 } // namespace v8 | 1321 } // namespace v8 |
| OLD | NEW |