LCOV - code coverage report
Current view: top level - src/interpreter - control-flow-builders.h (source / functions) Hit Total Coverage
Test: app.info Lines: 36 36 100.0 %
Date: 2017-10-20 Functions: 6 14 42.9 %

          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             : #ifndef V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
       6             : #define V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
       7             : 
       8             : #include "src/interpreter/bytecode-array-builder.h"
       9             : 
      10             : #include "src/ast/ast-source-ranges.h"
      11             : #include "src/interpreter/block-coverage-builder.h"
      12             : #include "src/interpreter/bytecode-label.h"
      13             : #include "src/zone/zone-containers.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : namespace interpreter {
      18             : 
      19             : class V8_EXPORT_PRIVATE ControlFlowBuilder BASE_EMBEDDED {
      20             :  public:
      21             :   explicit ControlFlowBuilder(BytecodeArrayBuilder* builder)
      22     6556280 :       : builder_(builder) {}
      23     6417846 :   virtual ~ControlFlowBuilder() {}
      24             : 
      25             :  protected:
      26             :   BytecodeArrayBuilder* builder() const { return builder_; }
      27             : 
      28             :  private:
      29             :   BytecodeArrayBuilder* builder_;
      30             : 
      31             :   DISALLOW_COPY_AND_ASSIGN(ControlFlowBuilder);
      32             : };
      33             : 
      34             : class V8_EXPORT_PRIVATE BreakableControlFlowBuilder
      35             :     : public ControlFlowBuilder {
      36             :  public:
      37     5402251 :   BreakableControlFlowBuilder(BytecodeArrayBuilder* builder,
      38             :                               BlockCoverageBuilder* block_coverage_builder,
      39             :                               AstNode* node)
      40             :       : ControlFlowBuilder(builder),
      41             :         break_labels_(builder->zone()),
      42             :         node_(node),
      43    10804502 :         block_coverage_builder_(block_coverage_builder) {}
      44             :   virtual ~BreakableControlFlowBuilder();
      45             : 
      46             :   // This method is called when visiting break statements in the AST.
      47             :   // Inserts a jump to an unbound label that is patched when the corresponding
      48             :   // BindBreakTarget is called.
      49       77323 :   void Break() { EmitJump(&break_labels_); }
      50             :   void BreakIfTrue(BytecodeArrayBuilder::ToBooleanMode mode) {
      51       24663 :     EmitJumpIfTrue(mode, &break_labels_);
      52             :   }
      53             :   void BreakIfFalse(BytecodeArrayBuilder::ToBooleanMode mode) {
      54        6072 :     EmitJumpIfFalse(mode, &break_labels_);
      55             :   }
      56             :   void BreakIfUndefined() { EmitJumpIfUndefined(&break_labels_); }
      57             :   void BreakIfNull() { EmitJumpIfNull(&break_labels_); }
      58             : 
      59             :   BytecodeLabels* break_labels() { return &break_labels_; }
      60             : 
      61      594551 :   void set_needs_continuation_counter() { needs_continuation_counter_ = true; }
      62             :   bool needs_continuation_counter() const {
      63             :     return needs_continuation_counter_;
      64             :   }
      65             : 
      66             :  protected:
      67             :   void EmitJump(BytecodeLabels* labels);
      68             :   void EmitJumpIfTrue(BytecodeArrayBuilder::ToBooleanMode mode,
      69             :                       BytecodeLabels* labels);
      70             :   void EmitJumpIfFalse(BytecodeArrayBuilder::ToBooleanMode mode,
      71             :                        BytecodeLabels* labels);
      72             :   void EmitJumpIfUndefined(BytecodeLabels* labels);
      73             :   void EmitJumpIfNull(BytecodeLabels* labels);
      74             : 
      75             :   // Called from the destructor to update sites that emit jumps for break.
      76             :   void BindBreakTarget();
      77             : 
      78             :   // Unbound labels that identify jumps for break statements in the code.
      79             :   BytecodeLabels break_labels_;
      80             : 
      81             :   // A continuation counter (for block coverage) is needed e.g. when
      82             :   // encountering a break statement.
      83             :   AstNode* node_;
      84             :   bool needs_continuation_counter_ = false;
      85             :   BlockCoverageBuilder* block_coverage_builder_;
      86             : };
      87             : 
      88             : 
      89             : // Class to track control flow for block statements (which can break in JS).
      90     5146767 : class V8_EXPORT_PRIVATE BlockBuilder final
      91             :     : public BreakableControlFlowBuilder {
      92             :  public:
      93             :   BlockBuilder(BytecodeArrayBuilder* builder,
      94             :                BlockCoverageBuilder* block_coverage_builder,
      95             :                BreakableStatement* statement)
      96             :       : BreakableControlFlowBuilder(builder, block_coverage_builder,
      97     5146767 :                                     statement) {}
      98             : };
      99             : 
     100             : 
     101             : // A class to help with co-ordinating break and continue statements with
     102             : // their loop.
     103             : class V8_EXPORT_PRIVATE LoopBuilder final : public BreakableControlFlowBuilder {
     104             :  public:
     105      477626 :   LoopBuilder(BytecodeArrayBuilder* builder,
     106             :               BlockCoverageBuilder* block_coverage_builder, AstNode* node)
     107             :       : BreakableControlFlowBuilder(builder, block_coverage_builder, node),
     108             :         continue_labels_(builder->zone()),
     109             :         generator_jump_table_location_(nullptr),
     110      477626 :         parent_generator_jump_table_(nullptr) {
     111      238813 :     if (block_coverage_builder_ != nullptr) {
     112             :       set_needs_continuation_counter();
     113             :       block_coverage_body_slot_ =
     114             :           block_coverage_builder_->AllocateBlockCoverageSlot(
     115         330 :               node, SourceRangeKind::kBody);
     116             :     }
     117      238813 :   }
     118             :   ~LoopBuilder();
     119             : 
     120             :   void LoopHeader();
     121             :   void LoopHeaderInGenerator(BytecodeJumpTable** parent_generator_jump_table,
     122             :                              int first_resume_id, int resume_count);
     123             :   void LoopBody();
     124             :   void JumpToHeader(int loop_depth);
     125             :   void BindContinueTarget();
     126             : 
     127             :   // This method is called when visiting continue statements in the AST.
     128             :   // Inserts a jump to an unbound label that is patched when BindContinueTarget
     129             :   // is called.
     130        8726 :   void Continue() { EmitJump(&continue_labels_); }
     131        6072 :   void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_labels_); }
     132             :   void ContinueIfNull() { EmitJumpIfNull(&continue_labels_); }
     133             : 
     134             :  private:
     135             :   BytecodeLabel loop_header_;
     136             : 
     137             :   // Unbound labels that identify jumps for continue statements in the code and
     138             :   // jumps from checking the loop condition to the header for do-while loops.
     139             :   BytecodeLabels continue_labels_;
     140             : 
     141             :   // While we're in the loop, we want to have a different jump table for
     142             :   // generator switch statements. We restore it at the end of the loop.
     143             :   // TODO(leszeks): Storing a pointer to the BytecodeGenerator's jump table
     144             :   // field is ugly, figure out a better way to do this.
     145             :   BytecodeJumpTable** generator_jump_table_location_;
     146             :   BytecodeJumpTable* parent_generator_jump_table_;
     147             : 
     148             :   int block_coverage_body_slot_;
     149             : };
     150             : 
     151             : 
     152             : // A class to help with co-ordinating break statements with their switch.
     153             : class V8_EXPORT_PRIVATE SwitchBuilder final
     154             :     : public BreakableControlFlowBuilder {
     155             :  public:
     156       33342 :   SwitchBuilder(BytecodeArrayBuilder* builder,
     157             :                 BlockCoverageBuilder* block_coverage_builder,
     158             :                 SwitchStatement* statement, int number_of_cases)
     159             :       : BreakableControlFlowBuilder(builder, block_coverage_builder, statement),
     160       16671 :         case_sites_(builder->zone()) {
     161       16671 :     case_sites_.resize(number_of_cases);
     162       16671 :   }
     163             :   ~SwitchBuilder();
     164             : 
     165             :   // This method should be called by the SwitchBuilder owner when the case
     166             :   // statement with |index| is emitted to update the case jump site.
     167             :   void SetCaseTarget(int index, CaseClause* clause);
     168             : 
     169             :   // This method is called when visiting case comparison operation for |index|.
     170             :   // Inserts a JumpIfTrue with ToBooleanMode |mode| to a unbound label that is
     171             :   // patched when the corresponding SetCaseTarget is called.
     172       93269 :   void Case(BytecodeArrayBuilder::ToBooleanMode mode, int index) {
     173      186538 :     builder()->JumpIfTrue(mode, &case_sites_.at(index));
     174       93269 :   }
     175             : 
     176             :   // This method is called when all cases comparisons have been emitted if there
     177             :   // is a default case statement. Inserts a Jump to a unbound label that is
     178             :   // patched when the corresponding SetCaseTarget is called.
     179       14678 :   void DefaultAt(int index) { builder()->Jump(&case_sites_.at(index)); }
     180             : 
     181             :  private:
     182             :   // Unbound labels that identify jumps for case statements in the code.
     183             :   ZoneVector<BytecodeLabel> case_sites_;
     184             : };
     185             : 
     186             : 
     187             : // A class to help with co-ordinating control flow in try-catch statements.
     188           1 : class V8_EXPORT_PRIVATE TryCatchBuilder final : public ControlFlowBuilder {
     189             :  public:
     190             :   TryCatchBuilder(BytecodeArrayBuilder* builder,
     191             :                   HandlerTable::CatchPrediction catch_prediction)
     192             :       : ControlFlowBuilder(builder),
     193             :         handler_id_(builder->NewHandlerEntry()),
     194      204246 :         catch_prediction_(catch_prediction) {}
     195             : 
     196             :   void BeginTry(Register context);
     197             :   void EndTry();
     198             :   void EndCatch();
     199             : 
     200             :  private:
     201             :   int handler_id_;
     202             :   HandlerTable::CatchPrediction catch_prediction_;
     203             :   BytecodeLabel handler_;
     204             :   BytecodeLabel exit_;
     205             : };
     206             : 
     207             : 
     208             : // A class to help with co-ordinating control flow in try-finally statements.
     209       36312 : class V8_EXPORT_PRIVATE TryFinallyBuilder final : public ControlFlowBuilder {
     210             :  public:
     211       72624 :   TryFinallyBuilder(BytecodeArrayBuilder* builder,
     212             :                     HandlerTable::CatchPrediction catch_prediction)
     213             :       : ControlFlowBuilder(builder),
     214             :         handler_id_(builder->NewHandlerEntry()),
     215             :         catch_prediction_(catch_prediction),
     216      108936 :         finalization_sites_(builder->zone()) {}
     217             : 
     218             :   void BeginTry(Register context);
     219             :   void LeaveTry();
     220             :   void EndTry();
     221             :   void BeginHandler();
     222             :   void BeginFinally();
     223             :   void EndFinally();
     224             : 
     225             :  private:
     226             :   int handler_id_;
     227             :   HandlerTable::CatchPrediction catch_prediction_;
     228             :   BytecodeLabel handler_;
     229             : 
     230             :   // Unbound labels that identify jumps to the finally block in the code.
     231             :   BytecodeLabels finalization_sites_;
     232             : };
     233             : 
     234             : class V8_EXPORT_PRIVATE ConditionalControlFlowBuilder final
     235             :     : public ControlFlowBuilder {
     236             :  public:
     237     4062376 :   ConditionalControlFlowBuilder(BytecodeArrayBuilder* builder,
     238             :                                 BlockCoverageBuilder* block_coverage_builder,
     239             :                                 AstNode* node)
     240             :       : ControlFlowBuilder(builder),
     241             :         end_labels_(builder->zone()),
     242             :         then_labels_(builder->zone()),
     243             :         else_labels_(builder->zone()),
     244             :         node_(node),
     245     2031188 :         block_coverage_builder_(block_coverage_builder) {
     246             :     DCHECK(node->IsIfStatement() || node->IsConditional());
     247     1015594 :     if (block_coverage_builder != nullptr) {
     248             :       block_coverage_then_slot_ =
     249             :           block_coverage_builder->AllocateBlockCoverageSlot(
     250         773 :               node, SourceRangeKind::kThen);
     251             :       block_coverage_else_slot_ =
     252             :           block_coverage_builder->AllocateBlockCoverageSlot(
     253         773 :               node, SourceRangeKind::kElse);
     254             :     }
     255     1015594 :   }
     256             :   ~ConditionalControlFlowBuilder();
     257             : 
     258             :   BytecodeLabels* then_labels() { return &then_labels_; }
     259             :   BytecodeLabels* else_labels() { return &else_labels_; }
     260             : 
     261             :   void Then();
     262             :   void Else();
     263             : 
     264             :   void JumpToEnd();
     265             : 
     266             :  private:
     267             :   BytecodeLabels end_labels_;
     268             :   BytecodeLabels then_labels_;
     269             :   BytecodeLabels else_labels_;
     270             : 
     271             :   AstNode* node_;
     272             :   int block_coverage_then_slot_;
     273             :   int block_coverage_else_slot_;
     274             :   BlockCoverageBuilder* block_coverage_builder_;
     275             : };
     276             : 
     277             : }  // namespace interpreter
     278             : }  // namespace internal
     279             : }  // namespace v8
     280             : 
     281             : #endif  // V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_

Generated by: LCOV version 1.10