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

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

Issue 2752273003: [builtins] Implement Array.prototype.reduce in the CSA (Closed)
Patch Set: Cleanup Created 3 years, 9 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
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-factory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 16
17 typedef std::function<Node*(Node* o, Node* len)> BuiltinResultGenerator; 17 typedef std::function<std::pair<Node*, Node*>(
danno 2017/03/17 10:26:31 Per Camillo's comments, I am going to add comments
18 typedef std::function<void(Node* a, Node* pK, Node* value)> 18 ArrayBuiltinCodeStubAssembler* masm, Node* this_arg, Node* o, Node* len)>
19 BuiltinResultGenerator;
20
21 typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm,
22 Node* context, Node* callbackfn, Node* this_arg,
23 Node* k_value, Node* k, Node* o, Node* a)>
19 CallResultProcessor; 24 CallResultProcessor;
20 25
26 typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm, Node* context,
27 Node* a)>
28 PostLoopAction;
29
21 void GenerateIteratingArrayBuiltinBody( 30 void GenerateIteratingArrayBuiltinBody(
22 const char* name, const BuiltinResultGenerator& generator, 31 const char* name, const BuiltinResultGenerator& generator,
23 const CallResultProcessor& processor, 32 const CallResultProcessor& processor, const PostLoopAction& action,
24 const Callable& slow_case_continuation) { 33 const Callable& slow_case_continuation) {
25 Node* receiver = Parameter(IteratingArrayBuiltinDescriptor::kReceiver); 34 Node* receiver = Parameter(IteratingArrayBuiltinDescriptor::kReceiver);
26 Node* callbackfn = Parameter(IteratingArrayBuiltinDescriptor::kCallback); 35 Node* callbackfn = Parameter(IteratingArrayBuiltinDescriptor::kCallback);
27 Node* this_arg = Parameter(IteratingArrayBuiltinDescriptor::kThisArg); 36 Node* this_arg = Parameter(IteratingArrayBuiltinDescriptor::kThisArg);
28 Node* context = Parameter(IteratingArrayBuiltinDescriptor::kContext); 37 Node* context = Parameter(IteratingArrayBuiltinDescriptor::kContext);
29 Node* new_target = Parameter(IteratingArrayBuiltinDescriptor::kNewTarget); 38 Node* new_target = Parameter(IteratingArrayBuiltinDescriptor::kNewTarget);
30 39
31 Variable k(this, MachineRepresentation::kTagged, SmiConstant(0)); 40 Variable k(this, MachineRepresentation::kTagged, SmiConstant(0));
32 Label non_array(this), slow(this, &k), array_changes(this, &k); 41 Variable a(this, MachineRepresentation::kTagged, UndefinedConstant());
42 Label non_array(this), slow(this, {&k, &a}), array_changes(this, {&k, &a});
33 43
34 // TODO(danno): Seriously? Do we really need to throw the exact error 44 // TODO(danno): Seriously? Do we really need to throw the exact error
35 // message on null and undefined so that the webkit tests pass? 45 // message on null and undefined so that the webkit tests pass?
36 Label throw_null_undefined_exception(this, Label::kDeferred); 46 Label throw_null_undefined_exception(this, Label::kDeferred);
37 GotoIf(WordEqual(receiver, NullConstant()), 47 GotoIf(WordEqual(receiver, NullConstant()),
38 &throw_null_undefined_exception); 48 &throw_null_undefined_exception);
39 GotoIf(WordEqual(receiver, UndefinedConstant()), 49 GotoIf(WordEqual(receiver, UndefinedConstant()),
40 &throw_null_undefined_exception); 50 &throw_null_undefined_exception);
41 51
42 // By the book: taken directly from the ECMAScript 2015 specification 52 // By the book: taken directly from the ECMAScript 2015 specification
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 88
79 Bind(&type_exception); 89 Bind(&type_exception);
80 { 90 {
81 CallRuntime(Runtime::kThrowTypeError, context, 91 CallRuntime(Runtime::kThrowTypeError, context,
82 SmiConstant(MessageTemplate::kCalledNonCallable), callbackfn); 92 SmiConstant(MessageTemplate::kCalledNonCallable), callbackfn);
83 Unreachable(); 93 Unreachable();
84 } 94 }
85 95
86 Bind(&done); 96 Bind(&done);
87 97
88 Node* a = generator(o, len); 98 Node* initial_a;
99 Node* initial_k;
100 std::tie(initial_a, initial_k) = generator(this, this_arg, o, len);
89 101
90 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. 102 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
91 // [Already done by the arguments adapter] 103 // [Already done by the arguments adapter]
92 104
93 HandleFastElements(context, this_arg, o, len, callbackfn, processor, a, k, 105 // 7. Let k be 0.
94 &slow); 106 k.Bind(initial_k);
107 a.Bind(initial_a);
95 108
96 // 7. Let k be 0. 109 HandleFastElements(context, this_arg, o, len, callbackfn, processor, action,
97 // Already done above in initialization of the Variable k 110 a, k, &slow);
98 111
99 Bind(&slow); 112 Bind(&slow);
100 113
101 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, 114 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
102 MachineType::TaggedPointer()); 115 MachineType::TaggedPointer());
103 TailCallStub( 116 TailCallStub(
104 slow_case_continuation, context, target, new_target, 117 slow_case_continuation, context, target, new_target,
105 Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity), 118 Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity),
106 receiver, callbackfn, this_arg, a, o, k.value(), len); 119 receiver, callbackfn, this_arg, a.value(), o, k.value(), len);
107 } 120 }
108 121
109 void GenerateIteratingArrayBuiltinLoopContinuation( 122 void GenerateIteratingArrayBuiltinLoopContinuation(
110 const CallResultProcessor& processor) { 123 const CallResultProcessor& processor, const PostLoopAction& action) {
111 Node* callbackfn = 124 Node* callbackfn =
112 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kCallback); 125 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kCallback);
113 Node* this_arg = 126 Node* this_arg =
114 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kThisArg); 127 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kThisArg);
115 Node* a = 128 Node* initial_a =
116 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kArray); 129 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kArray);
117 Node* o = 130 Node* o =
118 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kObject); 131 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kObject);
119 Node* initial_k = 132 Node* initial_k =
120 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kInitialK); 133 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kInitialK);
121 Node* len = 134 Node* len =
122 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kLength); 135 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kLength);
123 Node* context = 136 Node* context =
124 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kContext); 137 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kContext);
125 138
126 // 8. Repeat, while k < len 139 // 8. Repeat, while k < len
127 Variable k(this, MachineRepresentation::kTagged, initial_k); 140 Variable k(this, MachineRepresentation::kTagged, initial_k);
128 Label loop(this, &k); 141 Variable a(this, MachineRepresentation::kTagged, initial_a);
142 Label loop(this, {&k, &a});
129 Label after_loop(this); 143 Label after_loop(this);
130 Goto(&loop); 144 Goto(&loop);
131 Bind(&loop); 145 Bind(&loop);
132 { 146 {
133 GotoUnlessNumberLessThan(k.value(), len, &after_loop); 147 GotoUnlessNumberLessThan(k.value(), len, &after_loop);
134 148
135 Label done_element(this); 149 Label done_element(this);
136 // a. Let Pk be ToString(k). 150 // a. Let Pk be ToString(k).
137 Node* p_k = ToString(context, k.value()); 151 Node* p_k = ToString(context, k.value());
138 152
139 // b. Let kPresent be HasProperty(O, Pk). 153 // b. Let kPresent be HasProperty(O, Pk).
140 // c. ReturnIfAbrupt(kPresent). 154 // c. ReturnIfAbrupt(kPresent).
141 Node* k_present = HasProperty(o, p_k, context); 155 Node* k_present = HasProperty(o, p_k, context);
142 156
143 // d. If kPresent is true, then 157 // d. If kPresent is true, then
144 GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element); 158 GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element);
145 159
146 // i. Let kValue be Get(O, Pk). 160 // i. Let kValue be Get(O, Pk).
147 // ii. ReturnIfAbrupt(kValue). 161 // ii. ReturnIfAbrupt(kValue).
148 Node* k_value = GetProperty(context, o, k.value()); 162 Node* k_value = GetProperty(context, o, k.value());
149 163
150 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»). 164 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»).
151 // iv. ReturnIfAbrupt(funcResult). 165 // iv. ReturnIfAbrupt(funcResult).
152 Node* result = CallJS(CodeFactory::Call(isolate()), context, callbackfn, 166 a.Bind(processor(this, context, callbackfn, this_arg, k_value, k.value(),
153 this_arg, k_value, k.value(), o); 167 o, a.value()));
154
155 processor(a, p_k, result);
156 Goto(&done_element); 168 Goto(&done_element);
157 Bind(&done_element); 169 Bind(&done_element);
158 170
159 // e. Increase k by 1. 171 // e. Increase k by 1.
160 k.Bind(NumberInc(k.value())); 172 k.Bind(NumberInc(k.value()));
161 Goto(&loop); 173 Goto(&loop);
162 } 174 }
163 Bind(&after_loop); 175 Bind(&after_loop);
164 Return(a); 176
177 action(this, context, a.value());
178
179 Return(a.value());
165 } 180 }
166 181
167 void ForEachProcessor(Node* a, Node* p_k, Node* value) {} 182 std::pair<Node*, Node*> ForEachResultGenerator(Node* this_arg, Node* o,
183 Node* len) {
184 return std::make_pair(UndefinedConstant(), SmiConstant(0));
185 }
168 186
169 void SomeProcessor(Node* a, Node* p_k, Node* value) { 187 Node* ForEachProcessor(Node* context, Node* callbackfn, Node* this_arg,
188 Node* k_value, Node* k, Node* o, Node* a) {
189 CallJS(CodeFactory::Call(isolate()), context, callbackfn, this_arg, k_value,
190 k, o);
191 return a;
192 }
193
194 std::pair<Node*, Node*> SomeResultGenerator(Node* this_arg, Node* o,
195 Node* len) {
196 return std::make_pair(FalseConstant(), SmiConstant(0));
197 }
198
199 Node* SomeProcessor(Node* context, Node* callbackfn, Node* this_arg,
200 Node* k_value, Node* k, Node* o, Node* a) {
201 Node* value = CallJS(CodeFactory::Call(isolate()), context, callbackfn,
202 this_arg, k_value, k, o);
170 Label false_continue(this), return_true(this); 203 Label false_continue(this), return_true(this);
171 BranchIfToBooleanIsTrue(value, &return_true, &false_continue); 204 BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
172 Bind(&return_true); 205 Bind(&return_true);
173 Return(TrueConstant()); 206 Return(TrueConstant());
174 Bind(&false_continue); 207 Bind(&false_continue);
208 return a;
175 } 209 }
176 210
177 void EveryProcessor(Node* a, Node* p_k, Node* value) { 211 std::pair<Node*, Node*> EveryResultGenerator(Node* this_arg, Node* o,
212 Node* len) {
213 return std::make_pair(TrueConstant(), SmiConstant(0));
214 }
215
216 Node* EveryProcessor(Node* context, Node* callbackfn, Node* this_arg,
217 Node* k_value, Node* k, Node* o, Node* a) {
218 Node* value = CallJS(CodeFactory::Call(isolate()), context, callbackfn,
219 this_arg, k_value, k, o);
178 Label true_continue(this), return_false(this); 220 Label true_continue(this), return_false(this);
179 BranchIfToBooleanIsTrue(value, &true_continue, &return_false); 221 BranchIfToBooleanIsTrue(value, &true_continue, &return_false);
180 Bind(&return_false); 222 Bind(&return_false);
181 Return(FalseConstant()); 223 Return(FalseConstant());
182 Bind(&true_continue); 224 Bind(&true_continue);
225 return a;
183 } 226 }
184 227
228 std::pair<Node*, Node*> ReduceResultGenerator(Node* initial_value, Node* o,
229 Node* len) {
230 Variable a(this, MachineRepresentation::kTagged, UndefinedConstant());
231 Label no_initial_value(this), has_initial_value(this), done(this, {&a});
232
233 // 8. If initialValue is present, then
234 Node* parent_frame_ptr = LoadParentFramePointer();
235 Node* marker_or_function = LoadBufferObject(
236 parent_frame_ptr, CommonFrameConstants::kContextOrFrameTypeOffset);
237 GotoIf(
238 MarkerIsNotFrameType(marker_or_function, StackFrame::ARGUMENTS_ADAPTOR),
239 &has_initial_value);
240
241 // Has arguments adapter, check count.
242 Node* adapted_parameter_count = LoadBufferObject(
243 parent_frame_ptr, ArgumentsAdaptorFrameConstants::kLengthOffset);
244 Branch(SmiLessThan(adapted_parameter_count,
245 SmiConstant(IteratingArrayBuiltinDescriptor::kThisArg)),
246 &no_initial_value, &has_initial_value);
247
248 // a. Set accumulator to initialValue.
249 Bind(&has_initial_value);
250 a.Bind(initial_value);
251 Goto(&done);
252
253 // 9. Else initialValue is not present,
254 Bind(&no_initial_value);
255
256 // a. Let kPresent be false.
257 a.Bind(TheHoleConstant());
258 Goto(&done);
259 Bind(&done);
260 return std::make_pair(a.value(), SmiConstant(0));
261 }
262
263 Node* ReduceProcessor(Node* context, Node* callbackfn, Node* this_arg,
264 Node* k_value, Node* k, Node* o, Node* a) {
265 Variable result(this, MachineRepresentation::kTagged);
266 Label done(this, {&result}), initial(this);
267 GotoIf(WordEqual(a, TheHoleConstant()), &initial);
268 result.Bind(CallJS(CodeFactory::Call(isolate()), context, callbackfn,
269 UndefinedConstant(), a, k_value, k, o));
270 Goto(&done);
271
272 Bind(&initial);
273 result.Bind(k_value);
274 Goto(&done);
275
276 Bind(&done);
277 return result.value();
278 }
279
280 void ReducePostLoopAction(Node* context, Node* a) {
281 Label ok(this);
282 GotoIf(WordNotEqual(a, TheHoleConstant()), &ok);
283 CallRuntime(Runtime::kThrowTypeError, context,
284 SmiConstant(MessageTemplate::kReduceNoInitial));
285 Unreachable();
286 Bind(&ok);
287 }
288
289 void NullPostLoopAction(Node* context, Node* a) {}
290
185 private: 291 private:
186 Node* VisitAllFastElementsOneKind(Node* context, ElementsKind kind, 292 Node* VisitAllFastElementsOneKind(Node* context, ElementsKind kind,
187 Node* this_arg, Node* o, Node* len, 293 Node* this_arg, Node* o, Node* len,
188 Node* callbackfn, 294 Node* callbackfn,
189 const CallResultProcessor& processor, 295 const CallResultProcessor& processor,
190 Node* a, Label* array_changed, 296 Variable& a, Label* array_changed,
191 ParameterMode mode) { 297 ParameterMode mode) {
192 Comment("begin VisitAllFastElementsOneKind"); 298 Comment("begin VisitAllFastElementsOneKind");
193 Variable original_map(this, MachineRepresentation::kTagged); 299 Variable original_map(this, MachineRepresentation::kTagged);
194 original_map.Bind(LoadMap(o)); 300 original_map.Bind(LoadMap(o));
195 VariableList list({&original_map}, zone()); 301 VariableList list({&original_map, &a}, zone());
196 Node* last_index = nullptr; 302 Node* last_index = nullptr;
197 BuildFastLoop( 303 BuildFastLoop(
198 list, IntPtrOrSmiConstant(0, mode), TaggedToParameter(len, mode), 304 list, IntPtrOrSmiConstant(0, mode), TaggedToParameter(len, mode),
199 [=, &original_map, &last_index](Node* index) { 305 [=, &a, &original_map, &last_index](Node* index) {
200 last_index = index; 306 last_index = index;
201 Label one_element_done(this), hole_element(this); 307 Label one_element_done(this), hole_element(this);
202 308
203 // Check if o's map has changed during the callback. If so, we have to 309 // Check if o's map has changed during the callback. If so, we have to
204 // fall back to the slower spec implementation for the rest of the 310 // fall back to the slower spec implementation for the rest of the
205 // iteration. 311 // iteration.
206 Node* o_map = LoadMap(o); 312 Node* o_map = LoadMap(o);
207 GotoIf(WordNotEqual(o_map, original_map.value()), array_changed); 313 GotoIf(WordNotEqual(o_map, original_map.value()), array_changed);
208 314
209 // Check if o's length has changed during the callback and if the 315 // Check if o's length has changed during the callback and if the
(...skipping 14 matching lines...) Expand all
224 Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size); 330 Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size);
225 Node* value = nullptr; 331 Node* value = nullptr;
226 if (kind == FAST_ELEMENTS) { 332 if (kind == FAST_ELEMENTS) {
227 value = LoadObjectField(elements, offset); 333 value = LoadObjectField(elements, offset);
228 GotoIf(WordEqual(value, TheHoleConstant()), &hole_element); 334 GotoIf(WordEqual(value, TheHoleConstant()), &hole_element);
229 } else { 335 } else {
230 Node* double_value = 336 Node* double_value =
231 LoadDoubleWithHoleCheck(elements, offset, &hole_element); 337 LoadDoubleWithHoleCheck(elements, offset, &hole_element);
232 value = AllocateHeapNumberWithValue(double_value); 338 value = AllocateHeapNumberWithValue(double_value);
233 } 339 }
234 Node* result = CallJS(CodeFactory::Call(isolate()), context, 340 a.Bind(processor(this, context, callbackfn, this_arg, value,
235 callbackfn, this_arg, value, tagged_index, o); 341 tagged_index, o, a.value()));
236 processor(a, tagged_index, result);
237 Goto(&one_element_done); 342 Goto(&one_element_done);
238 343
239 Bind(&hole_element); 344 Bind(&hole_element);
240 // Check if o's prototype change unexpectedly has elements after the 345 // Check if o's prototype change unexpectedly has elements after the
241 // callback in the case of a hole. 346 // callback in the case of a hole.
242 BranchIfPrototypesHaveNoElements(o_map, &one_element_done, 347 BranchIfPrototypesHaveNoElements(o_map, &one_element_done,
243 array_changed); 348 array_changed);
244 349
245 Bind(&one_element_done); 350 Bind(&one_element_done);
246 }, 351 },
247 1, mode, IndexAdvanceMode::kPost); 352 1, mode, IndexAdvanceMode::kPost);
248 Comment("end VisitAllFastElementsOneKind"); 353 Comment("end VisitAllFastElementsOneKind");
249 return last_index; 354 return last_index;
250 } 355 }
251 356
252 void HandleFastElements(Node* context, Node* this_arg, Node* o, Node* len, 357 void HandleFastElements(Node* context, Node* this_arg, Node* o, Node* len,
253 Node* callbackfn, CallResultProcessor processor, 358 Node* callbackfn,
254 Node* a, Variable& k, Label* slow) { 359 const CallResultProcessor& processor,
360 const PostLoopAction& action, Variable& a,
361 Variable& k, Label* slow) {
255 Label switch_on_elements_kind(this), fast_elements(this), 362 Label switch_on_elements_kind(this), fast_elements(this),
256 maybe_double_elements(this), fast_double_elements(this); 363 maybe_double_elements(this), fast_double_elements(this);
257 364
258 Comment("begin HandleFastElements"); 365 Comment("begin HandleFastElements");
259 // Non-smi lengths must use the slow path. 366 // Non-smi lengths must use the slow path.
260 GotoIf(TaggedIsNotSmi(len), slow); 367 GotoIf(TaggedIsNotSmi(len), slow);
261 368
262 BranchIfFastJSArray(o, context, 369 BranchIfFastJSArray(o, context,
263 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, 370 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ,
264 &switch_on_elements_kind, slow); 371 &switch_on_elements_kind, slow);
265 372
266 Bind(&switch_on_elements_kind); 373 Bind(&switch_on_elements_kind);
267 // Select by ElementsKind 374 // Select by ElementsKind
268 Node* o_map = LoadMap(o); 375 Node* o_map = LoadMap(o);
269 Node* bit_field2 = LoadMapBitField2(o_map); 376 Node* bit_field2 = LoadMapBitField2(o_map);
270 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); 377 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
271 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), 378 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)),
272 &maybe_double_elements, &fast_elements); 379 &maybe_double_elements, &fast_elements);
273 380
274 ParameterMode mode = OptimalParameterMode(); 381 ParameterMode mode = OptimalParameterMode();
275 Bind(&fast_elements); 382 Bind(&fast_elements);
276 { 383 {
277 Label array_changed(this, Label::kDeferred); 384 Label array_changed(this, Label::kDeferred);
278 Node* last_index = VisitAllFastElementsOneKind( 385 Node* last_index = VisitAllFastElementsOneKind(
279 context, FAST_ELEMENTS, this_arg, o, len, callbackfn, processor, a, 386 context, FAST_ELEMENTS, this_arg, o, len, callbackfn, processor, a,
280 &array_changed, mode); 387 &array_changed, mode);
281 388
389 action(this, context, a.value());
390
282 // No exception, return success 391 // No exception, return success
283 Return(a); 392 Return(a.value());
284 393
285 Bind(&array_changed); 394 Bind(&array_changed);
286 k.Bind(ParameterToTagged(last_index, mode)); 395 k.Bind(ParameterToTagged(last_index, mode));
287 Goto(slow); 396 Goto(slow);
288 } 397 }
289 398
290 Bind(&maybe_double_elements); 399 Bind(&maybe_double_elements);
291 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_DOUBLE_ELEMENTS)), 400 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_DOUBLE_ELEMENTS)),
292 slow, &fast_double_elements); 401 slow, &fast_double_elements);
293 402
294 Bind(&fast_double_elements); 403 Bind(&fast_double_elements);
295 { 404 {
296 Label array_changed(this, Label::kDeferred); 405 Label array_changed(this, Label::kDeferred);
297 Node* last_index = VisitAllFastElementsOneKind( 406 Node* last_index = VisitAllFastElementsOneKind(
298 context, FAST_DOUBLE_ELEMENTS, this_arg, o, len, callbackfn, 407 context, FAST_DOUBLE_ELEMENTS, this_arg, o, len, callbackfn,
299 processor, a, &array_changed, mode); 408 processor, a, &array_changed, mode);
300 409
410 action(this, context, a.value());
411
301 // No exception, return success 412 // No exception, return success
302 Return(a); 413 Return(a.value());
303 414
304 Bind(&array_changed); 415 Bind(&array_changed);
305 k.Bind(ParameterToTagged(last_index, mode)); 416 k.Bind(ParameterToTagged(last_index, mode));
306 Goto(slow); 417 Goto(slow);
307 } 418 }
308 } 419 }
309 }; 420 };
310 421
311 TF_BUILTIN(FastArrayPush, CodeStubAssembler) { 422 TF_BUILTIN(FastArrayPush, CodeStubAssembler) {
312 Variable arg_index(this, MachineType::PointerRepresentation()); 423 Variable arg_index(this, MachineType::PointerRepresentation());
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 { 568 {
458 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, 569 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
459 MachineType::TaggedPointer()); 570 MachineType::TaggedPointer());
460 TailCallStub(CodeFactory::ArrayPush(isolate()), context, target, new_target, 571 TailCallStub(CodeFactory::ArrayPush(isolate()), context, target, new_target,
461 argc); 572 argc);
462 } 573 }
463 } 574 }
464 575
465 TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) { 576 TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) {
466 GenerateIteratingArrayBuiltinLoopContinuation( 577 GenerateIteratingArrayBuiltinLoopContinuation(
467 [this](Node* a, Node* p_k, Node* value) { 578 &ArrayBuiltinCodeStubAssembler::ForEachProcessor,
468 ForEachProcessor(a, p_k, value); 579 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
469 });
470 } 580 }
471 581
472 TF_BUILTIN(ArrayForEach, ArrayBuiltinCodeStubAssembler) { 582 TF_BUILTIN(ArrayForEach, ArrayBuiltinCodeStubAssembler) {
473 GenerateIteratingArrayBuiltinBody( 583 GenerateIteratingArrayBuiltinBody(
474 "Array.prototype.forEach", 584 "Array.prototype.forEach",
475 [=](Node*, Node*) { return UndefinedConstant(); }, 585 &ArrayBuiltinCodeStubAssembler::ForEachResultGenerator,
476 [this](Node* a, Node* p_k, Node* value) { 586 &ArrayBuiltinCodeStubAssembler::ForEachProcessor,
477 ForEachProcessor(a, p_k, value); 587 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
478 },
479 CodeFactory::ArrayForEachLoopContinuation(isolate())); 588 CodeFactory::ArrayForEachLoopContinuation(isolate()));
480 } 589 }
481 590
482 TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) { 591 TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) {
483 GenerateIteratingArrayBuiltinLoopContinuation( 592 GenerateIteratingArrayBuiltinLoopContinuation(
484 [this](Node* a, Node* p_k, Node* value) { 593 &ArrayBuiltinCodeStubAssembler::SomeProcessor,
485 SomeProcessor(a, p_k, value); 594 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
486 });
487 } 595 }
488 596
489 TF_BUILTIN(ArraySome, ArrayBuiltinCodeStubAssembler) { 597 TF_BUILTIN(ArraySome, ArrayBuiltinCodeStubAssembler) {
490 GenerateIteratingArrayBuiltinBody( 598 GenerateIteratingArrayBuiltinBody(
491 "Array.prototype.some", [=](Node*, Node*) { return FalseConstant(); }, 599 "Array.prototype.some",
492 [this](Node* a, Node* p_k, Node* value) { SomeProcessor(a, p_k, value); }, 600 &ArrayBuiltinCodeStubAssembler::SomeResultGenerator,
601 &ArrayBuiltinCodeStubAssembler::SomeProcessor,
602 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
493 CodeFactory::ArraySomeLoopContinuation(isolate())); 603 CodeFactory::ArraySomeLoopContinuation(isolate()));
494 } 604 }
495 605
496 TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) { 606 TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) {
497 GenerateIteratingArrayBuiltinLoopContinuation( 607 GenerateIteratingArrayBuiltinLoopContinuation(
498 [this](Node* a, Node* p_k, Node* value) { 608 &ArrayBuiltinCodeStubAssembler::EveryProcessor,
499 EveryProcessor(a, p_k, value); 609 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
500 });
501 } 610 }
502 611
503 TF_BUILTIN(ArrayEvery, ArrayBuiltinCodeStubAssembler) { 612 TF_BUILTIN(ArrayEvery, ArrayBuiltinCodeStubAssembler) {
504 GenerateIteratingArrayBuiltinBody( 613 GenerateIteratingArrayBuiltinBody(
505 "Array.prototype.every", [=](Node*, Node*) { return TrueConstant(); }, 614 "Array.prototype.every",
506 [this](Node* a, Node* p_k, Node* value) { 615 &ArrayBuiltinCodeStubAssembler::EveryResultGenerator,
507 EveryProcessor(a, p_k, value); 616 &ArrayBuiltinCodeStubAssembler::EveryProcessor,
508 }, 617 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
509 CodeFactory::ArrayEveryLoopContinuation(isolate())); 618 CodeFactory::ArrayEveryLoopContinuation(isolate()));
510 } 619 }
511 620
621 TF_BUILTIN(ArrayReduceLoopContinuation, ArrayBuiltinCodeStubAssembler) {
622 GenerateIteratingArrayBuiltinLoopContinuation(
623 &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
624 &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction);
625 }
626
627 TF_BUILTIN(ArrayReduce, ArrayBuiltinCodeStubAssembler) {
628 GenerateIteratingArrayBuiltinBody(
629 "Array.prototype.reduce",
630 &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
631 &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
632 &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
633 CodeFactory::ArrayReduceLoopContinuation(isolate()));
634 }
635
512 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { 636 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) {
513 Node* object = Parameter(1); 637 Node* object = Parameter(1);
514 Node* context = Parameter(4); 638 Node* context = Parameter(4);
515 639
516 Label call_runtime(this), return_true(this), return_false(this); 640 Label call_runtime(this), return_true(this), return_false(this);
517 641
518 GotoIf(TaggedIsSmi(object), &return_false); 642 GotoIf(TaggedIsSmi(object), &return_false);
519 Node* instance_type = LoadInstanceType(object); 643 Node* instance_type = LoadInstanceType(object);
520 644
521 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)), 645 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)),
(...skipping 1034 matching lines...) Expand 10 before | Expand all | Expand 10 after
1556 { 1680 {
1557 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); 1681 Node* message = SmiConstant(MessageTemplate::kDetachedOperation);
1558 CallRuntime(Runtime::kThrowTypeError, context, message, 1682 CallRuntime(Runtime::kThrowTypeError, context, message,
1559 HeapConstant(operation)); 1683 HeapConstant(operation));
1560 Unreachable(); 1684 Unreachable();
1561 } 1685 }
1562 } 1686 }
1563 1687
1564 } // namespace internal 1688 } // namespace internal
1565 } // namespace v8 1689 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698