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

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

Issue 1706013: Changing string length field type from int to SMI. It will make it be a regu... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
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 | Annotate | Revision Log
« 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 2676 matching lines...) Expand 10 before | Expand all | Expand 10 after
2687 is_string.Bind(&left_side); 2687 is_string.Bind(&left_side);
2688 // left_side is a sequential ASCII string. 2688 // left_side is a sequential ASCII string.
2689 left_side = Result(left_reg); 2689 left_side = Result(left_reg);
2690 right_side = Result(right_val); 2690 right_side = Result(right_val);
2691 Result temp2 = allocator_->Allocate(); 2691 Result temp2 = allocator_->Allocate();
2692 ASSERT(temp2.is_valid()); 2692 ASSERT(temp2.is_valid());
2693 // Test string equality and comparison. 2693 // Test string equality and comparison.
2694 if (cc == equal) { 2694 if (cc == equal) {
2695 Label comparison_done; 2695 Label comparison_done;
2696 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), 2696 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2697 Immediate(1)); 2697 Immediate(Smi::FromInt(1)));
2698 __ j(not_equal, &comparison_done); 2698 __ j(not_equal, &comparison_done);
2699 uint8_t char_value = 2699 uint8_t char_value =
2700 static_cast<uint8_t>(String::cast(*right_val)->Get(0)); 2700 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
2701 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize), 2701 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
2702 char_value); 2702 char_value);
2703 __ bind(&comparison_done); 2703 __ bind(&comparison_done);
2704 } else { 2704 } else {
2705 __ mov(temp2.reg(), 2705 __ mov(temp2.reg(),
2706 FieldOperand(left_side.reg(), String::kLengthOffset)); 2706 FieldOperand(left_side.reg(), String::kLengthOffset));
2707 __ SmiUntag(temp2.reg());
2707 __ sub(Operand(temp2.reg()), Immediate(1)); 2708 __ sub(Operand(temp2.reg()), Immediate(1));
2708 Label comparison; 2709 Label comparison;
2709 // If the length is 0 then the subtraction gave -1 which compares less 2710 // If the length is 0 then the subtraction gave -1 which compares less
2710 // than any character. 2711 // than any character.
2711 __ j(negative, &comparison); 2712 __ j(negative, &comparison);
2712 // Otherwise load the first character. 2713 // Otherwise load the first character.
2713 __ movzx_b(temp2.reg(), 2714 __ movzx_b(temp2.reg(),
2714 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize)); 2715 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize));
2715 __ bind(&comparison); 2716 __ bind(&comparison);
2716 // Compare the first character of the string with the 2717 // Compare the first character of the string with the
2717 // constant 1-character string. 2718 // constant 1-character string.
2718 uint8_t char_value = 2719 uint8_t char_value =
2719 static_cast<uint8_t>(String::cast(*right_val)->Get(0)); 2720 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
2720 __ cmp(Operand(temp2.reg()), Immediate(char_value)); 2721 __ cmp(Operand(temp2.reg()), Immediate(char_value));
2721 Label characters_were_different; 2722 Label characters_were_different;
2722 __ j(not_equal, &characters_were_different); 2723 __ j(not_equal, &characters_were_different);
2723 // If the first character is the same then the long string sorts after 2724 // If the first character is the same then the long string sorts after
2724 // the short one. 2725 // the short one.
2725 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), 2726 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2726 Immediate(1)); 2727 Immediate(Smi::FromInt(1)));
2727 __ bind(&characters_were_different); 2728 __ bind(&characters_were_different);
2728 } 2729 }
2729 temp2.Unuse(); 2730 temp2.Unuse();
2730 left_side.Unuse(); 2731 left_side.Unuse();
2731 right_side.Unuse(); 2732 right_side.Unuse();
2732 dest->Split(cc); 2733 dest->Split(cc);
2733 } 2734 }
2734 } else { 2735 } else {
2735 // Neither side is a constant Smi, constant 1-char string or constant null. 2736 // 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 2737 // If either side is a non-smi constant, or known to be a heap number skip
(...skipping 6196 matching lines...) Expand 10 before | Expand all | Expand 10 after
8933 __ j(not_zero, &false_result); 8934 __ j(not_zero, &false_result);
8934 8935
8935 // JavaScript object => true. 8936 // JavaScript object => true.
8936 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 8937 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
8937 __ j(above_equal, &true_result); 8938 __ j(above_equal, &true_result);
8938 8939
8939 // String value => false iff empty. 8940 // String value => false iff empty.
8940 __ cmp(ecx, FIRST_NONSTRING_TYPE); 8941 __ cmp(ecx, FIRST_NONSTRING_TYPE);
8941 __ j(above_equal, &not_string); 8942 __ j(above_equal, &not_string);
8942 __ mov(edx, FieldOperand(eax, String::kLengthOffset)); 8943 __ mov(edx, FieldOperand(eax, String::kLengthOffset));
8944 ASSERT(kSmiTag == 0);
8943 __ test(edx, Operand(edx)); 8945 __ test(edx, Operand(edx));
8944 __ j(zero, &false_result); 8946 __ j(zero, &false_result);
8945 __ jmp(&true_result); 8947 __ jmp(&true_result);
8946 8948
8947 __ bind(&not_string); 8949 __ bind(&not_string);
8948 // HeapNumber => false iff +0, -0, or NaN. 8950 // HeapNumber => false iff +0, -0, or NaN.
8949 __ cmp(edx, Factory::heap_number_map()); 8951 __ cmp(edx, Factory::heap_number_map());
8950 __ j(not_equal, &true_result); 8952 __ j(not_equal, &true_result);
8951 __ fldz(); 8953 __ fldz();
8952 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 8954 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
(...skipping 1936 matching lines...) Expand 10 before | Expand all | Expand 10 after
10889 // edx: Number of capture registers 10891 // edx: Number of capture registers
10890 // Check that the second argument is a string. 10892 // Check that the second argument is a string.
10891 __ mov(eax, Operand(esp, kSubjectOffset)); 10893 __ mov(eax, Operand(esp, kSubjectOffset));
10892 __ test(eax, Immediate(kSmiTagMask)); 10894 __ test(eax, Immediate(kSmiTagMask));
10893 __ j(zero, &runtime); 10895 __ j(zero, &runtime);
10894 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); 10896 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx);
10895 __ j(NegateCondition(is_string), &runtime); 10897 __ j(NegateCondition(is_string), &runtime);
10896 // Get the length of the string to ebx. 10898 // Get the length of the string to ebx.
10897 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); 10899 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
10898 10900
10899 // ebx: Length of subject string 10901 // ebx: Length of subject string as a smi
10900 // ecx: RegExp data (FixedArray) 10902 // ecx: RegExp data (FixedArray)
10901 // edx: Number of capture registers 10903 // edx: Number of capture registers
10902 // Check that the third argument is a positive smi less than the subject 10904 // Check that the third argument is a positive smi less than the subject
10903 // string length. A negative value will be greater (unsigned comparison). 10905 // string length. A negative value will be greater (unsigned comparison).
10904 __ mov(eax, Operand(esp, kPreviousIndexOffset)); 10906 __ mov(eax, Operand(esp, kPreviousIndexOffset));
10905 __ SmiUntag(eax); 10907 __ test(eax, Immediate(kSmiTagMask));
10908 __ j(zero, &runtime);
10906 __ cmp(eax, Operand(ebx)); 10909 __ cmp(eax, Operand(ebx));
10907 __ j(above, &runtime); 10910 __ j(above_equal, &runtime);
10908 10911
10909 // ecx: RegExp data (FixedArray) 10912 // ecx: RegExp data (FixedArray)
10910 // edx: Number of capture registers 10913 // edx: Number of capture registers
10911 // Check that the fourth object is a JSArray object. 10914 // Check that the fourth object is a JSArray object.
10912 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); 10915 __ mov(eax, Operand(esp, kLastMatchInfoOffset));
10913 __ test(eax, Immediate(kSmiTagMask)); 10916 __ test(eax, Immediate(kSmiTagMask));
10914 __ j(zero, &runtime); 10917 __ j(zero, &runtime);
10915 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); 10918 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
10916 __ j(not_equal, &runtime); 10919 __ j(not_equal, &runtime);
10917 // Check that the JSArray is in fast case. 10920 // Check that the JSArray is in fast case.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
11020 // Argument 5: static offsets vector buffer. 11023 // Argument 5: static offsets vector buffer.
11021 __ mov(Operand(esp, 4 * kPointerSize), 11024 __ mov(Operand(esp, 4 * kPointerSize),
11022 Immediate(ExternalReference::address_of_static_offsets_vector())); 11025 Immediate(ExternalReference::address_of_static_offsets_vector()));
11023 11026
11024 // Argument 4: End of string data 11027 // Argument 4: End of string data
11025 // Argument 3: Start of string data 11028 // Argument 3: Start of string data
11026 Label setup_two_byte, setup_rest; 11029 Label setup_two_byte, setup_rest;
11027 __ test(edi, Operand(edi)); 11030 __ test(edi, Operand(edi));
11028 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); 11031 __ mov(edi, FieldOperand(eax, String::kLengthOffset));
11029 __ j(zero, &setup_two_byte); 11032 __ j(zero, &setup_two_byte);
11033 __ SmiUntag(edi);
11030 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); 11034 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize));
11031 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. 11035 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4.
11032 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); 11036 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize));
11033 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. 11037 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3.
11034 __ jmp(&setup_rest); 11038 __ jmp(&setup_rest);
11035 11039
11036 __ bind(&setup_two_byte); 11040 __ bind(&setup_two_byte);
11037 __ lea(ecx, FieldOperand(eax, edi, times_2, SeqTwoByteString::kHeaderSize)); 11041 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); // edi is smi (powered by 2).
11042 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqTwoByteString::kHeaderSize));
11038 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. 11043 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4.
11039 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); 11044 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize));
11040 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. 11045 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3.
11041 11046
11042 __ bind(&setup_rest); 11047 __ bind(&setup_rest);
11043 11048
11044 // Argument 2: Previous index. 11049 // Argument 2: Previous index.
11045 __ mov(Operand(esp, 1 * kPointerSize), ebx); 11050 __ mov(Operand(esp, 1 * kPointerSize), ebx);
11046 11051
11047 // Argument 1: Subject string. 11052 // Argument 1: Subject string.
(...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after
12190 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); 12195 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
12191 // If the receiver is not a string trigger the non-string case. 12196 // If the receiver is not a string trigger the non-string case.
12192 __ test(result, Immediate(kIsNotStringMask)); 12197 __ test(result, Immediate(kIsNotStringMask));
12193 __ j(not_zero, receiver_not_string); 12198 __ j(not_zero, receiver_not_string);
12194 12199
12195 // If the index is non-smi trigger the non-smi case. 12200 // If the index is non-smi trigger the non-smi case.
12196 ASSERT(kSmiTag == 0); 12201 ASSERT(kSmiTag == 0);
12197 __ test(index, Immediate(kSmiTagMask)); 12202 __ test(index, Immediate(kSmiTagMask));
12198 __ j(not_zero, index_not_smi); 12203 __ j(not_zero, index_not_smi);
12199 12204
12200 // Put untagged index into scratch register.
12201 __ mov(scratch, index);
12202 __ SmiUntag(scratch);
12203
12204 // Check for index out of range. 12205 // Check for index out of range.
12205 __ cmp(scratch, FieldOperand(object, String::kLengthOffset)); 12206 __ cmp(index, FieldOperand(object, String::kLengthOffset));
12206 __ j(above_equal, index_out_of_range); 12207 __ j(above_equal, index_out_of_range);
12207 12208
12208 __ bind(&try_again_with_new_string); 12209 __ bind(&try_again_with_new_string);
12209 // ----------- S t a t e ------------- 12210 // ----------- S t a t e -------------
12210 // -- object : string to access 12211 // -- object : string to access
12211 // -- result : instance type of the string 12212 // -- result : instance type of the string
12212 // -- scratch : non-negative index < length 12213 // -- scratch : non-negative index < length
12213 // ----------------------------------- 12214 // -----------------------------------
12214 12215
12215 // We need special handling for non-flat strings. 12216 // We need special handling for non-flat strings.
12216 ASSERT(kSeqStringTag == 0); 12217 ASSERT(kSeqStringTag == 0);
12217 __ test(result, Immediate(kStringRepresentationMask)); 12218 __ test(result, Immediate(kStringRepresentationMask));
12218 __ j(not_zero, &not_a_flat_string); 12219 __ j(not_zero, &not_a_flat_string);
12219 12220
12220 // Check for 1-byte or 2-byte string. 12221 // Check for 1-byte or 2-byte string.
12221 ASSERT(kAsciiStringTag != 0); 12222 ASSERT(kAsciiStringTag != 0);
12222 __ test(result, Immediate(kStringEncodingMask)); 12223 __ test(result, Immediate(kStringEncodingMask));
12223 __ j(not_zero, &ascii_string); 12224 __ j(not_zero, &ascii_string);
12224 12225
12225 // 2-byte string. 12226 // 2-byte string.
12226 // Load the 2-byte character code into the result register. 12227 // Load the 2-byte character code into the result register.
12228 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); // index is smi (powered by 2).
12227 __ movzx_w(result, FieldOperand(object, 12229 __ movzx_w(result, FieldOperand(object,
12228 scratch, times_2, 12230 index, times_1,
12229 SeqTwoByteString::kHeaderSize)); 12231 SeqTwoByteString::kHeaderSize));
12230 __ jmp(&got_char_code); 12232 __ jmp(&got_char_code);
12231 12233
12232 // Handle non-flat strings. 12234 // Handle non-flat strings.
12233 __ bind(&not_a_flat_string); 12235 __ bind(&not_a_flat_string);
12234 __ and_(result, kStringRepresentationMask); 12236 __ and_(result, kStringRepresentationMask);
12235 __ cmp(result, kConsStringTag); 12237 __ cmp(result, kConsStringTag);
12236 __ j(not_equal, slow_case); 12238 __ j(not_equal, slow_case);
12237 12239
12238 // ConsString. 12240 // ConsString.
12239 // Check whether the right hand side is the empty string (i.e. if 12241 // Check whether the right hand side is the empty string (i.e. if
12240 // this is really a flat string in a cons string). If that is not 12242 // this is really a flat string in a cons string). If that is not
12241 // the case we would rather go to the runtime system now to flatten 12243 // the case we would rather go to the runtime system now to flatten
12242 // the string. 12244 // the string.
12243 __ mov(result, FieldOperand(object, ConsString::kSecondOffset)); 12245 __ mov(result, FieldOperand(object, ConsString::kSecondOffset));
12244 __ cmp(Operand(result), Factory::empty_string()); 12246 __ cmp(Operand(result), Factory::empty_string());
12245 __ j(not_equal, slow_case); 12247 __ j(not_equal, slow_case);
12246 // Get the first of the two strings and load its instance type. 12248 // Get the first of the two strings and load its instance type.
12247 __ mov(object, FieldOperand(object, ConsString::kFirstOffset)); 12249 __ mov(object, FieldOperand(object, ConsString::kFirstOffset));
12248 __ mov(result, FieldOperand(object, HeapObject::kMapOffset)); 12250 __ mov(result, FieldOperand(object, HeapObject::kMapOffset));
12249 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); 12251 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
12250 __ jmp(&try_again_with_new_string); 12252 __ jmp(&try_again_with_new_string);
12251 12253
12252 // ASCII string. 12254 // ASCII string.
12253 __ bind(&ascii_string); 12255 __ bind(&ascii_string);
12256 // Put untagged index into scratch register.
12257 __ mov(scratch, index);
12258 __ SmiUntag(scratch);
12259
12254 // Load the byte into the result register. 12260 // Load the byte into the result register.
12255 __ movzx_b(result, FieldOperand(object, 12261 __ movzx_b(result, FieldOperand(object,
12256 scratch, times_1, 12262 scratch, times_1,
12257 SeqAsciiString::kHeaderSize)); 12263 SeqAsciiString::kHeaderSize));
12258 __ bind(&got_char_code); 12264 __ bind(&got_char_code);
12259 __ SmiTag(result); 12265 __ SmiTag(result);
12260 } 12266 }
12261 12267
12262 12268
12263 void StringHelper::GenerateCharFromCode(MacroAssembler* masm, 12269 void StringHelper::GenerateCharFromCode(MacroAssembler* masm,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
12334 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); 12340 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx);
12335 __ j(above_equal, &string_add_runtime); 12341 __ j(above_equal, &string_add_runtime);
12336 } 12342 }
12337 12343
12338 // Both arguments are strings. 12344 // Both arguments are strings.
12339 // eax: first string 12345 // eax: first string
12340 // edx: second string 12346 // edx: second string
12341 // Check if either of the strings are empty. In that case return the other. 12347 // Check if either of the strings are empty. In that case return the other.
12342 Label second_not_zero_length, both_not_zero_length; 12348 Label second_not_zero_length, both_not_zero_length;
12343 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); 12349 __ mov(ecx, FieldOperand(edx, String::kLengthOffset));
12350 ASSERT(kSmiTag == 0);
12344 __ test(ecx, Operand(ecx)); 12351 __ test(ecx, Operand(ecx));
12345 __ j(not_zero, &second_not_zero_length); 12352 __ j(not_zero, &second_not_zero_length);
12346 // Second string is empty, result is first string which is already in eax. 12353 // Second string is empty, result is first string which is already in eax.
12347 __ IncrementCounter(&Counters::string_add_native, 1); 12354 __ IncrementCounter(&Counters::string_add_native, 1);
12348 __ ret(2 * kPointerSize); 12355 __ ret(2 * kPointerSize);
12349 __ bind(&second_not_zero_length); 12356 __ bind(&second_not_zero_length);
12350 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); 12357 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
12358 ASSERT(kSmiTag == 0);
12351 __ test(ebx, Operand(ebx)); 12359 __ test(ebx, Operand(ebx));
12352 __ j(not_zero, &both_not_zero_length); 12360 __ j(not_zero, &both_not_zero_length);
12353 // First string is empty, result is second string which is in edx. 12361 // First string is empty, result is second string which is in edx.
12354 __ mov(eax, edx); 12362 __ mov(eax, edx);
12355 __ IncrementCounter(&Counters::string_add_native, 1); 12363 __ IncrementCounter(&Counters::string_add_native, 1);
12356 __ ret(2 * kPointerSize); 12364 __ ret(2 * kPointerSize);
12357 12365
12358 // Both strings are non-empty. 12366 // Both strings are non-empty.
12359 // eax: first string 12367 // eax: first string
12360 // ebx: length of first string 12368 // ebx: length of first string as a smi
12361 // ecx: length of second string 12369 // ecx: length of second string as a smi
12362 // edx: second string 12370 // edx: second string
12363 // Look at the length of the result of adding the two strings. 12371 // Look at the length of the result of adding the two strings.
12364 Label string_add_flat_result, longer_than_two; 12372 Label string_add_flat_result, longer_than_two;
12365 __ bind(&both_not_zero_length); 12373 __ bind(&both_not_zero_length);
12366 __ add(ebx, Operand(ecx)); 12374 __ add(ebx, Operand(ecx));
12375 ASSERT(Smi::kMaxValue == String::kMaxLength);
12376 // Handle exceptionally long strings in the runtime system.
12377 __ j(overflow, &string_add_runtime);
12367 // Use the runtime system when adding two one character strings, as it 12378 // Use the runtime system when adding two one character strings, as it
12368 // contains optimizations for this specific case using the symbol table. 12379 // contains optimizations for this specific case using the symbol table.
12369 __ cmp(ebx, 2); 12380 __ cmp(Operand(ebx), Immediate(Smi::FromInt(2)));
12370 __ j(not_equal, &longer_than_two); 12381 __ j(not_equal, &longer_than_two);
12371 12382
12372 // Check that both strings are non-external ascii strings. 12383 // Check that both strings are non-external ascii strings.
12373 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, 12384 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx,
12374 &string_add_runtime); 12385 &string_add_runtime);
12375 12386
12376 // Get the two characters forming the sub string. 12387 // Get the two characters forming the sub string.
12377 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); 12388 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize));
12378 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); 12389 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize));
12379 12390
12380 // Try to lookup two character string in symbol table. If it is not found 12391 // Try to lookup two character string in symbol table. If it is not found
12381 // just allocate a new one. 12392 // just allocate a new one.
12382 Label make_two_character_string, make_flat_ascii_string; 12393 Label make_two_character_string, make_flat_ascii_string;
12383 StringHelper::GenerateTwoCharacterSymbolTableProbe( 12394 StringHelper::GenerateTwoCharacterSymbolTableProbe(
12384 masm, ebx, ecx, eax, edx, edi, &make_two_character_string); 12395 masm, ebx, ecx, eax, edx, edi, &make_two_character_string);
12385 __ IncrementCounter(&Counters::string_add_native, 1); 12396 __ IncrementCounter(&Counters::string_add_native, 1);
12386 __ ret(2 * kPointerSize); 12397 __ ret(2 * kPointerSize);
12387 12398
12388 __ bind(&make_two_character_string); 12399 __ bind(&make_two_character_string);
12389 __ Set(ebx, Immediate(2)); 12400 __ Set(ebx, Immediate(Smi::FromInt(2)));
12390 __ jmp(&make_flat_ascii_string); 12401 __ jmp(&make_flat_ascii_string);
12391 12402
12392 __ bind(&longer_than_two); 12403 __ bind(&longer_than_two);
12393 // Check if resulting string will be flat. 12404 // Check if resulting string will be flat.
12394 __ cmp(ebx, String::kMinNonFlatLength); 12405 __ cmp(Operand(ebx), Immediate(Smi::FromInt(String::kMinNonFlatLength)));
12395 __ j(below, &string_add_flat_result); 12406 __ j(below, &string_add_flat_result);
12396 // Handle exceptionally long strings in the runtime system.
12397 ASSERT((String::kMaxLength & 0x80000000) == 0);
12398 __ cmp(ebx, String::kMaxLength);
12399 __ j(above, &string_add_runtime);
12400 12407
12401 // If result is not supposed to be flat allocate a cons string object. If both 12408 // If result is not supposed to be flat allocate a cons string object. If both
12402 // strings are ascii the result is an ascii cons string. 12409 // strings are ascii the result is an ascii cons string.
12403 Label non_ascii, allocated; 12410 Label non_ascii, allocated;
12404 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset)); 12411 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
12405 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset)); 12412 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
12406 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 12413 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
12407 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset)); 12414 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
12408 __ and_(ecx, Operand(edi)); 12415 __ and_(ecx, Operand(edi));
12409 ASSERT(kStringEncodingMask == kAsciiStringTag); 12416 ASSERT(kStringEncodingMask == kAsciiStringTag);
12410 __ test(ecx, Immediate(kAsciiStringTag)); 12417 __ test(ecx, Immediate(kAsciiStringTag));
12411 __ j(zero, &non_ascii); 12418 __ j(zero, &non_ascii);
12412 // Allocate an acsii cons string. 12419 // Allocate an acsii cons string.
12413 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime); 12420 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime);
12414 __ bind(&allocated); 12421 __ bind(&allocated);
12415 // Fill the fields of the cons string. 12422 // Fill the fields of the cons string.
12423 if (FLAG_debug_code) __ AbortIfNotSmi(ebx);
12416 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx); 12424 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx);
12417 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset), 12425 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset),
12418 Immediate(String::kEmptyHashField)); 12426 Immediate(String::kEmptyHashField));
12419 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax); 12427 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
12420 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx); 12428 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
12421 __ mov(eax, ecx); 12429 __ mov(eax, ecx);
12422 __ IncrementCounter(&Counters::string_add_native, 1); 12430 __ IncrementCounter(&Counters::string_add_native, 1);
12423 __ ret(2 * kPointerSize); 12431 __ ret(2 * kPointerSize);
12424 __ bind(&non_ascii); 12432 __ bind(&non_ascii);
12425 // Allocate a two byte cons string. 12433 // Allocate a two byte cons string.
12426 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime); 12434 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime);
12427 __ jmp(&allocated); 12435 __ jmp(&allocated);
12428 12436
12429 // Handle creating a flat result. First check that both strings are not 12437 // Handle creating a flat result. First check that both strings are not
12430 // external strings. 12438 // external strings.
12431 // eax: first string 12439 // eax: first string
12432 // ebx: length of resulting flat string 12440 // ebx: length of resulting flat string as a smi
12433 // edx: second string 12441 // edx: second string
12434 __ bind(&string_add_flat_result); 12442 __ bind(&string_add_flat_result);
12435 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 12443 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
12436 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12444 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12437 __ and_(ecx, kStringRepresentationMask); 12445 __ and_(ecx, kStringRepresentationMask);
12438 __ cmp(ecx, kExternalStringTag); 12446 __ cmp(ecx, kExternalStringTag);
12439 __ j(equal, &string_add_runtime); 12447 __ j(equal, &string_add_runtime);
12440 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12448 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12441 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12449 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12442 __ and_(ecx, kStringRepresentationMask); 12450 __ and_(ecx, kStringRepresentationMask);
12443 __ cmp(ecx, kExternalStringTag); 12451 __ cmp(ecx, kExternalStringTag);
12444 __ j(equal, &string_add_runtime); 12452 __ j(equal, &string_add_runtime);
12445 // Now check if both strings are ascii strings. 12453 // Now check if both strings are ascii strings.
12446 // eax: first string 12454 // eax: first string
12447 // ebx: length of resulting flat string 12455 // ebx: length of resulting flat string as a smi
12448 // edx: second string 12456 // edx: second string
12449 Label non_ascii_string_add_flat_result; 12457 Label non_ascii_string_add_flat_result;
12450 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 12458 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
12451 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12459 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12452 ASSERT(kStringEncodingMask == kAsciiStringTag); 12460 ASSERT(kStringEncodingMask == kAsciiStringTag);
12453 __ test(ecx, Immediate(kAsciiStringTag)); 12461 __ test(ecx, Immediate(kAsciiStringTag));
12454 __ j(zero, &non_ascii_string_add_flat_result); 12462 __ j(zero, &non_ascii_string_add_flat_result);
12455 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12463 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12456 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12464 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12457 __ test(ecx, Immediate(kAsciiStringTag)); 12465 __ test(ecx, Immediate(kAsciiStringTag));
12458 __ j(zero, &string_add_runtime); 12466 __ j(zero, &string_add_runtime);
12459 12467
12460 __ bind(&make_flat_ascii_string); 12468 __ bind(&make_flat_ascii_string);
12461 // Both strings are ascii strings. As they are short they are both flat. 12469 // Both strings are ascii strings. As they are short they are both flat.
12462 // ebx: length of resulting flat string 12470 // ebx: length of resulting flat string as a smi
12471 __ SmiUntag(ebx);
12463 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime); 12472 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime);
12464 // eax: result string 12473 // eax: result string
12465 __ mov(ecx, eax); 12474 __ mov(ecx, eax);
12466 // Locate first character of result. 12475 // Locate first character of result.
12467 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12476 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12468 // Load first argument and locate first character. 12477 // Load first argument and locate first character.
12469 __ mov(edx, Operand(esp, 2 * kPointerSize)); 12478 __ mov(edx, Operand(esp, 2 * kPointerSize));
12470 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12479 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12480 __ SmiUntag(edi);
12471 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12481 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12472 // eax: result string 12482 // eax: result string
12473 // ecx: first character of result 12483 // ecx: first character of result
12474 // edx: first char of first argument 12484 // edx: first char of first argument
12475 // edi: length of first argument 12485 // edi: length of first argument
12476 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 12486 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
12477 // Load second argument and locate first character. 12487 // Load second argument and locate first character.
12478 __ mov(edx, Operand(esp, 1 * kPointerSize)); 12488 __ mov(edx, Operand(esp, 1 * kPointerSize));
12479 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12489 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12490 __ SmiUntag(edi);
12480 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12491 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12481 // eax: result string 12492 // eax: result string
12482 // ecx: next character of result 12493 // ecx: next character of result
12483 // edx: first char of second argument 12494 // edx: first char of second argument
12484 // edi: length of second argument 12495 // edi: length of second argument
12485 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 12496 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
12486 __ IncrementCounter(&Counters::string_add_native, 1); 12497 __ IncrementCounter(&Counters::string_add_native, 1);
12487 __ ret(2 * kPointerSize); 12498 __ ret(2 * kPointerSize);
12488 12499
12489 // Handle creating a flat two byte result. 12500 // Handle creating a flat two byte result.
12490 // eax: first string - known to be two byte 12501 // eax: first string - known to be two byte
12491 // ebx: length of resulting flat string 12502 // ebx: length of resulting flat string as a smi
12492 // edx: second string 12503 // edx: second string
12493 __ bind(&non_ascii_string_add_flat_result); 12504 __ bind(&non_ascii_string_add_flat_result);
12494 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12505 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12495 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12506 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12496 __ and_(ecx, kAsciiStringTag); 12507 __ and_(ecx, kAsciiStringTag);
12497 __ j(not_zero, &string_add_runtime); 12508 __ j(not_zero, &string_add_runtime);
12498 // Both strings are two byte strings. As they are short they are both 12509 // Both strings are two byte strings. As they are short they are both
12499 // flat. 12510 // flat.
12511 __ SmiUntag(ebx);
12500 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime); 12512 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime);
12501 // eax: result string 12513 // eax: result string
12502 __ mov(ecx, eax); 12514 __ mov(ecx, eax);
12503 // Locate first character of result. 12515 // Locate first character of result.
12504 __ add(Operand(ecx), 12516 __ add(Operand(ecx),
12505 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 12517 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
12506 // Load first argument and locate first character. 12518 // Load first argument and locate first character.
12507 __ mov(edx, Operand(esp, 2 * kPointerSize)); 12519 __ mov(edx, Operand(esp, 2 * kPointerSize));
12508 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12520 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12521 __ SmiUntag(edi);
12509 __ add(Operand(edx), 12522 __ add(Operand(edx),
12510 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 12523 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
12511 // eax: result string 12524 // eax: result string
12512 // ecx: first character of result 12525 // ecx: first character of result
12513 // edx: first char of first argument 12526 // edx: first char of first argument
12514 // edi: length of first argument 12527 // edi: length of first argument
12515 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 12528 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
12516 // Load second argument and locate first character. 12529 // Load second argument and locate first character.
12517 __ mov(edx, Operand(esp, 1 * kPointerSize)); 12530 __ mov(edx, Operand(esp, 1 * kPointerSize));
12518 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12531 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12532 __ SmiUntag(edi);
12519 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12533 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12520 // eax: result string 12534 // eax: result string
12521 // ecx: next character of result 12535 // ecx: next character of result
12522 // edx: first char of second argument 12536 // edx: first char of second argument
12523 // edi: length of second argument 12537 // edi: length of second argument
12524 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 12538 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
12525 __ IncrementCounter(&Counters::string_add_native, 1); 12539 __ IncrementCounter(&Counters::string_add_native, 1);
12526 __ ret(2 * kPointerSize); 12540 __ ret(2 * kPointerSize);
12527 12541
12528 // Just jump to runtime to add the two strings. 12542 // Just jump to runtime to add the two strings.
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
12693 FieldOperand(symbol_table, 12707 FieldOperand(symbol_table,
12694 scratch, 12708 scratch,
12695 times_pointer_size, 12709 times_pointer_size,
12696 SymbolTable::kElementsStartOffset)); 12710 SymbolTable::kElementsStartOffset));
12697 12711
12698 // If entry is undefined no string with this hash can be found. 12712 // If entry is undefined no string with this hash can be found.
12699 __ cmp(candidate, Factory::undefined_value()); 12713 __ cmp(candidate, Factory::undefined_value());
12700 __ j(equal, not_found); 12714 __ j(equal, not_found);
12701 12715
12702 // If length is not 2 the string is not a candidate. 12716 // If length is not 2 the string is not a candidate.
12703 __ cmp(FieldOperand(candidate, String::kLengthOffset), Immediate(2)); 12717 __ cmp(FieldOperand(candidate, String::kLengthOffset),
12718 Immediate(Smi::FromInt(2)));
12704 __ j(not_equal, &next_probe[i]); 12719 __ j(not_equal, &next_probe[i]);
12705 12720
12706 // As we are out of registers save the mask on the stack and use that 12721 // As we are out of registers save the mask on the stack and use that
12707 // register as a temporary. 12722 // register as a temporary.
12708 __ push(mask); 12723 __ push(mask);
12709 Register temp = mask; 12724 Register temp = mask;
12710 12725
12711 // Check that the candidate is a non-external ascii string. 12726 // Check that the candidate is a non-external ascii string.
12712 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset)); 12727 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset));
12713 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 12728 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
12962 12977
12963 Register min_length = scratch1; 12978 Register min_length = scratch1;
12964 12979
12965 // If either length is zero, just compare lengths. 12980 // If either length is zero, just compare lengths.
12966 __ test(min_length, Operand(min_length)); 12981 __ test(min_length, Operand(min_length));
12967 __ j(zero, &compare_lengths); 12982 __ j(zero, &compare_lengths);
12968 12983
12969 // Change index to run from -min_length to -1 by adding min_length 12984 // Change index to run from -min_length to -1 by adding min_length
12970 // to string start. This means that loop ends when index reaches zero, 12985 // to string start. This means that loop ends when index reaches zero,
12971 // which doesn't need an additional compare. 12986 // which doesn't need an additional compare.
12987 __ SmiUntag(min_length);
12972 __ lea(left, 12988 __ lea(left,
12973 FieldOperand(left, 12989 FieldOperand(left,
12974 min_length, times_1, 12990 min_length, times_1,
12975 SeqAsciiString::kHeaderSize)); 12991 SeqAsciiString::kHeaderSize));
12976 __ lea(right, 12992 __ lea(right,
12977 FieldOperand(right, 12993 FieldOperand(right,
12978 min_length, times_1, 12994 min_length, times_1,
12979 SeqAsciiString::kHeaderSize)); 12995 SeqAsciiString::kHeaderSize));
12980 __ neg(min_length); 12996 __ neg(min_length);
12981 12997
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
13048 13064
13049 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 13065 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
13050 // tagged as a small integer. 13066 // tagged as a small integer.
13051 __ bind(&runtime); 13067 __ bind(&runtime);
13052 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 13068 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
13053 } 13069 }
13054 13070
13055 #undef __ 13071 #undef __
13056 13072
13057 } } // namespace v8::internal 13073 } } // 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