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

Side by Side Diff: src/builtins/builtins.cc

Issue 2146293003: [builtins] implement Array.prototype.includes in TurboFan (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: try lots of tight loops Created 4 years, 5 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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.h" 5 #include "src/builtins/builtins.h"
6 6
7 #include "src/api-arguments.h" 7 #include "src/api-arguments.h"
8 #include "src/api-natives.h" 8 #include "src/api-natives.h"
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/base/ieee754.h" 10 #include "src/base/ieee754.h"
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 assembler->Return(assembler->BooleanConstant(true)); 336 assembler->Return(assembler->BooleanConstant(true));
337 337
338 assembler->Bind(&return_false); 338 assembler->Bind(&return_false);
339 assembler->Return(assembler->BooleanConstant(false)); 339 assembler->Return(assembler->BooleanConstant(false));
340 340
341 assembler->Bind(&call_runtime); 341 assembler->Bind(&call_runtime);
342 assembler->Return( 342 assembler->Return(
343 assembler->CallRuntime(Runtime::kArrayIsArray, context, object)); 343 assembler->CallRuntime(Runtime::kArrayIsArray, context, object));
344 } 344 }
345 345
346 void Builtins::Generate_ArrayIncludes(CodeStubAssembler* assembler) {
347 typedef compiler::Node Node;
348 typedef CodeStubAssembler::Label Label;
349 typedef CodeStubAssembler::Variable Variable;
350
351 Node* array = assembler->Parameter(0);
352 Node* search_element = assembler->Parameter(1);
353 Node* start_from = assembler->Parameter(2);
354 Node* context = assembler->Parameter(3 + 2);
355
356 Node* int32_zero = assembler->Int32Constant(0);
357 Node* int32_one = assembler->Int32Constant(1);
358
359 Node* the_hole = assembler->TheHoleConstant();
360 Node* undefined = assembler->UndefinedConstant();
361 Node* heap_number_map = assembler->HeapNumberMapConstant();
362
363 Variable len(assembler, MachineRepresentation::kWord32),
364 k(assembler, MachineRepresentation::kWord32),
365 n(assembler, MachineRepresentation::kWord32);
366
367 Label init_k(assembler), return_true(assembler), return_false(assembler),
368 call_runtime(assembler);
369
370 {
371 // Take slow path if not a JSArray, if retrieving elements requires
372 // traversing prototype, or if access checks are required.
373 Label init_len(assembler);
374 assembler->BranchIfFastJSArray(array, context, &init_len, &call_runtime);
375
376 assembler->Bind(&init_len);
377 len.Bind(assembler->SmiToWord(
378 assembler->LoadObjectField(array, JSArray::kLengthOffset)));
379
380 assembler->GotoUnless(assembler->Word32Equal(len.value(), int32_zero),
381 &init_k);
382 assembler->Return(assembler->BooleanConstant(false));
383 }
384
385 assembler->Bind(&init_k);
386 {
387 Label done(assembler), init_k_smi(assembler), init_k_heap_num(assembler),
388 init_k_zero(assembler), init_k_n(assembler);
389 Callable call_to_integer = CodeFactory::ToInteger(assembler->isolate());
390 Node* tagged_n = assembler->CallStub(call_to_integer, context, start_from);
391
392 assembler->Branch(assembler->WordIsSmi(tagged_n), &init_k_smi,
393 &init_k_heap_num);
394
395 assembler->Bind(&init_k_smi);
396 {
397 n.Bind(assembler->SmiToWord32(tagged_n));
398 assembler->Goto(&init_k_n);
399 }
400
401 assembler->Bind(&init_k_heap_num);
402 {
403 Label abort(assembler);
404 Node* fp_len = assembler->ChangeInt32ToFloat64(len.value());
405 Node* fp_n = assembler->LoadHeapNumberValue(tagged_n);
406 assembler->GotoIf(assembler->Float64GreaterThanOrEqual(fp_n, fp_len),
407 &abort);
408 n.Bind(assembler->TruncateFloat64ToWord32(fp_n));
409 assembler->Goto(&init_k_n);
410
411 assembler->Bind(&abort);
412 assembler->Return(assembler->BooleanConstant(false));
413 }
414
415 assembler->Bind(&init_k_n);
416 {
417 Label if_positive(assembler), if_negative(assembler), done(assembler);
418 assembler->Branch(assembler->Int32LessThan(n.value(), int32_zero),
419 &if_negative, &if_positive);
420
421 assembler->Bind(&if_positive);
422 {
423 k.Bind(n.value());
424 assembler->Goto(&done);
425 }
426
427 assembler->Bind(&if_negative);
428 {
429 k.Bind(assembler->Int32Add(len.value(), n.value()));
430 assembler->Branch(assembler->Int32LessThan(k.value(), int32_zero),
431 &init_k_zero, &done);
432 }
433
434 assembler->Bind(&init_k_zero);
435 {
436 k.Bind(int32_zero);
437 assembler->Goto(&done);
438 }
439
440 assembler->Bind(&done);
441 }
442 }
443
444 int32_t element_kinds[] = {
445 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS,
446 FAST_HOLEY_ELEMENTS, FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS,
447 };
448
449 Label if_smiorobjects(assembler), if_packed_doubles(assembler),
450 if_holey_doubles(assembler);
451 Label* element_kind_handlers[] = {&if_smiorobjects, &if_smiorobjects,
452 &if_smiorobjects, &if_smiorobjects,
453 &if_packed_doubles, &if_holey_doubles};
454
455 Node* map = assembler->LoadMap(array);
456 Node* bit_field2 = assembler->LoadMapBitField2(map);
457 Node* elements_kind =
458 assembler->BitFieldDecode<Map::ElementsKindBits>(bit_field2);
459 Node* elements = assembler->LoadElements(array);
460 assembler->Switch(elements_kind, &return_false, element_kinds,
461 element_kind_handlers, arraysize(element_kinds));
462
463 assembler->Bind(&if_smiorobjects);
caitp 2016/07/17 03:26:47 There are lots of different tight loops here, to b
Benedikt Meurer 2016/07/17 06:03:18 Awesome, I think this is the maximum you can get o
caitp 2016/07/18 22:10:23 I had looked at adding a JSBuiltinReducer for Arra
464 {
465 Label ident_loop(assembler, &k), heap_num_loop(assembler),
466 string_loop(assembler, &k), simd_loop(assembler),
467 undef_loop(assembler, &k);
468
469 assembler->GotoIf(assembler->WordIsSmi(search_element), &ident_loop);
470 assembler->GotoIf(assembler->WordEqual(search_element, undefined),
471 &undef_loop);
472 Node* map = assembler->LoadMap(search_element);
473 assembler->GotoIf(assembler->WordEqual(map, heap_number_map),
474 &heap_num_loop);
475 Node* search_type = assembler->LoadMapInstanceType(map);
476 assembler->GotoIf(
477 assembler->Int32LessThan(
478 search_type, assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
479 &string_loop);
480 assembler->GotoIf(
481 assembler->WordEqual(search_type,
482 assembler->Int32Constant(SIMD128_VALUE_TYPE)),
483 &simd_loop);
484 assembler->Goto(&ident_loop);
485
486 assembler->Bind(&ident_loop);
487 {
488 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
489 &return_false);
490 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
491 assembler->GotoIf(assembler->WordEqual(element_k, search_element),
492 &return_true);
493
494 k.Bind(assembler->Int32Add(k.value(), int32_one));
495 assembler->Goto(&ident_loop);
496 }
497
498 assembler->Bind(&undef_loop);
499 {
500 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
501 &return_false);
502 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
503 assembler->GotoIf(assembler->WordEqual(element_k, undefined),
504 &return_true);
505 assembler->GotoIf(assembler->WordEqual(element_k, the_hole),
506 &return_true);
507
508 k.Bind(assembler->Int32Add(k.value(), int32_one));
509 assembler->Goto(&undef_loop);
510 }
511
512 assembler->Bind(&heap_num_loop);
513 {
514 Label nan_loop(assembler, &k), not_nan_loop(assembler, &k);
515 Node* search_num = assembler->LoadHeapNumberValue(search_element);
516 assembler->BranchIfFloat64IsNaN(search_num, &nan_loop, &not_nan_loop);
517
518 assembler->Bind(&not_nan_loop);
519 {
520 Label continue_loop(assembler);
521 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
522 &return_false);
523 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
524 assembler->GotoIf(assembler->WordIsSmi(element_k), &continue_loop);
525 assembler->GotoIf(assembler->WordNotEqual(assembler->LoadMap(element_k),
526 heap_number_map),
527 &continue_loop);
528 assembler->BranchIfFloat64Equal(
529 search_num, assembler->LoadHeapNumberValue(element_k), &return_true,
530 &continue_loop);
531
532 assembler->Bind(&continue_loop);
533 k.Bind(assembler->Int32Add(k.value(), int32_one));
534 assembler->Goto(&not_nan_loop);
535 }
536
537 assembler->Bind(&nan_loop);
538 {
539 Label continue_loop(assembler);
540 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
541 &return_false);
542 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
543 assembler->GotoIf(assembler->WordIsSmi(element_k), &continue_loop);
544 assembler->GotoIf(assembler->WordNotEqual(assembler->LoadMap(element_k),
545 heap_number_map),
546 &continue_loop);
547 assembler->BranchIfFloat64IsNaN(
548 assembler->LoadHeapNumberValue(element_k), &return_true,
549 &continue_loop);
550
551 assembler->Bind(&continue_loop);
552 k.Bind(assembler->Int32Add(k.value(), int32_one));
553 assembler->Goto(&nan_loop);
554 }
555 }
556
557 assembler->Bind(&string_loop);
558 {
559 Label continue_loop(assembler);
560 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
561 &return_false);
562 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
563 assembler->GotoIf(assembler->WordIsSmi(element_k), &continue_loop);
564 assembler->GotoUnless(assembler->Int32LessThan(
565 assembler->LoadMapInstanceType(element_k),
566 assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
567 &continue_loop);
568
569 Callable callable = CodeFactory::StringEqual(assembler->isolate());
570 Node* result =
571 assembler->CallStub(callable, context, search_element, element_k);
572 assembler->Branch(
573 assembler->WordEqual(assembler->BooleanConstant(true), result),
574 &return_true, &continue_loop);
575
576 assembler->Bind(&continue_loop);
577 k.Bind(assembler->Int32Add(k.value(), int32_one));
578 assembler->Goto(&string_loop);
579 }
580
581 assembler->Bind(&simd_loop);
582 {
583 Label continue_loop(assembler, &k), loop_body(assembler, &k);
584 Node* map = assembler->LoadMap(search_element);
585
586 assembler->Goto(&loop_body);
587 assembler->Bind(&loop_body);
588 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
589 &return_false);
590
591 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
592 assembler->GotoIf(assembler->WordIsSmi(element_k), &continue_loop);
593
594 Node* map_k = assembler->LoadMap(element_k);
595 assembler->BranchIfSimd128Equal(search_element, map, element_k, map_k,
596 &return_true, &continue_loop);
597
598 assembler->Bind(&continue_loop);
599 k.Bind(assembler->Int32Add(k.value(), int32_one));
600 assembler->Goto(&loop_body);
601 }
602 }
603
604 assembler->Bind(&if_packed_doubles);
605 {
606 Label nan_loop(assembler, &k), not_nan_loop(assembler, &k),
607 hole_loop(assembler, &k);
608 assembler->GotoIf(assembler->WordIsSmi(search_element), &return_false);
609 assembler->GotoIf(assembler->WordNotEqual(
610 assembler->LoadMap(search_element), heap_number_map),
611 &return_false);
612
613 Node* search_num = assembler->LoadHeapNumberValue(search_element);
614
615 assembler->BranchIfFloat64IsNaN(search_num, &nan_loop, &not_nan_loop);
616
617 // Search for HeapNumber
618 assembler->Bind(&not_nan_loop);
619 {
620 Label continue_loop(assembler);
621 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
622 &return_false);
623 Node* element_k = assembler->LoadFixedDoubleArrayElement(
624 elements, k.value(), MachineType::Float64());
625 assembler->BranchIfFloat64Equal(element_k, search_num, &return_true,
626 &continue_loop);
627 assembler->Bind(&continue_loop);
628 k.Bind(assembler->Int32Add(k.value(), int32_one));
629 assembler->Goto(&not_nan_loop);
630 }
631
632 // Search for NaN
633 assembler->Bind(&nan_loop);
634 {
635 Label continue_loop(assembler);
636 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
637 &return_false);
638 Node* element_k = assembler->LoadFixedDoubleArrayElement(
639 elements, k.value(), MachineType::Float64());
640 assembler->BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop);
641 assembler->Bind(&continue_loop);
642 k.Bind(assembler->Int32Add(k.value(), int32_one));
643 assembler->Goto(&nan_loop);
644 }
645 }
646
647 assembler->Bind(&if_holey_doubles);
648 {
649 Label nan_loop(assembler, &k), not_nan_loop(assembler, &k),
650 hole_loop(assembler, &k);
651 assembler->GotoIf(assembler->WordIsSmi(search_element), &return_false);
652 assembler->GotoIf(assembler->WordEqual(search_element, undefined),
653 &hole_loop);
654 assembler->GotoIf(assembler->WordNotEqual(
655 assembler->LoadMap(search_element), heap_number_map),
656 &return_false);
657
658 Node* search_num = assembler->LoadHeapNumberValue(search_element);
659
660 assembler->BranchIfFloat64IsNaN(search_num, &nan_loop, &not_nan_loop);
661
662 // Search for HeapNumber
663 assembler->Bind(&not_nan_loop);
664 {
665 Label continue_loop(assembler);
666 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
667 &return_false);
668
669 if (kPointerSize == kDoubleSize) {
670 Node* element = assembler->LoadFixedDoubleArrayElement(
671 elements, k.value(), MachineType::Uint64());
672 Node* the_hole = assembler->Int64Constant(kHoleNanInt64);
673 assembler->GotoIf(assembler->Word64Equal(element, the_hole),
674 &continue_loop);
675 } else {
676 Node* element_upper = assembler->LoadFixedDoubleArrayElement(
677 elements, k.value(), MachineType::Uint32(),
678 kIeeeDoubleExponentWordOffset);
679 assembler->GotoIf(
680 assembler->Word32Equal(element_upper,
681 assembler->Int32Constant(kHoleNanUpper32)),
682 &continue_loop);
683 }
684
685 Node* element_k = assembler->LoadFixedDoubleArrayElement(
686 elements, k.value(), MachineType::Float64());
687 assembler->BranchIfFloat64Equal(element_k, search_num, &return_true,
688 &continue_loop);
689 assembler->Bind(&continue_loop);
690 k.Bind(assembler->Int32Add(k.value(), int32_one));
691 assembler->Goto(&not_nan_loop);
692 }
693
694 // Search for NaN
695 assembler->Bind(&nan_loop);
696 {
697 Label continue_loop(assembler);
698 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
699 &return_false);
700
701 if (kPointerSize == kDoubleSize) {
702 Node* element = assembler->LoadFixedDoubleArrayElement(
703 elements, k.value(), MachineType::Uint64());
704 Node* the_hole = assembler->Int64Constant(kHoleNanInt64);
705 assembler->GotoIf(assembler->Word64Equal(element, the_hole),
706 &continue_loop);
707 } else {
708 Node* element_upper = assembler->LoadFixedDoubleArrayElement(
709 elements, k.value(), MachineType::Uint32(),
710 kIeeeDoubleExponentWordOffset);
711 assembler->GotoIf(
712 assembler->Word32Equal(element_upper,
713 assembler->Int32Constant(kHoleNanUpper32)),
714 &continue_loop);
715 }
716
717 Node* element_k = assembler->LoadFixedDoubleArrayElement(
718 elements, k.value(), MachineType::Float64());
719 assembler->BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop);
720 assembler->Bind(&continue_loop);
721 k.Bind(assembler->Int32Add(k.value(), int32_one));
722 assembler->Goto(&nan_loop);
723 }
724
725 // Search for the Hole
726 assembler->Bind(&hole_loop);
727 {
728 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
729 &return_false);
730
731 if (kPointerSize == kDoubleSize) {
732 Node* element = assembler->LoadFixedDoubleArrayElement(
733 elements, k.value(), MachineType::Uint64());
734 Node* the_hole = assembler->Int64Constant(kHoleNanInt64);
735 assembler->GotoIf(assembler->Word64Equal(element, the_hole),
736 &return_true);
737 } else {
738 Node* element_upper = assembler->LoadFixedDoubleArrayElement(
739 elements, k.value(), MachineType::Uint32(),
740 kIeeeDoubleExponentWordOffset);
741 assembler->GotoIf(
742 assembler->Word32Equal(element_upper,
743 assembler->Int32Constant(kHoleNanUpper32)),
744 &return_true);
745 }
746
747 k.Bind(assembler->Int32Add(k.value(), int32_one));
748 assembler->Goto(&hole_loop);
749 }
750 }
751
752 assembler->Bind(&return_true);
753 assembler->Return(assembler->BooleanConstant(true));
754
755 assembler->Bind(&return_false);
756 assembler->Return(assembler->BooleanConstant(false));
757
758 assembler->Bind(&call_runtime);
759 assembler->Return(assembler->CallRuntime(Runtime::kArrayIncludes_Slow,
760 context, array, search_element,
761 start_from));
762 }
763
346 void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) { 764 void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
347 typedef compiler::Node Node; 765 typedef compiler::Node Node;
348 typedef CodeStubAssembler::Label Label; 766 typedef CodeStubAssembler::Label Label;
349 typedef CodeStubAssembler::Variable Variable; 767 typedef CodeStubAssembler::Variable Variable;
350 768
351 Node* object = assembler->Parameter(0); 769 Node* object = assembler->Parameter(0);
352 Node* key = assembler->Parameter(1); 770 Node* key = assembler->Parameter(1);
353 Node* context = assembler->Parameter(4); 771 Node* context = assembler->Parameter(4);
354 772
355 Label call_runtime(assembler), return_true(assembler), 773 Label call_runtime(assembler), return_true(assembler),
(...skipping 6567 matching lines...) Expand 10 before | Expand all | Expand 10 after
6923 #define DEFINE_BUILTIN_ACCESSOR(Name, ...) \ 7341 #define DEFINE_BUILTIN_ACCESSOR(Name, ...) \
6924 Handle<Code> Builtins::Name() { \ 7342 Handle<Code> Builtins::Name() { \
6925 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##Name)); \ 7343 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##Name)); \
6926 return Handle<Code>(code_address); \ 7344 return Handle<Code>(code_address); \
6927 } 7345 }
6928 BUILTIN_LIST_ALL(DEFINE_BUILTIN_ACCESSOR) 7346 BUILTIN_LIST_ALL(DEFINE_BUILTIN_ACCESSOR)
6929 #undef DEFINE_BUILTIN_ACCESSOR 7347 #undef DEFINE_BUILTIN_ACCESSOR
6930 7348
6931 } // namespace internal 7349 } // namespace internal
6932 } // namespace v8 7350 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | src/code-stub-assembler.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698