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

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

Issue 2673001: Improve generated code for string encoding tests on ia32. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 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 | « no previous file | no next file » | 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 11285 matching lines...) Expand 10 before | Expand all | Expand 10 after
11296 // Check that the last match info has space for the capture registers and the 11296 // Check that the last match info has space for the capture registers and the
11297 // additional information. 11297 // additional information.
11298 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset)); 11298 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset));
11299 __ SmiUntag(eax); 11299 __ SmiUntag(eax);
11300 __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead)); 11300 __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead));
11301 __ cmp(edx, Operand(eax)); 11301 __ cmp(edx, Operand(eax));
11302 __ j(greater, &runtime); 11302 __ j(greater, &runtime);
11303 11303
11304 // ecx: RegExp data (FixedArray) 11304 // ecx: RegExp data (FixedArray)
11305 // Check the representation and encoding of the subject string. 11305 // Check the representation and encoding of the subject string.
11306 Label seq_string, seq_two_byte_string, check_code; 11306 Label seq_ascii_string, seq_two_byte_string, check_code;
11307 const int kStringRepresentationEncodingMask =
11308 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
11309 __ mov(eax, Operand(esp, kSubjectOffset)); 11307 __ mov(eax, Operand(esp, kSubjectOffset));
11310 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 11308 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
11311 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 11309 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
11312 __ and_(ebx, kStringRepresentationEncodingMask); 11310 // First check for flat two byte string.
Lasse Reichstein 2010/06/07 09:29:06 "two-byte"?
William Hesse 2010/06/07 12:17:28 Done.
11313 // First check for sequential string. 11311 __ and_(ebx,
Lasse Reichstein 2010/06/07 09:29:06 Would andb be enough? (Although I don't think it m
William Hesse 2010/06/07 12:17:28 All of these changed to test_b. On 2010/06/07 09:
11314 ASSERT_EQ(0, kStringTag); 11312 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
11315 ASSERT_EQ(0, kSeqStringTag); 11313 ASSERT_EQ(0, kStringTag | kSeqStringTag | kTwoByteStringTag);
11314 __ j(zero, &seq_two_byte_string);
11315 // Any other flat string must be a flat ascii string.
11316 __ test(Operand(ebx), 11316 __ test(Operand(ebx),
11317 Immediate(kIsNotStringMask | kStringRepresentationMask)); 11317 Immediate(kIsNotStringMask | kStringRepresentationMask));
11318 __ j(zero, &seq_string); 11318 __ j(zero, &seq_ascii_string);
11319 11319
11320 // Check for flat cons string. 11320 // Check for flat cons string.
11321 // A flat cons string is a cons string where the second part is the empty 11321 // A flat cons string is a cons string where the second part is the empty
11322 // string. In that case the subject string is just the first part of the cons 11322 // string. In that case the subject string is just the first part of the cons
11323 // string. Also in this case the first part of the cons string is known to be 11323 // string. Also in this case the first part of the cons string is known to be
11324 // a sequential string or an external string. 11324 // a sequential string or an external string.
11325 __ and_(ebx, kStringRepresentationMask); 11325 ASSERT(kExternalStringTag !=0);
11326 __ cmp(ebx, kConsStringTag); 11326 ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
11327 __ j(not_equal, &runtime); 11327 __ test(Operand(ebx),
11328 Immediate(kIsNotStringMask | kExternalStringTag));
11329 __ j(not_zero, &runtime);
11330 // String is a cons string.
11328 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset)); 11331 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset));
11329 __ cmp(Operand(edx), Factory::empty_string()); 11332 __ cmp(Operand(edx), Factory::empty_string());
Lasse Reichstein 2010/06/07 09:29:06 Can you do a direct compare to memory? I.e., cmp(
William Hesse 2010/06/07 12:17:28 Done.
11330 __ j(not_equal, &runtime); 11333 __ j(not_equal, &runtime);
11331 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); 11334 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
11332 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 11335 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
11333 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 11336 // String is a cons string with empty second part.
11334 ASSERT_EQ(0, kSeqStringTag); 11337 // eax: first part of cons string.
11335 __ test(ebx, Immediate(kStringRepresentationMask)); 11338 // ebx: map of first part of cons string.
11339 // Is first part a flat two byte string?
11340 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset),
11341 kStringRepresentationMask | kStringEncodingMask);
11342 ASSERT_EQ(0, kSeqStringTag | kTwoByteStringTag);
11343 __ j(zero, &seq_two_byte_string);
11344 // Any other flat string must be ascii.
11345 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset),
11346 kStringRepresentationMask);
11336 __ j(not_zero, &runtime); 11347 __ j(not_zero, &runtime);
11337 __ and_(ebx, kStringRepresentationEncodingMask);
11338 11348
11339 __ bind(&seq_string); 11349 __ bind(&seq_ascii_string);
11340 // eax: subject string (sequential either ascii to two byte) 11350 // eax: subject string (flat ascii)
11341 // ebx: suject string type & kStringRepresentationEncodingMask
11342 // ecx: RegExp data (FixedArray) 11351 // ecx: RegExp data (FixedArray)
11343 // Check that the irregexp code has been generated for an ascii string. If
11344 // it has, the field contains a code object otherwise it contains the hole.
11345 const int kSeqTwoByteString = kStringTag | kSeqStringTag | kTwoByteStringTag;
11346 __ cmp(ebx, kSeqTwoByteString);
11347 __ j(equal, &seq_two_byte_string);
11348 if (FLAG_debug_code) {
11349 __ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag);
11350 __ Check(equal, "Expected sequential ascii string");
11351 }
11352 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); 11352 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset));
11353 __ Set(edi, Immediate(1)); // Type is ascii. 11353 __ Set(edi, Immediate(1)); // Type is ascii.
11354 __ jmp(&check_code); 11354 __ jmp(&check_code);
11355 11355
11356 __ bind(&seq_two_byte_string); 11356 __ bind(&seq_two_byte_string);
11357 // eax: subject string 11357 // eax: subject string (flat two byte)
11358 // ecx: RegExp data (FixedArray) 11358 // ecx: RegExp data (FixedArray)
11359 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); 11359 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset));
11360 __ Set(edi, Immediate(0)); // Type is two byte. 11360 __ Set(edi, Immediate(0)); // Type is two byte.
11361 11361
11362 __ bind(&check_code); 11362 __ bind(&check_code);
11363 // Check that the irregexp code has been generated for the actual string 11363 // Check that the irregexp code has been generated for the actual string
11364 // encoding. If it has, the field contains a code object otherwise it contains 11364 // encoding. If it has, the field contains a code object otherwise it contains
11365 // the hole. 11365 // the hole.
11366 __ CmpObjectType(edx, CODE_TYPE, ebx); 11366 __ CmpObjectType(edx, CODE_TYPE, ebx);
11367 __ j(not_equal, &runtime); 11367 __ j(not_equal, &runtime);
(...skipping 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after
12753 12753
12754 void StringAddStub::Generate(MacroAssembler* masm) { 12754 void StringAddStub::Generate(MacroAssembler* masm) {
12755 Label string_add_runtime; 12755 Label string_add_runtime;
12756 12756
12757 // Load the two arguments. 12757 // Load the two arguments.
12758 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. 12758 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
12759 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. 12759 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
12760 12760
12761 // Make sure that both arguments are strings if not known in advance. 12761 // Make sure that both arguments are strings if not known in advance.
12762 if (string_check_) { 12762 if (string_check_) {
12763 __ test(eax, Immediate(kSmiTagMask)); 12763 __ mov(ecx, eax);
12764 __ and_(Operand(ecx), edx);
12765 __ test(ecx, Immediate(kSmiTagMask));
12764 __ j(zero, &string_add_runtime); 12766 __ j(zero, &string_add_runtime);
12765 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx); 12767 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
12766 __ j(above_equal, &string_add_runtime); 12768 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
12767 12769 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
12768 // First argument is a a string, test second. 12770 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
12769 __ test(edx, Immediate(kSmiTagMask)); 12771 __ or_(Operand(ecx), ebx);
12770 __ j(zero, &string_add_runtime); 12772 __ test_b(Operand(ecx), kIsNotStringMask);
12771 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); 12773 __ j(not_zero, &string_add_runtime);
12772 __ j(above_equal, &string_add_runtime);
12773 } 12774 }
12774 12775
12775 // Both arguments are strings. 12776 // Both arguments are strings.
12776 // eax: first string 12777 // eax: first string
12777 // edx: second string 12778 // edx: second string
12778 // Check if either of the strings are empty. In that case return the other. 12779 // Check if either of the strings are empty. In that case return the other.
12779 Label second_not_zero_length, both_not_zero_length; 12780 Label second_not_zero_length, both_not_zero_length;
12780 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); 12781 __ mov(ecx, FieldOperand(edx, String::kLengthOffset));
12781 ASSERT(kSmiTag == 0); 12782 ASSERT(kSmiTag == 0);
12782 __ test(ecx, Operand(ecx)); 12783 __ test(ecx, Operand(ecx));
(...skipping 10 matching lines...) Expand all
12793 __ mov(eax, edx); 12794 __ mov(eax, edx);
12794 __ IncrementCounter(&Counters::string_add_native, 1); 12795 __ IncrementCounter(&Counters::string_add_native, 1);
12795 __ ret(2 * kPointerSize); 12796 __ ret(2 * kPointerSize);
12796 12797
12797 // Both strings are non-empty. 12798 // Both strings are non-empty.
12798 // eax: first string 12799 // eax: first string
12799 // ebx: length of first string as a smi 12800 // ebx: length of first string as a smi
12800 // ecx: length of second string as a smi 12801 // ecx: length of second string as a smi
12801 // edx: second string 12802 // edx: second string
12802 // Look at the length of the result of adding the two strings. 12803 // Look at the length of the result of adding the two strings.
12803 Label string_add_flat_result, longer_than_two; 12804 Label make_two_character_string, longer_than_two,
12805 make_flat_string, make_flat_ascii_string, make_flat_non_ascii_string;
12804 __ bind(&both_not_zero_length); 12806 __ bind(&both_not_zero_length);
12805 __ add(ebx, Operand(ecx)); 12807 __ add(ebx, Operand(ecx));
12806 ASSERT(Smi::kMaxValue == String::kMaxLength); 12808 ASSERT(Smi::kMaxValue == String::kMaxLength);
12807 // Handle exceptionally long strings in the runtime system. 12809 // Handle exceptionally long strings in the runtime system.
12808 __ j(overflow, &string_add_runtime); 12810 __ j(overflow, &string_add_runtime);
12809 // Use the runtime system when adding two one character strings, as it 12811 // Use the runtime system when adding two one character strings, as it
12810 // contains optimizations for this specific case using the symbol table. 12812 // contains optimizations for this specific case using the symbol table.
12811 __ cmp(Operand(ebx), Immediate(Smi::FromInt(2))); 12813 __ cmp(Operand(ebx), Immediate(Smi::FromInt(2)));
12812 __ j(not_equal, &longer_than_two); 12814 __ j(not_equal, &longer_than_two);
12813 12815
12814 // Check that both strings are non-external ascii strings. 12816 // Check that both strings are non-external ascii strings.
12815 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, 12817 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx,
12816 &string_add_runtime); 12818 &string_add_runtime);
12817 12819
12818 // Get the two characters forming the sub string. 12820 // Get the two characters forming the sub string.
12819 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); 12821 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize));
12820 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); 12822 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize));
12821 12823
12822 // Try to lookup two character string in symbol table. If it is not found 12824 // Try to lookup two character string in symbol table. If it is not found
12823 // just allocate a new one. 12825 // just allocate a new one.
12824 Label make_two_character_string, make_flat_ascii_string;
12825 StringHelper::GenerateTwoCharacterSymbolTableProbe( 12826 StringHelper::GenerateTwoCharacterSymbolTableProbe(
12826 masm, ebx, ecx, eax, edx, edi, &make_two_character_string); 12827 masm, ebx, ecx, eax, edx, edi, &make_two_character_string);
12827 __ IncrementCounter(&Counters::string_add_native, 1); 12828 __ IncrementCounter(&Counters::string_add_native, 1);
12828 __ ret(2 * kPointerSize); 12829 __ ret(2 * kPointerSize);
12829 12830
12830 __ bind(&make_two_character_string); 12831 __ bind(&make_two_character_string);
12831 __ Set(ebx, Immediate(Smi::FromInt(2))); 12832 __ Set(ebx, Immediate(Smi::FromInt(2)));
12832 __ jmp(&make_flat_ascii_string); 12833 __ jmp(&make_flat_ascii_string);
12833 12834
12834 __ bind(&longer_than_two); 12835 __ bind(&longer_than_two);
12835 // Check if resulting string will be flat. 12836 // Check if resulting string will be flat.
12836 __ cmp(Operand(ebx), Immediate(Smi::FromInt(String::kMinNonFlatLength))); 12837 __ cmp(Operand(ebx), Immediate(Smi::FromInt(String::kMinNonFlatLength)));
12837 __ j(below, &string_add_flat_result); 12838 __ j(below, &make_flat_string);
12838 12839
12839 // If result is not supposed to be flat allocate a cons string object. If both 12840 // If result is not supposed to be flat allocate a cons string object. If both
12840 // strings are ascii the result is an ascii cons string. 12841 // strings are ascii the result is an ascii cons string.
12841 Label non_ascii, allocated; 12842 Label non_ascii, allocated;
12842 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset)); 12843 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
12843 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset)); 12844 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
12844 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 12845 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
12845 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset)); 12846 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
12846 __ and_(ecx, Operand(edi)); 12847 __ and_(ecx, Operand(edi));
12847 ASSERT(kStringEncodingMask == kAsciiStringTag); 12848 ASSERT(kStringEncodingMask == kAsciiStringTag);
(...skipping 10 matching lines...) Expand all
12858 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax); 12859 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
12859 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx); 12860 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
12860 __ mov(eax, ecx); 12861 __ mov(eax, ecx);
12861 __ IncrementCounter(&Counters::string_add_native, 1); 12862 __ IncrementCounter(&Counters::string_add_native, 1);
12862 __ ret(2 * kPointerSize); 12863 __ ret(2 * kPointerSize);
12863 __ bind(&non_ascii); 12864 __ bind(&non_ascii);
12864 // Allocate a two byte cons string. 12865 // Allocate a two byte cons string.
12865 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime); 12866 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime);
12866 __ jmp(&allocated); 12867 __ jmp(&allocated);
12867 12868
12868 // Handle creating a flat result. First check that both strings are not 12869 // Handle creating a flat result. Branch to runtime if either string
12869 // external strings. 12870 // is external or if they are not both ascii or both two-byte.
12871 // Otherwise branch to ascii case or two-byte case.
12870 // eax: first string 12872 // eax: first string
12871 // ebx: length of resulting flat string as a smi 12873 // ebx: length of resulting flat string as a smi
12872 // edx: second string 12874 // edx: second string
12873 __ bind(&string_add_flat_result); 12875 __ bind(&make_flat_string);
12874 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 12876 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
12875 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12877 __ movzx_b(edi, FieldOperand(ecx, Map::kInstanceTypeOffset));
12876 __ and_(ecx, kStringRepresentationMask);
12877 __ cmp(ecx, kExternalStringTag);
12878 __ j(equal, &string_add_runtime);
12879 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12878 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12880 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12879 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12881 __ and_(ecx, kStringRepresentationMask); 12880 __ or_(ecx, Operand(edi));
12882 __ cmp(ecx, kExternalStringTag); 12881 ASSERT(kExternalStringTag !=0);
12883 __ j(equal, &string_add_runtime); 12882 ASSERT((kConsStringTag & kExternalStringTag) == 0);
12884 // Now check if both strings are ascii strings. 12883 ASSERT((kSeqStringTag & kExternalStringTag) == 0);
12885 // eax: first string 12884 ASSERT(kTwoByteStringTag == 0);
12886 // ebx: length of resulting flat string as a smi 12885 __ test_b(Operand(ecx), kExternalStringTag | kStringEncodingMask);
12887 // edx: second string 12886 __ j(zero, &make_flat_non_ascii_string); // Neither is ascii or external.
12888 Label non_ascii_string_add_flat_result; 12887 __ test_b(Operand(ecx), kExternalStringTag);
12889 ASSERT(kStringEncodingMask == kAsciiStringTag); 12888 __ j(not_zero, &string_add_runtime); // One or both is external.
12890 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 12889 // At this point, neither is external, and at least one is ascii.
12891 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); 12890 __ test(edi, Immediate(kStringEncodingMask));
Lasse Reichstein 2010/06/07 09:29:06 Could you do an xor (or just an and) here to check
William Hesse 2010/06/07 12:17:28 We can do a test with the other one and the mask,
12892 __ j(zero, &non_ascii_string_add_flat_result); 12891 __ j(zero, &string_add_runtime); // First string is two-byte, second ascii.
12893 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12892 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12894 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); 12893 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kStringEncodingMask);
12895 __ j(zero, &string_add_runtime); 12894 __ j(zero, &string_add_runtime); // First string is ascii, second two-byte.
12896 12895
12897 __ bind(&make_flat_ascii_string); 12896 __ bind(&make_flat_ascii_string);
12898 // Both strings are ascii strings. As they are short they are both flat. 12897 // Both strings are ascii strings. As they are short they are both flat.
12898 // Create a flat ascii result.
12899 // ebx: length of resulting flat string as a smi 12899 // ebx: length of resulting flat string as a smi
12900 __ SmiUntag(ebx); 12900 __ SmiUntag(ebx);
12901 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime); 12901 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime);
12902 // eax: result string 12902 // eax: result string
12903 __ mov(ecx, eax); 12903 __ mov(ecx, eax);
12904 // Locate first character of result. 12904 // Locate first character of result.
12905 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12905 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12906 // Load first argument and locate first character. 12906 // Load first argument and locate first character.
12907 __ mov(edx, Operand(esp, 2 * kPointerSize)); 12907 __ mov(edx, Operand(esp, 2 * kPointerSize));
12908 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12908 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
(...skipping 10 matching lines...) Expand all
12919 __ SmiUntag(edi); 12919 __ SmiUntag(edi);
12920 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12920 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12921 // eax: result string 12921 // eax: result string
12922 // ecx: next character of result 12922 // ecx: next character of result
12923 // edx: first char of second argument 12923 // edx: first char of second argument
12924 // edi: length of second argument 12924 // edi: length of second argument
12925 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 12925 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
12926 __ IncrementCounter(&Counters::string_add_native, 1); 12926 __ IncrementCounter(&Counters::string_add_native, 1);
12927 __ ret(2 * kPointerSize); 12927 __ ret(2 * kPointerSize);
12928 12928
12929 // Handle creating a flat two byte result. 12929 // Both strings are two-byte strings. As they are short they are both flat.
12930 // eax: first string - known to be two byte 12930 // Create a flat two byte result.
12931 // ebx: length of resulting flat string as a smi 12931 // ebx: length of resulting flat string as a smi
12932 // edx: second string 12932 __ bind(&make_flat_non_ascii_string);
12933 __ bind(&non_ascii_string_add_flat_result);
12934 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12935 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
12936 __ j(not_zero, &string_add_runtime);
12937 // Both strings are two byte strings. As they are short they are both 12933 // Both strings are two byte strings. As they are short they are both
12938 // flat. 12934 // flat.
12939 __ SmiUntag(ebx); 12935 __ SmiUntag(ebx);
12940 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime); 12936 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime);
12941 // eax: result string 12937 // eax: result string
12942 __ mov(ecx, eax); 12938 __ mov(ecx, eax);
12943 // Locate first character of result. 12939 // Locate first character of result.
12944 __ add(Operand(ecx), 12940 __ add(Operand(ecx),
12945 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 12941 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
12946 // Load first argument and locate first character. 12942 // Load first argument and locate first character.
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after
13699 masm.GetCode(&desc); 13695 masm.GetCode(&desc);
13700 // Call the function from C++. 13696 // Call the function from C++.
13701 return FUNCTION_CAST<MemCopyFunction>(buffer); 13697 return FUNCTION_CAST<MemCopyFunction>(buffer);
13702 } 13698 }
13703 13699
13704 #undef __ 13700 #undef __
13705 13701
13706 } } // namespace v8::internal 13702 } } // namespace v8::internal
13707 13703
13708 #endif // V8_TARGET_ARCH_IA32 13704 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698