Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: src/builtins/builtins-array-gen.cc

Issue 2775503006: [builtins] Improve performance of array.prototype.filter and map (Closed)
Patch Set: Remove old impl. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 {
11 11
12 class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { 12 class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
13 public: 13 public:
14 explicit ArrayBuiltinCodeStubAssembler(compiler::CodeAssemblerState* state) 14 explicit ArrayBuiltinCodeStubAssembler(compiler::CodeAssemblerState* state)
15 : CodeStubAssembler(state), 15 : CodeStubAssembler(state),
16 k_(this, MachineRepresentation::kTagged, SmiConstant(0)), 16 k_(this, MachineRepresentation::kTagged, SmiConstant(0)),
17 a_(this, MachineRepresentation::kTagged, SmiConstant(0)), 17 a_(this, MachineRepresentation::kTagged, SmiConstant(0)),
18 to_(this, MachineRepresentation::kTagged, SmiConstant(0)) {} 18 to_(this, MachineRepresentation::kTagged, SmiConstant(0)) {}
19 19
20 typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm)> 20 typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm)>
21 BuiltinResultGenerator; 21 BuiltinResultGenerator;
22 22
23 typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)> 23 typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)>
24 BuiltinResultIndexInitializer; 24 BuiltinResultIndexInitializer;
25 25
26 typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm, 26 typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm,
27 Node* k_value, Node* k)> 27 ElementsKind o_kind, Node* k_value, Node* k)>
28 CallResultProcessor; 28 CallResultProcessor;
29 29
30 typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)> 30 typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)>
31 PostLoopAction; 31 PostLoopAction;
32 32
33 Node* ForEachResultGenerator() { return UndefinedConstant(); } 33 Node* ForEachResultGenerator() { return UndefinedConstant(); }
34 34
35 Node* ForEachProcessor(Node* k_value, Node* k) { 35 Node* ForEachProcessor(ElementsKind o_kind, Node* k_value, Node* k) {
36 CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), this_arg(), 36 CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), this_arg(),
37 k_value, k, o()); 37 k_value, k, o());
38 return a(); 38 return a();
39 } 39 }
40 40
41 Node* SomeResultGenerator() { return FalseConstant(); } 41 Node* SomeResultGenerator() { return FalseConstant(); }
42 42
43 Node* SomeProcessor(Node* k_value, Node* k) { 43 Node* SomeProcessor(ElementsKind o_kind, Node* k_value, Node* k) {
44 Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), 44 Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
45 this_arg(), k_value, k, o()); 45 this_arg(), k_value, k, o());
46 Label false_continue(this), return_true(this); 46 Label false_continue(this), return_true(this);
47 BranchIfToBooleanIsTrue(value, &return_true, &false_continue); 47 BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
48 Bind(&return_true); 48 Bind(&return_true);
49 Return(TrueConstant()); 49 Return(TrueConstant());
50 Bind(&false_continue); 50 Bind(&false_continue);
51 return a(); 51 return a();
52 } 52 }
53 53
54 Node* EveryResultGenerator() { return TrueConstant(); } 54 Node* EveryResultGenerator() { return TrueConstant(); }
55 55
56 Node* EveryProcessor(Node* k_value, Node* k) { 56 Node* EveryProcessor(ElementsKind o_kind, Node* k_value, Node* k) {
57 Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), 57 Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
58 this_arg(), k_value, k, o()); 58 this_arg(), k_value, k, o());
59 Label true_continue(this), return_false(this); 59 Label true_continue(this), return_false(this);
60 BranchIfToBooleanIsTrue(value, &true_continue, &return_false); 60 BranchIfToBooleanIsTrue(value, &true_continue, &return_false);
61 Bind(&return_false); 61 Bind(&return_false);
62 Return(FalseConstant()); 62 Return(FalseConstant());
63 Bind(&true_continue); 63 Bind(&true_continue);
64 return a(); 64 return a();
65 } 65 }
66 66
(...skipping 24 matching lines...) Expand all
91 // 9. Else initialValue is not present, 91 // 9. Else initialValue is not present,
92 Bind(&no_initial_value); 92 Bind(&no_initial_value);
93 93
94 // a. Let kPresent be false. 94 // a. Let kPresent be false.
95 a.Bind(TheHoleConstant()); 95 a.Bind(TheHoleConstant());
96 Goto(&done); 96 Goto(&done);
97 Bind(&done); 97 Bind(&done);
98 return a.value(); 98 return a.value();
99 } 99 }
100 100
101 Node* ReduceProcessor(Node* k_value, Node* k) { 101 Node* ReduceProcessor(ElementsKind o_kind, Node* k_value, Node* k) {
102 Variable result(this, MachineRepresentation::kTagged); 102 Variable result(this, MachineRepresentation::kTagged);
103 Label done(this, {&result}), initial(this); 103 Label done(this, {&result}), initial(this);
104 GotoIf(WordEqual(a(), TheHoleConstant()), &initial); 104 GotoIf(WordEqual(a(), TheHoleConstant()), &initial);
105 result.Bind(CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), 105 result.Bind(CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
106 UndefinedConstant(), a(), k_value, k, o())); 106 UndefinedConstant(), a(), k_value, k, o()));
107 Goto(&done); 107 Goto(&done);
108 108
109 Bind(&initial); 109 Bind(&initial);
110 result.Bind(k_value); 110 result.Bind(k_value);
111 Goto(&done); 111 Goto(&done);
112 112
113 Bind(&done); 113 Bind(&done);
114 return result.value(); 114 return result.value();
115 } 115 }
116 116
117 void ReducePostLoopAction() { 117 void ReducePostLoopAction() {
118 Label ok(this); 118 Label ok(this);
119 GotoIf(WordNotEqual(a(), TheHoleConstant()), &ok); 119 GotoIf(WordNotEqual(a(), TheHoleConstant()), &ok);
120 CallRuntime(Runtime::kThrowTypeError, context(), 120 CallRuntime(Runtime::kThrowTypeError, context(),
121 SmiConstant(MessageTemplate::kReduceNoInitial)); 121 SmiConstant(MessageTemplate::kReduceNoInitial));
122 Unreachable(); 122 Unreachable();
123 Bind(&ok); 123 Bind(&ok);
124 } 124 }
125 125
126 Node* FilterResultGenerator() { 126 Node* FilterResultGenerator() {
127 // 7. Let A be ArraySpeciesCreate(O, 0). 127 // 7. Let A be ArraySpeciesCreate(O, 0).
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(ElementsKind o_kind, 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 {
139 // iii. If selected is true, then...
140 Label after_work(this, &to_);
141 if (o_kind < DICTIONARY_ELEMENTS) {
danno 2017/04/03 15:35:27 Please use the predicates in elements-kind.h, e.g.
mvstanton 2017/04/06 08:57:36 Per our discussion, I'll just remove the o_kind pa
142 Node* kind = nullptr;
143
144 // If a() is a JSArray, we can have a fast path.
145 Label fast(this);
146 Label runtime(this);
147 Label object_push_pre(this), object_push(this), double_push(this);
danno 2017/04/03 15:35:27 I think you can make this slightly better. Since y
mvstanton 2017/04/06 08:57:36 Right, because of the vagaries of what can happen
148 BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS,
149 &fast, &runtime);
150
151 Bind(&fast);
152 {
153 kind = EnsureArrayPushable(a(), &runtime);
154 GotoIf(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)),
155 &object_push_pre);
156
157 BuildAppendJSArray(FAST_SMI_ELEMENTS, a(), k_value, &runtime);
158 Goto(&after_work);
159 }
160
161 Bind(&object_push_pre);
162 {
163 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)),
164 &double_push, &object_push);
165 }
166
167 Bind(&object_push);
168 {
169 BuildAppendJSArray(FAST_ELEMENTS, a(), k_value, &runtime);
170 Goto(&after_work);
171 }
172
173 Bind(&double_push);
174 {
175 BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, a(), k_value, &runtime);
176 Goto(&after_work);
177 }
178
179 Bind(&runtime);
180 }
181
140 // 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue). 182 // 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue).
141 CallRuntime(Runtime::kCreateDataProperty, context(), a(), to_.value(), 183 CallRuntime(Runtime::kCreateDataProperty, context(), a(), to_.value(),
142 k_value); 184 k_value);
185 Goto(&after_work);
143 186
144 // 2. Increase to by 1. 187 Bind(&after_work);
145 to_.Bind(NumberInc(to_.value())); 188 {
146 Goto(&false_continue); 189 // 2. Increase to by 1.
190 to_.Bind(NumberInc(to_.value()));
191 Goto(&false_continue);
192 }
147 } 193 }
148 Bind(&false_continue); 194 Bind(&false_continue);
149 return a(); 195 return a();
150 } 196 }
151 197
152 Node* MapResultGenerator() { 198 Node* MapResultGenerator() {
153 // 5. Let A be ? ArraySpeciesCreate(O, len). 199 // 5. Let A be ? ArraySpeciesCreate(O, len).
154 return ArraySpeciesCreate(context(), o(), len_); 200 return ArraySpeciesCreate(context(), o(), len_);
155 } 201 }
156 202
157 Node* MapProcessor(Node* k_value, Node* k) { 203 Node* MapProcessor(ElementsKind o_kind, Node* k_value, Node* k) {
158 // i. Let kValue be ? Get(O, Pk). Performed by the caller of MapProcessor. 204 // i. Let kValue be ? Get(O, Pk). Performed by the caller of MapProcessor.
159 // ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O). 205 // ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O).
160 Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(), 206 Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(),
161 callbackfn(), this_arg(), k_value, k, o()); 207 callbackfn(), this_arg(), k_value, k, o());
162 208
209 Label finished(this);
210 if (o_kind < DICTIONARY_ELEMENTS) {
211 Node* kind = nullptr;
212 Node* elements = nullptr;
213
214 // If a() is a JSArray, we can have a fast path.
215 // mode is SMI_PARAMETERS because k has tagged representation.
216 ParameterMode mode = SMI_PARAMETERS;
217 Label fast(this);
218 Label runtime(this);
219 Label object_push_pre(this), object_push(this), double_push(this);
220 BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS,
221 &fast, &runtime);
222
223 Bind(&fast);
224 {
225 kind = EnsureArrayPushable(a(), &runtime);
226 elements = LoadElements(a());
227 GotoIf(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)),
danno 2017/04/03 15:35:27 Consider adding/using existing predicates in code-
mvstanton 2017/04/06 08:57:36 I use a "greater than" metaphor to avoid multiple
228 &object_push_pre);
229
230 TryStoreArrayElement(FAST_SMI_ELEMENTS, mode, &runtime, elements, k,
231 mappedValue);
232 Goto(&finished);
233 }
234
235 Bind(&object_push_pre);
236 {
237 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)),
238 &double_push, &object_push);
239 }
240
241 Bind(&object_push);
242 {
243 TryStoreArrayElement(FAST_ELEMENTS, mode, &runtime, elements, k,
244 mappedValue);
245 Goto(&finished);
246 }
247
248 Bind(&double_push);
249 {
250 TryStoreArrayElement(FAST_DOUBLE_ELEMENTS, mode, &runtime, elements, k,
251 mappedValue);
252 Goto(&finished);
253 }
254
255 Bind(&runtime);
256 }
257
163 // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). 258 // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
164 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue); 259 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue);
260 Goto(&finished);
261
262 Bind(&finished);
165 return a(); 263 return a();
166 } 264 }
167 265
168 void NullPostLoopAction() {} 266 void NullPostLoopAction() {}
169 267
170 protected: 268 protected:
171 Node* context() { return context_; } 269 Node* context() { return context_; }
172 Node* receiver() { return receiver_; } 270 Node* receiver() { return receiver_; }
173 Node* new_target() { return new_target_; } 271 Node* new_target() { return new_target_; }
174 Node* o() { return o_; } 272 Node* o() { return o_; }
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 511
414 // d. If kPresent is true, then 512 // d. If kPresent is true, then
415 GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element); 513 GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element);
416 514
417 // i. Let kValue be Get(O, Pk). 515 // i. Let kValue be Get(O, Pk).
418 // ii. ReturnIfAbrupt(kValue). 516 // ii. ReturnIfAbrupt(kValue).
419 Node* k_value = GetProperty(context(), o(), k()); 517 Node* k_value = GetProperty(context(), o(), k());
420 518
421 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»). 519 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»).
422 // iv. ReturnIfAbrupt(funcResult). 520 // iv. ReturnIfAbrupt(funcResult).
423 a_.Bind(processor(this, k_value, k())); 521 a_.Bind(processor(this, DICTIONARY_ELEMENTS, k_value, k()));
danno 2017/04/03 15:35:27 Although I know what you mean here, the elements m
424 Goto(&done_element); 522 Goto(&done_element);
425 523
426 Bind(&done_element); 524 Bind(&done_element);
427 525
428 if (direction == ForEachDirection::kForward) { 526 if (direction == ForEachDirection::kForward) {
429 // e. Increase k by 1. 527 // e. Increase k by 1.
430 k_.Bind(NumberInc(k())); 528 k_.Bind(NumberInc(k()));
431 } else { 529 } else {
432 // e. Decrease k by 1. 530 // e. Decrease k by 1.
433 k_.Bind(NumberDec(k())); 531 k_.Bind(NumberDec(k()));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 Node* elements = LoadElements(o_); 564 Node* elements = LoadElements(o_);
467 Node* base_ptr = 565 Node* base_ptr =
468 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset); 566 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
469 Node* external_ptr = 567 Node* external_ptr =
470 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, 568 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
471 MachineType::Pointer()); 569 MachineType::Pointer());
472 Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr); 570 Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
473 Node* value = LoadFixedTypedArrayElementAsTagged(data_ptr, index, kind, 571 Node* value = LoadFixedTypedArrayElementAsTagged(data_ptr, index, kind,
474 SMI_PARAMETERS); 572 SMI_PARAMETERS);
475 k_.Bind(index); 573 k_.Bind(index);
476 a_.Bind(processor(this, value, index)); 574 a_.Bind(processor(this, kind, value, index));
477 }; 575 };
478 BuildFastLoop(list, SmiConstant(0), len_, body, 1, 576 BuildFastLoop(list, SmiConstant(0), len_, body, 1,
479 ParameterMode::SMI_PARAMETERS, IndexAdvanceMode::kPost); 577 ParameterMode::SMI_PARAMETERS, IndexAdvanceMode::kPost);
480 } 578 }
481 579
482 void VisitAllFastElementsOneKind(ElementsKind kind, 580 void VisitAllFastElementsOneKind(ElementsKind kind,
483 const CallResultProcessor& processor, 581 const CallResultProcessor& processor,
484 Label* array_changed, ParameterMode mode, 582 Label* array_changed, ParameterMode mode,
485 ForEachDirection direction) { 583 ForEachDirection direction) {
486 Comment("begin VisitAllFastElementsOneKind"); 584 Comment("begin VisitAllFastElementsOneKind");
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size); 620 Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size);
523 Node* value = nullptr; 621 Node* value = nullptr;
524 if (kind == FAST_ELEMENTS) { 622 if (kind == FAST_ELEMENTS) {
525 value = LoadObjectField(elements, offset); 623 value = LoadObjectField(elements, offset);
526 GotoIf(WordEqual(value, TheHoleConstant()), &hole_element); 624 GotoIf(WordEqual(value, TheHoleConstant()), &hole_element);
527 } else { 625 } else {
528 Node* double_value = 626 Node* double_value =
529 LoadDoubleWithHoleCheck(elements, offset, &hole_element); 627 LoadDoubleWithHoleCheck(elements, offset, &hole_element);
530 value = AllocateHeapNumberWithValue(double_value); 628 value = AllocateHeapNumberWithValue(double_value);
531 } 629 }
532 a_.Bind(processor(this, value, k())); 630 a_.Bind(processor(this, kind, value, k()));
533 Goto(&one_element_done); 631 Goto(&one_element_done);
534 632
535 Bind(&hole_element); 633 Bind(&hole_element);
536 // Check if o's prototype change unexpectedly has elements after the 634 // Check if o's prototype change unexpectedly has elements after the
537 // callback in the case of a hole. 635 // callback in the case of a hole.
538 BranchIfPrototypesHaveNoElements(o_map, &one_element_done, 636 BranchIfPrototypesHaveNoElements(o_map, &one_element_done,
539 array_changed); 637 array_changed);
540 638
541 Bind(&one_element_done); 639 Bind(&one_element_done);
542 }, 640 },
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 CodeStubArguments args(this, ChangeInt32ToIntPtr(argc)); 723 CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
626 Node* receiver = args.GetReceiver(); 724 Node* receiver = args.GetReceiver();
627 Node* kind = nullptr; 725 Node* kind = nullptr;
628 726
629 Label fast(this); 727 Label fast(this);
630 BranchIfFastJSArray(receiver, context, FastJSArrayAccessMode::ANY_ACCESS, 728 BranchIfFastJSArray(receiver, context, FastJSArrayAccessMode::ANY_ACCESS,
631 &fast, &runtime); 729 &fast, &runtime);
632 730
633 Bind(&fast); 731 Bind(&fast);
634 { 732 {
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)); 733 arg_index.Bind(IntPtrConstant(0));
661 kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); 734 kind = EnsureArrayPushable(receiver, &runtime);
662
663 GotoIf(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)), 735 GotoIf(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)),
664 &object_push_pre); 736 &object_push_pre);
665 737
666 Node* new_length = BuildAppendJSArray(FAST_SMI_ELEMENTS, context, receiver, 738 Node* new_length = BuildAppendJSArray(FAST_SMI_ELEMENTS, receiver, args,
667 args, arg_index, &smi_transition); 739 arg_index, &smi_transition);
668 args.PopAndReturn(new_length); 740 args.PopAndReturn(new_length);
669 } 741 }
670 742
671 // If the argument is not a smi, then use a heavyweight SetProperty to 743 // 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 744 // 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 745 // 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. 746 // the most generic implementation for the rest of the array.
675 Bind(&smi_transition); 747 Bind(&smi_transition);
676 { 748 {
677 Node* arg = args.AtIndex(arg_index.value()); 749 Node* arg = args.AtIndex(arg_index.value());
(...skipping 17 matching lines...) Expand all
695 } 767 }
696 768
697 Bind(&object_push_pre); 769 Bind(&object_push_pre);
698 { 770 {
699 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), 771 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)),
700 &double_push, &object_push); 772 &double_push, &object_push);
701 } 773 }
702 774
703 Bind(&object_push); 775 Bind(&object_push);
704 { 776 {
705 Node* new_length = BuildAppendJSArray(FAST_ELEMENTS, context, receiver, 777 Node* new_length = BuildAppendJSArray(FAST_ELEMENTS, receiver, args,
706 args, arg_index, &default_label); 778 arg_index, &default_label);
707 args.PopAndReturn(new_length); 779 args.PopAndReturn(new_length);
708 } 780 }
709 781
710 Bind(&double_push); 782 Bind(&double_push);
711 { 783 {
712 Node* new_length = 784 Node* new_length = BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, receiver, args,
713 BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, context, receiver, args, 785 arg_index, &double_transition);
714 arg_index, &double_transition);
715 args.PopAndReturn(new_length); 786 args.PopAndReturn(new_length);
716 } 787 }
717 788
718 // If the argument is not a double, then use a heavyweight SetProperty to 789 // 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 790 // 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 791 // 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. 792 // on the most generic implementation for the rest of the array.
722 Bind(&double_transition); 793 Bind(&double_transition);
723 { 794 {
724 Node* arg = args.AtIndex(arg_index.value()); 795 Node* arg = args.AtIndex(arg_index.value());
(...skipping 1392 matching lines...) Expand 10 before | Expand all | Expand 10 after
2117 { 2188 {
2118 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); 2189 Node* message = SmiConstant(MessageTemplate::kDetachedOperation);
2119 CallRuntime(Runtime::kThrowTypeError, context, message, 2190 CallRuntime(Runtime::kThrowTypeError, context, message,
2120 HeapConstant(operation)); 2191 HeapConstant(operation));
2121 Unreachable(); 2192 Unreachable();
2122 } 2193 }
2123 } 2194 }
2124 2195
2125 } // namespace internal 2196 } // namespace internal
2126 } // namespace v8 2197 } // namespace v8
OLDNEW
« no previous file with comments | « src/bootstrapper.cc ('k') | src/code-stub-assembler.h » ('j') | src/code-stub-assembler.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698