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 |