| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/code-factory.h" | 5 #include "src/code-factory.h" |
| 6 #include "src/compilation-dependencies.h" | 6 #include "src/compilation-dependencies.h" |
| 7 #include "src/compiler/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
| 8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
| 9 #include "src/compiler/js-typed-lowering.h" | 9 #include "src/compiler/js-typed-lowering.h" |
| 10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
| (...skipping 2252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2263 | 2263 |
| 2264 | 2264 |
| 2265 Reduction JSTypedLowering::ReduceJSForInDone(Node* node) { | 2265 Reduction JSTypedLowering::ReduceJSForInDone(Node* node) { |
| 2266 DCHECK_EQ(IrOpcode::kJSForInDone, node->opcode()); | 2266 DCHECK_EQ(IrOpcode::kJSForInDone, node->opcode()); |
| 2267 node->TrimInputCount(2); | 2267 node->TrimInputCount(2); |
| 2268 NodeProperties::ChangeOp(node, machine()->Word32Equal()); | 2268 NodeProperties::ChangeOp(node, machine()->Word32Equal()); |
| 2269 return Changed(node); | 2269 return Changed(node); |
| 2270 } | 2270 } |
| 2271 | 2271 |
| 2272 | 2272 |
| 2273 Reduction JSTypedLowering::ReduceJSForInPrepare(Node* node) { | |
| 2274 DCHECK_EQ(IrOpcode::kJSForInPrepare, node->opcode()); | |
| 2275 Node* receiver = NodeProperties::GetValueInput(node, 0); | |
| 2276 Node* context = NodeProperties::GetContextInput(node); | |
| 2277 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); | |
| 2278 Node* effect = NodeProperties::GetEffectInput(node); | |
| 2279 Node* control = NodeProperties::GetControlInput(node); | |
| 2280 | |
| 2281 // Get the set of properties to enumerate. | |
| 2282 Node* cache_type = effect = graph()->NewNode( | |
| 2283 javascript()->CallRuntime(Runtime::kGetPropertyNamesFast), receiver, | |
| 2284 context, frame_state, effect, control); | |
| 2285 control = graph()->NewNode(common()->IfSuccess(), cache_type); | |
| 2286 | |
| 2287 Node* receiver_map = effect = | |
| 2288 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
| 2289 receiver, effect, control); | |
| 2290 Node* cache_type_map = effect = | |
| 2291 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
| 2292 cache_type, effect, control); | |
| 2293 Node* meta_map = jsgraph()->HeapConstant(factory()->meta_map()); | |
| 2294 | |
| 2295 // If we got a map from the GetPropertyNamesFast runtime call, we can do a | |
| 2296 // fast modification check. Otherwise, we got a fixed array, and we have to | |
| 2297 // perform a slow check on every iteration. | |
| 2298 Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), | |
| 2299 cache_type_map, meta_map); | |
| 2300 Node* branch0 = | |
| 2301 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | |
| 2302 | |
| 2303 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | |
| 2304 Node* cache_array_true0; | |
| 2305 Node* cache_length_true0; | |
| 2306 Node* cache_type_true0; | |
| 2307 Node* etrue0; | |
| 2308 { | |
| 2309 // Enum cache case. | |
| 2310 Node* cache_type_enum_length = etrue0 = graph()->NewNode( | |
| 2311 simplified()->LoadField(AccessBuilder::ForMapBitField3()), cache_type, | |
| 2312 effect, if_true0); | |
| 2313 cache_length_true0 = graph()->NewNode( | |
| 2314 simplified()->NumberBitwiseAnd(), cache_type_enum_length, | |
| 2315 jsgraph()->Int32Constant(Map::EnumLengthBits::kMask)); | |
| 2316 | |
| 2317 Node* check1 = | |
| 2318 graph()->NewNode(machine()->Word32Equal(), cache_length_true0, | |
| 2319 jsgraph()->Int32Constant(0)); | |
| 2320 Node* branch1 = | |
| 2321 graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0); | |
| 2322 | |
| 2323 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 2324 Node* cache_array_true1; | |
| 2325 Node* etrue1; | |
| 2326 { | |
| 2327 // No properties to enumerate. | |
| 2328 cache_array_true1 = | |
| 2329 jsgraph()->HeapConstant(factory()->empty_fixed_array()); | |
| 2330 etrue1 = etrue0; | |
| 2331 } | |
| 2332 | |
| 2333 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 2334 Node* cache_array_false1; | |
| 2335 Node* efalse1; | |
| 2336 { | |
| 2337 // Load the enumeration cache from the instance descriptors of {receiver}. | |
| 2338 Node* receiver_map_descriptors = efalse1 = graph()->NewNode( | |
| 2339 simplified()->LoadField(AccessBuilder::ForMapDescriptors()), | |
| 2340 receiver_map, etrue0, if_false1); | |
| 2341 Node* object_map_enum_cache = efalse1 = graph()->NewNode( | |
| 2342 simplified()->LoadField(AccessBuilder::ForDescriptorArrayEnumCache()), | |
| 2343 receiver_map_descriptors, efalse1, if_false1); | |
| 2344 cache_array_false1 = efalse1 = graph()->NewNode( | |
| 2345 simplified()->LoadField( | |
| 2346 AccessBuilder::ForDescriptorArrayEnumCacheBridgeCache()), | |
| 2347 object_map_enum_cache, efalse1, if_false1); | |
| 2348 } | |
| 2349 | |
| 2350 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 2351 etrue0 = | |
| 2352 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); | |
| 2353 cache_array_true0 = | |
| 2354 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2355 cache_array_true1, cache_array_false1, if_true0); | |
| 2356 | |
| 2357 cache_type_true0 = cache_type; | |
| 2358 } | |
| 2359 | |
| 2360 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | |
| 2361 Node* cache_array_false0; | |
| 2362 Node* cache_length_false0; | |
| 2363 Node* cache_type_false0; | |
| 2364 Node* efalse0; | |
| 2365 { | |
| 2366 // FixedArray case. | |
| 2367 cache_type_false0 = jsgraph()->OneConstant(); // Smi means slow check | |
| 2368 cache_array_false0 = cache_type; | |
| 2369 cache_length_false0 = efalse0 = graph()->NewNode( | |
| 2370 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), | |
| 2371 cache_array_false0, effect, if_false0); | |
| 2372 } | |
| 2373 | |
| 2374 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
| 2375 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | |
| 2376 Node* cache_array = | |
| 2377 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2378 cache_array_true0, cache_array_false0, control); | |
| 2379 Node* cache_length = | |
| 2380 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2381 cache_length_true0, cache_length_false0, control); | |
| 2382 cache_type = | |
| 2383 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2384 cache_type_true0, cache_type_false0, control); | |
| 2385 | |
| 2386 for (auto edge : node->use_edges()) { | |
| 2387 Node* const use = edge.from(); | |
| 2388 if (NodeProperties::IsEffectEdge(edge)) { | |
| 2389 edge.UpdateTo(effect); | |
| 2390 Revisit(use); | |
| 2391 } else { | |
| 2392 if (NodeProperties::IsControlEdge(edge)) { | |
| 2393 if (use->opcode() == IrOpcode::kIfSuccess) { | |
| 2394 Replace(use, control); | |
| 2395 } else if (use->opcode() == IrOpcode::kIfException) { | |
| 2396 edge.UpdateTo(cache_type_true0); | |
| 2397 continue; | |
| 2398 } else { | |
| 2399 UNREACHABLE(); | |
| 2400 } | |
| 2401 } else { | |
| 2402 DCHECK(NodeProperties::IsValueEdge(edge)); | |
| 2403 DCHECK_EQ(IrOpcode::kProjection, use->opcode()); | |
| 2404 switch (ProjectionIndexOf(use->op())) { | |
| 2405 case 0: | |
| 2406 Replace(use, cache_type); | |
| 2407 break; | |
| 2408 case 1: | |
| 2409 Replace(use, cache_array); | |
| 2410 break; | |
| 2411 case 2: | |
| 2412 Replace(use, cache_length); | |
| 2413 break; | |
| 2414 default: | |
| 2415 UNREACHABLE(); | |
| 2416 break; | |
| 2417 } | |
| 2418 } | |
| 2419 use->Kill(); | |
| 2420 } | |
| 2421 } | |
| 2422 return NoChange(); // All uses were replaced already above. | |
| 2423 } | |
| 2424 | |
| 2425 | |
| 2426 Reduction JSTypedLowering::ReduceJSForInNext(Node* node) { | 2273 Reduction JSTypedLowering::ReduceJSForInNext(Node* node) { |
| 2427 DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode()); | 2274 DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode()); |
| 2428 Node* receiver = NodeProperties::GetValueInput(node, 0); | 2275 Node* receiver = NodeProperties::GetValueInput(node, 0); |
| 2429 Node* cache_array = NodeProperties::GetValueInput(node, 1); | 2276 Node* cache_array = NodeProperties::GetValueInput(node, 1); |
| 2430 Node* cache_type = NodeProperties::GetValueInput(node, 2); | 2277 Node* cache_type = NodeProperties::GetValueInput(node, 2); |
| 2431 Node* index = NodeProperties::GetValueInput(node, 3); | 2278 Node* index = NodeProperties::GetValueInput(node, 3); |
| 2432 Node* context = NodeProperties::GetContextInput(node); | 2279 Node* context = NodeProperties::GetContextInput(node); |
| 2433 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); | 2280 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); |
| 2434 Node* effect = NodeProperties::GetEffectInput(node); | 2281 Node* effect = NodeProperties::GetEffectInput(node); |
| 2435 Node* control = NodeProperties::GetControlInput(node); | 2282 Node* control = NodeProperties::GetControlInput(node); |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2663 case IrOpcode::kJSCreateBlockContext: | 2510 case IrOpcode::kJSCreateBlockContext: |
| 2664 return ReduceJSCreateBlockContext(node); | 2511 return ReduceJSCreateBlockContext(node); |
| 2665 case IrOpcode::kJSCallConstruct: | 2512 case IrOpcode::kJSCallConstruct: |
| 2666 return ReduceJSCallConstruct(node); | 2513 return ReduceJSCallConstruct(node); |
| 2667 case IrOpcode::kJSCallFunction: | 2514 case IrOpcode::kJSCallFunction: |
| 2668 return ReduceJSCallFunction(node); | 2515 return ReduceJSCallFunction(node); |
| 2669 case IrOpcode::kJSForInDone: | 2516 case IrOpcode::kJSForInDone: |
| 2670 return ReduceJSForInDone(node); | 2517 return ReduceJSForInDone(node); |
| 2671 case IrOpcode::kJSForInNext: | 2518 case IrOpcode::kJSForInNext: |
| 2672 return ReduceJSForInNext(node); | 2519 return ReduceJSForInNext(node); |
| 2673 case IrOpcode::kJSForInPrepare: | |
| 2674 return ReduceJSForInPrepare(node); | |
| 2675 case IrOpcode::kJSForInStep: | 2520 case IrOpcode::kJSForInStep: |
| 2676 return ReduceJSForInStep(node); | 2521 return ReduceJSForInStep(node); |
| 2677 case IrOpcode::kSelect: | 2522 case IrOpcode::kSelect: |
| 2678 return ReduceSelect(node); | 2523 return ReduceSelect(node); |
| 2679 default: | 2524 default: |
| 2680 break; | 2525 break; |
| 2681 } | 2526 } |
| 2682 return NoChange(); | 2527 return NoChange(); |
| 2683 } | 2528 } |
| 2684 | 2529 |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2852 } | 2697 } |
| 2853 | 2698 |
| 2854 | 2699 |
| 2855 CompilationDependencies* JSTypedLowering::dependencies() const { | 2700 CompilationDependencies* JSTypedLowering::dependencies() const { |
| 2856 return dependencies_; | 2701 return dependencies_; |
| 2857 } | 2702 } |
| 2858 | 2703 |
| 2859 } // namespace compiler | 2704 } // namespace compiler |
| 2860 } // namespace internal | 2705 } // namespace internal |
| 2861 } // namespace v8 | 2706 } // namespace v8 |
| OLD | NEW |