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_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
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 1208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1219 // ecx: RegExp data (FixedArray) | 1219 // ecx: RegExp data (FixedArray) |
1220 // (6) One byte sequential. Load regexp code for one byte. | 1220 // (6) One byte sequential. Load regexp code for one byte. |
1221 __ bind(&seq_one_byte_string); | 1221 __ bind(&seq_one_byte_string); |
1222 // Load previous index and check range before edx is overwritten. We have | 1222 // Load previous index and check range before edx is overwritten. We have |
1223 // to use edx instead of eax here because it might have been only made to | 1223 // to use edx instead of eax here because it might have been only made to |
1224 // look like a sequential string when it actually is an external string. | 1224 // look like a sequential string when it actually is an external string. |
1225 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); | 1225 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); |
1226 __ JumpIfNotSmi(ebx, &runtime); | 1226 __ JumpIfNotSmi(ebx, &runtime); |
1227 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); | 1227 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); |
1228 __ j(above_equal, &runtime); | 1228 __ j(above_equal, &runtime); |
1229 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); | 1229 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataOneByteCodeOffset)); |
1230 __ Move(ecx, Immediate(1)); // Type is one byte. | 1230 __ Move(ecx, Immediate(1)); // Type is one byte. |
1231 | 1231 |
1232 // (E) Carry on. String handling is done. | 1232 // (E) Carry on. String handling is done. |
1233 __ bind(&check_code); | 1233 __ bind(&check_code); |
1234 // edx: irregexp code | 1234 // edx: irregexp code |
1235 // Check that the irregexp code has been generated for the actual string | 1235 // Check that the irregexp code has been generated for the actual string |
1236 // encoding. If it has, the field contains a code object otherwise it contains | 1236 // encoding. If it has, the field contains a code object otherwise it contains |
1237 // a smi (code flushing support). | 1237 // a smi (code flushing support). |
1238 __ JumpIfSmi(edx, &runtime); | 1238 __ JumpIfSmi(edx, &runtime); |
1239 | 1239 |
1240 // eax: subject string | 1240 // eax: subject string |
1241 // ebx: previous index (smi) | 1241 // ebx: previous index (smi) |
1242 // edx: code | 1242 // edx: code |
1243 // ecx: encoding of subject string (1 if ASCII, 0 if two_byte); | 1243 // ecx: encoding of subject string (1 if one_byte, 0 if two_byte); |
1244 // All checks done. Now push arguments for native regexp code. | 1244 // All checks done. Now push arguments for native regexp code. |
1245 Counters* counters = isolate()->counters(); | 1245 Counters* counters = isolate()->counters(); |
1246 __ IncrementCounter(counters->regexp_entry_native(), 1); | 1246 __ IncrementCounter(counters->regexp_entry_native(), 1); |
1247 | 1247 |
1248 // Isolates: note we add an additional parameter here (isolate pointer). | 1248 // Isolates: note we add an additional parameter here (isolate pointer). |
1249 static const int kRegExpExecuteArguments = 9; | 1249 static const int kRegExpExecuteArguments = 9; |
1250 __ EnterApiExitFrame(kRegExpExecuteArguments); | 1250 __ EnterApiExitFrame(kRegExpExecuteArguments); |
1251 | 1251 |
1252 // Argument 9: Pass current isolate address. | 1252 // Argument 9: Pass current isolate address. |
1253 __ mov(Operand(esp, 8 * kPointerSize), | 1253 __ mov(Operand(esp, 8 * kPointerSize), |
(...skipping 24 matching lines...) Expand all Loading... |
1278 // The original subject is in the previous stack frame. Therefore we have to | 1278 // The original subject is in the previous stack frame. Therefore we have to |
1279 // use ebp, which points exactly to one pointer size below the previous esp. | 1279 // use ebp, which points exactly to one pointer size below the previous esp. |
1280 // (Because creating a new stack frame pushes the previous ebp onto the stack | 1280 // (Because creating a new stack frame pushes the previous ebp onto the stack |
1281 // and thereby moves up esp by one kPointerSize.) | 1281 // and thereby moves up esp by one kPointerSize.) |
1282 __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize)); | 1282 __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize)); |
1283 __ mov(Operand(esp, 0 * kPointerSize), esi); | 1283 __ mov(Operand(esp, 0 * kPointerSize), esi); |
1284 | 1284 |
1285 // esi: original subject string | 1285 // esi: original subject string |
1286 // eax: underlying subject string | 1286 // eax: underlying subject string |
1287 // ebx: previous index | 1287 // ebx: previous index |
1288 // ecx: encoding of subject string (1 if ASCII 0 if two_byte); | 1288 // ecx: encoding of subject string (1 if one_byte 0 if two_byte); |
1289 // edx: code | 1289 // edx: code |
1290 // Argument 4: End of string data | 1290 // Argument 4: End of string data |
1291 // Argument 3: Start of string data | 1291 // Argument 3: Start of string data |
1292 // Prepare start and end index of the input. | 1292 // Prepare start and end index of the input. |
1293 // Load the length from the original sliced string if that is the case. | 1293 // Load the length from the original sliced string if that is the case. |
1294 __ mov(esi, FieldOperand(esi, String::kLengthOffset)); | 1294 __ mov(esi, FieldOperand(esi, String::kLengthOffset)); |
1295 __ add(esi, edi); // Calculate input end wrt offset. | 1295 __ add(esi, edi); // Calculate input end wrt offset. |
1296 __ SmiUntag(edi); | 1296 __ SmiUntag(edi); |
1297 __ add(ebx, edi); // Calculate input start wrt offset. | 1297 __ add(ebx, edi); // Calculate input start wrt offset. |
1298 | 1298 |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1724 BranchIfNotInternalizedString(masm, &check_for_strings, edx, ecx); | 1724 BranchIfNotInternalizedString(masm, &check_for_strings, edx, ecx); |
1725 | 1725 |
1726 // We've already checked for object identity, so if both operands | 1726 // We've already checked for object identity, so if both operands |
1727 // are internalized they aren't equal. Register eax already holds a | 1727 // are internalized they aren't equal. Register eax already holds a |
1728 // non-zero value, which indicates not equal, so just return. | 1728 // non-zero value, which indicates not equal, so just return. |
1729 __ ret(0); | 1729 __ ret(0); |
1730 } | 1730 } |
1731 | 1731 |
1732 __ bind(&check_for_strings); | 1732 __ bind(&check_for_strings); |
1733 | 1733 |
1734 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, | 1734 __ JumpIfNotBothSequentialOneByteStrings(edx, eax, ecx, ebx, |
1735 &check_unequal_objects); | 1735 &check_unequal_objects); |
1736 | 1736 |
1737 // Inline comparison of ASCII strings. | 1737 // Inline comparison of one-byte strings. |
1738 if (cc == equal) { | 1738 if (cc == equal) { |
1739 StringHelper::GenerateFlatAsciiStringEquals(masm, edx, eax, ecx, ebx); | 1739 StringHelper::GenerateFlatOneByteStringEquals(masm, edx, eax, ecx, ebx); |
1740 } else { | 1740 } else { |
1741 StringHelper::GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, | 1741 StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, |
1742 edi); | 1742 edi); |
1743 } | 1743 } |
1744 #ifdef DEBUG | 1744 #ifdef DEBUG |
1745 __ Abort(kUnexpectedFallThroughFromStringComparison); | 1745 __ Abort(kUnexpectedFallThroughFromStringComparison); |
1746 #endif | 1746 #endif |
1747 | 1747 |
1748 __ bind(&check_unequal_objects); | 1748 __ bind(&check_unequal_objects); |
1749 if (cc == equal && !strict()) { | 1749 if (cc == equal && !strict()) { |
1750 // Non-strict equality. Objects are unequal if | 1750 // Non-strict equality. Objects are unequal if |
1751 // they are both JSObjects and not undetectable, | 1751 // they are both JSObjects and not undetectable, |
1752 // and their pointers are different. | 1752 // and their pointers are different. |
(...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2807 __ test(code_, | 2807 __ test(code_, |
2808 Immediate(kSmiTagMask | | 2808 Immediate(kSmiTagMask | |
2809 ((~String::kMaxOneByteCharCode) << kSmiTagSize))); | 2809 ((~String::kMaxOneByteCharCode) << kSmiTagSize))); |
2810 __ j(not_zero, &slow_case_); | 2810 __ j(not_zero, &slow_case_); |
2811 | 2811 |
2812 Factory* factory = masm->isolate()->factory(); | 2812 Factory* factory = masm->isolate()->factory(); |
2813 __ Move(result_, Immediate(factory->single_character_string_cache())); | 2813 __ Move(result_, Immediate(factory->single_character_string_cache())); |
2814 STATIC_ASSERT(kSmiTag == 0); | 2814 STATIC_ASSERT(kSmiTag == 0); |
2815 STATIC_ASSERT(kSmiTagSize == 1); | 2815 STATIC_ASSERT(kSmiTagSize == 1); |
2816 STATIC_ASSERT(kSmiShiftSize == 0); | 2816 STATIC_ASSERT(kSmiShiftSize == 0); |
2817 // At this point code register contains smi tagged ASCII char code. | 2817 // At this point code register contains smi tagged one byte char code. |
2818 __ mov(result_, FieldOperand(result_, | 2818 __ mov(result_, FieldOperand(result_, |
2819 code_, times_half_pointer_size, | 2819 code_, times_half_pointer_size, |
2820 FixedArray::kHeaderSize)); | 2820 FixedArray::kHeaderSize)); |
2821 __ cmp(result_, factory->undefined_value()); | 2821 __ cmp(result_, factory->undefined_value()); |
2822 __ j(equal, &slow_case_); | 2822 __ j(equal, &slow_case_); |
2823 __ bind(&exit_); | 2823 __ bind(&exit_); |
2824 } | 2824 } |
2825 | 2825 |
2826 | 2826 |
2827 void StringCharFromCodeGenerator::GenerateSlow( | 2827 void StringCharFromCodeGenerator::GenerateSlow( |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2971 // Allocate new sliced string. At this point we do not reload the instance | 2971 // Allocate new sliced string. At this point we do not reload the instance |
2972 // type including the string encoding because we simply rely on the info | 2972 // type including the string encoding because we simply rely on the info |
2973 // provided by the original string. It does not matter if the original | 2973 // provided by the original string. It does not matter if the original |
2974 // string's encoding is wrong because we always have to recheck encoding of | 2974 // string's encoding is wrong because we always have to recheck encoding of |
2975 // the newly created string's parent anyways due to externalized strings. | 2975 // the newly created string's parent anyways due to externalized strings. |
2976 Label two_byte_slice, set_slice_header; | 2976 Label two_byte_slice, set_slice_header; |
2977 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); | 2977 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); |
2978 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); | 2978 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
2979 __ test(ebx, Immediate(kStringEncodingMask)); | 2979 __ test(ebx, Immediate(kStringEncodingMask)); |
2980 __ j(zero, &two_byte_slice, Label::kNear); | 2980 __ j(zero, &two_byte_slice, Label::kNear); |
2981 __ AllocateAsciiSlicedString(eax, ebx, no_reg, &runtime); | 2981 __ AllocateOneByteSlicedString(eax, ebx, no_reg, &runtime); |
2982 __ jmp(&set_slice_header, Label::kNear); | 2982 __ jmp(&set_slice_header, Label::kNear); |
2983 __ bind(&two_byte_slice); | 2983 __ bind(&two_byte_slice); |
2984 __ AllocateTwoByteSlicedString(eax, ebx, no_reg, &runtime); | 2984 __ AllocateTwoByteSlicedString(eax, ebx, no_reg, &runtime); |
2985 __ bind(&set_slice_header); | 2985 __ bind(&set_slice_header); |
2986 __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx); | 2986 __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx); |
2987 __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset), | 2987 __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset), |
2988 Immediate(String::kEmptyHashField)); | 2988 Immediate(String::kEmptyHashField)); |
2989 __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi); | 2989 __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi); |
2990 __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx); | 2990 __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx); |
2991 __ IncrementCounter(counters->sub_string_native(), 1); | 2991 __ IncrementCounter(counters->sub_string_native(), 1); |
(...skipping 26 matching lines...) Expand all Loading... |
3018 | 3018 |
3019 __ bind(&sequential_string); | 3019 __ bind(&sequential_string); |
3020 // Stash away (adjusted) index and (underlying) string. | 3020 // Stash away (adjusted) index and (underlying) string. |
3021 __ push(edx); | 3021 __ push(edx); |
3022 __ push(edi); | 3022 __ push(edi); |
3023 __ SmiUntag(ecx); | 3023 __ SmiUntag(ecx); |
3024 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 3024 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); |
3025 __ test_b(ebx, kStringEncodingMask); | 3025 __ test_b(ebx, kStringEncodingMask); |
3026 __ j(zero, &two_byte_sequential); | 3026 __ j(zero, &two_byte_sequential); |
3027 | 3027 |
3028 // Sequential ASCII string. Allocate the result. | 3028 // Sequential one byte string. Allocate the result. |
3029 __ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime_drop_two); | 3029 __ AllocateOneByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two); |
3030 | 3030 |
3031 // eax: result string | 3031 // eax: result string |
3032 // ecx: result string length | 3032 // ecx: result string length |
3033 // Locate first character of result. | 3033 // Locate first character of result. |
3034 __ mov(edi, eax); | 3034 __ mov(edi, eax); |
3035 __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3035 __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3036 // Load string argument and locate character of sub string start. | 3036 // Load string argument and locate character of sub string start. |
3037 __ pop(edx); | 3037 __ pop(edx); |
3038 __ pop(ebx); | 3038 __ pop(ebx); |
3039 __ SmiUntag(ebx); | 3039 __ SmiUntag(ebx); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3090 // ecx: sub string length (smi) | 3090 // ecx: sub string length (smi) |
3091 // edx: from index (smi) | 3091 // edx: from index (smi) |
3092 StringCharAtGenerator generator( | 3092 StringCharAtGenerator generator( |
3093 eax, edx, ecx, eax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); | 3093 eax, edx, ecx, eax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); |
3094 generator.GenerateFast(masm); | 3094 generator.GenerateFast(masm); |
3095 __ ret(3 * kPointerSize); | 3095 __ ret(3 * kPointerSize); |
3096 generator.SkipSlow(masm, &runtime); | 3096 generator.SkipSlow(masm, &runtime); |
3097 } | 3097 } |
3098 | 3098 |
3099 | 3099 |
3100 void StringHelper::GenerateFlatAsciiStringEquals(MacroAssembler* masm, | 3100 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, |
3101 Register left, Register right, | 3101 Register left, |
3102 Register scratch1, | 3102 Register right, |
3103 Register scratch2) { | 3103 Register scratch1, |
| 3104 Register scratch2) { |
3104 Register length = scratch1; | 3105 Register length = scratch1; |
3105 | 3106 |
3106 // Compare lengths. | 3107 // Compare lengths. |
3107 Label strings_not_equal, check_zero_length; | 3108 Label strings_not_equal, check_zero_length; |
3108 __ mov(length, FieldOperand(left, String::kLengthOffset)); | 3109 __ mov(length, FieldOperand(left, String::kLengthOffset)); |
3109 __ cmp(length, FieldOperand(right, String::kLengthOffset)); | 3110 __ cmp(length, FieldOperand(right, String::kLengthOffset)); |
3110 __ j(equal, &check_zero_length, Label::kNear); | 3111 __ j(equal, &check_zero_length, Label::kNear); |
3111 __ bind(&strings_not_equal); | 3112 __ bind(&strings_not_equal); |
3112 __ Move(eax, Immediate(Smi::FromInt(NOT_EQUAL))); | 3113 __ Move(eax, Immediate(Smi::FromInt(NOT_EQUAL))); |
3113 __ ret(0); | 3114 __ ret(0); |
3114 | 3115 |
3115 // Check if the length is zero. | 3116 // Check if the length is zero. |
3116 Label compare_chars; | 3117 Label compare_chars; |
3117 __ bind(&check_zero_length); | 3118 __ bind(&check_zero_length); |
3118 STATIC_ASSERT(kSmiTag == 0); | 3119 STATIC_ASSERT(kSmiTag == 0); |
3119 __ test(length, length); | 3120 __ test(length, length); |
3120 __ j(not_zero, &compare_chars, Label::kNear); | 3121 __ j(not_zero, &compare_chars, Label::kNear); |
3121 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3122 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
3122 __ ret(0); | 3123 __ ret(0); |
3123 | 3124 |
3124 // Compare characters. | 3125 // Compare characters. |
3125 __ bind(&compare_chars); | 3126 __ bind(&compare_chars); |
3126 GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2, | 3127 GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, |
3127 &strings_not_equal, Label::kNear); | 3128 &strings_not_equal, Label::kNear); |
3128 | 3129 |
3129 // Characters are equal. | 3130 // Characters are equal. |
3130 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3131 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
3131 __ ret(0); | 3132 __ ret(0); |
3132 } | 3133 } |
3133 | 3134 |
3134 | 3135 |
3135 void StringHelper::GenerateCompareFlatAsciiStrings( | 3136 void StringHelper::GenerateCompareFlatOneByteStrings( |
3136 MacroAssembler* masm, Register left, Register right, Register scratch1, | 3137 MacroAssembler* masm, Register left, Register right, Register scratch1, |
3137 Register scratch2, Register scratch3) { | 3138 Register scratch2, Register scratch3) { |
3138 Counters* counters = masm->isolate()->counters(); | 3139 Counters* counters = masm->isolate()->counters(); |
3139 __ IncrementCounter(counters->string_compare_native(), 1); | 3140 __ IncrementCounter(counters->string_compare_native(), 1); |
3140 | 3141 |
3141 // Find minimum length. | 3142 // Find minimum length. |
3142 Label left_shorter; | 3143 Label left_shorter; |
3143 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); | 3144 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); |
3144 __ mov(scratch3, scratch1); | 3145 __ mov(scratch3, scratch1); |
3145 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); | 3146 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); |
3146 | 3147 |
3147 Register length_delta = scratch3; | 3148 Register length_delta = scratch3; |
3148 | 3149 |
3149 __ j(less_equal, &left_shorter, Label::kNear); | 3150 __ j(less_equal, &left_shorter, Label::kNear); |
3150 // Right string is shorter. Change scratch1 to be length of right string. | 3151 // Right string is shorter. Change scratch1 to be length of right string. |
3151 __ sub(scratch1, length_delta); | 3152 __ sub(scratch1, length_delta); |
3152 __ bind(&left_shorter); | 3153 __ bind(&left_shorter); |
3153 | 3154 |
3154 Register min_length = scratch1; | 3155 Register min_length = scratch1; |
3155 | 3156 |
3156 // If either length is zero, just compare lengths. | 3157 // If either length is zero, just compare lengths. |
3157 Label compare_lengths; | 3158 Label compare_lengths; |
3158 __ test(min_length, min_length); | 3159 __ test(min_length, min_length); |
3159 __ j(zero, &compare_lengths, Label::kNear); | 3160 __ j(zero, &compare_lengths, Label::kNear); |
3160 | 3161 |
3161 // Compare characters. | 3162 // Compare characters. |
3162 Label result_not_equal; | 3163 Label result_not_equal; |
3163 GenerateAsciiCharsCompareLoop(masm, left, right, min_length, scratch2, | 3164 GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2, |
3164 &result_not_equal, Label::kNear); | 3165 &result_not_equal, Label::kNear); |
3165 | 3166 |
3166 // Compare lengths - strings up to min-length are equal. | 3167 // Compare lengths - strings up to min-length are equal. |
3167 __ bind(&compare_lengths); | 3168 __ bind(&compare_lengths); |
3168 __ test(length_delta, length_delta); | 3169 __ test(length_delta, length_delta); |
3169 Label length_not_equal; | 3170 Label length_not_equal; |
3170 __ j(not_zero, &length_not_equal, Label::kNear); | 3171 __ j(not_zero, &length_not_equal, Label::kNear); |
3171 | 3172 |
3172 // Result is EQUAL. | 3173 // Result is EQUAL. |
3173 STATIC_ASSERT(EQUAL == 0); | 3174 STATIC_ASSERT(EQUAL == 0); |
3174 STATIC_ASSERT(kSmiTag == 0); | 3175 STATIC_ASSERT(kSmiTag == 0); |
(...skipping 13 matching lines...) Expand all Loading... |
3188 __ Move(eax, Immediate(Smi::FromInt(LESS))); | 3189 __ Move(eax, Immediate(Smi::FromInt(LESS))); |
3189 __ ret(0); | 3190 __ ret(0); |
3190 | 3191 |
3191 // Result is GREATER. | 3192 // Result is GREATER. |
3192 __ bind(&result_greater); | 3193 __ bind(&result_greater); |
3193 __ Move(eax, Immediate(Smi::FromInt(GREATER))); | 3194 __ Move(eax, Immediate(Smi::FromInt(GREATER))); |
3194 __ ret(0); | 3195 __ ret(0); |
3195 } | 3196 } |
3196 | 3197 |
3197 | 3198 |
3198 void StringHelper::GenerateAsciiCharsCompareLoop( | 3199 void StringHelper::GenerateOneByteCharsCompareLoop( |
3199 MacroAssembler* masm, Register left, Register right, Register length, | 3200 MacroAssembler* masm, Register left, Register right, Register length, |
3200 Register scratch, Label* chars_not_equal, | 3201 Register scratch, Label* chars_not_equal, |
3201 Label::Distance chars_not_equal_near) { | 3202 Label::Distance chars_not_equal_near) { |
3202 // Change index to run from -length to -1 by adding length to string | 3203 // Change index to run from -length to -1 by adding length to string |
3203 // start. This means that loop ends when index reaches zero, which | 3204 // start. This means that loop ends when index reaches zero, which |
3204 // doesn't need an additional compare. | 3205 // doesn't need an additional compare. |
3205 __ SmiUntag(length); | 3206 __ SmiUntag(length); |
3206 __ lea(left, | 3207 __ lea(left, |
3207 FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize)); | 3208 FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize)); |
3208 __ lea(right, | 3209 __ lea(right, |
(...skipping 27 matching lines...) Expand all Loading... |
3236 __ cmp(edx, eax); | 3237 __ cmp(edx, eax); |
3237 __ j(not_equal, ¬_same, Label::kNear); | 3238 __ j(not_equal, ¬_same, Label::kNear); |
3238 STATIC_ASSERT(EQUAL == 0); | 3239 STATIC_ASSERT(EQUAL == 0); |
3239 STATIC_ASSERT(kSmiTag == 0); | 3240 STATIC_ASSERT(kSmiTag == 0); |
3240 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3241 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
3241 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1); | 3242 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1); |
3242 __ ret(2 * kPointerSize); | 3243 __ ret(2 * kPointerSize); |
3243 | 3244 |
3244 __ bind(¬_same); | 3245 __ bind(¬_same); |
3245 | 3246 |
3246 // Check that both objects are sequential ASCII strings. | 3247 // Check that both objects are sequential one-byte strings. |
3247 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); | 3248 __ JumpIfNotBothSequentialOneByteStrings(edx, eax, ecx, ebx, &runtime); |
3248 | 3249 |
3249 // Compare flat ASCII strings. | 3250 // Compare flat one-byte strings. |
3250 // Drop arguments from the stack. | 3251 // Drop arguments from the stack. |
3251 __ pop(ecx); | 3252 __ pop(ecx); |
3252 __ add(esp, Immediate(2 * kPointerSize)); | 3253 __ add(esp, Immediate(2 * kPointerSize)); |
3253 __ push(ecx); | 3254 __ push(ecx); |
3254 StringHelper::GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); | 3255 StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, |
| 3256 edi); |
3255 | 3257 |
3256 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 3258 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
3257 // tagged as a small integer. | 3259 // tagged as a small integer. |
3258 __ bind(&runtime); | 3260 __ bind(&runtime); |
3259 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3261 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3260 } | 3262 } |
3261 | 3263 |
3262 | 3264 |
3263 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 3265 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
3264 // ----------- S t a t e ------------- | 3266 // ----------- S t a t e ------------- |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3539 __ or_(tmp1, tmp2); | 3541 __ or_(tmp1, tmp2); |
3540 __ test(tmp1, Immediate(kIsNotInternalizedMask)); | 3542 __ test(tmp1, Immediate(kIsNotInternalizedMask)); |
3541 __ j(not_zero, &do_compare, Label::kNear); | 3543 __ j(not_zero, &do_compare, Label::kNear); |
3542 // Make sure eax is non-zero. At this point input operands are | 3544 // Make sure eax is non-zero. At this point input operands are |
3543 // guaranteed to be non-zero. | 3545 // guaranteed to be non-zero. |
3544 DCHECK(right.is(eax)); | 3546 DCHECK(right.is(eax)); |
3545 __ ret(0); | 3547 __ ret(0); |
3546 __ bind(&do_compare); | 3548 __ bind(&do_compare); |
3547 } | 3549 } |
3548 | 3550 |
3549 // Check that both strings are sequential ASCII. | 3551 // Check that both strings are sequential one-byte. |
3550 Label runtime; | 3552 Label runtime; |
3551 __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime); | 3553 __ JumpIfNotBothSequentialOneByteStrings(left, right, tmp1, tmp2, &runtime); |
3552 | 3554 |
3553 // Compare flat ASCII strings. Returns when done. | 3555 // Compare flat one byte strings. Returns when done. |
3554 if (equality) { | 3556 if (equality) { |
3555 StringHelper::GenerateFlatAsciiStringEquals(masm, left, right, tmp1, tmp2); | 3557 StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, |
| 3558 tmp2); |
3556 } else { | 3559 } else { |
3557 StringHelper::GenerateCompareFlatAsciiStrings(masm, left, right, tmp1, tmp2, | 3560 StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1, |
3558 tmp3); | 3561 tmp2, tmp3); |
3559 } | 3562 } |
3560 | 3563 |
3561 // Handle more complex cases in runtime. | 3564 // Handle more complex cases in runtime. |
3562 __ bind(&runtime); | 3565 __ bind(&runtime); |
3563 __ pop(tmp1); // Return address. | 3566 __ pop(tmp1); // Return address. |
3564 __ push(left); | 3567 __ push(left); |
3565 __ push(right); | 3568 __ push(right); |
3566 __ push(tmp1); | 3569 __ push(tmp1); |
3567 if (equality) { | 3570 if (equality) { |
3568 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 3571 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); |
(...skipping 1091 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4660 Operand(ebp, 7 * kPointerSize), | 4663 Operand(ebp, 7 * kPointerSize), |
4661 NULL); | 4664 NULL); |
4662 } | 4665 } |
4663 | 4666 |
4664 | 4667 |
4665 #undef __ | 4668 #undef __ |
4666 | 4669 |
4667 } } // namespace v8::internal | 4670 } } // namespace v8::internal |
4668 | 4671 |
4669 #endif // V8_TARGET_ARCH_IA32 | 4672 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |