 Chromium Code Reviews
 Chromium Code Reviews Issue 542193003:
  MIPS: Rename ascii to one-byte where applicable.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 542193003:
  MIPS: Rename ascii to one-byte where applicable.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| 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 |