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_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
11 #include "src/codegen.h" | 11 #include "src/codegen.h" |
12 #include "src/ic/handler-compiler.h" | 12 #include "src/ic/handler-compiler.h" |
| 13 #include "src/ic/ic.h" |
13 #include "src/isolate.h" | 14 #include "src/isolate.h" |
14 #include "src/jsregexp.h" | 15 #include "src/jsregexp.h" |
15 #include "src/regexp-macro-assembler.h" | 16 #include "src/regexp-macro-assembler.h" |
16 #include "src/runtime.h" | 17 #include "src/runtime.h" |
17 | 18 |
18 namespace v8 { | 19 namespace v8 { |
19 namespace internal { | 20 namespace internal { |
20 | 21 |
21 | 22 |
22 static void InitializeArrayConstructorDescriptor( | 23 static void InitializeArrayConstructorDescriptor( |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 __ lbu(a3, FieldMemOperand(a3, Map::kBitFieldOffset)); | 585 __ lbu(a3, FieldMemOperand(a3, Map::kBitFieldOffset)); |
585 __ and_(a0, a2, a3); | 586 __ and_(a0, a2, a3); |
586 __ And(a0, a0, Operand(1 << Map::kIsUndetectable)); | 587 __ And(a0, a0, Operand(1 << Map::kIsUndetectable)); |
587 __ Ret(USE_DELAY_SLOT); | 588 __ Ret(USE_DELAY_SLOT); |
588 __ xori(v0, a0, 1 << Map::kIsUndetectable); | 589 __ xori(v0, a0, 1 << Map::kIsUndetectable); |
589 } | 590 } |
590 | 591 |
591 | 592 |
592 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, | 593 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, |
593 Register scratch, | 594 Register scratch, |
594 CompareIC::State expected, | 595 CompareICState::State expected, |
595 Label* fail) { | 596 Label* fail) { |
596 Label ok; | 597 Label ok; |
597 if (expected == CompareIC::SMI) { | 598 if (expected == CompareICState::SMI) { |
598 __ JumpIfNotSmi(input, fail); | 599 __ JumpIfNotSmi(input, fail); |
599 } else if (expected == CompareIC::NUMBER) { | 600 } else if (expected == CompareICState::NUMBER) { |
600 __ JumpIfSmi(input, &ok); | 601 __ JumpIfSmi(input, &ok); |
601 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, | 602 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, |
602 DONT_DO_SMI_CHECK); | 603 DONT_DO_SMI_CHECK); |
603 } | 604 } |
604 // We could be strict about internalized/string here, but as long as | 605 // We could be strict about internalized/string here, but as long as |
605 // hydrogen doesn't care, the stub doesn't have to care either. | 606 // hydrogen doesn't care, the stub doesn't have to care either. |
606 __ bind(&ok); | 607 __ bind(&ok); |
607 } | 608 } |
608 | 609 |
609 | 610 |
(...skipping 2204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2814 // Verify that a4 contains an AllocationSite | 2815 // Verify that a4 contains an AllocationSite |
2815 __ ld(a5, FieldMemOperand(a4, HeapObject::kMapOffset)); | 2816 __ ld(a5, FieldMemOperand(a4, HeapObject::kMapOffset)); |
2816 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); | 2817 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); |
2817 __ Branch(&miss, ne, a5, Operand(at)); | 2818 __ Branch(&miss, ne, a5, Operand(at)); |
2818 | 2819 |
2819 __ mov(a2, a4); | 2820 __ mov(a2, a4); |
2820 ArrayConstructorStub stub(masm->isolate(), arg_count()); | 2821 ArrayConstructorStub stub(masm->isolate(), arg_count()); |
2821 __ TailCallStub(&stub); | 2822 __ TailCallStub(&stub); |
2822 | 2823 |
2823 __ bind(&miss); | 2824 __ bind(&miss); |
2824 GenerateMiss(masm, IC::kCallIC_Customization_Miss); | 2825 GenerateMiss(masm); |
2825 | 2826 |
2826 // The slow case, we need this no matter what to complete a call after a miss. | 2827 // The slow case, we need this no matter what to complete a call after a miss. |
2827 CallFunctionNoFeedback(masm, | 2828 CallFunctionNoFeedback(masm, |
2828 arg_count(), | 2829 arg_count(), |
2829 true, | 2830 true, |
2830 CallAsMethod()); | 2831 CallAsMethod()); |
2831 | 2832 |
2832 // Unreachable. | 2833 // Unreachable. |
2833 __ stop("Unexpected code address"); | 2834 __ stop("Unexpected code address"); |
2834 } | 2835 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2890 __ Branch(&miss, ne, a5, Operand(JS_FUNCTION_TYPE)); | 2891 __ Branch(&miss, ne, a5, Operand(JS_FUNCTION_TYPE)); |
2891 __ dsrl(a4, a3, 32 - kPointerSizeLog2); | 2892 __ dsrl(a4, a3, 32 - kPointerSizeLog2); |
2892 __ Daddu(a4, a2, Operand(a4)); | 2893 __ Daddu(a4, a2, Operand(a4)); |
2893 __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex); | 2894 __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex); |
2894 __ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize)); | 2895 __ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize)); |
2895 __ Branch(&slow_start); | 2896 __ Branch(&slow_start); |
2896 } | 2897 } |
2897 | 2898 |
2898 // We are here because tracing is on or we are going monomorphic. | 2899 // We are here because tracing is on or we are going monomorphic. |
2899 __ bind(&miss); | 2900 __ bind(&miss); |
2900 GenerateMiss(masm, IC::kCallIC_Miss); | 2901 GenerateMiss(masm); |
2901 | 2902 |
2902 // the slow case | 2903 // the slow case |
2903 __ bind(&slow_start); | 2904 __ bind(&slow_start); |
2904 // Check that the function is really a JavaScript function. | 2905 // Check that the function is really a JavaScript function. |
2905 // r1: pushed function (to be verified) | 2906 // r1: pushed function (to be verified) |
2906 __ JumpIfSmi(a1, &non_function); | 2907 __ JumpIfSmi(a1, &non_function); |
2907 | 2908 |
2908 // Goto slow case if we do not have a function. | 2909 // Goto slow case if we do not have a function. |
2909 __ GetObjectType(a1, a4, a4); | 2910 __ GetObjectType(a1, a4, a4); |
2910 __ Branch(&slow, ne, a4, Operand(JS_FUNCTION_TYPE)); | 2911 __ Branch(&slow, ne, a4, Operand(JS_FUNCTION_TYPE)); |
2911 __ Branch(&have_js_function); | 2912 __ Branch(&have_js_function); |
2912 } | 2913 } |
2913 | 2914 |
2914 | 2915 |
2915 void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) { | 2916 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
2916 // Get the receiver of the function from the stack; 1 ~ return address. | 2917 // Get the receiver of the function from the stack; 1 ~ return address. |
2917 __ ld(a4, MemOperand(sp, (arg_count() + 1) * kPointerSize)); | 2918 __ ld(a4, MemOperand(sp, (arg_count() + 1) * kPointerSize)); |
2918 | 2919 |
2919 { | 2920 { |
2920 FrameScope scope(masm, StackFrame::INTERNAL); | 2921 FrameScope scope(masm, StackFrame::INTERNAL); |
2921 | 2922 |
2922 // Push the receiver and the function and feedback info. | 2923 // Push the receiver and the function and feedback info. |
2923 __ Push(a4, a1, a2, a3); | 2924 __ Push(a4, a1, a2, a3); |
2924 | 2925 |
2925 // Call the entry. | 2926 // Call the entry. |
| 2927 IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss |
| 2928 : IC::kCallIC_Customization_Miss; |
| 2929 |
2926 ExternalReference miss = ExternalReference(IC_Utility(id), | 2930 ExternalReference miss = ExternalReference(IC_Utility(id), |
2927 masm->isolate()); | 2931 masm->isolate()); |
2928 __ CallExternalReference(miss, 4); | 2932 __ CallExternalReference(miss, 4); |
2929 | 2933 |
2930 // Move result to a1 and exit the internal frame. | 2934 // Move result to a1 and exit the internal frame. |
2931 __ mov(a1, v0); | 2935 __ mov(a1, v0); |
2932 } | 2936 } |
2933 } | 2937 } |
2934 | 2938 |
2935 | 2939 |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3468 } | 3472 } |
3469 | 3473 |
3470 // Tail call into the stub that handles binary operations with allocation | 3474 // Tail call into the stub that handles binary operations with allocation |
3471 // sites. | 3475 // sites. |
3472 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3476 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
3473 __ TailCallStub(&stub); | 3477 __ TailCallStub(&stub); |
3474 } | 3478 } |
3475 | 3479 |
3476 | 3480 |
3477 void CompareICStub::GenerateSmis(MacroAssembler* masm) { | 3481 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
3478 DCHECK(state() == CompareIC::SMI); | 3482 DCHECK(state() == CompareICState::SMI); |
3479 Label miss; | 3483 Label miss; |
3480 __ Or(a2, a1, a0); | 3484 __ Or(a2, a1, a0); |
3481 __ JumpIfNotSmi(a2, &miss); | 3485 __ JumpIfNotSmi(a2, &miss); |
3482 | 3486 |
3483 if (GetCondition() == eq) { | 3487 if (GetCondition() == eq) { |
3484 // For equality we do not care about the sign of the result. | 3488 // For equality we do not care about the sign of the result. |
3485 __ Ret(USE_DELAY_SLOT); | 3489 __ Ret(USE_DELAY_SLOT); |
3486 __ Dsubu(v0, a0, a1); | 3490 __ Dsubu(v0, a0, a1); |
3487 } else { | 3491 } else { |
3488 // Untag before subtracting to avoid handling overflow. | 3492 // Untag before subtracting to avoid handling overflow. |
3489 __ SmiUntag(a1); | 3493 __ SmiUntag(a1); |
3490 __ SmiUntag(a0); | 3494 __ SmiUntag(a0); |
3491 __ Ret(USE_DELAY_SLOT); | 3495 __ Ret(USE_DELAY_SLOT); |
3492 __ Dsubu(v0, a1, a0); | 3496 __ Dsubu(v0, a1, a0); |
3493 } | 3497 } |
3494 | 3498 |
3495 __ bind(&miss); | 3499 __ bind(&miss); |
3496 GenerateMiss(masm); | 3500 GenerateMiss(masm); |
3497 } | 3501 } |
3498 | 3502 |
3499 | 3503 |
3500 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { | 3504 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
3501 DCHECK(state() == CompareIC::NUMBER); | 3505 DCHECK(state() == CompareICState::NUMBER); |
3502 | 3506 |
3503 Label generic_stub; | 3507 Label generic_stub; |
3504 Label unordered, maybe_undefined1, maybe_undefined2; | 3508 Label unordered, maybe_undefined1, maybe_undefined2; |
3505 Label miss; | 3509 Label miss; |
3506 | 3510 |
3507 if (left() == CompareIC::SMI) { | 3511 if (left() == CompareICState::SMI) { |
3508 __ JumpIfNotSmi(a1, &miss); | 3512 __ JumpIfNotSmi(a1, &miss); |
3509 } | 3513 } |
3510 if (right() == CompareIC::SMI) { | 3514 if (right() == CompareICState::SMI) { |
3511 __ JumpIfNotSmi(a0, &miss); | 3515 __ JumpIfNotSmi(a0, &miss); |
3512 } | 3516 } |
3513 | 3517 |
3514 // Inlining the double comparison and falling back to the general compare | 3518 // Inlining the double comparison and falling back to the general compare |
3515 // stub if NaN is involved. | 3519 // stub if NaN is involved. |
3516 // Load left and right operand. | 3520 // Load left and right operand. |
3517 Label done, left, left_smi, right_smi; | 3521 Label done, left, left_smi, right_smi; |
3518 __ JumpIfSmi(a0, &right_smi); | 3522 __ JumpIfSmi(a0, &right_smi); |
3519 __ CheckMap(a0, a2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, | 3523 __ CheckMap(a0, a2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, |
3520 DONT_DO_SMI_CHECK); | 3524 DONT_DO_SMI_CHECK); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3558 __ bind(&fpu_eq); | 3562 __ bind(&fpu_eq); |
3559 __ Ret(USE_DELAY_SLOT); | 3563 __ Ret(USE_DELAY_SLOT); |
3560 __ li(v0, Operand(EQUAL)); | 3564 __ li(v0, Operand(EQUAL)); |
3561 | 3565 |
3562 __ bind(&fpu_lt); | 3566 __ bind(&fpu_lt); |
3563 __ Ret(USE_DELAY_SLOT); | 3567 __ Ret(USE_DELAY_SLOT); |
3564 __ li(v0, Operand(LESS)); | 3568 __ li(v0, Operand(LESS)); |
3565 | 3569 |
3566 __ bind(&unordered); | 3570 __ bind(&unordered); |
3567 __ bind(&generic_stub); | 3571 __ bind(&generic_stub); |
3568 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3572 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
3569 CompareIC::GENERIC); | 3573 CompareICState::GENERIC, CompareICState::GENERIC); |
3570 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 3574 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
3571 | 3575 |
3572 __ bind(&maybe_undefined1); | 3576 __ bind(&maybe_undefined1); |
3573 if (Token::IsOrderedRelationalCompareOp(op())) { | 3577 if (Token::IsOrderedRelationalCompareOp(op())) { |
3574 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 3578 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
3575 __ Branch(&miss, ne, a0, Operand(at)); | 3579 __ Branch(&miss, ne, a0, Operand(at)); |
3576 __ JumpIfSmi(a1, &unordered); | 3580 __ JumpIfSmi(a1, &unordered); |
3577 __ GetObjectType(a1, a2, a2); | 3581 __ GetObjectType(a1, a2, a2); |
3578 __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE)); | 3582 __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE)); |
3579 __ jmp(&unordered); | 3583 __ jmp(&unordered); |
3580 } | 3584 } |
3581 | 3585 |
3582 __ bind(&maybe_undefined2); | 3586 __ bind(&maybe_undefined2); |
3583 if (Token::IsOrderedRelationalCompareOp(op())) { | 3587 if (Token::IsOrderedRelationalCompareOp(op())) { |
3584 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 3588 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
3585 __ Branch(&unordered, eq, a1, Operand(at)); | 3589 __ Branch(&unordered, eq, a1, Operand(at)); |
3586 } | 3590 } |
3587 | 3591 |
3588 __ bind(&miss); | 3592 __ bind(&miss); |
3589 GenerateMiss(masm); | 3593 GenerateMiss(masm); |
3590 } | 3594 } |
3591 | 3595 |
3592 | 3596 |
3593 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3597 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3594 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3598 DCHECK(state() == CompareICState::INTERNALIZED_STRING); |
3595 Label miss; | 3599 Label miss; |
3596 | 3600 |
3597 // Registers containing left and right operands respectively. | 3601 // Registers containing left and right operands respectively. |
3598 Register left = a1; | 3602 Register left = a1; |
3599 Register right = a0; | 3603 Register right = a0; |
3600 Register tmp1 = a2; | 3604 Register tmp1 = a2; |
3601 Register tmp2 = a3; | 3605 Register tmp2 = a3; |
3602 | 3606 |
3603 // Check that both operands are heap objects. | 3607 // Check that both operands are heap objects. |
3604 __ JumpIfEitherSmi(left, right, &miss); | 3608 __ JumpIfEitherSmi(left, right, &miss); |
(...skipping 19 matching lines...) Expand all Loading... |
3624 DCHECK(is_int16(EQUAL)); | 3628 DCHECK(is_int16(EQUAL)); |
3625 __ Ret(USE_DELAY_SLOT); | 3629 __ Ret(USE_DELAY_SLOT); |
3626 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3630 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3627 | 3631 |
3628 __ bind(&miss); | 3632 __ bind(&miss); |
3629 GenerateMiss(masm); | 3633 GenerateMiss(masm); |
3630 } | 3634 } |
3631 | 3635 |
3632 | 3636 |
3633 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { | 3637 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
3634 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3638 DCHECK(state() == CompareICState::UNIQUE_NAME); |
3635 DCHECK(GetCondition() == eq); | 3639 DCHECK(GetCondition() == eq); |
3636 Label miss; | 3640 Label miss; |
3637 | 3641 |
3638 // Registers containing left and right operands respectively. | 3642 // Registers containing left and right operands respectively. |
3639 Register left = a1; | 3643 Register left = a1; |
3640 Register right = a0; | 3644 Register right = a0; |
3641 Register tmp1 = a2; | 3645 Register tmp1 = a2; |
3642 Register tmp2 = a3; | 3646 Register tmp2 = a3; |
3643 | 3647 |
3644 // Check that both operands are heap objects. | 3648 // Check that both operands are heap objects. |
(...skipping 23 matching lines...) Expand all Loading... |
3668 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3672 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3669 __ bind(&done); | 3673 __ bind(&done); |
3670 __ Ret(); | 3674 __ Ret(); |
3671 | 3675 |
3672 __ bind(&miss); | 3676 __ bind(&miss); |
3673 GenerateMiss(masm); | 3677 GenerateMiss(masm); |
3674 } | 3678 } |
3675 | 3679 |
3676 | 3680 |
3677 void CompareICStub::GenerateStrings(MacroAssembler* masm) { | 3681 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
3678 DCHECK(state() == CompareIC::STRING); | 3682 DCHECK(state() == CompareICState::STRING); |
3679 Label miss; | 3683 Label miss; |
3680 | 3684 |
3681 bool equality = Token::IsEqualityOp(op()); | 3685 bool equality = Token::IsEqualityOp(op()); |
3682 | 3686 |
3683 // Registers containing left and right operands respectively. | 3687 // Registers containing left and right operands respectively. |
3684 Register left = a1; | 3688 Register left = a1; |
3685 Register right = a0; | 3689 Register right = a0; |
3686 Register tmp1 = a2; | 3690 Register tmp1 = a2; |
3687 Register tmp2 = a3; | 3691 Register tmp2 = a3; |
3688 Register tmp3 = a4; | 3692 Register tmp3 = a4; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3754 } else { | 3758 } else { |
3755 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3759 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3756 } | 3760 } |
3757 | 3761 |
3758 __ bind(&miss); | 3762 __ bind(&miss); |
3759 GenerateMiss(masm); | 3763 GenerateMiss(masm); |
3760 } | 3764 } |
3761 | 3765 |
3762 | 3766 |
3763 void CompareICStub::GenerateObjects(MacroAssembler* masm) { | 3767 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
3764 DCHECK(state() == CompareIC::OBJECT); | 3768 DCHECK(state() == CompareICState::OBJECT); |
3765 Label miss; | 3769 Label miss; |
3766 __ And(a2, a1, Operand(a0)); | 3770 __ And(a2, a1, Operand(a0)); |
3767 __ JumpIfSmi(a2, &miss); | 3771 __ JumpIfSmi(a2, &miss); |
3768 | 3772 |
3769 __ GetObjectType(a0, a2, a2); | 3773 __ GetObjectType(a0, a2, a2); |
3770 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); | 3774 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); |
3771 __ GetObjectType(a1, a2, a2); | 3775 __ GetObjectType(a1, a2, a2); |
3772 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); | 3776 __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); |
3773 | 3777 |
3774 DCHECK(GetCondition() == eq); | 3778 DCHECK(GetCondition() == eq); |
(...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4893 MemOperand(fp, 6 * kPointerSize), | 4897 MemOperand(fp, 6 * kPointerSize), |
4894 NULL); | 4898 NULL); |
4895 } | 4899 } |
4896 | 4900 |
4897 | 4901 |
4898 #undef __ | 4902 #undef __ |
4899 | 4903 |
4900 } } // namespace v8::internal | 4904 } } // namespace v8::internal |
4901 | 4905 |
4902 #endif // V8_TARGET_ARCH_MIPS64 | 4906 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |