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      915865 : FrameElider::FrameElider(InstructionSequence* code) : code_(code) {}
      14             : 
      15      915860 : void FrameElider::Run() {
      16      915860 :   MarkBlocks();
      17      915885 :   PropagateMarks();
      18      915873 :   MarkDeConstruction();
      19      915838 : }
      20             : 
      21             : 
      22      915960 : void FrameElider::MarkBlocks() {
      23    52134671 :   for (InstructionBlock* block : instruction_blocks()) {
      24    11460756 :     if (block->needs_frame()) continue;
      25    58554134 :     for (int i = block->code_start(); i < block->code_end(); ++i) {
      26    21070061 :       const Instruction* instr = InstructionAt(i);
      27    40904179 :       if (instr->IsCall() || instr->IsDeoptimizeCall() ||
      28    40782398 :           instr->arch_opcode() == ArchOpcode::kArchStackPointer ||
      29             :           instr->arch_opcode() == ArchOpcode::kArchFramePointer) {
      30             :         block->mark_needs_frame();
      31             :         break;
      32             :       }
      33             :     }
      34             :   }
      35      915884 : }
      36             : 
      37             : 
      38      915867 : void FrameElider::PropagateMarks() {
      39      915867 :   while (PropagateInOrder() || PropagateReversed()) {
      40             :   }
      41      915872 : }
      42             : 
      43             : 
      44      915877 : void FrameElider::MarkDeConstruction() {
      45    14428178 :   for (InstructionBlock* block : instruction_blocks()) {
      46    11461247 :     if (block->needs_frame()) {
      47             :       // Special case: The start block needs a frame.
      48     9218194 :       if (block->predecessors().empty()) {
      49             :         block->mark_must_construct_frame();
      50             :       }
      51             :       // Find "frame -> no frame" transitions, inserting frame
      52             :       // deconstructions.
      53    30798323 :       for (RpoNumber& succ : block->successors()) {
      54    12361936 :         if (!InstructionBlockAt(succ)->needs_frame()) {
      55             :           DCHECK_EQ(1U, block->SuccessorCount());
      56             :           const Instruction* last =
      57     1135218 :               InstructionAt(block->last_instruction_index());
      58     3309915 :           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     6356535 :       for (RpoNumber& succ : block->successors()) {
      72     1870423 :         if (InstructionBlockAt(succ)->needs_frame()) {
      73             :           DCHECK_NE(1U, block->SuccessorCount());
      74             :           InstructionBlockAt(succ)->mark_must_construct_frame();
      75             :         }
      76             :       }
      77             :     }
      78             :   }
      79      915836 : }
      80             : 
      81             : 
      82     1455609 : bool FrameElider::PropagateInOrder() {
      83             :   bool changed = false;
      84    24920480 :   for (InstructionBlock* block : instruction_blocks()) {
      85    22009333 :     changed |= PropagateIntoBlock(block);
      86             :   }
      87     1455538 :   return changed;
      88             : }
      89             : 
      90             : 
      91      915890 : bool FrameElider::PropagateReversed() {
      92             :   bool changed = false;
      93    23838476 :   for (InstructionBlock* block : base::Reversed(instruction_blocks())) {
      94    11461303 :     changed |= PropagateIntoBlock(block);
      95             :   }
      96      915870 :   return changed;
      97             : }
      98             : 
      99             : 
     100    34985051 : bool FrameElider::PropagateIntoBlock(InstructionBlock* block) {
     101             :   // Already marked, nothing to do...
     102    33470316 :   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    11828161 :   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    23257909 :   for (RpoNumber& pred : block->predecessors()) {
     111    26824217 :     if (InstructionBlockAt(pred)->needs_frame() &&
     112     7821095 :         (!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     3536616 :   if (block->SuccessorCount() == 1) {
     121             :     // For single successors, propagate the needs_frame information.
     122             :     need_frame_successors =
     123     2160174 :         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     1634438 :     for (RpoNumber& succ : block->successors()) {
     131     2994884 :       InstructionBlock* successor_block = InstructionBlockAt(succ);
     132             :       DCHECK_EQ(1, successor_block->PredecessorCount());
     133     1615828 :       if (!successor_block->IsDeferred()) {
     134     1379056 :         if (successor_block->needs_frame()) {
     135             :           need_frame_successors = true;
     136             :         } else {
     137             :           return false;
     138             :         }
     139             :       }
     140             :     }
     141             :   }
     142     2178819 :   if (need_frame_successors) {
     143             :     block->mark_needs_frame();
     144       37404 :     return true;
     145             :   } else {
     146             :     return false;
     147             :   }
     148             : }
     149             : 
     150             : 
     151           0 : const InstructionBlocks& FrameElider::instruction_blocks() const {
     152     4203336 :   return code_->instruction_blocks();
     153             : }
     154             : 
     155             : 
     156           0 : InstructionBlock* FrameElider::InstructionBlockAt(RpoNumber rpo_number) const {
     157    34700191 :   return code_->InstructionBlockAt(rpo_number);
     158             : }
     159             : 
     160             : 
     161    22205256 : Instruction* FrameElider::InstructionAt(int index) const {
     162    44410503 :   return code_->InstructionAt(index);
     163             : }
     164             : 
     165             : }  // namespace compiler
     166             : }  // namespace internal
     167             : }  // namespace v8

Generated by: LCOV version 1.10