| 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_X87 | 7 #if V8_TARGET_ARCH_X87 |
| 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 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 // ecx: RegExp data (FixedArray) | 892 // ecx: RegExp data (FixedArray) |
| 893 // (6) One byte sequential. Load regexp code for one byte. | 893 // (6) One byte sequential. Load regexp code for one byte. |
| 894 __ bind(&seq_one_byte_string); | 894 __ bind(&seq_one_byte_string); |
| 895 // Load previous index and check range before edx is overwritten. We have | 895 // Load previous index and check range before edx is overwritten. We have |
| 896 // to use edx instead of eax here because it might have been only made to | 896 // to use edx instead of eax here because it might have been only made to |
| 897 // look like a sequential string when it actually is an external string. | 897 // look like a sequential string when it actually is an external string. |
| 898 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); | 898 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); |
| 899 __ JumpIfNotSmi(ebx, &runtime); | 899 __ JumpIfNotSmi(ebx, &runtime); |
| 900 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); | 900 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); |
| 901 __ j(above_equal, &runtime); | 901 __ j(above_equal, &runtime); |
| 902 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); | 902 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataOneByteCodeOffset)); |
| 903 __ Move(ecx, Immediate(1)); // Type is one byte. | 903 __ Move(ecx, Immediate(1)); // Type is one byte. |
| 904 | 904 |
| 905 // (E) Carry on. String handling is done. | 905 // (E) Carry on. String handling is done. |
| 906 __ bind(&check_code); | 906 __ bind(&check_code); |
| 907 // edx: irregexp code | 907 // edx: irregexp code |
| 908 // Check that the irregexp code has been generated for the actual string | 908 // Check that the irregexp code has been generated for the actual string |
| 909 // encoding. If it has, the field contains a code object otherwise it contains | 909 // encoding. If it has, the field contains a code object otherwise it contains |
| 910 // a smi (code flushing support). | 910 // a smi (code flushing support). |
| 911 __ JumpIfSmi(edx, &runtime); | 911 __ JumpIfSmi(edx, &runtime); |
| 912 | 912 |
| 913 // eax: subject string | 913 // eax: subject string |
| 914 // ebx: previous index (smi) | 914 // ebx: previous index (smi) |
| 915 // edx: code | 915 // edx: code |
| 916 // ecx: encoding of subject string (1 if ASCII, 0 if two_byte); | 916 // ecx: encoding of subject string (1 if one_byte, 0 if two_byte); |
| 917 // All checks done. Now push arguments for native regexp code. | 917 // All checks done. Now push arguments for native regexp code. |
| 918 Counters* counters = isolate()->counters(); | 918 Counters* counters = isolate()->counters(); |
| 919 __ IncrementCounter(counters->regexp_entry_native(), 1); | 919 __ IncrementCounter(counters->regexp_entry_native(), 1); |
| 920 | 920 |
| 921 // Isolates: note we add an additional parameter here (isolate pointer). | 921 // Isolates: note we add an additional parameter here (isolate pointer). |
| 922 static const int kRegExpExecuteArguments = 9; | 922 static const int kRegExpExecuteArguments = 9; |
| 923 __ EnterApiExitFrame(kRegExpExecuteArguments); | 923 __ EnterApiExitFrame(kRegExpExecuteArguments); |
| 924 | 924 |
| 925 // Argument 9: Pass current isolate address. | 925 // Argument 9: Pass current isolate address. |
| 926 __ mov(Operand(esp, 8 * kPointerSize), | 926 __ mov(Operand(esp, 8 * kPointerSize), |
| (...skipping 24 matching lines...) Expand all Loading... |
| 951 // The original subject is in the previous stack frame. Therefore we have to | 951 // The original subject is in the previous stack frame. Therefore we have to |
| 952 // use ebp, which points exactly to one pointer size below the previous esp. | 952 // use ebp, which points exactly to one pointer size below the previous esp. |
| 953 // (Because creating a new stack frame pushes the previous ebp onto the stack | 953 // (Because creating a new stack frame pushes the previous ebp onto the stack |
| 954 // and thereby moves up esp by one kPointerSize.) | 954 // and thereby moves up esp by one kPointerSize.) |
| 955 __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize)); | 955 __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize)); |
| 956 __ mov(Operand(esp, 0 * kPointerSize), esi); | 956 __ mov(Operand(esp, 0 * kPointerSize), esi); |
| 957 | 957 |
| 958 // esi: original subject string | 958 // esi: original subject string |
| 959 // eax: underlying subject string | 959 // eax: underlying subject string |
| 960 // ebx: previous index | 960 // ebx: previous index |
| 961 // ecx: encoding of subject string (1 if ASCII 0 if two_byte); | 961 // ecx: encoding of subject string (1 if one_byte 0 if two_byte); |
| 962 // edx: code | 962 // edx: code |
| 963 // Argument 4: End of string data | 963 // Argument 4: End of string data |
| 964 // Argument 3: Start of string data | 964 // Argument 3: Start of string data |
| 965 // Prepare start and end index of the input. | 965 // Prepare start and end index of the input. |
| 966 // Load the length from the original sliced string if that is the case. | 966 // Load the length from the original sliced string if that is the case. |
| 967 __ mov(esi, FieldOperand(esi, String::kLengthOffset)); | 967 __ mov(esi, FieldOperand(esi, String::kLengthOffset)); |
| 968 __ add(esi, edi); // Calculate input end wrt offset. | 968 __ add(esi, edi); // Calculate input end wrt offset. |
| 969 __ SmiUntag(edi); | 969 __ SmiUntag(edi); |
| 970 __ add(ebx, edi); // Calculate input start wrt offset. | 970 __ add(ebx, edi); // Calculate input start wrt offset. |
| 971 | 971 |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1407 BranchIfNotInternalizedString(masm, &check_for_strings, edx, ecx); | 1407 BranchIfNotInternalizedString(masm, &check_for_strings, edx, ecx); |
| 1408 | 1408 |
| 1409 // We've already checked for object identity, so if both operands | 1409 // We've already checked for object identity, so if both operands |
| 1410 // are internalized they aren't equal. Register eax already holds a | 1410 // are internalized they aren't equal. Register eax already holds a |
| 1411 // non-zero value, which indicates not equal, so just return. | 1411 // non-zero value, which indicates not equal, so just return. |
| 1412 __ ret(0); | 1412 __ ret(0); |
| 1413 } | 1413 } |
| 1414 | 1414 |
| 1415 __ bind(&check_for_strings); | 1415 __ bind(&check_for_strings); |
| 1416 | 1416 |
| 1417 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, | 1417 __ JumpIfNotBothSequentialOneByteStrings(edx, eax, ecx, ebx, |
| 1418 &check_unequal_objects); | 1418 &check_unequal_objects); |
| 1419 | 1419 |
| 1420 // Inline comparison of ASCII strings. | 1420 // Inline comparison of one-byte strings. |
| 1421 if (cc == equal) { | 1421 if (cc == equal) { |
| 1422 StringHelper::GenerateFlatAsciiStringEquals(masm, edx, eax, ecx, ebx); | 1422 StringHelper::GenerateFlatOneByteStringEquals(masm, edx, eax, ecx, ebx); |
| 1423 } else { | 1423 } else { |
| 1424 StringHelper::GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, | 1424 StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, |
| 1425 edi); | 1425 edi); |
| 1426 } | 1426 } |
| 1427 #ifdef DEBUG | 1427 #ifdef DEBUG |
| 1428 __ Abort(kUnexpectedFallThroughFromStringComparison); | 1428 __ Abort(kUnexpectedFallThroughFromStringComparison); |
| 1429 #endif | 1429 #endif |
| 1430 | 1430 |
| 1431 __ bind(&check_unequal_objects); | 1431 __ bind(&check_unequal_objects); |
| 1432 if (cc == equal && !strict()) { | 1432 if (cc == equal && !strict()) { |
| 1433 // Non-strict equality. Objects are unequal if | 1433 // Non-strict equality. Objects are unequal if |
| 1434 // they are both JSObjects and not undetectable, | 1434 // they are both JSObjects and not undetectable, |
| 1435 // and their pointers are different. | 1435 // and their pointers are different. |
| (...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2487 __ test(code_, | 2487 __ test(code_, |
| 2488 Immediate(kSmiTagMask | | 2488 Immediate(kSmiTagMask | |
| 2489 ((~String::kMaxOneByteCharCode) << kSmiTagSize))); | 2489 ((~String::kMaxOneByteCharCode) << kSmiTagSize))); |
| 2490 __ j(not_zero, &slow_case_); | 2490 __ j(not_zero, &slow_case_); |
| 2491 | 2491 |
| 2492 Factory* factory = masm->isolate()->factory(); | 2492 Factory* factory = masm->isolate()->factory(); |
| 2493 __ Move(result_, Immediate(factory->single_character_string_cache())); | 2493 __ Move(result_, Immediate(factory->single_character_string_cache())); |
| 2494 STATIC_ASSERT(kSmiTag == 0); | 2494 STATIC_ASSERT(kSmiTag == 0); |
| 2495 STATIC_ASSERT(kSmiTagSize == 1); | 2495 STATIC_ASSERT(kSmiTagSize == 1); |
| 2496 STATIC_ASSERT(kSmiShiftSize == 0); | 2496 STATIC_ASSERT(kSmiShiftSize == 0); |
| 2497 // At this point code register contains smi tagged ASCII char code. | 2497 // At this point code register contains smi tagged one byte char code. |
| 2498 __ mov(result_, FieldOperand(result_, | 2498 __ mov(result_, FieldOperand(result_, |
| 2499 code_, times_half_pointer_size, | 2499 code_, times_half_pointer_size, |
| 2500 FixedArray::kHeaderSize)); | 2500 FixedArray::kHeaderSize)); |
| 2501 __ cmp(result_, factory->undefined_value()); | 2501 __ cmp(result_, factory->undefined_value()); |
| 2502 __ j(equal, &slow_case_); | 2502 __ j(equal, &slow_case_); |
| 2503 __ bind(&exit_); | 2503 __ bind(&exit_); |
| 2504 } | 2504 } |
| 2505 | 2505 |
| 2506 | 2506 |
| 2507 void StringCharFromCodeGenerator::GenerateSlow( | 2507 void StringCharFromCodeGenerator::GenerateSlow( |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2651 // Allocate new sliced string. At this point we do not reload the instance | 2651 // Allocate new sliced string. At this point we do not reload the instance |
| 2652 // type including the string encoding because we simply rely on the info | 2652 // type including the string encoding because we simply rely on the info |
| 2653 // provided by the original string. It does not matter if the original | 2653 // provided by the original string. It does not matter if the original |
| 2654 // string's encoding is wrong because we always have to recheck encoding of | 2654 // string's encoding is wrong because we always have to recheck encoding of |
| 2655 // the newly created string's parent anyways due to externalized strings. | 2655 // the newly created string's parent anyways due to externalized strings. |
| 2656 Label two_byte_slice, set_slice_header; | 2656 Label two_byte_slice, set_slice_header; |
| 2657 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); | 2657 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); |
| 2658 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); | 2658 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
| 2659 __ test(ebx, Immediate(kStringEncodingMask)); | 2659 __ test(ebx, Immediate(kStringEncodingMask)); |
| 2660 __ j(zero, &two_byte_slice, Label::kNear); | 2660 __ j(zero, &two_byte_slice, Label::kNear); |
| 2661 __ AllocateAsciiSlicedString(eax, ebx, no_reg, &runtime); | 2661 __ AllocateOneByteSlicedString(eax, ebx, no_reg, &runtime); |
| 2662 __ jmp(&set_slice_header, Label::kNear); | 2662 __ jmp(&set_slice_header, Label::kNear); |
| 2663 __ bind(&two_byte_slice); | 2663 __ bind(&two_byte_slice); |
| 2664 __ AllocateTwoByteSlicedString(eax, ebx, no_reg, &runtime); | 2664 __ AllocateTwoByteSlicedString(eax, ebx, no_reg, &runtime); |
| 2665 __ bind(&set_slice_header); | 2665 __ bind(&set_slice_header); |
| 2666 __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx); | 2666 __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx); |
| 2667 __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset), | 2667 __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset), |
| 2668 Immediate(String::kEmptyHashField)); | 2668 Immediate(String::kEmptyHashField)); |
| 2669 __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi); | 2669 __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi); |
| 2670 __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx); | 2670 __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx); |
| 2671 __ IncrementCounter(counters->sub_string_native(), 1); | 2671 __ IncrementCounter(counters->sub_string_native(), 1); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2698 | 2698 |
| 2699 __ bind(&sequential_string); | 2699 __ bind(&sequential_string); |
| 2700 // Stash away (adjusted) index and (underlying) string. | 2700 // Stash away (adjusted) index and (underlying) string. |
| 2701 __ push(edx); | 2701 __ push(edx); |
| 2702 __ push(edi); | 2702 __ push(edi); |
| 2703 __ SmiUntag(ecx); | 2703 __ SmiUntag(ecx); |
| 2704 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 2704 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); |
| 2705 __ test_b(ebx, kStringEncodingMask); | 2705 __ test_b(ebx, kStringEncodingMask); |
| 2706 __ j(zero, &two_byte_sequential); | 2706 __ j(zero, &two_byte_sequential); |
| 2707 | 2707 |
| 2708 // Sequential ASCII string. Allocate the result. | 2708 // Sequential one byte string. Allocate the result. |
| 2709 __ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime_drop_two); | 2709 __ AllocateOneByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two); |
| 2710 | 2710 |
| 2711 // eax: result string | 2711 // eax: result string |
| 2712 // ecx: result string length | 2712 // ecx: result string length |
| 2713 // Locate first character of result. | 2713 // Locate first character of result. |
| 2714 __ mov(edi, eax); | 2714 __ mov(edi, eax); |
| 2715 __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 2715 __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
| 2716 // Load string argument and locate character of sub string start. | 2716 // Load string argument and locate character of sub string start. |
| 2717 __ pop(edx); | 2717 __ pop(edx); |
| 2718 __ pop(ebx); | 2718 __ pop(ebx); |
| 2719 __ SmiUntag(ebx); | 2719 __ SmiUntag(ebx); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2770 // ecx: sub string length (smi) | 2770 // ecx: sub string length (smi) |
| 2771 // edx: from index (smi) | 2771 // edx: from index (smi) |
| 2772 StringCharAtGenerator generator( | 2772 StringCharAtGenerator generator( |
| 2773 eax, edx, ecx, eax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); | 2773 eax, edx, ecx, eax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); |
| 2774 generator.GenerateFast(masm); | 2774 generator.GenerateFast(masm); |
| 2775 __ ret(3 * kPointerSize); | 2775 __ ret(3 * kPointerSize); |
| 2776 generator.SkipSlow(masm, &runtime); | 2776 generator.SkipSlow(masm, &runtime); |
| 2777 } | 2777 } |
| 2778 | 2778 |
| 2779 | 2779 |
| 2780 void StringHelper::GenerateFlatAsciiStringEquals(MacroAssembler* masm, | 2780 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, |
| 2781 Register left, Register right, | 2781 Register left, |
| 2782 Register scratch1, | 2782 Register right, |
| 2783 Register scratch2) { | 2783 Register scratch1, |
| 2784 Register scratch2) { |
| 2784 Register length = scratch1; | 2785 Register length = scratch1; |
| 2785 | 2786 |
| 2786 // Compare lengths. | 2787 // Compare lengths. |
| 2787 Label strings_not_equal, check_zero_length; | 2788 Label strings_not_equal, check_zero_length; |
| 2788 __ mov(length, FieldOperand(left, String::kLengthOffset)); | 2789 __ mov(length, FieldOperand(left, String::kLengthOffset)); |
| 2789 __ cmp(length, FieldOperand(right, String::kLengthOffset)); | 2790 __ cmp(length, FieldOperand(right, String::kLengthOffset)); |
| 2790 __ j(equal, &check_zero_length, Label::kNear); | 2791 __ j(equal, &check_zero_length, Label::kNear); |
| 2791 __ bind(&strings_not_equal); | 2792 __ bind(&strings_not_equal); |
| 2792 __ Move(eax, Immediate(Smi::FromInt(NOT_EQUAL))); | 2793 __ Move(eax, Immediate(Smi::FromInt(NOT_EQUAL))); |
| 2793 __ ret(0); | 2794 __ ret(0); |
| 2794 | 2795 |
| 2795 // Check if the length is zero. | 2796 // Check if the length is zero. |
| 2796 Label compare_chars; | 2797 Label compare_chars; |
| 2797 __ bind(&check_zero_length); | 2798 __ bind(&check_zero_length); |
| 2798 STATIC_ASSERT(kSmiTag == 0); | 2799 STATIC_ASSERT(kSmiTag == 0); |
| 2799 __ test(length, length); | 2800 __ test(length, length); |
| 2800 __ j(not_zero, &compare_chars, Label::kNear); | 2801 __ j(not_zero, &compare_chars, Label::kNear); |
| 2801 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 2802 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
| 2802 __ ret(0); | 2803 __ ret(0); |
| 2803 | 2804 |
| 2804 // Compare characters. | 2805 // Compare characters. |
| 2805 __ bind(&compare_chars); | 2806 __ bind(&compare_chars); |
| 2806 GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2, | 2807 GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, |
| 2807 &strings_not_equal, Label::kNear); | 2808 &strings_not_equal, Label::kNear); |
| 2808 | 2809 |
| 2809 // Characters are equal. | 2810 // Characters are equal. |
| 2810 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 2811 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
| 2811 __ ret(0); | 2812 __ ret(0); |
| 2812 } | 2813 } |
| 2813 | 2814 |
| 2814 | 2815 |
| 2815 void StringHelper::GenerateCompareFlatAsciiStrings( | 2816 void StringHelper::GenerateCompareFlatOneByteStrings( |
| 2816 MacroAssembler* masm, Register left, Register right, Register scratch1, | 2817 MacroAssembler* masm, Register left, Register right, Register scratch1, |
| 2817 Register scratch2, Register scratch3) { | 2818 Register scratch2, Register scratch3) { |
| 2818 Counters* counters = masm->isolate()->counters(); | 2819 Counters* counters = masm->isolate()->counters(); |
| 2819 __ IncrementCounter(counters->string_compare_native(), 1); | 2820 __ IncrementCounter(counters->string_compare_native(), 1); |
| 2820 | 2821 |
| 2821 // Find minimum length. | 2822 // Find minimum length. |
| 2822 Label left_shorter; | 2823 Label left_shorter; |
| 2823 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); | 2824 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); |
| 2824 __ mov(scratch3, scratch1); | 2825 __ mov(scratch3, scratch1); |
| 2825 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); | 2826 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); |
| 2826 | 2827 |
| 2827 Register length_delta = scratch3; | 2828 Register length_delta = scratch3; |
| 2828 | 2829 |
| 2829 __ j(less_equal, &left_shorter, Label::kNear); | 2830 __ j(less_equal, &left_shorter, Label::kNear); |
| 2830 // Right string is shorter. Change scratch1 to be length of right string. | 2831 // Right string is shorter. Change scratch1 to be length of right string. |
| 2831 __ sub(scratch1, length_delta); | 2832 __ sub(scratch1, length_delta); |
| 2832 __ bind(&left_shorter); | 2833 __ bind(&left_shorter); |
| 2833 | 2834 |
| 2834 Register min_length = scratch1; | 2835 Register min_length = scratch1; |
| 2835 | 2836 |
| 2836 // If either length is zero, just compare lengths. | 2837 // If either length is zero, just compare lengths. |
| 2837 Label compare_lengths; | 2838 Label compare_lengths; |
| 2838 __ test(min_length, min_length); | 2839 __ test(min_length, min_length); |
| 2839 __ j(zero, &compare_lengths, Label::kNear); | 2840 __ j(zero, &compare_lengths, Label::kNear); |
| 2840 | 2841 |
| 2841 // Compare characters. | 2842 // Compare characters. |
| 2842 Label result_not_equal; | 2843 Label result_not_equal; |
| 2843 GenerateAsciiCharsCompareLoop(masm, left, right, min_length, scratch2, | 2844 GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2, |
| 2844 &result_not_equal, Label::kNear); | 2845 &result_not_equal, Label::kNear); |
| 2845 | 2846 |
| 2846 // Compare lengths - strings up to min-length are equal. | 2847 // Compare lengths - strings up to min-length are equal. |
| 2847 __ bind(&compare_lengths); | 2848 __ bind(&compare_lengths); |
| 2848 __ test(length_delta, length_delta); | 2849 __ test(length_delta, length_delta); |
| 2849 Label length_not_equal; | 2850 Label length_not_equal; |
| 2850 __ j(not_zero, &length_not_equal, Label::kNear); | 2851 __ j(not_zero, &length_not_equal, Label::kNear); |
| 2851 | 2852 |
| 2852 // Result is EQUAL. | 2853 // Result is EQUAL. |
| 2853 STATIC_ASSERT(EQUAL == 0); | 2854 STATIC_ASSERT(EQUAL == 0); |
| 2854 STATIC_ASSERT(kSmiTag == 0); | 2855 STATIC_ASSERT(kSmiTag == 0); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2868 __ Move(eax, Immediate(Smi::FromInt(LESS))); | 2869 __ Move(eax, Immediate(Smi::FromInt(LESS))); |
| 2869 __ ret(0); | 2870 __ ret(0); |
| 2870 | 2871 |
| 2871 // Result is GREATER. | 2872 // Result is GREATER. |
| 2872 __ bind(&result_greater); | 2873 __ bind(&result_greater); |
| 2873 __ Move(eax, Immediate(Smi::FromInt(GREATER))); | 2874 __ Move(eax, Immediate(Smi::FromInt(GREATER))); |
| 2874 __ ret(0); | 2875 __ ret(0); |
| 2875 } | 2876 } |
| 2876 | 2877 |
| 2877 | 2878 |
| 2878 void StringHelper::GenerateAsciiCharsCompareLoop( | 2879 void StringHelper::GenerateOneByteCharsCompareLoop( |
| 2879 MacroAssembler* masm, Register left, Register right, Register length, | 2880 MacroAssembler* masm, Register left, Register right, Register length, |
| 2880 Register scratch, Label* chars_not_equal, | 2881 Register scratch, Label* chars_not_equal, |
| 2881 Label::Distance chars_not_equal_near) { | 2882 Label::Distance chars_not_equal_near) { |
| 2882 // Change index to run from -length to -1 by adding length to string | 2883 // Change index to run from -length to -1 by adding length to string |
| 2883 // start. This means that loop ends when index reaches zero, which | 2884 // start. This means that loop ends when index reaches zero, which |
| 2884 // doesn't need an additional compare. | 2885 // doesn't need an additional compare. |
| 2885 __ SmiUntag(length); | 2886 __ SmiUntag(length); |
| 2886 __ lea(left, | 2887 __ lea(left, |
| 2887 FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize)); | 2888 FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize)); |
| 2888 __ lea(right, | 2889 __ lea(right, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2916 __ cmp(edx, eax); | 2917 __ cmp(edx, eax); |
| 2917 __ j(not_equal, ¬_same, Label::kNear); | 2918 __ j(not_equal, ¬_same, Label::kNear); |
| 2918 STATIC_ASSERT(EQUAL == 0); | 2919 STATIC_ASSERT(EQUAL == 0); |
| 2919 STATIC_ASSERT(kSmiTag == 0); | 2920 STATIC_ASSERT(kSmiTag == 0); |
| 2920 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 2921 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
| 2921 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1); | 2922 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1); |
| 2922 __ ret(2 * kPointerSize); | 2923 __ ret(2 * kPointerSize); |
| 2923 | 2924 |
| 2924 __ bind(¬_same); | 2925 __ bind(¬_same); |
| 2925 | 2926 |
| 2926 // Check that both objects are sequential ASCII strings. | 2927 // Check that both objects are sequential one-byte strings. |
| 2927 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); | 2928 __ JumpIfNotBothSequentialOneByteStrings(edx, eax, ecx, ebx, &runtime); |
| 2928 | 2929 |
| 2929 // Compare flat ASCII strings. | 2930 // Compare flat one-byte strings. |
| 2930 // Drop arguments from the stack. | 2931 // Drop arguments from the stack. |
| 2931 __ pop(ecx); | 2932 __ pop(ecx); |
| 2932 __ add(esp, Immediate(2 * kPointerSize)); | 2933 __ add(esp, Immediate(2 * kPointerSize)); |
| 2933 __ push(ecx); | 2934 __ push(ecx); |
| 2934 StringHelper::GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); | 2935 StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, |
| 2936 edi); |
| 2935 | 2937 |
| 2936 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 2938 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 2937 // tagged as a small integer. | 2939 // tagged as a small integer. |
| 2938 __ bind(&runtime); | 2940 __ bind(&runtime); |
| 2939 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 2941 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 2940 } | 2942 } |
| 2941 | 2943 |
| 2942 | 2944 |
| 2943 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 2945 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
| 2944 // ----------- S t a t e ------------- | 2946 // ----------- S t a t e ------------- |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3191 __ or_(tmp1, tmp2); | 3193 __ or_(tmp1, tmp2); |
| 3192 __ test(tmp1, Immediate(kIsNotInternalizedMask)); | 3194 __ test(tmp1, Immediate(kIsNotInternalizedMask)); |
| 3193 __ j(not_zero, &do_compare, Label::kNear); | 3195 __ j(not_zero, &do_compare, Label::kNear); |
| 3194 // Make sure eax is non-zero. At this point input operands are | 3196 // Make sure eax is non-zero. At this point input operands are |
| 3195 // guaranteed to be non-zero. | 3197 // guaranteed to be non-zero. |
| 3196 DCHECK(right.is(eax)); | 3198 DCHECK(right.is(eax)); |
| 3197 __ ret(0); | 3199 __ ret(0); |
| 3198 __ bind(&do_compare); | 3200 __ bind(&do_compare); |
| 3199 } | 3201 } |
| 3200 | 3202 |
| 3201 // Check that both strings are sequential ASCII. | 3203 // Check that both strings are sequential one-byte. |
| 3202 Label runtime; | 3204 Label runtime; |
| 3203 __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime); | 3205 __ JumpIfNotBothSequentialOneByteStrings(left, right, tmp1, tmp2, &runtime); |
| 3204 | 3206 |
| 3205 // Compare flat ASCII strings. Returns when done. | 3207 // Compare flat one byte strings. Returns when done. |
| 3206 if (equality) { | 3208 if (equality) { |
| 3207 StringHelper::GenerateFlatAsciiStringEquals(masm, left, right, tmp1, tmp2); | 3209 StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, |
| 3210 tmp2); |
| 3208 } else { | 3211 } else { |
| 3209 StringHelper::GenerateCompareFlatAsciiStrings(masm, left, right, tmp1, tmp2, | 3212 StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1, |
| 3210 tmp3); | 3213 tmp2, tmp3); |
| 3211 } | 3214 } |
| 3212 | 3215 |
| 3213 // Handle more complex cases in runtime. | 3216 // Handle more complex cases in runtime. |
| 3214 __ bind(&runtime); | 3217 __ bind(&runtime); |
| 3215 __ pop(tmp1); // Return address. | 3218 __ pop(tmp1); // Return address. |
| 3216 __ push(left); | 3219 __ push(left); |
| 3217 __ push(right); | 3220 __ push(right); |
| 3218 __ push(tmp1); | 3221 __ push(tmp1); |
| 3219 if (equality) { | 3222 if (equality) { |
| 3220 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 3223 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); |
| (...skipping 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4309 Operand(ebp, 7 * kPointerSize), | 4312 Operand(ebp, 7 * kPointerSize), |
| 4310 NULL); | 4313 NULL); |
| 4311 } | 4314 } |
| 4312 | 4315 |
| 4313 | 4316 |
| 4314 #undef __ | 4317 #undef __ |
| 4315 | 4318 |
| 4316 } } // namespace v8::internal | 4319 } } // namespace v8::internal |
| 4317 | 4320 |
| 4318 #endif // V8_TARGET_ARCH_X87 | 4321 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |