Chromium Code Reviews| Index: src/compiler/escape-analysis-reducer.cc |
| diff --git a/src/compiler/escape-analysis-reducer.cc b/src/compiler/escape-analysis-reducer.cc |
| index be772f4e7607796c58679f8064b060924278e5c6..81dd8ad854dc20e44b32420a85d68738c5ecc012 100644 |
| --- a/src/compiler/escape-analysis-reducer.cc |
| +++ b/src/compiler/escape-analysis-reducer.cc |
| @@ -6,6 +6,8 @@ |
| #include "src/compiler/all-nodes.h" |
| #include "src/compiler/js-graph.h" |
| +#include "src/compiler/simplified-operator.h" |
| +#include "src/compiler/type-cache.h" |
| #include "src/counters.h" |
| namespace v8 { |
| @@ -86,6 +88,9 @@ Reduction EscapeAnalysisReducer::ReduceNode(Node* node) { |
| } |
| return NoChange(); |
| } |
| + case IrOpcode::kNewUnmappedArgumentsElements: |
| + arguments_elements_.insert(node); |
| + // Fallthrough. |
|
Jarin
2017/02/27 13:24:34
Could we get rid of the fallthrough?
Case fallthr
|
| default: |
| // TODO(sigurds): Change this to GetFrameStateInputCount once |
| // it is working. For now we use EffectInputCount > 0 to determine |
| @@ -397,6 +402,95 @@ void EscapeAnalysisReducer::VerifyReplacement() const { |
| #endif // DEBUG |
| } |
| +void EscapeAnalysisReducer::Finalize() { |
| + for (Node* node : arguments_elements_) { |
| + DCHECK(node->opcode() == IrOpcode::kNewUnmappedArgumentsElements); |
| + |
| + Node* arguments_frame = NodeProperties::GetValueInput(node, 0); |
| + if (arguments_frame->opcode() != IrOpcode::kArgumentsFrame) continue; |
| + Node* arguments_length = NodeProperties::GetValueInput(node, 1); |
| + if (arguments_length->opcode() != IrOpcode::kArgumentsLength) continue; |
| + |
| + bool escaping_use = false; |
| + ZoneVector<Node*> loads(zone()); |
| + for (Edge edge : node->use_edges()) { |
| + Node* use = edge.from(); |
| + if (!NodeProperties::IsValueEdge(edge)) continue; |
| + switch (use->opcode()) { |
| + case IrOpcode::kStateValues: |
| + case IrOpcode::kTypedStateValues: |
| + case IrOpcode::kObjectState: |
| + case IrOpcode::kTypedObjectState: |
| + break; |
| + case IrOpcode::kLoadElement: |
| + loads.push_back(use); |
| + break; |
| + case IrOpcode::kLoadField: |
| + if (FieldAccessOf(use->op()).offset == FixedArray::kLengthOffset) { |
| + loads.push_back(use); |
| + break; |
| + } |
| + // Fallthrough. |
|
Jarin
2017/02/27 13:24:34
Could not you say here
if (...) {
load.push_bac
|
| + default: |
| + if (!use->use_edges().empty()) { |
|
Jarin
2017/02/27 13:24:34
Explain in a comment what this check does, please.
|
| + escaping_use = true; |
| + break; |
| + } |
| + } |
| + if (escaping_use) break; |
| + } |
| + if (!escaping_use) { |
| + int formal_parameter_count = |
| + FormalParameterCountOf(arguments_length->op()); |
| + Node* arguments_elements_state = jsgraph()->graph()->NewNode( |
| + jsgraph()->common()->ArgumentsElementsState( |
| + IsRestLengthOf(arguments_length->op()))); |
| + NodeProperties::SetType(arguments_elements_state, Type::OtherInternal()); |
| + ReplaceWithValue(node, arguments_elements_state); |
| + |
| + ElementAccess stack_access; |
| + stack_access.base_is_tagged = BaseTaggedness::kUntaggedBase; |
| + // Reduce base address by {kPointerSize} such that (length - index) |
| + // resolves to the right position. |
| + stack_access.header_size = |
| + CommonFrameConstants::kFixedFrameSizeAboveFp - kPointerSize; |
| + stack_access.type = Type::NonInternal(); |
| + stack_access.machine_type = MachineType::AnyTagged(); |
| + stack_access.write_barrier_kind = WriteBarrierKind::kNoWriteBarrier; |
| + const Operator* load_stack_op = |
| + jsgraph()->simplified()->LoadElement(stack_access); |
| + |
| + for (Node* load : loads) { |
| + switch (load->opcode()) { |
| + case IrOpcode::kLoadElement: { |
| + Node* index = NodeProperties::GetValueInput(load, 1); |
| + // {offset} is a reverted index starting from 1. The base address is |
| + // adapted to allow offsets starting from 1. |
| + Node* offset = jsgraph()->graph()->NewNode( |
| + jsgraph()->simplified()->NumberSubtract(), arguments_length, |
| + index); |
| + NodeProperties::SetType(offset, |
| + TypeCache::Get().kArgumentsLengthType); |
| + NodeProperties::ReplaceValueInput(load, arguments_frame, 0); |
| + NodeProperties::ReplaceValueInput(load, offset, 1); |
| + NodeProperties::ChangeOp(load, load_stack_op); |
| + break; |
| + } |
| + case IrOpcode::kLoadField: { |
| + DCHECK_EQ(FieldAccessOf(load->op()).offset, |
| + FixedArray::kLengthOffset); |
| + Node* length = NodeProperties::GetValueInput(node, 1); |
| + ReplaceWithValue(load, length); |
| + break; |
| + } |
| + default: |
| + UNREACHABLE(); |
| + } |
| + } |
| + } |
| + } |
| +} |
| + |
| } // namespace compiler |
| } // namespace internal |
| } // namespace v8 |