OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/escape-analysis-reducer.h" | 5 #include "src/compiler/escape-analysis-reducer.h" |
6 | 6 |
7 #include "src/compiler/all-nodes.h" | 7 #include "src/compiler/all-nodes.h" |
8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
9 #include "src/compiler/simplified-operator.h" | |
10 #include "src/compiler/type-cache.h" | |
9 #include "src/counters.h" | 11 #include "src/counters.h" |
10 | 12 |
11 namespace v8 { | 13 namespace v8 { |
12 namespace internal { | 14 namespace internal { |
13 namespace compiler { | 15 namespace compiler { |
14 | 16 |
15 #ifdef DEBUG | 17 #ifdef DEBUG |
16 #define TRACE(...) \ | 18 #define TRACE(...) \ |
17 do { \ | 19 do { \ |
18 if (FLAG_trace_turbo_escape) PrintF(__VA_ARGS__); \ | 20 if (FLAG_trace_turbo_escape) PrintF(__VA_ARGS__); \ |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 break; | 81 break; |
80 default: | 82 default: |
81 break; | 83 break; |
82 } | 84 } |
83 } | 85 } |
84 if (!depends_on_object_state) { | 86 if (!depends_on_object_state) { |
85 fully_reduced_.Add(node->id()); | 87 fully_reduced_.Add(node->id()); |
86 } | 88 } |
87 return NoChange(); | 89 return NoChange(); |
88 } | 90 } |
91 case IrOpcode::kNewUnmappedArgumentsElements: | |
92 arguments_elements_.insert(node); | |
93 // Fallthrough. | |
Jarin
2017/02/27 13:24:34
Could we get rid of the fallthrough?
Case fallthr
| |
89 default: | 94 default: |
90 // TODO(sigurds): Change this to GetFrameStateInputCount once | 95 // TODO(sigurds): Change this to GetFrameStateInputCount once |
91 // it is working. For now we use EffectInputCount > 0 to determine | 96 // it is working. For now we use EffectInputCount > 0 to determine |
92 // whether a node might have a frame state input. | 97 // whether a node might have a frame state input. |
93 if (exists_virtual_allocate_ && node->op()->EffectInputCount() > 0) { | 98 if (exists_virtual_allocate_ && node->op()->EffectInputCount() > 0) { |
94 return ReduceFrameStateUses(node); | 99 return ReduceFrameStateUses(node); |
95 } | 100 } |
96 break; | 101 break; |
97 } | 102 } |
98 return NoChange(); | 103 return NoChange(); |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
390 #ifdef DEBUG | 395 #ifdef DEBUG |
391 AllNodes all(zone(), jsgraph()->graph()); | 396 AllNodes all(zone(), jsgraph()->graph()); |
392 for (Node* node : all.reachable) { | 397 for (Node* node : all.reachable) { |
393 if (node->opcode() == IrOpcode::kAllocate) { | 398 if (node->opcode() == IrOpcode::kAllocate) { |
394 CHECK(!escape_analysis_->IsVirtual(node)); | 399 CHECK(!escape_analysis_->IsVirtual(node)); |
395 } | 400 } |
396 } | 401 } |
397 #endif // DEBUG | 402 #endif // DEBUG |
398 } | 403 } |
399 | 404 |
405 void EscapeAnalysisReducer::Finalize() { | |
406 for (Node* node : arguments_elements_) { | |
407 DCHECK(node->opcode() == IrOpcode::kNewUnmappedArgumentsElements); | |
408 | |
409 Node* arguments_frame = NodeProperties::GetValueInput(node, 0); | |
410 if (arguments_frame->opcode() != IrOpcode::kArgumentsFrame) continue; | |
411 Node* arguments_length = NodeProperties::GetValueInput(node, 1); | |
412 if (arguments_length->opcode() != IrOpcode::kArgumentsLength) continue; | |
413 | |
414 bool escaping_use = false; | |
415 ZoneVector<Node*> loads(zone()); | |
416 for (Edge edge : node->use_edges()) { | |
417 Node* use = edge.from(); | |
418 if (!NodeProperties::IsValueEdge(edge)) continue; | |
419 switch (use->opcode()) { | |
420 case IrOpcode::kStateValues: | |
421 case IrOpcode::kTypedStateValues: | |
422 case IrOpcode::kObjectState: | |
423 case IrOpcode::kTypedObjectState: | |
424 break; | |
425 case IrOpcode::kLoadElement: | |
426 loads.push_back(use); | |
427 break; | |
428 case IrOpcode::kLoadField: | |
429 if (FieldAccessOf(use->op()).offset == FixedArray::kLengthOffset) { | |
430 loads.push_back(use); | |
431 break; | |
432 } | |
433 // Fallthrough. | |
Jarin
2017/02/27 13:24:34
Could not you say here
if (...) {
load.push_bac
| |
434 default: | |
435 if (!use->use_edges().empty()) { | |
Jarin
2017/02/27 13:24:34
Explain in a comment what this check does, please.
| |
436 escaping_use = true; | |
437 break; | |
438 } | |
439 } | |
440 if (escaping_use) break; | |
441 } | |
442 if (!escaping_use) { | |
443 int formal_parameter_count = | |
444 FormalParameterCountOf(arguments_length->op()); | |
445 Node* arguments_elements_state = jsgraph()->graph()->NewNode( | |
446 jsgraph()->common()->ArgumentsElementsState( | |
447 IsRestLengthOf(arguments_length->op()))); | |
448 NodeProperties::SetType(arguments_elements_state, Type::OtherInternal()); | |
449 ReplaceWithValue(node, arguments_elements_state); | |
450 | |
451 ElementAccess stack_access; | |
452 stack_access.base_is_tagged = BaseTaggedness::kUntaggedBase; | |
453 // Reduce base address by {kPointerSize} such that (length - index) | |
454 // resolves to the right position. | |
455 stack_access.header_size = | |
456 CommonFrameConstants::kFixedFrameSizeAboveFp - kPointerSize; | |
457 stack_access.type = Type::NonInternal(); | |
458 stack_access.machine_type = MachineType::AnyTagged(); | |
459 stack_access.write_barrier_kind = WriteBarrierKind::kNoWriteBarrier; | |
460 const Operator* load_stack_op = | |
461 jsgraph()->simplified()->LoadElement(stack_access); | |
462 | |
463 for (Node* load : loads) { | |
464 switch (load->opcode()) { | |
465 case IrOpcode::kLoadElement: { | |
466 Node* index = NodeProperties::GetValueInput(load, 1); | |
467 // {offset} is a reverted index starting from 1. The base address is | |
468 // adapted to allow offsets starting from 1. | |
469 Node* offset = jsgraph()->graph()->NewNode( | |
470 jsgraph()->simplified()->NumberSubtract(), arguments_length, | |
471 index); | |
472 NodeProperties::SetType(offset, | |
473 TypeCache::Get().kArgumentsLengthType); | |
474 NodeProperties::ReplaceValueInput(load, arguments_frame, 0); | |
475 NodeProperties::ReplaceValueInput(load, offset, 1); | |
476 NodeProperties::ChangeOp(load, load_stack_op); | |
477 break; | |
478 } | |
479 case IrOpcode::kLoadField: { | |
480 DCHECK_EQ(FieldAccessOf(load->op()).offset, | |
481 FixedArray::kLengthOffset); | |
482 Node* length = NodeProperties::GetValueInput(node, 1); | |
483 ReplaceWithValue(load, length); | |
484 break; | |
485 } | |
486 default: | |
487 UNREACHABLE(); | |
488 } | |
489 } | |
490 } | |
491 } | |
492 } | |
493 | |
400 } // namespace compiler | 494 } // namespace compiler |
401 } // namespace internal | 495 } // namespace internal |
402 } // namespace v8 | 496 } // namespace v8 |
OLD | NEW |