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

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

Issue 2776433003: [builtins] Implement Array.prototype.reduceRight in the CSA (Closed)
Patch Set: Add back accidental removals 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
« 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 {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 callbackfn_ = callbackfn; 187 callbackfn_ = callbackfn;
188 this_arg_ = this_arg; 188 this_arg_ = this_arg;
189 189
190 k_.Bind(SmiConstant(0)); 190 k_.Bind(SmiConstant(0));
191 a_.Bind(UndefinedConstant()); 191 a_.Bind(UndefinedConstant());
192 } 192 }
193 193
194 void GenerateIteratingArrayBuiltinBody( 194 void GenerateIteratingArrayBuiltinBody(
195 const char* name, const BuiltinResultGenerator& generator, 195 const char* name, const BuiltinResultGenerator& generator,
196 const CallResultProcessor& processor, const PostLoopAction& action, 196 const CallResultProcessor& processor, const PostLoopAction& action,
197 const Callable& slow_case_continuation) { 197 const Callable& slow_case_continuation,
198 ForEachDirection direction = ForEachDirection::kForward) {
198 Label non_array(this), slow(this, {&k_, &a_, &to_}), 199 Label non_array(this), slow(this, {&k_, &a_, &to_}),
199 array_changes(this, {&k_, &a_, &to_}); 200 array_changes(this, {&k_, &a_, &to_});
200 201
201 // TODO(danno): Seriously? Do we really need to throw the exact error 202 // TODO(danno): Seriously? Do we really need to throw the exact error
202 // message on null and undefined so that the webkit tests pass? 203 // message on null and undefined so that the webkit tests pass?
203 Label throw_null_undefined_exception(this, Label::kDeferred); 204 Label throw_null_undefined_exception(this, Label::kDeferred);
204 GotoIf(WordEqual(receiver(), NullConstant()), 205 GotoIf(WordEqual(receiver(), NullConstant()),
205 &throw_null_undefined_exception); 206 &throw_null_undefined_exception);
206 GotoIf(WordEqual(receiver(), UndefinedConstant()), 207 GotoIf(WordEqual(receiver(), UndefinedConstant()),
207 &throw_null_undefined_exception); 208 &throw_null_undefined_exception);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 SmiConstant(MessageTemplate::kCalledNonCallable), 250 SmiConstant(MessageTemplate::kCalledNonCallable),
250 callbackfn()); 251 callbackfn());
251 Unreachable(); 252 Unreachable();
252 } 253 }
253 254
254 Bind(&done); 255 Bind(&done);
255 256
256 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. 257 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
257 // [Already done by the arguments adapter] 258 // [Already done by the arguments adapter]
258 259
259 // 7. Let k be 0. 260 if (direction == ForEachDirection::kForward) {
260 // [Already done in code assembler initialization] 261 // 7. Let k be 0.
262 k_.Bind(SmiConstant(0));
263 } else {
264 k_.Bind(len());
265 k_.Bind(NumberDec(k_.value()));
266 }
261 267
262 a_.Bind(generator(this)); 268 a_.Bind(generator(this));
263 269
264 HandleFastElements(processor, action, &slow); 270 HandleFastElements(processor, action, &slow, direction);
265 271
266 Bind(&slow); 272 Bind(&slow);
267 273
268 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, 274 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
269 MachineType::TaggedPointer()); 275 MachineType::TaggedPointer());
270 TailCallStub( 276 TailCallStub(
271 slow_case_continuation, context(), target, new_target(), 277 slow_case_continuation, context(), target, new_target(),
272 Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity), 278 Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity),
273 receiver(), callbackfn(), this_arg(), a_.value(), o(), k_.value(), 279 receiver(), callbackfn(), this_arg(), a_.value(), o(), k_.value(),
274 len(), to_.value()); 280 len(), to_.value());
275 } 281 }
276 282
277 void InitIteratingArrayBuiltinLoopContinuation(Node* context, Node* receiver, 283 void InitIteratingArrayBuiltinLoopContinuation(Node* context, Node* receiver,
278 Node* callbackfn, 284 Node* callbackfn,
279 Node* this_arg, Node* a, 285 Node* this_arg, Node* a,
280 Node* o, Node* initial_k, 286 Node* o, Node* initial_k,
281 Node* len, Node* to) { 287 Node* len, Node* to) {
282 context_ = context; 288 context_ = context;
283 this_arg_ = this_arg; 289 this_arg_ = this_arg;
284 callbackfn_ = callbackfn; 290 callbackfn_ = callbackfn;
285 a_.Bind(a); 291 a_.Bind(a);
286 k_.Bind(initial_k); 292 k_.Bind(initial_k);
287 o_ = o; 293 o_ = o;
288 len_ = len; 294 len_ = len;
289 to_.Bind(to); 295 to_.Bind(to);
290 } 296 }
291 297
292 void GenerateIteratingArrayBuiltinLoopContinuation( 298 void GenerateIteratingArrayBuiltinLoopContinuation(
293 const CallResultProcessor& processor, const PostLoopAction& action) { 299 const CallResultProcessor& processor, const PostLoopAction& action,
294 // 8. Repeat, while k < len 300 ForEachDirection direction = ForEachDirection::kForward) {
295 Label loop(this, {&k_, &a_, &to_}); 301 Label loop(this, {&k_, &a_, &to_});
296 Label after_loop(this); 302 Label after_loop(this);
297 Goto(&loop); 303 Goto(&loop);
298 Bind(&loop); 304 Bind(&loop);
299 { 305 {
300 GotoUnlessNumberLessThan(k(), len_, &after_loop); 306 if (direction == ForEachDirection::kForward) {
307 // 8. Repeat, while k < len
308 GotoUnlessNumberLessThan(k(), len_, &after_loop);
309 } else {
310 // OR
311 // 10. Repeat, while k >= 0
312 GotoUnlessNumberLessThan(SmiConstant(-1), k(), &after_loop);
313 }
301 314
302 Label done_element(this, &to_); 315 Label done_element(this, &to_);
303 // a. Let Pk be ToString(k). 316 // a. Let Pk be ToString(k).
304 Node* p_k = ToString(context(), k()); 317 Node* p_k = ToString(context(), k());
305 318
306 // b. Let kPresent be HasProperty(O, Pk). 319 // b. Let kPresent be HasProperty(O, Pk).
307 // c. ReturnIfAbrupt(kPresent). 320 // c. ReturnIfAbrupt(kPresent).
308 Node* k_present = HasProperty(o(), p_k, context()); 321 Node* k_present = HasProperty(o(), p_k, context());
309 322
310 // d. If kPresent is true, then 323 // d. If kPresent is true, then
311 GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element); 324 GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element);
312 325
313 // i. Let kValue be Get(O, Pk). 326 // i. Let kValue be Get(O, Pk).
314 // ii. ReturnIfAbrupt(kValue). 327 // ii. ReturnIfAbrupt(kValue).
315 Node* k_value = GetProperty(context(), o(), k()); 328 Node* k_value = GetProperty(context(), o(), k());
316 329
317 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»). 330 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»).
318 // iv. ReturnIfAbrupt(funcResult). 331 // iv. ReturnIfAbrupt(funcResult).
319 a_.Bind(processor(this, k_value, k())); 332 a_.Bind(processor(this, k_value, k()));
320 Goto(&done_element); 333 Goto(&done_element);
321 334
322 Bind(&done_element); 335 Bind(&done_element);
323 336
324 // e. Increase k by 1. 337 if (direction == ForEachDirection::kForward) {
325 k_.Bind(NumberInc(k_.value())); 338 // e. Increase k by 1.
339 k_.Bind(NumberInc(k()));
340 } else {
341 // e. Decrease k by 1.
342 k_.Bind(NumberDec(k()));
343 }
326 Goto(&loop); 344 Goto(&loop);
327 } 345 }
328 Bind(&after_loop); 346 Bind(&after_loop);
329 347
330 action(this); 348 action(this);
331 Return(a_.value()); 349 Return(a_.value());
332 } 350 }
333 351
334 private: 352 private:
335 void VisitAllFastElementsOneKind(ElementsKind kind, 353 void VisitAllFastElementsOneKind(ElementsKind kind,
336 const CallResultProcessor& processor, 354 const CallResultProcessor& processor,
337 Label* array_changed, ParameterMode mode) { 355 Label* array_changed, ParameterMode mode,
356 ForEachDirection direction) {
338 Comment("begin VisitAllFastElementsOneKind"); 357 Comment("begin VisitAllFastElementsOneKind");
339 Variable original_map(this, MachineRepresentation::kTagged); 358 Variable original_map(this, MachineRepresentation::kTagged);
340 original_map.Bind(LoadMap(o())); 359 original_map.Bind(LoadMap(o()));
341 VariableList list({&original_map, &a_, &k_, &to_}, zone()); 360 VariableList list({&original_map, &a_, &k_, &to_}, zone());
361 Node* start = IntPtrOrSmiConstant(0, mode);
362 Node* end = TaggedToParameter(len(), mode);
363 IndexAdvanceMode advance_mode = direction == ForEachDirection::kReverse
364 ? IndexAdvanceMode::kPre
365 : IndexAdvanceMode::kPost;
366 if (direction == ForEachDirection::kReverse) std::swap(start, end);
342 BuildFastLoop( 367 BuildFastLoop(
343 list, IntPtrOrSmiConstant(0, mode), TaggedToParameter(len(), mode), 368 list, start, end,
344 [=, &original_map](Node* index) { 369 [=, &original_map](Node* index) {
345 k_.Bind(ParameterToTagged(index, mode)); 370 k_.Bind(ParameterToTagged(index, mode));
346 Label one_element_done(this), hole_element(this); 371 Label one_element_done(this), hole_element(this);
347 372
348 // Check if o's map has changed during the callback. If so, we have to 373 // Check if o's map has changed during the callback. If so, we have to
349 // fall back to the slower spec implementation for the rest of the 374 // fall back to the slower spec implementation for the rest of the
350 // iteration. 375 // iteration.
351 Node* o_map = LoadMap(o()); 376 Node* o_map = LoadMap(o());
352 GotoIf(WordNotEqual(o_map, original_map.value()), array_changed); 377 GotoIf(WordNotEqual(o_map, original_map.value()), array_changed);
353 378
(...skipping 25 matching lines...) Expand all
379 Goto(&one_element_done); 404 Goto(&one_element_done);
380 405
381 Bind(&hole_element); 406 Bind(&hole_element);
382 // Check if o's prototype change unexpectedly has elements after the 407 // Check if o's prototype change unexpectedly has elements after the
383 // callback in the case of a hole. 408 // callback in the case of a hole.
384 BranchIfPrototypesHaveNoElements(o_map, &one_element_done, 409 BranchIfPrototypesHaveNoElements(o_map, &one_element_done,
385 array_changed); 410 array_changed);
386 411
387 Bind(&one_element_done); 412 Bind(&one_element_done);
388 }, 413 },
389 1, mode, IndexAdvanceMode::kPost); 414 1, mode, advance_mode);
390 Comment("end VisitAllFastElementsOneKind"); 415 Comment("end VisitAllFastElementsOneKind");
391 } 416 }
392 417
393 void HandleFastElements(const CallResultProcessor& processor, 418 void HandleFastElements(const CallResultProcessor& processor,
394 const PostLoopAction& action, Label* slow) { 419 const PostLoopAction& action, Label* slow,
420 ForEachDirection direction) {
395 Label switch_on_elements_kind(this), fast_elements(this), 421 Label switch_on_elements_kind(this), fast_elements(this),
396 maybe_double_elements(this), fast_double_elements(this); 422 maybe_double_elements(this), fast_double_elements(this);
397 423
398 Comment("begin HandleFastElements"); 424 Comment("begin HandleFastElements");
399 // Non-smi lengths must use the slow path. 425 // Non-smi lengths must use the slow path.
400 GotoIf(TaggedIsNotSmi(len()), slow); 426 GotoIf(TaggedIsNotSmi(len()), slow);
401 427
402 BranchIfFastJSArray(o(), context(), 428 BranchIfFastJSArray(o(), context(),
403 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, 429 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ,
404 &switch_on_elements_kind, slow); 430 &switch_on_elements_kind, slow);
405 431
406 Bind(&switch_on_elements_kind); 432 Bind(&switch_on_elements_kind);
407 // Select by ElementsKind 433 // Select by ElementsKind
408 Node* o_map = LoadMap(o()); 434 Node* o_map = LoadMap(o());
409 Node* bit_field2 = LoadMapBitField2(o_map); 435 Node* bit_field2 = LoadMapBitField2(o_map);
410 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); 436 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
411 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), 437 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)),
412 &maybe_double_elements, &fast_elements); 438 &maybe_double_elements, &fast_elements);
413 439
414 ParameterMode mode = OptimalParameterMode(); 440 ParameterMode mode = OptimalParameterMode();
415 Bind(&fast_elements); 441 Bind(&fast_elements);
416 { 442 {
417 VisitAllFastElementsOneKind(FAST_ELEMENTS, processor, slow, mode); 443 VisitAllFastElementsOneKind(FAST_ELEMENTS, processor, slow, mode,
444 direction);
418 445
419 action(this); 446 action(this);
420 447
421 // No exception, return success 448 // No exception, return success
422 Return(a_.value()); 449 Return(a_.value());
423 } 450 }
424 451
425 Bind(&maybe_double_elements); 452 Bind(&maybe_double_elements);
426 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_DOUBLE_ELEMENTS)), 453 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_DOUBLE_ELEMENTS)),
427 slow, &fast_double_elements); 454 slow, &fast_double_elements);
428 455
429 Bind(&fast_double_elements); 456 Bind(&fast_double_elements);
430 { 457 {
431 VisitAllFastElementsOneKind(FAST_DOUBLE_ELEMENTS, processor, slow, mode); 458 VisitAllFastElementsOneKind(FAST_DOUBLE_ELEMENTS, processor, slow, mode,
459 direction);
432 460
433 action(this); 461 action(this);
434 462
435 // No exception, return success 463 // No exception, return success
436 Return(a_.value()); 464 Return(a_.value());
437 } 465 }
438 } 466 }
439 467
440 Node* callbackfn_ = nullptr; 468 Node* callbackfn_ = nullptr;
441 Node* o_ = nullptr; 469 Node* o_ = nullptr;
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 new_target); 778 new_target);
751 779
752 GenerateIteratingArrayBuiltinBody( 780 GenerateIteratingArrayBuiltinBody(
753 "Array.prototype.reduce", 781 "Array.prototype.reduce",
754 &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator, 782 &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
755 &ArrayBuiltinCodeStubAssembler::ReduceProcessor, 783 &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
756 &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction, 784 &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
757 CodeFactory::ArrayReduceLoopContinuation(isolate())); 785 CodeFactory::ArrayReduceLoopContinuation(isolate()));
758 } 786 }
759 787
788 TF_BUILTIN(ArrayReduceRightLoopContinuation, ArrayBuiltinCodeStubAssembler) {
789 Node* context = Parameter(Descriptor::kContext);
790 Node* receiver = Parameter(Descriptor::kReceiver);
791 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
792 Node* this_arg = Parameter(Descriptor::kThisArg);
793 Node* accumulator = Parameter(Descriptor::kAccumulator);
794 Node* object = Parameter(Descriptor::kObject);
795 Node* initial_k = Parameter(Descriptor::kInitialK);
796 Node* len = Parameter(Descriptor::kLength);
797 Node* to = Parameter(Descriptor::kTo);
798
799 InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
800 this_arg, accumulator, object,
801 initial_k, len, to);
802
803 GenerateIteratingArrayBuiltinLoopContinuation(
804 &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
805 &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
806 ForEachDirection::kReverse);
807 }
808
809 TF_BUILTIN(ArrayReduceRight, ArrayBuiltinCodeStubAssembler) {
810 Node* context = Parameter(Descriptor::kContext);
811 Node* receiver = Parameter(Descriptor::kReceiver);
812 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
813 Node* initial_value = Parameter(Descriptor::kInitialValue);
814 Node* new_target = Parameter(Descriptor::kNewTarget);
815
816 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
817 new_target);
818
819 GenerateIteratingArrayBuiltinBody(
820 "Array.prototype.reduceRight",
821 &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
822 &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
823 &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
824 CodeFactory::ArrayReduceRightLoopContinuation(isolate()),
825 ForEachDirection::kReverse);
826 }
827
760 TF_BUILTIN(ArrayFilterLoopContinuation, ArrayBuiltinCodeStubAssembler) { 828 TF_BUILTIN(ArrayFilterLoopContinuation, ArrayBuiltinCodeStubAssembler) {
761 Node* context = Parameter(Descriptor::kContext); 829 Node* context = Parameter(Descriptor::kContext);
762 Node* receiver = Parameter(Descriptor::kReceiver); 830 Node* receiver = Parameter(Descriptor::kReceiver);
763 Node* callbackfn = Parameter(Descriptor::kCallbackFn); 831 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
764 Node* this_arg = Parameter(Descriptor::kThisArg); 832 Node* this_arg = Parameter(Descriptor::kThisArg);
765 Node* array = Parameter(Descriptor::kArray); 833 Node* array = Parameter(Descriptor::kArray);
766 Node* object = Parameter(Descriptor::kObject); 834 Node* object = Parameter(Descriptor::kObject);
767 Node* initial_k = Parameter(Descriptor::kInitialK); 835 Node* initial_k = Parameter(Descriptor::kInitialK);
768 Node* len = Parameter(Descriptor::kLength); 836 Node* len = Parameter(Descriptor::kLength);
769 Node* to = Parameter(Descriptor::kTo); 837 Node* to = Parameter(Descriptor::kTo);
(...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1886 { 1954 {
1887 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); 1955 Node* message = SmiConstant(MessageTemplate::kDetachedOperation);
1888 CallRuntime(Runtime::kThrowTypeError, context, message, 1956 CallRuntime(Runtime::kThrowTypeError, context, message,
1889 HeapConstant(operation)); 1957 HeapConstant(operation));
1890 Unreachable(); 1958 Unreachable();
1891 } 1959 }
1892 } 1960 }
1893 1961
1894 } // namespace internal 1962 } // namespace internal
1895 } // namespace v8 1963 } // 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