OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3931 __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset)); | 3931 __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
3932 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | 3932 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); |
3933 // If the first cons component is also non-flat, then go to runtime. | 3933 // If the first cons component is also non-flat, then go to runtime. |
3934 STATIC_ASSERT(kSeqStringTag == 0); | 3934 STATIC_ASSERT(kSeqStringTag == 0); |
3935 __ testb(result_, Immediate(kStringRepresentationMask)); | 3935 __ testb(result_, Immediate(kStringRepresentationMask)); |
3936 __ j(not_zero, &call_runtime_); | 3936 __ j(not_zero, &call_runtime_); |
3937 __ jmp(&flat_string); | 3937 __ jmp(&flat_string); |
3938 | 3938 |
3939 // Check for 1-byte or 2-byte string. | 3939 // Check for 1-byte or 2-byte string. |
3940 __ bind(&flat_string); | 3940 __ bind(&flat_string); |
3941 STATIC_ASSERT(kAsciiStringTag != 0); | 3941 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |
| 3942 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
3942 __ testb(result_, Immediate(kStringEncodingMask)); | 3943 __ testb(result_, Immediate(kStringEncodingMask)); |
3943 __ j(not_zero, &ascii_string); | 3944 __ j(not_zero, &ascii_string); |
3944 | 3945 |
3945 // 2-byte string. | 3946 // 2-byte string. |
3946 // Load the 2-byte character code into the result register. | 3947 // Load the 2-byte character code into the result register. |
3947 __ SmiToInteger32(scratch_, scratch_); | 3948 __ SmiToInteger32(scratch_, scratch_); |
3948 __ movzxwl(result_, FieldOperand(object_, | 3949 __ movzxwl(result_, FieldOperand(object_, |
3949 scratch_, times_2, | 3950 scratch_, times_2, |
3950 SeqTwoByteString::kHeaderSize)); | 3951 SeqTwoByteString::kHeaderSize)); |
3951 __ jmp(&got_char_code); | 3952 __ jmp(&got_char_code); |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4188 // If result is not supposed to be flat, allocate a cons string object. If | 4189 // If result is not supposed to be flat, allocate a cons string object. If |
4189 // both strings are ascii the result is an ascii cons string. | 4190 // both strings are ascii the result is an ascii cons string. |
4190 // rax: first string | 4191 // rax: first string |
4191 // rbx: length of resulting flat string | 4192 // rbx: length of resulting flat string |
4192 // rdx: second string | 4193 // rdx: second string |
4193 // r8: instance type of first string | 4194 // r8: instance type of first string |
4194 // r9: instance type of second string | 4195 // r9: instance type of second string |
4195 Label non_ascii, allocated, ascii_data; | 4196 Label non_ascii, allocated, ascii_data; |
4196 __ movl(rcx, r8); | 4197 __ movl(rcx, r8); |
4197 __ and_(rcx, r9); | 4198 __ and_(rcx, r9); |
4198 STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag); | 4199 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |
4199 __ testl(rcx, Immediate(kAsciiStringTag)); | 4200 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
| 4201 __ testl(rcx, Immediate(kStringEncodingMask)); |
4200 __ j(zero, &non_ascii); | 4202 __ j(zero, &non_ascii); |
4201 __ bind(&ascii_data); | 4203 __ bind(&ascii_data); |
4202 // Allocate an acsii cons string. | 4204 // Allocate an acsii cons string. |
4203 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime); | 4205 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime); |
4204 __ bind(&allocated); | 4206 __ bind(&allocated); |
4205 // Fill the fields of the cons string. | 4207 // Fill the fields of the cons string. |
4206 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx); | 4208 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx); |
4207 __ movq(FieldOperand(rcx, ConsString::kHashFieldOffset), | 4209 __ movq(FieldOperand(rcx, ConsString::kHashFieldOffset), |
4208 Immediate(String::kEmptyHashField)); | 4210 Immediate(String::kEmptyHashField)); |
4209 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax); | 4211 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax); |
4210 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx); | 4212 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx); |
4211 __ movq(rax, rcx); | 4213 __ movq(rax, rcx); |
4212 __ IncrementCounter(counters->string_add_native(), 1); | 4214 __ IncrementCounter(counters->string_add_native(), 1); |
4213 __ ret(2 * kPointerSize); | 4215 __ ret(2 * kPointerSize); |
4214 __ bind(&non_ascii); | 4216 __ bind(&non_ascii); |
4215 // At least one of the strings is two-byte. Check whether it happens | 4217 // At least one of the strings is two-byte. Check whether it happens |
4216 // to contain only ascii characters. | 4218 // to contain only ascii characters. |
4217 // rcx: first instance type AND second instance type. | 4219 // rcx: first instance type AND second instance type. |
4218 // r8: first instance type. | 4220 // r8: first instance type. |
4219 // r9: second instance type. | 4221 // r9: second instance type. |
4220 __ testb(rcx, Immediate(kAsciiDataHintMask)); | 4222 __ testb(rcx, Immediate(kAsciiDataHintMask)); |
4221 __ j(not_zero, &ascii_data); | 4223 __ j(not_zero, &ascii_data); |
4222 __ xor_(r8, r9); | 4224 __ xor_(r8, r9); |
4223 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); | 4225 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); |
4224 __ andb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag)); | 4226 __ andb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag)); |
4225 __ cmpb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag)); | 4227 __ cmpb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag)); |
4226 __ j(equal, &ascii_data); | 4228 __ j(equal, &ascii_data); |
4227 // Allocate a two byte cons string. | 4229 // Allocate a two byte cons string. |
4228 __ AllocateConsString(rcx, rdi, no_reg, &string_add_runtime); | 4230 __ AllocateTwoByteConsString(rcx, rdi, no_reg, &string_add_runtime); |
4229 __ jmp(&allocated); | 4231 __ jmp(&allocated); |
4230 | 4232 |
4231 // Handle creating a flat result. First check that both strings are not | 4233 // Handle creating a flat result. First check that both strings are not |
4232 // external strings. | 4234 // external strings. |
4233 // rax: first string | 4235 // rax: first string |
4234 // rbx: length of resulting flat string as smi | 4236 // rbx: length of resulting flat string as smi |
4235 // rdx: second string | 4237 // rdx: second string |
4236 // r8: instance type of first string | 4238 // r8: instance type of first string |
4237 // r9: instance type of first string | 4239 // r9: instance type of first string |
4238 __ bind(&string_add_flat_result); | 4240 __ bind(&string_add_flat_result); |
4239 __ SmiToInteger32(rbx, rbx); | 4241 __ SmiToInteger32(rbx, rbx); |
4240 __ movl(rcx, r8); | 4242 __ movl(rcx, r8); |
4241 __ and_(rcx, Immediate(kStringRepresentationMask)); | 4243 __ and_(rcx, Immediate(kStringRepresentationMask)); |
4242 __ cmpl(rcx, Immediate(kExternalStringTag)); | 4244 __ cmpl(rcx, Immediate(kExternalStringTag)); |
4243 __ j(equal, &string_add_runtime); | 4245 __ j(equal, &string_add_runtime); |
4244 __ movl(rcx, r9); | 4246 __ movl(rcx, r9); |
4245 __ and_(rcx, Immediate(kStringRepresentationMask)); | 4247 __ and_(rcx, Immediate(kStringRepresentationMask)); |
4246 __ cmpl(rcx, Immediate(kExternalStringTag)); | 4248 __ cmpl(rcx, Immediate(kExternalStringTag)); |
4247 __ j(equal, &string_add_runtime); | 4249 __ j(equal, &string_add_runtime); |
4248 // We cannot encounter sliced strings here since: | 4250 // We cannot encounter sliced strings here since: |
4249 STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength); | 4251 STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength); |
4250 // Now check if both strings are ascii strings. | 4252 // Now check if both strings are ascii strings. |
4251 // rax: first string | 4253 // rax: first string |
4252 // rbx: length of resulting flat string | 4254 // rbx: length of resulting flat string |
4253 // rdx: second string | 4255 // rdx: second string |
4254 // r8: instance type of first string | 4256 // r8: instance type of first string |
4255 // r9: instance type of second string | 4257 // r9: instance type of second string |
4256 Label non_ascii_string_add_flat_result; | 4258 Label non_ascii_string_add_flat_result; |
4257 STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag); | 4259 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |
4258 __ testl(r8, Immediate(kAsciiStringTag)); | 4260 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
| 4261 __ testl(r8, Immediate(kStringEncodingMask)); |
4259 __ j(zero, &non_ascii_string_add_flat_result); | 4262 __ j(zero, &non_ascii_string_add_flat_result); |
4260 __ testl(r9, Immediate(kAsciiStringTag)); | 4263 __ testl(r9, Immediate(kStringEncodingMask)); |
4261 __ j(zero, &string_add_runtime); | 4264 __ j(zero, &string_add_runtime); |
4262 | 4265 |
4263 __ bind(&make_flat_ascii_string); | 4266 __ bind(&make_flat_ascii_string); |
4264 // Both strings are ascii strings. As they are short they are both flat. | 4267 // Both strings are ascii strings. As they are short they are both flat. |
4265 __ AllocateAsciiString(rcx, rbx, rdi, r14, r11, &string_add_runtime); | 4268 __ AllocateAsciiString(rcx, rbx, rdi, r14, r11, &string_add_runtime); |
4266 // rcx: result string | 4269 // rcx: result string |
4267 __ movq(rbx, rcx); | 4270 __ movq(rbx, rcx); |
4268 // Locate first character of result. | 4271 // Locate first character of result. |
4269 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 4272 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
4270 // Locate first character of first argument | 4273 // Locate first character of first argument |
(...skipping 17 matching lines...) Expand all Loading... |
4288 __ IncrementCounter(counters->string_add_native(), 1); | 4291 __ IncrementCounter(counters->string_add_native(), 1); |
4289 __ ret(2 * kPointerSize); | 4292 __ ret(2 * kPointerSize); |
4290 | 4293 |
4291 // Handle creating a flat two byte result. | 4294 // Handle creating a flat two byte result. |
4292 // rax: first string - known to be two byte | 4295 // rax: first string - known to be two byte |
4293 // rbx: length of resulting flat string | 4296 // rbx: length of resulting flat string |
4294 // rdx: second string | 4297 // rdx: second string |
4295 // r8: instance type of first string | 4298 // r8: instance type of first string |
4296 // r9: instance type of first string | 4299 // r9: instance type of first string |
4297 __ bind(&non_ascii_string_add_flat_result); | 4300 __ bind(&non_ascii_string_add_flat_result); |
4298 __ and_(r9, Immediate(kAsciiStringTag)); | 4301 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |
| 4302 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
| 4303 __ and_(r9, Immediate(kStringEncodingMask)); |
4299 __ j(not_zero, &string_add_runtime); | 4304 __ j(not_zero, &string_add_runtime); |
4300 // Both strings are two byte strings. As they are short they are both | 4305 // Both strings are two byte strings. As they are short they are both |
4301 // flat. | 4306 // flat. |
4302 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r11, &string_add_runtime); | 4307 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r11, &string_add_runtime); |
4303 // rcx: result string | 4308 // rcx: result string |
4304 __ movq(rbx, rcx); | 4309 __ movq(rbx, rcx); |
4305 // Locate first character of result. | 4310 // Locate first character of result. |
4306 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 4311 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
4307 // Locate first character of first argument. | 4312 // Locate first character of first argument. |
4308 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); | 4313 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4632 // if (hash == 0) hash = 27; | 4637 // if (hash == 0) hash = 27; |
4633 Label hash_not_zero; | 4638 Label hash_not_zero; |
4634 __ j(not_zero, &hash_not_zero); | 4639 __ j(not_zero, &hash_not_zero); |
4635 __ Set(hash, 27); | 4640 __ Set(hash, 27); |
4636 __ bind(&hash_not_zero); | 4641 __ bind(&hash_not_zero); |
4637 } | 4642 } |
4638 | 4643 |
4639 void SubStringStub::Generate(MacroAssembler* masm) { | 4644 void SubStringStub::Generate(MacroAssembler* masm) { |
4640 Label runtime; | 4645 Label runtime; |
4641 | 4646 |
4642 if (FLAG_string_slices) { | |
4643 __ jmp(&runtime); | |
4644 } | |
4645 // Stack frame on entry. | 4647 // Stack frame on entry. |
4646 // rsp[0]: return address | 4648 // rsp[0]: return address |
4647 // rsp[8]: to | 4649 // rsp[8]: to |
4648 // rsp[16]: from | 4650 // rsp[16]: from |
4649 // rsp[24]: string | 4651 // rsp[24]: string |
4650 | 4652 |
4651 const int kToOffset = 1 * kPointerSize; | 4653 const int kToOffset = 1 * kPointerSize; |
4652 const int kFromOffset = kToOffset + kPointerSize; | 4654 const int kFromOffset = kToOffset + kPointerSize; |
4653 const int kStringOffset = kFromOffset + kPointerSize; | 4655 const int kStringOffset = kFromOffset + kPointerSize; |
4654 const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset; | 4656 const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4700 masm, rbx, rcx, rax, rdx, rdi, r14, &make_two_character_string); | 4702 masm, rbx, rcx, rax, rdx, rdi, r14, &make_two_character_string); |
4701 __ ret(3 * kPointerSize); | 4703 __ ret(3 * kPointerSize); |
4702 | 4704 |
4703 __ bind(&make_two_character_string); | 4705 __ bind(&make_two_character_string); |
4704 // Setup registers for allocating the two character string. | 4706 // Setup registers for allocating the two character string. |
4705 __ movq(rax, Operand(rsp, kStringOffset)); | 4707 __ movq(rax, Operand(rsp, kStringOffset)); |
4706 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 4708 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
4707 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 4709 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
4708 __ Set(rcx, 2); | 4710 __ Set(rcx, 2); |
4709 | 4711 |
4710 __ bind(&result_longer_than_two); | 4712 if (FLAG_string_slices) { |
| 4713 Label copy_routine; |
| 4714 // If coming from the make_two_character_string path, the string |
| 4715 // is too short to be sliced anyways. |
| 4716 STATIC_ASSERT(2 < SlicedString::kMinLength); |
| 4717 __ jmp(©_routine); |
| 4718 __ bind(&result_longer_than_two); |
| 4719 |
| 4720 // rax: string |
| 4721 // rbx: instance type |
| 4722 // rcx: sub string length |
| 4723 // rdx: from index (smi) |
| 4724 Label allocate_slice, sliced_string, seq_string; |
| 4725 __ cmpq(rcx, Immediate(SlicedString::kMinLength)); |
| 4726 // Short slice. Copy instead of slicing. |
| 4727 __ j(less, ©_routine); |
| 4728 STATIC_ASSERT(kSeqStringTag == 0); |
| 4729 __ testb(rbx, Immediate(kStringRepresentationMask)); |
| 4730 __ j(zero, &seq_string, Label::kNear); |
| 4731 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); |
| 4732 STATIC_ASSERT(kIsIndirectStringMask != 0); |
| 4733 __ testb(rbx, Immediate(kIsIndirectStringMask)); |
| 4734 // External string. Jump to runtime. |
| 4735 __ j(zero, &runtime); |
| 4736 |
| 4737 __ testb(rbx, Immediate(kSlicedNotConsMask)); |
| 4738 __ j(not_zero, &sliced_string, Label::kNear); |
| 4739 // Cons string. Check whether it is flat, then fetch first part. |
| 4740 __ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset), |
| 4741 Heap::kEmptyStringRootIndex); |
| 4742 __ j(not_equal, &runtime); |
| 4743 __ movq(rdi, FieldOperand(rax, ConsString::kFirstOffset)); |
| 4744 __ jmp(&allocate_slice, Label::kNear); |
| 4745 |
| 4746 __ bind(&sliced_string); |
| 4747 // Sliced string. Fetch parent and correct start index by offset. |
| 4748 __ addq(rdx, FieldOperand(rax, SlicedString::kOffsetOffset)); |
| 4749 __ movq(rdi, FieldOperand(rax, SlicedString::kParentOffset)); |
| 4750 __ jmp(&allocate_slice, Label::kNear); |
| 4751 |
| 4752 __ bind(&seq_string); |
| 4753 // Sequential string. Just move string to the right register. |
| 4754 __ movq(rdi, rax); |
| 4755 |
| 4756 __ bind(&allocate_slice); |
| 4757 // edi: underlying subject string |
| 4758 // ebx: instance type of original subject string |
| 4759 // edx: offset |
| 4760 // ecx: length |
| 4761 // Allocate new sliced string. At this point we do not reload the instance |
| 4762 // type including the string encoding because we simply rely on the info |
| 4763 // provided by the original string. It does not matter if the original |
| 4764 // string's encoding is wrong because we always have to recheck encoding of |
| 4765 // the newly created string's parent anyways due to externalized strings. |
| 4766 Label two_byte_slice, set_slice_header; |
| 4767 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |
| 4768 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
| 4769 __ testb(rbx, Immediate(kStringEncodingMask)); |
| 4770 __ j(zero, &two_byte_slice, Label::kNear); |
| 4771 __ AllocateAsciiSlicedString(rax, rbx, no_reg, &runtime); |
| 4772 __ jmp(&set_slice_header, Label::kNear); |
| 4773 __ bind(&two_byte_slice); |
| 4774 __ AllocateTwoByteSlicedString(rax, rbx, no_reg, &runtime); |
| 4775 __ bind(&set_slice_header); |
| 4776 __ movq(FieldOperand(rax, SlicedString::kOffsetOffset), rdx); |
| 4777 __ Integer32ToSmi(rcx, rcx); |
| 4778 __ movq(FieldOperand(rax, SlicedString::kLengthOffset), rcx); |
| 4779 __ movq(FieldOperand(rax, SlicedString::kParentOffset), rdi); |
| 4780 __ movq(FieldOperand(rax, SlicedString::kHashFieldOffset), |
| 4781 Immediate(String::kEmptyHashField)); |
| 4782 __ jmp(&return_rax); |
| 4783 |
| 4784 __ bind(©_routine); |
| 4785 } else { |
| 4786 __ bind(&result_longer_than_two); |
| 4787 } |
4711 | 4788 |
4712 // rax: string | 4789 // rax: string |
4713 // rbx: instance type | 4790 // rbx: instance type |
4714 // rcx: result string length | 4791 // rcx: result string length |
4715 // Check for flat ascii string | 4792 // Check for flat ascii string |
4716 Label non_ascii_flat; | 4793 Label non_ascii_flat; |
4717 __ JumpIfInstanceTypeIsNotSequentialAscii(rbx, rbx, &non_ascii_flat); | 4794 __ JumpIfInstanceTypeIsNotSequentialAscii(rbx, rbx, &non_ascii_flat); |
4718 | 4795 |
4719 // Allocate the result. | 4796 // Allocate the result. |
4720 __ AllocateAsciiString(rax, rcx, rbx, rdx, rdi, &runtime); | 4797 __ AllocateAsciiString(rax, rcx, rbx, rdx, rdi, &runtime); |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5396 __ Drop(1); | 5473 __ Drop(1); |
5397 __ ret(2 * kPointerSize); | 5474 __ ret(2 * kPointerSize); |
5398 } | 5475 } |
5399 | 5476 |
5400 | 5477 |
5401 #undef __ | 5478 #undef __ |
5402 | 5479 |
5403 } } // namespace v8::internal | 5480 } } // namespace v8::internal |
5404 | 5481 |
5405 #endif // V8_TARGET_ARCH_X64 | 5482 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |