Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(370)

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 1857001: Revert "Changing string length field type from int to SMI." (Closed)
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/arm/stub-cache-arm.cc ('k') | src/ia32/macro-assembler-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 2675 matching lines...) Expand 10 before | Expand all | Expand 10 after
2686 is_string.Bind(&left_side); 2686 is_string.Bind(&left_side);
2687 // left_side is a sequential ASCII string. 2687 // left_side is a sequential ASCII string.
2688 left_side = Result(left_reg); 2688 left_side = Result(left_reg);
2689 right_side = Result(right_val); 2689 right_side = Result(right_val);
2690 Result temp2 = allocator_->Allocate(); 2690 Result temp2 = allocator_->Allocate();
2691 ASSERT(temp2.is_valid()); 2691 ASSERT(temp2.is_valid());
2692 // Test string equality and comparison. 2692 // Test string equality and comparison.
2693 if (cc == equal) { 2693 if (cc == equal) {
2694 Label comparison_done; 2694 Label comparison_done;
2695 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), 2695 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2696 Immediate(Smi::FromInt(1))); 2696 Immediate(1));
2697 __ j(not_equal, &comparison_done); 2697 __ j(not_equal, &comparison_done);
2698 uint8_t char_value = 2698 uint8_t char_value =
2699 static_cast<uint8_t>(String::cast(*right_val)->Get(0)); 2699 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
2700 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize), 2700 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
2701 char_value); 2701 char_value);
2702 __ bind(&comparison_done); 2702 __ bind(&comparison_done);
2703 } else { 2703 } else {
2704 __ mov(temp2.reg(), 2704 __ mov(temp2.reg(),
2705 FieldOperand(left_side.reg(), String::kLengthOffset)); 2705 FieldOperand(left_side.reg(), String::kLengthOffset));
2706 __ SmiUntag(temp2.reg());
2707 __ sub(Operand(temp2.reg()), Immediate(1)); 2706 __ sub(Operand(temp2.reg()), Immediate(1));
2708 Label comparison; 2707 Label comparison;
2709 // If the length is 0 then the subtraction gave -1 which compares less 2708 // If the length is 0 then the subtraction gave -1 which compares less
2710 // than any character. 2709 // than any character.
2711 __ j(negative, &comparison); 2710 __ j(negative, &comparison);
2712 // Otherwise load the first character. 2711 // Otherwise load the first character.
2713 __ movzx_b(temp2.reg(), 2712 __ movzx_b(temp2.reg(),
2714 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize)); 2713 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize));
2715 __ bind(&comparison); 2714 __ bind(&comparison);
2716 // Compare the first character of the string with the 2715 // Compare the first character of the string with the
2717 // constant 1-character string. 2716 // constant 1-character string.
2718 uint8_t char_value = 2717 uint8_t char_value =
2719 static_cast<uint8_t>(String::cast(*right_val)->Get(0)); 2718 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
2720 __ cmp(Operand(temp2.reg()), Immediate(char_value)); 2719 __ cmp(Operand(temp2.reg()), Immediate(char_value));
2721 Label characters_were_different; 2720 Label characters_were_different;
2722 __ j(not_equal, &characters_were_different); 2721 __ j(not_equal, &characters_were_different);
2723 // If the first character is the same then the long string sorts after 2722 // If the first character is the same then the long string sorts after
2724 // the short one. 2723 // the short one.
2725 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), 2724 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2726 Immediate(Smi::FromInt(1))); 2725 Immediate(1));
2727 __ bind(&characters_were_different); 2726 __ bind(&characters_were_different);
2728 } 2727 }
2729 temp2.Unuse(); 2728 temp2.Unuse();
2730 left_side.Unuse(); 2729 left_side.Unuse();
2731 right_side.Unuse(); 2730 right_side.Unuse();
2732 dest->Split(cc); 2731 dest->Split(cc);
2733 } 2732 }
2734 } else { 2733 } else {
2735 // Neither side is a constant Smi, constant 1-char string or constant null. 2734 // Neither side is a constant Smi, constant 1-char string or constant null.
2736 // If either side is a non-smi constant, or known to be a heap number skip 2735 // If either side is a non-smi constant, or known to be a heap number skip
(...skipping 6076 matching lines...) Expand 10 before | Expand all | Expand 10 after
8813 __ j(not_zero, &false_result); 8812 __ j(not_zero, &false_result);
8814 8813
8815 // JavaScript object => true. 8814 // JavaScript object => true.
8816 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 8815 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
8817 __ j(above_equal, &true_result); 8816 __ j(above_equal, &true_result);
8818 8817
8819 // String value => false iff empty. 8818 // String value => false iff empty.
8820 __ cmp(ecx, FIRST_NONSTRING_TYPE); 8819 __ cmp(ecx, FIRST_NONSTRING_TYPE);
8821 __ j(above_equal, &not_string); 8820 __ j(above_equal, &not_string);
8822 __ mov(edx, FieldOperand(eax, String::kLengthOffset)); 8821 __ mov(edx, FieldOperand(eax, String::kLengthOffset));
8823 ASSERT(kSmiTag == 0);
8824 __ test(edx, Operand(edx)); 8822 __ test(edx, Operand(edx));
8825 __ j(zero, &false_result); 8823 __ j(zero, &false_result);
8826 __ jmp(&true_result); 8824 __ jmp(&true_result);
8827 8825
8828 __ bind(&not_string); 8826 __ bind(&not_string);
8829 // HeapNumber => false iff +0, -0, or NaN. 8827 // HeapNumber => false iff +0, -0, or NaN.
8830 __ cmp(edx, Factory::heap_number_map()); 8828 __ cmp(edx, Factory::heap_number_map());
8831 __ j(not_equal, &true_result); 8829 __ j(not_equal, &true_result);
8832 __ fldz(); 8830 __ fldz();
8833 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 8831 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
(...skipping 1936 matching lines...) Expand 10 before | Expand all | Expand 10 after
10770 // edx: Number of capture registers 10768 // edx: Number of capture registers
10771 // Check that the second argument is a string. 10769 // Check that the second argument is a string.
10772 __ mov(eax, Operand(esp, kSubjectOffset)); 10770 __ mov(eax, Operand(esp, kSubjectOffset));
10773 __ test(eax, Immediate(kSmiTagMask)); 10771 __ test(eax, Immediate(kSmiTagMask));
10774 __ j(zero, &runtime); 10772 __ j(zero, &runtime);
10775 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); 10773 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx);
10776 __ j(NegateCondition(is_string), &runtime); 10774 __ j(NegateCondition(is_string), &runtime);
10777 // Get the length of the string to ebx. 10775 // Get the length of the string to ebx.
10778 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); 10776 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
10779 10777
10780 // ebx: Length of subject string as a smi 10778 // ebx: Length of subject string
10781 // ecx: RegExp data (FixedArray) 10779 // ecx: RegExp data (FixedArray)
10782 // edx: Number of capture registers 10780 // edx: Number of capture registers
10783 // Check that the third argument is a positive smi less than the subject 10781 // Check that the third argument is a positive smi less than the subject
10784 // string length. A negative value will be greater (unsigned comparison). 10782 // string length. A negative value will be greater (unsigned comparison).
10785 __ mov(eax, Operand(esp, kPreviousIndexOffset)); 10783 __ mov(eax, Operand(esp, kPreviousIndexOffset));
10786 __ test(eax, Immediate(kSmiTagMask)); 10784 __ SmiUntag(eax);
10787 __ j(zero, &runtime);
10788 __ cmp(eax, Operand(ebx)); 10785 __ cmp(eax, Operand(ebx));
10789 __ j(above_equal, &runtime); 10786 __ j(above, &runtime);
10790 10787
10791 // ecx: RegExp data (FixedArray) 10788 // ecx: RegExp data (FixedArray)
10792 // edx: Number of capture registers 10789 // edx: Number of capture registers
10793 // Check that the fourth object is a JSArray object. 10790 // Check that the fourth object is a JSArray object.
10794 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); 10791 __ mov(eax, Operand(esp, kLastMatchInfoOffset));
10795 __ test(eax, Immediate(kSmiTagMask)); 10792 __ test(eax, Immediate(kSmiTagMask));
10796 __ j(zero, &runtime); 10793 __ j(zero, &runtime);
10797 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); 10794 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
10798 __ j(not_equal, &runtime); 10795 __ j(not_equal, &runtime);
10799 // Check that the JSArray is in fast case. 10796 // Check that the JSArray is in fast case.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
10902 // Argument 5: static offsets vector buffer. 10899 // Argument 5: static offsets vector buffer.
10903 __ mov(Operand(esp, 4 * kPointerSize), 10900 __ mov(Operand(esp, 4 * kPointerSize),
10904 Immediate(ExternalReference::address_of_static_offsets_vector())); 10901 Immediate(ExternalReference::address_of_static_offsets_vector()));
10905 10902
10906 // Argument 4: End of string data 10903 // Argument 4: End of string data
10907 // Argument 3: Start of string data 10904 // Argument 3: Start of string data
10908 Label setup_two_byte, setup_rest; 10905 Label setup_two_byte, setup_rest;
10909 __ test(edi, Operand(edi)); 10906 __ test(edi, Operand(edi));
10910 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); 10907 __ mov(edi, FieldOperand(eax, String::kLengthOffset));
10911 __ j(zero, &setup_two_byte); 10908 __ j(zero, &setup_two_byte);
10912 __ SmiUntag(edi);
10913 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); 10909 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize));
10914 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. 10910 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4.
10915 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); 10911 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize));
10916 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. 10912 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3.
10917 __ jmp(&setup_rest); 10913 __ jmp(&setup_rest);
10918 10914
10919 __ bind(&setup_two_byte); 10915 __ bind(&setup_two_byte);
10920 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); // edi is smi (powered by 2). 10916 __ lea(ecx, FieldOperand(eax, edi, times_2, SeqTwoByteString::kHeaderSize));
10921 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqTwoByteString::kHeaderSize));
10922 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. 10917 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4.
10923 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); 10918 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize));
10924 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. 10919 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3.
10925 10920
10926 __ bind(&setup_rest); 10921 __ bind(&setup_rest);
10927 10922
10928 // Argument 2: Previous index. 10923 // Argument 2: Previous index.
10929 __ mov(Operand(esp, 1 * kPointerSize), ebx); 10924 __ mov(Operand(esp, 1 * kPointerSize), ebx);
10930 10925
10931 // Argument 1: Subject string. 10926 // Argument 1: Subject string.
(...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after
12074 // If the receiver is not a string trigger the non-string case. 12069 // If the receiver is not a string trigger the non-string case.
12075 __ test(result, Immediate(kIsNotStringMask)); 12070 __ test(result, Immediate(kIsNotStringMask));
12076 __ j(not_zero, receiver_not_string); 12071 __ j(not_zero, receiver_not_string);
12077 12072
12078 // If the index is negative or non-smi trigger the non-positive-smi 12073 // If the index is negative or non-smi trigger the non-positive-smi
12079 // case. 12074 // case.
12080 ASSERT(kSmiTag == 0); 12075 ASSERT(kSmiTag == 0);
12081 __ test(index, Immediate(kSmiTagMask | kSmiSignMask)); 12076 __ test(index, Immediate(kSmiTagMask | kSmiSignMask));
12082 __ j(not_zero, index_not_positive_smi); 12077 __ j(not_zero, index_not_positive_smi);
12083 12078
12079 // Put untagged index into scratch register.
12080 __ mov(scratch, index);
12081 __ SmiUntag(scratch);
12082
12084 // Check for index out of range. 12083 // Check for index out of range.
12085 __ cmp(index, FieldOperand(object, String::kLengthOffset)); 12084 __ cmp(scratch, FieldOperand(object, String::kLengthOffset));
12086 __ j(greater_equal, slow_case); 12085 __ j(greater_equal, slow_case);
12087 12086
12088 __ bind(&try_again_with_new_string); 12087 __ bind(&try_again_with_new_string);
12089 // ----------- S t a t e ------------- 12088 // ----------- S t a t e -------------
12090 // -- object : string to access 12089 // -- object : string to access
12091 // -- result : instance type of the string 12090 // -- result : instance type of the string
12092 // -- scratch : positive smi index < length 12091 // -- scratch : positive smi index < length
12093 // ----------------------------------- 12092 // -----------------------------------
12094 12093
12095 // We need special handling for non-flat strings. 12094 // We need special handling for non-flat strings.
12096 ASSERT(kSeqStringTag == 0); 12095 ASSERT(kSeqStringTag == 0);
12097 __ test(result, Immediate(kStringRepresentationMask)); 12096 __ test(result, Immediate(kStringRepresentationMask));
12098 __ j(not_zero, &not_a_flat_string); 12097 __ j(not_zero, &not_a_flat_string);
12099 12098
12100 // Check for 1-byte or 2-byte string. 12099 // Check for 1-byte or 2-byte string.
12101 ASSERT(kAsciiStringTag != 0); 12100 ASSERT(kAsciiStringTag != 0);
12102 __ test(result, Immediate(kStringEncodingMask)); 12101 __ test(result, Immediate(kStringEncodingMask));
12103 __ j(not_zero, &ascii_string); 12102 __ j(not_zero, &ascii_string);
12104 12103
12105 // 2-byte string. 12104 // 2-byte string.
12106 // Load the 2-byte character code into the temp register. 12105 // Load the 2-byte character code into the temp register.
12107 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); // index is smi (powered by 2).
12108 __ movzx_w(result, FieldOperand(object, 12106 __ movzx_w(result, FieldOperand(object,
12109 index, times_1, 12107 scratch, times_2,
12110 SeqTwoByteString::kHeaderSize)); 12108 SeqTwoByteString::kHeaderSize));
12111 __ jmp(&got_char_code); 12109 __ jmp(&got_char_code);
12112 12110
12113 // Handle non-flat strings. 12111 // Handle non-flat strings.
12114 __ bind(&not_a_flat_string); 12112 __ bind(&not_a_flat_string);
12115 __ and_(result, kStringRepresentationMask); 12113 __ and_(result, kStringRepresentationMask);
12116 __ cmp(result, kConsStringTag); 12114 __ cmp(result, kConsStringTag);
12117 __ j(not_equal, slow_case); 12115 __ j(not_equal, slow_case);
12118 12116
12119 // ConsString. 12117 // ConsString.
12120 // Check whether the right hand side is the empty string (i.e. if 12118 // Check whether the right hand side is the empty string (i.e. if
12121 // this is really a flat string in a cons string). If that is not 12119 // this is really a flat string in a cons string). If that is not
12122 // the case we would rather go to the runtime system now to flatten 12120 // the case we would rather go to the runtime system now to flatten
12123 // the string. 12121 // the string.
12124 __ mov(result, FieldOperand(object, ConsString::kSecondOffset)); 12122 __ mov(result, FieldOperand(object, ConsString::kSecondOffset));
12125 __ cmp(Operand(result), Factory::empty_string()); 12123 __ cmp(Operand(result), Factory::empty_string());
12126 __ j(not_equal, slow_case); 12124 __ j(not_equal, slow_case);
12127 // Get the first of the two strings and load its instance type. 12125 // Get the first of the two strings and load its instance type.
12128 __ mov(object, FieldOperand(object, ConsString::kFirstOffset)); 12126 __ mov(object, FieldOperand(object, ConsString::kFirstOffset));
12129 __ mov(result, FieldOperand(object, HeapObject::kMapOffset)); 12127 __ mov(result, FieldOperand(object, HeapObject::kMapOffset));
12130 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); 12128 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
12131 __ jmp(&try_again_with_new_string); 12129 __ jmp(&try_again_with_new_string);
12132 12130
12133 // ASCII string. 12131 // ASCII string.
12134 __ bind(&ascii_string); 12132 __ bind(&ascii_string);
12135 // Put untagged index into scratch register.
12136 __ mov(scratch, index);
12137 __ SmiUntag(scratch);
12138
12139 // Load the byte into the temp register. 12133 // Load the byte into the temp register.
12140 __ movzx_b(result, FieldOperand(object, 12134 __ movzx_b(result, FieldOperand(object,
12141 scratch, times_1, 12135 scratch, times_1,
12142 SeqAsciiString::kHeaderSize)); 12136 SeqAsciiString::kHeaderSize));
12143 __ bind(&got_char_code); 12137 __ bind(&got_char_code);
12144 __ SmiTag(result); 12138 __ SmiTag(result);
12145 } 12139 }
12146 12140
12147 12141
12148 void StringHelper::GenerateCharFromCode(MacroAssembler* masm, 12142 void StringHelper::GenerateCharFromCode(MacroAssembler* masm,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
12219 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); 12213 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx);
12220 __ j(above_equal, &string_add_runtime); 12214 __ j(above_equal, &string_add_runtime);
12221 } 12215 }
12222 12216
12223 // Both arguments are strings. 12217 // Both arguments are strings.
12224 // eax: first string 12218 // eax: first string
12225 // edx: second string 12219 // edx: second string
12226 // Check if either of the strings are empty. In that case return the other. 12220 // Check if either of the strings are empty. In that case return the other.
12227 Label second_not_zero_length, both_not_zero_length; 12221 Label second_not_zero_length, both_not_zero_length;
12228 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); 12222 __ mov(ecx, FieldOperand(edx, String::kLengthOffset));
12229 ASSERT(kSmiTag == 0);
12230 __ test(ecx, Operand(ecx)); 12223 __ test(ecx, Operand(ecx));
12231 __ j(not_zero, &second_not_zero_length); 12224 __ j(not_zero, &second_not_zero_length);
12232 // Second string is empty, result is first string which is already in eax. 12225 // Second string is empty, result is first string which is already in eax.
12233 __ IncrementCounter(&Counters::string_add_native, 1); 12226 __ IncrementCounter(&Counters::string_add_native, 1);
12234 __ ret(2 * kPointerSize); 12227 __ ret(2 * kPointerSize);
12235 __ bind(&second_not_zero_length); 12228 __ bind(&second_not_zero_length);
12236 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); 12229 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
12237 ASSERT(kSmiTag == 0);
12238 __ test(ebx, Operand(ebx)); 12230 __ test(ebx, Operand(ebx));
12239 __ j(not_zero, &both_not_zero_length); 12231 __ j(not_zero, &both_not_zero_length);
12240 // First string is empty, result is second string which is in edx. 12232 // First string is empty, result is second string which is in edx.
12241 __ mov(eax, edx); 12233 __ mov(eax, edx);
12242 __ IncrementCounter(&Counters::string_add_native, 1); 12234 __ IncrementCounter(&Counters::string_add_native, 1);
12243 __ ret(2 * kPointerSize); 12235 __ ret(2 * kPointerSize);
12244 12236
12245 // Both strings are non-empty. 12237 // Both strings are non-empty.
12246 // eax: first string 12238 // eax: first string
12247 // ebx: length of first string as a smi 12239 // ebx: length of first string
12248 // ecx: length of second string as a smi 12240 // ecx: length of second string
12249 // edx: second string 12241 // edx: second string
12250 // Look at the length of the result of adding the two strings. 12242 // Look at the length of the result of adding the two strings.
12251 Label string_add_flat_result, longer_than_two; 12243 Label string_add_flat_result, longer_than_two;
12252 __ bind(&both_not_zero_length); 12244 __ bind(&both_not_zero_length);
12253 __ add(ebx, Operand(ecx)); 12245 __ add(ebx, Operand(ecx));
12254 ASSERT(Smi::kMaxValue == String::kMaxLength);
12255 // Handle exceptionally long strings in the runtime system.
12256 __ j(overflow, &string_add_runtime);
12257 // Use the runtime system when adding two one character strings, as it 12246 // Use the runtime system when adding two one character strings, as it
12258 // contains optimizations for this specific case using the symbol table. 12247 // contains optimizations for this specific case using the symbol table.
12259 __ cmp(Operand(ebx), Immediate(Smi::FromInt(2))); 12248 __ cmp(ebx, 2);
12260 __ j(not_equal, &longer_than_two); 12249 __ j(not_equal, &longer_than_two);
12261 12250
12262 // Check that both strings are non-external ascii strings. 12251 // Check that both strings are non-external ascii strings.
12263 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, 12252 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx,
12264 &string_add_runtime); 12253 &string_add_runtime);
12265 12254
12266 // Get the two characters forming the sub string. 12255 // Get the two characters forming the sub string.
12267 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); 12256 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize));
12268 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); 12257 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize));
12269 12258
12270 // Try to lookup two character string in symbol table. If it is not found 12259 // Try to lookup two character string in symbol table. If it is not found
12271 // just allocate a new one. 12260 // just allocate a new one.
12272 Label make_two_character_string, make_flat_ascii_string; 12261 Label make_two_character_string, make_flat_ascii_string;
12273 StringHelper::GenerateTwoCharacterSymbolTableProbe( 12262 StringHelper::GenerateTwoCharacterSymbolTableProbe(
12274 masm, ebx, ecx, eax, edx, edi, &make_two_character_string); 12263 masm, ebx, ecx, eax, edx, edi, &make_two_character_string);
12275 __ IncrementCounter(&Counters::string_add_native, 1); 12264 __ IncrementCounter(&Counters::string_add_native, 1);
12276 __ ret(2 * kPointerSize); 12265 __ ret(2 * kPointerSize);
12277 12266
12278 __ bind(&make_two_character_string); 12267 __ bind(&make_two_character_string);
12279 __ Set(ebx, Immediate(Smi::FromInt(2))); 12268 __ Set(ebx, Immediate(2));
12280 __ jmp(&make_flat_ascii_string); 12269 __ jmp(&make_flat_ascii_string);
12281 12270
12282 __ bind(&longer_than_two); 12271 __ bind(&longer_than_two);
12283 // Check if resulting string will be flat. 12272 // Check if resulting string will be flat.
12284 __ cmp(Operand(ebx), Immediate(Smi::FromInt(String::kMinNonFlatLength))); 12273 __ cmp(ebx, String::kMinNonFlatLength);
12285 __ j(below, &string_add_flat_result); 12274 __ j(below, &string_add_flat_result);
12275 // Handle exceptionally long strings in the runtime system.
12276 ASSERT((String::kMaxLength & 0x80000000) == 0);
12277 __ cmp(ebx, String::kMaxLength);
12278 __ j(above, &string_add_runtime);
12286 12279
12287 // If result is not supposed to be flat allocate a cons string object. If both 12280 // If result is not supposed to be flat allocate a cons string object. If both
12288 // strings are ascii the result is an ascii cons string. 12281 // strings are ascii the result is an ascii cons string.
12289 Label non_ascii, allocated; 12282 Label non_ascii, allocated;
12290 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset)); 12283 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
12291 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset)); 12284 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
12292 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 12285 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
12293 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset)); 12286 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
12294 __ and_(ecx, Operand(edi)); 12287 __ and_(ecx, Operand(edi));
12295 ASSERT(kStringEncodingMask == kAsciiStringTag); 12288 ASSERT(kStringEncodingMask == kAsciiStringTag);
12296 __ test(ecx, Immediate(kAsciiStringTag)); 12289 __ test(ecx, Immediate(kAsciiStringTag));
12297 __ j(zero, &non_ascii); 12290 __ j(zero, &non_ascii);
12298 // Allocate an acsii cons string. 12291 // Allocate an acsii cons string.
12299 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime); 12292 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime);
12300 __ bind(&allocated); 12293 __ bind(&allocated);
12301 // Fill the fields of the cons string. 12294 // Fill the fields of the cons string.
12302 if (FLAG_debug_code) __ AbortIfNotSmi(ebx);
12303 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx); 12295 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx);
12304 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset), 12296 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset),
12305 Immediate(String::kEmptyHashField)); 12297 Immediate(String::kEmptyHashField));
12306 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax); 12298 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
12307 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx); 12299 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
12308 __ mov(eax, ecx); 12300 __ mov(eax, ecx);
12309 __ IncrementCounter(&Counters::string_add_native, 1); 12301 __ IncrementCounter(&Counters::string_add_native, 1);
12310 __ ret(2 * kPointerSize); 12302 __ ret(2 * kPointerSize);
12311 __ bind(&non_ascii); 12303 __ bind(&non_ascii);
12312 // Allocate a two byte cons string. 12304 // Allocate a two byte cons string.
12313 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime); 12305 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime);
12314 __ jmp(&allocated); 12306 __ jmp(&allocated);
12315 12307
12316 // Handle creating a flat result. First check that both strings are not 12308 // Handle creating a flat result. First check that both strings are not
12317 // external strings. 12309 // external strings.
12318 // eax: first string 12310 // eax: first string
12319 // ebx: length of resulting flat string as a smi 12311 // ebx: length of resulting flat string
12320 // edx: second string 12312 // edx: second string
12321 __ bind(&string_add_flat_result); 12313 __ bind(&string_add_flat_result);
12322 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 12314 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
12323 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12315 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12324 __ and_(ecx, kStringRepresentationMask); 12316 __ and_(ecx, kStringRepresentationMask);
12325 __ cmp(ecx, kExternalStringTag); 12317 __ cmp(ecx, kExternalStringTag);
12326 __ j(equal, &string_add_runtime); 12318 __ j(equal, &string_add_runtime);
12327 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12319 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12328 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12320 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12329 __ and_(ecx, kStringRepresentationMask); 12321 __ and_(ecx, kStringRepresentationMask);
12330 __ cmp(ecx, kExternalStringTag); 12322 __ cmp(ecx, kExternalStringTag);
12331 __ j(equal, &string_add_runtime); 12323 __ j(equal, &string_add_runtime);
12332 // Now check if both strings are ascii strings. 12324 // Now check if both strings are ascii strings.
12333 // eax: first string 12325 // eax: first string
12334 // ebx: length of resulting flat string as a smi 12326 // ebx: length of resulting flat string
12335 // edx: second string 12327 // edx: second string
12336 Label non_ascii_string_add_flat_result; 12328 Label non_ascii_string_add_flat_result;
12337 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 12329 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
12338 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12330 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12339 ASSERT(kStringEncodingMask == kAsciiStringTag); 12331 ASSERT(kStringEncodingMask == kAsciiStringTag);
12340 __ test(ecx, Immediate(kAsciiStringTag)); 12332 __ test(ecx, Immediate(kAsciiStringTag));
12341 __ j(zero, &non_ascii_string_add_flat_result); 12333 __ j(zero, &non_ascii_string_add_flat_result);
12342 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12334 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12343 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12335 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12344 __ test(ecx, Immediate(kAsciiStringTag)); 12336 __ test(ecx, Immediate(kAsciiStringTag));
12345 __ j(zero, &string_add_runtime); 12337 __ j(zero, &string_add_runtime);
12346 12338
12347 __ bind(&make_flat_ascii_string); 12339 __ bind(&make_flat_ascii_string);
12348 // Both strings are ascii strings. As they are short they are both flat. 12340 // Both strings are ascii strings. As they are short they are both flat.
12349 // ebx: length of resulting flat string as a smi 12341 // ebx: length of resulting flat string
12350 __ SmiUntag(ebx);
12351 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime); 12342 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime);
12352 // eax: result string 12343 // eax: result string
12353 __ mov(ecx, eax); 12344 __ mov(ecx, eax);
12354 // Locate first character of result. 12345 // Locate first character of result.
12355 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12346 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12356 // Load first argument and locate first character. 12347 // Load first argument and locate first character.
12357 __ mov(edx, Operand(esp, 2 * kPointerSize)); 12348 __ mov(edx, Operand(esp, 2 * kPointerSize));
12358 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12349 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12359 __ SmiUntag(edi);
12360 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12350 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12361 // eax: result string 12351 // eax: result string
12362 // ecx: first character of result 12352 // ecx: first character of result
12363 // edx: first char of first argument 12353 // edx: first char of first argument
12364 // edi: length of first argument 12354 // edi: length of first argument
12365 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 12355 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
12366 // Load second argument and locate first character. 12356 // Load second argument and locate first character.
12367 __ mov(edx, Operand(esp, 1 * kPointerSize)); 12357 __ mov(edx, Operand(esp, 1 * kPointerSize));
12368 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12358 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12369 __ SmiUntag(edi);
12370 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12359 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12371 // eax: result string 12360 // eax: result string
12372 // ecx: next character of result 12361 // ecx: next character of result
12373 // edx: first char of second argument 12362 // edx: first char of second argument
12374 // edi: length of second argument 12363 // edi: length of second argument
12375 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 12364 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
12376 __ IncrementCounter(&Counters::string_add_native, 1); 12365 __ IncrementCounter(&Counters::string_add_native, 1);
12377 __ ret(2 * kPointerSize); 12366 __ ret(2 * kPointerSize);
12378 12367
12379 // Handle creating a flat two byte result. 12368 // Handle creating a flat two byte result.
12380 // eax: first string - known to be two byte 12369 // eax: first string - known to be two byte
12381 // ebx: length of resulting flat string as a smi 12370 // ebx: length of resulting flat string
12382 // edx: second string 12371 // edx: second string
12383 __ bind(&non_ascii_string_add_flat_result); 12372 __ bind(&non_ascii_string_add_flat_result);
12384 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12373 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12385 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12374 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12386 __ and_(ecx, kAsciiStringTag); 12375 __ and_(ecx, kAsciiStringTag);
12387 __ j(not_zero, &string_add_runtime); 12376 __ j(not_zero, &string_add_runtime);
12388 // Both strings are two byte strings. As they are short they are both 12377 // Both strings are two byte strings. As they are short they are both
12389 // flat. 12378 // flat.
12390 __ SmiUntag(ebx);
12391 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime); 12379 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime);
12392 // eax: result string 12380 // eax: result string
12393 __ mov(ecx, eax); 12381 __ mov(ecx, eax);
12394 // Locate first character of result. 12382 // Locate first character of result.
12395 __ add(Operand(ecx), 12383 __ add(Operand(ecx),
12396 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 12384 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
12397 // Load first argument and locate first character. 12385 // Load first argument and locate first character.
12398 __ mov(edx, Operand(esp, 2 * kPointerSize)); 12386 __ mov(edx, Operand(esp, 2 * kPointerSize));
12399 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12387 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12400 __ SmiUntag(edi);
12401 __ add(Operand(edx), 12388 __ add(Operand(edx),
12402 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 12389 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
12403 // eax: result string 12390 // eax: result string
12404 // ecx: first character of result 12391 // ecx: first character of result
12405 // edx: first char of first argument 12392 // edx: first char of first argument
12406 // edi: length of first argument 12393 // edi: length of first argument
12407 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 12394 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
12408 // Load second argument and locate first character. 12395 // Load second argument and locate first character.
12409 __ mov(edx, Operand(esp, 1 * kPointerSize)); 12396 __ mov(edx, Operand(esp, 1 * kPointerSize));
12410 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12397 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12411 __ SmiUntag(edi);
12412 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12398 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12413 // eax: result string 12399 // eax: result string
12414 // ecx: next character of result 12400 // ecx: next character of result
12415 // edx: first char of second argument 12401 // edx: first char of second argument
12416 // edi: length of second argument 12402 // edi: length of second argument
12417 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 12403 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
12418 __ IncrementCounter(&Counters::string_add_native, 1); 12404 __ IncrementCounter(&Counters::string_add_native, 1);
12419 __ ret(2 * kPointerSize); 12405 __ ret(2 * kPointerSize);
12420 12406
12421 // Just jump to runtime to add the two strings. 12407 // Just jump to runtime to add the two strings.
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
12586 FieldOperand(symbol_table, 12572 FieldOperand(symbol_table,
12587 scratch, 12573 scratch,
12588 times_pointer_size, 12574 times_pointer_size,
12589 SymbolTable::kElementsStartOffset)); 12575 SymbolTable::kElementsStartOffset));
12590 12576
12591 // If entry is undefined no string with this hash can be found. 12577 // If entry is undefined no string with this hash can be found.
12592 __ cmp(candidate, Factory::undefined_value()); 12578 __ cmp(candidate, Factory::undefined_value());
12593 __ j(equal, not_found); 12579 __ j(equal, not_found);
12594 12580
12595 // If length is not 2 the string is not a candidate. 12581 // If length is not 2 the string is not a candidate.
12596 __ cmp(FieldOperand(candidate, String::kLengthOffset), 12582 __ cmp(FieldOperand(candidate, String::kLengthOffset), Immediate(2));
12597 Immediate(Smi::FromInt(2)));
12598 __ j(not_equal, &next_probe[i]); 12583 __ j(not_equal, &next_probe[i]);
12599 12584
12600 // As we are out of registers save the mask on the stack and use that 12585 // As we are out of registers save the mask on the stack and use that
12601 // register as a temporary. 12586 // register as a temporary.
12602 __ push(mask); 12587 __ push(mask);
12603 Register temp = mask; 12588 Register temp = mask;
12604 12589
12605 // Check that the candidate is a non-external ascii string. 12590 // Check that the candidate is a non-external ascii string.
12606 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset)); 12591 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset));
12607 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 12592 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
12856 12841
12857 Register min_length = scratch1; 12842 Register min_length = scratch1;
12858 12843
12859 // If either length is zero, just compare lengths. 12844 // If either length is zero, just compare lengths.
12860 __ test(min_length, Operand(min_length)); 12845 __ test(min_length, Operand(min_length));
12861 __ j(zero, &compare_lengths); 12846 __ j(zero, &compare_lengths);
12862 12847
12863 // Change index to run from -min_length to -1 by adding min_length 12848 // Change index to run from -min_length to -1 by adding min_length
12864 // to string start. This means that loop ends when index reaches zero, 12849 // to string start. This means that loop ends when index reaches zero,
12865 // which doesn't need an additional compare. 12850 // which doesn't need an additional compare.
12866 __ SmiUntag(min_length);
12867 __ lea(left, 12851 __ lea(left,
12868 FieldOperand(left, 12852 FieldOperand(left,
12869 min_length, times_1, 12853 min_length, times_1,
12870 SeqAsciiString::kHeaderSize)); 12854 SeqAsciiString::kHeaderSize));
12871 __ lea(right, 12855 __ lea(right,
12872 FieldOperand(right, 12856 FieldOperand(right,
12873 min_length, times_1, 12857 min_length, times_1,
12874 SeqAsciiString::kHeaderSize)); 12858 SeqAsciiString::kHeaderSize));
12875 __ neg(min_length); 12859 __ neg(min_length);
12876 12860
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
12943 12927
12944 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 12928 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
12945 // tagged as a small integer. 12929 // tagged as a small integer.
12946 __ bind(&runtime); 12930 __ bind(&runtime);
12947 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 12931 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
12948 } 12932 }
12949 12933
12950 #undef __ 12934 #undef __
12951 12935
12952 } } // namespace v8::internal 12936 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/stub-cache-arm.cc ('k') | src/ia32/macro-assembler-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698