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

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

Issue 2372113004: [turbofan] JSGenericLowering mostly uses builtins instead of code stubs now (Closed)
Patch Set: removed TFSC macro Created 4 years, 2 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 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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.h"
5 #include "src/builtins/builtins.h" 6 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h" 7 #include "src/code-factory.h"
7 8
8 namespace v8 { 9 namespace v8 {
9 namespace internal { 10 namespace internal {
10 11
11 // ----------------------------------------------------------------------------- 12 // -----------------------------------------------------------------------------
12 // ES6 section 20.1 Number Objects 13 // ES6 section 20.1 Number Objects
13 14
14 // ES6 section 20.1.2.2 Number.isFinite ( number ) 15 // ES6 section 20.1.2.2 Number.isFinite ( number )
15 void Builtins::Generate_NumberIsFinite(CodeStubAssembler* assembler) { 16 void Builtins::Generate_NumberIsFinite(CodeStubAssembler* assembler) {
16 typedef CodeStubAssembler::Label Label; 17 typedef CodeStubAssembler::Label Label;
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 typedef compiler::Node Node; 363 typedef compiler::Node Node;
363 364
364 Node* receiver = assembler->Parameter(0); 365 Node* receiver = assembler->Parameter(0);
365 Node* context = assembler->Parameter(3); 366 Node* context = assembler->Parameter(3);
366 367
367 Node* result = assembler->ToThisValue( 368 Node* result = assembler->ToThisValue(
368 context, receiver, PrimitiveType::kNumber, "Number.prototype.valueOf"); 369 context, receiver, PrimitiveType::kNumber, "Number.prototype.valueOf");
369 assembler->Return(result); 370 assembler->Return(result);
370 } 371 }
371 372
373 // static
374 void Builtins::Generate_Add(CodeStubAssembler* assembler) {
375 typedef CodeStubAssembler::Label Label;
376 typedef compiler::Node Node;
377 typedef CodeStubAssembler::Variable Variable;
378
379 Node* left = assembler->Parameter(0);
380 Node* right = assembler->Parameter(1);
381 Node* context = assembler->Parameter(2);
382
383 // Shared entry for floating point addition.
384 Label do_fadd(assembler);
385 Variable var_fadd_lhs(assembler, MachineRepresentation::kFloat64),
386 var_fadd_rhs(assembler, MachineRepresentation::kFloat64);
387
388 // We might need to loop several times due to ToPrimitive, ToString and/or
389 // ToNumber conversions.
390 Variable var_lhs(assembler, MachineRepresentation::kTagged),
391 var_rhs(assembler, MachineRepresentation::kTagged),
392 var_result(assembler, MachineRepresentation::kTagged);
393 Variable* loop_vars[2] = {&var_lhs, &var_rhs};
394 Label loop(assembler, 2, loop_vars), end(assembler),
395 string_add_convert_left(assembler, Label::kDeferred),
396 string_add_convert_right(assembler, Label::kDeferred);
397 var_lhs.Bind(left);
398 var_rhs.Bind(right);
399 assembler->Goto(&loop);
400 assembler->Bind(&loop);
401 {
402 // Load the current {lhs} and {rhs} values.
403 Node* lhs = var_lhs.value();
404 Node* rhs = var_rhs.value();
405
406 // Check if the {lhs} is a Smi or a HeapObject.
407 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler);
408 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
409
410 assembler->Bind(&if_lhsissmi);
411 {
412 // Check if the {rhs} is also a Smi.
413 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
414 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
415 &if_rhsisnotsmi);
416
417 assembler->Bind(&if_rhsissmi);
418 {
419 // Try fast Smi addition first.
420 Node* pair = assembler->SmiAddWithOverflow(lhs, rhs);
421 Node* overflow = assembler->Projection(1, pair);
422
423 // Check if the Smi additon overflowed.
424 Label if_overflow(assembler), if_notoverflow(assembler);
425 assembler->Branch(overflow, &if_overflow, &if_notoverflow);
426
427 assembler->Bind(&if_overflow);
428 {
429 var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs));
430 var_fadd_rhs.Bind(assembler->SmiToFloat64(rhs));
431 assembler->Goto(&do_fadd);
432 }
433
434 assembler->Bind(&if_notoverflow);
435 var_result.Bind(assembler->Projection(0, pair));
436 assembler->Goto(&end);
437 }
438
439 assembler->Bind(&if_rhsisnotsmi);
440 {
441 // Load the map of {rhs}.
442 Node* rhs_map = assembler->LoadMap(rhs);
443
444 // Check if the {rhs} is a HeapNumber.
445 Label if_rhsisnumber(assembler),
446 if_rhsisnotnumber(assembler, Label::kDeferred);
447 Node* number_map = assembler->HeapNumberMapConstant();
448 assembler->Branch(assembler->WordEqual(rhs_map, number_map),
449 &if_rhsisnumber, &if_rhsisnotnumber);
450
451 assembler->Bind(&if_rhsisnumber);
452 {
453 var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs));
454 var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
455 assembler->Goto(&do_fadd);
456 }
457
458 assembler->Bind(&if_rhsisnotnumber);
459 {
460 // Load the instance type of {rhs}.
461 Node* rhs_instance_type = assembler->LoadMapInstanceType(rhs_map);
462
463 // Check if the {rhs} is a String.
464 Label if_rhsisstring(assembler, Label::kDeferred),
465 if_rhsisnotstring(assembler, Label::kDeferred);
466 assembler->Branch(assembler->Int32LessThan(
467 rhs_instance_type,
468 assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
469 &if_rhsisstring, &if_rhsisnotstring);
470
471 assembler->Bind(&if_rhsisstring);
472 {
473 var_lhs.Bind(lhs);
474 var_rhs.Bind(rhs);
475 assembler->Goto(&string_add_convert_left);
476 }
477
478 assembler->Bind(&if_rhsisnotstring);
479 {
480 // Check if {rhs} is a JSReceiver.
481 Label if_rhsisreceiver(assembler, Label::kDeferred),
482 if_rhsisnotreceiver(assembler, Label::kDeferred);
483 assembler->Branch(
484 assembler->Int32LessThanOrEqual(
485 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE),
486 rhs_instance_type),
487 &if_rhsisreceiver, &if_rhsisnotreceiver);
488
489 assembler->Bind(&if_rhsisreceiver);
490 {
491 // Convert {rhs} to a primitive first passing no hint.
492 Callable callable =
493 CodeFactory::NonPrimitiveToPrimitive(assembler->isolate());
494 var_rhs.Bind(assembler->CallStub(callable, context, rhs));
495 assembler->Goto(&loop);
496 }
497
498 assembler->Bind(&if_rhsisnotreceiver);
499 {
500 // Convert {rhs} to a Number first.
501 Callable callable =
502 CodeFactory::NonNumberToNumber(assembler->isolate());
503 var_rhs.Bind(assembler->CallStub(callable, context, rhs));
504 assembler->Goto(&loop);
505 }
506 }
507 }
508 }
509 }
510
511 assembler->Bind(&if_lhsisnotsmi);
512 {
513 // Load the map and instance type of {lhs}.
514 Node* lhs_instance_type = assembler->LoadInstanceType(lhs);
515
516 // Check if {lhs} is a String.
517 Label if_lhsisstring(assembler), if_lhsisnotstring(assembler);
518 assembler->Branch(assembler->Int32LessThan(
519 lhs_instance_type,
520 assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
521 &if_lhsisstring, &if_lhsisnotstring);
522
523 assembler->Bind(&if_lhsisstring);
524 {
525 var_lhs.Bind(lhs);
526 var_rhs.Bind(rhs);
527 assembler->Goto(&string_add_convert_right);
528 }
529
530 assembler->Bind(&if_lhsisnotstring);
531 {
532 // Check if {rhs} is a Smi.
533 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
534 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
535 &if_rhsisnotsmi);
536
537 assembler->Bind(&if_rhsissmi);
538 {
539 // Check if {lhs} is a Number.
540 Label if_lhsisnumber(assembler),
541 if_lhsisnotnumber(assembler, Label::kDeferred);
542 assembler->Branch(assembler->Word32Equal(
543 lhs_instance_type,
544 assembler->Int32Constant(HEAP_NUMBER_TYPE)),
545 &if_lhsisnumber, &if_lhsisnotnumber);
546
547 assembler->Bind(&if_lhsisnumber);
548 {
549 // The {lhs} is a HeapNumber, the {rhs} is a Smi, just add them.
550 var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
551 var_fadd_rhs.Bind(assembler->SmiToFloat64(rhs));
552 assembler->Goto(&do_fadd);
553 }
554
555 assembler->Bind(&if_lhsisnotnumber);
556 {
557 // The {lhs} is neither a Number nor a String, and the {rhs} is a
558 // Smi.
559 Label if_lhsisreceiver(assembler, Label::kDeferred),
560 if_lhsisnotreceiver(assembler, Label::kDeferred);
561 assembler->Branch(
562 assembler->Int32LessThanOrEqual(
563 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE),
564 lhs_instance_type),
565 &if_lhsisreceiver, &if_lhsisnotreceiver);
566
567 assembler->Bind(&if_lhsisreceiver);
568 {
569 // Convert {lhs} to a primitive first passing no hint.
570 Callable callable =
571 CodeFactory::NonPrimitiveToPrimitive(assembler->isolate());
572 var_lhs.Bind(assembler->CallStub(callable, context, lhs));
573 assembler->Goto(&loop);
574 }
575
576 assembler->Bind(&if_lhsisnotreceiver);
577 {
578 // Convert {lhs} to a Number first.
579 Callable callable =
580 CodeFactory::NonNumberToNumber(assembler->isolate());
581 var_lhs.Bind(assembler->CallStub(callable, context, lhs));
582 assembler->Goto(&loop);
583 }
584 }
585 }
586
587 assembler->Bind(&if_rhsisnotsmi);
588 {
589 // Load the instance type of {rhs}.
590 Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
591
592 // Check if {rhs} is a String.
593 Label if_rhsisstring(assembler), if_rhsisnotstring(assembler);
594 assembler->Branch(assembler->Int32LessThan(
595 rhs_instance_type,
596 assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
597 &if_rhsisstring, &if_rhsisnotstring);
598
599 assembler->Bind(&if_rhsisstring);
600 {
601 var_lhs.Bind(lhs);
602 var_rhs.Bind(rhs);
603 assembler->Goto(&string_add_convert_left);
604 }
605
606 assembler->Bind(&if_rhsisnotstring);
607 {
608 // Check if {lhs} is a HeapNumber.
609 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler);
610 assembler->Branch(assembler->Word32Equal(
611 lhs_instance_type,
612 assembler->Int32Constant(HEAP_NUMBER_TYPE)),
613 &if_lhsisnumber, &if_lhsisnotnumber);
614
615 assembler->Bind(&if_lhsisnumber);
616 {
617 // Check if {rhs} is also a HeapNumber.
618 Label if_rhsisnumber(assembler),
619 if_rhsisnotnumber(assembler, Label::kDeferred);
620 assembler->Branch(assembler->Word32Equal(
621 rhs_instance_type,
622 assembler->Int32Constant(HEAP_NUMBER_TYPE)),
623 &if_rhsisnumber, &if_rhsisnotnumber);
624
625 assembler->Bind(&if_rhsisnumber);
626 {
627 // Perform a floating point addition.
628 var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
629 var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
630 assembler->Goto(&do_fadd);
631 }
632
633 assembler->Bind(&if_rhsisnotnumber);
634 {
635 // Check if {rhs} is a JSReceiver.
636 Label if_rhsisreceiver(assembler, Label::kDeferred),
637 if_rhsisnotreceiver(assembler, Label::kDeferred);
638 assembler->Branch(
639 assembler->Int32LessThanOrEqual(
640 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE),
641 rhs_instance_type),
642 &if_rhsisreceiver, &if_rhsisnotreceiver);
643
644 assembler->Bind(&if_rhsisreceiver);
645 {
646 // Convert {rhs} to a primitive first passing no hint.
647 Callable callable = CodeFactory::NonPrimitiveToPrimitive(
648 assembler->isolate());
649 var_rhs.Bind(assembler->CallStub(callable, context, rhs));
650 assembler->Goto(&loop);
651 }
652
653 assembler->Bind(&if_rhsisnotreceiver);
654 {
655 // Convert {rhs} to a Number first.
656 Callable callable =
657 CodeFactory::NonNumberToNumber(assembler->isolate());
658 var_rhs.Bind(assembler->CallStub(callable, context, rhs));
659 assembler->Goto(&loop);
660 }
661 }
662 }
663
664 assembler->Bind(&if_lhsisnotnumber);
665 {
666 // Check if {lhs} is a JSReceiver.
667 Label if_lhsisreceiver(assembler, Label::kDeferred),
668 if_lhsisnotreceiver(assembler);
669 assembler->Branch(
670 assembler->Int32LessThanOrEqual(
671 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE),
672 lhs_instance_type),
673 &if_lhsisreceiver, &if_lhsisnotreceiver);
674
675 assembler->Bind(&if_lhsisreceiver);
676 {
677 // Convert {lhs} to a primitive first passing no hint.
678 Callable callable =
679 CodeFactory::NonPrimitiveToPrimitive(assembler->isolate());
680 var_lhs.Bind(assembler->CallStub(callable, context, lhs));
681 assembler->Goto(&loop);
682 }
683
684 assembler->Bind(&if_lhsisnotreceiver);
685 {
686 // Check if {rhs} is a JSReceiver.
687 Label if_rhsisreceiver(assembler, Label::kDeferred),
688 if_rhsisnotreceiver(assembler, Label::kDeferred);
689 assembler->Branch(
690 assembler->Int32LessThanOrEqual(
691 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE),
692 rhs_instance_type),
693 &if_rhsisreceiver, &if_rhsisnotreceiver);
694
695 assembler->Bind(&if_rhsisreceiver);
696 {
697 // Convert {rhs} to a primitive first passing no hint.
698 Callable callable = CodeFactory::NonPrimitiveToPrimitive(
699 assembler->isolate());
700 var_rhs.Bind(assembler->CallStub(callable, context, rhs));
701 assembler->Goto(&loop);
702 }
703
704 assembler->Bind(&if_rhsisnotreceiver);
705 {
706 // Convert {lhs} to a Number first.
707 Callable callable =
708 CodeFactory::NonNumberToNumber(assembler->isolate());
709 var_lhs.Bind(assembler->CallStub(callable, context, lhs));
710 assembler->Goto(&loop);
711 }
712 }
713 }
714 }
715 }
716 }
717 }
718 }
719 assembler->Bind(&string_add_convert_left);
720 {
721 // Convert {lhs}, which is a Smi, to a String and concatenate the
722 // resulting string with the String {rhs}.
723 Callable callable = CodeFactory::StringAdd(
724 assembler->isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED);
725 var_result.Bind(assembler->CallStub(callable, context, var_lhs.value(),
726 var_rhs.value()));
727 assembler->Goto(&end);
728 }
729
730 assembler->Bind(&string_add_convert_right);
731 {
732 // Convert {lhs}, which is a Smi, to a String and concatenate the
733 // resulting string with the String {rhs}.
734 Callable callable = CodeFactory::StringAdd(
735 assembler->isolate(), STRING_ADD_CONVERT_RIGHT, NOT_TENURED);
736 var_result.Bind(assembler->CallStub(callable, context, var_lhs.value(),
737 var_rhs.value()));
738 assembler->Goto(&end);
739 }
740
741 assembler->Bind(&do_fadd);
742 {
743 Node* lhs_value = var_fadd_lhs.value();
744 Node* rhs_value = var_fadd_rhs.value();
745 Node* value = assembler->Float64Add(lhs_value, rhs_value);
746 Node* result = assembler->ChangeFloat64ToTagged(value);
747 var_result.Bind(result);
748 assembler->Goto(&end);
749 }
750 assembler->Bind(&end);
751 assembler->Return(var_result.value());
752 }
753
754 void Builtins::Generate_Subtract(CodeStubAssembler* assembler) {
755 typedef CodeStubAssembler::Label Label;
756 typedef compiler::Node Node;
757 typedef CodeStubAssembler::Variable Variable;
758
759 Node* left = assembler->Parameter(0);
760 Node* right = assembler->Parameter(1);
761 Node* context = assembler->Parameter(2);
762
763 // Shared entry for floating point subtraction.
764 Label do_fsub(assembler), end(assembler);
765 Variable var_fsub_lhs(assembler, MachineRepresentation::kFloat64),
766 var_fsub_rhs(assembler, MachineRepresentation::kFloat64);
767
768 // We might need to loop several times due to ToPrimitive and/or ToNumber
769 // conversions.
770 Variable var_lhs(assembler, MachineRepresentation::kTagged),
771 var_rhs(assembler, MachineRepresentation::kTagged),
772 var_result(assembler, MachineRepresentation::kTagged);
773 Variable* loop_vars[2] = {&var_lhs, &var_rhs};
774 Label loop(assembler, 2, loop_vars);
775 var_lhs.Bind(left);
776 var_rhs.Bind(right);
777 assembler->Goto(&loop);
778 assembler->Bind(&loop);
779 {
780 // Load the current {lhs} and {rhs} values.
781 Node* lhs = var_lhs.value();
782 Node* rhs = var_rhs.value();
783
784 // Check if the {lhs} is a Smi or a HeapObject.
785 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler);
786 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
787
788 assembler->Bind(&if_lhsissmi);
789 {
790 // Check if the {rhs} is also a Smi.
791 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
792 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
793 &if_rhsisnotsmi);
794
795 assembler->Bind(&if_rhsissmi);
796 {
797 // Try a fast Smi subtraction first.
798 Node* pair = assembler->SmiSubWithOverflow(lhs, rhs);
799 Node* overflow = assembler->Projection(1, pair);
800
801 // Check if the Smi subtraction overflowed.
802 Label if_overflow(assembler), if_notoverflow(assembler);
803 assembler->Branch(overflow, &if_overflow, &if_notoverflow);
804
805 assembler->Bind(&if_overflow);
806 {
807 // The result doesn't fit into Smi range.
808 var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs));
809 var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs));
810 assembler->Goto(&do_fsub);
811 }
812
813 assembler->Bind(&if_notoverflow);
814 var_result.Bind(assembler->Projection(0, pair));
815 assembler->Goto(&end);
816 }
817
818 assembler->Bind(&if_rhsisnotsmi);
819 {
820 // Load the map of the {rhs}.
821 Node* rhs_map = assembler->LoadMap(rhs);
822
823 // Check if {rhs} is a HeapNumber.
824 Label if_rhsisnumber(assembler),
825 if_rhsisnotnumber(assembler, Label::kDeferred);
826 Node* number_map = assembler->HeapNumberMapConstant();
827 assembler->Branch(assembler->WordEqual(rhs_map, number_map),
828 &if_rhsisnumber, &if_rhsisnotnumber);
829
830 assembler->Bind(&if_rhsisnumber);
831 {
832 // Perform a floating point subtraction.
833 var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs));
834 var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
835 assembler->Goto(&do_fsub);
836 }
837
838 assembler->Bind(&if_rhsisnotnumber);
839 {
840 // Convert the {rhs} to a Number first.
841 Callable callable =
842 CodeFactory::NonNumberToNumber(assembler->isolate());
843 var_rhs.Bind(assembler->CallStub(callable, context, rhs));
844 assembler->Goto(&loop);
845 }
846 }
847 }
848
849 assembler->Bind(&if_lhsisnotsmi);
850 {
851 // Load the map of the {lhs}.
852 Node* lhs_map = assembler->LoadMap(lhs);
853
854 // Check if the {lhs} is a HeapNumber.
855 Label if_lhsisnumber(assembler),
856 if_lhsisnotnumber(assembler, Label::kDeferred);
857 Node* number_map = assembler->HeapNumberMapConstant();
858 assembler->Branch(assembler->WordEqual(lhs_map, number_map),
859 &if_lhsisnumber, &if_lhsisnotnumber);
860
861 assembler->Bind(&if_lhsisnumber);
862 {
863 // Check if the {rhs} is a Smi.
864 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
865 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
866 &if_rhsisnotsmi);
867
868 assembler->Bind(&if_rhsissmi);
869 {
870 // Perform a floating point subtraction.
871 var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
872 var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs));
873 assembler->Goto(&do_fsub);
874 }
875
876 assembler->Bind(&if_rhsisnotsmi);
877 {
878 // Load the map of the {rhs}.
879 Node* rhs_map = assembler->LoadMap(rhs);
880
881 // Check if the {rhs} is a HeapNumber.
882 Label if_rhsisnumber(assembler),
883 if_rhsisnotnumber(assembler, Label::kDeferred);
884 assembler->Branch(assembler->WordEqual(rhs_map, number_map),
885 &if_rhsisnumber, &if_rhsisnotnumber);
886
887 assembler->Bind(&if_rhsisnumber);
888 {
889 // Perform a floating point subtraction.
890 var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
891 var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
892 assembler->Goto(&do_fsub);
893 }
894
895 assembler->Bind(&if_rhsisnotnumber);
896 {
897 // Convert the {rhs} to a Number first.
898 Callable callable =
899 CodeFactory::NonNumberToNumber(assembler->isolate());
900 var_rhs.Bind(assembler->CallStub(callable, context, rhs));
901 assembler->Goto(&loop);
902 }
903 }
904 }
905
906 assembler->Bind(&if_lhsisnotnumber);
907 {
908 // Convert the {lhs} to a Number first.
909 Callable callable =
910 CodeFactory::NonNumberToNumber(assembler->isolate());
911 var_lhs.Bind(assembler->CallStub(callable, context, lhs));
912 assembler->Goto(&loop);
913 }
914 }
915 }
916
917 assembler->Bind(&do_fsub);
918 {
919 Node* lhs_value = var_fsub_lhs.value();
920 Node* rhs_value = var_fsub_rhs.value();
921 Node* value = assembler->Float64Sub(lhs_value, rhs_value);
922 var_result.Bind(assembler->ChangeFloat64ToTagged(value));
923 assembler->Goto(&end);
924 }
925 assembler->Bind(&end);
926 assembler->Return(var_result.value());
927 }
928
929 void Builtins::Generate_Multiply(CodeStubAssembler* assembler) {
930 typedef CodeStubAssembler::Label Label;
931 typedef compiler::Node Node;
932 typedef CodeStubAssembler::Variable Variable;
933
934 Node* left = assembler->Parameter(0);
935 Node* right = assembler->Parameter(1);
936 Node* context = assembler->Parameter(2);
937
938 // Shared entry point for floating point multiplication.
939 Label do_fmul(assembler), return_result(assembler);
940 Variable var_lhs_float64(assembler, MachineRepresentation::kFloat64),
941 var_rhs_float64(assembler, MachineRepresentation::kFloat64);
942
943 Node* number_map = assembler->HeapNumberMapConstant();
944
945 // We might need to loop one or two times due to ToNumber conversions.
946 Variable var_lhs(assembler, MachineRepresentation::kTagged),
947 var_rhs(assembler, MachineRepresentation::kTagged),
948 var_result(assembler, MachineRepresentation::kTagged);
949 Variable* loop_variables[] = {&var_lhs, &var_rhs};
950 Label loop(assembler, 2, loop_variables);
951 var_lhs.Bind(left);
952 var_rhs.Bind(right);
953 assembler->Goto(&loop);
954 assembler->Bind(&loop);
955 {
956 Node* lhs = var_lhs.value();
957 Node* rhs = var_rhs.value();
958
959 Label lhs_is_smi(assembler), lhs_is_not_smi(assembler);
960 assembler->Branch(assembler->WordIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi);
961
962 assembler->Bind(&lhs_is_smi);
963 {
964 Label rhs_is_smi(assembler), rhs_is_not_smi(assembler);
965 assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi,
966 &rhs_is_not_smi);
967
968 assembler->Bind(&rhs_is_smi);
969 {
970 // Both {lhs} and {rhs} are Smis. The result is not necessarily a smi,
971 // in case of overflow.
972 var_result.Bind(assembler->SmiMul(lhs, rhs));
973 assembler->Goto(&return_result);
974 }
975
976 assembler->Bind(&rhs_is_not_smi);
977 {
978 Node* rhs_map = assembler->LoadMap(rhs);
979
980 // Check if {rhs} is a HeapNumber.
981 Label rhs_is_number(assembler),
982 rhs_is_not_number(assembler, Label::kDeferred);
983 assembler->Branch(assembler->WordEqual(rhs_map, number_map),
984 &rhs_is_number, &rhs_is_not_number);
985
986 assembler->Bind(&rhs_is_number);
987 {
988 // Convert {lhs} to a double and multiply it with the value of {rhs}.
989 var_lhs_float64.Bind(assembler->SmiToFloat64(lhs));
990 var_rhs_float64.Bind(assembler->LoadHeapNumberValue(rhs));
991 assembler->Goto(&do_fmul);
992 }
993
994 assembler->Bind(&rhs_is_not_number);
995 {
996 // Multiplication is commutative, swap {lhs} with {rhs} and loop.
997 var_lhs.Bind(rhs);
998 var_rhs.Bind(lhs);
999 assembler->Goto(&loop);
1000 }
1001 }
1002 }
1003
1004 assembler->Bind(&lhs_is_not_smi);
1005 {
1006 Node* lhs_map = assembler->LoadMap(lhs);
1007
1008 // Check if {lhs} is a HeapNumber.
1009 Label lhs_is_number(assembler),
1010 lhs_is_not_number(assembler, Label::kDeferred);
1011 assembler->Branch(assembler->WordEqual(lhs_map, number_map),
1012 &lhs_is_number, &lhs_is_not_number);
1013
1014 assembler->Bind(&lhs_is_number);
1015 {
1016 // Check if {rhs} is a Smi.
1017 Label rhs_is_smi(assembler), rhs_is_not_smi(assembler);
1018 assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi,
1019 &rhs_is_not_smi);
1020
1021 assembler->Bind(&rhs_is_smi);
1022 {
1023 // Convert {rhs} to a double and multiply it with the value of {lhs}.
1024 var_lhs_float64.Bind(assembler->LoadHeapNumberValue(lhs));
1025 var_rhs_float64.Bind(assembler->SmiToFloat64(rhs));
1026 assembler->Goto(&do_fmul);
1027 }
1028
1029 assembler->Bind(&rhs_is_not_smi);
1030 {
1031 Node* rhs_map = assembler->LoadMap(rhs);
1032
1033 // Check if {rhs} is a HeapNumber.
1034 Label rhs_is_number(assembler),
1035 rhs_is_not_number(assembler, Label::kDeferred);
1036 assembler->Branch(assembler->WordEqual(rhs_map, number_map),
1037 &rhs_is_number, &rhs_is_not_number);
1038
1039 assembler->Bind(&rhs_is_number);
1040 {
1041 // Both {lhs} and {rhs} are HeapNumbers. Load their values and
1042 // multiply them.
1043 var_lhs_float64.Bind(assembler->LoadHeapNumberValue(lhs));
1044 var_rhs_float64.Bind(assembler->LoadHeapNumberValue(rhs));
1045 assembler->Goto(&do_fmul);
1046 }
1047
1048 assembler->Bind(&rhs_is_not_number);
1049 {
1050 // Multiplication is commutative, swap {lhs} with {rhs} and loop.
1051 var_lhs.Bind(rhs);
1052 var_rhs.Bind(lhs);
1053 assembler->Goto(&loop);
1054 }
1055 }
1056 }
1057
1058 assembler->Bind(&lhs_is_not_number);
1059 {
1060 // Convert {lhs} to a Number and loop.
1061 Callable callable =
1062 CodeFactory::NonNumberToNumber(assembler->isolate());
1063 var_lhs.Bind(assembler->CallStub(callable, context, lhs));
1064 assembler->Goto(&loop);
1065 }
1066 }
1067 }
1068
1069 assembler->Bind(&do_fmul);
1070 {
1071 Node* value =
1072 assembler->Float64Mul(var_lhs_float64.value(), var_rhs_float64.value());
1073 Node* result = assembler->ChangeFloat64ToTagged(value);
1074 var_result.Bind(result);
1075 assembler->Goto(&return_result);
1076 }
1077
1078 assembler->Bind(&return_result);
1079 assembler->Return(var_result.value());
1080 }
1081
1082 void Builtins::Generate_Divide(CodeStubAssembler* assembler) {
1083 typedef CodeStubAssembler::Label Label;
1084 typedef compiler::Node Node;
1085 typedef CodeStubAssembler::Variable Variable;
1086
1087 Node* left = assembler->Parameter(0);
1088 Node* right = assembler->Parameter(1);
1089 Node* context = assembler->Parameter(2);
1090
1091 // Shared entry point for floating point division.
1092 Label do_fdiv(assembler), end(assembler);
1093 Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
1094 var_divisor_float64(assembler, MachineRepresentation::kFloat64);
1095
1096 Node* number_map = assembler->HeapNumberMapConstant();
1097
1098 // We might need to loop one or two times due to ToNumber conversions.
1099 Variable var_dividend(assembler, MachineRepresentation::kTagged),
1100 var_divisor(assembler, MachineRepresentation::kTagged),
1101 var_result(assembler, MachineRepresentation::kTagged);
1102 Variable* loop_variables[] = {&var_dividend, &var_divisor};
1103 Label loop(assembler, 2, loop_variables);
1104 var_dividend.Bind(left);
1105 var_divisor.Bind(right);
1106 assembler->Goto(&loop);
1107 assembler->Bind(&loop);
1108 {
1109 Node* dividend = var_dividend.value();
1110 Node* divisor = var_divisor.value();
1111
1112 Label dividend_is_smi(assembler), dividend_is_not_smi(assembler);
1113 assembler->Branch(assembler->WordIsSmi(dividend), &dividend_is_smi,
1114 &dividend_is_not_smi);
1115
1116 assembler->Bind(&dividend_is_smi);
1117 {
1118 Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
1119 assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
1120 &divisor_is_not_smi);
1121
1122 assembler->Bind(&divisor_is_smi);
1123 {
1124 Label bailout(assembler);
1125
1126 // Do floating point division if {divisor} is zero.
1127 assembler->GotoIf(
1128 assembler->WordEqual(divisor, assembler->IntPtrConstant(0)),
1129 &bailout);
1130
1131 // Do floating point division {dividend} is zero and {divisor} is
1132 // negative.
1133 Label dividend_is_zero(assembler), dividend_is_not_zero(assembler);
1134 assembler->Branch(
1135 assembler->WordEqual(dividend, assembler->IntPtrConstant(0)),
1136 &dividend_is_zero, &dividend_is_not_zero);
1137
1138 assembler->Bind(&dividend_is_zero);
1139 {
1140 assembler->GotoIf(
1141 assembler->IntPtrLessThan(divisor, assembler->IntPtrConstant(0)),
1142 &bailout);
1143 assembler->Goto(&dividend_is_not_zero);
1144 }
1145 assembler->Bind(&dividend_is_not_zero);
1146
1147 Node* untagged_divisor = assembler->SmiUntag(divisor);
1148 Node* untagged_dividend = assembler->SmiUntag(dividend);
1149
1150 // Do floating point division if {dividend} is kMinInt (or kMinInt - 1
1151 // if the Smi size is 31) and {divisor} is -1.
1152 Label divisor_is_minus_one(assembler),
1153 divisor_is_not_minus_one(assembler);
1154 assembler->Branch(assembler->Word32Equal(untagged_divisor,
1155 assembler->Int32Constant(-1)),
1156 &divisor_is_minus_one, &divisor_is_not_minus_one);
1157
1158 assembler->Bind(&divisor_is_minus_one);
1159 {
1160 assembler->GotoIf(
1161 assembler->Word32Equal(
1162 untagged_dividend,
1163 assembler->Int32Constant(
1164 kSmiValueSize == 32 ? kMinInt : (kMinInt >> 1))),
1165 &bailout);
1166 assembler->Goto(&divisor_is_not_minus_one);
1167 }
1168 assembler->Bind(&divisor_is_not_minus_one);
1169
1170 // TODO(epertoso): consider adding a machine instruction that returns
1171 // both the result and the remainder.
1172 Node* untagged_result =
1173 assembler->Int32Div(untagged_dividend, untagged_divisor);
1174 Node* truncated =
1175 assembler->Int32Mul(untagged_result, untagged_divisor);
1176 // Do floating point division if the remainder is not 0.
1177 assembler->GotoIf(
1178 assembler->Word32NotEqual(untagged_dividend, truncated), &bailout);
1179 var_result.Bind(assembler->SmiTag(untagged_result));
1180 assembler->Goto(&end);
1181
1182 // Bailout: convert {dividend} and {divisor} to double and do double
1183 // division.
1184 assembler->Bind(&bailout);
1185 {
1186 var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
1187 var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
1188 assembler->Goto(&do_fdiv);
1189 }
1190 }
1191
1192 assembler->Bind(&divisor_is_not_smi);
1193 {
1194 Node* divisor_map = assembler->LoadMap(divisor);
1195
1196 // Check if {divisor} is a HeapNumber.
1197 Label divisor_is_number(assembler),
1198 divisor_is_not_number(assembler, Label::kDeferred);
1199 assembler->Branch(assembler->WordEqual(divisor_map, number_map),
1200 &divisor_is_number, &divisor_is_not_number);
1201
1202 assembler->Bind(&divisor_is_number);
1203 {
1204 // Convert {dividend} to a double and divide it with the value of
1205 // {divisor}.
1206 var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
1207 var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
1208 assembler->Goto(&do_fdiv);
1209 }
1210
1211 assembler->Bind(&divisor_is_not_number);
1212 {
1213 // Convert {divisor} to a number and loop.
1214 Callable callable =
1215 CodeFactory::NonNumberToNumber(assembler->isolate());
1216 var_divisor.Bind(assembler->CallStub(callable, context, divisor));
1217 assembler->Goto(&loop);
1218 }
1219 }
1220 }
1221
1222 assembler->Bind(&dividend_is_not_smi);
1223 {
1224 Node* dividend_map = assembler->LoadMap(dividend);
1225
1226 // Check if {dividend} is a HeapNumber.
1227 Label dividend_is_number(assembler),
1228 dividend_is_not_number(assembler, Label::kDeferred);
1229 assembler->Branch(assembler->WordEqual(dividend_map, number_map),
1230 &dividend_is_number, &dividend_is_not_number);
1231
1232 assembler->Bind(&dividend_is_number);
1233 {
1234 // Check if {divisor} is a Smi.
1235 Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
1236 assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
1237 &divisor_is_not_smi);
1238
1239 assembler->Bind(&divisor_is_smi);
1240 {
1241 // Convert {divisor} to a double and use it for a floating point
1242 // division.
1243 var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
1244 var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
1245 assembler->Goto(&do_fdiv);
1246 }
1247
1248 assembler->Bind(&divisor_is_not_smi);
1249 {
1250 Node* divisor_map = assembler->LoadMap(divisor);
1251
1252 // Check if {divisor} is a HeapNumber.
1253 Label divisor_is_number(assembler),
1254 divisor_is_not_number(assembler, Label::kDeferred);
1255 assembler->Branch(assembler->WordEqual(divisor_map, number_map),
1256 &divisor_is_number, &divisor_is_not_number);
1257
1258 assembler->Bind(&divisor_is_number);
1259 {
1260 // Both {dividend} and {divisor} are HeapNumbers. Load their values
1261 // and divide them.
1262 var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
1263 var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
1264 assembler->Goto(&do_fdiv);
1265 }
1266
1267 assembler->Bind(&divisor_is_not_number);
1268 {
1269 // Convert {divisor} to a number and loop.
1270 Callable callable =
1271 CodeFactory::NonNumberToNumber(assembler->isolate());
1272 var_divisor.Bind(assembler->CallStub(callable, context, divisor));
1273 assembler->Goto(&loop);
1274 }
1275 }
1276 }
1277
1278 assembler->Bind(&dividend_is_not_number);
1279 {
1280 // Convert {dividend} to a Number and loop.
1281 Callable callable =
1282 CodeFactory::NonNumberToNumber(assembler->isolate());
1283 var_dividend.Bind(assembler->CallStub(callable, context, dividend));
1284 assembler->Goto(&loop);
1285 }
1286 }
1287 }
1288
1289 assembler->Bind(&do_fdiv);
1290 {
1291 Node* value = assembler->Float64Div(var_dividend_float64.value(),
1292 var_divisor_float64.value());
1293 var_result.Bind(assembler->ChangeFloat64ToTagged(value));
1294 assembler->Goto(&end);
1295 }
1296 assembler->Bind(&end);
1297 assembler->Return(var_result.value());
1298 }
1299
1300 void Builtins::Generate_Modulus(CodeStubAssembler* assembler) {
1301 typedef CodeStubAssembler::Label Label;
1302 typedef compiler::Node Node;
1303 typedef CodeStubAssembler::Variable Variable;
1304
1305 Node* left = assembler->Parameter(0);
1306 Node* right = assembler->Parameter(1);
1307 Node* context = assembler->Parameter(2);
1308
1309 Variable var_result(assembler, MachineRepresentation::kTagged);
1310 Label return_result(assembler, &var_result);
1311
1312 // Shared entry point for floating point modulus.
1313 Label do_fmod(assembler);
1314 Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
1315 var_divisor_float64(assembler, MachineRepresentation::kFloat64);
1316
1317 Node* number_map = assembler->HeapNumberMapConstant();
1318
1319 // We might need to loop one or two times due to ToNumber conversions.
1320 Variable var_dividend(assembler, MachineRepresentation::kTagged),
1321 var_divisor(assembler, MachineRepresentation::kTagged);
1322 Variable* loop_variables[] = {&var_dividend, &var_divisor};
1323 Label loop(assembler, 2, loop_variables);
1324 var_dividend.Bind(left);
1325 var_divisor.Bind(right);
1326 assembler->Goto(&loop);
1327 assembler->Bind(&loop);
1328 {
1329 Node* dividend = var_dividend.value();
1330 Node* divisor = var_divisor.value();
1331
1332 Label dividend_is_smi(assembler), dividend_is_not_smi(assembler);
1333 assembler->Branch(assembler->WordIsSmi(dividend), &dividend_is_smi,
1334 &dividend_is_not_smi);
1335
1336 assembler->Bind(&dividend_is_smi);
1337 {
1338 Label dividend_is_not_zero(assembler);
1339 Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
1340 assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
1341 &divisor_is_not_smi);
1342
1343 assembler->Bind(&divisor_is_smi);
1344 {
1345 // Compute the modulus of two Smis.
1346 var_result.Bind(assembler->SmiMod(dividend, divisor));
1347 assembler->Goto(&return_result);
1348 }
1349
1350 assembler->Bind(&divisor_is_not_smi);
1351 {
1352 Node* divisor_map = assembler->LoadMap(divisor);
1353
1354 // Check if {divisor} is a HeapNumber.
1355 Label divisor_is_number(assembler),
1356 divisor_is_not_number(assembler, Label::kDeferred);
1357 assembler->Branch(assembler->WordEqual(divisor_map, number_map),
1358 &divisor_is_number, &divisor_is_not_number);
1359
1360 assembler->Bind(&divisor_is_number);
1361 {
1362 // Convert {dividend} to a double and compute its modulus with the
1363 // value of {dividend}.
1364 var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
1365 var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
1366 assembler->Goto(&do_fmod);
1367 }
1368
1369 assembler->Bind(&divisor_is_not_number);
1370 {
1371 // Convert {divisor} to a number and loop.
1372 Callable callable =
1373 CodeFactory::NonNumberToNumber(assembler->isolate());
1374 var_divisor.Bind(assembler->CallStub(callable, context, divisor));
1375 assembler->Goto(&loop);
1376 }
1377 }
1378 }
1379
1380 assembler->Bind(&dividend_is_not_smi);
1381 {
1382 Node* dividend_map = assembler->LoadMap(dividend);
1383
1384 // Check if {dividend} is a HeapNumber.
1385 Label dividend_is_number(assembler),
1386 dividend_is_not_number(assembler, Label::kDeferred);
1387 assembler->Branch(assembler->WordEqual(dividend_map, number_map),
1388 &dividend_is_number, &dividend_is_not_number);
1389
1390 assembler->Bind(&dividend_is_number);
1391 {
1392 // Check if {divisor} is a Smi.
1393 Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
1394 assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
1395 &divisor_is_not_smi);
1396
1397 assembler->Bind(&divisor_is_smi);
1398 {
1399 // Convert {divisor} to a double and compute {dividend}'s modulus with
1400 // it.
1401 var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
1402 var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
1403 assembler->Goto(&do_fmod);
1404 }
1405
1406 assembler->Bind(&divisor_is_not_smi);
1407 {
1408 Node* divisor_map = assembler->LoadMap(divisor);
1409
1410 // Check if {divisor} is a HeapNumber.
1411 Label divisor_is_number(assembler),
1412 divisor_is_not_number(assembler, Label::kDeferred);
1413 assembler->Branch(assembler->WordEqual(divisor_map, number_map),
1414 &divisor_is_number, &divisor_is_not_number);
1415
1416 assembler->Bind(&divisor_is_number);
1417 {
1418 // Both {dividend} and {divisor} are HeapNumbers. Load their values
1419 // and compute their modulus.
1420 var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
1421 var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
1422 assembler->Goto(&do_fmod);
1423 }
1424
1425 assembler->Bind(&divisor_is_not_number);
1426 {
1427 // Convert {divisor} to a number and loop.
1428 Callable callable =
1429 CodeFactory::NonNumberToNumber(assembler->isolate());
1430 var_divisor.Bind(assembler->CallStub(callable, context, divisor));
1431 assembler->Goto(&loop);
1432 }
1433 }
1434 }
1435
1436 assembler->Bind(&dividend_is_not_number);
1437 {
1438 // Convert {dividend} to a Number and loop.
1439 Callable callable =
1440 CodeFactory::NonNumberToNumber(assembler->isolate());
1441 var_dividend.Bind(assembler->CallStub(callable, context, dividend));
1442 assembler->Goto(&loop);
1443 }
1444 }
1445 }
1446
1447 assembler->Bind(&do_fmod);
1448 {
1449 Node* value = assembler->Float64Mod(var_dividend_float64.value(),
1450 var_divisor_float64.value());
1451 var_result.Bind(assembler->ChangeFloat64ToTagged(value));
1452 assembler->Goto(&return_result);
1453 }
1454
1455 assembler->Bind(&return_result);
1456 assembler->Return(var_result.value());
1457 }
1458
1459 void Builtins::Generate_ShiftLeft(CodeStubAssembler* assembler) {
1460 compiler::Node* left = assembler->Parameter(0);
1461 compiler::Node* right = assembler->Parameter(1);
1462 compiler::Node* context = assembler->Parameter(2);
1463
1464 using compiler::Node;
1465
1466 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
1467 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
1468 Node* shift_count =
1469 assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f));
1470 Node* value = assembler->Word32Shl(lhs_value, shift_count);
1471 Node* result = assembler->ChangeInt32ToTagged(value);
1472 assembler->Return(result);
1473 }
1474
1475 void Builtins::Generate_ShiftRight(CodeStubAssembler* assembler) {
1476 compiler::Node* left = assembler->Parameter(0);
1477 compiler::Node* right = assembler->Parameter(1);
1478 compiler::Node* context = assembler->Parameter(2);
1479
1480 using compiler::Node;
1481
1482 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
1483 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
1484 Node* shift_count =
1485 assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f));
1486 Node* value = assembler->Word32Sar(lhs_value, shift_count);
1487 Node* result = assembler->ChangeInt32ToTagged(value);
1488 assembler->Return(result);
1489 }
1490
1491 void Builtins::Generate_ShiftRightLogical(CodeStubAssembler* assembler) {
1492 compiler::Node* left = assembler->Parameter(0);
1493 compiler::Node* right = assembler->Parameter(1);
1494 compiler::Node* context = assembler->Parameter(2);
1495
1496 using compiler::Node;
1497
1498 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
1499 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
1500 Node* shift_count =
1501 assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f));
1502 Node* value = assembler->Word32Shr(lhs_value, shift_count);
1503 Node* result = assembler->ChangeUint32ToTagged(value);
1504 assembler->Return(result);
1505 }
1506
1507 void Builtins::Generate_BitwiseAnd(CodeStubAssembler* assembler) {
1508 compiler::Node* left = assembler->Parameter(0);
1509 compiler::Node* right = assembler->Parameter(1);
1510 compiler::Node* context = assembler->Parameter(2);
1511
1512 using compiler::Node;
1513
1514 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
1515 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
1516 Node* value = assembler->Word32And(lhs_value, rhs_value);
1517 Node* result = assembler->ChangeInt32ToTagged(value);
1518 assembler->Return(result);
1519 }
1520
1521 void Builtins::Generate_BitwiseOr(CodeStubAssembler* assembler) {
1522 compiler::Node* left = assembler->Parameter(0);
1523 compiler::Node* right = assembler->Parameter(1);
1524 compiler::Node* context = assembler->Parameter(2);
1525
1526 using compiler::Node;
1527
1528 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
1529 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
1530 Node* value = assembler->Word32Or(lhs_value, rhs_value);
1531 Node* result = assembler->ChangeInt32ToTagged(value);
1532 assembler->Return(result);
1533 }
1534
1535 void Builtins::Generate_BitwiseXor(CodeStubAssembler* assembler) {
1536 compiler::Node* left = assembler->Parameter(0);
1537 compiler::Node* right = assembler->Parameter(1);
1538 compiler::Node* context = assembler->Parameter(2);
1539
1540 using compiler::Node;
1541
1542 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
1543 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
1544 Node* value = assembler->Word32Xor(lhs_value, rhs_value);
1545 Node* result = assembler->ChangeInt32ToTagged(value);
1546 assembler->Return(result);
1547 }
1548
1549 void Builtins::Generate_LessThan(CodeStubAssembler* assembler) {
1550 compiler::Node* lhs = assembler->Parameter(0);
1551 compiler::Node* rhs = assembler->Parameter(1);
1552 compiler::Node* context = assembler->Parameter(2);
1553
1554 assembler->Return(assembler->RelationalComparison(
1555 CodeStubAssembler::kLessThan, lhs, rhs, context));
1556 }
1557
1558 void Builtins::Generate_LessThanOrEqual(CodeStubAssembler* assembler) {
1559 compiler::Node* lhs = assembler->Parameter(0);
1560 compiler::Node* rhs = assembler->Parameter(1);
1561 compiler::Node* context = assembler->Parameter(2);
1562
1563 assembler->Return(assembler->RelationalComparison(
1564 CodeStubAssembler::kLessThanOrEqual, lhs, rhs, context));
1565 }
1566
1567 void Builtins::Generate_GreaterThan(CodeStubAssembler* assembler) {
1568 compiler::Node* lhs = assembler->Parameter(0);
1569 compiler::Node* rhs = assembler->Parameter(1);
1570 compiler::Node* context = assembler->Parameter(2);
1571
1572 assembler->Return(assembler->RelationalComparison(
1573 CodeStubAssembler::kGreaterThan, lhs, rhs, context));
1574 }
1575
1576 void Builtins::Generate_GreaterThanOrEqual(CodeStubAssembler* assembler) {
1577 compiler::Node* lhs = assembler->Parameter(0);
1578 compiler::Node* rhs = assembler->Parameter(1);
1579 compiler::Node* context = assembler->Parameter(2);
1580
1581 assembler->Return(assembler->RelationalComparison(
1582 CodeStubAssembler::kGreaterThanOrEqual, lhs, rhs, context));
1583 }
1584
1585 void Builtins::Generate_Equal(CodeStubAssembler* assembler) {
1586 compiler::Node* lhs = assembler->Parameter(0);
1587 compiler::Node* rhs = assembler->Parameter(1);
1588 compiler::Node* context = assembler->Parameter(2);
1589
1590 assembler->Return(assembler->Equal(CodeStubAssembler::kDontNegateResult, lhs,
1591 rhs, context));
1592 }
1593
1594 void Builtins::Generate_NotEqual(CodeStubAssembler* assembler) {
1595 compiler::Node* lhs = assembler->Parameter(0);
1596 compiler::Node* rhs = assembler->Parameter(1);
1597 compiler::Node* context = assembler->Parameter(2);
1598
1599 assembler->Return(
1600 assembler->Equal(CodeStubAssembler::kNegateResult, lhs, rhs, context));
1601 }
1602
1603 void Builtins::Generate_StrictEqual(CodeStubAssembler* assembler) {
1604 compiler::Node* lhs = assembler->Parameter(0);
1605 compiler::Node* rhs = assembler->Parameter(1);
1606 compiler::Node* context = assembler->Parameter(2);
1607
1608 assembler->Return(assembler->StrictEqual(CodeStubAssembler::kDontNegateResult,
1609 lhs, rhs, context));
1610 }
1611
1612 void Builtins::Generate_StrictNotEqual(CodeStubAssembler* assembler) {
1613 compiler::Node* lhs = assembler->Parameter(0);
1614 compiler::Node* rhs = assembler->Parameter(1);
1615 compiler::Node* context = assembler->Parameter(2);
1616
1617 assembler->Return(assembler->StrictEqual(CodeStubAssembler::kNegateResult,
1618 lhs, rhs, context));
1619 }
1620
372 } // namespace internal 1621 } // namespace internal
373 } // namespace v8 1622 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698