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" |
(...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
733 __ bind(&check_for_internalized_strings); | 733 __ bind(&check_for_internalized_strings); |
734 if (cc == eq && !strict()) { | 734 if (cc == eq && !strict()) { |
735 // Returns an answer for two internalized strings or two | 735 // Returns an answer for two internalized strings or two |
736 // detectable objects. | 736 // detectable objects. |
737 // Otherwise jumps to string case or not both strings case. | 737 // Otherwise jumps to string case or not both strings case. |
738 // Assumes that a2 is the type of lhs_ on entry. | 738 // Assumes that a2 is the type of lhs_ on entry. |
739 EmitCheckForInternalizedStringsOrObjects( | 739 EmitCheckForInternalizedStringsOrObjects( |
740 masm, lhs, rhs, &flat_string_check, &slow); | 740 masm, lhs, rhs, &flat_string_check, &slow); |
741 } | 741 } |
742 | 742 |
743 // Check for both being sequential ASCII strings, and inline if that is the | 743 // Check for both being sequential one-byte strings, |
744 // case. | 744 // and inline if that is the case. |
745 __ bind(&flat_string_check); | 745 __ bind(&flat_string_check); |
746 | 746 |
747 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, a2, a3, &slow); | 747 __ JumpIfNonSmisNotBothSequentialOneByteStrings(lhs, rhs, a2, a3, &slow); |
748 | 748 |
749 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, a2, | 749 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, a2, |
750 a3); | 750 a3); |
751 if (cc == eq) { | 751 if (cc == eq) { |
752 StringHelper::GenerateFlatAsciiStringEquals(masm, lhs, rhs, a2, a3, a4); | 752 StringHelper::GenerateFlatOneByteStringEquals(masm, lhs, rhs, a2, a3, a4); |
753 } else { | 753 } else { |
754 StringHelper::GenerateCompareFlatAsciiStrings(masm, lhs, rhs, a2, a3, a4, | 754 StringHelper::GenerateCompareFlatOneByteStrings(masm, lhs, rhs, a2, a3, a4, |
755 a5); | 755 a5); |
756 } | 756 } |
757 // Never falls through to here. | 757 // Never falls through to here. |
758 | 758 |
759 __ bind(&slow); | 759 __ bind(&slow); |
760 // Prepare for call to builtin. Push object pointers, a0 (lhs) first, | 760 // Prepare for call to builtin. Push object pointers, a0 (lhs) first, |
761 // a1 (rhs) second. | 761 // a1 (rhs) second. |
762 __ Push(lhs, rhs); | 762 __ Push(lhs, rhs); |
763 // Figure out which native to call and setup the arguments. | 763 // Figure out which native to call and setup the arguments. |
764 Builtins::JavaScript native; | 764 Builtins::JavaScript native; |
765 if (cc == eq) { | 765 if (cc == eq) { |
(...skipping 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2150 // to look like a sequential string when it actually is an external string. | 2150 // to look like a sequential string when it actually is an external string. |
2151 __ ld(a1, MemOperand(sp, kPreviousIndexOffset)); | 2151 __ ld(a1, MemOperand(sp, kPreviousIndexOffset)); |
2152 __ JumpIfNotSmi(a1, &runtime); | 2152 __ JumpIfNotSmi(a1, &runtime); |
2153 __ ld(a3, FieldMemOperand(a3, String::kLengthOffset)); | 2153 __ ld(a3, FieldMemOperand(a3, String::kLengthOffset)); |
2154 __ Branch(&runtime, ls, a3, Operand(a1)); | 2154 __ Branch(&runtime, ls, a3, Operand(a1)); |
2155 __ SmiUntag(a1); | 2155 __ SmiUntag(a1); |
2156 | 2156 |
2157 STATIC_ASSERT(kStringEncodingMask == 4); | 2157 STATIC_ASSERT(kStringEncodingMask == 4); |
2158 STATIC_ASSERT(kOneByteStringTag == 4); | 2158 STATIC_ASSERT(kOneByteStringTag == 4); |
2159 STATIC_ASSERT(kTwoByteStringTag == 0); | 2159 STATIC_ASSERT(kTwoByteStringTag == 0); |
2160 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ASCII. | 2160 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for one_byte. |
2161 __ ld(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset)); | 2161 __ ld(t9, FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset)); |
2162 __ dsra(a3, a0, 2); // a3 is 1 for ASCII, 0 for UC16 (used below). | 2162 __ dsra(a3, a0, 2); // a3 is 1 for one_byte, 0 for UC16 (used below). |
2163 __ ld(a5, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); | 2163 __ ld(a5, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); |
2164 __ Movz(t9, a5, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. | 2164 __ Movz(t9, a5, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. |
2165 | 2165 |
2166 // (E) Carry on. String handling is done. | 2166 // (E) Carry on. String handling is done. |
2167 // t9: irregexp code | 2167 // t9: irregexp code |
2168 // Check that the irregexp code has been generated for the actual string | 2168 // Check that the irregexp code has been generated for the actual string |
2169 // encoding. If it has, the field contains a code object otherwise it contains | 2169 // encoding. If it has, the field contains a code object otherwise it contains |
2170 // a smi (code flushing support). | 2170 // a smi (code flushing support). |
2171 __ JumpIfSmi(t9, &runtime); | 2171 __ JumpIfSmi(t9, &runtime); |
2172 | 2172 |
2173 // a1: previous index | 2173 // a1: previous index |
2174 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); | 2174 // a3: encoding of subject string (1 if one_byte, 0 if two_byte); |
2175 // t9: code | 2175 // t9: code |
2176 // subject: Subject string | 2176 // subject: Subject string |
2177 // regexp_data: RegExp data (FixedArray) | 2177 // regexp_data: RegExp data (FixedArray) |
2178 // All checks done. Now push arguments for native regexp code. | 2178 // All checks done. Now push arguments for native regexp code. |
2179 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), | 2179 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), |
2180 1, a0, a2); | 2180 1, a0, a2); |
2181 | 2181 |
2182 // Isolates: note we add an additional parameter here (isolate pointer). | 2182 // Isolates: note we add an additional parameter here (isolate pointer). |
2183 const int kRegExpExecuteArguments = 9; | 2183 const int kRegExpExecuteArguments = 9; |
2184 const int kParameterRegisters = (kMipsAbi == kN64) ? 8 : 4; | 2184 const int kParameterRegisters = (kMipsAbi == kN64) ? 8 : 4; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2249 __ mov(a0, zero_reg); | 2249 __ mov(a0, zero_reg); |
2250 __ sd(a0, MemOperand(sp, 2 * kPointerSize)); | 2250 __ sd(a0, MemOperand(sp, 2 * kPointerSize)); |
2251 | 2251 |
2252 // Argument 5: static offsets vector buffer. | 2252 // Argument 5: static offsets vector buffer. |
2253 __ li(a0, Operand( | 2253 __ li(a0, Operand( |
2254 ExternalReference::address_of_static_offsets_vector(isolate()))); | 2254 ExternalReference::address_of_static_offsets_vector(isolate()))); |
2255 __ sd(a0, MemOperand(sp, 1 * kPointerSize)); | 2255 __ sd(a0, MemOperand(sp, 1 * kPointerSize)); |
2256 } | 2256 } |
2257 | 2257 |
2258 // For arguments 4 and 3 get string length, calculate start of string data | 2258 // For arguments 4 and 3 get string length, calculate start of string data |
2259 // and calculate the shift of the index (0 for ASCII and 1 for two byte). | 2259 // and calculate the shift of the index (0 for one_byte and 1 for two byte). |
2260 __ Daddu(t2, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); | 2260 __ Daddu(t2, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); |
2261 __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte. | 2261 __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte. |
2262 // Load the length from the original subject string from the previous stack | 2262 // Load the length from the original subject string from the previous stack |
2263 // frame. Therefore we have to use fp, which points exactly to two pointer | 2263 // frame. Therefore we have to use fp, which points exactly to two pointer |
2264 // sizes below the previous sp. (Because creating a new stack frame pushes | 2264 // sizes below the previous sp. (Because creating a new stack frame pushes |
2265 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) | 2265 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) |
2266 __ ld(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); | 2266 __ ld(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); |
2267 // If slice offset is not 0, load the length from the original sliced string. | 2267 // If slice offset is not 0, load the length from the original sliced string. |
2268 // Argument 4, a3: End of string data | 2268 // Argument 4, a3: End of string data |
2269 // Argument 3, a2: Start of string data | 2269 // Argument 3, a2: Start of string data |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2741 __ bind(&do_call); | 2741 __ bind(&do_call); |
2742 // Set expected number of arguments to zero (not changing r0). | 2742 // Set expected number of arguments to zero (not changing r0). |
2743 __ li(a2, Operand(0, RelocInfo::NONE32)); | 2743 __ li(a2, Operand(0, RelocInfo::NONE32)); |
2744 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 2744 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
2745 RelocInfo::CODE_TARGET); | 2745 RelocInfo::CODE_TARGET); |
2746 } | 2746 } |
2747 | 2747 |
2748 | 2748 |
2749 // StringCharCodeAtGenerator. | 2749 // StringCharCodeAtGenerator. |
2750 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 2750 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
2751 Label flat_string; | |
2752 Label ascii_string; | |
2753 Label got_char_code; | |
2754 Label sliced_string; | |
2755 | |
2756 DCHECK(!a4.is(index_)); | 2751 DCHECK(!a4.is(index_)); |
2757 DCHECK(!a4.is(result_)); | 2752 DCHECK(!a4.is(result_)); |
2758 DCHECK(!a4.is(object_)); | 2753 DCHECK(!a4.is(object_)); |
2759 | 2754 |
2760 // If the receiver is a smi trigger the non-string case. | 2755 // If the receiver is a smi trigger the non-string case. |
2761 __ JumpIfSmi(object_, receiver_not_string_); | 2756 __ JumpIfSmi(object_, receiver_not_string_); |
2762 | 2757 |
2763 // Fetch the instance type of the receiver into result register. | 2758 // Fetch the instance type of the receiver into result register. |
2764 __ ld(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 2759 __ ld(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
2765 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 2760 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3003 STATIC_ASSERT(kSmiTag == 0); | 2998 STATIC_ASSERT(kSmiTag == 0); |
3004 DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCode + 1)); | 2999 DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCode + 1)); |
3005 __ And(a4, | 3000 __ And(a4, |
3006 code_, | 3001 code_, |
3007 Operand(kSmiTagMask | | 3002 Operand(kSmiTagMask | |
3008 ((~String::kMaxOneByteCharCode) << kSmiTagSize))); | 3003 ((~String::kMaxOneByteCharCode) << kSmiTagSize))); |
3009 __ Branch(&slow_case_, ne, a4, Operand(zero_reg)); | 3004 __ Branch(&slow_case_, ne, a4, Operand(zero_reg)); |
3010 | 3005 |
3011 | 3006 |
3012 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); | 3007 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); |
3013 // At this point code register contains smi tagged ASCII char code. | 3008 // At this point code register contains smi tagged one_byte char code. |
3014 STATIC_ASSERT(kSmiTag == 0); | 3009 STATIC_ASSERT(kSmiTag == 0); |
3015 __ SmiScale(a4, code_, kPointerSizeLog2); | 3010 __ SmiScale(a4, code_, kPointerSizeLog2); |
3016 __ Daddu(result_, result_, a4); | 3011 __ Daddu(result_, result_, a4); |
3017 __ ld(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); | 3012 __ ld(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); |
3018 __ LoadRoot(a4, Heap::kUndefinedValueRootIndex); | 3013 __ LoadRoot(a4, Heap::kUndefinedValueRootIndex); |
3019 __ Branch(&slow_case_, eq, result_, Operand(a4)); | 3014 __ Branch(&slow_case_, eq, result_, Operand(a4)); |
3020 __ bind(&exit_); | 3015 __ bind(&exit_); |
3021 } | 3016 } |
3022 | 3017 |
3023 | 3018 |
3024 void StringCharFromCodeGenerator::GenerateSlow( | 3019 void StringCharFromCodeGenerator::GenerateSlow( |
3025 MacroAssembler* masm, | 3020 MacroAssembler* masm, |
3026 const RuntimeCallHelper& call_helper) { | 3021 const RuntimeCallHelper& call_helper) { |
3027 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); | 3022 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); |
3028 | 3023 |
3029 __ bind(&slow_case_); | 3024 __ bind(&slow_case_); |
3030 call_helper.BeforeCall(masm); | 3025 call_helper.BeforeCall(masm); |
3031 __ push(code_); | 3026 __ push(code_); |
3032 __ CallRuntime(Runtime::kCharFromCode, 1); | 3027 __ CallRuntime(Runtime::kCharFromCode, 1); |
3033 __ Move(result_, v0); | 3028 __ Move(result_, v0); |
3034 | 3029 |
3035 call_helper.AfterCall(masm); | 3030 call_helper.AfterCall(masm); |
3036 __ Branch(&exit_); | 3031 __ Branch(&exit_); |
3037 | 3032 |
3038 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); | 3033 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
3039 } | 3034 } |
3040 | 3035 |
3041 | 3036 |
3042 enum CopyCharactersFlags { | 3037 enum CopyCharactersFlags { COPY_ONE_BYTE = 1, DEST_ALWAYS_ALIGNED = 2 }; |
3043 COPY_ASCII = 1, | |
3044 DEST_ALWAYS_ALIGNED = 2 | |
3045 }; | |
3046 | 3038 |
3047 | 3039 |
3048 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, | 3040 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
3049 Register dest, | 3041 Register dest, |
3050 Register src, | 3042 Register src, |
3051 Register count, | 3043 Register count, |
3052 Register scratch, | 3044 Register scratch, |
3053 String::Encoding encoding) { | 3045 String::Encoding encoding) { |
3054 if (FLAG_debug_code) { | 3046 if (FLAG_debug_code) { |
3055 // Check that destination is word aligned. | 3047 // Check that destination is word aligned. |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3203 // Allocate new sliced string. At this point we do not reload the instance | 3195 // Allocate new sliced string. At this point we do not reload the instance |
3204 // type including the string encoding because we simply rely on the info | 3196 // type including the string encoding because we simply rely on the info |
3205 // provided by the original string. It does not matter if the original | 3197 // provided by the original string. It does not matter if the original |
3206 // string's encoding is wrong because we always have to recheck encoding of | 3198 // string's encoding is wrong because we always have to recheck encoding of |
3207 // the newly created string's parent anyways due to externalized strings. | 3199 // the newly created string's parent anyways due to externalized strings. |
3208 Label two_byte_slice, set_slice_header; | 3200 Label two_byte_slice, set_slice_header; |
3209 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); | 3201 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); |
3210 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); | 3202 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
3211 __ And(a4, a1, Operand(kStringEncodingMask)); | 3203 __ And(a4, a1, Operand(kStringEncodingMask)); |
3212 __ Branch(&two_byte_slice, eq, a4, Operand(zero_reg)); | 3204 __ Branch(&two_byte_slice, eq, a4, Operand(zero_reg)); |
3213 __ AllocateAsciiSlicedString(v0, a2, a6, a7, &runtime); | 3205 __ AllocateOneByteSlicedString(v0, a2, a6, a7, &runtime); |
3214 __ jmp(&set_slice_header); | 3206 __ jmp(&set_slice_header); |
3215 __ bind(&two_byte_slice); | 3207 __ bind(&two_byte_slice); |
3216 __ AllocateTwoByteSlicedString(v0, a2, a6, a7, &runtime); | 3208 __ AllocateTwoByteSlicedString(v0, a2, a6, a7, &runtime); |
3217 __ bind(&set_slice_header); | 3209 __ bind(&set_slice_header); |
3218 __ SmiTag(a3); | 3210 __ SmiTag(a3); |
3219 __ sd(a5, FieldMemOperand(v0, SlicedString::kParentOffset)); | 3211 __ sd(a5, FieldMemOperand(v0, SlicedString::kParentOffset)); |
3220 __ sd(a3, FieldMemOperand(v0, SlicedString::kOffsetOffset)); | 3212 __ sd(a3, FieldMemOperand(v0, SlicedString::kOffsetOffset)); |
3221 __ jmp(&return_v0); | 3213 __ jmp(&return_v0); |
3222 | 3214 |
3223 __ bind(©_routine); | 3215 __ bind(©_routine); |
(...skipping 22 matching lines...) Expand all Loading... |
3246 // Locate first character of underlying subject string. | 3238 // Locate first character of underlying subject string. |
3247 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 3239 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
3248 __ Daddu(a5, a5, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3240 __ Daddu(a5, a5, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3249 | 3241 |
3250 __ bind(&allocate_result); | 3242 __ bind(&allocate_result); |
3251 // Sequential acii string. Allocate the result. | 3243 // Sequential acii string. Allocate the result. |
3252 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 3244 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); |
3253 __ And(a4, a1, Operand(kStringEncodingMask)); | 3245 __ And(a4, a1, Operand(kStringEncodingMask)); |
3254 __ Branch(&two_byte_sequential, eq, a4, Operand(zero_reg)); | 3246 __ Branch(&two_byte_sequential, eq, a4, Operand(zero_reg)); |
3255 | 3247 |
3256 // Allocate and copy the resulting ASCII string. | 3248 // Allocate and copy the resulting one_byte string. |
3257 __ AllocateAsciiString(v0, a2, a4, a6, a7, &runtime); | 3249 __ AllocateOneByteString(v0, a2, a4, a6, a7, &runtime); |
3258 | 3250 |
3259 // Locate first character of substring to copy. | 3251 // Locate first character of substring to copy. |
3260 __ Daddu(a5, a5, a3); | 3252 __ Daddu(a5, a5, a3); |
3261 | 3253 |
3262 // Locate first character of result. | 3254 // Locate first character of result. |
3263 __ Daddu(a1, v0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3255 __ Daddu(a1, v0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3264 | 3256 |
3265 // v0: result string | 3257 // v0: result string |
3266 // a1: first character of result string | 3258 // a1: first character of result string |
3267 // a2: result string length | 3259 // a2: result string length |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3305 // a2: length | 3297 // a2: length |
3306 // a3: from index (untagged) | 3298 // a3: from index (untagged) |
3307 StringCharAtGenerator generator( | 3299 StringCharAtGenerator generator( |
3308 v0, a3, a2, v0, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); | 3300 v0, a3, a2, v0, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); |
3309 generator.GenerateFast(masm); | 3301 generator.GenerateFast(masm); |
3310 __ DropAndRet(3); | 3302 __ DropAndRet(3); |
3311 generator.SkipSlow(masm, &runtime); | 3303 generator.SkipSlow(masm, &runtime); |
3312 } | 3304 } |
3313 | 3305 |
3314 | 3306 |
3315 void StringHelper::GenerateFlatAsciiStringEquals(MacroAssembler* masm, | 3307 void StringHelper::GenerateFlatOneByteStringEquals( |
3316 Register left, Register right, | 3308 MacroAssembler* masm, Register left, Register right, Register scratch1, |
3317 Register scratch1, | 3309 Register scratch2, Register scratch3) { |
3318 Register scratch2, | |
3319 Register scratch3) { | |
3320 Register length = scratch1; | 3310 Register length = scratch1; |
3321 | 3311 |
3322 // Compare lengths. | 3312 // Compare lengths. |
3323 Label strings_not_equal, check_zero_length; | 3313 Label strings_not_equal, check_zero_length; |
3324 __ ld(length, FieldMemOperand(left, String::kLengthOffset)); | 3314 __ ld(length, FieldMemOperand(left, String::kLengthOffset)); |
3325 __ ld(scratch2, FieldMemOperand(right, String::kLengthOffset)); | 3315 __ ld(scratch2, FieldMemOperand(right, String::kLengthOffset)); |
3326 __ Branch(&check_zero_length, eq, length, Operand(scratch2)); | 3316 __ Branch(&check_zero_length, eq, length, Operand(scratch2)); |
3327 __ bind(&strings_not_equal); | 3317 __ bind(&strings_not_equal); |
3328 // Can not put li in delayslot, it has multi instructions. | 3318 // Can not put li in delayslot, it has multi instructions. |
3329 __ li(v0, Operand(Smi::FromInt(NOT_EQUAL))); | 3319 __ li(v0, Operand(Smi::FromInt(NOT_EQUAL))); |
3330 __ Ret(); | 3320 __ Ret(); |
3331 | 3321 |
3332 // Check if the length is zero. | 3322 // Check if the length is zero. |
3333 Label compare_chars; | 3323 Label compare_chars; |
3334 __ bind(&check_zero_length); | 3324 __ bind(&check_zero_length); |
3335 STATIC_ASSERT(kSmiTag == 0); | 3325 STATIC_ASSERT(kSmiTag == 0); |
3336 __ Branch(&compare_chars, ne, length, Operand(zero_reg)); | 3326 __ Branch(&compare_chars, ne, length, Operand(zero_reg)); |
3337 DCHECK(is_int16((intptr_t)Smi::FromInt(EQUAL))); | 3327 DCHECK(is_int16((intptr_t)Smi::FromInt(EQUAL))); |
3338 __ Ret(USE_DELAY_SLOT); | 3328 __ Ret(USE_DELAY_SLOT); |
3339 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3329 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3340 | 3330 |
3341 // Compare characters. | 3331 // Compare characters. |
3342 __ bind(&compare_chars); | 3332 __ bind(&compare_chars); |
3343 | 3333 |
3344 GenerateAsciiCharsCompareLoop(masm, | 3334 GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, scratch3, |
3345 left, right, length, scratch2, scratch3, v0, | 3335 v0, &strings_not_equal); |
3346 &strings_not_equal); | |
3347 | 3336 |
3348 // Characters are equal. | 3337 // Characters are equal. |
3349 __ Ret(USE_DELAY_SLOT); | 3338 __ Ret(USE_DELAY_SLOT); |
3350 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3339 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3351 } | 3340 } |
3352 | 3341 |
3353 | 3342 |
3354 void StringHelper::GenerateCompareFlatAsciiStrings( | 3343 void StringHelper::GenerateCompareFlatOneByteStrings( |
3355 MacroAssembler* masm, Register left, Register right, Register scratch1, | 3344 MacroAssembler* masm, Register left, Register right, Register scratch1, |
3356 Register scratch2, Register scratch3, Register scratch4) { | 3345 Register scratch2, Register scratch3, Register scratch4) { |
3357 Label result_not_equal, compare_lengths; | 3346 Label result_not_equal, compare_lengths; |
3358 // Find minimum length and length difference. | 3347 // Find minimum length and length difference. |
3359 __ ld(scratch1, FieldMemOperand(left, String::kLengthOffset)); | 3348 __ ld(scratch1, FieldMemOperand(left, String::kLengthOffset)); |
3360 __ ld(scratch2, FieldMemOperand(right, String::kLengthOffset)); | 3349 __ ld(scratch2, FieldMemOperand(right, String::kLengthOffset)); |
3361 __ Dsubu(scratch3, scratch1, Operand(scratch2)); | 3350 __ Dsubu(scratch3, scratch1, Operand(scratch2)); |
3362 Register length_delta = scratch3; | 3351 Register length_delta = scratch3; |
3363 __ slt(scratch4, scratch2, scratch1); | 3352 __ slt(scratch4, scratch2, scratch1); |
3364 __ Movn(scratch1, scratch2, scratch4); | 3353 __ Movn(scratch1, scratch2, scratch4); |
3365 Register min_length = scratch1; | 3354 Register min_length = scratch1; |
3366 STATIC_ASSERT(kSmiTag == 0); | 3355 STATIC_ASSERT(kSmiTag == 0); |
3367 __ Branch(&compare_lengths, eq, min_length, Operand(zero_reg)); | 3356 __ Branch(&compare_lengths, eq, min_length, Operand(zero_reg)); |
3368 | 3357 |
3369 // Compare loop. | 3358 // Compare loop. |
3370 GenerateAsciiCharsCompareLoop(masm, | 3359 GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2, |
3371 left, right, min_length, scratch2, scratch4, v0, | 3360 scratch4, v0, &result_not_equal); |
3372 &result_not_equal); | |
3373 | 3361 |
3374 // Compare lengths - strings up to min-length are equal. | 3362 // Compare lengths - strings up to min-length are equal. |
3375 __ bind(&compare_lengths); | 3363 __ bind(&compare_lengths); |
3376 DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); | 3364 DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); |
3377 // Use length_delta as result if it's zero. | 3365 // Use length_delta as result if it's zero. |
3378 __ mov(scratch2, length_delta); | 3366 __ mov(scratch2, length_delta); |
3379 __ mov(scratch4, zero_reg); | 3367 __ mov(scratch4, zero_reg); |
3380 __ mov(v0, zero_reg); | 3368 __ mov(v0, zero_reg); |
3381 | 3369 |
3382 __ bind(&result_not_equal); | 3370 __ bind(&result_not_equal); |
3383 // Conditionally update the result based either on length_delta or | 3371 // Conditionally update the result based either on length_delta or |
3384 // the last comparion performed in the loop above. | 3372 // the last comparion performed in the loop above. |
3385 Label ret; | 3373 Label ret; |
3386 __ Branch(&ret, eq, scratch2, Operand(scratch4)); | 3374 __ Branch(&ret, eq, scratch2, Operand(scratch4)); |
3387 __ li(v0, Operand(Smi::FromInt(GREATER))); | 3375 __ li(v0, Operand(Smi::FromInt(GREATER))); |
3388 __ Branch(&ret, gt, scratch2, Operand(scratch4)); | 3376 __ Branch(&ret, gt, scratch2, Operand(scratch4)); |
3389 __ li(v0, Operand(Smi::FromInt(LESS))); | 3377 __ li(v0, Operand(Smi::FromInt(LESS))); |
3390 __ bind(&ret); | 3378 __ bind(&ret); |
3391 __ Ret(); | 3379 __ Ret(); |
3392 } | 3380 } |
3393 | 3381 |
3394 | 3382 |
3395 void StringHelper::GenerateAsciiCharsCompareLoop( | 3383 void StringHelper::GenerateOneByteCharsCompareLoop( |
3396 MacroAssembler* masm, Register left, Register right, Register length, | 3384 MacroAssembler* masm, Register left, Register right, Register length, |
3397 Register scratch1, Register scratch2, Register scratch3, | 3385 Register scratch1, Register scratch2, Register scratch3, |
3398 Label* chars_not_equal) { | 3386 Label* chars_not_equal) { |
3399 // Change index to run from -length to -1 by adding length to string | 3387 // Change index to run from -length to -1 by adding length to string |
3400 // start. This means that loop ends when index reaches zero, which | 3388 // start. This means that loop ends when index reaches zero, which |
3401 // doesn't need an additional compare. | 3389 // doesn't need an additional compare. |
3402 __ SmiUntag(length); | 3390 __ SmiUntag(length); |
3403 __ Daddu(scratch1, length, | 3391 __ Daddu(scratch1, length, |
3404 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3392 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3405 __ Daddu(left, left, Operand(scratch1)); | 3393 __ Daddu(left, left, Operand(scratch1)); |
(...skipping 29 matching lines...) Expand all Loading... |
3435 Label not_same; | 3423 Label not_same; |
3436 __ Branch(¬_same, ne, a0, Operand(a1)); | 3424 __ Branch(¬_same, ne, a0, Operand(a1)); |
3437 STATIC_ASSERT(EQUAL == 0); | 3425 STATIC_ASSERT(EQUAL == 0); |
3438 STATIC_ASSERT(kSmiTag == 0); | 3426 STATIC_ASSERT(kSmiTag == 0); |
3439 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 3427 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
3440 __ IncrementCounter(counters->string_compare_native(), 1, a1, a2); | 3428 __ IncrementCounter(counters->string_compare_native(), 1, a1, a2); |
3441 __ DropAndRet(2); | 3429 __ DropAndRet(2); |
3442 | 3430 |
3443 __ bind(¬_same); | 3431 __ bind(¬_same); |
3444 | 3432 |
3445 // Check that both objects are sequential ASCII strings. | 3433 // Check that both objects are sequential one_byte strings. |
3446 __ JumpIfNotBothSequentialAsciiStrings(a1, a0, a2, a3, &runtime); | 3434 __ JumpIfNotBothSequentialOneByteStrings(a1, a0, a2, a3, &runtime); |
3447 | 3435 |
3448 // Compare flat ASCII strings natively. Remove arguments from stack first. | 3436 // Compare flat one_byte strings natively. Remove arguments from stack first. |
3449 __ IncrementCounter(counters->string_compare_native(), 1, a2, a3); | 3437 __ IncrementCounter(counters->string_compare_native(), 1, a2, a3); |
3450 __ Daddu(sp, sp, Operand(2 * kPointerSize)); | 3438 __ Daddu(sp, sp, Operand(2 * kPointerSize)); |
3451 StringHelper::GenerateCompareFlatAsciiStrings(masm, a1, a0, a2, a3, a4, a5); | 3439 StringHelper::GenerateCompareFlatOneByteStrings(masm, a1, a0, a2, a3, a4, a5); |
3452 | 3440 |
3453 __ bind(&runtime); | 3441 __ bind(&runtime); |
3454 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3442 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3455 } | 3443 } |
3456 | 3444 |
3457 | 3445 |
3458 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 3446 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
3459 // ----------- S t a t e ------------- | 3447 // ----------- S t a t e ------------- |
3460 // -- a1 : left | 3448 // -- a1 : left |
3461 // -- a0 : right | 3449 // -- a0 : right |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3734 Label is_symbol; | 3722 Label is_symbol; |
3735 __ Branch(&is_symbol, ne, tmp5, Operand(zero_reg)); | 3723 __ Branch(&is_symbol, ne, tmp5, Operand(zero_reg)); |
3736 // Make sure a0 is non-zero. At this point input operands are | 3724 // Make sure a0 is non-zero. At this point input operands are |
3737 // guaranteed to be non-zero. | 3725 // guaranteed to be non-zero. |
3738 DCHECK(right.is(a0)); | 3726 DCHECK(right.is(a0)); |
3739 __ Ret(USE_DELAY_SLOT); | 3727 __ Ret(USE_DELAY_SLOT); |
3740 __ mov(v0, a0); // In the delay slot. | 3728 __ mov(v0, a0); // In the delay slot. |
3741 __ bind(&is_symbol); | 3729 __ bind(&is_symbol); |
3742 } | 3730 } |
3743 | 3731 |
3744 // Check that both strings are sequential ASCII. | 3732 // Check that both strings are sequential one_byte. |
3745 Label runtime; | 3733 Label runtime; |
3746 __ JumpIfBothInstanceTypesAreNotSequentialAscii( | 3734 __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4, |
3747 tmp1, tmp2, tmp3, tmp4, &runtime); | 3735 &runtime); |
3748 | 3736 |
3749 // Compare flat ASCII strings. Returns when done. | 3737 // Compare flat one_byte strings. Returns when done. |
3750 if (equality) { | 3738 if (equality) { |
3751 StringHelper::GenerateFlatAsciiStringEquals(masm, left, right, tmp1, tmp2, | 3739 StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, tmp2, |
3752 tmp3); | 3740 tmp3); |
3753 } else { | 3741 } else { |
3754 StringHelper::GenerateCompareFlatAsciiStrings(masm, left, right, tmp1, tmp2, | 3742 StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1, |
3755 tmp3, tmp4); | 3743 tmp2, tmp3, tmp4); |
3756 } | 3744 } |
3757 | 3745 |
3758 // Handle more complex cases in runtime. | 3746 // Handle more complex cases in runtime. |
3759 __ bind(&runtime); | 3747 __ bind(&runtime); |
3760 __ Push(left, right); | 3748 __ Push(left, right); |
3761 if (equality) { | 3749 if (equality) { |
3762 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 3750 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); |
3763 } else { | 3751 } else { |
3764 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3752 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3765 } | 3753 } |
(...skipping 1135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4901 MemOperand(fp, 6 * kPointerSize), | 4889 MemOperand(fp, 6 * kPointerSize), |
4902 NULL); | 4890 NULL); |
4903 } | 4891 } |
4904 | 4892 |
4905 | 4893 |
4906 #undef __ | 4894 #undef __ |
4907 | 4895 |
4908 } } // namespace v8::internal | 4896 } } // namespace v8::internal |
4909 | 4897 |
4910 #endif // V8_TARGET_ARCH_MIPS64 | 4898 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |