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 |