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

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

Issue 2355793003: [stubs] Port SubStringStub to TurboFan (Closed)
Patch Set: Turn proper substring case into straight-line path Created 4 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
« no previous file with comments | « no previous file | src/arm64/code-stubs-arm64.cc » ('j') | src/code-stub-assembler.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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_ARM 5 #if V8_TARGET_ARCH_ARM
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/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 2109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2120 __ bind(&loop); 2120 __ bind(&loop);
2121 __ ldrb(scratch, MemOperand(src, 1, PostIndex), lt); 2121 __ ldrb(scratch, MemOperand(src, 1, PostIndex), lt);
2122 __ strb(scratch, MemOperand(dest, 1, PostIndex)); 2122 __ strb(scratch, MemOperand(dest, 1, PostIndex));
2123 __ bind(&loop_entry); 2123 __ bind(&loop_entry);
2124 __ cmp(dest, Operand(limit)); 2124 __ cmp(dest, Operand(limit));
2125 __ b(lt, &loop); 2125 __ b(lt, &loop);
2126 2126
2127 __ bind(&done); 2127 __ bind(&done);
2128 } 2128 }
2129 2129
2130
2131 void SubStringStub::Generate(MacroAssembler* masm) {
2132 Label runtime;
2133
2134 // Stack frame on entry.
2135 // lr: return address
2136 // sp[0]: to
2137 // sp[4]: from
2138 // sp[8]: string
2139
2140 // This stub is called from the native-call %_SubString(...), so
2141 // nothing can be assumed about the arguments. It is tested that:
2142 // "string" is a sequential string,
2143 // both "from" and "to" are smis, and
2144 // 0 <= from <= to <= string.length.
2145 // If any of these assumptions fail, we call the runtime system.
2146
2147 const int kToOffset = 0 * kPointerSize;
2148 const int kFromOffset = 1 * kPointerSize;
2149 const int kStringOffset = 2 * kPointerSize;
2150
2151 __ Ldrd(r2, r3, MemOperand(sp, kToOffset));
2152 STATIC_ASSERT(kFromOffset == kToOffset + 4);
2153 STATIC_ASSERT(kSmiTag == 0);
2154 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
2155
2156 // Arithmetic shift right by one un-smi-tags. In this case we rotate right
2157 // instead because we bail out on non-smi values: ROR and ASR are equivalent
2158 // for smis but they set the flags in a way that's easier to optimize.
2159 __ mov(r2, Operand(r2, ROR, 1), SetCC);
2160 __ mov(r3, Operand(r3, ROR, 1), SetCC, cc);
2161 // If either to or from had the smi tag bit set, then C is set now, and N
2162 // has the same value: we rotated by 1, so the bottom bit is now the top bit.
2163 // We want to bailout to runtime here if From is negative. In that case, the
2164 // next instruction is not executed and we fall through to bailing out to
2165 // runtime.
2166 // Executed if both r2 and r3 are untagged integers.
2167 __ sub(r2, r2, Operand(r3), SetCC, cc);
2168 // One of the above un-smis or the above SUB could have set N==1.
2169 __ b(mi, &runtime); // Either "from" or "to" is not an smi, or from > to.
2170
2171 // Make sure first argument is a string.
2172 __ ldr(r0, MemOperand(sp, kStringOffset));
2173 __ JumpIfSmi(r0, &runtime);
2174 Condition is_string = masm->IsObjectStringType(r0, r1);
2175 __ b(NegateCondition(is_string), &runtime);
2176
2177 Label single_char;
2178 __ cmp(r2, Operand(1));
2179 __ b(eq, &single_char);
2180
2181 // Short-cut for the case of trivial substring.
2182 Label return_r0;
2183 // r0: original string
2184 // r2: result string length
2185 __ ldr(r4, FieldMemOperand(r0, String::kLengthOffset));
2186 __ cmp(r2, Operand(r4, ASR, 1));
2187 // Return original string.
2188 __ b(eq, &return_r0);
2189 // Longer than original string's length or negative: unsafe arguments.
2190 __ b(hi, &runtime);
2191 // Shorter than original string's length: an actual substring.
2192
2193 // Deal with different string types: update the index if necessary
2194 // and put the underlying string into r5.
2195 // r0: original string
2196 // r1: instance type
2197 // r2: length
2198 // r3: from index (untagged)
2199 Label underlying_unpacked, sliced_string, seq_or_external_string;
2200 // If the string is not indirect, it can only be sequential or external.
2201 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
2202 STATIC_ASSERT(kIsIndirectStringMask != 0);
2203 __ tst(r1, Operand(kIsIndirectStringMask));
2204 __ b(eq, &seq_or_external_string);
2205
2206 __ tst(r1, Operand(kSlicedNotConsMask));
2207 __ b(ne, &sliced_string);
2208 // Cons string. Check whether it is flat, then fetch first part.
2209 __ ldr(r5, FieldMemOperand(r0, ConsString::kSecondOffset));
2210 __ CompareRoot(r5, Heap::kempty_stringRootIndex);
2211 __ b(ne, &runtime);
2212 __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset));
2213 // Update instance type.
2214 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset));
2215 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
2216 __ jmp(&underlying_unpacked);
2217
2218 __ bind(&sliced_string);
2219 // Sliced string. Fetch parent and correct start index by offset.
2220 __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
2221 __ ldr(r4, FieldMemOperand(r0, SlicedString::kOffsetOffset));
2222 __ add(r3, r3, Operand(r4, ASR, 1)); // Add offset to index.
2223 // Update instance type.
2224 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset));
2225 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
2226 __ jmp(&underlying_unpacked);
2227
2228 __ bind(&seq_or_external_string);
2229 // Sequential or external string. Just move string to the expected register.
2230 __ mov(r5, r0);
2231
2232 __ bind(&underlying_unpacked);
2233
2234 if (FLAG_string_slices) {
2235 Label copy_routine;
2236 // r5: underlying subject string
2237 // r1: instance type of underlying subject string
2238 // r2: length
2239 // r3: adjusted start index (untagged)
2240 __ cmp(r2, Operand(SlicedString::kMinLength));
2241 // Short slice. Copy instead of slicing.
2242 __ b(lt, &copy_routine);
2243 // Allocate new sliced string. At this point we do not reload the instance
2244 // type including the string encoding because we simply rely on the info
2245 // provided by the original string. It does not matter if the original
2246 // string's encoding is wrong because we always have to recheck encoding of
2247 // the newly created string's parent anyways due to externalized strings.
2248 Label two_byte_slice, set_slice_header;
2249 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
2250 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
2251 __ tst(r1, Operand(kStringEncodingMask));
2252 __ b(eq, &two_byte_slice);
2253 __ AllocateOneByteSlicedString(r0, r2, r6, r4, &runtime);
2254 __ jmp(&set_slice_header);
2255 __ bind(&two_byte_slice);
2256 __ AllocateTwoByteSlicedString(r0, r2, r6, r4, &runtime);
2257 __ bind(&set_slice_header);
2258 __ mov(r3, Operand(r3, LSL, 1));
2259 __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
2260 __ str(r3, FieldMemOperand(r0, SlicedString::kOffsetOffset));
2261 __ jmp(&return_r0);
2262
2263 __ bind(&copy_routine);
2264 }
2265
2266 // r5: underlying subject string
2267 // r1: instance type of underlying subject string
2268 // r2: length
2269 // r3: adjusted start index (untagged)
2270 Label two_byte_sequential, sequential_string, allocate_result;
2271 STATIC_ASSERT(kExternalStringTag != 0);
2272 STATIC_ASSERT(kSeqStringTag == 0);
2273 __ tst(r1, Operand(kExternalStringTag));
2274 __ b(eq, &sequential_string);
2275
2276 // Handle external string.
2277 // Rule out short external strings.
2278 STATIC_ASSERT(kShortExternalStringTag != 0);
2279 __ tst(r1, Operand(kShortExternalStringTag));
2280 __ b(ne, &runtime);
2281 __ ldr(r5, FieldMemOperand(r5, ExternalString::kResourceDataOffset));
2282 // r5 already points to the first character of underlying string.
2283 __ jmp(&allocate_result);
2284
2285 __ bind(&sequential_string);
2286 // Locate first character of underlying subject string.
2287 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
2288 __ add(r5, r5, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
2289
2290 __ bind(&allocate_result);
2291 // Sequential acii string. Allocate the result.
2292 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
2293 __ tst(r1, Operand(kStringEncodingMask));
2294 __ b(eq, &two_byte_sequential);
2295
2296 // Allocate and copy the resulting one-byte string.
2297 __ AllocateOneByteString(r0, r2, r4, r6, r1, &runtime);
2298
2299 // Locate first character of substring to copy.
2300 __ add(r5, r5, r3);
2301 // Locate first character of result.
2302 __ add(r1, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
2303
2304 // r0: result string
2305 // r1: first character of result string
2306 // r2: result string length
2307 // r5: first character of substring to copy
2308 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
2309 StringHelper::GenerateCopyCharacters(
2310 masm, r1, r5, r2, r3, String::ONE_BYTE_ENCODING);
2311 __ jmp(&return_r0);
2312
2313 // Allocate and copy the resulting two-byte string.
2314 __ bind(&two_byte_sequential);
2315 __ AllocateTwoByteString(r0, r2, r4, r6, r1, &runtime);
2316
2317 // Locate first character of substring to copy.
2318 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
2319 __ add(r5, r5, Operand(r3, LSL, 1));
2320 // Locate first character of result.
2321 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
2322
2323 // r0: result string.
2324 // r1: first character of result.
2325 // r2: result length.
2326 // r5: first character of substring to copy.
2327 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
2328 StringHelper::GenerateCopyCharacters(
2329 masm, r1, r5, r2, r3, String::TWO_BYTE_ENCODING);
2330
2331 __ bind(&return_r0);
2332 Counters* counters = isolate()->counters();
2333 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
2334 __ Drop(3);
2335 __ Ret();
2336
2337 // Just jump to runtime to create the sub string.
2338 __ bind(&runtime);
2339 __ TailCallRuntime(Runtime::kSubString);
2340
2341 __ bind(&single_char);
2342 // r0: original string
2343 // r1: instance type
2344 // r2: length
2345 // r3: from index (untagged)
2346 __ SmiTag(r3, r3);
2347 StringCharAtGenerator generator(r0, r3, r2, r0, &runtime, &runtime, &runtime,
2348 RECEIVER_IS_STRING);
2349 generator.GenerateFast(masm);
2350 __ Drop(3);
2351 __ Ret();
2352 generator.SkipSlow(masm, &runtime);
2353 }
2354
2355 void ToStringStub::Generate(MacroAssembler* masm) { 2130 void ToStringStub::Generate(MacroAssembler* masm) {
2356 // The ToString stub takes one argument in r0. 2131 // The ToString stub takes one argument in r0.
2357 Label is_number; 2132 Label is_number;
2358 __ JumpIfSmi(r0, &is_number); 2133 __ JumpIfSmi(r0, &is_number);
2359 2134
2360 __ CompareObjectType(r0, r1, r1, FIRST_NONSTRING_TYPE); 2135 __ CompareObjectType(r0, r1, r1, FIRST_NONSTRING_TYPE);
2361 // r0: receiver 2136 // r0: receiver
2362 // r1: receiver instance type 2137 // r1: receiver instance type
2363 __ Ret(lo); 2138 __ Ret(lo);
2364 2139
(...skipping 2815 matching lines...) Expand 10 before | Expand all | Expand 10 after
5180 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, 4955 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
5181 kStackUnwindSpace, NULL, return_value_operand, NULL); 4956 kStackUnwindSpace, NULL, return_value_operand, NULL);
5182 } 4957 }
5183 4958
5184 #undef __ 4959 #undef __
5185 4960
5186 } // namespace internal 4961 } // namespace internal
5187 } // namespace v8 4962 } // namespace v8
5188 4963
5189 #endif // V8_TARGET_ARCH_ARM 4964 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/arm64/code-stubs-arm64.cc » ('j') | src/code-stub-assembler.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698