OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |