| OLD | NEW |
| 1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 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/builtins/builtins-utils-gen.h" | 5 #include "src/builtins/builtins-utils-gen.h" |
| 6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
| 7 #include "src/code-stub-assembler.h" | 7 #include "src/code-stub-assembler.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 return ArraySpeciesCreate(context(), o(), SmiConstant(0)); | 128 return ArraySpeciesCreate(context(), o(), SmiConstant(0)); |
| 129 } | 129 } |
| 130 | 130 |
| 131 Node* FilterProcessor(Node* k_value, Node* k) { | 131 Node* FilterProcessor(Node* k_value, Node* k) { |
| 132 // ii. Let selected be ToBoolean(? Call(callbackfn, T, kValue, k, O)). | 132 // ii. Let selected be ToBoolean(? Call(callbackfn, T, kValue, k, O)). |
| 133 Node* selected = CallJS(CodeFactory::Call(isolate()), context(), | 133 Node* selected = CallJS(CodeFactory::Call(isolate()), context(), |
| 134 callbackfn(), this_arg(), k_value, k, o()); | 134 callbackfn(), this_arg(), k_value, k, o()); |
| 135 Label true_continue(this, &to_), false_continue(this); | 135 Label true_continue(this, &to_), false_continue(this); |
| 136 BranchIfToBooleanIsTrue(selected, &true_continue, &false_continue); | 136 BranchIfToBooleanIsTrue(selected, &true_continue, &false_continue); |
| 137 Bind(&true_continue); | 137 Bind(&true_continue); |
| 138 // iii. If selected is true, then... | |
| 139 { | 138 { |
| 140 // 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue). | 139 // iii. If selected is true, then... |
| 141 CallRuntime(Runtime::kCreateDataProperty, context(), a(), to_.value(), | 140 Label after_work(this, &to_); |
| 142 k_value); | 141 Node* kind = nullptr; |
| 143 | 142 |
| 144 // 2. Increase to by 1. | 143 // If a() is a JSArray, we can have a fast path. |
| 145 to_.Bind(NumberInc(to_.value())); | 144 Label fast(this); |
| 146 Goto(&false_continue); | 145 Label runtime(this); |
| 146 Label object_push_pre(this), object_push(this), double_push(this); |
| 147 BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS, |
| 148 &fast, &runtime); |
| 149 |
| 150 Bind(&fast); |
| 151 { |
| 152 kind = EnsureArrayPushable(a(), &runtime); |
| 153 GotoIf(IsElementsKindGreaterThan(kind, FAST_HOLEY_SMI_ELEMENTS), |
| 154 &object_push_pre); |
| 155 |
| 156 BuildAppendJSArray(FAST_SMI_ELEMENTS, a(), k_value, &runtime); |
| 157 Goto(&after_work); |
| 158 } |
| 159 |
| 160 Bind(&object_push_pre); |
| 161 { |
| 162 Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS), |
| 163 &double_push, &object_push); |
| 164 } |
| 165 |
| 166 Bind(&object_push); |
| 167 { |
| 168 BuildAppendJSArray(FAST_ELEMENTS, a(), k_value, &runtime); |
| 169 Goto(&after_work); |
| 170 } |
| 171 |
| 172 Bind(&double_push); |
| 173 { |
| 174 BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, a(), k_value, &runtime); |
| 175 Goto(&after_work); |
| 176 } |
| 177 |
| 178 Bind(&runtime); |
| 179 { |
| 180 // 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue). |
| 181 CallRuntime(Runtime::kCreateDataProperty, context(), a(), to_.value(), |
| 182 k_value); |
| 183 Goto(&after_work); |
| 184 } |
| 185 |
| 186 Bind(&after_work); |
| 187 { |
| 188 // 2. Increase to by 1. |
| 189 to_.Bind(NumberInc(to_.value())); |
| 190 Goto(&false_continue); |
| 191 } |
| 147 } | 192 } |
| 148 Bind(&false_continue); | 193 Bind(&false_continue); |
| 149 return a(); | 194 return a(); |
| 150 } | 195 } |
| 151 | 196 |
| 152 Node* MapResultGenerator() { | 197 Node* MapResultGenerator() { |
| 153 // 5. Let A be ? ArraySpeciesCreate(O, len). | 198 // 5. Let A be ? ArraySpeciesCreate(O, len). |
| 154 return ArraySpeciesCreate(context(), o(), len_); | 199 return ArraySpeciesCreate(context(), o(), len_); |
| 155 } | 200 } |
| 156 | 201 |
| 157 Node* MapProcessor(Node* k_value, Node* k) { | 202 Node* MapProcessor(Node* k_value, Node* k) { |
| 158 // i. Let kValue be ? Get(O, Pk). Performed by the caller of MapProcessor. | 203 // i. Let kValue be ? Get(O, Pk). Performed by the caller of MapProcessor. |
| 159 // ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O). | 204 // ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O). |
| 160 Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(), | 205 Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(), |
| 161 callbackfn(), this_arg(), k_value, k, o()); | 206 callbackfn(), this_arg(), k_value, k, o()); |
| 162 | 207 |
| 163 // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). | 208 Label finished(this); |
| 164 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue); | 209 Node* kind = nullptr; |
| 210 Node* elements = nullptr; |
| 211 |
| 212 // If a() is a JSArray, we can have a fast path. |
| 213 // mode is SMI_PARAMETERS because k has tagged representation. |
| 214 ParameterMode mode = SMI_PARAMETERS; |
| 215 Label fast(this); |
| 216 Label runtime(this); |
| 217 Label object_push_pre(this), object_push(this), double_push(this); |
| 218 BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS, |
| 219 &fast, &runtime); |
| 220 |
| 221 Bind(&fast); |
| 222 { |
| 223 kind = EnsureArrayPushable(a(), &runtime); |
| 224 elements = LoadElements(a()); |
| 225 GotoIf(IsElementsKindGreaterThan(kind, FAST_HOLEY_SMI_ELEMENTS), |
| 226 &object_push_pre); |
| 227 TryStoreArrayElement(FAST_SMI_ELEMENTS, mode, &runtime, elements, k, |
| 228 mappedValue); |
| 229 Goto(&finished); |
| 230 } |
| 231 |
| 232 Bind(&object_push_pre); |
| 233 { |
| 234 Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS), &double_push, |
| 235 &object_push); |
| 236 } |
| 237 |
| 238 Bind(&object_push); |
| 239 { |
| 240 TryStoreArrayElement(FAST_ELEMENTS, mode, &runtime, elements, k, |
| 241 mappedValue); |
| 242 Goto(&finished); |
| 243 } |
| 244 |
| 245 Bind(&double_push); |
| 246 { |
| 247 TryStoreArrayElement(FAST_DOUBLE_ELEMENTS, mode, &runtime, elements, k, |
| 248 mappedValue); |
| 249 Goto(&finished); |
| 250 } |
| 251 |
| 252 Bind(&runtime); |
| 253 { |
| 254 // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). |
| 255 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue); |
| 256 Goto(&finished); |
| 257 } |
| 258 |
| 259 Bind(&finished); |
| 165 return a(); | 260 return a(); |
| 166 } | 261 } |
| 167 | 262 |
| 168 void NullPostLoopAction() {} | 263 void NullPostLoopAction() {} |
| 169 | 264 |
| 170 protected: | 265 protected: |
| 171 Node* context() { return context_; } | 266 Node* context() { return context_; } |
| 172 Node* receiver() { return receiver_; } | 267 Node* receiver() { return receiver_; } |
| 173 Node* new_target() { return new_target_; } | 268 Node* new_target() { return new_target_; } |
| 174 Node* o() { return o_; } | 269 Node* o() { return o_; } |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 | 651 |
| 557 BranchIfFastJSArray(o(), context(), | 652 BranchIfFastJSArray(o(), context(), |
| 558 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, | 653 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, |
| 559 &switch_on_elements_kind, slow); | 654 &switch_on_elements_kind, slow); |
| 560 | 655 |
| 561 Bind(&switch_on_elements_kind); | 656 Bind(&switch_on_elements_kind); |
| 562 // Select by ElementsKind | 657 // Select by ElementsKind |
| 563 Node* o_map = LoadMap(o()); | 658 Node* o_map = LoadMap(o()); |
| 564 Node* bit_field2 = LoadMapBitField2(o_map); | 659 Node* bit_field2 = LoadMapBitField2(o_map); |
| 565 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); | 660 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); |
| 566 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), | 661 Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS), |
| 567 &maybe_double_elements, &fast_elements); | 662 &maybe_double_elements, &fast_elements); |
| 568 | 663 |
| 569 ParameterMode mode = OptimalParameterMode(); | 664 ParameterMode mode = OptimalParameterMode(); |
| 570 Bind(&fast_elements); | 665 Bind(&fast_elements); |
| 571 { | 666 { |
| 572 VisitAllFastElementsOneKind(FAST_ELEMENTS, processor, slow, mode, | 667 VisitAllFastElementsOneKind(FAST_ELEMENTS, processor, slow, mode, |
| 573 direction); | 668 direction); |
| 574 | 669 |
| 575 action(this); | 670 action(this); |
| 576 | 671 |
| 577 // No exception, return success | 672 // No exception, return success |
| 578 Return(a_.value()); | 673 Return(a_.value()); |
| 579 } | 674 } |
| 580 | 675 |
| 581 Bind(&maybe_double_elements); | 676 Bind(&maybe_double_elements); |
| 582 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_DOUBLE_ELEMENTS)), | 677 Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_DOUBLE_ELEMENTS), slow, |
| 583 slow, &fast_double_elements); | 678 &fast_double_elements); |
| 584 | 679 |
| 585 Bind(&fast_double_elements); | 680 Bind(&fast_double_elements); |
| 586 { | 681 { |
| 587 VisitAllFastElementsOneKind(FAST_DOUBLE_ELEMENTS, processor, slow, mode, | 682 VisitAllFastElementsOneKind(FAST_DOUBLE_ELEMENTS, processor, slow, mode, |
| 588 direction); | 683 direction); |
| 589 | 684 |
| 590 action(this); | 685 action(this); |
| 591 | 686 |
| 592 // No exception, return success | 687 // No exception, return success |
| 593 Return(a_.value()); | 688 Return(a_.value()); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 CodeStubArguments args(this, ChangeInt32ToIntPtr(argc)); | 720 CodeStubArguments args(this, ChangeInt32ToIntPtr(argc)); |
| 626 Node* receiver = args.GetReceiver(); | 721 Node* receiver = args.GetReceiver(); |
| 627 Node* kind = nullptr; | 722 Node* kind = nullptr; |
| 628 | 723 |
| 629 Label fast(this); | 724 Label fast(this); |
| 630 BranchIfFastJSArray(receiver, context, FastJSArrayAccessMode::ANY_ACCESS, | 725 BranchIfFastJSArray(receiver, context, FastJSArrayAccessMode::ANY_ACCESS, |
| 631 &fast, &runtime); | 726 &fast, &runtime); |
| 632 | 727 |
| 633 Bind(&fast); | 728 Bind(&fast); |
| 634 { | 729 { |
| 635 // Disallow pushing onto prototypes. It might be the JSArray prototype. | |
| 636 // Disallow pushing onto non-extensible objects. | |
| 637 Comment("Disallow pushing onto prototypes"); | |
| 638 Node* map = LoadMap(receiver); | |
| 639 Node* bit_field2 = LoadMapBitField2(map); | |
| 640 int mask = static_cast<int>(Map::IsPrototypeMapBits::kMask) | | |
| 641 (1 << Map::kIsExtensible); | |
| 642 Node* test = Word32And(bit_field2, Int32Constant(mask)); | |
| 643 GotoIf(Word32NotEqual(test, Int32Constant(1 << Map::kIsExtensible)), | |
| 644 &runtime); | |
| 645 | |
| 646 // Disallow pushing onto arrays in dictionary named property mode. We need | |
| 647 // to figure out whether the length property is still writable. | |
| 648 Comment("Disallow pushing onto arrays in dictionary named property mode"); | |
| 649 GotoIf(IsDictionaryMap(map), &runtime); | |
| 650 | |
| 651 // Check whether the length property is writable. The length property is the | |
| 652 // only default named property on arrays. It's nonconfigurable, hence is | |
| 653 // guaranteed to stay the first property. | |
| 654 Node* descriptors = LoadMapDescriptors(map); | |
| 655 Node* details = | |
| 656 LoadFixedArrayElement(descriptors, DescriptorArray::ToDetailsIndex(0)); | |
| 657 GotoIf(IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask), | |
| 658 &runtime); | |
| 659 | |
| 660 arg_index.Bind(IntPtrConstant(0)); | 730 arg_index.Bind(IntPtrConstant(0)); |
| 661 kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); | 731 kind = EnsureArrayPushable(receiver, &runtime); |
| 662 | 732 GotoIf(IsElementsKindGreaterThan(kind, FAST_HOLEY_SMI_ELEMENTS), |
| 663 GotoIf(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)), | |
| 664 &object_push_pre); | 733 &object_push_pre); |
| 665 | 734 |
| 666 Node* new_length = BuildAppendJSArray(FAST_SMI_ELEMENTS, context, receiver, | 735 Node* new_length = BuildAppendJSArray(FAST_SMI_ELEMENTS, receiver, args, |
| 667 args, arg_index, &smi_transition); | 736 arg_index, &smi_transition); |
| 668 args.PopAndReturn(new_length); | 737 args.PopAndReturn(new_length); |
| 669 } | 738 } |
| 670 | 739 |
| 671 // If the argument is not a smi, then use a heavyweight SetProperty to | 740 // If the argument is not a smi, then use a heavyweight SetProperty to |
| 672 // transition the array for only the single next element. If the argument is | 741 // transition the array for only the single next element. If the argument is |
| 673 // a smi, the failure is due to some other reason and we should fall back on | 742 // a smi, the failure is due to some other reason and we should fall back on |
| 674 // the most generic implementation for the rest of the array. | 743 // the most generic implementation for the rest of the array. |
| 675 Bind(&smi_transition); | 744 Bind(&smi_transition); |
| 676 { | 745 { |
| 677 Node* arg = args.AtIndex(arg_index.value()); | 746 Node* arg = args.AtIndex(arg_index.value()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 689 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); | 758 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); |
| 690 GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)), | 759 GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)), |
| 691 &default_label); | 760 &default_label); |
| 692 | 761 |
| 693 GotoIfNotNumber(arg, &object_push); | 762 GotoIfNotNumber(arg, &object_push); |
| 694 Goto(&double_push); | 763 Goto(&double_push); |
| 695 } | 764 } |
| 696 | 765 |
| 697 Bind(&object_push_pre); | 766 Bind(&object_push_pre); |
| 698 { | 767 { |
| 699 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), | 768 Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS), &double_push, |
| 700 &double_push, &object_push); | 769 &object_push); |
| 701 } | 770 } |
| 702 | 771 |
| 703 Bind(&object_push); | 772 Bind(&object_push); |
| 704 { | 773 { |
| 705 Node* new_length = BuildAppendJSArray(FAST_ELEMENTS, context, receiver, | 774 Node* new_length = BuildAppendJSArray(FAST_ELEMENTS, receiver, args, |
| 706 args, arg_index, &default_label); | 775 arg_index, &default_label); |
| 707 args.PopAndReturn(new_length); | 776 args.PopAndReturn(new_length); |
| 708 } | 777 } |
| 709 | 778 |
| 710 Bind(&double_push); | 779 Bind(&double_push); |
| 711 { | 780 { |
| 712 Node* new_length = | 781 Node* new_length = BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, receiver, args, |
| 713 BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, context, receiver, args, | 782 arg_index, &double_transition); |
| 714 arg_index, &double_transition); | |
| 715 args.PopAndReturn(new_length); | 783 args.PopAndReturn(new_length); |
| 716 } | 784 } |
| 717 | 785 |
| 718 // If the argument is not a double, then use a heavyweight SetProperty to | 786 // If the argument is not a double, then use a heavyweight SetProperty to |
| 719 // transition the array for only the single next element. If the argument is | 787 // transition the array for only the single next element. If the argument is |
| 720 // a double, the failure is due to some other reason and we should fall back | 788 // a double, the failure is due to some other reason and we should fall back |
| 721 // on the most generic implementation for the rest of the array. | 789 // on the most generic implementation for the rest of the array. |
| 722 Bind(&double_transition); | 790 Bind(&double_transition); |
| 723 { | 791 { |
| 724 Node* arg = args.AtIndex(arg_index.value()); | 792 Node* arg = args.AtIndex(arg_index.value()); |
| (...skipping 1392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2117 { | 2185 { |
| 2118 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); | 2186 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); |
| 2119 CallRuntime(Runtime::kThrowTypeError, context, message, | 2187 CallRuntime(Runtime::kThrowTypeError, context, message, |
| 2120 HeapConstant(operation)); | 2188 HeapConstant(operation)); |
| 2121 Unreachable(); | 2189 Unreachable(); |
| 2122 } | 2190 } |
| 2123 } | 2191 } |
| 2124 | 2192 |
| 2125 } // namespace internal | 2193 } // namespace internal |
| 2126 } // namespace v8 | 2194 } // namespace v8 |
| OLD | NEW |