OLD | NEW |
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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_MIPS | 7 #if V8_TARGET_ARCH_MIPS |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 __ lw(a3, FieldMemOperand(lhs, HeapObject::kMapOffset)); | 602 __ lw(a3, FieldMemOperand(lhs, HeapObject::kMapOffset)); |
603 __ lbu(a2, FieldMemOperand(a2, Map::kBitFieldOffset)); | 603 __ lbu(a2, FieldMemOperand(a2, Map::kBitFieldOffset)); |
604 __ lbu(a3, FieldMemOperand(a3, Map::kBitFieldOffset)); | 604 __ lbu(a3, FieldMemOperand(a3, Map::kBitFieldOffset)); |
605 __ and_(a0, a2, a3); | 605 __ and_(a0, a2, a3); |
606 __ And(a0, a0, Operand(1 << Map::kIsUndetectable)); | 606 __ And(a0, a0, Operand(1 << Map::kIsUndetectable)); |
607 __ Ret(USE_DELAY_SLOT); | 607 __ Ret(USE_DELAY_SLOT); |
608 __ xori(v0, a0, 1 << Map::kIsUndetectable); | 608 __ xori(v0, a0, 1 << Map::kIsUndetectable); |
609 } | 609 } |
610 | 610 |
611 | 611 |
612 static void ICCompareStub_CheckInputType(MacroAssembler* masm, | 612 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, |
613 Register input, | |
614 Register scratch, | 613 Register scratch, |
615 CompareIC::State expected, | 614 CompareIC::State expected, |
616 Label* fail) { | 615 Label* fail) { |
617 Label ok; | 616 Label ok; |
618 if (expected == CompareIC::SMI) { | 617 if (expected == CompareIC::SMI) { |
619 __ JumpIfNotSmi(input, fail); | 618 __ JumpIfNotSmi(input, fail); |
620 } else if (expected == CompareIC::NUMBER) { | 619 } else if (expected == CompareIC::NUMBER) { |
621 __ JumpIfSmi(input, &ok); | 620 __ JumpIfSmi(input, &ok); |
622 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, | 621 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, |
623 DONT_DO_SMI_CHECK); | 622 DONT_DO_SMI_CHECK); |
624 } | 623 } |
625 // We could be strict about internalized/string here, but as long as | 624 // We could be strict about internalized/string here, but as long as |
626 // hydrogen doesn't care, the stub doesn't have to care either. | 625 // hydrogen doesn't care, the stub doesn't have to care either. |
627 __ bind(&ok); | 626 __ bind(&ok); |
628 } | 627 } |
629 | 628 |
630 | 629 |
631 // On entry a1 and a2 are the values to be compared. | 630 // On entry a1 and a2 are the values to be compared. |
632 // On exit a0 is 0, positive or negative to indicate the result of | 631 // On exit a0 is 0, positive or negative to indicate the result of |
633 // the comparison. | 632 // the comparison. |
634 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 633 void CompareICStub::GenerateGeneric(MacroAssembler* masm) { |
635 Register lhs = a1; | 634 Register lhs = a1; |
636 Register rhs = a0; | 635 Register rhs = a0; |
637 Condition cc = GetCondition(); | 636 Condition cc = GetCondition(); |
638 | 637 |
639 Label miss; | 638 Label miss; |
640 ICCompareStub_CheckInputType(masm, lhs, a2, left(), &miss); | 639 CompareICStub_CheckInputType(masm, lhs, a2, left(), &miss); |
641 ICCompareStub_CheckInputType(masm, rhs, a3, right(), &miss); | 640 CompareICStub_CheckInputType(masm, rhs, a3, right(), &miss); |
642 | 641 |
643 Label slow; // Call builtin. | 642 Label slow; // Call builtin. |
644 Label not_smis, both_loaded_as_doubles; | 643 Label not_smis, both_loaded_as_doubles; |
645 | 644 |
646 Label not_two_smis, smi_done; | 645 Label not_two_smis, smi_done; |
647 __ Or(a2, a1, a0); | 646 __ Or(a2, a1, a0); |
648 __ JumpIfNotSmi(a2, ¬_two_smis); | 647 __ JumpIfNotSmi(a2, ¬_two_smis); |
649 __ sra(a1, a1, 1); | 648 __ sra(a1, a1, 1); |
650 __ sra(a0, a0, 1); | 649 __ sra(a0, a0, 1); |
651 __ Ret(USE_DELAY_SLOT); | 650 __ Ret(USE_DELAY_SLOT); |
(...skipping 2863 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3515 __ Assert(eq, kExpectedAllocationSite, t0, Operand(at)); | 3514 __ Assert(eq, kExpectedAllocationSite, t0, Operand(at)); |
3516 } | 3515 } |
3517 | 3516 |
3518 // Tail call into the stub that handles binary operations with allocation | 3517 // Tail call into the stub that handles binary operations with allocation |
3519 // sites. | 3518 // sites. |
3520 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3519 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
3521 __ TailCallStub(&stub); | 3520 __ TailCallStub(&stub); |
3522 } | 3521 } |
3523 | 3522 |
3524 | 3523 |
3525 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3524 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
3526 DCHECK(state() == CompareIC::SMI); | 3525 DCHECK(state() == CompareIC::SMI); |
3527 Label miss; | 3526 Label miss; |
3528 __ Or(a2, a1, a0); | 3527 __ Or(a2, a1, a0); |
3529 __ JumpIfNotSmi(a2, &miss); | 3528 __ JumpIfNotSmi(a2, &miss); |
3530 | 3529 |
3531 if (GetCondition() == eq) { | 3530 if (GetCondition() == eq) { |
3532 // For equality we do not care about the sign of the result. | 3531 // For equality we do not care about the sign of the result. |
3533 __ Ret(USE_DELAY_SLOT); | 3532 __ Ret(USE_DELAY_SLOT); |
3534 __ Subu(v0, a0, a1); | 3533 __ Subu(v0, a0, a1); |
3535 } else { | 3534 } else { |
3536 // Untag before subtracting to avoid handling overflow. | 3535 // Untag before subtracting to avoid handling overflow. |
3537 __ SmiUntag(a1); | 3536 __ SmiUntag(a1); |
3538 __ SmiUntag(a0); | 3537 __ SmiUntag(a0); |
3539 __ Ret(USE_DELAY_SLOT); | 3538 __ Ret(USE_DELAY_SLOT); |
3540 __ Subu(v0, a1, a0); | 3539 __ Subu(v0, a1, a0); |
3541 } | 3540 } |
3542 | 3541 |
3543 __ bind(&miss); | 3542 __ bind(&miss); |
3544 GenerateMiss(masm); | 3543 GenerateMiss(masm); |
3545 } | 3544 } |
3546 | 3545 |
3547 | 3546 |
3548 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { | 3547 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
3549 DCHECK(state() == CompareIC::NUMBER); | 3548 DCHECK(state() == CompareIC::NUMBER); |
3550 | 3549 |
3551 Label generic_stub; | 3550 Label generic_stub; |
3552 Label unordered, maybe_undefined1, maybe_undefined2; | 3551 Label unordered, maybe_undefined1, maybe_undefined2; |
3553 Label miss; | 3552 Label miss; |
3554 | 3553 |
3555 if (left() == CompareIC::SMI) { | 3554 if (left() == CompareIC::SMI) { |
3556 __ JumpIfNotSmi(a1, &miss); | 3555 __ JumpIfNotSmi(a1, &miss); |
3557 } | 3556 } |
3558 if (right() == CompareIC::SMI) { | 3557 if (right() == CompareIC::SMI) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3606 __ bind(&fpu_eq); | 3605 __ bind(&fpu_eq); |
3607 __ Ret(USE_DELAY_SLOT); | 3606 __ Ret(USE_DELAY_SLOT); |
3608 __ li(v0, Operand(EQUAL)); | 3607 __ li(v0, Operand(EQUAL)); |
3609 | 3608 |
3610 __ bind(&fpu_lt); | 3609 __ bind(&fpu_lt); |
3611 __ Ret(USE_DELAY_SLOT); | 3610 __ Ret(USE_DELAY_SLOT); |
3612 __ li(v0, Operand(LESS)); | 3611 __ li(v0, Operand(LESS)); |
3613 | 3612 |
3614 __ bind(&unordered); | 3613 __ bind(&unordered); |
3615 __ bind(&generic_stub); | 3614 __ bind(&generic_stub); |
3616 ICCompareStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3615 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, |
3617 CompareIC::GENERIC); | 3616 CompareIC::GENERIC); |
3618 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 3617 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
3619 | 3618 |
3620 __ bind(&maybe_undefined1); | 3619 __ bind(&maybe_undefined1); |
3621 if (Token::IsOrderedRelationalCompareOp(op())) { | 3620 if (Token::IsOrderedRelationalCompareOp(op())) { |
3622 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 3621 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
3623 __ Branch(&miss, ne, a0, Operand(at)); | 3622 __ Branch(&miss, ne, a0, Operand(at)); |
3624 __ JumpIfSmi(a1, &unordered); | 3623 __ JumpIfSmi(a1, &unordered); |
3625 __ GetObjectType(a1, a2, a2); | 3624 __ GetObjectType(a1, a2, a2); |
3626 __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE)); | 3625 __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE)); |
3627 __ jmp(&unordered); | 3626 __ jmp(&unordered); |
3628 } | 3627 } |
3629 | 3628 |
3630 __ bind(&maybe_undefined2); | 3629 __ bind(&maybe_undefined2); |
3631 if (Token::IsOrderedRelationalCompareOp(op())) { | 3630 if (Token::IsOrderedRelationalCompareOp(op())) { |
3632 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 3631 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
3633 __ Branch(&unordered, eq, a1, Operand(at)); | 3632 __ Branch(&unordered, eq, a1, Operand(at)); |
3634 } | 3633 } |
3635 | 3634 |
3636 __ bind(&miss); | 3635 __ bind(&miss); |
3637 GenerateMiss(masm); | 3636 GenerateMiss(masm); |
3638 } | 3637 } |
3639 | 3638 |
3640 | 3639 |
3641 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3640 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3642 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3641 DCHECK(state() == CompareIC::INTERNALIZED_STRING); |
3643 Label miss; | 3642 Label miss; |
3644 | 3643 |
3645 // Registers containing left and right operands respectively. | 3644 // Registers containing left and right operands respectively. |
3646 Register left = a1; | 3645 Register left = a1; |
3647 Register right = a0; | 3646 Register right = a0; |
3648 Register tmp1 = a2; | 3647 Register tmp1 = a2; |
3649 Register tmp2 = a3; | 3648 Register tmp2 = a3; |
3650 | 3649 |
3651 // Check that both operands are heap objects. | 3650 // Check that both operands are heap objects. |
(...skipping 19 matching lines...) Expand all Loading... |
3671 __ Ret(ne, left, Operand(right)); | 3670 __ Ret(ne, left, Operand(right)); |
3672 DCHECK(is_int16(EQUAL)); | 3671 DCHECK(is_int16(EQUAL)); |
3673 __ Ret(USE_DELAY_SLOT); | 3672 __ Ret(USE_DELAY_SLOT); |
3674 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3673 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3675 | 3674 |
3676 __ bind(&miss); | 3675 __ bind(&miss); |
3677 GenerateMiss(masm); | 3676 GenerateMiss(masm); |
3678 } | 3677 } |
3679 | 3678 |
3680 | 3679 |
3681 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { | 3680 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
3682 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3681 DCHECK(state() == CompareIC::UNIQUE_NAME); |
3683 DCHECK(GetCondition() == eq); | 3682 DCHECK(GetCondition() == eq); |
3684 Label miss; | 3683 Label miss; |
3685 | 3684 |
3686 // Registers containing left and right operands respectively. | 3685 // Registers containing left and right operands respectively. |
3687 Register left = a1; | 3686 Register left = a1; |
3688 Register right = a0; | 3687 Register right = a0; |
3689 Register tmp1 = a2; | 3688 Register tmp1 = a2; |
3690 Register tmp2 = a3; | 3689 Register tmp2 = a3; |
3691 | 3690 |
(...skipping 23 matching lines...) Expand all Loading... |
3715 STATIC_ASSERT(kSmiTag == 0); | 3714 STATIC_ASSERT(kSmiTag == 0); |
3716 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3715 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3717 __ bind(&done); | 3716 __ bind(&done); |
3718 __ Ret(); | 3717 __ Ret(); |
3719 | 3718 |
3720 __ bind(&miss); | 3719 __ bind(&miss); |
3721 GenerateMiss(masm); | 3720 GenerateMiss(masm); |
3722 } | 3721 } |
3723 | 3722 |
3724 | 3723 |
3725 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 3724 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
3726 DCHECK(state() == CompareIC::STRING); | 3725 DCHECK(state() == CompareIC::STRING); |
3727 Label miss; | 3726 Label miss; |
3728 | 3727 |
3729 bool equality = Token::IsEqualityOp(op()); | 3728 bool equality = Token::IsEqualityOp(op()); |
3730 | 3729 |
3731 // Registers containing left and right operands respectively. | 3730 // Registers containing left and right operands respectively. |
3732 Register left = a1; | 3731 Register left = a1; |
3733 Register right = a0; | 3732 Register right = a0; |
3734 Register tmp1 = a2; | 3733 Register tmp1 = a2; |
3735 Register tmp2 = a3; | 3734 Register tmp2 = a3; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3801 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 3800 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); |
3802 } else { | 3801 } else { |
3803 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3802 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3804 } | 3803 } |
3805 | 3804 |
3806 __ bind(&miss); | 3805 __ bind(&miss); |
3807 GenerateMiss(masm); | 3806 GenerateMiss(masm); |
3808 } | 3807 } |
3809 | 3808 |
3810 | 3809 |
3811 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 3810 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
3812 DCHECK(state() == CompareIC::OBJECT); | 3811 DCHECK(state() == CompareIC::OBJECT); |
3813 Label miss; | 3812 Label miss; |
3814 __ And(a2, a1, Operand(a0)); | 3813 __ And(a2, a1, Operand(a0)); |
3815 __ JumpIfSmi(a2, &miss); | 3814 __ JumpIfSmi(a2, &miss); |
3816 | 3815 |
3817 __ GetObjectType(a0, a2, a2); | 3816 __ GetObjectType(a0, a2, a2); |
3818 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); | 3817 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); |
3819 __ GetObjectType(a1, a2, a2); | 3818 __ GetObjectType(a1, a2, a2); |
3820 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); | 3819 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); |
3821 | 3820 |
3822 DCHECK(GetCondition() == eq); | 3821 DCHECK(GetCondition() == eq); |
3823 __ Ret(USE_DELAY_SLOT); | 3822 __ Ret(USE_DELAY_SLOT); |
3824 __ subu(v0, a0, a1); | 3823 __ subu(v0, a0, a1); |
3825 | 3824 |
3826 __ bind(&miss); | 3825 __ bind(&miss); |
3827 GenerateMiss(masm); | 3826 GenerateMiss(masm); |
3828 } | 3827 } |
3829 | 3828 |
3830 | 3829 |
3831 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { | 3830 void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { |
3832 Label miss; | 3831 Label miss; |
3833 __ And(a2, a1, a0); | 3832 __ And(a2, a1, a0); |
3834 __ JumpIfSmi(a2, &miss); | 3833 __ JumpIfSmi(a2, &miss); |
3835 __ lw(a2, FieldMemOperand(a0, HeapObject::kMapOffset)); | 3834 __ lw(a2, FieldMemOperand(a0, HeapObject::kMapOffset)); |
3836 __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset)); | 3835 __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset)); |
3837 __ Branch(&miss, ne, a2, Operand(known_map_)); | 3836 __ Branch(&miss, ne, a2, Operand(known_map_)); |
3838 __ Branch(&miss, ne, a3, Operand(known_map_)); | 3837 __ Branch(&miss, ne, a3, Operand(known_map_)); |
3839 | 3838 |
3840 __ Ret(USE_DELAY_SLOT); | 3839 __ Ret(USE_DELAY_SLOT); |
3841 __ subu(v0, a0, a1); | 3840 __ subu(v0, a0, a1); |
3842 | 3841 |
3843 __ bind(&miss); | 3842 __ bind(&miss); |
3844 GenerateMiss(masm); | 3843 GenerateMiss(masm); |
3845 } | 3844 } |
3846 | 3845 |
3847 | 3846 |
3848 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | 3847 void CompareICStub::GenerateMiss(MacroAssembler* masm) { |
3849 { | 3848 { |
3850 // Call the runtime system in a fresh internal frame. | 3849 // Call the runtime system in a fresh internal frame. |
3851 ExternalReference miss = | 3850 ExternalReference miss = |
3852 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); | 3851 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); |
3853 FrameScope scope(masm, StackFrame::INTERNAL); | 3852 FrameScope scope(masm, StackFrame::INTERNAL); |
3854 __ Push(a1, a0); | 3853 __ Push(a1, a0); |
3855 __ Push(ra, a1, a0); | 3854 __ Push(ra, a1, a0); |
3856 __ li(t0, Operand(Smi::FromInt(op()))); | 3855 __ li(t0, Operand(Smi::FromInt(op()))); |
3857 __ addiu(sp, sp, -kPointerSize); | 3856 __ addiu(sp, sp, -kPointerSize); |
3858 __ CallExternalReference(miss, 3, USE_DELAY_SLOT); | 3857 __ CallExternalReference(miss, 3, USE_DELAY_SLOT); |
(...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4939 MemOperand(fp, 6 * kPointerSize), | 4938 MemOperand(fp, 6 * kPointerSize), |
4940 NULL); | 4939 NULL); |
4941 } | 4940 } |
4942 | 4941 |
4943 | 4942 |
4944 #undef __ | 4943 #undef __ |
4945 | 4944 |
4946 } } // namespace v8::internal | 4945 } } // namespace v8::internal |
4947 | 4946 |
4948 #endif // V8_TARGET_ARCH_MIPS | 4947 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |