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 |