| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
| 5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
| 6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
| 7 #include "src/frames.h" | 7 #include "src/frames.h" |
| 8 #include "src/ic/handler-configuration.h" | 8 #include "src/ic/handler-configuration.h" |
| 9 #include "src/ic/stub-cache.h" | 9 #include "src/ic/stub-cache.h" |
| 10 | 10 |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 } | 265 } |
| 266 | 266 |
| 267 Bind(&return_minus_x); | 267 Bind(&return_minus_x); |
| 268 var_x.Bind(Float64Neg(var_x.value())); | 268 var_x.Bind(Float64Neg(var_x.value())); |
| 269 Goto(&return_x); | 269 Goto(&return_x); |
| 270 | 270 |
| 271 Bind(&return_x); | 271 Bind(&return_x); |
| 272 return var_x.value(); | 272 return var_x.value(); |
| 273 } | 273 } |
| 274 | 274 |
| 275 Node* CodeStubAssembler::Float64RoundToEven(Node* x) { |
| 276 if (IsFloat64RoundTiesEvenSupported()) { |
| 277 return Float64RoundTiesEven(x); |
| 278 } |
| 279 // See ES#sec-touint8clamp for details. |
| 280 Node* f = Float64Floor(x); |
| 281 Node* f_and_half = Float64Add(f, Float64Constant(0.5)); |
| 282 |
| 283 Variable var_result(this, MachineRepresentation::kFloat64); |
| 284 Label return_f(this), return_f_plus_one(this), done(this); |
| 285 |
| 286 GotoIf(Float64LessThan(f_and_half, x), &return_f_plus_one); |
| 287 GotoIf(Float64LessThan(x, f_and_half), &return_f); |
| 288 { |
| 289 Node* f_mod_2 = Float64Mod(f, Float64Constant(2.0)); |
| 290 Branch(Float64Equal(f_mod_2, Float64Constant(0.0)), &return_f, |
| 291 &return_f_plus_one); |
| 292 } |
| 293 |
| 294 Bind(&return_f); |
| 295 var_result.Bind(f); |
| 296 Goto(&done); |
| 297 |
| 298 Bind(&return_f_plus_one); |
| 299 var_result.Bind(Float64Add(f, Float64Constant(1.0))); |
| 300 Goto(&done); |
| 301 |
| 302 Bind(&done); |
| 303 return var_result.value(); |
| 304 } |
| 305 |
| 275 Node* CodeStubAssembler::Float64Trunc(Node* x) { | 306 Node* CodeStubAssembler::Float64Trunc(Node* x) { |
| 276 if (IsFloat64RoundTruncateSupported()) { | 307 if (IsFloat64RoundTruncateSupported()) { |
| 277 return Float64RoundTruncate(x); | 308 return Float64RoundTruncate(x); |
| 278 } | 309 } |
| 279 | 310 |
| 280 Node* one = Float64Constant(1.0); | 311 Node* one = Float64Constant(1.0); |
| 281 Node* zero = Float64Constant(0.0); | 312 Node* zero = Float64Constant(0.0); |
| 282 Node* two_52 = Float64Constant(4503599627370496.0E0); | 313 Node* two_52 = Float64Constant(4503599627370496.0E0); |
| 283 Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); | 314 Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); |
| 284 | 315 |
| (...skipping 6468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6753 Node* native_context = LoadNativeContext(context); | 6784 Node* native_context = LoadNativeContext(context); |
| 6754 Node* script_context_table = | 6785 Node* script_context_table = |
| 6755 LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX); | 6786 LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX); |
| 6756 | 6787 |
| 6757 int offset = | 6788 int offset = |
| 6758 ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag; | 6789 ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag; |
| 6759 return Load(MachineType::AnyTagged(), script_context_table, | 6790 return Load(MachineType::AnyTagged(), script_context_table, |
| 6760 IntPtrConstant(offset)); | 6791 IntPtrConstant(offset)); |
| 6761 } | 6792 } |
| 6762 | 6793 |
| 6763 Node* CodeStubAssembler::ClampedToUint8(Node* int32_value) { | |
| 6764 Label done(this); | |
| 6765 Node* int32_zero = Int32Constant(0); | |
| 6766 Node* int32_255 = Int32Constant(255); | |
| 6767 Variable var_value(this, MachineRepresentation::kWord32); | |
| 6768 var_value.Bind(int32_value); | |
| 6769 GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done); | |
| 6770 var_value.Bind(int32_zero); | |
| 6771 GotoIf(Int32LessThan(int32_value, int32_zero), &done); | |
| 6772 var_value.Bind(int32_255); | |
| 6773 Goto(&done); | |
| 6774 Bind(&done); | |
| 6775 return var_value.value(); | |
| 6776 } | |
| 6777 | |
| 6778 namespace { | 6794 namespace { |
| 6779 | 6795 |
| 6780 // Converts typed array elements kind to a machine representations. | 6796 // Converts typed array elements kind to a machine representations. |
| 6781 MachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) { | 6797 MachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) { |
| 6782 switch (kind) { | 6798 switch (kind) { |
| 6783 case UINT8_CLAMPED_ELEMENTS: | 6799 case UINT8_CLAMPED_ELEMENTS: |
| 6784 case UINT8_ELEMENTS: | 6800 case UINT8_ELEMENTS: |
| 6785 case INT8_ELEMENTS: | 6801 case INT8_ELEMENTS: |
| 6786 return MachineRepresentation::kWord8; | 6802 return MachineRepresentation::kWord8; |
| 6787 case UINT16_ELEMENTS: | 6803 case UINT16_ELEMENTS: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 6800 } | 6816 } |
| 6801 } | 6817 } |
| 6802 | 6818 |
| 6803 } // namespace | 6819 } // namespace |
| 6804 | 6820 |
| 6805 void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind, | 6821 void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind, |
| 6806 Node* index, Node* value, | 6822 Node* index, Node* value, |
| 6807 ParameterMode mode) { | 6823 ParameterMode mode) { |
| 6808 if (IsFixedTypedArrayElementsKind(kind)) { | 6824 if (IsFixedTypedArrayElementsKind(kind)) { |
| 6809 if (kind == UINT8_CLAMPED_ELEMENTS) { | 6825 if (kind == UINT8_CLAMPED_ELEMENTS) { |
| 6810 value = ClampedToUint8(value); | 6826 CSA_ASSERT(this, |
| 6827 Word32Equal(value, Word32And(Int32Constant(0xff), value))); |
| 6811 } | 6828 } |
| 6812 Node* offset = ElementOffsetFromIndex(index, kind, mode, 0); | 6829 Node* offset = ElementOffsetFromIndex(index, kind, mode, 0); |
| 6813 MachineRepresentation rep = ElementsKindToMachineRepresentation(kind); | 6830 MachineRepresentation rep = ElementsKindToMachineRepresentation(kind); |
| 6814 StoreNoWriteBarrier(rep, elements, offset, value); | 6831 StoreNoWriteBarrier(rep, elements, offset, value); |
| 6815 return; | 6832 return; |
| 6816 } | 6833 } |
| 6817 | 6834 |
| 6818 WriteBarrierMode barrier_mode = | 6835 WriteBarrierMode barrier_mode = |
| 6819 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; | 6836 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; |
| 6820 if (IsFastDoubleElementsKind(kind)) { | 6837 if (IsFastDoubleElementsKind(kind)) { |
| 6821 // Make sure we do not store signalling NaNs into double arrays. | 6838 // Make sure we do not store signalling NaNs into double arrays. |
| 6822 value = Float64SilenceNaN(value); | 6839 value = Float64SilenceNaN(value); |
| 6823 StoreFixedDoubleArrayElement(elements, index, value, mode); | 6840 StoreFixedDoubleArrayElement(elements, index, value, mode); |
| 6824 } else { | 6841 } else { |
| 6825 StoreFixedArrayElement(elements, index, value, barrier_mode, mode); | 6842 StoreFixedArrayElement(elements, index, value, barrier_mode, mode); |
| 6826 } | 6843 } |
| 6827 } | 6844 } |
| 6828 | 6845 |
| 6846 Node* CodeStubAssembler::Int32ToUint8Clamped(Node* int32_value) { |
| 6847 Label done(this); |
| 6848 Node* int32_zero = Int32Constant(0); |
| 6849 Node* int32_255 = Int32Constant(255); |
| 6850 Variable var_value(this, MachineRepresentation::kWord32); |
| 6851 var_value.Bind(int32_value); |
| 6852 GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done); |
| 6853 var_value.Bind(int32_zero); |
| 6854 GotoIf(Int32LessThan(int32_value, int32_zero), &done); |
| 6855 var_value.Bind(int32_255); |
| 6856 Goto(&done); |
| 6857 Bind(&done); |
| 6858 return var_value.value(); |
| 6859 } |
| 6860 |
| 6861 Node* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) { |
| 6862 Label done(this); |
| 6863 Variable var_value(this, MachineRepresentation::kWord32); |
| 6864 var_value.Bind(Int32Constant(0)); |
| 6865 GotoIf(Float64LessThanOrEqual(float64_value, Float64Constant(0.0)), &done); |
| 6866 var_value.Bind(Int32Constant(255)); |
| 6867 GotoIf(Float64LessThanOrEqual(Float64Constant(255.0), float64_value), &done); |
| 6868 { |
| 6869 Node* rounded_value = Float64RoundToEven(float64_value); |
| 6870 var_value.Bind(TruncateFloat64ToWord32(rounded_value)); |
| 6871 Goto(&done); |
| 6872 } |
| 6873 Bind(&done); |
| 6874 return var_value.value(); |
| 6875 } |
| 6876 |
| 6877 Node* CodeStubAssembler::PrepareValueForWriteToTypedArray( |
| 6878 Node* input, ElementsKind elements_kind, Label* bailout) { |
| 6879 DCHECK(IsFixedTypedArrayElementsKind(elements_kind)); |
| 6880 |
| 6881 MachineRepresentation rep; |
| 6882 switch (elements_kind) { |
| 6883 case UINT8_ELEMENTS: |
| 6884 case INT8_ELEMENTS: |
| 6885 case UINT16_ELEMENTS: |
| 6886 case INT16_ELEMENTS: |
| 6887 case UINT32_ELEMENTS: |
| 6888 case INT32_ELEMENTS: |
| 6889 case UINT8_CLAMPED_ELEMENTS: |
| 6890 rep = MachineRepresentation::kWord32; |
| 6891 break; |
| 6892 case FLOAT32_ELEMENTS: |
| 6893 rep = MachineRepresentation::kFloat32; |
| 6894 break; |
| 6895 case FLOAT64_ELEMENTS: |
| 6896 rep = MachineRepresentation::kFloat64; |
| 6897 break; |
| 6898 default: |
| 6899 UNREACHABLE(); |
| 6900 return nullptr; |
| 6901 } |
| 6902 |
| 6903 Variable var_result(this, rep); |
| 6904 Label done(this, &var_result), if_smi(this); |
| 6905 GotoIf(TaggedIsSmi(input), &if_smi); |
| 6906 // Try to convert a heap number to a Smi. |
| 6907 GotoUnless(IsHeapNumberMap(LoadMap(input)), bailout); |
| 6908 { |
| 6909 Node* value = LoadHeapNumberValue(input); |
| 6910 if (rep == MachineRepresentation::kWord32) { |
| 6911 if (elements_kind == UINT8_CLAMPED_ELEMENTS) { |
| 6912 value = Float64ToUint8Clamped(value); |
| 6913 } else { |
| 6914 value = TruncateFloat64ToWord32(value); |
| 6915 } |
| 6916 } else if (rep == MachineRepresentation::kFloat32) { |
| 6917 value = TruncateFloat64ToFloat32(value); |
| 6918 } else { |
| 6919 DCHECK_EQ(MachineRepresentation::kFloat64, rep); |
| 6920 } |
| 6921 var_result.Bind(value); |
| 6922 Goto(&done); |
| 6923 } |
| 6924 |
| 6925 Bind(&if_smi); |
| 6926 { |
| 6927 Node* value = SmiToWord32(input); |
| 6928 if (rep == MachineRepresentation::kFloat32) { |
| 6929 value = RoundInt32ToFloat32(value); |
| 6930 } else if (rep == MachineRepresentation::kFloat64) { |
| 6931 value = ChangeInt32ToFloat64(value); |
| 6932 } else { |
| 6933 DCHECK_EQ(MachineRepresentation::kWord32, rep); |
| 6934 if (elements_kind == UINT8_CLAMPED_ELEMENTS) { |
| 6935 value = Int32ToUint8Clamped(value); |
| 6936 } |
| 6937 } |
| 6938 var_result.Bind(value); |
| 6939 Goto(&done); |
| 6940 } |
| 6941 |
| 6942 Bind(&done); |
| 6943 return var_result.value(); |
| 6944 } |
| 6945 |
| 6829 void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, | 6946 void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, |
| 6830 bool is_jsarray, | 6947 bool is_jsarray, |
| 6831 ElementsKind elements_kind, | 6948 ElementsKind elements_kind, |
| 6832 KeyedAccessStoreMode store_mode, | 6949 KeyedAccessStoreMode store_mode, |
| 6833 Label* bailout) { | 6950 Label* bailout) { |
| 6834 Node* elements = LoadElements(object); | 6951 Node* elements = LoadElements(object); |
| 6835 if (IsFastSmiOrObjectElementsKind(elements_kind) && | 6952 if (IsFastSmiOrObjectElementsKind(elements_kind) && |
| 6836 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 6953 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
| 6837 // Bailout in case of COW elements. | 6954 // Bailout in case of COW elements. |
| 6838 GotoIf(WordNotEqual(LoadMap(elements), | 6955 GotoIf(WordNotEqual(LoadMap(elements), |
| 6839 LoadRoot(Heap::kFixedArrayMapRootIndex)), | 6956 LoadRoot(Heap::kFixedArrayMapRootIndex)), |
| 6840 bailout); | 6957 bailout); |
| 6841 } | 6958 } |
| 6842 // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode(). | 6959 // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode(). |
| 6843 ParameterMode parameter_mode = INTPTR_PARAMETERS; | 6960 ParameterMode parameter_mode = INTPTR_PARAMETERS; |
| 6844 key = TryToIntptr(key, bailout); | 6961 key = TryToIntptr(key, bailout); |
| 6845 | 6962 |
| 6846 if (IsFixedTypedArrayElementsKind(elements_kind)) { | 6963 if (IsFixedTypedArrayElementsKind(elements_kind)) { |
| 6847 Label done(this); | 6964 Label done(this); |
| 6848 // TODO(ishell): call ToNumber() on value and don't bailout but be careful | 6965 // TODO(ishell): call ToNumber() on value and don't bailout but be careful |
| 6849 // to call it only once if we decide to bailout because of bounds checks. | 6966 // to call it only once if we decide to bailout because of bounds checks. |
| 6850 | 6967 |
| 6851 if (IsFixedFloatElementsKind(elements_kind)) { | 6968 value = PrepareValueForWriteToTypedArray(value, elements_kind, bailout); |
| 6852 // TODO(ishell): move float32 truncation into PrepareValueForWrite. | |
| 6853 value = PrepareValueForWrite(value, Representation::Double(), bailout); | |
| 6854 if (elements_kind == FLOAT32_ELEMENTS) { | |
| 6855 value = TruncateFloat64ToFloat32(value); | |
| 6856 } | |
| 6857 } else { | |
| 6858 // TODO(ishell): It's fine for word8/16/32 to truncate the result. | |
| 6859 value = TryToIntptr(value, bailout); | |
| 6860 } | |
| 6861 | 6969 |
| 6862 // There must be no allocations between the buffer load and | 6970 // There must be no allocations between the buffer load and |
| 6863 // and the actual store to backing store, because GC may decide that | 6971 // and the actual store to backing store, because GC may decide that |
| 6864 // the buffer is not alive or move the elements. | 6972 // the buffer is not alive or move the elements. |
| 6865 // TODO(ishell): introduce DisallowHeapAllocationCode scope here. | 6973 // TODO(ishell): introduce DisallowHeapAllocationCode scope here. |
| 6866 | 6974 |
| 6867 // Check if buffer has been neutered. | 6975 // Check if buffer has been neutered. |
| 6868 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); | 6976 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); |
| 6869 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, | 6977 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, |
| 6870 MachineType::Uint32()); | 6978 MachineType::Uint32()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6904 Node* length = is_jsarray ? LoadObjectField(object, JSArray::kLengthOffset) | 7012 Node* length = is_jsarray ? LoadObjectField(object, JSArray::kLengthOffset) |
| 6905 : LoadFixedArrayBaseLength(elements); | 7013 : LoadFixedArrayBaseLength(elements); |
| 6906 length = UntagParameter(length, parameter_mode); | 7014 length = UntagParameter(length, parameter_mode); |
| 6907 | 7015 |
| 6908 // In case value is stored into a fast smi array, assure that the value is | 7016 // In case value is stored into a fast smi array, assure that the value is |
| 6909 // a smi before manipulating the backing store. Otherwise the backing store | 7017 // a smi before manipulating the backing store. Otherwise the backing store |
| 6910 // may be left in an invalid state. | 7018 // may be left in an invalid state. |
| 6911 if (IsFastSmiElementsKind(elements_kind)) { | 7019 if (IsFastSmiElementsKind(elements_kind)) { |
| 6912 GotoUnless(TaggedIsSmi(value), bailout); | 7020 GotoUnless(TaggedIsSmi(value), bailout); |
| 6913 } else if (IsFastDoubleElementsKind(elements_kind)) { | 7021 } else if (IsFastDoubleElementsKind(elements_kind)) { |
| 6914 value = PrepareValueForWrite(value, Representation::Double(), bailout); | 7022 value = TryTaggedToFloat64(value, bailout); |
| 6915 } | 7023 } |
| 6916 | 7024 |
| 6917 if (IsGrowStoreMode(store_mode)) { | 7025 if (IsGrowStoreMode(store_mode)) { |
| 6918 elements = CheckForCapacityGrow(object, elements, elements_kind, length, | 7026 elements = CheckForCapacityGrow(object, elements, elements_kind, length, |
| 6919 key, parameter_mode, is_jsarray, bailout); | 7027 key, parameter_mode, is_jsarray, bailout); |
| 6920 } else { | 7028 } else { |
| 6921 GotoUnless(UintPtrLessThan(key, length), bailout); | 7029 GotoUnless(UintPtrLessThan(key, length), bailout); |
| 6922 | 7030 |
| 6923 if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW) && | 7031 if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW) && |
| 6924 IsFastSmiOrObjectElementsKind(elements_kind)) { | 7032 IsFastSmiOrObjectElementsKind(elements_kind)) { |
| (...skipping 2301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9226 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); | 9334 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); |
| 9227 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); | 9335 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); |
| 9228 | 9336 |
| 9229 // Check prototype chain if receiver does not have packed elements. | 9337 // Check prototype chain if receiver does not have packed elements. |
| 9230 Node* holey_elements = Word32And(elements_kind, Int32Constant(1)); | 9338 Node* holey_elements = Word32And(elements_kind, Int32Constant(1)); |
| 9231 return Word32Equal(holey_elements, Int32Constant(1)); | 9339 return Word32Equal(holey_elements, Int32Constant(1)); |
| 9232 } | 9340 } |
| 9233 | 9341 |
| 9234 } // namespace internal | 9342 } // namespace internal |
| 9235 } // namespace v8 | 9343 } // namespace v8 |
| OLD | NEW |