| 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/base/adapters.h" | 5 #include "src/base/adapters.h" | 
| 6 #include "src/compiler/frame-elider.h" | 6 #include "src/compiler/frame-elider.h" | 
| 7 | 7 | 
| 8 namespace v8 { | 8 namespace v8 { | 
| 9 namespace internal { | 9 namespace internal { | 
| 10 namespace compiler { | 10 namespace compiler { | 
| 11 | 11 | 
| 12 FrameElider::FrameElider(InstructionSequence* code) : code_(code) {} | 12 FrameElider::FrameElider(InstructionSequence* code) : code_(code) {} | 
| 13 | 13 | 
| 14 void FrameElider::Run() { | 14 void FrameElider::Run() { | 
| 15   MarkBlocks(); | 15   MarkBlocks(); | 
| 16   PropagateMarks(); | 16   PropagateMarks(); | 
| 17   MarkDeConstruction(); | 17   MarkDeConstruction(); | 
| 18 } | 18 } | 
| 19 | 19 | 
| 20 | 20 | 
| 21 void FrameElider::MarkBlocks() { | 21 void FrameElider::MarkBlocks() { | 
| 22   for (auto block : instruction_blocks()) { | 22   for (InstructionBlock* block : instruction_blocks()) { | 
| 23     if (block->needs_frame()) continue; | 23     if (block->needs_frame()) continue; | 
| 24     for (auto i = block->code_start(); i < block->code_end(); ++i) { | 24     for (int i = block->code_start(); i < block->code_end(); ++i) { | 
| 25       if (InstructionAt(i)->IsCall() || | 25       if (InstructionAt(i)->IsCall() || | 
| 26           InstructionAt(i)->opcode() == ArchOpcode::kArchDeoptimize) { | 26           InstructionAt(i)->opcode() == ArchOpcode::kArchDeoptimize) { | 
| 27         block->mark_needs_frame(); | 27         block->mark_needs_frame(); | 
| 28         break; | 28         break; | 
| 29       } | 29       } | 
| 30     } | 30     } | 
| 31   } | 31   } | 
| 32 } | 32 } | 
| 33 | 33 | 
| 34 | 34 | 
| 35 void FrameElider::PropagateMarks() { | 35 void FrameElider::PropagateMarks() { | 
| 36   while (PropagateInOrder() && PropagateReversed()) { | 36   while (PropagateInOrder() && PropagateReversed()) { | 
| 37   } | 37   } | 
| 38 } | 38 } | 
| 39 | 39 | 
| 40 | 40 | 
| 41 void FrameElider::MarkDeConstruction() { | 41 void FrameElider::MarkDeConstruction() { | 
| 42   for (auto block : instruction_blocks()) { | 42   for (InstructionBlock* block : instruction_blocks()) { | 
| 43     if (block->needs_frame()) { | 43     if (block->needs_frame()) { | 
| 44       // Special case: The start block needs a frame. | 44       // Special case: The start block needs a frame. | 
| 45       if (block->predecessors().empty()) { | 45       if (block->predecessors().empty()) { | 
| 46         block->mark_must_construct_frame(); | 46         block->mark_must_construct_frame(); | 
| 47       } | 47       } | 
| 48       // Find "frame -> no frame" transitions, inserting frame | 48       // Find "frame -> no frame" transitions, inserting frame | 
| 49       // deconstructions. | 49       // deconstructions. | 
| 50       for (auto succ : block->successors()) { | 50       for (RpoNumber& succ : block->successors()) { | 
| 51         if (!InstructionBlockAt(succ)->needs_frame()) { | 51         if (!InstructionBlockAt(succ)->needs_frame()) { | 
| 52           DCHECK_EQ(1U, block->SuccessorCount()); | 52           DCHECK_EQ(1U, block->SuccessorCount()); | 
| 53           block->mark_must_deconstruct_frame(); | 53           block->mark_must_deconstruct_frame(); | 
| 54         } | 54         } | 
| 55       } | 55       } | 
| 56     } else { | 56     } else { | 
| 57       // Find "no frame -> frame" transitions, inserting frame constructions. | 57       // Find "no frame -> frame" transitions, inserting frame constructions. | 
| 58       for (auto succ : block->successors()) { | 58       for (RpoNumber& succ : block->successors()) { | 
| 59         if (InstructionBlockAt(succ)->needs_frame()) { | 59         if (InstructionBlockAt(succ)->needs_frame()) { | 
| 60           DCHECK_NE(1U, block->SuccessorCount()); | 60           DCHECK_NE(1U, block->SuccessorCount()); | 
| 61           InstructionBlockAt(succ)->mark_must_construct_frame(); | 61           InstructionBlockAt(succ)->mark_must_construct_frame(); | 
| 62         } | 62         } | 
| 63       } | 63       } | 
| 64     } | 64     } | 
| 65   } | 65   } | 
| 66 } | 66 } | 
| 67 | 67 | 
| 68 | 68 | 
| 69 bool FrameElider::PropagateInOrder() { | 69 bool FrameElider::PropagateInOrder() { | 
| 70   bool changed = false; | 70   bool changed = false; | 
| 71   for (auto block : instruction_blocks()) { | 71   for (InstructionBlock* block : instruction_blocks()) { | 
| 72     changed |= PropagateIntoBlock(block); | 72     changed |= PropagateIntoBlock(block); | 
| 73   } | 73   } | 
| 74   return changed; | 74   return changed; | 
| 75 } | 75 } | 
| 76 | 76 | 
| 77 | 77 | 
| 78 bool FrameElider::PropagateReversed() { | 78 bool FrameElider::PropagateReversed() { | 
| 79   bool changed = false; | 79   bool changed = false; | 
| 80   for (auto block : base::Reversed(instruction_blocks())) { | 80   for (InstructionBlock* block : base::Reversed(instruction_blocks())) { | 
| 81     changed |= PropagateIntoBlock(block); | 81     changed |= PropagateIntoBlock(block); | 
| 82   } | 82   } | 
| 83   return changed; | 83   return changed; | 
| 84 } | 84 } | 
| 85 | 85 | 
| 86 | 86 | 
| 87 bool FrameElider::PropagateIntoBlock(InstructionBlock* block) { | 87 bool FrameElider::PropagateIntoBlock(InstructionBlock* block) { | 
| 88   // Already marked, nothing to do... | 88   // Already marked, nothing to do... | 
| 89   if (block->needs_frame()) return false; | 89   if (block->needs_frame()) return false; | 
| 90 | 90 | 
| 91   // Never mark the dummy end node, otherwise we might incorrectly decide to | 91   // Never mark the dummy end node, otherwise we might incorrectly decide to | 
| 92   // put frame deconstruction code there later, | 92   // put frame deconstruction code there later, | 
| 93   if (block->successors().empty()) return false; | 93   if (block->successors().empty()) return false; | 
| 94 | 94 | 
| 95   // Propagate towards the end ("downwards") if there is a predecessor needing | 95   // Propagate towards the end ("downwards") if there is a predecessor needing | 
| 96   // a frame, but don't "bleed" from deferred code to non-deferred code. | 96   // a frame, but don't "bleed" from deferred code to non-deferred code. | 
| 97   for (auto pred : block->predecessors()) { | 97   for (RpoNumber& pred : block->predecessors()) { | 
| 98     if (InstructionBlockAt(pred)->needs_frame() && | 98     if (InstructionBlockAt(pred)->needs_frame() && | 
| 99         (!InstructionBlockAt(pred)->IsDeferred() || block->IsDeferred())) { | 99         (!InstructionBlockAt(pred)->IsDeferred() || block->IsDeferred())) { | 
| 100       block->mark_needs_frame(); | 100       block->mark_needs_frame(); | 
| 101       return true; | 101       return true; | 
| 102     } | 102     } | 
| 103   } | 103   } | 
| 104 | 104 | 
| 105   // Propagate towards start ("upwards") if there are successors and all of | 105   // Propagate towards start ("upwards") if there are successors and all of | 
| 106   // them need a frame. | 106   // them need a frame. | 
| 107   for (auto succ : block->successors()) { | 107   for (RpoNumber& succ : block->successors()) { | 
| 108     if (!InstructionBlockAt(succ)->needs_frame()) return false; | 108     if (!InstructionBlockAt(succ)->needs_frame()) return false; | 
| 109   } | 109   } | 
| 110   block->mark_needs_frame(); | 110   block->mark_needs_frame(); | 
| 111   return true; | 111   return true; | 
| 112 } | 112 } | 
| 113 | 113 | 
| 114 | 114 | 
| 115 const InstructionBlocks& FrameElider::instruction_blocks() const { | 115 const InstructionBlocks& FrameElider::instruction_blocks() const { | 
| 116   return code_->instruction_blocks(); | 116   return code_->instruction_blocks(); | 
| 117 } | 117 } | 
| 118 | 118 | 
| 119 | 119 | 
| 120 InstructionBlock* FrameElider::InstructionBlockAt(RpoNumber rpo_number) const { | 120 InstructionBlock* FrameElider::InstructionBlockAt(RpoNumber rpo_number) const { | 
| 121   return code_->InstructionBlockAt(rpo_number); | 121   return code_->InstructionBlockAt(rpo_number); | 
| 122 } | 122 } | 
| 123 | 123 | 
| 124 | 124 | 
| 125 Instruction* FrameElider::InstructionAt(int index) const { | 125 Instruction* FrameElider::InstructionAt(int index) const { | 
| 126   return code_->InstructionAt(index); | 126   return code_->InstructionAt(index); | 
| 127 } | 127 } | 
| 128 | 128 | 
| 129 }  // namespace compiler | 129 }  // namespace compiler | 
| 130 }  // namespace internal | 130 }  // namespace internal | 
| 131 }  // namespace v8 | 131 }  // namespace v8 | 
| OLD | NEW | 
|---|