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 11298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11309 // Check that the last match info has space for the capture registers and the | 11309 // Check that the last match info has space for the capture registers and the |
11310 // additional information. | 11310 // additional information. |
11311 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset)); | 11311 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset)); |
11312 __ SmiUntag(eax); | 11312 __ SmiUntag(eax); |
11313 __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead)); | 11313 __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead)); |
11314 __ cmp(edx, Operand(eax)); | 11314 __ cmp(edx, Operand(eax)); |
11315 __ j(greater, &runtime); | 11315 __ j(greater, &runtime); |
11316 | 11316 |
11317 // ecx: RegExp data (FixedArray) | 11317 // ecx: RegExp data (FixedArray) |
11318 // Check the representation and encoding of the subject string. | 11318 // Check the representation and encoding of the subject string. |
11319 Label seq_ascii_string, seq_two_byte_string, check_code; | 11319 Label seq_string, seq_two_byte_string, check_code; |
| 11320 const int kStringRepresentationEncodingMask = |
| 11321 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
11320 __ mov(eax, Operand(esp, kSubjectOffset)); | 11322 __ mov(eax, Operand(esp, kSubjectOffset)); |
11321 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 11323 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
11322 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 11324 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
11323 // First check for flat two-byte string. | 11325 __ and_(ebx, kStringRepresentationEncodingMask); |
11324 __ test_b(Operand(ebx), | 11326 // First check for sequential string. |
11325 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); | 11327 ASSERT_EQ(0, kStringTag); |
11326 ASSERT_EQ(0, kStringTag | kSeqStringTag | kTwoByteStringTag); | 11328 ASSERT_EQ(0, kSeqStringTag); |
11327 __ j(zero, &seq_two_byte_string); | 11329 __ test(Operand(ebx), |
11328 // Any other flat string must be a flat ascii string. | 11330 Immediate(kIsNotStringMask | kStringRepresentationMask)); |
11329 __ test_b(Operand(ebx), kIsNotStringMask | kStringRepresentationMask); | 11331 __ j(zero, &seq_string); |
11330 __ j(zero, &seq_ascii_string); | |
11331 | 11332 |
11332 // Check for flat cons string. | 11333 // Check for flat cons string. |
11333 // If this is a string, and not an external string, it is a cons string. | |
11334 // A flat cons string is a cons string where the second part is the empty | 11334 // A flat cons string is a cons string where the second part is the empty |
11335 // string. In that case the subject string is just the first part of the cons | 11335 // string. In that case the subject string is just the first part of the cons |
11336 // string. Also in this case the first part of the cons string is known to be | 11336 // string. Also in this case the first part of the cons string is known to be |
11337 // a sequential string or an external string. | 11337 // a sequential string or an external string. |
11338 ASSERT(kExternalStringTag !=0); | 11338 __ and_(ebx, kStringRepresentationMask); |
11339 ASSERT_EQ(0, kConsStringTag & kExternalStringTag); | 11339 __ cmp(ebx, kConsStringTag); |
11340 __ test_b(Operand(ebx), kIsNotStringMask | kExternalStringTag); | 11340 __ j(not_equal, &runtime); |
11341 __ j(not_zero, &runtime); | 11341 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset)); |
11342 // String is a cons string. | 11342 __ cmp(Operand(edx), Factory::empty_string()); |
11343 __ cmp(FieldOperand(eax, ConsString::kSecondOffset), | |
11344 Factory::empty_string()); | |
11345 __ j(not_equal, &runtime); | 11343 __ j(not_equal, &runtime); |
11346 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); | 11344 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); |
11347 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 11345 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
11348 // String is a cons string with empty second part. | 11346 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
11349 // eax: first part of cons string. | 11347 ASSERT_EQ(0, kSeqStringTag); |
11350 // ebx: map of first part of cons string. | 11348 __ test(ebx, Immediate(kStringRepresentationMask)); |
11351 // Is first part a flat two byte string? | |
11352 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), | |
11353 kStringRepresentationMask | kStringEncodingMask); | |
11354 ASSERT_EQ(0, kSeqStringTag | kTwoByteStringTag); | |
11355 __ j(zero, &seq_two_byte_string); | |
11356 // Any other flat string must be ascii. | |
11357 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), | |
11358 kStringRepresentationMask); | |
11359 __ j(not_zero, &runtime); | 11349 __ j(not_zero, &runtime); |
| 11350 __ and_(ebx, kStringRepresentationEncodingMask); |
11360 | 11351 |
11361 __ bind(&seq_ascii_string); | 11352 __ bind(&seq_string); |
11362 // eax: subject string (flat ascii) | 11353 // eax: subject string (sequential either ascii to two byte) |
| 11354 // ebx: suject string type & kStringRepresentationEncodingMask |
11363 // ecx: RegExp data (FixedArray) | 11355 // ecx: RegExp data (FixedArray) |
| 11356 // Check that the irregexp code has been generated for an ascii string. If |
| 11357 // it has, the field contains a code object otherwise it contains the hole. |
| 11358 const int kSeqTwoByteString = kStringTag | kSeqStringTag | kTwoByteStringTag; |
| 11359 __ cmp(ebx, kSeqTwoByteString); |
| 11360 __ j(equal, &seq_two_byte_string); |
| 11361 if (FLAG_debug_code) { |
| 11362 __ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag); |
| 11363 __ Check(equal, "Expected sequential ascii string"); |
| 11364 } |
11364 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); | 11365 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); |
11365 __ Set(edi, Immediate(1)); // Type is ascii. | 11366 __ Set(edi, Immediate(1)); // Type is ascii. |
11366 __ jmp(&check_code); | 11367 __ jmp(&check_code); |
11367 | 11368 |
11368 __ bind(&seq_two_byte_string); | 11369 __ bind(&seq_two_byte_string); |
11369 // eax: subject string (flat two byte) | 11370 // eax: subject string |
11370 // ecx: RegExp data (FixedArray) | 11371 // ecx: RegExp data (FixedArray) |
11371 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); | 11372 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); |
11372 __ Set(edi, Immediate(0)); // Type is two byte. | 11373 __ Set(edi, Immediate(0)); // Type is two byte. |
11373 | 11374 |
11374 __ bind(&check_code); | 11375 __ bind(&check_code); |
11375 // Check that the irregexp code has been generated for the actual string | 11376 // Check that the irregexp code has been generated for the actual string |
11376 // encoding. If it has, the field contains a code object otherwise it contains | 11377 // encoding. If it has, the field contains a code object otherwise it contains |
11377 // the hole. | 11378 // the hole. |
11378 __ CmpObjectType(edx, CODE_TYPE, ebx); | 11379 __ CmpObjectType(edx, CODE_TYPE, ebx); |
11379 __ j(not_equal, &runtime); | 11380 __ j(not_equal, &runtime); |
(...skipping 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12765 | 12766 |
12766 void StringAddStub::Generate(MacroAssembler* masm) { | 12767 void StringAddStub::Generate(MacroAssembler* masm) { |
12767 Label string_add_runtime; | 12768 Label string_add_runtime; |
12768 | 12769 |
12769 // Load the two arguments. | 12770 // Load the two arguments. |
12770 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. | 12771 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. |
12771 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. | 12772 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. |
12772 | 12773 |
12773 // Make sure that both arguments are strings if not known in advance. | 12774 // Make sure that both arguments are strings if not known in advance. |
12774 if (string_check_) { | 12775 if (string_check_) { |
12775 __ mov(ecx, eax); | 12776 __ test(eax, Immediate(kSmiTagMask)); |
12776 __ and_(Operand(ecx), edx); | |
12777 __ test(ecx, Immediate(kSmiTagMask)); | |
12778 __ j(zero, &string_add_runtime); | 12777 __ j(zero, &string_add_runtime); |
12779 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 12778 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx); |
12780 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 12779 __ j(above_equal, &string_add_runtime); |
12781 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 12780 |
12782 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 12781 // First argument is a a string, test second. |
12783 __ or_(Operand(ecx), ebx); | 12782 __ test(edx, Immediate(kSmiTagMask)); |
12784 __ test_b(Operand(ecx), kIsNotStringMask); | 12783 __ j(zero, &string_add_runtime); |
12785 __ j(not_zero, &string_add_runtime); | 12784 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); |
| 12785 __ j(above_equal, &string_add_runtime); |
12786 } | 12786 } |
12787 | 12787 |
12788 // Both arguments are strings. | 12788 // Both arguments are strings. |
12789 // eax: first string | 12789 // eax: first string |
12790 // edx: second string | 12790 // edx: second string |
12791 // Check if either of the strings are empty. In that case return the other. | 12791 // Check if either of the strings are empty. In that case return the other. |
12792 Label second_not_zero_length, both_not_zero_length; | 12792 Label second_not_zero_length, both_not_zero_length; |
12793 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); | 12793 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); |
12794 ASSERT(kSmiTag == 0); | 12794 ASSERT(kSmiTag == 0); |
12795 __ test(ecx, Operand(ecx)); | 12795 __ test(ecx, Operand(ecx)); |
(...skipping 10 matching lines...) Expand all Loading... |
12806 __ mov(eax, edx); | 12806 __ mov(eax, edx); |
12807 __ IncrementCounter(&Counters::string_add_native, 1); | 12807 __ IncrementCounter(&Counters::string_add_native, 1); |
12808 __ ret(2 * kPointerSize); | 12808 __ ret(2 * kPointerSize); |
12809 | 12809 |
12810 // Both strings are non-empty. | 12810 // Both strings are non-empty. |
12811 // eax: first string | 12811 // eax: first string |
12812 // ebx: length of first string as a smi | 12812 // ebx: length of first string as a smi |
12813 // ecx: length of second string as a smi | 12813 // ecx: length of second string as a smi |
12814 // edx: second string | 12814 // edx: second string |
12815 // Look at the length of the result of adding the two strings. | 12815 // Look at the length of the result of adding the two strings. |
12816 Label make_two_character_string, longer_than_two, | 12816 Label string_add_flat_result, longer_than_two; |
12817 make_flat_string, make_flat_ascii_string, make_flat_non_ascii_string; | |
12818 __ bind(&both_not_zero_length); | 12817 __ bind(&both_not_zero_length); |
12819 __ add(ebx, Operand(ecx)); | 12818 __ add(ebx, Operand(ecx)); |
12820 ASSERT(Smi::kMaxValue == String::kMaxLength); | 12819 ASSERT(Smi::kMaxValue == String::kMaxLength); |
12821 // Handle exceptionally long strings in the runtime system. | 12820 // Handle exceptionally long strings in the runtime system. |
12822 __ j(overflow, &string_add_runtime); | 12821 __ j(overflow, &string_add_runtime); |
12823 // Use the runtime system when adding two one character strings, as it | 12822 // Use the runtime system when adding two one character strings, as it |
12824 // contains optimizations for this specific case using the symbol table. | 12823 // contains optimizations for this specific case using the symbol table. |
12825 __ cmp(Operand(ebx), Immediate(Smi::FromInt(2))); | 12824 __ cmp(Operand(ebx), Immediate(Smi::FromInt(2))); |
12826 __ j(not_equal, &longer_than_two); | 12825 __ j(not_equal, &longer_than_two); |
12827 | 12826 |
12828 // Check that both strings are non-external ascii strings. | 12827 // Check that both strings are non-external ascii strings. |
12829 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, | 12828 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, |
12830 &string_add_runtime); | 12829 &string_add_runtime); |
12831 | 12830 |
12832 // Get the two characters forming the sub string. | 12831 // Get the two characters forming the sub string. |
12833 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); | 12832 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); |
12834 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); | 12833 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); |
12835 | 12834 |
12836 // Try to lookup two character string in symbol table. If it is not found | 12835 // Try to lookup two character string in symbol table. If it is not found |
12837 // just allocate a new one. | 12836 // just allocate a new one. |
| 12837 Label make_two_character_string, make_flat_ascii_string; |
12838 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 12838 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
12839 masm, ebx, ecx, eax, edx, edi, &make_two_character_string); | 12839 masm, ebx, ecx, eax, edx, edi, &make_two_character_string); |
12840 __ IncrementCounter(&Counters::string_add_native, 1); | 12840 __ IncrementCounter(&Counters::string_add_native, 1); |
12841 __ ret(2 * kPointerSize); | 12841 __ ret(2 * kPointerSize); |
12842 | 12842 |
12843 __ bind(&make_two_character_string); | 12843 __ bind(&make_two_character_string); |
12844 __ Set(ebx, Immediate(Smi::FromInt(2))); | 12844 __ Set(ebx, Immediate(Smi::FromInt(2))); |
12845 __ jmp(&make_flat_ascii_string); | 12845 __ jmp(&make_flat_ascii_string); |
12846 | 12846 |
12847 __ bind(&longer_than_two); | 12847 __ bind(&longer_than_two); |
12848 // Check if resulting string will be flat. | 12848 // Check if resulting string will be flat. |
12849 __ cmp(Operand(ebx), Immediate(Smi::FromInt(String::kMinNonFlatLength))); | 12849 __ cmp(Operand(ebx), Immediate(Smi::FromInt(String::kMinNonFlatLength))); |
12850 __ j(below, &make_flat_string); | 12850 __ j(below, &string_add_flat_result); |
12851 | 12851 |
12852 // If result is not supposed to be flat allocate a cons string object. If both | 12852 // If result is not supposed to be flat allocate a cons string object. If both |
12853 // strings are ascii the result is an ascii cons string. | 12853 // strings are ascii the result is an ascii cons string. |
12854 Label non_ascii, allocated; | 12854 Label non_ascii, allocated; |
12855 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset)); | 12855 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset)); |
12856 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset)); | 12856 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset)); |
12857 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 12857 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
12858 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset)); | 12858 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset)); |
12859 __ and_(ecx, Operand(edi)); | 12859 __ and_(ecx, Operand(edi)); |
12860 ASSERT(kStringEncodingMask == kAsciiStringTag); | 12860 ASSERT(kStringEncodingMask == kAsciiStringTag); |
(...skipping 10 matching lines...) Expand all Loading... |
12871 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax); | 12871 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax); |
12872 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx); | 12872 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx); |
12873 __ mov(eax, ecx); | 12873 __ mov(eax, ecx); |
12874 __ IncrementCounter(&Counters::string_add_native, 1); | 12874 __ IncrementCounter(&Counters::string_add_native, 1); |
12875 __ ret(2 * kPointerSize); | 12875 __ ret(2 * kPointerSize); |
12876 __ bind(&non_ascii); | 12876 __ bind(&non_ascii); |
12877 // Allocate a two byte cons string. | 12877 // Allocate a two byte cons string. |
12878 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime); | 12878 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime); |
12879 __ jmp(&allocated); | 12879 __ jmp(&allocated); |
12880 | 12880 |
12881 // Handle creating a flat result. Branch to runtime if either string | 12881 // Handle creating a flat result. First check that both strings are not |
12882 // is external or if they are not both ascii or both two-byte. | 12882 // external strings. |
12883 // Otherwise branch to ascii case or two-byte case. | |
12884 // eax: first string | 12883 // eax: first string |
12885 // ebx: length of resulting flat string as a smi | 12884 // ebx: length of resulting flat string as a smi |
12886 // edx: second string | 12885 // edx: second string |
12887 __ bind(&make_flat_string); | 12886 __ bind(&string_add_flat_result); |
12888 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 12887 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
12889 __ movzx_b(edi, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 12888 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
| 12889 __ and_(ecx, kStringRepresentationMask); |
| 12890 __ cmp(ecx, kExternalStringTag); |
| 12891 __ j(equal, &string_add_runtime); |
12890 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 12892 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
12891 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 12893 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
12892 __ or_(ecx, Operand(edi)); | 12894 __ and_(ecx, kStringRepresentationMask); |
12893 ASSERT(kExternalStringTag !=0); | 12895 __ cmp(ecx, kExternalStringTag); |
12894 ASSERT_EQ(0, kConsStringTag & kExternalStringTag); | 12896 __ j(equal, &string_add_runtime); |
12895 ASSERT_EQ(0, kSeqStringTag & kExternalStringTag); | 12897 // Now check if both strings are ascii strings. |
12896 ASSERT_EQ(0, kTwoByteStringTag); | 12898 // eax: first string |
12897 __ test_b(Operand(ecx), kExternalStringTag | kStringEncodingMask); | 12899 // ebx: length of resulting flat string as a smi |
12898 __ j(zero, &make_flat_non_ascii_string); // Neither is ascii or external. | 12900 // edx: second string |
12899 __ test_b(Operand(ecx), kExternalStringTag); | 12901 Label non_ascii_string_add_flat_result; |
12900 __ j(not_zero, &string_add_runtime); // One or both is external. | 12902 ASSERT(kStringEncodingMask == kAsciiStringTag); |
12901 | 12903 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
12902 // At this point, neither is external, and at least one is ascii. | 12904 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); |
12903 // Check that both are ascii, by computing mask & first type & second type. | 12905 __ j(zero, &non_ascii_string_add_flat_result); |
12904 __ and_(edi, kStringEncodingMask); | |
12905 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 12906 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
12906 __ test_b(edi, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 12907 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); |
12907 ASSERT(kAsciiStringTag != 0); | |
12908 __ j(zero, &string_add_runtime); | 12908 __ j(zero, &string_add_runtime); |
12909 | 12909 |
12910 __ bind(&make_flat_ascii_string); | 12910 __ bind(&make_flat_ascii_string); |
12911 // Both strings are ascii strings. As they are short they are both flat. | 12911 // Both strings are ascii strings. As they are short they are both flat. |
12912 // Create a flat ascii result. | |
12913 // ebx: length of resulting flat string as a smi | 12912 // ebx: length of resulting flat string as a smi |
12914 __ SmiUntag(ebx); | 12913 __ SmiUntag(ebx); |
12915 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime); | 12914 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime); |
12916 // eax: result string | 12915 // eax: result string |
12917 __ mov(ecx, eax); | 12916 __ mov(ecx, eax); |
12918 // Locate first character of result. | 12917 // Locate first character of result. |
12919 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 12918 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
12920 // Load first argument and locate first character. | 12919 // Load first argument and locate first character. |
12921 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 12920 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
12922 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); | 12921 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); |
(...skipping 10 matching lines...) Expand all Loading... |
12933 __ SmiUntag(edi); | 12932 __ SmiUntag(edi); |
12934 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 12933 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
12935 // eax: result string | 12934 // eax: result string |
12936 // ecx: next character of result | 12935 // ecx: next character of result |
12937 // edx: first char of second argument | 12936 // edx: first char of second argument |
12938 // edi: length of second argument | 12937 // edi: length of second argument |
12939 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); | 12938 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); |
12940 __ IncrementCounter(&Counters::string_add_native, 1); | 12939 __ IncrementCounter(&Counters::string_add_native, 1); |
12941 __ ret(2 * kPointerSize); | 12940 __ ret(2 * kPointerSize); |
12942 | 12941 |
12943 // Both strings are two-byte strings. As they are short they are both flat. | 12942 // Handle creating a flat two byte result. |
12944 // Create a flat two byte result. | 12943 // eax: first string - known to be two byte |
12945 // ebx: length of resulting flat string as a smi | 12944 // ebx: length of resulting flat string as a smi |
12946 __ bind(&make_flat_non_ascii_string); | 12945 // edx: second string |
| 12946 __ bind(&non_ascii_string_add_flat_result); |
| 12947 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 12948 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); |
| 12949 __ j(not_zero, &string_add_runtime); |
12947 // Both strings are two byte strings. As they are short they are both | 12950 // Both strings are two byte strings. As they are short they are both |
12948 // flat. | 12951 // flat. |
12949 __ SmiUntag(ebx); | 12952 __ SmiUntag(ebx); |
12950 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime); | 12953 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime); |
12951 // eax: result string | 12954 // eax: result string |
12952 __ mov(ecx, eax); | 12955 __ mov(ecx, eax); |
12953 // Locate first character of result. | 12956 // Locate first character of result. |
12954 __ add(Operand(ecx), | 12957 __ add(Operand(ecx), |
12955 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 12958 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
12956 // Load first argument and locate first character. | 12959 // Load first argument and locate first character. |
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13709 masm.GetCode(&desc); | 13712 masm.GetCode(&desc); |
13710 // Call the function from C++. | 13713 // Call the function from C++. |
13711 return FUNCTION_CAST<MemCopyFunction>(buffer); | 13714 return FUNCTION_CAST<MemCopyFunction>(buffer); |
13712 } | 13715 } |
13713 | 13716 |
13714 #undef __ | 13717 #undef __ |
13715 | 13718 |
13716 } } // namespace v8::internal | 13719 } } // namespace v8::internal |
13717 | 13720 |
13718 #endif // V8_TARGET_ARCH_IA32 | 13721 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |