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

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

Issue 2355793003: [stubs] Port SubStringStub to TurboFan (Closed)
Patch Set: Address comments 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
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_IA32 5 #if V8_TARGET_ARCH_IA32
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 2047 matching lines...) Expand 10 before | Expand all | Expand 10 after
2058 __ mov_b(scratch, Operand(src, 0)); 2058 __ mov_b(scratch, Operand(src, 0));
2059 __ mov_b(Operand(dest, 0), scratch); 2059 __ mov_b(Operand(dest, 0), scratch);
2060 __ inc(src); 2060 __ inc(src);
2061 __ inc(dest); 2061 __ inc(dest);
2062 __ dec(count); 2062 __ dec(count);
2063 __ j(not_zero, &loop); 2063 __ j(not_zero, &loop);
2064 2064
2065 __ bind(&done); 2065 __ bind(&done);
2066 } 2066 }
2067 2067
2068
2069 void SubStringStub::Generate(MacroAssembler* masm) {
2070 Label runtime;
2071
2072 // Stack frame on entry.
2073 // esp[0]: return address
2074 // esp[4]: to
2075 // esp[8]: from
2076 // esp[12]: string
2077
2078 // Make sure first argument is a string.
2079 __ mov(eax, Operand(esp, 3 * kPointerSize));
2080 STATIC_ASSERT(kSmiTag == 0);
2081 __ JumpIfSmi(eax, &runtime);
2082 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx);
2083 __ j(NegateCondition(is_string), &runtime);
2084
2085 // eax: string
2086 // ebx: instance type
2087
2088 // Calculate length of sub string using the smi values.
2089 __ mov(ecx, Operand(esp, 1 * kPointerSize)); // To index.
2090 __ JumpIfNotSmi(ecx, &runtime);
2091 __ mov(edx, Operand(esp, 2 * kPointerSize)); // From index.
2092 __ JumpIfNotSmi(edx, &runtime);
2093 __ sub(ecx, edx);
2094 __ cmp(ecx, FieldOperand(eax, String::kLengthOffset));
2095 Label not_original_string;
2096 // Shorter than original string's length: an actual substring.
2097 __ j(below, &not_original_string, Label::kNear);
2098 // Longer than original string's length or negative: unsafe arguments.
2099 __ j(above, &runtime);
2100 // Return original string.
2101 Counters* counters = isolate()->counters();
2102 __ IncrementCounter(counters->sub_string_native(), 1);
2103 __ ret(3 * kPointerSize);
2104 __ bind(&not_original_string);
2105
2106 Label single_char;
2107 __ cmp(ecx, Immediate(Smi::FromInt(1)));
2108 __ j(equal, &single_char);
2109
2110 // eax: string
2111 // ebx: instance type
2112 // ecx: sub string length (smi)
2113 // edx: from index (smi)
2114 // Deal with different string types: update the index if necessary
2115 // and put the underlying string into edi.
2116 Label underlying_unpacked, sliced_string, seq_or_external_string;
2117 // If the string is not indirect, it can only be sequential or external.
2118 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
2119 STATIC_ASSERT(kIsIndirectStringMask != 0);
2120 __ test(ebx, Immediate(kIsIndirectStringMask));
2121 __ j(zero, &seq_or_external_string, Label::kNear);
2122
2123 Factory* factory = isolate()->factory();
2124 __ test(ebx, Immediate(kSlicedNotConsMask));
2125 __ j(not_zero, &sliced_string, Label::kNear);
2126 // Cons string. Check whether it is flat, then fetch first part.
2127 // Flat cons strings have an empty second part.
2128 __ cmp(FieldOperand(eax, ConsString::kSecondOffset),
2129 factory->empty_string());
2130 __ j(not_equal, &runtime);
2131 __ mov(edi, FieldOperand(eax, ConsString::kFirstOffset));
2132 // Update instance type.
2133 __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset));
2134 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
2135 __ jmp(&underlying_unpacked, Label::kNear);
2136
2137 __ bind(&sliced_string);
2138 // Sliced string. Fetch parent and adjust start index by offset.
2139 __ add(edx, FieldOperand(eax, SlicedString::kOffsetOffset));
2140 __ mov(edi, FieldOperand(eax, SlicedString::kParentOffset));
2141 // Update instance type.
2142 __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset));
2143 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
2144 __ jmp(&underlying_unpacked, Label::kNear);
2145
2146 __ bind(&seq_or_external_string);
2147 // Sequential or external string. Just move string to the expected register.
2148 __ mov(edi, eax);
2149
2150 __ bind(&underlying_unpacked);
2151
2152 if (FLAG_string_slices) {
2153 Label copy_routine;
2154 // edi: underlying subject string
2155 // ebx: instance type of underlying subject string
2156 // edx: adjusted start index (smi)
2157 // ecx: length (smi)
2158 __ cmp(ecx, Immediate(Smi::FromInt(SlicedString::kMinLength)));
2159 // Short slice. Copy instead of slicing.
2160 __ j(less, &copy_routine);
2161 // Allocate new sliced string. At this point we do not reload the instance
2162 // type including the string encoding because we simply rely on the info
2163 // provided by the original string. It does not matter if the original
2164 // string's encoding is wrong because we always have to recheck encoding of
2165 // the newly created string's parent anyways due to externalized strings.
2166 Label two_byte_slice, set_slice_header;
2167 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
2168 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
2169 __ test(ebx, Immediate(kStringEncodingMask));
2170 __ j(zero, &two_byte_slice, Label::kNear);
2171 __ AllocateOneByteSlicedString(eax, ebx, no_reg, &runtime);
2172 __ jmp(&set_slice_header, Label::kNear);
2173 __ bind(&two_byte_slice);
2174 __ AllocateTwoByteSlicedString(eax, ebx, no_reg, &runtime);
2175 __ bind(&set_slice_header);
2176 __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx);
2177 __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset),
2178 Immediate(String::kEmptyHashField));
2179 __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi);
2180 __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx);
2181 __ IncrementCounter(counters->sub_string_native(), 1);
2182 __ ret(3 * kPointerSize);
2183
2184 __ bind(&copy_routine);
2185 }
2186
2187 // edi: underlying subject string
2188 // ebx: instance type of underlying subject string
2189 // edx: adjusted start index (smi)
2190 // ecx: length (smi)
2191 // The subject string can only be external or sequential string of either
2192 // encoding at this point.
2193 Label two_byte_sequential, runtime_drop_two, sequential_string;
2194 STATIC_ASSERT(kExternalStringTag != 0);
2195 STATIC_ASSERT(kSeqStringTag == 0);
2196 __ test_b(ebx, Immediate(kExternalStringTag));
2197 __ j(zero, &sequential_string);
2198
2199 // Handle external string.
2200 // Rule out short external strings.
2201 STATIC_ASSERT(kShortExternalStringTag != 0);
2202 __ test_b(ebx, Immediate(kShortExternalStringMask));
2203 __ j(not_zero, &runtime);
2204 __ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset));
2205 // Move the pointer so that offset-wise, it looks like a sequential string.
2206 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
2207 __ sub(edi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
2208
2209 __ bind(&sequential_string);
2210 // Stash away (adjusted) index and (underlying) string.
2211 __ push(edx);
2212 __ push(edi);
2213 __ SmiUntag(ecx);
2214 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
2215 __ test_b(ebx, Immediate(kStringEncodingMask));
2216 __ j(zero, &two_byte_sequential);
2217
2218 // Sequential one byte string. Allocate the result.
2219 __ AllocateOneByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two);
2220
2221 // eax: result string
2222 // ecx: result string length
2223 // Locate first character of result.
2224 __ mov(edi, eax);
2225 __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
2226 // Load string argument and locate character of sub string start.
2227 __ pop(edx);
2228 __ pop(ebx);
2229 __ SmiUntag(ebx);
2230 __ lea(edx, FieldOperand(edx, ebx, times_1, SeqOneByteString::kHeaderSize));
2231
2232 // eax: result string
2233 // ecx: result length
2234 // edi: first character of result
2235 // edx: character of sub string start
2236 StringHelper::GenerateCopyCharacters(
2237 masm, edi, edx, ecx, ebx, String::ONE_BYTE_ENCODING);
2238 __ IncrementCounter(counters->sub_string_native(), 1);
2239 __ ret(3 * kPointerSize);
2240
2241 __ bind(&two_byte_sequential);
2242 // Sequential two-byte string. Allocate the result.
2243 __ AllocateTwoByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two);
2244
2245 // eax: result string
2246 // ecx: result string length
2247 // Locate first character of result.
2248 __ mov(edi, eax);
2249 __ add(edi,
2250 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
2251 // Load string argument and locate character of sub string start.
2252 __ pop(edx);
2253 __ pop(ebx);
2254 // As from is a smi it is 2 times the value which matches the size of a two
2255 // byte character.
2256 STATIC_ASSERT(kSmiTag == 0);
2257 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
2258 __ lea(edx, FieldOperand(edx, ebx, times_1, SeqTwoByteString::kHeaderSize));
2259
2260 // eax: result string
2261 // ecx: result length
2262 // edi: first character of result
2263 // edx: character of sub string start
2264 StringHelper::GenerateCopyCharacters(
2265 masm, edi, edx, ecx, ebx, String::TWO_BYTE_ENCODING);
2266 __ IncrementCounter(counters->sub_string_native(), 1);
2267 __ ret(3 * kPointerSize);
2268
2269 // Drop pushed values on the stack before tail call.
2270 __ bind(&runtime_drop_two);
2271 __ Drop(2);
2272
2273 // Just jump to runtime to create the sub string.
2274 __ bind(&runtime);
2275 __ TailCallRuntime(Runtime::kSubString);
2276
2277 __ bind(&single_char);
2278 // eax: string
2279 // ebx: instance type
2280 // ecx: sub string length (smi)
2281 // edx: from index (smi)
2282 StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime,
2283 &runtime, RECEIVER_IS_STRING);
2284 generator.GenerateFast(masm);
2285 __ ret(3 * kPointerSize);
2286 generator.SkipSlow(masm, &runtime);
2287 }
2288
2289 void ToStringStub::Generate(MacroAssembler* masm) { 2068 void ToStringStub::Generate(MacroAssembler* masm) {
2290 // The ToString stub takes one argument in eax. 2069 // The ToString stub takes one argument in eax.
2291 Label is_number; 2070 Label is_number;
2292 __ JumpIfSmi(eax, &is_number, Label::kNear); 2071 __ JumpIfSmi(eax, &is_number, Label::kNear);
2293 2072
2294 Label not_string; 2073 Label not_string;
2295 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi); 2074 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi);
2296 // eax: receiver 2075 // eax: receiver
2297 // edi: receiver map 2076 // edi: receiver map
2298 __ j(above_equal, &not_string, Label::kNear); 2077 __ j(above_equal, &not_string, Label::kNear);
(...skipping 3158 matching lines...) Expand 10 before | Expand all | Expand 10 after
5457 kStackUnwindSpace, nullptr, return_value_operand, 5236 kStackUnwindSpace, nullptr, return_value_operand,
5458 NULL); 5237 NULL);
5459 } 5238 }
5460 5239
5461 #undef __ 5240 #undef __
5462 5241
5463 } // namespace internal 5242 } // namespace internal
5464 } // namespace v8 5243 } // namespace v8
5465 5244
5466 #endif // V8_TARGET_ARCH_IA32 5245 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698