Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(346)

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 7795018: Generated code for substring slices in x64 and arm. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Applied Bill's suggestions. Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/mips/code-stubs-mips.cc ('k') | src/x64/lithium-codegen-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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(&copy_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, &copy_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(&copy_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
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
OLDNEW
« no previous file with comments | « src/mips/code-stubs-mips.cc ('k') | src/x64/lithium-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698