blob: 5ad4aad41eb35c2bdf30e047aae1756b56792f5b [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
3// found in the LICENSE file.
4
5#include "src/base/adapters.h"
6#include "src/compiler/frame-elider.h"
7
8namespace v8 {
9namespace internal {
10namespace compiler {
11
12FrameElider::FrameElider(InstructionSequence* code) : code_(code) {}
13
14void FrameElider::Run() {
15 MarkBlocks();
16 PropagateMarks();
17 MarkDeConstruction();
18}
19
20
21void FrameElider::MarkBlocks() {
Ben Murdochda12d292016-06-02 14:46:10 +010022 for (InstructionBlock* block : instruction_blocks()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023 if (block->needs_frame()) continue;
Ben Murdochda12d292016-06-02 14:46:10 +010024 for (int i = block->code_start(); i < block->code_end(); ++i) {
25 const Instruction* instr = InstructionAt(i);
26 if (instr->IsCall() || instr->IsDeoptimizeCall() ||
27 instr->arch_opcode() == ArchOpcode::kArchStackPointer) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028 block->mark_needs_frame();
29 break;
30 }
31 }
32 }
33}
34
35
36void FrameElider::PropagateMarks() {
Ben Murdochda12d292016-06-02 14:46:10 +010037 while (PropagateInOrder() || PropagateReversed()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000038 }
39}
40
41
42void FrameElider::MarkDeConstruction() {
Ben Murdochda12d292016-06-02 14:46:10 +010043 for (InstructionBlock* block : instruction_blocks()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 if (block->needs_frame()) {
45 // Special case: The start block needs a frame.
46 if (block->predecessors().empty()) {
47 block->mark_must_construct_frame();
48 }
49 // Find "frame -> no frame" transitions, inserting frame
50 // deconstructions.
Ben Murdochda12d292016-06-02 14:46:10 +010051 for (RpoNumber& succ : block->successors()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052 if (!InstructionBlockAt(succ)->needs_frame()) {
53 DCHECK_EQ(1U, block->SuccessorCount());
Ben Murdochda12d292016-06-02 14:46:10 +010054 const Instruction* last =
55 InstructionAt(block->last_instruction_index());
56 if (last->IsThrow() || last->IsTailCall() ||
57 last->IsDeoptimizeCall()) {
58 // We need to keep the frame if we exit the block through any
59 // of these.
60 continue;
61 }
62 // The only cases when we need to deconstruct are ret and jump.
63 DCHECK(last->IsRet() || last->IsJump());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 block->mark_must_deconstruct_frame();
65 }
66 }
67 } else {
68 // Find "no frame -> frame" transitions, inserting frame constructions.
Ben Murdochda12d292016-06-02 14:46:10 +010069 for (RpoNumber& succ : block->successors()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 if (InstructionBlockAt(succ)->needs_frame()) {
71 DCHECK_NE(1U, block->SuccessorCount());
72 InstructionBlockAt(succ)->mark_must_construct_frame();
73 }
74 }
75 }
76 }
77}
78
79
80bool FrameElider::PropagateInOrder() {
81 bool changed = false;
Ben Murdochda12d292016-06-02 14:46:10 +010082 for (InstructionBlock* block : instruction_blocks()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 changed |= PropagateIntoBlock(block);
84 }
85 return changed;
86}
87
88
89bool FrameElider::PropagateReversed() {
90 bool changed = false;
Ben Murdochda12d292016-06-02 14:46:10 +010091 for (InstructionBlock* block : base::Reversed(instruction_blocks())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092 changed |= PropagateIntoBlock(block);
93 }
94 return changed;
95}
96
97
98bool FrameElider::PropagateIntoBlock(InstructionBlock* block) {
99 // Already marked, nothing to do...
100 if (block->needs_frame()) return false;
101
102 // Never mark the dummy end node, otherwise we might incorrectly decide to
103 // put frame deconstruction code there later,
104 if (block->successors().empty()) return false;
105
106 // Propagate towards the end ("downwards") if there is a predecessor needing
107 // a frame, but don't "bleed" from deferred code to non-deferred code.
Ben Murdochda12d292016-06-02 14:46:10 +0100108 for (RpoNumber& pred : block->predecessors()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109 if (InstructionBlockAt(pred)->needs_frame() &&
110 (!InstructionBlockAt(pred)->IsDeferred() || block->IsDeferred())) {
111 block->mark_needs_frame();
112 return true;
113 }
114 }
115
116 // Propagate towards start ("upwards") if there are successors and all of
117 // them need a frame.
Ben Murdochda12d292016-06-02 14:46:10 +0100118 for (RpoNumber& succ : block->successors()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000119 if (!InstructionBlockAt(succ)->needs_frame()) return false;
120 }
121 block->mark_needs_frame();
122 return true;
123}
124
125
126const InstructionBlocks& FrameElider::instruction_blocks() const {
127 return code_->instruction_blocks();
128}
129
130
131InstructionBlock* FrameElider::InstructionBlockAt(RpoNumber rpo_number) const {
132 return code_->InstructionBlockAt(rpo_number);
133}
134
135
136Instruction* FrameElider::InstructionAt(int index) const {
137 return code_->InstructionAt(index);
138}
139
140} // namespace compiler
141} // namespace internal
142} // namespace v8