OLD | NEW |
---|---|
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 Loading... | |
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 |
OLD | NEW |