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