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 2996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3007 // Load the length from the original sliced string if that is the case. | 3007 // Load the length from the original sliced string if that is the case. |
3008 __ addq(rbx, r14); | 3008 __ addq(rbx, r14); |
3009 __ SmiToInteger32(arg3, FieldOperand(r15, String::kLengthOffset)); | 3009 __ SmiToInteger32(arg3, FieldOperand(r15, String::kLengthOffset)); |
3010 __ addq(r14, arg3); // Using arg3 as scratch. | 3010 __ addq(r14, arg3); // Using arg3 as scratch. |
3011 | 3011 |
3012 // rbx: start index of the input | 3012 // rbx: start index of the input |
3013 // r14: end index of the input | 3013 // r14: end index of the input |
3014 // r15: original subject string | 3014 // r15: original subject string |
3015 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. | 3015 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. |
3016 __ j(zero, &setup_two_byte, Label::kNear); | 3016 __ j(zero, &setup_two_byte, Label::kNear); |
3017 __ lea(arg4, FieldOperand(rdi, r14, times_1, SeqAsciiString::kHeaderSize)); | 3017 __ lea(arg4, FieldOperand(rdi, r14, times_1, SeqOneByteString::kHeaderSize)); |
3018 __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize)); | 3018 __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqOneByteString::kHeaderSize)); |
3019 __ jmp(&setup_rest, Label::kNear); | 3019 __ jmp(&setup_rest, Label::kNear); |
3020 __ bind(&setup_two_byte); | 3020 __ bind(&setup_two_byte); |
3021 __ lea(arg4, FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize)); | 3021 __ lea(arg4, FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize)); |
3022 __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); | 3022 __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); |
3023 __ bind(&setup_rest); | 3023 __ bind(&setup_rest); |
3024 | 3024 |
3025 // Argument 1: Original subject string. | 3025 // Argument 1: Original subject string. |
3026 // The original subject is in the previous stack frame. Therefore we have to | 3026 // The original subject is in the previous stack frame. Therefore we have to |
3027 // use rbp, which points exactly to one pointer size below the previous rsp. | 3027 // use rbp, which points exactly to one pointer size below the previous rsp. |
3028 // (Because creating a new stack frame pushes the previous rbp onto the stack | 3028 // (Because creating a new stack frame pushes the previous rbp onto the stack |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3148 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 3148 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
3149 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 3149 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
3150 if (FLAG_debug_code) { | 3150 if (FLAG_debug_code) { |
3151 // Assert that we do not have a cons or slice (indirect strings) here. | 3151 // Assert that we do not have a cons or slice (indirect strings) here. |
3152 // Sequential strings have already been ruled out. | 3152 // Sequential strings have already been ruled out. |
3153 __ testb(rbx, Immediate(kIsIndirectStringMask)); | 3153 __ testb(rbx, Immediate(kIsIndirectStringMask)); |
3154 __ Assert(zero, "external string expected, but not found"); | 3154 __ Assert(zero, "external string expected, but not found"); |
3155 } | 3155 } |
3156 __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); | 3156 __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); |
3157 // Move the pointer so that offset-wise, it looks like a sequential string. | 3157 // Move the pointer so that offset-wise, it looks like a sequential string. |
3158 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 3158 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
3159 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 3159 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
3160 STATIC_ASSERT(kTwoByteStringTag == 0); | 3160 STATIC_ASSERT(kTwoByteStringTag == 0); |
3161 __ testb(rbx, Immediate(kStringEncodingMask)); | 3161 __ testb(rbx, Immediate(kStringEncodingMask)); |
3162 __ j(not_zero, &seq_ascii_string); | 3162 __ j(not_zero, &seq_ascii_string); |
3163 __ jmp(&seq_two_byte_string); | 3163 __ jmp(&seq_two_byte_string); |
3164 | 3164 |
3165 // Do the runtime call to execute the regexp. | 3165 // Do the runtime call to execute the regexp. |
3166 __ bind(&runtime); | 3166 __ bind(&runtime); |
3167 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 3167 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
3168 #endif // V8_INTERPRETED_REGEXP | 3168 #endif // V8_INTERPRETED_REGEXP |
(...skipping 1480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4649 // Use the symbol table when adding two one character strings, as it | 4649 // Use the symbol table when adding two one character strings, as it |
4650 // helps later optimizations to return a symbol here. | 4650 // helps later optimizations to return a symbol here. |
4651 __ SmiCompare(rbx, Smi::FromInt(2)); | 4651 __ SmiCompare(rbx, Smi::FromInt(2)); |
4652 __ j(not_equal, &longer_than_two); | 4652 __ j(not_equal, &longer_than_two); |
4653 | 4653 |
4654 // Check that both strings are non-external ASCII strings. | 4654 // Check that both strings are non-external ASCII strings. |
4655 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, | 4655 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, |
4656 &call_runtime); | 4656 &call_runtime); |
4657 | 4657 |
4658 // Get the two characters forming the sub string. | 4658 // Get the two characters forming the sub string. |
4659 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); | 4659 __ movzxbq(rbx, FieldOperand(rax, SeqOneByteString::kHeaderSize)); |
4660 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); | 4660 __ movzxbq(rcx, FieldOperand(rdx, SeqOneByteString::kHeaderSize)); |
4661 | 4661 |
4662 // Try to lookup two character string in symbol table. If it is not found | 4662 // Try to lookup two character string in symbol table. If it is not found |
4663 // just allocate a new one. | 4663 // just allocate a new one. |
4664 Label make_two_character_string, make_flat_ascii_string; | 4664 Label make_two_character_string, make_flat_ascii_string; |
4665 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 4665 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
4666 masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string); | 4666 masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string); |
4667 __ IncrementCounter(counters->string_add_native(), 1); | 4667 __ IncrementCounter(counters->string_add_native(), 1); |
4668 __ ret(2 * kPointerSize); | 4668 __ ret(2 * kPointerSize); |
4669 | 4669 |
4670 __ bind(&make_two_character_string); | 4670 __ bind(&make_two_character_string); |
4671 __ Set(rdi, 2); | 4671 __ Set(rdi, 2); |
4672 __ AllocateAsciiString(rax, rdi, r8, r9, r11, &call_runtime); | 4672 __ AllocateAsciiString(rax, rdi, r8, r9, r11, &call_runtime); |
4673 // rbx - first byte: first character | 4673 // rbx - first byte: first character |
4674 // rbx - second byte: *maybe* second character | 4674 // rbx - second byte: *maybe* second character |
4675 // Make sure that the second byte of rbx contains the second character. | 4675 // Make sure that the second byte of rbx contains the second character. |
4676 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); | 4676 __ movzxbq(rcx, FieldOperand(rdx, SeqOneByteString::kHeaderSize)); |
4677 __ shll(rcx, Immediate(kBitsPerByte)); | 4677 __ shll(rcx, Immediate(kBitsPerByte)); |
4678 __ orl(rbx, rcx); | 4678 __ orl(rbx, rcx); |
4679 // Write both characters to the new string. | 4679 // Write both characters to the new string. |
4680 __ movw(FieldOperand(rax, SeqAsciiString::kHeaderSize), rbx); | 4680 __ movw(FieldOperand(rax, SeqOneByteString::kHeaderSize), rbx); |
4681 __ IncrementCounter(counters->string_add_native(), 1); | 4681 __ IncrementCounter(counters->string_add_native(), 1); |
4682 __ ret(2 * kPointerSize); | 4682 __ ret(2 * kPointerSize); |
4683 | 4683 |
4684 __ bind(&longer_than_two); | 4684 __ bind(&longer_than_two); |
4685 // Check if resulting string will be flat. | 4685 // Check if resulting string will be flat. |
4686 __ SmiCompare(rbx, Smi::FromInt(ConsString::kMinLength)); | 4686 __ SmiCompare(rbx, Smi::FromInt(ConsString::kMinLength)); |
4687 __ j(below, &string_add_flat_result); | 4687 __ j(below, &string_add_flat_result); |
4688 // Handle exceptionally long strings in the runtime system. | 4688 // Handle exceptionally long strings in the runtime system. |
4689 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); | 4689 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); |
4690 __ SmiCompare(rbx, Smi::FromInt(String::kMaxLength)); | 4690 __ SmiCompare(rbx, Smi::FromInt(String::kMaxLength)); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4747 STATIC_ASSERT(kSeqStringTag == 0); | 4747 STATIC_ASSERT(kSeqStringTag == 0); |
4748 __ testb(r8, Immediate(kStringRepresentationMask)); | 4748 __ testb(r8, Immediate(kStringRepresentationMask)); |
4749 __ j(zero, &first_is_sequential, Label::kNear); | 4749 __ j(zero, &first_is_sequential, Label::kNear); |
4750 // Rule out short external string and load string resource. | 4750 // Rule out short external string and load string resource. |
4751 STATIC_ASSERT(kShortExternalStringTag != 0); | 4751 STATIC_ASSERT(kShortExternalStringTag != 0); |
4752 __ testb(r8, Immediate(kShortExternalStringMask)); | 4752 __ testb(r8, Immediate(kShortExternalStringMask)); |
4753 __ j(not_zero, &call_runtime); | 4753 __ j(not_zero, &call_runtime); |
4754 __ movq(rcx, FieldOperand(rax, ExternalString::kResourceDataOffset)); | 4754 __ movq(rcx, FieldOperand(rax, ExternalString::kResourceDataOffset)); |
4755 __ jmp(&first_prepared, Label::kNear); | 4755 __ jmp(&first_prepared, Label::kNear); |
4756 __ bind(&first_is_sequential); | 4756 __ bind(&first_is_sequential); |
4757 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); | 4757 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
4758 __ lea(rcx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); | 4758 __ lea(rcx, FieldOperand(rax, SeqOneByteString::kHeaderSize)); |
4759 __ bind(&first_prepared); | 4759 __ bind(&first_prepared); |
4760 | 4760 |
4761 // Check whether both strings have same encoding. | 4761 // Check whether both strings have same encoding. |
4762 __ xorl(r8, r9); | 4762 __ xorl(r8, r9); |
4763 __ testb(r8, Immediate(kStringEncodingMask)); | 4763 __ testb(r8, Immediate(kStringEncodingMask)); |
4764 __ j(not_zero, &call_runtime); | 4764 __ j(not_zero, &call_runtime); |
4765 | 4765 |
4766 __ SmiToInteger32(r15, FieldOperand(rdx, SeqString::kLengthOffset)); | 4766 __ SmiToInteger32(r15, FieldOperand(rdx, SeqString::kLengthOffset)); |
4767 // r15: length of second string | 4767 // r15: length of second string |
4768 STATIC_ASSERT(kSeqStringTag == 0); | 4768 STATIC_ASSERT(kSeqStringTag == 0); |
4769 __ testb(r9, Immediate(kStringRepresentationMask)); | 4769 __ testb(r9, Immediate(kStringRepresentationMask)); |
4770 __ j(zero, &second_is_sequential, Label::kNear); | 4770 __ j(zero, &second_is_sequential, Label::kNear); |
4771 // Rule out short external string and load string resource. | 4771 // Rule out short external string and load string resource. |
4772 STATIC_ASSERT(kShortExternalStringTag != 0); | 4772 STATIC_ASSERT(kShortExternalStringTag != 0); |
4773 __ testb(r9, Immediate(kShortExternalStringMask)); | 4773 __ testb(r9, Immediate(kShortExternalStringMask)); |
4774 __ j(not_zero, &call_runtime); | 4774 __ j(not_zero, &call_runtime); |
4775 __ movq(rdx, FieldOperand(rdx, ExternalString::kResourceDataOffset)); | 4775 __ movq(rdx, FieldOperand(rdx, ExternalString::kResourceDataOffset)); |
4776 __ jmp(&second_prepared, Label::kNear); | 4776 __ jmp(&second_prepared, Label::kNear); |
4777 __ bind(&second_is_sequential); | 4777 __ bind(&second_is_sequential); |
4778 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); | 4778 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
4779 __ lea(rdx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); | 4779 __ lea(rdx, FieldOperand(rdx, SeqOneByteString::kHeaderSize)); |
4780 __ bind(&second_prepared); | 4780 __ bind(&second_prepared); |
4781 | 4781 |
4782 Label non_ascii_string_add_flat_result; | 4782 Label non_ascii_string_add_flat_result; |
4783 // r9: instance type of second string | 4783 // r9: instance type of second string |
4784 // First string and second string have the same encoding. | 4784 // First string and second string have the same encoding. |
4785 STATIC_ASSERT(kTwoByteStringTag == 0); | 4785 STATIC_ASSERT(kTwoByteStringTag == 0); |
4786 __ SmiToInteger32(rbx, rbx); | 4786 __ SmiToInteger32(rbx, rbx); |
4787 __ testb(r9, Immediate(kStringEncodingMask)); | 4787 __ testb(r9, Immediate(kStringEncodingMask)); |
4788 __ j(zero, &non_ascii_string_add_flat_result); | 4788 __ j(zero, &non_ascii_string_add_flat_result); |
4789 | 4789 |
4790 __ bind(&make_flat_ascii_string); | 4790 __ bind(&make_flat_ascii_string); |
4791 // Both strings are ASCII strings. As they are short they are both flat. | 4791 // Both strings are ASCII strings. As they are short they are both flat. |
4792 __ AllocateAsciiString(rax, rbx, rdi, r8, r9, &call_runtime); | 4792 __ AllocateAsciiString(rax, rbx, rdi, r8, r9, &call_runtime); |
4793 // rax: result string | 4793 // rax: result string |
4794 // Locate first character of result. | 4794 // Locate first character of result. |
4795 __ lea(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); | 4795 __ lea(rbx, FieldOperand(rax, SeqOneByteString::kHeaderSize)); |
4796 // rcx: first char of first string | 4796 // rcx: first char of first string |
4797 // rbx: first character of result | 4797 // rbx: first character of result |
4798 // r14: length of first string | 4798 // r14: length of first string |
4799 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, true); | 4799 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, true); |
4800 // rbx: next character of result | 4800 // rbx: next character of result |
4801 // rdx: first char of second string | 4801 // rdx: first char of second string |
4802 // r15: length of second string | 4802 // r15: length of second string |
4803 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, true); | 4803 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, true); |
4804 __ IncrementCounter(counters->string_add_native(), 1); | 4804 __ IncrementCounter(counters->string_add_native(), 1); |
4805 __ ret(2 * kPointerSize); | 4805 __ ret(2 * kPointerSize); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5058 // We use kScratchRegister as a temporary register in assumption that | 5058 // We use kScratchRegister as a temporary register in assumption that |
5059 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly | 5059 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly |
5060 Register temp = kScratchRegister; | 5060 Register temp = kScratchRegister; |
5061 | 5061 |
5062 // Check that the candidate is a non-external ASCII string. | 5062 // Check that the candidate is a non-external ASCII string. |
5063 __ movzxbl(temp, FieldOperand(map, Map::kInstanceTypeOffset)); | 5063 __ movzxbl(temp, FieldOperand(map, Map::kInstanceTypeOffset)); |
5064 __ JumpIfInstanceTypeIsNotSequentialAscii( | 5064 __ JumpIfInstanceTypeIsNotSequentialAscii( |
5065 temp, temp, &next_probe[i]); | 5065 temp, temp, &next_probe[i]); |
5066 | 5066 |
5067 // Check if the two characters match. | 5067 // Check if the two characters match. |
5068 __ movl(temp, FieldOperand(candidate, SeqAsciiString::kHeaderSize)); | 5068 __ movl(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize)); |
5069 __ andl(temp, Immediate(0x0000ffff)); | 5069 __ andl(temp, Immediate(0x0000ffff)); |
5070 __ cmpl(chars, temp); | 5070 __ cmpl(chars, temp); |
5071 __ j(equal, &found_in_symbol_table); | 5071 __ j(equal, &found_in_symbol_table); |
5072 __ bind(&next_probe[i]); | 5072 __ bind(&next_probe[i]); |
5073 } | 5073 } |
5074 | 5074 |
5075 // No matching 2 character string found by probing. | 5075 // No matching 2 character string found by probing. |
5076 __ jmp(not_found); | 5076 __ jmp(not_found); |
5077 | 5077 |
5078 // Scratch register contains result when we fall through to here. | 5078 // Scratch register contains result when we fall through to here. |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5276 __ testb(rbx, Immediate(kExternalStringTag)); | 5276 __ testb(rbx, Immediate(kExternalStringTag)); |
5277 __ j(zero, &sequential_string); | 5277 __ j(zero, &sequential_string); |
5278 | 5278 |
5279 // Handle external string. | 5279 // Handle external string. |
5280 // Rule out short external strings. | 5280 // Rule out short external strings. |
5281 STATIC_CHECK(kShortExternalStringTag != 0); | 5281 STATIC_CHECK(kShortExternalStringTag != 0); |
5282 __ testb(rbx, Immediate(kShortExternalStringMask)); | 5282 __ testb(rbx, Immediate(kShortExternalStringMask)); |
5283 __ j(not_zero, &runtime); | 5283 __ j(not_zero, &runtime); |
5284 __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); | 5284 __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); |
5285 // Move the pointer so that offset-wise, it looks like a sequential string. | 5285 // Move the pointer so that offset-wise, it looks like a sequential string. |
5286 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 5286 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
5287 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 5287 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
5288 | 5288 |
5289 __ bind(&sequential_string); | 5289 __ bind(&sequential_string); |
5290 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 5290 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); |
5291 __ testb(rbx, Immediate(kStringEncodingMask)); | 5291 __ testb(rbx, Immediate(kStringEncodingMask)); |
5292 __ j(zero, &two_byte_sequential); | 5292 __ j(zero, &two_byte_sequential); |
5293 | 5293 |
5294 // Allocate the result. | 5294 // Allocate the result. |
5295 __ AllocateAsciiString(rax, rcx, r11, r14, r15, &runtime); | 5295 __ AllocateAsciiString(rax, rcx, r11, r14, r15, &runtime); |
5296 | 5296 |
5297 // rax: result string | 5297 // rax: result string |
5298 // rcx: result string length | 5298 // rcx: result string length |
5299 __ movq(r14, rsi); // esi used by following code. | 5299 __ movq(r14, rsi); // esi used by following code. |
5300 { // Locate character of sub string start. | 5300 { // Locate character of sub string start. |
5301 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_1); | 5301 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_1); |
5302 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, | 5302 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, |
5303 SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 5303 SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
5304 } | 5304 } |
5305 // Locate first character of result. | 5305 // Locate first character of result. |
5306 __ lea(rdi, FieldOperand(rax, SeqAsciiString::kHeaderSize)); | 5306 __ lea(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize)); |
5307 | 5307 |
5308 // rax: result string | 5308 // rax: result string |
5309 // rcx: result length | 5309 // rcx: result length |
5310 // rdi: first character of result | 5310 // rdi: first character of result |
5311 // rsi: character of sub string start | 5311 // rsi: character of sub string start |
5312 // r14: original value of rsi | 5312 // r14: original value of rsi |
5313 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); | 5313 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); |
5314 __ movq(rsi, r14); // Restore rsi. | 5314 __ movq(rsi, r14); // Restore rsi. |
5315 __ IncrementCounter(counters->sub_string_native(), 1); | 5315 __ IncrementCounter(counters->sub_string_native(), 1); |
5316 __ ret(kArgumentsSize); | 5316 __ ret(kArgumentsSize); |
5317 | 5317 |
5318 __ bind(&two_byte_sequential); | 5318 __ bind(&two_byte_sequential); |
5319 // Allocate the result. | 5319 // Allocate the result. |
5320 __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime); | 5320 __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime); |
5321 | 5321 |
5322 // rax: result string | 5322 // rax: result string |
5323 // rcx: result string length | 5323 // rcx: result string length |
5324 __ movq(r14, rsi); // esi used by following code. | 5324 __ movq(r14, rsi); // esi used by following code. |
5325 { // Locate character of sub string start. | 5325 { // Locate character of sub string start. |
5326 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2); | 5326 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2); |
5327 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, | 5327 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, |
5328 SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 5328 SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
5329 } | 5329 } |
5330 // Locate first character of result. | 5330 // Locate first character of result. |
5331 __ lea(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); | 5331 __ lea(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); |
5332 | 5332 |
5333 // rax: result string | 5333 // rax: result string |
5334 // rcx: result length | 5334 // rcx: result length |
5335 // rdi: first character of result | 5335 // rdi: first character of result |
5336 // rsi: character of sub string start | 5336 // rsi: character of sub string start |
5337 // r14: original value of rsi | 5337 // r14: original value of rsi |
5338 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); | 5338 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5458 Register right, | 5458 Register right, |
5459 Register length, | 5459 Register length, |
5460 Register scratch, | 5460 Register scratch, |
5461 Label* chars_not_equal, | 5461 Label* chars_not_equal, |
5462 Label::Distance near_jump) { | 5462 Label::Distance near_jump) { |
5463 // Change index to run from -length to -1 by adding length to string | 5463 // Change index to run from -length to -1 by adding length to string |
5464 // start. This means that loop ends when index reaches zero, which | 5464 // start. This means that loop ends when index reaches zero, which |
5465 // doesn't need an additional compare. | 5465 // doesn't need an additional compare. |
5466 __ SmiToInteger32(length, length); | 5466 __ SmiToInteger32(length, length); |
5467 __ lea(left, | 5467 __ lea(left, |
5468 FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize)); | 5468 FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize)); |
5469 __ lea(right, | 5469 __ lea(right, |
5470 FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize)); | 5470 FieldOperand(right, length, times_1, SeqOneByteString::kHeaderSize)); |
5471 __ neg(length); | 5471 __ neg(length); |
5472 Register index = length; // index = -length; | 5472 Register index = length; // index = -length; |
5473 | 5473 |
5474 // Compare loop. | 5474 // Compare loop. |
5475 Label loop; | 5475 Label loop; |
5476 __ bind(&loop); | 5476 __ bind(&loop); |
5477 __ movb(scratch, Operand(left, index, times_1, 0)); | 5477 __ movb(scratch, Operand(left, index, times_1, 0)); |
5478 __ cmpb(scratch, Operand(right, index, times_1, 0)); | 5478 __ cmpb(scratch, Operand(right, index, times_1, 0)); |
5479 __ j(not_equal, chars_not_equal, near_jump); | 5479 __ j(not_equal, chars_not_equal, near_jump); |
5480 __ incq(index); | 5480 __ incq(index); |
(...skipping 993 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6474 #endif | 6474 #endif |
6475 | 6475 |
6476 __ Ret(); | 6476 __ Ret(); |
6477 } | 6477 } |
6478 | 6478 |
6479 #undef __ | 6479 #undef __ |
6480 | 6480 |
6481 } } // namespace v8::internal | 6481 } } // namespace v8::internal |
6482 | 6482 |
6483 #endif // V8_TARGET_ARCH_X64 | 6483 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |