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" |
11 #include "src/code-stubs.h" | 11 #include "src/code-stubs.h" |
12 #include "src/codegen.h" | 12 #include "src/codegen.h" |
13 #include "src/ic/handler-compiler.h" | 13 #include "src/ic/handler-compiler.h" |
| 14 #include "src/ic/ic.h" |
14 #include "src/isolate.h" | 15 #include "src/isolate.h" |
15 #include "src/jsregexp.h" | 16 #include "src/jsregexp.h" |
16 #include "src/regexp-macro-assembler.h" | 17 #include "src/regexp-macro-assembler.h" |
17 #include "src/runtime.h" | 18 #include "src/runtime.h" |
18 | 19 |
19 namespace v8 { | 20 namespace v8 { |
20 namespace internal { | 21 namespace internal { |
21 | 22 |
22 | 23 |
23 static void InitializeArrayConstructorDescriptor( | 24 static void InitializeArrayConstructorDescriptor( |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 __ lbu(a3, FieldMemOperand(a3, Map::kBitFieldOffset)); | 591 __ lbu(a3, FieldMemOperand(a3, Map::kBitFieldOffset)); |
591 __ and_(a0, a2, a3); | 592 __ and_(a0, a2, a3); |
592 __ And(a0, a0, Operand(1 << Map::kIsUndetectable)); | 593 __ And(a0, a0, Operand(1 << Map::kIsUndetectable)); |
593 __ Ret(USE_DELAY_SLOT); | 594 __ Ret(USE_DELAY_SLOT); |
594 __ xori(v0, a0, 1 << Map::kIsUndetectable); | 595 __ xori(v0, a0, 1 << Map::kIsUndetectable); |
595 } | 596 } |
596 | 597 |
597 | 598 |
598 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, | 599 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, |
599 Register scratch, | 600 Register scratch, |
600 CompareIC::State expected, | 601 CompareICState::State expected, |
601 Label* fail) { | 602 Label* fail) { |
602 Label ok; | 603 Label ok; |
603 if (expected == CompareIC::SMI) { | 604 if (expected == CompareICState::SMI) { |
604 __ JumpIfNotSmi(input, fail); | 605 __ JumpIfNotSmi(input, fail); |
605 } else if (expected == CompareIC::NUMBER) { | 606 } else if (expected == CompareICState::NUMBER) { |
606 __ JumpIfSmi(input, &ok); | 607 __ JumpIfSmi(input, &ok); |
607 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, | 608 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, |
608 DONT_DO_SMI_CHECK); | 609 DONT_DO_SMI_CHECK); |
609 } | 610 } |
610 // We could be strict about internalized/string here, but as long as | 611 // We could be strict about internalized/string here, but as long as |
611 // hydrogen doesn't care, the stub doesn't have to care either. | 612 // hydrogen doesn't care, the stub doesn't have to care either. |
612 __ bind(&ok); | 613 __ bind(&ok); |
613 } | 614 } |
614 | 615 |
615 | 616 |
(...skipping 2126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2742 // Verify that t0 contains an AllocationSite | 2743 // Verify that t0 contains an AllocationSite |
2743 __ lw(t1, FieldMemOperand(t0, HeapObject::kMapOffset)); | 2744 __ lw(t1, FieldMemOperand(t0, HeapObject::kMapOffset)); |
2744 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); | 2745 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); |
2745 __ Branch(&miss, ne, t1, Operand(at)); | 2746 __ Branch(&miss, ne, t1, Operand(at)); |
2746 | 2747 |
2747 __ mov(a2, t0); | 2748 __ mov(a2, t0); |
2748 ArrayConstructorStub stub(masm->isolate(), arg_count()); | 2749 ArrayConstructorStub stub(masm->isolate(), arg_count()); |
2749 __ TailCallStub(&stub); | 2750 __ TailCallStub(&stub); |
2750 | 2751 |
2751 __ bind(&miss); | 2752 __ bind(&miss); |
2752 GenerateMiss(masm, IC::kCallIC_Customization_Miss); | 2753 GenerateMiss(masm); |
2753 | 2754 |
2754 // The slow case, we need this no matter what to complete a call after a miss. | 2755 // The slow case, we need this no matter what to complete a call after a miss. |
2755 CallFunctionNoFeedback(masm, | 2756 CallFunctionNoFeedback(masm, |
2756 arg_count(), | 2757 arg_count(), |
2757 true, | 2758 true, |
2758 CallAsMethod()); | 2759 CallAsMethod()); |
2759 | 2760 |
2760 // Unreachable. | 2761 // Unreachable. |
2761 __ stop("Unexpected code address"); | 2762 __ stop("Unexpected code address"); |
2762 } | 2763 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2818 __ Branch(&miss, ne, t1, Operand(JS_FUNCTION_TYPE)); | 2819 __ Branch(&miss, ne, t1, Operand(JS_FUNCTION_TYPE)); |
2819 __ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize); | 2820 __ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize); |
2820 __ Addu(t0, a2, Operand(t0)); | 2821 __ Addu(t0, a2, Operand(t0)); |
2821 __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex); | 2822 __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex); |
2822 __ sw(at, FieldMemOperand(t0, FixedArray::kHeaderSize)); | 2823 __ sw(at, FieldMemOperand(t0, FixedArray::kHeaderSize)); |
2823 __ Branch(&slow_start); | 2824 __ Branch(&slow_start); |
2824 } | 2825 } |
2825 | 2826 |
2826 // We are here because tracing is on or we are going monomorphic. | 2827 // We are here because tracing is on or we are going monomorphic. |
2827 __ bind(&miss); | 2828 __ bind(&miss); |
2828 GenerateMiss(masm, IC::kCallIC_Miss); | 2829 GenerateMiss(masm); |
2829 | 2830 |
2830 // the slow case | 2831 // the slow case |
2831 __ bind(&slow_start); | 2832 __ bind(&slow_start); |
2832 // Check that the function is really a JavaScript function. | 2833 // Check that the function is really a JavaScript function. |
2833 // r1: pushed function (to be verified) | 2834 // r1: pushed function (to be verified) |
2834 __ JumpIfSmi(a1, &non_function); | 2835 __ JumpIfSmi(a1, &non_function); |
2835 | 2836 |
2836 // Goto slow case if we do not have a function. | 2837 // Goto slow case if we do not have a function. |
2837 __ GetObjectType(a1, t0, t0); | 2838 __ GetObjectType(a1, t0, t0); |
2838 __ Branch(&slow, ne, t0, Operand(JS_FUNCTION_TYPE)); | 2839 __ Branch(&slow, ne, t0, Operand(JS_FUNCTION_TYPE)); |
2839 __ Branch(&have_js_function); | 2840 __ Branch(&have_js_function); |
2840 } | 2841 } |
2841 | 2842 |
2842 | 2843 |
2843 void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) { | 2844 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
2844 // Get the receiver of the function from the stack; 1 ~ return address. | 2845 // Get the receiver of the function from the stack; 1 ~ return address. |
2845 __ lw(t0, MemOperand(sp, (arg_count() + 1) * kPointerSize)); | 2846 __ lw(t0, MemOperand(sp, (arg_count() + 1) * kPointerSize)); |
2846 | 2847 |
2847 { | 2848 { |
2848 FrameScope scope(masm, StackFrame::INTERNAL); | 2849 FrameScope scope(masm, StackFrame::INTERNAL); |
2849 | 2850 |
2850 // Push the receiver and the function and feedback info. | 2851 // Push the receiver and the function and feedback info. |
2851 __ Push(t0, a1, a2, a3); | 2852 __ Push(t0, a1, a2, a3); |
2852 | 2853 |
2853 // Call the entry. | 2854 // Call the entry. |
| 2855 IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss |
| 2856 : IC::kCallIC_Customization_Miss; |
| 2857 |
2854 ExternalReference miss = ExternalReference(IC_Utility(id), | 2858 ExternalReference miss = ExternalReference(IC_Utility(id), |
2855 masm->isolate()); | 2859 masm->isolate()); |
2856 __ CallExternalReference(miss, 4); | 2860 __ CallExternalReference(miss, 4); |
2857 | 2861 |
2858 // Move result to a1 and exit the internal frame. | 2862 // Move result to a1 and exit the internal frame. |
2859 __ mov(a1, v0); | 2863 __ mov(a1, v0); |
2860 } | 2864 } |
2861 } | 2865 } |
2862 | 2866 |
2863 | 2867 |
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3431 } | 3435 } |
3432 | 3436 |
3433 // Tail call into the stub that handles binary operations with allocation | 3437 // Tail call into the stub that handles binary operations with allocation |
3434 // sites. | 3438 // sites. |
3435 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3439 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
3436 __ TailCallStub(&stub); | 3440 __ TailCallStub(&stub); |
3437 } | 3441 } |
3438 | 3442 |
3439 | 3443 |
3440 void CompareICStub::GenerateSmis(MacroAssembler* masm) { | 3444 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
3441 DCHECK(state() == CompareIC::SMI); | 3445 DCHECK(state() == CompareICState::SMI); |
3442 Label miss; | 3446 Label miss; |
3443 __ Or(a2, a1, a0); | 3447 __ Or(a2, a1, a0); |
3444 __ JumpIfNotSmi(a2, &miss); | 3448 __ JumpIfNotSmi(a2, &miss); |
3445 | 3449 |
3446 if (GetCondition() == eq) { | 3450 if (GetCondition() == eq) { |
3447 // For equality we do not care about the sign of the result. | 3451 // For equality we do not care about the sign of the result. |
3448 __ Ret(USE_DELAY_SLOT); | 3452 __ Ret(USE_DELAY_SLOT); |
3449 __ Subu(v0, a0, a1); | 3453 __ Subu(v0, a0, a1); |
3450 } else { | 3454 } else { |
3451 // Untag before subtracting to avoid handling overflow. | 3455 // Untag before subtracting to avoid handling overflow. |
3452 __ SmiUntag(a1); | 3456 __ SmiUntag(a1); |
3453 __ SmiUntag(a0); | 3457 __ SmiUntag(a0); |
3454 __ Ret(USE_DELAY_SLOT); | 3458 __ Ret(USE_DELAY_SLOT); |
3455 __ Subu(v0, a1, a0); | 3459 __ Subu(v0, a1, a0); |
3456 } | 3460 } |
3457 | 3461 |
3458 __ bind(&miss); | 3462 __ bind(&miss); |
3459 GenerateMiss(masm); | 3463 GenerateMiss(masm); |
3460 } | 3464 } |
3461 | 3465 |
3462 | 3466 |
3463 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { | 3467 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
3464 DCHECK(state() == CompareIC::NUMBER); | 3468 DCHECK(state() == CompareICState::NUMBER); |
3465 | 3469 |
3466 Label generic_stub; | 3470 Label generic_stub; |
3467 Label unordered, maybe_undefined1, maybe_undefined2; | 3471 Label unordered, maybe_undefined1, maybe_undefined2; |
3468 Label miss; | 3472 Label miss; |
3469 | 3473 |
3470 if (left() == CompareIC::SMI) { | 3474 if (left() == CompareICState::SMI) { |
3471 __ JumpIfNotSmi(a1, &miss); | 3475 __ JumpIfNotSmi(a1, &miss); |
3472 } | 3476 } |
3473 if (right() == CompareIC::SMI) { | 3477 if (right() == CompareICState::SMI) { |
3474 __ JumpIfNotSmi(a0, &miss); | 3478 __ JumpIfNotSmi(a0, &miss); |
3475 } | 3479 } |
3476 | 3480 |
3477 // Inlining the double comparison and falling back to the general compare | 3481 // Inlining the double comparison and falling back to the general compare |
3478 // stub if NaN is involved. | 3482 // stub if NaN is involved. |
3479 // Load left and right operand. | 3483 // Load left and right operand. |
3480 Label done, left, left_smi, right_smi; | 3484 Label done, left, left_smi, right_smi; |
3481 __ JumpIfSmi(a0, &right_smi); | 3485 __ JumpIfSmi(a0, &right_smi); |
3482 __ CheckMap(a0, a2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, | 3486 __ CheckMap(a0, a2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, |
3483 DONT_DO_SMI_CHECK); | 3487 DONT_DO_SMI_CHECK); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3521 __ bind(&fpu_eq); | 3525 __ bind(&fpu_eq); |
3522 __ Ret(USE_DELAY_SLOT); | 3526 __ Ret(USE_DELAY_SLOT); |
3523 __ li(v0, Operand(EQUAL)); | 3527 __ li(v0, Operand(EQUAL)); |
3524 | 3528 |
3525 __ bind(&fpu_lt); | 3529 __ bind(&fpu_lt); |
3526 __ Ret(USE_DELAY_SLOT); | 3530 __ Ret(USE_DELAY_SLOT); |
3527 __ li(v0, Operand(LESS)); | 3531 __ li(v0, Operand(LESS)); |
3528 | 3532 |
3529 __ bind(&unordered); | 3533 __ bind(&unordered); |
3530 __ bind(&generic_stub); | 3534 __ bind(&generic_stub); |
3531 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3535 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
3532 CompareIC::GENERIC); | 3536 CompareICState::GENERIC, CompareICState::GENERIC); |
3533 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 3537 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
3534 | 3538 |
3535 __ bind(&maybe_undefined1); | 3539 __ bind(&maybe_undefined1); |
3536 if (Token::IsOrderedRelationalCompareOp(op())) { | 3540 if (Token::IsOrderedRelationalCompareOp(op())) { |
3537 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 3541 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
3538 __ Branch(&miss, ne, a0, Operand(at)); | 3542 __ Branch(&miss, ne, a0, Operand(at)); |
3539 __ JumpIfSmi(a1, &unordered); | 3543 __ JumpIfSmi(a1, &unordered); |
3540 __ GetObjectType(a1, a2, a2); | 3544 __ GetObjectType(a1, a2, a2); |
3541 __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE)); | 3545 __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE)); |
3542 __ jmp(&unordered); | 3546 __ jmp(&unordered); |
3543 } | 3547 } |
3544 | 3548 |
3545 __ bind(&maybe_undefined2); | 3549 __ bind(&maybe_undefined2); |
3546 if (Token::IsOrderedRelationalCompareOp(op())) { | 3550 if (Token::IsOrderedRelationalCompareOp(op())) { |
3547 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 3551 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
3548 __ Branch(&unordered, eq, a1, Operand(at)); | 3552 __ Branch(&unordered, eq, a1, Operand(at)); |
3549 } | 3553 } |
3550 | 3554 |
3551 __ bind(&miss); | 3555 __ bind(&miss); |
3552 GenerateMiss(masm); | 3556 GenerateMiss(masm); |
3553 } | 3557 } |
3554 | 3558 |
3555 | 3559 |
3556 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3560 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3557 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3561 DCHECK(state() == CompareICState::INTERNALIZED_STRING); |
3558 Label miss; | 3562 Label miss; |
3559 | 3563 |
3560 // Registers containing left and right operands respectively. | 3564 // Registers containing left and right operands respectively. |
3561 Register left = a1; | 3565 Register left = a1; |
3562 Register right = a0; | 3566 Register right = a0; |
3563 Register tmp1 = a2; | 3567 Register tmp1 = a2; |
3564 Register tmp2 = a3; | 3568 Register tmp2 = a3; |
3565 | 3569 |
3566 // Check that both operands are heap objects. | 3570 // Check that both operands are heap objects. |
3567 __ JumpIfEitherSmi(left, right, &miss); | 3571 __ JumpIfEitherSmi(left, right, &miss); |
(...skipping 19 matching lines...) Expand all Loading... |
3587 DCHECK(is_int16(EQUAL)); | 3591 DCHECK(is_int16(EQUAL)); |
3588 __ Ret(USE_DELAY_SLOT); | 3592 __ Ret(USE_DELAY_SLOT); |
3589 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3593 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3590 | 3594 |
3591 __ bind(&miss); | 3595 __ bind(&miss); |
3592 GenerateMiss(masm); | 3596 GenerateMiss(masm); |
3593 } | 3597 } |
3594 | 3598 |
3595 | 3599 |
3596 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { | 3600 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
3597 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3601 DCHECK(state() == CompareICState::UNIQUE_NAME); |
3598 DCHECK(GetCondition() == eq); | 3602 DCHECK(GetCondition() == eq); |
3599 Label miss; | 3603 Label miss; |
3600 | 3604 |
3601 // Registers containing left and right operands respectively. | 3605 // Registers containing left and right operands respectively. |
3602 Register left = a1; | 3606 Register left = a1; |
3603 Register right = a0; | 3607 Register right = a0; |
3604 Register tmp1 = a2; | 3608 Register tmp1 = a2; |
3605 Register tmp2 = a3; | 3609 Register tmp2 = a3; |
3606 | 3610 |
3607 // Check that both operands are heap objects. | 3611 // Check that both operands are heap objects. |
(...skipping 23 matching lines...) Expand all Loading... |
3631 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3635 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3632 __ bind(&done); | 3636 __ bind(&done); |
3633 __ Ret(); | 3637 __ Ret(); |
3634 | 3638 |
3635 __ bind(&miss); | 3639 __ bind(&miss); |
3636 GenerateMiss(masm); | 3640 GenerateMiss(masm); |
3637 } | 3641 } |
3638 | 3642 |
3639 | 3643 |
3640 void CompareICStub::GenerateStrings(MacroAssembler* masm) { | 3644 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
3641 DCHECK(state() == CompareIC::STRING); | 3645 DCHECK(state() == CompareICState::STRING); |
3642 Label miss; | 3646 Label miss; |
3643 | 3647 |
3644 bool equality = Token::IsEqualityOp(op()); | 3648 bool equality = Token::IsEqualityOp(op()); |
3645 | 3649 |
3646 // Registers containing left and right operands respectively. | 3650 // Registers containing left and right operands respectively. |
3647 Register left = a1; | 3651 Register left = a1; |
3648 Register right = a0; | 3652 Register right = a0; |
3649 Register tmp1 = a2; | 3653 Register tmp1 = a2; |
3650 Register tmp2 = a3; | 3654 Register tmp2 = a3; |
3651 Register tmp3 = t0; | 3655 Register tmp3 = t0; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3717 } else { | 3721 } else { |
3718 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3722 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3719 } | 3723 } |
3720 | 3724 |
3721 __ bind(&miss); | 3725 __ bind(&miss); |
3722 GenerateMiss(masm); | 3726 GenerateMiss(masm); |
3723 } | 3727 } |
3724 | 3728 |
3725 | 3729 |
3726 void CompareICStub::GenerateObjects(MacroAssembler* masm) { | 3730 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
3727 DCHECK(state() == CompareIC::OBJECT); | 3731 DCHECK(state() == CompareICState::OBJECT); |
3728 Label miss; | 3732 Label miss; |
3729 __ And(a2, a1, Operand(a0)); | 3733 __ And(a2, a1, Operand(a0)); |
3730 __ JumpIfSmi(a2, &miss); | 3734 __ JumpIfSmi(a2, &miss); |
3731 | 3735 |
3732 __ GetObjectType(a0, a2, a2); | 3736 __ GetObjectType(a0, a2, a2); |
3733 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); | 3737 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); |
3734 __ GetObjectType(a1, a2, a2); | 3738 __ GetObjectType(a1, a2, a2); |
3735 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); | 3739 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); |
3736 | 3740 |
3737 DCHECK(GetCondition() == eq); | 3741 DCHECK(GetCondition() == eq); |
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4855 MemOperand(fp, 6 * kPointerSize), | 4859 MemOperand(fp, 6 * kPointerSize), |
4856 NULL); | 4860 NULL); |
4857 } | 4861 } |
4858 | 4862 |
4859 | 4863 |
4860 #undef __ | 4864 #undef __ |
4861 | 4865 |
4862 } } // namespace v8::internal | 4866 } } // namespace v8::internal |
4863 | 4867 |
4864 #endif // V8_TARGET_ARCH_MIPS | 4868 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |