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 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
738 __ bind(&check_for_internalized_strings); | 738 __ bind(&check_for_internalized_strings); |
739 if (cc == eq && !strict()) { | 739 if (cc == eq && !strict()) { |
740 // Returns an answer for two internalized strings or two | 740 // Returns an answer for two internalized strings or two |
741 // detectable objects. | 741 // detectable objects. |
742 // Otherwise jumps to string case or not both strings case. | 742 // Otherwise jumps to string case or not both strings case. |
743 // Assumes that a2 is the type of lhs_ on entry. | 743 // Assumes that a2 is the type of lhs_ on entry. |
744 EmitCheckForInternalizedStringsOrObjects( | 744 EmitCheckForInternalizedStringsOrObjects( |
745 masm, lhs, rhs, &flat_string_check, &slow); | 745 masm, lhs, rhs, &flat_string_check, &slow); |
746 } | 746 } |
747 | 747 |
748 // Check for both being sequential ASCII strings, and inline if that is the | 748 // Check for both being sequential one-byte strings, |
749 // case. | 749 // and inline if that is the case. |
750 __ bind(&flat_string_check); | 750 __ bind(&flat_string_check); |
751 | 751 |
752 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, a2, a3, &slow); | 752 __ JumpIfNonSmisNotBothSequentialOneByteStrings(lhs, rhs, a2, a3, &slow); |
753 | 753 |
754 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, a2, | 754 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, a2, |
755 a3); | 755 a3); |
756 if (cc == eq) { | 756 if (cc == eq) { |
757 StringHelper::GenerateFlatAsciiStringEquals(masm, lhs, rhs, a2, a3, t0); | 757 StringHelper::GenerateFlatOneByteStringEquals(masm, lhs, rhs, a2, a3, t0); |
758 } else { | 758 } else { |
759 StringHelper::GenerateCompareFlatAsciiStrings(masm, lhs, rhs, a2, a3, t0, | 759 StringHelper::GenerateCompareFlatOneByteStrings(masm, lhs, rhs, a2, a3, t0, |
760 t1); | 760 t1); |
761 } | 761 } |
762 // Never falls through to here. | 762 // Never falls through to here. |
763 | 763 |
764 __ bind(&slow); | 764 __ bind(&slow); |
765 // Prepare for call to builtin. Push object pointers, a0 (lhs) first, | 765 // Prepare for call to builtin. Push object pointers, a0 (lhs) first, |
766 // a1 (rhs) second. | 766 // a1 (rhs) second. |
767 __ Push(lhs, rhs); | 767 __ Push(lhs, rhs); |
768 // Figure out which native to call and setup the arguments. | 768 // Figure out which native to call and setup the arguments. |
769 Builtins::JavaScript native; | 769 Builtins::JavaScript native; |
770 if (cc == eq) { | 770 if (cc == eq) { |
(...skipping 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2149 // to look like a sequential string when it actually is an external string. | 2149 // to look like a sequential string when it actually is an external string. |
2150 __ lw(a1, MemOperand(sp, kPreviousIndexOffset)); | 2150 __ lw(a1, MemOperand(sp, kPreviousIndexOffset)); |
2151 __ JumpIfNotSmi(a1, &runtime); | 2151 __ JumpIfNotSmi(a1, &runtime); |
2152 __ lw(a3, FieldMemOperand(a3, String::kLengthOffset)); | 2152 __ lw(a3, FieldMemOperand(a3, String::kLengthOffset)); |
2153 __ Branch(&runtime, ls, a3, Operand(a1)); | 2153 __ Branch(&runtime, ls, a3, Operand(a1)); |
2154 __ sra(a1, a1, kSmiTagSize); // Untag the Smi. | 2154 __ sra(a1, a1, kSmiTagSize); // Untag the Smi. |
2155 | 2155 |
2156 STATIC_ASSERT(kStringEncodingMask == 4); | 2156 STATIC_ASSERT(kStringEncodingMask == 4); |
2157 STATIC_ASSERT(kOneByteStringTag == 4); | 2157 STATIC_ASSERT(kOneByteStringTag == 4); |
2158 STATIC_ASSERT(kTwoByteStringTag == 0); | 2158 STATIC_ASSERT(kTwoByteStringTag == 0); |
2159 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ASCII. | 2159 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ASCII. |
paul.l...
2014/09/10 19:12:56
nit: ascii in comment.
| |
2160 __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset)); | 2160 __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset)); |
2161 __ sra(a3, a0, 2); // a3 is 1 for ASCII, 0 for UC16 (used below). | 2161 __ sra(a3, a0, 2); // a3 is 1 for ASCII, 0 for UC16 (used below). |
2162 __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); | 2162 __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); |
2163 __ Movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. | 2163 __ Movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. |
2164 | 2164 |
2165 // (E) Carry on. String handling is done. | 2165 // (E) Carry on. String handling is done. |
2166 // t9: irregexp code | 2166 // t9: irregexp code |
2167 // Check that the irregexp code has been generated for the actual string | 2167 // Check that the irregexp code has been generated for the actual string |
2168 // encoding. If it has, the field contains a code object otherwise it contains | 2168 // encoding. If it has, the field contains a code object otherwise it contains |
2169 // a smi (code flushing support). | 2169 // a smi (code flushing support). |
2170 __ JumpIfSmi(t9, &runtime); | 2170 __ JumpIfSmi(t9, &runtime); |
2171 | 2171 |
2172 // a1: previous index | 2172 // a1: previous index |
2173 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); | 2173 // a3: encoding of subject string (1 if one_byte, 0 if two_byte); |
2174 // t9: code | 2174 // t9: code |
2175 // subject: Subject string | 2175 // subject: Subject string |
2176 // regexp_data: RegExp data (FixedArray) | 2176 // regexp_data: RegExp data (FixedArray) |
2177 // All checks done. Now push arguments for native regexp code. | 2177 // All checks done. Now push arguments for native regexp code. |
2178 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), | 2178 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), |
2179 1, a0, a2); | 2179 1, a0, a2); |
2180 | 2180 |
2181 // Isolates: note we add an additional parameter here (isolate pointer). | 2181 // Isolates: note we add an additional parameter here (isolate pointer). |
2182 const int kRegExpExecuteArguments = 9; | 2182 const int kRegExpExecuteArguments = 9; |
2183 const int kParameterRegisters = 4; | 2183 const int kParameterRegisters = 4; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2218 // regexps to behave as non-global. This does not affect non-global regexps. | 2218 // regexps to behave as non-global. This does not affect non-global regexps. |
2219 __ mov(a0, zero_reg); | 2219 __ mov(a0, zero_reg); |
2220 __ sw(a0, MemOperand(sp, 2 * kPointerSize)); | 2220 __ sw(a0, MemOperand(sp, 2 * kPointerSize)); |
2221 | 2221 |
2222 // Argument 5: static offsets vector buffer. | 2222 // Argument 5: static offsets vector buffer. |
2223 __ li(a0, Operand( | 2223 __ li(a0, Operand( |
2224 ExternalReference::address_of_static_offsets_vector(isolate()))); | 2224 ExternalReference::address_of_static_offsets_vector(isolate()))); |
2225 __ sw(a0, MemOperand(sp, 1 * kPointerSize)); | 2225 __ sw(a0, MemOperand(sp, 1 * kPointerSize)); |
2226 | 2226 |
2227 // For arguments 4 and 3 get string length, calculate start of string data | 2227 // For arguments 4 and 3 get string length, calculate start of string data |
2228 // and calculate the shift of the index (0 for ASCII and 1 for two byte). | 2228 // calculate the shift of the index (0 for one-byte and 1 for two-byte). |
2229 __ Addu(t2, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); | 2229 __ Addu(t2, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); |
2230 __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte. | 2230 __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte. |
2231 // Load the length from the original subject string from the previous stack | 2231 // Load the length from the original subject string from the previous stack |
2232 // frame. Therefore we have to use fp, which points exactly to two pointer | 2232 // frame. Therefore we have to use fp, which points exactly to two pointer |
2233 // sizes below the previous sp. (Because creating a new stack frame pushes | 2233 // sizes below the previous sp. (Because creating a new stack frame pushes |
2234 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) | 2234 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) |
2235 __ lw(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); | 2235 __ lw(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); |
2236 // If slice offset is not 0, load the length from the original sliced string. | 2236 // If slice offset is not 0, load the length from the original sliced string. |
2237 // Argument 4, a3: End of string data | 2237 // Argument 4, a3: End of string data |
2238 // Argument 3, a2: Start of string data | 2238 // Argument 3, a2: Start of string data |
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2853 __ CallExternalReference(miss, 4); | 2853 __ CallExternalReference(miss, 4); |
2854 | 2854 |
2855 // Move result to a1 and exit the internal frame. | 2855 // Move result to a1 and exit the internal frame. |
2856 __ mov(a1, v0); | 2856 __ mov(a1, v0); |
2857 } | 2857 } |
2858 } | 2858 } |
2859 | 2859 |
2860 | 2860 |
2861 // StringCharCodeAtGenerator. | 2861 // StringCharCodeAtGenerator. |
2862 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 2862 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
2863 Label flat_string; | |
2864 Label ascii_string; | |
2865 Label got_char_code; | |
2866 Label sliced_string; | |
2867 | |
2868 DCHECK(!t0.is(index_)); | 2863 DCHECK(!t0.is(index_)); |
2869 DCHECK(!t0.is(result_)); | 2864 DCHECK(!t0.is(result_)); |
2870 DCHECK(!t0.is(object_)); | 2865 DCHECK(!t0.is(object_)); |
2871 | 2866 |
2872 // If the receiver is a smi trigger the non-string case. | 2867 // If the receiver is a smi trigger the non-string case. |
2873 __ JumpIfSmi(object_, receiver_not_string_); | 2868 __ JumpIfSmi(object_, receiver_not_string_); |
2874 | 2869 |
2875 // Fetch the instance type of the receiver into result register. | 2870 // Fetch the instance type of the receiver into result register. |
2876 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 2871 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
2877 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 2872 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2969 STATIC_ASSERT(kSmiTag == 0); | 2964 STATIC_ASSERT(kSmiTag == 0); |
2970 STATIC_ASSERT(kSmiShiftSize == 0); | 2965 STATIC_ASSERT(kSmiShiftSize == 0); |
2971 DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCode + 1)); | 2966 DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCode + 1)); |
2972 __ And(t0, | 2967 __ And(t0, |
2973 code_, | 2968 code_, |
2974 Operand(kSmiTagMask | | 2969 Operand(kSmiTagMask | |
2975 ((~String::kMaxOneByteCharCode) << kSmiTagSize))); | 2970 ((~String::kMaxOneByteCharCode) << kSmiTagSize))); |
2976 __ Branch(&slow_case_, ne, t0, Operand(zero_reg)); | 2971 __ Branch(&slow_case_, ne, t0, Operand(zero_reg)); |
2977 | 2972 |
2978 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); | 2973 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); |
2979 // At this point code register contains smi tagged ASCII char code. | 2974 // At this point code register contains smi tagged one-byte char code. |
2980 STATIC_ASSERT(kSmiTag == 0); | 2975 STATIC_ASSERT(kSmiTag == 0); |
2981 __ sll(t0, code_, kPointerSizeLog2 - kSmiTagSize); | 2976 __ sll(t0, code_, kPointerSizeLog2 - kSmiTagSize); |
2982 __ Addu(result_, result_, t0); | 2977 __ Addu(result_, result_, t0); |
2983 __ lw(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); | 2978 __ lw(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); |
2984 __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); | 2979 __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); |
2985 __ Branch(&slow_case_, eq, result_, Operand(t0)); | 2980 __ Branch(&slow_case_, eq, result_, Operand(t0)); |
2986 __ bind(&exit_); | 2981 __ bind(&exit_); |
2987 } | 2982 } |
2988 | 2983 |
2989 | 2984 |
2990 void StringCharFromCodeGenerator::GenerateSlow( | 2985 void StringCharFromCodeGenerator::GenerateSlow( |
2991 MacroAssembler* masm, | 2986 MacroAssembler* masm, |
2992 const RuntimeCallHelper& call_helper) { | 2987 const RuntimeCallHelper& call_helper) { |
2993 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); | 2988 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); |
2994 | 2989 |
2995 __ bind(&slow_case_); | 2990 __ bind(&slow_case_); |
2996 call_helper.BeforeCall(masm); | 2991 call_helper.BeforeCall(masm); |
2997 __ push(code_); | 2992 __ push(code_); |
2998 __ CallRuntime(Runtime::kCharFromCode, 1); | 2993 __ CallRuntime(Runtime::kCharFromCode, 1); |
2999 __ Move(result_, v0); | 2994 __ Move(result_, v0); |
3000 | 2995 |
3001 call_helper.AfterCall(masm); | 2996 call_helper.AfterCall(masm); |
3002 __ Branch(&exit_); | 2997 __ Branch(&exit_); |
3003 | 2998 |
3004 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); | 2999 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
3005 } | 3000 } |
3006 | 3001 |
3007 | 3002 |
3008 enum CopyCharactersFlags { | 3003 enum CopyCharactersFlags { COPY_ONE_BYTE = 1, DEST_ALWAYS_ALIGNED = 2 }; |
3009 COPY_ASCII = 1, | |
3010 DEST_ALWAYS_ALIGNED = 2 | |
3011 }; | |
3012 | 3004 |
3013 | 3005 |
3014 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, | 3006 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
3015 Register dest, | 3007 Register dest, |
3016 Register src, | 3008 Register src, |
3017 Register count, | 3009 Register count, |
3018 Register scratch, | 3010 Register scratch, |
3019 String::Encoding encoding) { | 3011 String::Encoding encoding) { |
3020 if (FLAG_debug_code) { | 3012 if (FLAG_debug_code) { |
3021 // Check that destination is word aligned. | 3013 // Check that destination is word aligned. |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3165 // Allocate new sliced string. At this point we do not reload the instance | 3157 // Allocate new sliced string. At this point we do not reload the instance |
3166 // type including the string encoding because we simply rely on the info | 3158 // type including the string encoding because we simply rely on the info |
3167 // provided by the original string. It does not matter if the original | 3159 // provided by the original string. It does not matter if the original |
3168 // string's encoding is wrong because we always have to recheck encoding of | 3160 // string's encoding is wrong because we always have to recheck encoding of |
3169 // the newly created string's parent anyways due to externalized strings. | 3161 // the newly created string's parent anyways due to externalized strings. |
3170 Label two_byte_slice, set_slice_header; | 3162 Label two_byte_slice, set_slice_header; |
3171 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); | 3163 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); |
3172 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); | 3164 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
3173 __ And(t0, a1, Operand(kStringEncodingMask)); | 3165 __ And(t0, a1, Operand(kStringEncodingMask)); |
3174 __ Branch(&two_byte_slice, eq, t0, Operand(zero_reg)); | 3166 __ Branch(&two_byte_slice, eq, t0, Operand(zero_reg)); |
3175 __ AllocateAsciiSlicedString(v0, a2, t2, t3, &runtime); | 3167 __ AllocateOneByteSlicedString(v0, a2, t2, t3, &runtime); |
3176 __ jmp(&set_slice_header); | 3168 __ jmp(&set_slice_header); |
3177 __ bind(&two_byte_slice); | 3169 __ bind(&two_byte_slice); |
3178 __ AllocateTwoByteSlicedString(v0, a2, t2, t3, &runtime); | 3170 __ AllocateTwoByteSlicedString(v0, a2, t2, t3, &runtime); |
3179 __ bind(&set_slice_header); | 3171 __ bind(&set_slice_header); |
3180 __ sll(a3, a3, 1); | 3172 __ sll(a3, a3, 1); |
3181 __ sw(t1, FieldMemOperand(v0, SlicedString::kParentOffset)); | 3173 __ sw(t1, FieldMemOperand(v0, SlicedString::kParentOffset)); |
3182 __ sw(a3, FieldMemOperand(v0, SlicedString::kOffsetOffset)); | 3174 __ sw(a3, FieldMemOperand(v0, SlicedString::kOffsetOffset)); |
3183 __ jmp(&return_v0); | 3175 __ jmp(&return_v0); |
3184 | 3176 |
3185 __ bind(©_routine); | 3177 __ bind(©_routine); |
(...skipping 23 matching lines...) Expand all Loading... | |
3209 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 3201 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
3210 __ Addu(t1, t1, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3202 __ Addu(t1, t1, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3211 | 3203 |
3212 __ bind(&allocate_result); | 3204 __ bind(&allocate_result); |
3213 // Sequential acii string. Allocate the result. | 3205 // Sequential acii string. Allocate the result. |
3214 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 3206 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); |
3215 __ And(t0, a1, Operand(kStringEncodingMask)); | 3207 __ And(t0, a1, Operand(kStringEncodingMask)); |
3216 __ Branch(&two_byte_sequential, eq, t0, Operand(zero_reg)); | 3208 __ Branch(&two_byte_sequential, eq, t0, Operand(zero_reg)); |
3217 | 3209 |
3218 // Allocate and copy the resulting ASCII string. | 3210 // Allocate and copy the resulting ASCII string. |
3219 __ AllocateAsciiString(v0, a2, t0, t2, t3, &runtime); | 3211 __ AllocateOneByteString(v0, a2, t0, t2, t3, &runtime); |
3220 | 3212 |
3221 // Locate first character of substring to copy. | 3213 // Locate first character of substring to copy. |
3222 __ Addu(t1, t1, a3); | 3214 __ Addu(t1, t1, a3); |
3223 | 3215 |
3224 // Locate first character of result. | 3216 // Locate first character of result. |
3225 __ Addu(a1, v0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3217 __ Addu(a1, v0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3226 | 3218 |
3227 // v0: result string | 3219 // v0: result string |
3228 // a1: first character of result string | 3220 // a1: first character of result string |
3229 // a2: result string length | 3221 // a2: result string length |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3268 // a3: from index (untagged) | 3260 // a3: from index (untagged) |
3269 __ SmiTag(a3, a3); | 3261 __ SmiTag(a3, a3); |
3270 StringCharAtGenerator generator( | 3262 StringCharAtGenerator generator( |
3271 v0, a3, a2, v0, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); | 3263 v0, a3, a2, v0, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); |
3272 generator.GenerateFast(masm); | 3264 generator.GenerateFast(masm); |
3273 __ DropAndRet(3); | 3265 __ DropAndRet(3); |
3274 generator.SkipSlow(masm, &runtime); | 3266 generator.SkipSlow(masm, &runtime); |
3275 } | 3267 } |
3276 | 3268 |
3277 | 3269 |
3278 void StringHelper::GenerateFlatAsciiStringEquals(MacroAssembler* masm, | 3270 void StringHelper::GenerateFlatOneByteStringEquals( |
3279 Register left, Register right, | 3271 MacroAssembler* masm, Register left, Register right, Register scratch1, |
3280 Register scratch1, | 3272 Register scratch2, Register scratch3) { |
3281 Register scratch2, | |
3282 Register scratch3) { | |
3283 Register length = scratch1; | 3273 Register length = scratch1; |
3284 | 3274 |
3285 // Compare lengths. | 3275 // Compare lengths. |
3286 Label strings_not_equal, check_zero_length; | 3276 Label strings_not_equal, check_zero_length; |
3287 __ lw(length, FieldMemOperand(left, String::kLengthOffset)); | 3277 __ lw(length, FieldMemOperand(left, String::kLengthOffset)); |
3288 __ lw(scratch2, FieldMemOperand(right, String::kLengthOffset)); | 3278 __ lw(scratch2, FieldMemOperand(right, String::kLengthOffset)); |
3289 __ Branch(&check_zero_length, eq, length, Operand(scratch2)); | 3279 __ Branch(&check_zero_length, eq, length, Operand(scratch2)); |
3290 __ bind(&strings_not_equal); | 3280 __ bind(&strings_not_equal); |
3291 DCHECK(is_int16(NOT_EQUAL)); | 3281 DCHECK(is_int16(NOT_EQUAL)); |
3292 __ Ret(USE_DELAY_SLOT); | 3282 __ Ret(USE_DELAY_SLOT); |
3293 __ li(v0, Operand(Smi::FromInt(NOT_EQUAL))); | 3283 __ li(v0, Operand(Smi::FromInt(NOT_EQUAL))); |
3294 | 3284 |
3295 // Check if the length is zero. | 3285 // Check if the length is zero. |
3296 Label compare_chars; | 3286 Label compare_chars; |
3297 __ bind(&check_zero_length); | 3287 __ bind(&check_zero_length); |
3298 STATIC_ASSERT(kSmiTag == 0); | 3288 STATIC_ASSERT(kSmiTag == 0); |
3299 __ Branch(&compare_chars, ne, length, Operand(zero_reg)); | 3289 __ Branch(&compare_chars, ne, length, Operand(zero_reg)); |
3300 DCHECK(is_int16(EQUAL)); | 3290 DCHECK(is_int16(EQUAL)); |
3301 __ Ret(USE_DELAY_SLOT); | 3291 __ Ret(USE_DELAY_SLOT); |
3302 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3292 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3303 | 3293 |
3304 // Compare characters. | 3294 // Compare characters. |
3305 __ bind(&compare_chars); | 3295 __ bind(&compare_chars); |
3306 | 3296 |
3307 GenerateAsciiCharsCompareLoop(masm, | 3297 GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, scratch3, |
3308 left, right, length, scratch2, scratch3, v0, | 3298 v0, &strings_not_equal); |
3309 &strings_not_equal); | |
3310 | 3299 |
3311 // Characters are equal. | 3300 // Characters are equal. |
3312 __ Ret(USE_DELAY_SLOT); | 3301 __ Ret(USE_DELAY_SLOT); |
3313 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3302 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3314 } | 3303 } |
3315 | 3304 |
3316 | 3305 |
3317 void StringHelper::GenerateCompareFlatAsciiStrings( | 3306 void StringHelper::GenerateCompareFlatOneByteStrings( |
3318 MacroAssembler* masm, Register left, Register right, Register scratch1, | 3307 MacroAssembler* masm, Register left, Register right, Register scratch1, |
3319 Register scratch2, Register scratch3, Register scratch4) { | 3308 Register scratch2, Register scratch3, Register scratch4) { |
3320 Label result_not_equal, compare_lengths; | 3309 Label result_not_equal, compare_lengths; |
3321 // Find minimum length and length difference. | 3310 // Find minimum length and length difference. |
3322 __ lw(scratch1, FieldMemOperand(left, String::kLengthOffset)); | 3311 __ lw(scratch1, FieldMemOperand(left, String::kLengthOffset)); |
3323 __ lw(scratch2, FieldMemOperand(right, String::kLengthOffset)); | 3312 __ lw(scratch2, FieldMemOperand(right, String::kLengthOffset)); |
3324 __ Subu(scratch3, scratch1, Operand(scratch2)); | 3313 __ Subu(scratch3, scratch1, Operand(scratch2)); |
3325 Register length_delta = scratch3; | 3314 Register length_delta = scratch3; |
3326 __ slt(scratch4, scratch2, scratch1); | 3315 __ slt(scratch4, scratch2, scratch1); |
3327 __ Movn(scratch1, scratch2, scratch4); | 3316 __ Movn(scratch1, scratch2, scratch4); |
3328 Register min_length = scratch1; | 3317 Register min_length = scratch1; |
3329 STATIC_ASSERT(kSmiTag == 0); | 3318 STATIC_ASSERT(kSmiTag == 0); |
3330 __ Branch(&compare_lengths, eq, min_length, Operand(zero_reg)); | 3319 __ Branch(&compare_lengths, eq, min_length, Operand(zero_reg)); |
3331 | 3320 |
3332 // Compare loop. | 3321 // Compare loop. |
3333 GenerateAsciiCharsCompareLoop(masm, | 3322 GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2, |
3334 left, right, min_length, scratch2, scratch4, v0, | 3323 scratch4, v0, &result_not_equal); |
3335 &result_not_equal); | |
3336 | 3324 |
3337 // Compare lengths - strings up to min-length are equal. | 3325 // Compare lengths - strings up to min-length are equal. |
3338 __ bind(&compare_lengths); | 3326 __ bind(&compare_lengths); |
3339 DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); | 3327 DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); |
3340 // Use length_delta as result if it's zero. | 3328 // Use length_delta as result if it's zero. |
3341 __ mov(scratch2, length_delta); | 3329 __ mov(scratch2, length_delta); |
3342 __ mov(scratch4, zero_reg); | 3330 __ mov(scratch4, zero_reg); |
3343 __ mov(v0, zero_reg); | 3331 __ mov(v0, zero_reg); |
3344 | 3332 |
3345 __ bind(&result_not_equal); | 3333 __ bind(&result_not_equal); |
3346 // Conditionally update the result based either on length_delta or | 3334 // Conditionally update the result based either on length_delta or |
3347 // the last comparion performed in the loop above. | 3335 // the last comparion performed in the loop above. |
3348 Label ret; | 3336 Label ret; |
3349 __ Branch(&ret, eq, scratch2, Operand(scratch4)); | 3337 __ Branch(&ret, eq, scratch2, Operand(scratch4)); |
3350 __ li(v0, Operand(Smi::FromInt(GREATER))); | 3338 __ li(v0, Operand(Smi::FromInt(GREATER))); |
3351 __ Branch(&ret, gt, scratch2, Operand(scratch4)); | 3339 __ Branch(&ret, gt, scratch2, Operand(scratch4)); |
3352 __ li(v0, Operand(Smi::FromInt(LESS))); | 3340 __ li(v0, Operand(Smi::FromInt(LESS))); |
3353 __ bind(&ret); | 3341 __ bind(&ret); |
3354 __ Ret(); | 3342 __ Ret(); |
3355 } | 3343 } |
3356 | 3344 |
3357 | 3345 |
3358 void StringHelper::GenerateAsciiCharsCompareLoop( | 3346 void StringHelper::GenerateOneByteCharsCompareLoop( |
3359 MacroAssembler* masm, Register left, Register right, Register length, | 3347 MacroAssembler* masm, Register left, Register right, Register length, |
3360 Register scratch1, Register scratch2, Register scratch3, | 3348 Register scratch1, Register scratch2, Register scratch3, |
3361 Label* chars_not_equal) { | 3349 Label* chars_not_equal) { |
3362 // Change index to run from -length to -1 by adding length to string | 3350 // Change index to run from -length to -1 by adding length to string |
3363 // start. This means that loop ends when index reaches zero, which | 3351 // start. This means that loop ends when index reaches zero, which |
3364 // doesn't need an additional compare. | 3352 // doesn't need an additional compare. |
3365 __ SmiUntag(length); | 3353 __ SmiUntag(length); |
3366 __ Addu(scratch1, length, | 3354 __ Addu(scratch1, length, |
3367 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3355 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3368 __ Addu(left, left, Operand(scratch1)); | 3356 __ Addu(left, left, Operand(scratch1)); |
(...skipping 29 matching lines...) Expand all Loading... | |
3398 Label not_same; | 3386 Label not_same; |
3399 __ Branch(¬_same, ne, a0, Operand(a1)); | 3387 __ Branch(¬_same, ne, a0, Operand(a1)); |
3400 STATIC_ASSERT(EQUAL == 0); | 3388 STATIC_ASSERT(EQUAL == 0); |
3401 STATIC_ASSERT(kSmiTag == 0); | 3389 STATIC_ASSERT(kSmiTag == 0); |
3402 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3390 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3403 __ IncrementCounter(counters->string_compare_native(), 1, a1, a2); | 3391 __ IncrementCounter(counters->string_compare_native(), 1, a1, a2); |
3404 __ DropAndRet(2); | 3392 __ DropAndRet(2); |
3405 | 3393 |
3406 __ bind(¬_same); | 3394 __ bind(¬_same); |
3407 | 3395 |
3408 // Check that both objects are sequential ASCII strings. | 3396 // Check that both objects are sequential one-byte strings. |
3409 __ JumpIfNotBothSequentialAsciiStrings(a1, a0, a2, a3, &runtime); | 3397 __ JumpIfNotBothSequentialOneByteStrings(a1, a0, a2, a3, &runtime); |
3410 | 3398 |
3411 // Compare flat ASCII strings natively. Remove arguments from stack first. | 3399 // Compare flat ASCII strings natively. Remove arguments from stack first. |
3412 __ IncrementCounter(counters->string_compare_native(), 1, a2, a3); | 3400 __ IncrementCounter(counters->string_compare_native(), 1, a2, a3); |
3413 __ Addu(sp, sp, Operand(2 * kPointerSize)); | 3401 __ Addu(sp, sp, Operand(2 * kPointerSize)); |
3414 StringHelper::GenerateCompareFlatAsciiStrings(masm, a1, a0, a2, a3, t0, t1); | 3402 StringHelper::GenerateCompareFlatOneByteStrings(masm, a1, a0, a2, a3, t0, t1); |
3415 | 3403 |
3416 __ bind(&runtime); | 3404 __ bind(&runtime); |
3417 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3405 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3418 } | 3406 } |
3419 | 3407 |
3420 | 3408 |
3421 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 3409 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
3422 // ----------- S t a t e ------------- | 3410 // ----------- S t a t e ------------- |
3423 // -- a1 : left | 3411 // -- a1 : left |
3424 // -- a0 : right | 3412 // -- a0 : right |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3697 Label is_symbol; | 3685 Label is_symbol; |
3698 __ Branch(&is_symbol, ne, tmp5, Operand(zero_reg)); | 3686 __ Branch(&is_symbol, ne, tmp5, Operand(zero_reg)); |
3699 // Make sure a0 is non-zero. At this point input operands are | 3687 // Make sure a0 is non-zero. At this point input operands are |
3700 // guaranteed to be non-zero. | 3688 // guaranteed to be non-zero. |
3701 DCHECK(right.is(a0)); | 3689 DCHECK(right.is(a0)); |
3702 __ Ret(USE_DELAY_SLOT); | 3690 __ Ret(USE_DELAY_SLOT); |
3703 __ mov(v0, a0); // In the delay slot. | 3691 __ mov(v0, a0); // In the delay slot. |
3704 __ bind(&is_symbol); | 3692 __ bind(&is_symbol); |
3705 } | 3693 } |
3706 | 3694 |
3707 // Check that both strings are sequential ASCII. | 3695 // Check that both strings are sequential one-byte. |
3708 Label runtime; | 3696 Label runtime; |
3709 __ JumpIfBothInstanceTypesAreNotSequentialAscii( | 3697 __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4, |
3710 tmp1, tmp2, tmp3, tmp4, &runtime); | 3698 &runtime); |
3711 | 3699 |
3712 // Compare flat ASCII strings. Returns when done. | 3700 // Compare flat one-byte strings. Returns when done. |
3713 if (equality) { | 3701 if (equality) { |
3714 StringHelper::GenerateFlatAsciiStringEquals(masm, left, right, tmp1, tmp2, | 3702 StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, tmp2, |
3715 tmp3); | 3703 tmp3); |
3716 } else { | 3704 } else { |
3717 StringHelper::GenerateCompareFlatAsciiStrings(masm, left, right, tmp1, tmp2, | 3705 StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1, |
3718 tmp3, tmp4); | 3706 tmp2, tmp3, tmp4); |
3719 } | 3707 } |
3720 | 3708 |
3721 // Handle more complex cases in runtime. | 3709 // Handle more complex cases in runtime. |
3722 __ bind(&runtime); | 3710 __ bind(&runtime); |
3723 __ Push(left, right); | 3711 __ Push(left, right); |
3724 if (equality) { | 3712 if (equality) { |
3725 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 3713 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); |
3726 } else { | 3714 } else { |
3727 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3715 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3728 } | 3716 } |
(...skipping 1134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4863 MemOperand(fp, 6 * kPointerSize), | 4851 MemOperand(fp, 6 * kPointerSize), |
4864 NULL); | 4852 NULL); |
4865 } | 4853 } |
4866 | 4854 |
4867 | 4855 |
4868 #undef __ | 4856 #undef __ |
4869 | 4857 |
4870 } } // namespace v8::internal | 4858 } } // namespace v8::internal |
4871 | 4859 |
4872 #endif // V8_TARGET_ARCH_MIPS | 4860 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |