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

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

Issue 2355793003: [stubs] Port SubStringStub to TurboFan (Closed)
Patch Set: Address comments Created 4 years, 2 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
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_X64 5 #if V8_TARGET_ARCH_X64
6 6
7 #include "src/code-stubs.h" 7 #include "src/code-stubs.h"
8 #include "src/api-arguments.h" 8 #include "src/api-arguments.h"
9 #include "src/bootstrapper.h" 9 #include "src/bootstrapper.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 1993 matching lines...) Expand 10 before | Expand all | Expand 10 after
2004 __ movb(kScratchRegister, Operand(src, 0)); 2004 __ movb(kScratchRegister, Operand(src, 0));
2005 __ movb(Operand(dest, 0), kScratchRegister); 2005 __ movb(Operand(dest, 0), kScratchRegister);
2006 __ incp(src); 2006 __ incp(src);
2007 __ incp(dest); 2007 __ incp(dest);
2008 __ decl(count); 2008 __ decl(count);
2009 __ j(not_zero, &loop); 2009 __ j(not_zero, &loop);
2010 2010
2011 __ bind(&done); 2011 __ bind(&done);
2012 } 2012 }
2013 2013
2014
2015 void SubStringStub::Generate(MacroAssembler* masm) {
2016 Label runtime;
2017
2018 // Stack frame on entry.
2019 // rsp[0] : return address
2020 // rsp[8] : to
2021 // rsp[16] : from
2022 // rsp[24] : string
2023
2024 enum SubStringStubArgumentIndices {
2025 STRING_ARGUMENT_INDEX,
2026 FROM_ARGUMENT_INDEX,
2027 TO_ARGUMENT_INDEX,
2028 SUB_STRING_ARGUMENT_COUNT
2029 };
2030
2031 StackArgumentsAccessor args(rsp, SUB_STRING_ARGUMENT_COUNT,
2032 ARGUMENTS_DONT_CONTAIN_RECEIVER);
2033
2034 // Make sure first argument is a string.
2035 __ movp(rax, args.GetArgumentOperand(STRING_ARGUMENT_INDEX));
2036 STATIC_ASSERT(kSmiTag == 0);
2037 __ testl(rax, Immediate(kSmiTagMask));
2038 __ j(zero, &runtime);
2039 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx);
2040 __ j(NegateCondition(is_string), &runtime);
2041
2042 // rax: string
2043 // rbx: instance type
2044 // Calculate length of sub string using the smi values.
2045 __ movp(rcx, args.GetArgumentOperand(TO_ARGUMENT_INDEX));
2046 __ movp(rdx, args.GetArgumentOperand(FROM_ARGUMENT_INDEX));
2047 __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime);
2048
2049 __ SmiSub(rcx, rcx, rdx); // Overflow doesn't happen.
2050 __ cmpp(rcx, FieldOperand(rax, String::kLengthOffset));
2051 Label not_original_string;
2052 // Shorter than original string's length: an actual substring.
2053 __ j(below, &not_original_string, Label::kNear);
2054 // Longer than original string's length or negative: unsafe arguments.
2055 __ j(above, &runtime);
2056 // Return original string.
2057 Counters* counters = isolate()->counters();
2058 __ IncrementCounter(counters->sub_string_native(), 1);
2059 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
2060 __ bind(&not_original_string);
2061
2062 Label single_char;
2063 __ SmiCompare(rcx, Smi::FromInt(1));
2064 __ j(equal, &single_char);
2065
2066 __ SmiToInteger32(rcx, rcx);
2067
2068 // rax: string
2069 // rbx: instance type
2070 // rcx: sub string length
2071 // rdx: from index (smi)
2072 // Deal with different string types: update the index if necessary
2073 // and put the underlying string into edi.
2074 Label underlying_unpacked, sliced_string, seq_or_external_string;
2075 // If the string is not indirect, it can only be sequential or external.
2076 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
2077 STATIC_ASSERT(kIsIndirectStringMask != 0);
2078 __ testb(rbx, Immediate(kIsIndirectStringMask));
2079 __ j(zero, &seq_or_external_string, Label::kNear);
2080
2081 __ testb(rbx, Immediate(kSlicedNotConsMask));
2082 __ j(not_zero, &sliced_string, Label::kNear);
2083 // Cons string. Check whether it is flat, then fetch first part.
2084 // Flat cons strings have an empty second part.
2085 __ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset),
2086 Heap::kempty_stringRootIndex);
2087 __ j(not_equal, &runtime);
2088 __ movp(rdi, FieldOperand(rax, ConsString::kFirstOffset));
2089 // Update instance type.
2090 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
2091 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2092 __ jmp(&underlying_unpacked, Label::kNear);
2093
2094 __ bind(&sliced_string);
2095 // Sliced string. Fetch parent and correct start index by offset.
2096 __ addp(rdx, FieldOperand(rax, SlicedString::kOffsetOffset));
2097 __ movp(rdi, FieldOperand(rax, SlicedString::kParentOffset));
2098 // Update instance type.
2099 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
2100 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2101 __ jmp(&underlying_unpacked, Label::kNear);
2102
2103 __ bind(&seq_or_external_string);
2104 // Sequential or external string. Just move string to the correct register.
2105 __ movp(rdi, rax);
2106
2107 __ bind(&underlying_unpacked);
2108
2109 if (FLAG_string_slices) {
2110 Label copy_routine;
2111 // rdi: underlying subject string
2112 // rbx: instance type of underlying subject string
2113 // rdx: adjusted start index (smi)
2114 // rcx: length
2115 // If coming from the make_two_character_string path, the string
2116 // is too short to be sliced anyways.
2117 __ cmpp(rcx, Immediate(SlicedString::kMinLength));
2118 // Short slice. Copy instead of slicing.
2119 __ j(less, &copy_routine);
2120 // Allocate new sliced string. At this point we do not reload the instance
2121 // type including the string encoding because we simply rely on the info
2122 // provided by the original string. It does not matter if the original
2123 // string's encoding is wrong because we always have to recheck encoding of
2124 // the newly created string's parent anyways due to externalized strings.
2125 Label two_byte_slice, set_slice_header;
2126 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
2127 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
2128 __ testb(rbx, Immediate(kStringEncodingMask));
2129 __ j(zero, &two_byte_slice, Label::kNear);
2130 __ AllocateOneByteSlicedString(rax, rbx, r14, &runtime);
2131 __ jmp(&set_slice_header, Label::kNear);
2132 __ bind(&two_byte_slice);
2133 __ AllocateTwoByteSlicedString(rax, rbx, r14, &runtime);
2134 __ bind(&set_slice_header);
2135 __ Integer32ToSmi(rcx, rcx);
2136 __ movp(FieldOperand(rax, SlicedString::kLengthOffset), rcx);
2137 __ movp(FieldOperand(rax, SlicedString::kHashFieldOffset),
2138 Immediate(String::kEmptyHashField));
2139 __ movp(FieldOperand(rax, SlicedString::kParentOffset), rdi);
2140 __ movp(FieldOperand(rax, SlicedString::kOffsetOffset), rdx);
2141 __ IncrementCounter(counters->sub_string_native(), 1);
2142 __ ret(3 * kPointerSize);
2143
2144 __ bind(&copy_routine);
2145 }
2146
2147 // rdi: underlying subject string
2148 // rbx: instance type of underlying subject string
2149 // rdx: adjusted start index (smi)
2150 // rcx: length
2151 // The subject string can only be external or sequential string of either
2152 // encoding at this point.
2153 Label two_byte_sequential, sequential_string;
2154 STATIC_ASSERT(kExternalStringTag != 0);
2155 STATIC_ASSERT(kSeqStringTag == 0);
2156 __ testb(rbx, Immediate(kExternalStringTag));
2157 __ j(zero, &sequential_string);
2158
2159 // Handle external string.
2160 // Rule out short external strings.
2161 STATIC_ASSERT(kShortExternalStringTag != 0);
2162 __ testb(rbx, Immediate(kShortExternalStringMask));
2163 __ j(not_zero, &runtime);
2164 __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset));
2165 // Move the pointer so that offset-wise, it looks like a sequential string.
2166 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
2167 __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
2168
2169 __ bind(&sequential_string);
2170 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
2171 __ testb(rbx, Immediate(kStringEncodingMask));
2172 __ j(zero, &two_byte_sequential);
2173
2174 // Allocate the result.
2175 __ AllocateOneByteString(rax, rcx, r11, r14, r15, &runtime);
2176
2177 // rax: result string
2178 // rcx: result string length
2179 { // Locate character of sub string start.
2180 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_1);
2181 __ leap(r14, Operand(rdi, smi_as_index.reg, smi_as_index.scale,
2182 SeqOneByteString::kHeaderSize - kHeapObjectTag));
2183 }
2184 // Locate first character of result.
2185 __ leap(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize));
2186
2187 // rax: result string
2188 // rcx: result length
2189 // r14: first character of result
2190 // rsi: character of sub string start
2191 StringHelper::GenerateCopyCharacters(
2192 masm, rdi, r14, rcx, String::ONE_BYTE_ENCODING);
2193 __ IncrementCounter(counters->sub_string_native(), 1);
2194 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
2195
2196 __ bind(&two_byte_sequential);
2197 // Allocate the result.
2198 __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime);
2199
2200 // rax: result string
2201 // rcx: result string length
2202 { // Locate character of sub string start.
2203 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2);
2204 __ leap(r14, Operand(rdi, smi_as_index.reg, smi_as_index.scale,
2205 SeqOneByteString::kHeaderSize - kHeapObjectTag));
2206 }
2207 // Locate first character of result.
2208 __ leap(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize));
2209
2210 // rax: result string
2211 // rcx: result length
2212 // rdi: first character of result
2213 // r14: character of sub string start
2214 StringHelper::GenerateCopyCharacters(
2215 masm, rdi, r14, rcx, String::TWO_BYTE_ENCODING);
2216 __ IncrementCounter(counters->sub_string_native(), 1);
2217 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
2218
2219 // Just jump to runtime to create the sub string.
2220 __ bind(&runtime);
2221 __ TailCallRuntime(Runtime::kSubString);
2222
2223 __ bind(&single_char);
2224 // rax: string
2225 // rbx: instance type
2226 // rcx: sub string length (smi)
2227 // rdx: from index (smi)
2228 StringCharAtGenerator generator(rax, rdx, rcx, rax, &runtime, &runtime,
2229 &runtime, RECEIVER_IS_STRING);
2230 generator.GenerateFast(masm);
2231 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
2232 generator.SkipSlow(masm, &runtime);
2233 }
2234
2235 void ToStringStub::Generate(MacroAssembler* masm) { 2014 void ToStringStub::Generate(MacroAssembler* masm) {
2236 // The ToString stub takes one argument in rax. 2015 // The ToString stub takes one argument in rax.
2237 Label is_number; 2016 Label is_number;
2238 __ JumpIfSmi(rax, &is_number, Label::kNear); 2017 __ JumpIfSmi(rax, &is_number, Label::kNear);
2239 2018
2240 Label not_string; 2019 Label not_string;
2241 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdi); 2020 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdi);
2242 // rax: receiver 2021 // rax: receiver
2243 // rdi: receiver map 2022 // rdi: receiver map
2244 __ j(above_equal, &not_string, Label::kNear); 2023 __ j(above_equal, &not_string, Label::kNear);
(...skipping 2916 matching lines...) Expand 10 before | Expand all | Expand 10 after
5161 kStackUnwindSpace, nullptr, return_value_operand, 4940 kStackUnwindSpace, nullptr, return_value_operand,
5162 NULL); 4941 NULL);
5163 } 4942 }
5164 4943
5165 #undef __ 4944 #undef __
5166 4945
5167 } // namespace internal 4946 } // namespace internal
5168 } // namespace v8 4947 } // namespace v8
5169 4948
5170 #endif // V8_TARGET_ARCH_X64 4949 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/code-stubs.cc ('K') | « src/s390/code-stubs-s390.cc ('k') | src/x87/code-stubs-x87.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698