| 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 |