OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
510 __ j(greater, &negative, Label::kNear); | 510 __ j(greater, &negative, Label::kNear); |
511 __ mov(ecx, scratch2); | 511 __ mov(ecx, scratch2); |
512 __ jmp(&done, Label::kNear); | 512 __ jmp(&done, Label::kNear); |
513 __ bind(&negative); | 513 __ bind(&negative); |
514 __ sub(ecx, Operand(scratch2)); | 514 __ sub(ecx, Operand(scratch2)); |
515 __ bind(&done); | 515 __ bind(&done); |
516 } | 516 } |
517 } | 517 } |
518 | 518 |
519 | 519 |
520 Handle<Code> GetTypeRecordingUnaryOpStub(int key, | 520 Handle<Code> GetUnaryOpStub(int key, |
Søren Thygesen Gjesse
2011/05/24 11:33:11
Indentation.
fschneider
2011/05/24 12:16:41
Done.
| |
521 TRUnaryOpIC::TypeInfo type_info) { | 521 UnaryOpIC::TypeInfo type_info) { |
522 TypeRecordingUnaryOpStub stub(key, type_info); | 522 UnaryOpStub stub(key, type_info); |
523 return stub.GetCode(); | 523 return stub.GetCode(); |
524 } | 524 } |
525 | 525 |
526 | 526 |
527 const char* TypeRecordingUnaryOpStub::GetName() { | 527 const char* UnaryOpStub::GetName() { |
528 if (name_ != NULL) return name_; | 528 if (name_ != NULL) return name_; |
529 const int kMaxNameLength = 100; | 529 const int kMaxNameLength = 100; |
530 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( | 530 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( |
531 kMaxNameLength); | 531 kMaxNameLength); |
532 if (name_ == NULL) return "OOM"; | 532 if (name_ == NULL) return "OOM"; |
533 const char* op_name = Token::Name(op_); | 533 const char* op_name = Token::Name(op_); |
534 const char* overwrite_name = NULL; // Make g++ happy. | 534 const char* overwrite_name = NULL; // Make g++ happy. |
535 switch (mode_) { | 535 switch (mode_) { |
536 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; | 536 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; |
537 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; | 537 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; |
538 } | 538 } |
539 | 539 |
540 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 540 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), |
541 "TypeRecordingUnaryOpStub_%s_%s_%s", | 541 "UnaryOpStub_%s_%s_%s", |
542 op_name, | 542 op_name, |
543 overwrite_name, | 543 overwrite_name, |
544 TRUnaryOpIC::GetName(operand_type_)); | 544 UnaryOpIC::GetName(operand_type_)); |
545 return name_; | 545 return name_; |
546 } | 546 } |
547 | 547 |
548 | 548 |
549 // TODO(svenpanne): Use virtual functions instead of switch. | 549 // TODO(svenpanne): Use virtual functions instead of switch. |
550 void TypeRecordingUnaryOpStub::Generate(MacroAssembler* masm) { | 550 void UnaryOpStub::Generate(MacroAssembler* masm) { |
551 switch (operand_type_) { | 551 switch (operand_type_) { |
552 case TRUnaryOpIC::UNINITIALIZED: | 552 case UnaryOpIC::UNINITIALIZED: |
553 GenerateTypeTransition(masm); | 553 GenerateTypeTransition(masm); |
554 break; | 554 break; |
555 case TRUnaryOpIC::SMI: | 555 case UnaryOpIC::SMI: |
556 GenerateSmiStub(masm); | 556 GenerateSmiStub(masm); |
557 break; | 557 break; |
558 case TRUnaryOpIC::HEAP_NUMBER: | 558 case UnaryOpIC::HEAP_NUMBER: |
559 GenerateHeapNumberStub(masm); | 559 GenerateHeapNumberStub(masm); |
560 break; | 560 break; |
561 case TRUnaryOpIC::GENERIC: | 561 case UnaryOpIC::GENERIC: |
562 GenerateGenericStub(masm); | 562 GenerateGenericStub(masm); |
563 break; | 563 break; |
564 } | 564 } |
565 } | 565 } |
566 | 566 |
567 | 567 |
568 void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { | 568 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { |
569 __ pop(ecx); // Save return address. | 569 __ pop(ecx); // Save return address. |
570 __ push(eax); | 570 __ push(eax); |
571 // the argument is now on top. | 571 // the argument is now on top. |
572 // Push this stub's key. Although the operation and the type info are | 572 // Push this stub's key. Although the operation and the type info are |
573 // encoded into the key, the encoding is opaque, so push them too. | 573 // encoded into the key, the encoding is opaque, so push them too. |
574 __ push(Immediate(Smi::FromInt(MinorKey()))); | 574 __ push(Immediate(Smi::FromInt(MinorKey()))); |
575 __ push(Immediate(Smi::FromInt(op_))); | 575 __ push(Immediate(Smi::FromInt(op_))); |
576 __ push(Immediate(Smi::FromInt(operand_type_))); | 576 __ push(Immediate(Smi::FromInt(operand_type_))); |
577 | 577 |
578 __ push(ecx); // Push return address. | 578 __ push(ecx); // Push return address. |
579 | 579 |
580 // Patch the caller to an appropriate specialized stub and return the | 580 // Patch the caller to an appropriate specialized stub and return the |
581 // operation result to the caller of the stub. | 581 // operation result to the caller of the stub. |
582 __ TailCallExternalReference( | 582 __ TailCallExternalReference( |
583 ExternalReference(IC_Utility(IC::kTypeRecordingUnaryOp_Patch), | 583 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), |
584 masm->isolate()), | 584 masm->isolate()), 4, 1); |
585 4, | |
586 1); | |
587 } | 585 } |
588 | 586 |
589 | 587 |
590 // TODO(svenpanne): Use virtual functions instead of switch. | 588 // TODO(svenpanne): Use virtual functions instead of switch. |
591 void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { | 589 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { |
592 switch (op_) { | 590 switch (op_) { |
593 case Token::SUB: | 591 case Token::SUB: |
594 GenerateSmiStubSub(masm); | 592 GenerateSmiStubSub(masm); |
595 break; | 593 break; |
596 case Token::BIT_NOT: | 594 case Token::BIT_NOT: |
597 GenerateSmiStubBitNot(masm); | 595 GenerateSmiStubBitNot(masm); |
598 break; | 596 break; |
599 default: | 597 default: |
600 UNREACHABLE(); | 598 UNREACHABLE(); |
601 } | 599 } |
602 } | 600 } |
603 | 601 |
604 | 602 |
605 void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) { | 603 void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) { |
606 Label non_smi, undo, slow; | 604 Label non_smi, undo, slow; |
607 GenerateSmiCodeSub(masm, &non_smi, &undo, &slow, | 605 GenerateSmiCodeSub(masm, &non_smi, &undo, &slow, |
608 Label::kNear, Label::kNear, Label::kNear); | 606 Label::kNear, Label::kNear, Label::kNear); |
609 __ bind(&undo); | 607 __ bind(&undo); |
610 GenerateSmiCodeUndo(masm); | 608 GenerateSmiCodeUndo(masm); |
611 __ bind(&non_smi); | 609 __ bind(&non_smi); |
612 __ bind(&slow); | 610 __ bind(&slow); |
613 GenerateTypeTransition(masm); | 611 GenerateTypeTransition(masm); |
614 } | 612 } |
615 | 613 |
616 | 614 |
617 void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) { | 615 void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) { |
618 Label non_smi; | 616 Label non_smi; |
619 GenerateSmiCodeBitNot(masm, &non_smi); | 617 GenerateSmiCodeBitNot(masm, &non_smi); |
620 __ bind(&non_smi); | 618 __ bind(&non_smi); |
621 GenerateTypeTransition(masm); | 619 GenerateTypeTransition(masm); |
622 } | 620 } |
623 | 621 |
624 | 622 |
625 void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, | 623 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, |
Søren Thygesen Gjesse
2011/05/24 11:33:11
Indentation.
fschneider
2011/05/24 12:16:41
Done.
| |
626 Label* non_smi, | 624 Label* non_smi, |
627 Label* undo, | 625 Label* undo, |
628 Label* slow, | 626 Label* slow, |
629 Label::Distance non_smi_near, | 627 Label::Distance non_smi_near, |
630 Label::Distance undo_near, | 628 Label::Distance undo_near, |
631 Label::Distance slow_near) { | 629 Label::Distance slow_near) { |
632 // Check whether the value is a smi. | 630 // Check whether the value is a smi. |
633 __ test(eax, Immediate(kSmiTagMask)); | 631 __ test(eax, Immediate(kSmiTagMask)); |
634 __ j(not_zero, non_smi, non_smi_near); | 632 __ j(not_zero, non_smi, non_smi_near); |
635 | 633 |
636 // We can't handle -0 with smis, so use a type transition for that case. | 634 // We can't handle -0 with smis, so use a type transition for that case. |
637 __ test(eax, Operand(eax)); | 635 __ test(eax, Operand(eax)); |
638 __ j(zero, slow, slow_near); | 636 __ j(zero, slow, slow_near); |
639 | 637 |
640 // Try optimistic subtraction '0 - value', saving operand in eax for undo. | 638 // Try optimistic subtraction '0 - value', saving operand in eax for undo. |
641 __ mov(edx, Operand(eax)); | 639 __ mov(edx, Operand(eax)); |
642 __ Set(eax, Immediate(0)); | 640 __ Set(eax, Immediate(0)); |
643 __ sub(eax, Operand(edx)); | 641 __ sub(eax, Operand(edx)); |
644 __ j(overflow, undo, undo_near); | 642 __ j(overflow, undo, undo_near); |
645 __ ret(0); | 643 __ ret(0); |
646 } | 644 } |
647 | 645 |
648 | 646 |
649 void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot( | 647 void UnaryOpStub::GenerateSmiCodeBitNot( |
650 MacroAssembler* masm, | 648 MacroAssembler* masm, |
651 Label* non_smi, | 649 Label* non_smi, |
652 Label::Distance non_smi_near) { | 650 Label::Distance non_smi_near) { |
653 // Check whether the value is a smi. | 651 // Check whether the value is a smi. |
654 __ test(eax, Immediate(kSmiTagMask)); | 652 __ test(eax, Immediate(kSmiTagMask)); |
655 __ j(not_zero, non_smi, non_smi_near); | 653 __ j(not_zero, non_smi, non_smi_near); |
656 | 654 |
657 // Flip bits and revert inverted smi-tag. | 655 // Flip bits and revert inverted smi-tag. |
658 __ not_(eax); | 656 __ not_(eax); |
659 __ and_(eax, ~kSmiTagMask); | 657 __ and_(eax, ~kSmiTagMask); |
660 __ ret(0); | 658 __ ret(0); |
661 } | 659 } |
662 | 660 |
663 | 661 |
664 void TypeRecordingUnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) { | 662 void UnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) { |
665 __ mov(eax, Operand(edx)); | 663 __ mov(eax, Operand(edx)); |
666 } | 664 } |
667 | 665 |
668 | 666 |
669 // TODO(svenpanne): Use virtual functions instead of switch. | 667 // TODO(svenpanne): Use virtual functions instead of switch. |
670 void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { | 668 void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { |
671 switch (op_) { | 669 switch (op_) { |
672 case Token::SUB: | 670 case Token::SUB: |
673 GenerateHeapNumberStubSub(masm); | 671 GenerateHeapNumberStubSub(masm); |
674 break; | 672 break; |
675 case Token::BIT_NOT: | 673 case Token::BIT_NOT: |
676 GenerateHeapNumberStubBitNot(masm); | 674 GenerateHeapNumberStubBitNot(masm); |
677 break; | 675 break; |
678 default: | 676 default: |
679 UNREACHABLE(); | 677 UNREACHABLE(); |
680 } | 678 } |
681 } | 679 } |
682 | 680 |
683 | 681 |
684 void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) { | 682 void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) { |
685 Label non_smi, undo, slow, call_builtin; | 683 Label non_smi, undo, slow, call_builtin; |
686 GenerateSmiCodeSub(masm, &non_smi, &undo, &call_builtin, Label::kNear); | 684 GenerateSmiCodeSub(masm, &non_smi, &undo, &call_builtin, Label::kNear); |
687 __ bind(&non_smi); | 685 __ bind(&non_smi); |
688 GenerateHeapNumberCodeSub(masm, &slow); | 686 GenerateHeapNumberCodeSub(masm, &slow); |
689 __ bind(&undo); | 687 __ bind(&undo); |
690 GenerateSmiCodeUndo(masm); | 688 GenerateSmiCodeUndo(masm); |
691 __ bind(&slow); | 689 __ bind(&slow); |
692 GenerateTypeTransition(masm); | 690 GenerateTypeTransition(masm); |
693 __ bind(&call_builtin); | 691 __ bind(&call_builtin); |
694 GenerateGenericCodeFallback(masm); | 692 GenerateGenericCodeFallback(masm); |
695 } | 693 } |
696 | 694 |
697 | 695 |
698 void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot( | 696 void UnaryOpStub::GenerateHeapNumberStubBitNot( |
699 MacroAssembler* masm) { | 697 MacroAssembler* masm) { |
700 Label non_smi, slow; | 698 Label non_smi, slow; |
701 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear); | 699 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear); |
702 __ bind(&non_smi); | 700 __ bind(&non_smi); |
703 GenerateHeapNumberCodeBitNot(masm, &slow); | 701 GenerateHeapNumberCodeBitNot(masm, &slow); |
704 __ bind(&slow); | 702 __ bind(&slow); |
705 GenerateTypeTransition(masm); | 703 GenerateTypeTransition(masm); |
706 } | 704 } |
707 | 705 |
708 | 706 |
709 void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, | 707 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, |
Søren Thygesen Gjesse
2011/05/24 11:33:11
Indentation.
fschneider
2011/05/24 12:16:41
Done.
| |
710 Label* slow) { | 708 Label* slow) { |
711 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 709 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
712 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); | 710 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); |
713 __ j(not_equal, slow); | 711 __ j(not_equal, slow); |
714 | 712 |
715 if (mode_ == UNARY_OVERWRITE) { | 713 if (mode_ == UNARY_OVERWRITE) { |
716 __ xor_(FieldOperand(eax, HeapNumber::kExponentOffset), | 714 __ xor_(FieldOperand(eax, HeapNumber::kExponentOffset), |
717 Immediate(HeapNumber::kSignMask)); // Flip sign. | 715 Immediate(HeapNumber::kSignMask)); // Flip sign. |
718 } else { | 716 } else { |
719 __ mov(edx, Operand(eax)); | 717 __ mov(edx, Operand(eax)); |
(...skipping 15 matching lines...) Expand all Loading... | |
735 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 733 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
736 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. | 734 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. |
737 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); | 735 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); |
738 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); | 736 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); |
739 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | 737 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); |
740 } | 738 } |
741 __ ret(0); | 739 __ ret(0); |
742 } | 740 } |
743 | 741 |
744 | 742 |
745 void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot( | 743 void UnaryOpStub::GenerateHeapNumberCodeBitNot( |
Søren Thygesen Gjesse
2011/05/24 11:33:11
Move MacroAssembler* masm, up one line and full in
fschneider
2011/05/24 12:16:41
Done.
| |
746 MacroAssembler* masm, | 744 MacroAssembler* masm, |
747 Label* slow) { | 745 Label* slow) { |
748 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 746 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
749 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); | 747 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); |
750 __ j(not_equal, slow); | 748 __ j(not_equal, slow); |
751 | 749 |
752 // Convert the heap number in eax to an untagged integer in ecx. | 750 // Convert the heap number in eax to an untagged integer in ecx. |
753 IntegerConvert(masm, eax, CpuFeatures::IsSupported(SSE3), slow); | 751 IntegerConvert(masm, eax, CpuFeatures::IsSupported(SSE3), slow); |
754 | 752 |
755 // Do the bitwise operation and check if the result fits in a smi. | 753 // Do the bitwise operation and check if the result fits in a smi. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
796 __ push(ecx); | 794 __ push(ecx); |
797 __ fild_s(Operand(esp, 0)); | 795 __ fild_s(Operand(esp, 0)); |
798 __ pop(ecx); | 796 __ pop(ecx); |
799 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 797 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
800 } | 798 } |
801 __ ret(0); | 799 __ ret(0); |
802 } | 800 } |
803 | 801 |
804 | 802 |
805 // TODO(svenpanne): Use virtual functions instead of switch. | 803 // TODO(svenpanne): Use virtual functions instead of switch. |
806 void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) { | 804 void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) { |
807 switch (op_) { | 805 switch (op_) { |
808 case Token::SUB: | 806 case Token::SUB: |
809 GenerateGenericStubSub(masm); | 807 GenerateGenericStubSub(masm); |
810 break; | 808 break; |
811 case Token::BIT_NOT: | 809 case Token::BIT_NOT: |
812 GenerateGenericStubBitNot(masm); | 810 GenerateGenericStubBitNot(masm); |
813 break; | 811 break; |
814 default: | 812 default: |
815 UNREACHABLE(); | 813 UNREACHABLE(); |
816 } | 814 } |
817 } | 815 } |
818 | 816 |
819 | 817 |
820 void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) { | 818 void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) { |
821 Label non_smi, undo, slow; | 819 Label non_smi, undo, slow; |
822 GenerateSmiCodeSub(masm, &non_smi, &undo, &slow, Label::kNear); | 820 GenerateSmiCodeSub(masm, &non_smi, &undo, &slow, Label::kNear); |
823 __ bind(&non_smi); | 821 __ bind(&non_smi); |
824 GenerateHeapNumberCodeSub(masm, &slow); | 822 GenerateHeapNumberCodeSub(masm, &slow); |
825 __ bind(&undo); | 823 __ bind(&undo); |
826 GenerateSmiCodeUndo(masm); | 824 GenerateSmiCodeUndo(masm); |
827 __ bind(&slow); | 825 __ bind(&slow); |
828 GenerateGenericCodeFallback(masm); | 826 GenerateGenericCodeFallback(masm); |
829 } | 827 } |
830 | 828 |
831 | 829 |
832 void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) { | 830 void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) { |
833 Label non_smi, slow; | 831 Label non_smi, slow; |
834 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear); | 832 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear); |
835 __ bind(&non_smi); | 833 __ bind(&non_smi); |
836 GenerateHeapNumberCodeBitNot(masm, &slow); | 834 GenerateHeapNumberCodeBitNot(masm, &slow); |
837 __ bind(&slow); | 835 __ bind(&slow); |
838 GenerateGenericCodeFallback(masm); | 836 GenerateGenericCodeFallback(masm); |
839 } | 837 } |
840 | 838 |
841 | 839 |
842 void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback( | 840 void UnaryOpStub::GenerateGenericCodeFallback( |
Søren Thygesen Gjesse
2011/05/24 11:33:11
Fits one line?
fschneider
2011/05/24 12:16:41
Done.
| |
843 MacroAssembler* masm) { | 841 MacroAssembler* masm) { |
844 // Handle the slow case by jumping to the corresponding JavaScript builtin. | 842 // Handle the slow case by jumping to the corresponding JavaScript builtin. |
845 __ pop(ecx); // pop return address. | 843 __ pop(ecx); // pop return address. |
846 __ push(eax); | 844 __ push(eax); |
847 __ push(ecx); // push return address | 845 __ push(ecx); // push return address |
848 switch (op_) { | 846 switch (op_) { |
849 case Token::SUB: | 847 case Token::SUB: |
850 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); | 848 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); |
851 break; | 849 break; |
852 case Token::BIT_NOT: | 850 case Token::BIT_NOT: |
853 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); | 851 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); |
854 break; | 852 break; |
855 default: | 853 default: |
856 UNREACHABLE(); | 854 UNREACHABLE(); |
857 } | 855 } |
858 } | 856 } |
859 | 857 |
860 | 858 |
861 Handle<Code> GetTypeRecordingBinaryOpStub(int key, | 859 Handle<Code> GetBinaryOpStub(int key, |
862 TRBinaryOpIC::TypeInfo type_info, | 860 BinaryOpIC::TypeInfo type_info, |
863 TRBinaryOpIC::TypeInfo result_type_info) { | 861 BinaryOpIC::TypeInfo result_type_info) { |
864 TypeRecordingBinaryOpStub stub(key, type_info, result_type_info); | 862 BinaryOpStub stub(key, type_info, result_type_info); |
865 return stub.GetCode(); | 863 return stub.GetCode(); |
866 } | 864 } |
867 | 865 |
868 | 866 |
869 void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { | 867 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { |
870 __ pop(ecx); // Save return address. | 868 __ pop(ecx); // Save return address. |
871 __ push(edx); | 869 __ push(edx); |
872 __ push(eax); | 870 __ push(eax); |
873 // Left and right arguments are now on top. | 871 // Left and right arguments are now on top. |
874 // Push this stub's key. Although the operation and the type info are | 872 // Push this stub's key. Although the operation and the type info are |
875 // encoded into the key, the encoding is opaque, so push them too. | 873 // encoded into the key, the encoding is opaque, so push them too. |
876 __ push(Immediate(Smi::FromInt(MinorKey()))); | 874 __ push(Immediate(Smi::FromInt(MinorKey()))); |
877 __ push(Immediate(Smi::FromInt(op_))); | 875 __ push(Immediate(Smi::FromInt(op_))); |
878 __ push(Immediate(Smi::FromInt(operands_type_))); | 876 __ push(Immediate(Smi::FromInt(operands_type_))); |
879 | 877 |
880 __ push(ecx); // Push return address. | 878 __ push(ecx); // Push return address. |
881 | 879 |
882 // Patch the caller to an appropriate specialized stub and return the | 880 // Patch the caller to an appropriate specialized stub and return the |
883 // operation result to the caller of the stub. | 881 // operation result to the caller of the stub. |
884 __ TailCallExternalReference( | 882 __ TailCallExternalReference( |
885 ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch), | 883 ExternalReference(IC_Utility(IC::kBinaryOp_Patch), |
886 masm->isolate()), | 884 masm->isolate()), |
887 5, | 885 5, |
888 1); | 886 1); |
889 } | 887 } |
890 | 888 |
891 | 889 |
892 // Prepare for a type transition runtime call when the args are already on | 890 // Prepare for a type transition runtime call when the args are already on |
893 // the stack, under the return address. | 891 // the stack, under the return address. |
894 void TypeRecordingBinaryOpStub::GenerateTypeTransitionWithSavedArgs( | 892 void BinaryOpStub::GenerateTypeTransitionWithSavedArgs( |
Søren Thygesen Gjesse
2011/05/24 11:33:11
Fits one line?
fschneider
2011/05/24 12:16:41
Done.
| |
895 MacroAssembler* masm) { | 893 MacroAssembler* masm) { |
896 __ pop(ecx); // Save return address. | 894 __ pop(ecx); // Save return address. |
897 // Left and right arguments are already on top of the stack. | 895 // Left and right arguments are already on top of the stack. |
898 // Push this stub's key. Although the operation and the type info are | 896 // Push this stub's key. Although the operation and the type info are |
899 // encoded into the key, the encoding is opaque, so push them too. | 897 // encoded into the key, the encoding is opaque, so push them too. |
900 __ push(Immediate(Smi::FromInt(MinorKey()))); | 898 __ push(Immediate(Smi::FromInt(MinorKey()))); |
901 __ push(Immediate(Smi::FromInt(op_))); | 899 __ push(Immediate(Smi::FromInt(op_))); |
902 __ push(Immediate(Smi::FromInt(operands_type_))); | 900 __ push(Immediate(Smi::FromInt(operands_type_))); |
903 | 901 |
904 __ push(ecx); // Push return address. | 902 __ push(ecx); // Push return address. |
905 | 903 |
906 // Patch the caller to an appropriate specialized stub and return the | 904 // Patch the caller to an appropriate specialized stub and return the |
907 // operation result to the caller of the stub. | 905 // operation result to the caller of the stub. |
908 __ TailCallExternalReference( | 906 __ TailCallExternalReference( |
909 ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch), | 907 ExternalReference(IC_Utility(IC::kBinaryOp_Patch), |
910 masm->isolate()), | 908 masm->isolate()), |
911 5, | 909 5, |
912 1); | 910 1); |
913 } | 911 } |
914 | 912 |
915 | 913 |
916 void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) { | 914 void BinaryOpStub::Generate(MacroAssembler* masm) { |
917 switch (operands_type_) { | 915 switch (operands_type_) { |
918 case TRBinaryOpIC::UNINITIALIZED: | 916 case BinaryOpIC::UNINITIALIZED: |
919 GenerateTypeTransition(masm); | 917 GenerateTypeTransition(masm); |
920 break; | 918 break; |
921 case TRBinaryOpIC::SMI: | 919 case BinaryOpIC::SMI: |
922 GenerateSmiStub(masm); | 920 GenerateSmiStub(masm); |
923 break; | 921 break; |
924 case TRBinaryOpIC::INT32: | 922 case BinaryOpIC::INT32: |
925 GenerateInt32Stub(masm); | 923 GenerateInt32Stub(masm); |
926 break; | 924 break; |
927 case TRBinaryOpIC::HEAP_NUMBER: | 925 case BinaryOpIC::HEAP_NUMBER: |
928 GenerateHeapNumberStub(masm); | 926 GenerateHeapNumberStub(masm); |
929 break; | 927 break; |
930 case TRBinaryOpIC::ODDBALL: | 928 case BinaryOpIC::ODDBALL: |
931 GenerateOddballStub(masm); | 929 GenerateOddballStub(masm); |
932 break; | 930 break; |
933 case TRBinaryOpIC::BOTH_STRING: | 931 case BinaryOpIC::BOTH_STRING: |
934 GenerateBothStringStub(masm); | 932 GenerateBothStringStub(masm); |
935 break; | 933 break; |
936 case TRBinaryOpIC::STRING: | 934 case BinaryOpIC::STRING: |
937 GenerateStringStub(masm); | 935 GenerateStringStub(masm); |
938 break; | 936 break; |
939 case TRBinaryOpIC::GENERIC: | 937 case BinaryOpIC::GENERIC: |
940 GenerateGeneric(masm); | 938 GenerateGeneric(masm); |
941 break; | 939 break; |
942 default: | 940 default: |
943 UNREACHABLE(); | 941 UNREACHABLE(); |
944 } | 942 } |
945 } | 943 } |
946 | 944 |
947 | 945 |
948 const char* TypeRecordingBinaryOpStub::GetName() { | 946 const char* BinaryOpStub::GetName() { |
949 if (name_ != NULL) return name_; | 947 if (name_ != NULL) return name_; |
950 const int kMaxNameLength = 100; | 948 const int kMaxNameLength = 100; |
951 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( | 949 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( |
952 kMaxNameLength); | 950 kMaxNameLength); |
953 if (name_ == NULL) return "OOM"; | 951 if (name_ == NULL) return "OOM"; |
954 const char* op_name = Token::Name(op_); | 952 const char* op_name = Token::Name(op_); |
955 const char* overwrite_name; | 953 const char* overwrite_name; |
956 switch (mode_) { | 954 switch (mode_) { |
957 case NO_OVERWRITE: overwrite_name = "Alloc"; break; | 955 case NO_OVERWRITE: overwrite_name = "Alloc"; break; |
958 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; | 956 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; |
959 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; | 957 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; |
960 default: overwrite_name = "UnknownOverwrite"; break; | 958 default: overwrite_name = "UnknownOverwrite"; break; |
961 } | 959 } |
962 | 960 |
963 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 961 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), |
964 "TypeRecordingBinaryOpStub_%s_%s_%s", | 962 "BinaryOpStub_%s_%s_%s", |
965 op_name, | 963 op_name, |
966 overwrite_name, | 964 overwrite_name, |
967 TRBinaryOpIC::GetName(operands_type_)); | 965 BinaryOpIC::GetName(operands_type_)); |
968 return name_; | 966 return name_; |
969 } | 967 } |
970 | 968 |
971 | 969 |
972 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, | 970 void BinaryOpStub::GenerateSmiCode(MacroAssembler* masm, |
Søren Thygesen Gjesse
2011/05/24 11:33:11
MacroAssembler* masm, on a separate line
fschneider
2011/05/24 12:16:41
Done.
| |
973 Label* slow, | 971 Label* slow, |
974 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { | 972 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { |
975 // 1. Move arguments into edx, eax except for DIV and MOD, which need the | 973 // 1. Move arguments into edx, eax except for DIV and MOD, which need the |
976 // dividend in eax and edx free for the division. Use eax, ebx for those. | 974 // dividend in eax and edx free for the division. Use eax, ebx for those. |
977 Comment load_comment(masm, "-- Load arguments"); | 975 Comment load_comment(masm, "-- Load arguments"); |
978 Register left = edx; | 976 Register left = edx; |
979 Register right = eax; | 977 Register right = eax; |
980 if (op_ == Token::DIV || op_ == Token::MOD) { | 978 if (op_ == Token::DIV || op_ == Token::MOD) { |
981 left = eax; | 979 left = eax; |
982 right = ebx; | 980 right = ebx; |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1337 __ mov(edx, eax); | 1335 __ mov(edx, eax); |
1338 __ mov(eax, ebx); | 1336 __ mov(eax, ebx); |
1339 break; | 1337 break; |
1340 | 1338 |
1341 default: | 1339 default: |
1342 break; | 1340 break; |
1343 } | 1341 } |
1344 } | 1342 } |
1345 | 1343 |
1346 | 1344 |
1347 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { | 1345 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { |
1348 Label call_runtime; | 1346 Label call_runtime; |
1349 | 1347 |
1350 switch (op_) { | 1348 switch (op_) { |
1351 case Token::ADD: | 1349 case Token::ADD: |
1352 case Token::SUB: | 1350 case Token::SUB: |
1353 case Token::MUL: | 1351 case Token::MUL: |
1354 case Token::DIV: | 1352 case Token::DIV: |
1355 break; | 1353 break; |
1356 case Token::MOD: | 1354 case Token::MOD: |
1357 case Token::BIT_OR: | 1355 case Token::BIT_OR: |
1358 case Token::BIT_AND: | 1356 case Token::BIT_AND: |
1359 case Token::BIT_XOR: | 1357 case Token::BIT_XOR: |
1360 case Token::SAR: | 1358 case Token::SAR: |
1361 case Token::SHL: | 1359 case Token::SHL: |
1362 case Token::SHR: | 1360 case Token::SHR: |
1363 GenerateRegisterArgsPush(masm); | 1361 GenerateRegisterArgsPush(masm); |
1364 break; | 1362 break; |
1365 default: | 1363 default: |
1366 UNREACHABLE(); | 1364 UNREACHABLE(); |
1367 } | 1365 } |
1368 | 1366 |
1369 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || | 1367 if (result_type_ == BinaryOpIC::UNINITIALIZED || |
1370 result_type_ == TRBinaryOpIC::SMI) { | 1368 result_type_ == BinaryOpIC::SMI) { |
1371 GenerateSmiCode(masm, &call_runtime, NO_HEAPNUMBER_RESULTS); | 1369 GenerateSmiCode(masm, &call_runtime, NO_HEAPNUMBER_RESULTS); |
1372 } else { | 1370 } else { |
1373 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); | 1371 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); |
1374 } | 1372 } |
1375 __ bind(&call_runtime); | 1373 __ bind(&call_runtime); |
1376 switch (op_) { | 1374 switch (op_) { |
1377 case Token::ADD: | 1375 case Token::ADD: |
1378 case Token::SUB: | 1376 case Token::SUB: |
1379 case Token::MUL: | 1377 case Token::MUL: |
1380 case Token::DIV: | 1378 case Token::DIV: |
1381 GenerateTypeTransition(masm); | 1379 GenerateTypeTransition(masm); |
1382 break; | 1380 break; |
1383 case Token::MOD: | 1381 case Token::MOD: |
1384 case Token::BIT_OR: | 1382 case Token::BIT_OR: |
1385 case Token::BIT_AND: | 1383 case Token::BIT_AND: |
1386 case Token::BIT_XOR: | 1384 case Token::BIT_XOR: |
1387 case Token::SAR: | 1385 case Token::SAR: |
1388 case Token::SHL: | 1386 case Token::SHL: |
1389 case Token::SHR: | 1387 case Token::SHR: |
1390 GenerateTypeTransitionWithSavedArgs(masm); | 1388 GenerateTypeTransitionWithSavedArgs(masm); |
1391 break; | 1389 break; |
1392 default: | 1390 default: |
1393 UNREACHABLE(); | 1391 UNREACHABLE(); |
1394 } | 1392 } |
1395 } | 1393 } |
1396 | 1394 |
1397 | 1395 |
1398 void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) { | 1396 void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) { |
1399 ASSERT(operands_type_ == TRBinaryOpIC::STRING); | 1397 ASSERT(operands_type_ == BinaryOpIC::STRING); |
1400 ASSERT(op_ == Token::ADD); | 1398 ASSERT(op_ == Token::ADD); |
1401 // Try to add arguments as strings, otherwise, transition to the generic | 1399 // Try to add arguments as strings, otherwise, transition to the generic |
1402 // TRBinaryOpIC type. | 1400 // BinaryOpIC type. |
1403 GenerateAddStrings(masm); | 1401 GenerateAddStrings(masm); |
1404 GenerateTypeTransition(masm); | 1402 GenerateTypeTransition(masm); |
1405 } | 1403 } |
1406 | 1404 |
1407 | 1405 |
1408 void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) { | 1406 void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) { |
1409 Label call_runtime; | 1407 Label call_runtime; |
1410 ASSERT(operands_type_ == TRBinaryOpIC::BOTH_STRING); | 1408 ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING); |
1411 ASSERT(op_ == Token::ADD); | 1409 ASSERT(op_ == Token::ADD); |
1412 // If both arguments are strings, call the string add stub. | 1410 // If both arguments are strings, call the string add stub. |
1413 // Otherwise, do a transition. | 1411 // Otherwise, do a transition. |
1414 | 1412 |
1415 // Registers containing left and right operands respectively. | 1413 // Registers containing left and right operands respectively. |
1416 Register left = edx; | 1414 Register left = edx; |
1417 Register right = eax; | 1415 Register right = eax; |
1418 | 1416 |
1419 // Test if left operand is a string. | 1417 // Test if left operand is a string. |
1420 __ test(left, Immediate(kSmiTagMask)); | 1418 __ test(left, Immediate(kSmiTagMask)); |
1421 __ j(zero, &call_runtime); | 1419 __ j(zero, &call_runtime); |
1422 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); | 1420 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
1423 __ j(above_equal, &call_runtime); | 1421 __ j(above_equal, &call_runtime); |
1424 | 1422 |
1425 // Test if right operand is a string. | 1423 // Test if right operand is a string. |
1426 __ test(right, Immediate(kSmiTagMask)); | 1424 __ test(right, Immediate(kSmiTagMask)); |
1427 __ j(zero, &call_runtime); | 1425 __ j(zero, &call_runtime); |
1428 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); | 1426 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); |
1429 __ j(above_equal, &call_runtime); | 1427 __ j(above_equal, &call_runtime); |
1430 | 1428 |
1431 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); | 1429 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); |
1432 GenerateRegisterArgsPush(masm); | 1430 GenerateRegisterArgsPush(masm); |
1433 __ TailCallStub(&string_add_stub); | 1431 __ TailCallStub(&string_add_stub); |
1434 | 1432 |
1435 __ bind(&call_runtime); | 1433 __ bind(&call_runtime); |
1436 GenerateTypeTransition(masm); | 1434 GenerateTypeTransition(masm); |
1437 } | 1435 } |
1438 | 1436 |
1439 | 1437 |
1440 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { | 1438 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
1441 Label call_runtime; | 1439 Label call_runtime; |
1442 ASSERT(operands_type_ == TRBinaryOpIC::INT32); | 1440 ASSERT(operands_type_ == BinaryOpIC::INT32); |
1443 | 1441 |
1444 // Floating point case. | 1442 // Floating point case. |
1445 switch (op_) { | 1443 switch (op_) { |
1446 case Token::ADD: | 1444 case Token::ADD: |
1447 case Token::SUB: | 1445 case Token::SUB: |
1448 case Token::MUL: | 1446 case Token::MUL: |
1449 case Token::DIV: { | 1447 case Token::DIV: { |
1450 Label not_floats; | 1448 Label not_floats; |
1451 Label not_int32; | 1449 Label not_int32; |
1452 if (CpuFeatures::IsSupported(SSE2)) { | 1450 if (CpuFeatures::IsSupported(SSE2)) { |
1453 CpuFeatures::Scope use_sse2(SSE2); | 1451 CpuFeatures::Scope use_sse2(SSE2); |
1454 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); | 1452 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); |
1455 FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, ¬_int32, ecx); | 1453 FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, ¬_int32, ecx); |
1456 switch (op_) { | 1454 switch (op_) { |
1457 case Token::ADD: __ addsd(xmm0, xmm1); break; | 1455 case Token::ADD: __ addsd(xmm0, xmm1); break; |
1458 case Token::SUB: __ subsd(xmm0, xmm1); break; | 1456 case Token::SUB: __ subsd(xmm0, xmm1); break; |
1459 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 1457 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
1460 case Token::DIV: __ divsd(xmm0, xmm1); break; | 1458 case Token::DIV: __ divsd(xmm0, xmm1); break; |
1461 default: UNREACHABLE(); | 1459 default: UNREACHABLE(); |
1462 } | 1460 } |
1463 // Check result type if it is currently Int32. | 1461 // Check result type if it is currently Int32. |
1464 if (result_type_ <= TRBinaryOpIC::INT32) { | 1462 if (result_type_ <= BinaryOpIC::INT32) { |
1465 __ cvttsd2si(ecx, Operand(xmm0)); | 1463 __ cvttsd2si(ecx, Operand(xmm0)); |
1466 __ cvtsi2sd(xmm2, Operand(ecx)); | 1464 __ cvtsi2sd(xmm2, Operand(ecx)); |
1467 __ ucomisd(xmm0, xmm2); | 1465 __ ucomisd(xmm0, xmm2); |
1468 __ j(not_zero, ¬_int32); | 1466 __ j(not_zero, ¬_int32); |
1469 __ j(carry, ¬_int32); | 1467 __ j(carry, ¬_int32); |
1470 } | 1468 } |
1471 GenerateHeapResultAllocation(masm, &call_runtime); | 1469 GenerateHeapResultAllocation(masm, &call_runtime); |
1472 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1470 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
1473 __ ret(0); | 1471 __ ret(0); |
1474 } else { // SSE2 not available, use FPU. | 1472 } else { // SSE2 not available, use FPU. |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1632 break; | 1630 break; |
1633 case Token::SHR: | 1631 case Token::SHR: |
1634 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); | 1632 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); |
1635 break; | 1633 break; |
1636 default: | 1634 default: |
1637 UNREACHABLE(); | 1635 UNREACHABLE(); |
1638 } | 1636 } |
1639 } | 1637 } |
1640 | 1638 |
1641 | 1639 |
1642 void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { | 1640 void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { |
1643 if (op_ == Token::ADD) { | 1641 if (op_ == Token::ADD) { |
1644 // Handle string addition here, because it is the only operation | 1642 // Handle string addition here, because it is the only operation |
1645 // that does not do a ToNumber conversion on the operands. | 1643 // that does not do a ToNumber conversion on the operands. |
1646 GenerateAddStrings(masm); | 1644 GenerateAddStrings(masm); |
1647 } | 1645 } |
1648 | 1646 |
1649 Factory* factory = masm->isolate()->factory(); | 1647 Factory* factory = masm->isolate()->factory(); |
1650 | 1648 |
1651 // Convert odd ball arguments to numbers. | 1649 // Convert odd ball arguments to numbers. |
1652 Label check, done; | 1650 Label check, done; |
(...skipping 12 matching lines...) Expand all Loading... | |
1665 __ xor_(eax, Operand(eax)); | 1663 __ xor_(eax, Operand(eax)); |
1666 } else { | 1664 } else { |
1667 __ mov(eax, Immediate(factory->nan_value())); | 1665 __ mov(eax, Immediate(factory->nan_value())); |
1668 } | 1666 } |
1669 __ bind(&done); | 1667 __ bind(&done); |
1670 | 1668 |
1671 GenerateHeapNumberStub(masm); | 1669 GenerateHeapNumberStub(masm); |
1672 } | 1670 } |
1673 | 1671 |
1674 | 1672 |
1675 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { | 1673 void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { |
1676 Label call_runtime; | 1674 Label call_runtime; |
1677 | 1675 |
1678 // Floating point case. | 1676 // Floating point case. |
1679 switch (op_) { | 1677 switch (op_) { |
1680 case Token::ADD: | 1678 case Token::ADD: |
1681 case Token::SUB: | 1679 case Token::SUB: |
1682 case Token::MUL: | 1680 case Token::MUL: |
1683 case Token::DIV: { | 1681 case Token::DIV: { |
1684 Label not_floats; | 1682 Label not_floats; |
1685 if (CpuFeatures::IsSupported(SSE2)) { | 1683 if (CpuFeatures::IsSupported(SSE2)) { |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1846 break; | 1844 break; |
1847 case Token::SHR: | 1845 case Token::SHR: |
1848 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); | 1846 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); |
1849 break; | 1847 break; |
1850 default: | 1848 default: |
1851 UNREACHABLE(); | 1849 UNREACHABLE(); |
1852 } | 1850 } |
1853 } | 1851 } |
1854 | 1852 |
1855 | 1853 |
1856 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { | 1854 void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) { |
1857 Label call_runtime; | 1855 Label call_runtime; |
1858 | 1856 |
1859 Counters* counters = masm->isolate()->counters(); | 1857 Counters* counters = masm->isolate()->counters(); |
1860 __ IncrementCounter(counters->generic_binary_stub_calls(), 1); | 1858 __ IncrementCounter(counters->generic_binary_stub_calls(), 1); |
1861 | 1859 |
1862 switch (op_) { | 1860 switch (op_) { |
1863 case Token::ADD: | 1861 case Token::ADD: |
1864 case Token::SUB: | 1862 case Token::SUB: |
1865 case Token::MUL: | 1863 case Token::MUL: |
1866 case Token::DIV: | 1864 case Token::DIV: |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2043 break; | 2041 break; |
2044 case Token::SHR: | 2042 case Token::SHR: |
2045 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); | 2043 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); |
2046 break; | 2044 break; |
2047 default: | 2045 default: |
2048 UNREACHABLE(); | 2046 UNREACHABLE(); |
2049 } | 2047 } |
2050 } | 2048 } |
2051 | 2049 |
2052 | 2050 |
2053 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { | 2051 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { |
2054 ASSERT(op_ == Token::ADD); | 2052 ASSERT(op_ == Token::ADD); |
2055 Label left_not_string, call_runtime; | 2053 Label left_not_string, call_runtime; |
2056 | 2054 |
2057 // Registers containing left and right operands respectively. | 2055 // Registers containing left and right operands respectively. |
2058 Register left = edx; | 2056 Register left = edx; |
2059 Register right = eax; | 2057 Register right = eax; |
2060 | 2058 |
2061 // Test if left operand is a string. | 2059 // Test if left operand is a string. |
2062 __ test(left, Immediate(kSmiTagMask)); | 2060 __ test(left, Immediate(kSmiTagMask)); |
2063 __ j(zero, &left_not_string, Label::kNear); | 2061 __ j(zero, &left_not_string, Label::kNear); |
(...skipping 13 matching lines...) Expand all Loading... | |
2077 | 2075 |
2078 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); | 2076 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); |
2079 GenerateRegisterArgsPush(masm); | 2077 GenerateRegisterArgsPush(masm); |
2080 __ TailCallStub(&string_add_right_stub); | 2078 __ TailCallStub(&string_add_right_stub); |
2081 | 2079 |
2082 // Neither argument is a string. | 2080 // Neither argument is a string. |
2083 __ bind(&call_runtime); | 2081 __ bind(&call_runtime); |
2084 } | 2082 } |
2085 | 2083 |
2086 | 2084 |
2087 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation( | 2085 void BinaryOpStub::GenerateHeapResultAllocation( |
2088 MacroAssembler* masm, | 2086 MacroAssembler* masm, |
2089 Label* alloc_failure) { | 2087 Label* alloc_failure) { |
2090 Label skip_allocation; | 2088 Label skip_allocation; |
2091 OverwriteMode mode = mode_; | 2089 OverwriteMode mode = mode_; |
2092 switch (mode) { | 2090 switch (mode) { |
2093 case OVERWRITE_LEFT: { | 2091 case OVERWRITE_LEFT: { |
2094 // If the argument in edx is already an object, we skip the | 2092 // If the argument in edx is already an object, we skip the |
2095 // allocation of a heap number. | 2093 // allocation of a heap number. |
2096 __ test(edx, Immediate(kSmiTagMask)); | 2094 __ test(edx, Immediate(kSmiTagMask)); |
2097 __ j(not_zero, &skip_allocation); | 2095 __ j(not_zero, &skip_allocation); |
(...skipping 21 matching lines...) Expand all Loading... | |
2119 // Now eax can be overwritten losing one of the arguments as we are | 2117 // Now eax can be overwritten losing one of the arguments as we are |
2120 // now done and will not need it any more. | 2118 // now done and will not need it any more. |
2121 __ mov(eax, ebx); | 2119 __ mov(eax, ebx); |
2122 __ bind(&skip_allocation); | 2120 __ bind(&skip_allocation); |
2123 break; | 2121 break; |
2124 default: UNREACHABLE(); | 2122 default: UNREACHABLE(); |
2125 } | 2123 } |
2126 } | 2124 } |
2127 | 2125 |
2128 | 2126 |
2129 void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { | 2127 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { |
2130 __ pop(ecx); | 2128 __ pop(ecx); |
2131 __ push(edx); | 2129 __ push(edx); |
2132 __ push(eax); | 2130 __ push(eax); |
2133 __ push(ecx); | 2131 __ push(ecx); |
2134 } | 2132 } |
2135 | 2133 |
2136 | 2134 |
2137 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { | 2135 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { |
2138 // TAGGED case: | 2136 // TAGGED case: |
2139 // Input: | 2137 // Input: |
(...skipping 4051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6191 __ Drop(1); | 6189 __ Drop(1); |
6192 __ ret(2 * kPointerSize); | 6190 __ ret(2 * kPointerSize); |
6193 } | 6191 } |
6194 | 6192 |
6195 | 6193 |
6196 #undef __ | 6194 #undef __ |
6197 | 6195 |
6198 } } // namespace v8::internal | 6196 } } // namespace v8::internal |
6199 | 6197 |
6200 #endif // V8_TARGET_ARCH_IA32 | 6198 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |