| 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 1779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1790 // If length is not zero, "tos_" contains a non-zero value ==> true. | 1790 // If length is not zero, "tos_" contains a non-zero value ==> true. |
| 1791 __ Ret(); | 1791 __ Ret(); |
| 1792 | 1792 |
| 1793 // Return 0 in "tos_" for false. | 1793 // Return 0 in "tos_" for false. |
| 1794 __ bind(&false_result); | 1794 __ bind(&false_result); |
| 1795 __ mov(tos_, zero_reg); | 1795 __ mov(tos_, zero_reg); |
| 1796 __ Ret(); | 1796 __ Ret(); |
| 1797 } | 1797 } |
| 1798 | 1798 |
| 1799 | 1799 |
| 1800 const char* UnaryOpStub::GetName() { | 1800 void UnaryOpStub::PrintName(StringStream* stream) { |
| 1801 if (name_ != NULL) return name_; | |
| 1802 const int kMaxNameLength = 100; | |
| 1803 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( | |
| 1804 kMaxNameLength); | |
| 1805 if (name_ == NULL) return "OOM"; | |
| 1806 const char* op_name = Token::Name(op_); | 1801 const char* op_name = Token::Name(op_); |
| 1807 const char* overwrite_name = NULL; // Make g++ happy. | 1802 const char* overwrite_name = NULL; // Make g++ happy. |
| 1808 switch (mode_) { | 1803 switch (mode_) { |
| 1809 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; | 1804 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; |
| 1810 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; | 1805 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; |
| 1811 } | 1806 } |
| 1812 | 1807 stream->Add("UnaryOpStub_%s_%s_%s", |
| 1813 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 1808 op_name, |
| 1814 "UnaryOpStub_%s_%s_%s", | 1809 overwrite_name, |
| 1815 op_name, | 1810 UnaryOpIC::GetName(operand_type_)); |
| 1816 overwrite_name, | |
| 1817 UnaryOpIC::GetName(operand_type_)); | |
| 1818 return name_; | |
| 1819 } | 1811 } |
| 1820 | 1812 |
| 1821 | 1813 |
| 1822 // TODO(svenpanne): Use virtual functions instead of switch. | 1814 // TODO(svenpanne): Use virtual functions instead of switch. |
| 1823 void UnaryOpStub::Generate(MacroAssembler* masm) { | 1815 void UnaryOpStub::Generate(MacroAssembler* masm) { |
| 1824 switch (operand_type_) { | 1816 switch (operand_type_) { |
| 1825 case UnaryOpIC::UNINITIALIZED: | 1817 case UnaryOpIC::UNINITIALIZED: |
| 1826 GenerateTypeTransition(masm); | 1818 GenerateTypeTransition(masm); |
| 1827 break; | 1819 break; |
| 1828 case UnaryOpIC::SMI: | 1820 case UnaryOpIC::SMI: |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2147 break; | 2139 break; |
| 2148 case BinaryOpIC::GENERIC: | 2140 case BinaryOpIC::GENERIC: |
| 2149 GenerateGeneric(masm); | 2141 GenerateGeneric(masm); |
| 2150 break; | 2142 break; |
| 2151 default: | 2143 default: |
| 2152 UNREACHABLE(); | 2144 UNREACHABLE(); |
| 2153 } | 2145 } |
| 2154 } | 2146 } |
| 2155 | 2147 |
| 2156 | 2148 |
| 2157 const char* BinaryOpStub::GetName() { | 2149 void BinaryOpStub::PrintName(StringStream* stream) { |
| 2158 if (name_ != NULL) return name_; | |
| 2159 const int kMaxNameLength = 100; | |
| 2160 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( | |
| 2161 kMaxNameLength); | |
| 2162 if (name_ == NULL) return "OOM"; | |
| 2163 const char* op_name = Token::Name(op_); | 2150 const char* op_name = Token::Name(op_); |
| 2164 const char* overwrite_name; | 2151 const char* overwrite_name; |
| 2165 switch (mode_) { | 2152 switch (mode_) { |
| 2166 case NO_OVERWRITE: overwrite_name = "Alloc"; break; | 2153 case NO_OVERWRITE: overwrite_name = "Alloc"; break; |
| 2167 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; | 2154 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; |
| 2168 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; | 2155 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; |
| 2169 default: overwrite_name = "UnknownOverwrite"; break; | 2156 default: overwrite_name = "UnknownOverwrite"; break; |
| 2170 } | 2157 } |
| 2171 | 2158 stream->Add("BinaryOpStub_%s_%s_%s", |
| 2172 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 2159 op_name, |
| 2173 "BinaryOpStub_%s_%s_%s", | 2160 overwrite_name, |
| 2174 op_name, | 2161 BinaryOpIC::GetName(operands_type_)); |
| 2175 overwrite_name, | |
| 2176 BinaryOpIC::GetName(operands_type_)); | |
| 2177 return name_; | |
| 2178 } | 2162 } |
| 2179 | 2163 |
| 2180 | 2164 |
| 2181 | 2165 |
| 2182 void BinaryOpStub::GenerateSmiSmiOperation(MacroAssembler* masm) { | 2166 void BinaryOpStub::GenerateSmiSmiOperation(MacroAssembler* masm) { |
| 2183 Register left = a1; | 2167 Register left = a1; |
| 2184 Register right = a0; | 2168 Register right = a0; |
| 2185 | 2169 |
| 2186 Register scratch1 = t0; | 2170 Register scratch1 = t0; |
| 2187 Register scratch2 = t1; | 2171 Register scratch2 = t1; |
| (...skipping 1548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3736 // | 3720 // |
| 3737 // Stack: | 3721 // Stack: |
| 3738 // caller fp | | 3722 // caller fp | |
| 3739 // function slot | entry frame | 3723 // function slot | entry frame |
| 3740 // context slot | | 3724 // context slot | |
| 3741 // bad fp (0xff...f) | | 3725 // bad fp (0xff...f) | |
| 3742 // callee saved registers + ra | 3726 // callee saved registers + ra |
| 3743 // 4 args slots | 3727 // 4 args slots |
| 3744 // args | 3728 // args |
| 3745 | 3729 |
| 3746 #ifdef ENABLE_LOGGING_AND_PROFILING | 3730 // If this is the outermost JS call, set js_entry_sp value. |
| 3747 // If this is the outermost JS call, set js_entry_sp value. | 3731 Label non_outermost_js; |
| 3748 Label non_outermost_js; | 3732 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, |
| 3749 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, | 3733 masm->isolate()); |
| 3750 masm->isolate()); | 3734 __ li(t1, Operand(ExternalReference(js_entry_sp))); |
| 3751 __ li(t1, Operand(ExternalReference(js_entry_sp))); | 3735 __ lw(t2, MemOperand(t1)); |
| 3752 __ lw(t2, MemOperand(t1)); | 3736 __ Branch(&non_outermost_js, ne, t2, Operand(zero_reg)); |
| 3753 __ Branch(&non_outermost_js, ne, t2, Operand(zero_reg)); | 3737 __ sw(fp, MemOperand(t1)); |
| 3754 __ sw(fp, MemOperand(t1)); | 3738 __ li(t0, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); |
| 3755 __ li(t0, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); | 3739 Label cont; |
| 3756 Label cont; | 3740 __ b(&cont); |
| 3757 __ b(&cont); | 3741 __ nop(); // Branch delay slot nop. |
| 3758 __ nop(); // Branch delay slot nop. | 3742 __ bind(&non_outermost_js); |
| 3759 __ bind(&non_outermost_js); | 3743 __ li(t0, Operand(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME))); |
| 3760 __ li(t0, Operand(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME))); | 3744 __ bind(&cont); |
| 3761 __ bind(&cont); | 3745 __ push(t0); |
| 3762 __ push(t0); | |
| 3763 #endif | |
| 3764 | 3746 |
| 3765 // Call a faked try-block that does the invoke. | 3747 // Call a faked try-block that does the invoke. |
| 3766 __ bal(&invoke); // bal exposes branch delay slot. | 3748 __ bal(&invoke); // bal exposes branch delay slot. |
| 3767 __ nop(); // Branch delay slot nop. | 3749 __ nop(); // Branch delay slot nop. |
| 3768 | 3750 |
| 3769 // Caught exception: Store result (exception) in the pending | 3751 // Caught exception: Store result (exception) in the pending |
| 3770 // exception field in the JSEnv and return a failure sentinel. | 3752 // exception field in the JSEnv and return a failure sentinel. |
| 3771 // Coming in here the fp will be invalid because the PushTryHandler below | 3753 // Coming in here the fp will be invalid because the PushTryHandler below |
| 3772 // sets it to 0 to signal the existence of the JSEntry frame. | 3754 // sets it to 0 to signal the existence of the JSEntry frame. |
| 3773 __ li(t0, Operand(ExternalReference(Isolate::k_pending_exception_address, | 3755 __ li(t0, Operand(ExternalReference(Isolate::k_pending_exception_address, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3822 __ lw(t9, MemOperand(t0)); // Deref address. | 3804 __ lw(t9, MemOperand(t0)); // Deref address. |
| 3823 | 3805 |
| 3824 // Call JSEntryTrampoline. | 3806 // Call JSEntryTrampoline. |
| 3825 __ addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag); | 3807 __ addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag); |
| 3826 __ Call(t9); | 3808 __ Call(t9); |
| 3827 | 3809 |
| 3828 // Unlink this frame from the handler chain. | 3810 // Unlink this frame from the handler chain. |
| 3829 __ PopTryHandler(); | 3811 __ PopTryHandler(); |
| 3830 | 3812 |
| 3831 __ bind(&exit); // v0 holds result | 3813 __ bind(&exit); // v0 holds result |
| 3832 #ifdef ENABLE_LOGGING_AND_PROFILING | 3814 // Check if the current stack frame is marked as the outermost JS frame. |
| 3833 // Check if the current stack frame is marked as the outermost JS frame. | 3815 Label non_outermost_js_2; |
| 3834 Label non_outermost_js_2; | 3816 __ pop(t1); |
| 3835 __ pop(t1); | 3817 __ Branch(&non_outermost_js_2, ne, t1, |
| 3836 __ Branch(&non_outermost_js_2, ne, t1, | 3818 Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); |
| 3837 Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); | 3819 __ li(t1, Operand(ExternalReference(js_entry_sp))); |
| 3838 __ li(t1, Operand(ExternalReference(js_entry_sp))); | 3820 __ sw(zero_reg, MemOperand(t1)); |
| 3839 __ sw(zero_reg, MemOperand(t1)); | 3821 __ bind(&non_outermost_js_2); |
| 3840 __ bind(&non_outermost_js_2); | |
| 3841 #endif | |
| 3842 | 3822 |
| 3843 // Restore the top frame descriptors from the stack. | 3823 // Restore the top frame descriptors from the stack. |
| 3844 __ pop(t1); | 3824 __ pop(t1); |
| 3845 __ li(t0, Operand(ExternalReference(Isolate::k_c_entry_fp_address, | 3825 __ li(t0, Operand(ExternalReference(Isolate::k_c_entry_fp_address, |
| 3846 masm->isolate()))); | 3826 masm->isolate()))); |
| 3847 __ sw(t1, MemOperand(t0)); | 3827 __ sw(t1, MemOperand(t0)); |
| 3848 | 3828 |
| 3849 // Reset the stack to the callee saved registers. | 3829 // Reset the stack to the callee saved registers. |
| 3850 __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset); | 3830 __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset); |
| 3851 | 3831 |
| (...skipping 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4926 CALL_AS_FUNCTION); | 4906 CALL_AS_FUNCTION); |
| 4927 | 4907 |
| 4928 // Slow-case: Non-function called. | 4908 // Slow-case: Non-function called. |
| 4929 __ bind(&slow); | 4909 __ bind(&slow); |
| 4930 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 4910 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
| 4931 // of the original receiver from the call site). | 4911 // of the original receiver from the call site). |
| 4932 __ sw(a1, MemOperand(sp, argc_ * kPointerSize)); | 4912 __ sw(a1, MemOperand(sp, argc_ * kPointerSize)); |
| 4933 __ li(a0, Operand(argc_)); // Setup the number of arguments. | 4913 __ li(a0, Operand(argc_)); // Setup the number of arguments. |
| 4934 __ mov(a2, zero_reg); | 4914 __ mov(a2, zero_reg); |
| 4935 __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION); | 4915 __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION); |
| 4916 __ SetCallKind(t1, CALL_AS_METHOD); |
| 4936 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 4917 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 4937 RelocInfo::CODE_TARGET); | 4918 RelocInfo::CODE_TARGET); |
| 4938 } | 4919 } |
| 4939 | 4920 |
| 4940 | 4921 |
| 4941 // Unfortunately you have to run without snapshots to see most of these | 4922 // Unfortunately you have to run without snapshots to see most of these |
| 4942 // names in the profile since most compare stubs end up in the snapshot. | 4923 // names in the profile since most compare stubs end up in the snapshot. |
| 4943 const char* CompareStub::GetName() { | 4924 void CompareStub::PrintName(StringStream* stream) { |
| 4944 ASSERT((lhs_.is(a0) && rhs_.is(a1)) || | 4925 ASSERT((lhs_.is(a0) && rhs_.is(a1)) || |
| 4945 (lhs_.is(a1) && rhs_.is(a0))); | 4926 (lhs_.is(a1) && rhs_.is(a0))); |
| 4946 | |
| 4947 if (name_ != NULL) return name_; | |
| 4948 const int kMaxNameLength = 100; | |
| 4949 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( | |
| 4950 kMaxNameLength); | |
| 4951 if (name_ == NULL) return "OOM"; | |
| 4952 | |
| 4953 const char* cc_name; | 4927 const char* cc_name; |
| 4954 switch (cc_) { | 4928 switch (cc_) { |
| 4955 case lt: cc_name = "LT"; break; | 4929 case lt: cc_name = "LT"; break; |
| 4956 case gt: cc_name = "GT"; break; | 4930 case gt: cc_name = "GT"; break; |
| 4957 case le: cc_name = "LE"; break; | 4931 case le: cc_name = "LE"; break; |
| 4958 case ge: cc_name = "GE"; break; | 4932 case ge: cc_name = "GE"; break; |
| 4959 case eq: cc_name = "EQ"; break; | 4933 case eq: cc_name = "EQ"; break; |
| 4960 case ne: cc_name = "NE"; break; | 4934 case ne: cc_name = "NE"; break; |
| 4961 default: cc_name = "UnknownCondition"; break; | 4935 default: cc_name = "UnknownCondition"; break; |
| 4962 } | 4936 } |
| 4963 | 4937 bool is_equality = cc_ == eq || cc_ == ne; |
| 4964 const char* lhs_name = lhs_.is(a0) ? "_a0" : "_a1"; | 4938 stream->Add("CompareStub_%s", cc_name); |
| 4965 const char* rhs_name = rhs_.is(a0) ? "_a0" : "_a1"; | 4939 stream->Add(lhs_.is(a0) ? "_a0" : "_a1"); |
| 4966 | 4940 stream->Add(rhs_.is(a0) ? "_a0" : "_a1"); |
| 4967 const char* strict_name = ""; | 4941 if (strict_ && is_equality) stream->Add("_STRICT"); |
| 4968 if (strict_ && (cc_ == eq || cc_ == ne)) { | 4942 if (never_nan_nan_ && is_equality) stream->Add("_NO_NAN"); |
| 4969 strict_name = "_STRICT"; | 4943 if (!include_number_compare_) stream->Add("_NO_NUMBER"); |
| 4970 } | 4944 if (!include_smi_compare_) stream->Add("_NO_SMI"); |
| 4971 | |
| 4972 const char* never_nan_nan_name = ""; | |
| 4973 if (never_nan_nan_ && (cc_ == eq || cc_ == ne)) { | |
| 4974 never_nan_nan_name = "_NO_NAN"; | |
| 4975 } | |
| 4976 | |
| 4977 const char* include_number_compare_name = ""; | |
| 4978 if (!include_number_compare_) { | |
| 4979 include_number_compare_name = "_NO_NUMBER"; | |
| 4980 } | |
| 4981 | |
| 4982 const char* include_smi_compare_name = ""; | |
| 4983 if (!include_smi_compare_) { | |
| 4984 include_smi_compare_name = "_NO_SMI"; | |
| 4985 } | |
| 4986 | |
| 4987 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | |
| 4988 "CompareStub_%s%s%s%s%s%s", | |
| 4989 cc_name, | |
| 4990 lhs_name, | |
| 4991 rhs_name, | |
| 4992 strict_name, | |
| 4993 never_nan_nan_name, | |
| 4994 include_number_compare_name, | |
| 4995 include_smi_compare_name); | |
| 4996 return name_; | |
| 4997 } | 4945 } |
| 4998 | 4946 |
| 4999 | 4947 |
| 5000 int CompareStub::MinorKey() { | 4948 int CompareStub::MinorKey() { |
| 5001 // Encode the two parameters in a unique 16 bit value. | 4949 // Encode the two parameters in a unique 16 bit value. |
| 5002 ASSERT(static_cast<unsigned>(cc_) < (1 << 14)); | 4950 ASSERT(static_cast<unsigned>(cc_) < (1 << 14)); |
| 5003 ASSERT((lhs_.is(a0) && rhs_.is(a1)) || | 4951 ASSERT((lhs_.is(a0) && rhs_.is(a1)) || |
| 5004 (lhs_.is(a1) && rhs_.is(a0))); | 4952 (lhs_.is(a1) && rhs_.is(a0))); |
| 5005 return ConditionField::encode(static_cast<unsigned>(cc_)) | 4953 return ConditionField::encode(static_cast<unsigned>(cc_)) |
| 5006 | RegisterField::encode(lhs_.is(a0)) | 4954 | RegisterField::encode(lhs_.is(a0)) |
| (...skipping 1866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6873 __ mov(result, zero_reg); | 6821 __ mov(result, zero_reg); |
| 6874 __ Ret(); | 6822 __ Ret(); |
| 6875 } | 6823 } |
| 6876 | 6824 |
| 6877 | 6825 |
| 6878 #undef __ | 6826 #undef __ |
| 6879 | 6827 |
| 6880 } } // namespace v8::internal | 6828 } } // namespace v8::internal |
| 6881 | 6829 |
| 6882 #endif // V8_TARGET_ARCH_MIPS | 6830 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |