OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 3870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3881 __ add(esi, edi); // Calculate input end wrt offset. | 3881 __ add(esi, edi); // Calculate input end wrt offset. |
3882 __ SmiUntag(edi); | 3882 __ SmiUntag(edi); |
3883 __ add(ebx, edi); // Calculate input start wrt offset. | 3883 __ add(ebx, edi); // Calculate input start wrt offset. |
3884 | 3884 |
3885 // ebx: start index of the input string | 3885 // ebx: start index of the input string |
3886 // esi: end index of the input string | 3886 // esi: end index of the input string |
3887 Label setup_two_byte, setup_rest; | 3887 Label setup_two_byte, setup_rest; |
3888 __ test(ecx, ecx); | 3888 __ test(ecx, ecx); |
3889 __ j(zero, &setup_two_byte, Label::kNear); | 3889 __ j(zero, &setup_two_byte, Label::kNear); |
3890 __ SmiUntag(esi); | 3890 __ SmiUntag(esi); |
3891 __ lea(ecx, FieldOperand(eax, esi, times_1, SeqAsciiString::kHeaderSize)); | 3891 __ lea(ecx, FieldOperand(eax, esi, times_1, SeqOneByteString::kHeaderSize)); |
3892 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. | 3892 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. |
3893 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); | 3893 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqOneByteString::kHeaderSize)); |
3894 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. | 3894 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. |
3895 __ jmp(&setup_rest, Label::kNear); | 3895 __ jmp(&setup_rest, Label::kNear); |
3896 | 3896 |
3897 __ bind(&setup_two_byte); | 3897 __ bind(&setup_two_byte); |
3898 STATIC_ASSERT(kSmiTag == 0); | 3898 STATIC_ASSERT(kSmiTag == 0); |
3899 STATIC_ASSERT(kSmiTagSize == 1); // esi is smi (powered by 2). | 3899 STATIC_ASSERT(kSmiTagSize == 1); // esi is smi (powered by 2). |
3900 __ lea(ecx, FieldOperand(eax, esi, times_1, SeqTwoByteString::kHeaderSize)); | 3900 __ lea(ecx, FieldOperand(eax, esi, times_1, SeqTwoByteString::kHeaderSize)); |
3901 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. | 3901 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. |
3902 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); | 3902 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); |
3903 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. | 3903 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4029 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 4029 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
4030 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 4030 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
4031 if (FLAG_debug_code) { | 4031 if (FLAG_debug_code) { |
4032 // Assert that we do not have a cons or slice (indirect strings) here. | 4032 // Assert that we do not have a cons or slice (indirect strings) here. |
4033 // Sequential strings have already been ruled out. | 4033 // Sequential strings have already been ruled out. |
4034 __ test_b(ebx, kIsIndirectStringMask); | 4034 __ test_b(ebx, kIsIndirectStringMask); |
4035 __ Assert(zero, "external string expected, but not found"); | 4035 __ Assert(zero, "external string expected, but not found"); |
4036 } | 4036 } |
4037 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); | 4037 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); |
4038 // Move the pointer so that offset-wise, it looks like a sequential string. | 4038 // Move the pointer so that offset-wise, it looks like a sequential string. |
4039 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 4039 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
4040 __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 4040 __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
4041 STATIC_ASSERT(kTwoByteStringTag == 0); | 4041 STATIC_ASSERT(kTwoByteStringTag == 0); |
4042 __ test_b(ebx, kStringEncodingMask); | 4042 __ test_b(ebx, kStringEncodingMask); |
4043 __ j(not_zero, &seq_ascii_string); | 4043 __ j(not_zero, &seq_ascii_string); |
4044 __ jmp(&seq_two_byte_string); | 4044 __ jmp(&seq_two_byte_string); |
4045 | 4045 |
4046 // Do the runtime call to execute the regexp. | 4046 // Do the runtime call to execute the regexp. |
4047 __ bind(&runtime); | 4047 __ bind(&runtime); |
4048 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 4048 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
4049 #endif // V8_INTERPRETED_REGEXP | 4049 #endif // V8_INTERPRETED_REGEXP |
(...skipping 1523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5573 __ j(overflow, &call_runtime); | 5573 __ j(overflow, &call_runtime); |
5574 // Use the symbol table when adding two one character strings, as it | 5574 // Use the symbol table when adding two one character strings, as it |
5575 // helps later optimizations to return a symbol here. | 5575 // helps later optimizations to return a symbol here. |
5576 __ cmp(ebx, Immediate(Smi::FromInt(2))); | 5576 __ cmp(ebx, Immediate(Smi::FromInt(2))); |
5577 __ j(not_equal, &longer_than_two); | 5577 __ j(not_equal, &longer_than_two); |
5578 | 5578 |
5579 // Check that both strings are non-external ASCII strings. | 5579 // Check that both strings are non-external ASCII strings. |
5580 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime); | 5580 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime); |
5581 | 5581 |
5582 // Get the two characters forming the new string. | 5582 // Get the two characters forming the new string. |
5583 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); | 5583 __ movzx_b(ebx, FieldOperand(eax, SeqOneByteString::kHeaderSize)); |
5584 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); | 5584 __ movzx_b(ecx, FieldOperand(edx, SeqOneByteString::kHeaderSize)); |
5585 | 5585 |
5586 // Try to lookup two character string in symbol table. If it is not found | 5586 // Try to lookup two character string in symbol table. If it is not found |
5587 // just allocate a new one. | 5587 // just allocate a new one. |
5588 Label make_two_character_string, make_two_character_string_no_reload; | 5588 Label make_two_character_string, make_two_character_string_no_reload; |
5589 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 5589 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
5590 masm, ebx, ecx, eax, edx, edi, | 5590 masm, ebx, ecx, eax, edx, edi, |
5591 &make_two_character_string_no_reload, &make_two_character_string); | 5591 &make_two_character_string_no_reload, &make_two_character_string); |
5592 __ IncrementCounter(counters->string_add_native(), 1); | 5592 __ IncrementCounter(counters->string_add_native(), 1); |
5593 __ ret(2 * kPointerSize); | 5593 __ ret(2 * kPointerSize); |
5594 | 5594 |
5595 // Allocate a two character string. | 5595 // Allocate a two character string. |
5596 __ bind(&make_two_character_string); | 5596 __ bind(&make_two_character_string); |
5597 // Reload the arguments. | 5597 // Reload the arguments. |
5598 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. | 5598 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. |
5599 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. | 5599 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. |
5600 // Get the two characters forming the new string. | 5600 // Get the two characters forming the new string. |
5601 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); | 5601 __ movzx_b(ebx, FieldOperand(eax, SeqOneByteString::kHeaderSize)); |
5602 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); | 5602 __ movzx_b(ecx, FieldOperand(edx, SeqOneByteString::kHeaderSize)); |
5603 __ bind(&make_two_character_string_no_reload); | 5603 __ bind(&make_two_character_string_no_reload); |
5604 __ IncrementCounter(counters->string_add_make_two_char(), 1); | 5604 __ IncrementCounter(counters->string_add_make_two_char(), 1); |
5605 __ AllocateAsciiString(eax, 2, edi, edx, &call_runtime); | 5605 __ AllocateAsciiString(eax, 2, edi, edx, &call_runtime); |
5606 // Pack both characters in ebx. | 5606 // Pack both characters in ebx. |
5607 __ shl(ecx, kBitsPerByte); | 5607 __ shl(ecx, kBitsPerByte); |
5608 __ or_(ebx, ecx); | 5608 __ or_(ebx, ecx); |
5609 // Set the characters in the new string. | 5609 // Set the characters in the new string. |
5610 __ mov_w(FieldOperand(eax, SeqAsciiString::kHeaderSize), ebx); | 5610 __ mov_w(FieldOperand(eax, SeqOneByteString::kHeaderSize), ebx); |
5611 __ IncrementCounter(counters->string_add_native(), 1); | 5611 __ IncrementCounter(counters->string_add_native(), 1); |
5612 __ ret(2 * kPointerSize); | 5612 __ ret(2 * kPointerSize); |
5613 | 5613 |
5614 __ bind(&longer_than_two); | 5614 __ bind(&longer_than_two); |
5615 // Check if resulting string will be flat. | 5615 // Check if resulting string will be flat. |
5616 __ cmp(ebx, Immediate(Smi::FromInt(ConsString::kMinLength))); | 5616 __ cmp(ebx, Immediate(Smi::FromInt(ConsString::kMinLength))); |
5617 __ j(below, &string_add_flat_result); | 5617 __ j(below, &string_add_flat_result); |
5618 | 5618 |
5619 // If result is not supposed to be flat allocate a cons string object. If both | 5619 // If result is not supposed to be flat allocate a cons string object. If both |
5620 // strings are ASCII the result is an ASCII cons string. | 5620 // strings are ASCII the result is an ASCII cons string. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5667 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 5667 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
5668 // ecx: instance type of first string | 5668 // ecx: instance type of first string |
5669 STATIC_ASSERT(kSeqStringTag == 0); | 5669 STATIC_ASSERT(kSeqStringTag == 0); |
5670 __ test_b(ecx, kStringRepresentationMask); | 5670 __ test_b(ecx, kStringRepresentationMask); |
5671 __ j(zero, &first_is_sequential, Label::kNear); | 5671 __ j(zero, &first_is_sequential, Label::kNear); |
5672 // Rule out short external string and load string resource. | 5672 // Rule out short external string and load string resource. |
5673 STATIC_ASSERT(kShortExternalStringTag != 0); | 5673 STATIC_ASSERT(kShortExternalStringTag != 0); |
5674 __ test_b(ecx, kShortExternalStringMask); | 5674 __ test_b(ecx, kShortExternalStringMask); |
5675 __ j(not_zero, &call_runtime); | 5675 __ j(not_zero, &call_runtime); |
5676 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); | 5676 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); |
5677 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); | 5677 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
5678 __ jmp(&first_prepared, Label::kNear); | 5678 __ jmp(&first_prepared, Label::kNear); |
5679 __ bind(&first_is_sequential); | 5679 __ bind(&first_is_sequential); |
5680 __ add(eax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 5680 __ add(eax, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
5681 __ bind(&first_prepared); | 5681 __ bind(&first_prepared); |
5682 | 5682 |
5683 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 5683 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
5684 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset)); | 5684 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset)); |
5685 // Check whether both strings have same encoding. | 5685 // Check whether both strings have same encoding. |
5686 // edi: instance type of second string | 5686 // edi: instance type of second string |
5687 __ xor_(ecx, edi); | 5687 __ xor_(ecx, edi); |
5688 __ test_b(ecx, kStringEncodingMask); | 5688 __ test_b(ecx, kStringEncodingMask); |
5689 __ j(not_zero, &call_runtime); | 5689 __ j(not_zero, &call_runtime); |
5690 STATIC_ASSERT(kSeqStringTag == 0); | 5690 STATIC_ASSERT(kSeqStringTag == 0); |
5691 __ test_b(edi, kStringRepresentationMask); | 5691 __ test_b(edi, kStringRepresentationMask); |
5692 __ j(zero, &second_is_sequential, Label::kNear); | 5692 __ j(zero, &second_is_sequential, Label::kNear); |
5693 // Rule out short external string and load string resource. | 5693 // Rule out short external string and load string resource. |
5694 STATIC_ASSERT(kShortExternalStringTag != 0); | 5694 STATIC_ASSERT(kShortExternalStringTag != 0); |
5695 __ test_b(edi, kShortExternalStringMask); | 5695 __ test_b(edi, kShortExternalStringMask); |
5696 __ j(not_zero, &call_runtime); | 5696 __ j(not_zero, &call_runtime); |
5697 __ mov(edx, FieldOperand(edx, ExternalString::kResourceDataOffset)); | 5697 __ mov(edx, FieldOperand(edx, ExternalString::kResourceDataOffset)); |
5698 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); | 5698 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
5699 __ jmp(&second_prepared, Label::kNear); | 5699 __ jmp(&second_prepared, Label::kNear); |
5700 __ bind(&second_is_sequential); | 5700 __ bind(&second_is_sequential); |
5701 __ add(edx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 5701 __ add(edx, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
5702 __ bind(&second_prepared); | 5702 __ bind(&second_prepared); |
5703 | 5703 |
5704 // Push the addresses of both strings' first characters onto the stack. | 5704 // Push the addresses of both strings' first characters onto the stack. |
5705 __ push(edx); | 5705 __ push(edx); |
5706 __ push(eax); | 5706 __ push(eax); |
5707 | 5707 |
5708 Label non_ascii_string_add_flat_result, call_runtime_drop_two; | 5708 Label non_ascii_string_add_flat_result, call_runtime_drop_two; |
5709 // edi: instance type of second string | 5709 // edi: instance type of second string |
5710 // First string and second string have the same encoding. | 5710 // First string and second string have the same encoding. |
5711 STATIC_ASSERT(kTwoByteStringTag == 0); | 5711 STATIC_ASSERT(kTwoByteStringTag == 0); |
5712 __ test_b(edi, kStringEncodingMask); | 5712 __ test_b(edi, kStringEncodingMask); |
5713 __ j(zero, &non_ascii_string_add_flat_result); | 5713 __ j(zero, &non_ascii_string_add_flat_result); |
5714 | 5714 |
5715 // Both strings are ASCII strings. | 5715 // Both strings are ASCII strings. |
5716 // ebx: length of resulting flat string as a smi | 5716 // ebx: length of resulting flat string as a smi |
5717 __ SmiUntag(ebx); | 5717 __ SmiUntag(ebx); |
5718 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two); | 5718 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two); |
5719 // eax: result string | 5719 // eax: result string |
5720 __ mov(ecx, eax); | 5720 __ mov(ecx, eax); |
5721 // Locate first character of result. | 5721 // Locate first character of result. |
5722 __ add(ecx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 5722 __ add(ecx, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
5723 // Load first argument's length and first character location. Account for | 5723 // Load first argument's length and first character location. Account for |
5724 // values currently on the stack when fetching arguments from it. | 5724 // values currently on the stack when fetching arguments from it. |
5725 __ mov(edx, Operand(esp, 4 * kPointerSize)); | 5725 __ mov(edx, Operand(esp, 4 * kPointerSize)); |
5726 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); | 5726 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); |
5727 __ SmiUntag(edi); | 5727 __ SmiUntag(edi); |
5728 __ pop(edx); | 5728 __ pop(edx); |
5729 // eax: result string | 5729 // eax: result string |
5730 // ecx: first character of result | 5730 // ecx: first character of result |
5731 // edx: first char of first argument | 5731 // edx: first char of first argument |
5732 // edi: length of first argument | 5732 // edi: length of first argument |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6022 __ push(mask); | 6022 __ push(mask); |
6023 Register temp = mask; | 6023 Register temp = mask; |
6024 | 6024 |
6025 // Check that the candidate is a non-external ASCII string. | 6025 // Check that the candidate is a non-external ASCII string. |
6026 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset)); | 6026 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset)); |
6027 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); | 6027 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
6028 __ JumpIfInstanceTypeIsNotSequentialAscii( | 6028 __ JumpIfInstanceTypeIsNotSequentialAscii( |
6029 temp, temp, &next_probe_pop_mask[i]); | 6029 temp, temp, &next_probe_pop_mask[i]); |
6030 | 6030 |
6031 // Check if the two characters match. | 6031 // Check if the two characters match. |
6032 __ mov(temp, FieldOperand(candidate, SeqAsciiString::kHeaderSize)); | 6032 __ mov(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize)); |
6033 __ and_(temp, 0x0000ffff); | 6033 __ and_(temp, 0x0000ffff); |
6034 __ cmp(chars, temp); | 6034 __ cmp(chars, temp); |
6035 __ j(equal, &found_in_symbol_table); | 6035 __ j(equal, &found_in_symbol_table); |
6036 __ bind(&next_probe_pop_mask[i]); | 6036 __ bind(&next_probe_pop_mask[i]); |
6037 __ pop(mask); | 6037 __ pop(mask); |
6038 __ bind(&next_probe[i]); | 6038 __ bind(&next_probe[i]); |
6039 } | 6039 } |
6040 | 6040 |
6041 // No matching 2 character string found by probing. | 6041 // No matching 2 character string found by probing. |
6042 __ jmp(not_found); | 6042 __ jmp(not_found); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6250 __ test_b(ebx, kExternalStringTag); | 6250 __ test_b(ebx, kExternalStringTag); |
6251 __ j(zero, &sequential_string); | 6251 __ j(zero, &sequential_string); |
6252 | 6252 |
6253 // Handle external string. | 6253 // Handle external string. |
6254 // Rule out short external strings. | 6254 // Rule out short external strings. |
6255 STATIC_CHECK(kShortExternalStringTag != 0); | 6255 STATIC_CHECK(kShortExternalStringTag != 0); |
6256 __ test_b(ebx, kShortExternalStringMask); | 6256 __ test_b(ebx, kShortExternalStringMask); |
6257 __ j(not_zero, &runtime); | 6257 __ j(not_zero, &runtime); |
6258 __ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset)); | 6258 __ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset)); |
6259 // Move the pointer so that offset-wise, it looks like a sequential string. | 6259 // Move the pointer so that offset-wise, it looks like a sequential string. |
6260 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 6260 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
6261 __ sub(edi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 6261 __ sub(edi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
6262 | 6262 |
6263 __ bind(&sequential_string); | 6263 __ bind(&sequential_string); |
6264 // Stash away (adjusted) index and (underlying) string. | 6264 // Stash away (adjusted) index and (underlying) string. |
6265 __ push(edx); | 6265 __ push(edx); |
6266 __ push(edi); | 6266 __ push(edi); |
6267 __ SmiUntag(ecx); | 6267 __ SmiUntag(ecx); |
6268 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 6268 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); |
6269 __ test_b(ebx, kStringEncodingMask); | 6269 __ test_b(ebx, kStringEncodingMask); |
6270 __ j(zero, &two_byte_sequential); | 6270 __ j(zero, &two_byte_sequential); |
6271 | 6271 |
6272 // Sequential ASCII string. Allocate the result. | 6272 // Sequential ASCII string. Allocate the result. |
6273 __ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime_drop_two); | 6273 __ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime_drop_two); |
6274 | 6274 |
6275 // eax: result string | 6275 // eax: result string |
6276 // ecx: result string length | 6276 // ecx: result string length |
6277 __ mov(edx, esi); // esi used by following code. | 6277 __ mov(edx, esi); // esi used by following code. |
6278 // Locate first character of result. | 6278 // Locate first character of result. |
6279 __ mov(edi, eax); | 6279 __ mov(edi, eax); |
6280 __ add(edi, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 6280 __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
6281 // Load string argument and locate character of sub string start. | 6281 // Load string argument and locate character of sub string start. |
6282 __ pop(esi); | 6282 __ pop(esi); |
6283 __ pop(ebx); | 6283 __ pop(ebx); |
6284 __ SmiUntag(ebx); | 6284 __ SmiUntag(ebx); |
6285 __ lea(esi, FieldOperand(esi, ebx, times_1, SeqAsciiString::kHeaderSize)); | 6285 __ lea(esi, FieldOperand(esi, ebx, times_1, SeqOneByteString::kHeaderSize)); |
6286 | 6286 |
6287 // eax: result string | 6287 // eax: result string |
6288 // ecx: result length | 6288 // ecx: result length |
6289 // edx: original value of esi | 6289 // edx: original value of esi |
6290 // edi: first character of result | 6290 // edi: first character of result |
6291 // esi: character of sub string start | 6291 // esi: character of sub string start |
6292 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true); | 6292 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true); |
6293 __ mov(esi, edx); // Restore esi. | 6293 __ mov(esi, edx); // Restore esi. |
6294 __ IncrementCounter(counters->sub_string_native(), 1); | 6294 __ IncrementCounter(counters->sub_string_native(), 1); |
6295 __ ret(3 * kPointerSize); | 6295 __ ret(3 * kPointerSize); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6436 Register right, | 6436 Register right, |
6437 Register length, | 6437 Register length, |
6438 Register scratch, | 6438 Register scratch, |
6439 Label* chars_not_equal, | 6439 Label* chars_not_equal, |
6440 Label::Distance chars_not_equal_near) { | 6440 Label::Distance chars_not_equal_near) { |
6441 // Change index to run from -length to -1 by adding length to string | 6441 // Change index to run from -length to -1 by adding length to string |
6442 // start. This means that loop ends when index reaches zero, which | 6442 // start. This means that loop ends when index reaches zero, which |
6443 // doesn't need an additional compare. | 6443 // doesn't need an additional compare. |
6444 __ SmiUntag(length); | 6444 __ SmiUntag(length); |
6445 __ lea(left, | 6445 __ lea(left, |
6446 FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize)); | 6446 FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize)); |
6447 __ lea(right, | 6447 __ lea(right, |
6448 FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize)); | 6448 FieldOperand(right, length, times_1, SeqOneByteString::kHeaderSize)); |
6449 __ neg(length); | 6449 __ neg(length); |
6450 Register index = length; // index = -length; | 6450 Register index = length; // index = -length; |
6451 | 6451 |
6452 // Compare loop. | 6452 // Compare loop. |
6453 Label loop; | 6453 Label loop; |
6454 __ bind(&loop); | 6454 __ bind(&loop); |
6455 __ mov_b(scratch, Operand(left, index, times_1, 0)); | 6455 __ mov_b(scratch, Operand(left, index, times_1, 0)); |
6456 __ cmpb(scratch, Operand(right, index, times_1, 0)); | 6456 __ cmpb(scratch, Operand(right, index, times_1, 0)); |
6457 __ j(not_equal, chars_not_equal, chars_not_equal_near); | 6457 __ j(not_equal, chars_not_equal, chars_not_equal_near); |
6458 __ inc(index); | 6458 __ inc(index); |
(...skipping 996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7455 // Restore ecx. | 7455 // Restore ecx. |
7456 __ pop(ecx); | 7456 __ pop(ecx); |
7457 __ ret(0); | 7457 __ ret(0); |
7458 } | 7458 } |
7459 | 7459 |
7460 #undef __ | 7460 #undef __ |
7461 | 7461 |
7462 } } // namespace v8::internal | 7462 } } // namespace v8::internal |
7463 | 7463 |
7464 #endif // V8_TARGET_ARCH_IA32 | 7464 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |