| 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 |