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

Side by Side Diff: src/builtins/builtins-array.cc

Issue 2405253006: [builtins] implement Array.prototype[@@iterator] in TFJ builtins (Closed)
Patch Set: 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 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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 #include "src/builtins/builtins.h" 5 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7 7
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/contexts.h"
9 #include "src/elements.h" 10 #include "src/elements.h"
10 11
11 namespace v8 { 12 namespace v8 {
12 namespace internal { 13 namespace internal {
13 14
14 namespace { 15 namespace {
15 16
16 inline bool ClampedToInteger(Isolate* isolate, Object* object, int* out) { 17 inline bool ClampedToInteger(Isolate* isolate, Object* object, int* out) {
17 // This is an extended version of ECMA-262 7.1.11 handling signed values 18 // This is an extended version of ECMA-262 7.1.11 handling signed values
18 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt] 19 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
(...skipping 2041 matching lines...) Expand 10 before | Expand all | Expand 10 after
2060 assembler->Return(assembler->ChangeInt32ToTagged(index_var.value())); 2061 assembler->Return(assembler->ChangeInt32ToTagged(index_var.value()));
2061 2062
2062 assembler->Bind(&return_not_found); 2063 assembler->Bind(&return_not_found);
2063 assembler->Return(assembler->NumberConstant(-1)); 2064 assembler->Return(assembler->NumberConstant(-1));
2064 2065
2065 assembler->Bind(&call_runtime); 2066 assembler->Bind(&call_runtime);
2066 assembler->Return(assembler->CallRuntime(Runtime::kArrayIndexOf, context, 2067 assembler->Return(assembler->CallRuntime(Runtime::kArrayIndexOf, context,
2067 array, search_element, start_from)); 2068 array, search_element, start_from));
2068 } 2069 }
2069 2070
2071 void Builtins::Generate_ArrayPrototypeValues(CodeStubAssembler* assembler) {
Benedikt Meurer 2016/10/13 05:07:19 Do you plan to do a separate TypedArrayPrototypeVa
caitp 2016/10/13 22:32:43 I've made it so that the triplet methods (keys/val
2072 typedef compiler::Node Node;
2073 typedef CodeStubAssembler::Label Label;
2074 typedef CodeStubAssembler::Variable Variable;
2075
2076 Variable var_array(assembler, MachineRepresentation::kTagged);
2077 Variable var_result(assembler, MachineRepresentation::kTagged);
Benedikt Meurer 2016/10/13 05:07:20 This seems to be unused.
caitp 2016/10/13 22:32:43 I _think_ this is no longer an issue after the big
2078 Variable var_map(assembler, MachineRepresentation::kTagged);
2079 Variable var_map_index(assembler, MachineType::PointerRepresentation());
2080
2081 Label call_to_object(assembler);
2082 Label check_instance_type(assembler);
2083 Label if_isfastarray(assembler);
2084 Label if_isgeneric(assembler);
2085 Label allocate_array_iterator(assembler);
2086 Label allocate_typed_array_iterator(assembler);
2087
2088 Node* receiver = assembler->Parameter(0);
caitp 2016/10/13 00:13:36 For reasons I don't completely understand, the for
Benedikt Meurer 2016/10/13 05:07:19 Hm, this looks like a bug somewhere. You could rep
Yang 2016/10/13 13:52:37 Doesn't ring a bell, sorry. But I'm not all that s
caitp 2016/10/13 16:12:58 It turns out, including the receiver in the intern
2089 Node* context = assembler->Parameter(3);
2090 Node* native_context = assembler->LoadNativeContext(context);
2091
2092 var_array.Bind(receiver);
2093 var_result.Bind(assembler->UndefinedConstant());
2094 var_map.Bind(assembler->UndefinedConstant());
2095 var_map_index.Bind(assembler->IntPtrConstant(0));
Benedikt Meurer 2016/10/13 05:07:19 You don't need to bind var_map / var_map_index her
caitp 2016/10/13 22:32:43 This still happens in the new version, in CodeStub
2096
2097 assembler->Branch(assembler->TaggedIsSmi(var_array.value()), &call_to_object,
2098 &check_instance_type);
2099 assembler->Bind(&check_instance_type);
2100 {
2101 var_map.Bind(assembler->LoadMap(var_array.value()));
2102 Node* instance_type = assembler->LoadMapInstanceType(var_map.value());
2103 assembler->GotoIf(
2104 assembler->Int32LessThan(
2105 instance_type, assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)),
2106 &call_to_object);
2107
2108 assembler->GotoIf(
2109 assembler->WordEqual(instance_type,
2110 assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
2111 &allocate_typed_array_iterator);
2112
2113 assembler->BranchIfFastJSArray(var_array.value(), context, &if_isfastarray,
2114 &if_isgeneric);
2115 }
2116
2117 assembler->Bind(&if_isfastarray);
2118 {
2119 Node* map_index = assembler->IntPtrAdd(
Benedikt Meurer 2016/10/13 05:07:19 Neat! But please add some STATIC_ASSERTs to guard
caitp 2016/10/13 22:32:43 ah, I think I added some comments to this stuff, b
2120 assembler->IntPtrConstant(Context::FAST_ARRAY_VALUE_ITERATOR_MAP_INDEX),
2121 assembler->LoadMapElementsKind(assembler->LoadMap(var_array.value())));
2122 assembler->Assert(assembler->IntPtrLessThan(
2123 map_index, assembler->IntPtrConstant(
2124 Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX)));
2125
2126 var_map_index.Bind(map_index);
2127 assembler->Goto(&allocate_array_iterator);
2128 }
2129
2130 assembler->Bind(&call_to_object);
2131 {
2132 Callable callable = CodeFactory::ToObject(assembler->isolate());
2133 Node* result = assembler->CallStub(callable, context, var_array.value());
2134 var_map.Bind(assembler->LoadMap(result));
2135 var_array.Bind(result);
2136 assembler->Goto(&if_isgeneric);
2137 }
2138
2139 assembler->Bind(&if_isgeneric);
2140 {
2141 Node* map_index =
2142 assembler->IntPtrConstant(Context::FAST_ARRAY_VALUE_ITERATOR_MAP_INDEX);
2143
2144 var_map_index.Bind(map_index);
2145 assembler->Goto(&allocate_array_iterator);
2146 }
2147
2148 assembler->Bind(&allocate_array_iterator);
2149 {
2150 Node* iterator = assembler->Allocate(JSArrayIterator::kSize);
Benedikt Meurer 2016/10/13 05:07:19 Can you add a helper method AllocateArrayIterator(
caitp 2016/10/13 22:32:44 I've added CodeStubAssembler::AllocateJSArrayItera
2151 Node* map = assembler->LoadFixedArrayElement(
2152 native_context, var_map_index.value(), 0,
2153 CodeStubAssembler::INTPTR_PARAMETERS);
2154 assembler->StoreMapNoWriteBarrier(iterator, map);
2155 assembler->StoreObjectFieldRoot(iterator,
2156 JSIteratorResult::kPropertiesOffset,
2157 Heap::kEmptyFixedArrayRootIndex);
2158 assembler->StoreObjectFieldRoot(iterator, JSIteratorResult::kElementsOffset,
2159 Heap::kEmptyFixedArrayRootIndex);
2160 assembler->StoreObjectFieldNoWriteBarrier(
2161 iterator, JSArrayIterator::kIteratedObjectOffset, var_array.value());
2162 assembler->StoreObjectFieldNoWriteBarrier(
2163 iterator, JSArrayIterator::kNextIndexOffset,
2164 assembler->SmiConstant(Smi::FromInt(0)));
2165 assembler->StoreObjectFieldNoWriteBarrier(
2166 iterator, JSArrayIterator::kIteratedObjectMapOffset, var_map.value());
2167 assembler->Return(iterator);
2168 }
2169
2170 assembler->Bind(&allocate_typed_array_iterator);
2171 {
2172 Node* map_index = assembler->IntPtrAdd(
2173 assembler->IntPtrConstant(
2174 Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX),
2175 assembler->Int32Sub(assembler->LoadMapElementsKind(
2176 assembler->LoadMap(var_array.value())),
2177 assembler->Int32Constant(UINT8_ELEMENTS)));
2178 Node* map = assembler->LoadFixedArrayElement(
2179 native_context, map_index, 0, CodeStubAssembler::INTPTR_PARAMETERS);
2180 Node* iterator = assembler->Allocate(JSTypedArrayIterator::kSize);
2181 assembler->StoreMapNoWriteBarrier(iterator, map);
2182 assembler->StoreObjectFieldRoot(iterator,
2183 JSTypedArrayIterator::kPropertiesOffset,
2184 Heap::kEmptyFixedArrayRootIndex);
2185 assembler->StoreObjectFieldRoot(iterator,
2186 JSTypedArrayIterator::kElementsOffset,
2187 Heap::kEmptyFixedArrayRootIndex);
2188 assembler->StoreObjectFieldNoWriteBarrier(
2189 iterator, JSTypedArrayIterator::kIteratedObjectOffset,
2190 var_array.value());
2191 assembler->StoreObjectFieldNoWriteBarrier(
2192 iterator, JSTypedArrayIterator::kNextIndexOffset,
2193 assembler->SmiConstant(Smi::FromInt(0)));
2194 assembler->Return(iterator);
2195 }
2196 }
2197
2198 void Builtins::Generate_ArrayPrototypeEntries(CodeStubAssembler* assembler) {
Benedikt Meurer 2016/10/13 05:07:19 Can you unify this with the ArrayPrototypeValues a
caitp 2016/10/13 22:32:43 Done in CodeStubAssembler::CreateArrayIterator()
2199 typedef compiler::Node Node;
2200 typedef CodeStubAssembler::Label Label;
2201 typedef CodeStubAssembler::Variable Variable;
2202
2203 Variable var_array(assembler, MachineRepresentation::kTagged);
2204 Variable var_result(assembler, MachineRepresentation::kTagged);
2205 Variable var_map(assembler, MachineRepresentation::kTagged);
2206 Variable var_map_index(assembler, MachineType::PointerRepresentation());
2207
2208 Label call_to_object(assembler);
2209 Label check_instance_type(assembler);
2210 Label if_isfastarray(assembler);
2211 Label if_isgeneric(assembler);
2212 Label allocate_array_iterator(assembler);
2213 Label allocate_typed_array_iterator(assembler);
2214
2215 Node* receiver = assembler->Parameter(0);
2216 Node* context = assembler->Parameter(3);
2217 Node* native_context = assembler->LoadNativeContext(context);
2218
2219 var_array.Bind(receiver);
2220 var_result.Bind(assembler->UndefinedConstant());
2221 var_map.Bind(assembler->UndefinedConstant());
2222 var_map_index.Bind(assembler->IntPtrConstant(0));
2223
2224 assembler->Branch(assembler->TaggedIsSmi(var_array.value()), &call_to_object,
2225 &check_instance_type);
2226 assembler->Bind(&check_instance_type);
2227 {
2228 var_map.Bind(assembler->LoadMap(var_array.value()));
2229 Node* instance_type = assembler->LoadMapInstanceType(var_map.value());
2230 assembler->GotoIf(
2231 assembler->Int32LessThan(
2232 instance_type, assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)),
2233 &call_to_object);
2234
2235 assembler->GotoIf(
2236 assembler->WordEqual(instance_type,
2237 assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
2238 &allocate_typed_array_iterator);
2239
2240 assembler->BranchIfFastJSArray(var_array.value(), context, &if_isfastarray,
2241 &if_isgeneric);
2242 }
2243
2244 assembler->Bind(&if_isfastarray);
2245 {
2246 Node* map_index = assembler->IntPtrAdd(
2247 assembler->IntPtrConstant(
2248 Context::FAST_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX),
2249 assembler->LoadMapElementsKind(assembler->LoadMap(var_array.value())));
2250 assembler->Assert(assembler->IntPtrLessThan(
2251 map_index, assembler->IntPtrConstant(
2252 Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX)));
2253
2254 var_map_index.Bind(map_index);
2255 assembler->Goto(&allocate_array_iterator);
2256 }
2257
2258 assembler->Bind(&call_to_object);
2259 {
2260 Callable callable = CodeFactory::ToObject(assembler->isolate());
2261 Node* result = assembler->CallStub(callable, context, var_array.value());
2262 var_map.Bind(assembler->LoadMap(result));
2263 var_array.Bind(result);
2264 assembler->Goto(&if_isgeneric);
2265 }
2266
2267 assembler->Bind(&if_isgeneric);
2268 {
2269 Node* map_index = assembler->IntPtrConstant(
2270 Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX);
2271 var_map_index.Bind(map_index);
2272 assembler->Goto(&allocate_array_iterator);
2273 }
2274
2275 assembler->Bind(&allocate_array_iterator);
2276 {
2277 Node* iterator = assembler->Allocate(JSArrayIterator::kSize);
2278 Node* map = assembler->LoadFixedArrayElement(
2279 native_context, var_map_index.value(), 0,
2280 CodeStubAssembler::INTPTR_PARAMETERS);
2281 assembler->StoreMapNoWriteBarrier(iterator, map);
2282 assembler->StoreObjectFieldRoot(iterator,
2283 JSIteratorResult::kPropertiesOffset,
2284 Heap::kEmptyFixedArrayRootIndex);
2285 assembler->StoreObjectFieldRoot(iterator, JSIteratorResult::kElementsOffset,
2286 Heap::kEmptyFixedArrayRootIndex);
2287 assembler->StoreObjectFieldNoWriteBarrier(
2288 iterator, JSArrayIterator::kIteratedObjectOffset, var_array.value());
2289 assembler->StoreObjectFieldNoWriteBarrier(
2290 iterator, JSArrayIterator::kNextIndexOffset,
2291 assembler->SmiConstant(Smi::FromInt(0)));
2292 assembler->StoreObjectFieldNoWriteBarrier(
2293 iterator, JSArrayIterator::kIteratedObjectMapOffset, var_map.value());
2294 assembler->Return(iterator);
2295 }
2296
2297 assembler->Bind(&allocate_typed_array_iterator);
2298 {
2299 Node* map_index = assembler->IntPtrAdd(
2300 assembler->IntPtrConstant(
2301 Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX),
2302 assembler->Int32Sub(assembler->LoadMapElementsKind(var_map.value()),
2303 assembler->Int32Constant(UINT8_ELEMENTS)));
2304 Node* map = assembler->LoadFixedArrayElement(
2305 native_context, map_index, 0, CodeStubAssembler::INTPTR_PARAMETERS);
2306 Node* iterator = assembler->Allocate(JSTypedArrayIterator::kSize);
2307 assembler->StoreMapNoWriteBarrier(iterator, map);
2308 assembler->StoreObjectFieldRoot(iterator,
2309 JSTypedArrayIterator::kPropertiesOffset,
2310 Heap::kEmptyFixedArrayRootIndex);
2311 assembler->StoreObjectFieldRoot(iterator,
2312 JSTypedArrayIterator::kElementsOffset,
2313 Heap::kEmptyFixedArrayRootIndex);
2314 assembler->StoreObjectFieldNoWriteBarrier(
2315 iterator, JSTypedArrayIterator::kIteratedObjectOffset,
2316 var_array.value());
2317 assembler->StoreObjectFieldNoWriteBarrier(
2318 iterator, JSTypedArrayIterator::kNextIndexOffset,
2319 assembler->SmiConstant(Smi::FromInt(0)));
2320 assembler->Return(iterator);
2321 }
2322 }
2323
2324 void Builtins::Generate_ArrayPrototypeKeys(CodeStubAssembler* assembler) {
2325 typedef compiler::Node Node;
2326 typedef CodeStubAssembler::Label Label;
2327 typedef CodeStubAssembler::Variable Variable;
2328
2329 Variable var_array(assembler, MachineRepresentation::kTagged);
2330 Variable var_result(assembler, MachineRepresentation::kTagged);
2331 Variable var_map(assembler, MachineRepresentation::kTagged);
2332
2333 Label call_to_object(assembler);
2334 Label check_instance_type(assembler);
2335 Label if_isfastarray(assembler);
2336 Label if_isgeneric(assembler);
2337 Label allocate_array_iterator(assembler);
2338 Label allocate_typed_array_iterator(assembler);
2339
2340 Node* receiver = assembler->Parameter(0);
2341 Node* context = assembler->Parameter(3);
2342 Node* native_context = assembler->LoadNativeContext(context);
2343
2344 var_array.Bind(receiver);
2345 var_result.Bind(assembler->UndefinedConstant());
2346 var_map.Bind(assembler->UndefinedConstant());
Benedikt Meurer 2016/10/13 05:07:19 You don't need to Bind var_result and var_map here
caitp 2016/10/13 22:32:43 They are, but as I mentioned, they still hit CHECK
2347
2348 assembler->Branch(assembler->TaggedIsSmi(var_array.value()), &call_to_object,
2349 &check_instance_type);
2350 assembler->Bind(&check_instance_type);
2351 {
2352 var_map.Bind(assembler->LoadMap(var_array.value()));
2353 Node* instance_type = assembler->LoadMapInstanceType(var_map.value());
2354 assembler->GotoIf(
2355 assembler->Int32LessThan(
2356 instance_type, assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)),
2357 &call_to_object);
2358
2359 assembler->Branch(
2360 assembler->WordEqual(instance_type,
2361 assembler->Int32Constant(JS_ARRAY_TYPE)),
2362 &allocate_array_iterator, &allocate_typed_array_iterator);
Benedikt Meurer 2016/10/13 05:07:19 You need to handle the generic as well. Also non-f
caitp 2016/10/13 22:32:43 I'm not sure it's possible to skip the length chec
Benedikt Meurer 2016/10/14 03:46:50 What I'm saying is you need to do the map check de
2363 }
2364
2365 assembler->Bind(&call_to_object);
2366 {
2367 Callable callable = CodeFactory::ToObject(assembler->isolate());
2368 Node* result = assembler->CallStub(callable, context, var_array.value());
2369 var_array.Bind(result);
2370 assembler->Goto(&allocate_array_iterator);
2371 }
2372
2373 assembler->Bind(&allocate_array_iterator);
2374 {
2375 Node* map_index = assembler->IntPtrConstant(
2376 Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX);
2377 Node* map = assembler->LoadFixedArrayElement(
2378 native_context, map_index, 0, CodeStubAssembler::INTPTR_PARAMETERS);
2379 Node* iterator = assembler->Allocate(JSArrayIterator::kSize);
2380 assembler->StoreMapNoWriteBarrier(iterator, map);
2381 assembler->StoreObjectFieldRoot(iterator,
2382 JSIteratorResult::kPropertiesOffset,
2383 Heap::kEmptyFixedArrayRootIndex);
2384 assembler->StoreObjectFieldRoot(iterator, JSIteratorResult::kElementsOffset,
2385 Heap::kEmptyFixedArrayRootIndex);
2386 assembler->StoreObjectFieldNoWriteBarrier(
2387 iterator, JSArrayIterator::kIteratedObjectOffset, var_array.value());
2388 assembler->StoreObjectFieldNoWriteBarrier(
2389 iterator, JSArrayIterator::kNextIndexOffset,
2390 assembler->SmiConstant(Smi::FromInt(0)));
2391 assembler->StoreObjectFieldNoWriteBarrier(
2392 iterator, JSArrayIterator::kIteratedObjectMapOffset, var_map.value());
2393 assembler->Return(iterator);
2394 }
2395
2396 assembler->Bind(&allocate_typed_array_iterator);
2397 {
2398 Node* map_index =
2399 assembler->IntPtrConstant(Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX);
2400 Node* map = assembler->LoadFixedArrayElement(
2401 native_context, map_index, 0, CodeStubAssembler::INTPTR_PARAMETERS);
2402 Node* iterator = assembler->Allocate(JSTypedArrayIterator::kSize);
2403 assembler->StoreMapNoWriteBarrier(iterator, map);
2404 assembler->StoreObjectFieldRoot(iterator,
2405 JSTypedArrayIterator::kPropertiesOffset,
2406 Heap::kEmptyFixedArrayRootIndex);
2407 assembler->StoreObjectFieldRoot(iterator,
2408 JSTypedArrayIterator::kElementsOffset,
2409 Heap::kEmptyFixedArrayRootIndex);
2410 assembler->StoreObjectFieldNoWriteBarrier(
2411 iterator, JSTypedArrayIterator::kIteratedObjectOffset,
2412 var_array.value());
2413 assembler->StoreObjectFieldNoWriteBarrier(
2414 iterator, JSTypedArrayIterator::kNextIndexOffset,
2415 assembler->SmiConstant(Smi::FromInt(0)));
2416 assembler->Return(iterator);
2417 }
2418 }
2419
2420 void Builtins::Generate_ArrayIteratorPrototypeNext(
2421 CodeStubAssembler* assembler) {
2422 typedef compiler::Node Node;
2423 typedef CodeStubAssembler::Label Label;
2424 typedef CodeStubAssembler::Variable Variable;
2425
2426 Variable var_value(assembler, MachineRepresentation::kTagged);
2427 Variable var_done(assembler, MachineRepresentation::kTagged);
2428 Variable var_result(assembler, MachineRepresentation::kTagged);
2429
2430 Label set_done_and_return(assembler);
2431 Label did_set_done(assembler);
2432 Label allocate_entry_if_needed(assembler);
2433 Label allocate_iterator_result(assembler);
2434 Label throw_bad_receiver(assembler);
2435
2436 Label if_isarray(assembler);
2437 Label if_istypedarray(assembler);
2438 Label if_slow(assembler);
2439 Label if_slownotkeyiterator(assembler);
2440
2441 var_value.Bind(assembler->UndefinedConstant());
2442 var_done.Bind(assembler->BooleanConstant(false));
2443 var_result.Bind(assembler->UndefinedConstant());
2444
2445 Node* iterator = assembler->Parameter(0);
2446 Node* context = assembler->Parameter(3);
2447
2448 // If O does not have all of the internal slots of an Array Iterator Instance
2449 // (22.1.5.3), throw a TypeError exception
2450 assembler->GotoIf(assembler->TaggedIsSmi(iterator), &throw_bad_receiver);
2451 Node* instance_type = assembler->LoadInstanceType(iterator);
2452 // FIXME: Use bitmasks instead of integer ranges
Benedikt Meurer 2016/10/13 05:07:19 You can subtract the base and then do a single uns
caitp 2016/10/13 22:32:43 Done, seems to be working nicely.
2453 assembler->GotoIf(
2454 assembler->Int32LessThan(
2455 instance_type, assembler->Int32Constant(FIRST_ARRAY_ITERATOR_TYPE)),
2456 &throw_bad_receiver);
2457 assembler->GotoIf(
2458 assembler->Int32GreaterThan(
2459 instance_type, assembler->Int32Constant(LAST_ARRAY_ITERATOR_TYPE)),
2460 &throw_bad_receiver);
2461
2462 Node* native_context = assembler->LoadNativeContext(context);
2463
2464 // Let a be O.[[IteratedObject]].
2465 STATIC_ASSERT(JSArrayIterator::kIteratedObjectOffset ==
2466 JSTypedArrayIterator::kIteratedObjectOffset);
2467 Node* array = assembler->LoadObjectField(
2468 iterator, JSArrayIterator::kIteratedObjectOffset);
2469
2470 Node* array_map = assembler->LoadMap(array);
2471 Node* array_type = assembler->LoadMapInstanceType(array_map);
2472
2473 // If a is undefined, return CreateIterResultObject(undefined, true)
2474 assembler->GotoIf(assembler->WordEqual(array, assembler->UndefinedConstant()),
2475 &did_set_done);
2476
2477 // Let index be O.[[ArrayIteratorNextIndex]].
2478 STATIC_ASSERT(JSArrayIterator::kNextIndexOffset ==
2479 JSTypedArrayIterator::kNextIndexOffset);
2480 Node* index =
2481 assembler->LoadObjectField(iterator, JSArrayIterator::kNextIndexOffset);
2482
2483 assembler->GotoIf(assembler->Word32Equal(
Benedikt Meurer 2016/10/13 05:07:19 How about just having a single switch over all rel
caitp 2016/10/13 22:32:43 Done
2484 array_type, assembler->Int32Constant(JS_ARRAY_TYPE)),
2485 &if_isarray);
2486
2487 assembler->Branch(
2488 assembler->Word32Equal(array_type,
2489 assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
2490 &if_istypedarray, &if_slow);
2491
2492 assembler->Bind(&if_isarray);
2493 { // JSArray-specialized algorithm for fast JSArrays
Benedikt Meurer 2016/10/13 05:07:19 You can only take the fast JSArray case if the arr
caitp 2016/10/13 22:32:43 I'll add some new interesting tests to ensure all
2494 assembler->Assert(assembler->TaggedIsSmi(index));
2495
2496 Node* length = assembler->LoadObjectField(array, JSArray::kLengthOffset);
2497 assembler->GotoIf(assembler->SmiAboveOrEqual(index, length),
2498 &set_done_and_return);
2499 assembler->StoreObjectFieldNoWriteBarrier(
2500 iterator, JSStringIterator::kNextIndexOffset,
2501 assembler->SmiAdd(index, assembler->SmiConstant(Smi::FromInt(1))));
2502
2503 Label if_keyiterator(assembler), if_notkeyiterator(assembler);
2504
2505 assembler->Branch(
2506 assembler->WordEqual(
2507 instance_type,
2508 assembler->Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)),
2509 &if_keyiterator, &if_notkeyiterator);
2510
2511 assembler->Bind(&if_keyiterator);
2512 {
2513 var_value.Bind(index);
2514 assembler->Goto(&allocate_iterator_result);
2515 }
2516
2517 assembler->Bind(&if_notkeyiterator);
2518 {
2519 assembler->GotoIf(
2520 assembler->WordEqual(instance_type,
2521 assembler->Int32Constant(
2522 JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE)),
2523 &if_slow);
2524 assembler->GotoIf(
2525 assembler->WordEqual(
2526 instance_type,
2527 assembler->Int32Constant(JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE)),
2528 &if_slownotkeyiterator);
2529 Node* orig_map = assembler->LoadObjectField(
2530 iterator, JSArrayIterator::kIteratedObjectMapOffset);
2531 assembler->GotoIf(assembler->WordNotEqual(orig_map, array_map),
2532 &if_slownotkeyiterator);
2533
2534 Node* elements = assembler->LoadElements(array);
2535 static int32_t kInstanceType[] = {
2536 JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2537 JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2538 JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2539 JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2540 JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2541 JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2542
2543 JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE,
2544 JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE,
2545 JS_FAST_ARRAY_VALUE_ITERATOR_TYPE,
2546 JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE,
2547 JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE,
2548 JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE,
2549 };
2550
2551 Label if_smiorobjects(assembler), if_doubles(assembler);
2552 Label* instance_type_handlers[] = {
2553 &if_smiorobjects, &if_smiorobjects, &if_smiorobjects,
2554 &if_smiorobjects, &if_doubles, &if_doubles,
2555 &if_smiorobjects, &if_smiorobjects, &if_smiorobjects,
2556 &if_smiorobjects, &if_doubles, &if_doubles};
2557
2558 assembler->Switch(instance_type, &set_done_and_return, kInstanceType,
2559 instance_type_handlers, arraysize(kInstanceType));
2560
2561 assembler->Bind(&if_smiorobjects);
2562 {
2563 Node* value = assembler->LoadFixedArrayElement(
2564 elements, index, 0, CodeStubAssembler::SMI_PARAMETERS);
2565 var_value.Bind(assembler->UndefinedConstant());
2566 assembler->GotoIf(
2567 assembler->WordEqual(value, assembler->TheHoleConstant()),
2568 &allocate_entry_if_needed);
2569 var_value.Bind(value);
2570 assembler->Goto(&allocate_entry_if_needed);
2571 }
2572
2573 assembler->Bind(&if_doubles);
2574 {
2575 Node* value = assembler->LoadFixedDoubleArrayElement(
2576 elements, index, MachineType::Float64(), 0,
2577 CodeStubAssembler::SMI_PARAMETERS, &allocate_entry_if_needed);
2578 var_value.Bind(assembler->AllocateHeapNumberWithValue(value));
2579 assembler->Goto(&allocate_entry_if_needed);
2580 }
2581 }
2582 }
2583
2584 assembler->Bind(&if_istypedarray);
2585 { // Special-cased algorithm for JSTypedArrays
2586 assembler->Assert(assembler->TaggedIsSmi(index));
2587
2588 Node* length = assembler->LoadObjectField(array, JSArray::kLengthOffset);
2589 assembler->GotoIf(assembler->SmiAboveOrEqual(index, length),
2590 &set_done_and_return);
2591 assembler->StoreObjectFieldNoWriteBarrier(
2592 iterator, JSStringIterator::kNextIndexOffset,
2593 assembler->SmiAdd(index, assembler->SmiConstant(Smi::FromInt(1))));
2594
2595 Label if_keyiterator(assembler), if_notkeyiterator(assembler);
2596
2597 assembler->Branch(assembler->WordEqual(
2598 instance_type, assembler->Int32Constant(
2599 JS_TYPED_ARRAY_KEY_ITERATOR_TYPE)),
2600 &if_keyiterator, &if_notkeyiterator);
2601
2602 assembler->Bind(&if_keyiterator);
2603 {
2604 var_value.Bind(index);
2605 assembler->Goto(&allocate_iterator_result);
2606 }
2607
2608 assembler->Bind(&if_notkeyiterator);
2609 {
2610 Node* elements = assembler->LoadElements(array);
2611 Node* base_pointer = assembler->LoadObjectField(
2612 elements, FixedTypedArrayBase::kBasePointerOffset);
2613 Node* external_pointer = assembler->LoadObjectField(
2614 elements, FixedTypedArrayBase::kExternalPointerOffset);
2615 Node* data_pointer = assembler->IntPtrAdd(base_pointer, external_pointer);
2616
2617 static int32_t kInstanceType[] = {
2618 JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2619 JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2620 JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2621 JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2622 JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2623 JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2624 JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2625 JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2626 JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE,
2627
2628 JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE,
2629 JS_INT8_ARRAY_VALUE_ITERATOR_TYPE,
2630 JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE,
2631 JS_INT16_ARRAY_VALUE_ITERATOR_TYPE,
2632 JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE,
2633 JS_INT32_ARRAY_VALUE_ITERATOR_TYPE,
2634 JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE,
2635 JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE,
2636 JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE,
2637 };
2638
2639 Label if_uint8(assembler), if_int8(assembler), if_uint16(assembler),
2640 if_int16(assembler), if_uint32(assembler), if_int32(assembler),
2641 if_float32(assembler), if_float64(assembler);
2642 Label* instance_type_handlers[] = {
2643 &if_uint8, &if_int8, &if_uint16, &if_int16, &if_uint32,
2644 &if_int32, &if_float32, &if_float64, &if_uint8, &if_uint8,
2645 &if_int8, &if_uint16, &if_int16, &if_uint32, &if_int32,
2646 &if_float32, &if_float64, &if_uint8};
2647
2648 assembler->Switch(instance_type, &set_done_and_return, kInstanceType,
2649 instance_type_handlers, arraysize(kInstanceType));
2650
2651 assembler->Bind(&if_uint8);
2652 {
2653 Node* value_uint8 = assembler->LoadFixedTypedArrayElement(
2654 data_pointer, index, UINT8_ELEMENTS,
2655 CodeStubAssembler::SMI_PARAMETERS);
2656 var_value.Bind(assembler->SmiFromWord(value_uint8));
2657 assembler->Goto(&allocate_entry_if_needed);
2658 }
2659 assembler->Bind(&if_int8);
2660 {
2661 Node* value_int8 = assembler->LoadFixedTypedArrayElement(
2662 data_pointer, index, INT8_ELEMENTS,
2663 CodeStubAssembler::SMI_PARAMETERS);
2664 var_value.Bind(assembler->SmiFromWord(value_int8));
2665 assembler->Goto(&allocate_entry_if_needed);
2666 }
2667 assembler->Bind(&if_uint16);
2668 {
2669 Node* value_uint16 = assembler->LoadFixedTypedArrayElement(
2670 data_pointer, index, UINT16_ELEMENTS,
2671 CodeStubAssembler::SMI_PARAMETERS);
2672 var_value.Bind(assembler->SmiFromWord(value_uint16));
2673 assembler->Goto(&allocate_entry_if_needed);
2674 }
2675 assembler->Bind(&if_int16);
2676 {
2677 Node* value_int16 = assembler->LoadFixedTypedArrayElement(
2678 data_pointer, index, INT16_ELEMENTS,
2679 CodeStubAssembler::SMI_PARAMETERS);
2680 var_value.Bind(assembler->SmiFromWord(value_int16));
2681 assembler->Goto(&allocate_entry_if_needed);
2682 }
2683 assembler->Bind(&if_uint32);
2684 {
2685 Node* value_uint32 = assembler->LoadFixedTypedArrayElement(
2686 data_pointer, index, UINT32_ELEMENTS,
2687 CodeStubAssembler::SMI_PARAMETERS);
2688 var_value.Bind(assembler->ChangeUint32ToTagged(value_uint32));
2689 assembler->Goto(&allocate_entry_if_needed);
2690 }
2691 assembler->Bind(&if_int32);
2692 {
2693 Node* value_int32 = assembler->LoadFixedTypedArrayElement(
2694 data_pointer, index, INT32_ELEMENTS,
2695 CodeStubAssembler::SMI_PARAMETERS);
2696 var_value.Bind(assembler->ChangeInt32ToTagged(value_int32));
2697 assembler->Goto(&allocate_entry_if_needed);
2698 }
2699 assembler->Bind(&if_float32);
2700 {
2701 Node* value_float32 = assembler->LoadFixedTypedArrayElement(
2702 data_pointer, index, FLOAT32_ELEMENTS,
2703 CodeStubAssembler::SMI_PARAMETERS);
2704 var_value.Bind(assembler->AllocateHeapNumberWithValue(
2705 assembler->ChangeFloat32ToFloat64(value_float32)));
2706 assembler->Goto(&allocate_entry_if_needed);
2707 }
2708 assembler->Bind(&if_float64);
2709 {
2710 Node* value_float64 = assembler->LoadFixedTypedArrayElement(
2711 data_pointer, index, FLOAT64_ELEMENTS,
2712 CodeStubAssembler::SMI_PARAMETERS);
2713 var_value.Bind(assembler->AllocateHeapNumberWithValue(value_float64));
2714 assembler->Goto(&allocate_entry_if_needed);
2715 }
2716 }
2717 }
2718
2719 assembler->Bind(&if_slow);
2720 { // Generic objects
2721 Label if_slowkeyiterator(assembler);
2722 // Let len be ? ToLength(? Get(a, "length")).
2723 Node* length;
2724 {
2725 Callable get_property = CodeFactory::GetProperty(assembler->isolate());
2726 length = assembler->CallStub(
2727 get_property, context, array,
2728 assembler->HeapConstant(
2729 assembler->isolate()->factory()->length_string()));
2730 Callable to_length = CodeFactory::ToLength(assembler->isolate());
2731 length = assembler->CallStub(to_length, context, length);
2732 }
2733
2734 // If index ≥ len, then <goto set_done_and_return>
2735 {
2736 Label if_notdone(assembler), if_smi(assembler), if_heapnum(assembler);
2737
2738 assembler->Branch(assembler->TaggedIsSmi(length), &if_smi, &if_heapnum);
2739
2740 assembler->Bind(&if_smi);
2741 {
2742 // Are these shortcuts valid?
2743 assembler->GotoUnless(assembler->TaggedIsSmi(index),
2744 &set_done_and_return);
2745 assembler->Branch(assembler->SmiBelow(index, length), &if_notdone,
2746 &set_done_and_return);
2747 }
2748
2749 assembler->Bind(&if_heapnum);
2750 {
2751 // Are these shortcuts valid?
2752 assembler->GotoIf(assembler->TaggedIsSmi(index), &if_notdone);
2753 assembler->Branch(
2754 assembler->Float64LessThan(assembler->LoadHeapNumberValue(index),
2755 assembler->LoadHeapNumberValue(length)),
2756 &if_notdone, &set_done_and_return);
2757 }
2758
2759 assembler->Bind(&if_notdone);
2760 assembler->StoreObjectFieldNoWriteBarrier(
2761 iterator, JSStringIterator::kNextIndexOffset,
2762 assembler->NumberInc(index));
2763
2764 assembler->Branch(
2765 assembler->WordEqual(
2766 instance_type,
2767 assembler->Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)),
2768 &if_slowkeyiterator, &if_slownotkeyiterator);
2769 }
2770
2771 assembler->Bind(&if_slowkeyiterator);
2772 {
2773 var_value.Bind(index);
2774 assembler->Goto(&allocate_iterator_result);
2775 }
2776
2777 assembler->Bind(&if_slownotkeyiterator);
2778 {
2779 Callable callable = CodeFactory::GetProperty(assembler->isolate());
2780 var_value.Bind(assembler->CallStub(callable, context, array, index));
2781 assembler->Goto(&allocate_entry_if_needed);
2782 }
2783 }
2784
2785 assembler->Bind(&set_done_and_return);
2786 {
2787 assembler->StoreObjectFieldNoWriteBarrier(
2788 iterator, JSTypedArrayIterator::kIteratedObjectOffset,
2789 assembler->UndefinedConstant());
2790 assembler->Goto(&did_set_done);
2791 assembler->Bind(&did_set_done);
2792 {
2793 var_value.Bind(assembler->UndefinedConstant());
2794 var_done.Bind(assembler->TrueConstant());
2795 assembler->Goto(&allocate_iterator_result);
2796 }
2797 }
2798
2799 assembler->Bind(&allocate_entry_if_needed);
2800 {
2801 assembler->GotoIf(
2802 assembler->Int32GreaterThan(
2803 instance_type,
2804 assembler->Int32Constant(LAST_ARRAY_KEY_VALUE_ITERATOR_TYPE)),
2805 &allocate_iterator_result);
2806 Node* elements = assembler->AllocateFixedArray(FAST_ELEMENTS,
2807 assembler->Int32Constant(2));
2808 assembler->StoreFixedArrayElement(elements, assembler->Int32Constant(0),
2809 index, SKIP_WRITE_BARRIER);
2810 assembler->StoreFixedArrayElement(elements, assembler->Int32Constant(1),
2811 var_value.value(), SKIP_WRITE_BARRIER);
2812
2813 Node* entry = assembler->Allocate(JSArray::kSize);
2814 Node* map = assembler->LoadFixedArrayElement(
2815 native_context,
2816 assembler->IntPtrConstant(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX), 0,
2817 CodeStubAssembler::INTPTR_PARAMETERS);
2818
2819 assembler->StoreMapNoWriteBarrier(entry, map);
2820 assembler->StoreObjectFieldRoot(entry, JSArray::kPropertiesOffset,
2821 Heap::kEmptyFixedArrayRootIndex);
2822 assembler->StoreObjectFieldNoWriteBarrier(entry, JSArray::kElementsOffset,
2823 elements);
2824 assembler->StoreObjectFieldNoWriteBarrier(
2825 entry, JSArray::kLengthOffset, assembler->SmiConstant(Smi::FromInt(2)));
2826
2827 var_value.Bind(entry);
2828 assembler->Goto(&allocate_iterator_result);
2829 }
2830
2831 assembler->Bind(&allocate_iterator_result);
2832 {
2833 Node* result = assembler->Allocate(JSIteratorResult::kSize);
2834 Node* map = assembler->LoadFixedArrayElement(
2835 native_context,
2836 assembler->IntPtrConstant(Context::ITERATOR_RESULT_MAP_INDEX), 0,
2837 CodeStubAssembler::INTPTR_PARAMETERS);
2838 assembler->StoreMapNoWriteBarrier(result, map);
2839 assembler->StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset,
2840 Heap::kEmptyFixedArrayRootIndex);
2841 assembler->StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
2842 Heap::kEmptyFixedArrayRootIndex);
2843 assembler->StoreObjectFieldNoWriteBarrier(
2844 result, JSIteratorResult::kValueOffset, var_value.value());
2845 assembler->StoreObjectFieldNoWriteBarrier(
2846 result, JSIteratorResult::kDoneOffset, var_done.value());
2847 assembler->Return(result);
2848 }
2849
2850 assembler->Bind(&throw_bad_receiver);
2851 {
2852 // The {receiver} is not a valid JSArrayIterator or JSTypedArrayIterator.
2853 Node* result = assembler->CallRuntime(
2854 Runtime::kThrowIncompatibleMethodReceiver, context,
2855 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
2856 "Array Iterator.prototype.next", TENURED)),
2857 iterator);
2858 assembler->Return(result);
2859 }
2860 }
2861
2070 } // namespace internal 2862 } // namespace internal
2071 } // namespace v8 2863 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | src/isolate.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698