LCOV - code coverage report
Current view: top level - src/interpreter - control-flow-builders.h (source / functions) Hit Total Coverage
Test: app.info Lines: 34 34 100.0 %
Date: 2019-04-19 Functions: 4 8 50.0 %

          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 {
      20             :  public:
      21             :   explicit ControlFlowBuilder(BytecodeArrayBuilder* builder)
      22     6311256 :       : builder_(builder) {}
      23     6311350 :   virtual ~ControlFlowBuilder() = default;
      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             :   BreakableControlFlowBuilder(BytecodeArrayBuilder* builder,
      38             :                               BlockCoverageBuilder* block_coverage_builder,
      39             :                               AstNode* node)
      40             :       : ControlFlowBuilder(builder),
      41             :         break_labels_(builder->zone()),
      42             :         node_(node),
      43    11089136 :         block_coverage_builder_(block_coverage_builder) {}
      44             :   ~BreakableControlFlowBuilder() override;
      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       49268 :   void Break() { EmitJump(&break_labels_); }
      50             :   void BreakIfTrue(BytecodeArrayBuilder::ToBooleanMode mode) {
      51       37805 :     EmitJumpIfTrue(mode, &break_labels_);
      52             :   }
      53             :   void BreakIfFalse(BytecodeArrayBuilder::ToBooleanMode mode) {
      54        4752 :     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             :  protected:
      62             :   void EmitJump(BytecodeLabels* labels);
      63             :   void EmitJumpIfTrue(BytecodeArrayBuilder::ToBooleanMode mode,
      64             :                       BytecodeLabels* labels);
      65             :   void EmitJumpIfFalse(BytecodeArrayBuilder::ToBooleanMode mode,
      66             :                        BytecodeLabels* labels);
      67             :   void EmitJumpIfUndefined(BytecodeLabels* labels);
      68             :   void EmitJumpIfNull(BytecodeLabels* labels);
      69             : 
      70             :   // Called from the destructor to update sites that emit jumps for break.
      71             :   void BindBreakTarget();
      72             : 
      73             :   // Unbound labels that identify jumps for break statements in the code.
      74             :   BytecodeLabels break_labels_;
      75             : 
      76             :   // A continuation counter (for block coverage) is needed e.g. when
      77             :   // encountering a break statement.
      78             :   AstNode* node_;
      79             :   BlockCoverageBuilder* block_coverage_builder_;
      80             : };
      81             : 
      82             : 
      83             : // Class to track control flow for block statements (which can break in JS).
      84     5255585 : class V8_EXPORT_PRIVATE BlockBuilder final
      85             :     : public BreakableControlFlowBuilder {
      86             :  public:
      87             :   BlockBuilder(BytecodeArrayBuilder* builder,
      88             :                BlockCoverageBuilder* block_coverage_builder,
      89             :                BreakableStatement* statement)
      90             :       : BreakableControlFlowBuilder(builder, block_coverage_builder,
      91     5255524 :                                     statement) {}
      92             : };
      93             : 
      94             : 
      95             : // A class to help with co-ordinating break and continue statements with
      96             : // their loop.
      97             : class V8_EXPORT_PRIVATE LoopBuilder final : public BreakableControlFlowBuilder {
      98             :  public:
      99      276121 :   LoopBuilder(BytecodeArrayBuilder* builder,
     100             :               BlockCoverageBuilder* block_coverage_builder, AstNode* node)
     101             :       : BreakableControlFlowBuilder(builder, block_coverage_builder, node),
     102      278389 :         continue_labels_(builder->zone()) {
     103      276121 :     if (block_coverage_builder_ != nullptr) {
     104             :       block_coverage_body_slot_ =
     105         244 :           block_coverage_builder_->AllocateBlockCoverageSlot(
     106         244 :               node, SourceRangeKind::kBody);
     107             :     }
     108      276121 :   }
     109             :   ~LoopBuilder() override;
     110             : 
     111             :   void LoopHeader();
     112             :   void LoopBody();
     113             :   void JumpToHeader(int loop_depth);
     114             :   void BindContinueTarget();
     115             : 
     116             :   // This method is called when visiting continue statements in the AST.
     117             :   // Inserts a jump to an unbound label that is patched when BindContinueTarget
     118             :   // is called.
     119        3642 :   void Continue() { EmitJump(&continue_labels_); }
     120        4752 :   void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_labels_); }
     121             :   void ContinueIfNull() { EmitJumpIfNull(&continue_labels_); }
     122             : 
     123             :  private:
     124             :   BytecodeLoopHeader loop_header_;
     125             : 
     126             :   // Unbound labels that identify jumps for continue statements in the code and
     127             :   // jumps from checking the loop condition to the header for do-while loops.
     128             :   BytecodeLabels continue_labels_;
     129             : 
     130             :   int block_coverage_body_slot_;
     131             : };
     132             : 
     133             : 
     134             : // A class to help with co-ordinating break statements with their switch.
     135             : class V8_EXPORT_PRIVATE SwitchBuilder final
     136             :     : public BreakableControlFlowBuilder {
     137             :  public:
     138             :   SwitchBuilder(BytecodeArrayBuilder* builder,
     139             :                 BlockCoverageBuilder* block_coverage_builder,
     140             :                 SwitchStatement* statement, int number_of_cases)
     141             :       : BreakableControlFlowBuilder(builder, block_coverage_builder, statement),
     142       10655 :         case_sites_(builder->zone()) {
     143       10655 :     case_sites_.resize(number_of_cases);
     144             :   }
     145             :   ~SwitchBuilder() override;  // NOLINT (modernize-use-equals-default)
     146             : 
     147             :   // This method should be called by the SwitchBuilder owner when the case
     148             :   // statement with |index| is emitted to update the case jump site.
     149             :   void SetCaseTarget(int index, CaseClause* clause);
     150             : 
     151             :   // This method is called when visiting case comparison operation for |index|.
     152             :   // Inserts a JumpIfTrue with ToBooleanMode |mode| to a unbound label that is
     153             :   // patched when the corresponding SetCaseTarget is called.
     154       73058 :   void Case(BytecodeArrayBuilder::ToBooleanMode mode, int index) {
     155      146116 :     builder()->JumpIfTrue(mode, &case_sites_.at(index));
     156       73058 :   }
     157             : 
     158             :   // This method is called when all cases comparisons have been emitted if there
     159             :   // is a default case statement. Inserts a Jump to a unbound label that is
     160             :   // patched when the corresponding SetCaseTarget is called.
     161       14958 :   void DefaultAt(int index) { builder()->Jump(&case_sites_.at(index)); }
     162             : 
     163             :  private:
     164             :   // Unbound labels that identify jumps for case statements in the code.
     165             :   ZoneVector<BytecodeLabel> case_sites_;
     166             : };
     167             : 
     168             : 
     169             : // A class to help with co-ordinating control flow in try-catch statements.
     170             : class V8_EXPORT_PRIVATE TryCatchBuilder final : public ControlFlowBuilder {
     171             :  public:
     172             :   TryCatchBuilder(BytecodeArrayBuilder* builder,
     173             :                   BlockCoverageBuilder* block_coverage_builder,
     174             :                   TryCatchStatement* statement,
     175             :                   HandlerTable::CatchPrediction catch_prediction)
     176             :       : ControlFlowBuilder(builder),
     177             :         handler_id_(builder->NewHandlerEntry()),
     178             :         catch_prediction_(catch_prediction),
     179             :         block_coverage_builder_(block_coverage_builder),
     180      339391 :         statement_(statement) {}
     181             : 
     182             :   ~TryCatchBuilder() override;
     183             : 
     184             :   void BeginTry(Register context);
     185             :   void EndTry();
     186             :   void EndCatch();
     187             : 
     188             :  private:
     189             :   int handler_id_;
     190             :   HandlerTable::CatchPrediction catch_prediction_;
     191             :   BytecodeLabel exit_;
     192             : 
     193             :   BlockCoverageBuilder* block_coverage_builder_;
     194             :   TryCatchStatement* statement_;
     195             : };
     196             : 
     197             : 
     198             : // A class to help with co-ordinating control flow in try-finally statements.
     199             : class V8_EXPORT_PRIVATE TryFinallyBuilder final : public ControlFlowBuilder {
     200             :  public:
     201             :   TryFinallyBuilder(BytecodeArrayBuilder* builder,
     202             :                     BlockCoverageBuilder* block_coverage_builder,
     203             :                     TryFinallyStatement* statement,
     204             :                     HandlerTable::CatchPrediction catch_prediction)
     205             :       : ControlFlowBuilder(builder),
     206             :         handler_id_(builder->NewHandlerEntry()),
     207             :         catch_prediction_(catch_prediction),
     208             :         finalization_sites_(builder->zone()),
     209             :         block_coverage_builder_(block_coverage_builder),
     210      124917 :         statement_(statement) {}
     211             : 
     212             :   ~TryFinallyBuilder() override;
     213             : 
     214             :   void BeginTry(Register context);
     215             :   void LeaveTry();
     216             :   void EndTry();
     217             :   void BeginHandler();
     218             :   void BeginFinally();
     219             :   void EndFinally();
     220             : 
     221             :  private:
     222             :   int handler_id_;
     223             :   HandlerTable::CatchPrediction catch_prediction_;
     224             :   BytecodeLabel handler_;
     225             : 
     226             :   // Unbound labels that identify jumps to the finally block in the code.
     227             :   BytecodeLabels finalization_sites_;
     228             : 
     229             :   BlockCoverageBuilder* block_coverage_builder_;
     230             :   TryFinallyStatement* statement_;
     231             : };
     232             : 
     233             : class V8_EXPORT_PRIVATE ConditionalControlFlowBuilder final
     234             :     : public ControlFlowBuilder {
     235             :  public:
     236      611922 :   ConditionalControlFlowBuilder(BytecodeArrayBuilder* builder,
     237             :                                 BlockCoverageBuilder* block_coverage_builder,
     238             :                                 AstNode* node)
     239             :       : ControlFlowBuilder(builder),
     240             :         end_labels_(builder->zone()),
     241             :         then_labels_(builder->zone()),
     242             :         else_labels_(builder->zone()),
     243             :         node_(node),
     244     1223844 :         block_coverage_builder_(block_coverage_builder) {
     245             :     DCHECK(node->IsIfStatement() || node->IsConditional());
     246      611922 :     if (block_coverage_builder != nullptr) {
     247             :       block_coverage_then_slot_ =
     248         524 :           block_coverage_builder->AllocateBlockCoverageSlot(
     249         524 :               node, SourceRangeKind::kThen);
     250             :       block_coverage_else_slot_ =
     251         524 :           block_coverage_builder->AllocateBlockCoverageSlot(
     252         524 :               node, SourceRangeKind::kElse);
     253             :     }
     254      611922 :   }
     255             :   ~ConditionalControlFlowBuilder() override;
     256             : 
     257      603501 :   BytecodeLabels* then_labels() { return &then_labels_; }
     258       79408 :   BytecodeLabels* else_labels() { return &else_labels_; }
     259             : 
     260             :   void Then();
     261             :   void Else();
     262             : 
     263             :   void JumpToEnd();
     264             : 
     265             :  private:
     266             :   BytecodeLabels end_labels_;
     267             :   BytecodeLabels then_labels_;
     268             :   BytecodeLabels else_labels_;
     269             : 
     270             :   AstNode* node_;
     271             :   int block_coverage_then_slot_;
     272             :   int block_coverage_else_slot_;
     273             :   BlockCoverageBuilder* block_coverage_builder_;
     274             : };
     275             : 
     276             : }  // namespace interpreter
     277             : }  // namespace internal
     278             : }  // namespace v8
     279             : 
     280             : #endif  // V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_

Generated by: LCOV version 1.10