LCOV - code coverage report
Current view: top level - src/compiler - frame-elider.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 54 56 96.4 %
Date: 2017-04-26 Functions: 9 11 81.8 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/frame-elider.h"
       6             : 
       7             : #include "src/base/adapters.h"
       8             : 
       9             : namespace v8 {
      10             : namespace internal {
      11             : namespace compiler {
      12             : 
      13      915006 : FrameElider::FrameElider(InstructionSequence* code) : code_(code) {}
      14             : 
      15      914998 : void FrameElider::Run() {
      16      914998 :   MarkBlocks();
      17      915051 :   PropagateMarks();
      18      915039 :   MarkDeConstruction();
      19      915031 : }
      20             : 
      21             : 
      22      915129 : void FrameElider::MarkBlocks() {
      23    52127021 :   for (InstructionBlock* block : instruction_blocks()) {
      24    11457163 :     if (block->needs_frame()) continue;
      25    58555754 :     for (int i = block->code_start(); i < block->code_end(); ++i) {
      26    21073775 :       const Instruction* instr = InstructionAt(i);
      27    40911735 :       if (instr->IsCall() || instr->IsDeoptimizeCall() ||
      28    40790175 :           instr->arch_opcode() == ArchOpcode::kArchStackPointer ||
      29             :           instr->arch_opcode() == ArchOpcode::kArchFramePointer) {
      30             :         block->mark_needs_frame();
      31             :         break;
      32             :       }
      33             :     }
      34             :   }
      35      915052 : }
      36             : 
      37             : 
      38      915029 : void FrameElider::PropagateMarks() {
      39      915029 :   while (PropagateInOrder() || PropagateReversed()) {
      40             :   }
      41      915042 : }
      42             : 
      43             : 
      44      915044 : void FrameElider::MarkDeConstruction() {
      45    14422877 :   for (InstructionBlock* block : instruction_blocks()) {
      46    11457704 :     if (block->needs_frame()) {
      47             :       // Special case: The start block needs a frame.
      48     9216707 :       if (block->predecessors().empty()) {
      49             :         block->mark_must_construct_frame();
      50             :       }
      51             :       // Find "frame -> no frame" transitions, inserting frame
      52             :       // deconstructions.
      53    30794191 :       for (RpoNumber& succ : block->successors()) {
      54    12360753 :         if (!InstructionBlockAt(succ)->needs_frame()) {
      55             :           DCHECK_EQ(1U, block->SuccessorCount());
      56             :           const Instruction* last =
      57     1135096 :               InstructionAt(block->last_instruction_index());
      58     3309116 :           if (last->IsThrow() || last->IsTailCall() ||
      59             :               last->IsDeoptimizeCall()) {
      60             :             // We need to keep the frame if we exit the block through any
      61             :             // of these.
      62             :             continue;
      63             :           }
      64             :           // The only cases when we need to deconstruct are ret and jump.
      65             :           DCHECK(last->IsRet() || last->IsJump());
      66             :           block->mark_must_deconstruct_frame();
      67             :         }
      68             :       }
      69             :     } else {
      70             :       // Find "no frame -> frame" transitions, inserting frame constructions.
      71     6350693 :       for (RpoNumber& succ : block->successors()) {
      72     1868696 :         if (InstructionBlockAt(succ)->needs_frame()) {
      73             :           DCHECK_NE(1U, block->SuccessorCount());
      74             :           InstructionBlockAt(succ)->mark_must_construct_frame();
      75             :         }
      76             :       }
      77             :     }
      78             :   }
      79      915033 : }
      80             : 
      81             : 
      82     1454051 : bool FrameElider::PropagateInOrder() {
      83             :   bool changed = false;
      84    24910990 :   for (InstructionBlock* block : instruction_blocks()) {
      85    22002928 :     changed |= PropagateIntoBlock(block);
      86             :   }
      87     1454011 :   return changed;
      88             : }
      89             : 
      90             : 
      91      915073 : bool FrameElider::PropagateReversed() {
      92             :   bool changed = false;
      93    23830684 :   for (InstructionBlock* block : base::Reversed(instruction_blocks())) {
      94    11457821 :     changed |= PropagateIntoBlock(block);
      95             :   }
      96      915042 :   return changed;
      97             : }
      98             : 
      99             : 
     100    34974276 : bool FrameElider::PropagateIntoBlock(InstructionBlock* block) {
     101             :   // Already marked, nothing to do...
     102    33460494 :   if (block->needs_frame()) return false;
     103             : 
     104             :   // Never mark the dummy end node, otherwise we might incorrectly decide to
     105             :   // put frame deconstruction code there later,
     106    11821974 :   if (block->successors().empty()) return false;
     107             : 
     108             :   // Propagate towards the end ("downwards") if there is a predecessor needing
     109             :   // a frame, but don't "bleed" from deferred code to non-deferred code.
     110    23246351 :   for (RpoNumber& pred : block->predecessors()) {
     111    26813774 :     if (InstructionBlockAt(pred)->needs_frame() &&
     112     7819266 :         (!InstructionBlockAt(pred)->IsDeferred() || block->IsDeferred())) {
     113             :       block->mark_needs_frame();
     114             :       return true;
     115             :     }
     116             :   }
     117             : 
     118             :   // Propagate towards start ("upwards")
     119             :   bool need_frame_successors = false;
     120     3533374 :   if (block->SuccessorCount() == 1) {
     121             :     // For single successors, propagate the needs_frame information.
     122             :     need_frame_successors =
     123     2158281 :         InstructionBlockAt(block->successors()[0])->needs_frame();
     124             :   } else {
     125             :     // For multiple successors, each successor must only have a single
     126             :     // predecessor (because the graph is in edge-split form), so each successor
     127             :     // can independently create/dismantle a frame if needed. Given this
     128             :     // independent control, only propagate needs_frame if all non-deferred
     129             :     // blocks need a frame.
     130     1632958 :     for (RpoNumber& succ : block->successors()) {
     131     2992023 :       InstructionBlock* successor_block = InstructionBlockAt(succ);
     132             :       DCHECK_EQ(1, successor_block->PredecessorCount());
     133     1614315 :       if (!successor_block->IsDeferred()) {
     134     1377708 :         if (successor_block->needs_frame()) {
     135             :           need_frame_successors = true;
     136             :         } else {
     137             :           return false;
     138             :         }
     139             :       }
     140             :     }
     141             :   }
     142     2176956 :   if (need_frame_successors) {
     143             :     block->mark_needs_frame();
     144       37413 :     return true;
     145             :   } else {
     146             :     return false;
     147             :   }
     148             : }
     149             : 
     150             : 
     151           0 : const InstructionBlocks& FrameElider::instruction_blocks() const {
     152     4199297 :   return code_->instruction_blocks();
     153             : }
     154             : 
     155             : 
     156           0 : InstructionBlock* FrameElider::InstructionBlockAt(RpoNumber rpo_number) const {
     157    34688278 :   return code_->InstructionBlockAt(rpo_number);
     158             : }
     159             : 
     160             : 
     161    22208862 : Instruction* FrameElider::InstructionAt(int index) const {
     162    44417757 :   return code_->InstructionAt(index);
     163             : }
     164             : 
     165             : }  // namespace compiler
     166             : }  // namespace internal
     167             : }  // namespace v8

Generated by: LCOV version 1.10