Home | History | Annotate | Download | only in compiler
      1 // Copyright 2013 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_COMPILER_CONTROL_BUILDERS_H_
      6 #define V8_COMPILER_CONTROL_BUILDERS_H_
      7 
      8 #include "src/compiler/ast-graph-builder.h"
      9 #include "src/compiler/node.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 namespace compiler {
     14 
     15 // Base class for all control builders. Also provides a common interface for
     16 // control builders to handle 'break' statements when they are used to model
     17 // breakable statements.
     18 class ControlBuilder {
     19  public:
     20   explicit ControlBuilder(AstGraphBuilder* builder) : builder_(builder) {}
     21   virtual ~ControlBuilder() {}
     22 
     23   // Interface for break.
     24   virtual void Break() { UNREACHABLE(); }
     25 
     26  protected:
     27   typedef AstGraphBuilder Builder;
     28   typedef AstGraphBuilder::Environment Environment;
     29 
     30   Zone* zone() const { return builder_->local_zone(); }
     31   Environment* environment() { return builder_->environment(); }
     32   void set_environment(Environment* env) { builder_->set_environment(env); }
     33   Node* the_hole() const { return builder_->jsgraph()->TheHoleConstant(); }
     34 
     35   Builder* builder_;
     36 };
     37 
     38 
     39 // Tracks control flow for a conditional statement.
     40 class IfBuilder final : public ControlBuilder {
     41  public:
     42   explicit IfBuilder(AstGraphBuilder* builder)
     43       : ControlBuilder(builder),
     44         then_environment_(nullptr),
     45         else_environment_(nullptr) {}
     46 
     47   // Primitive control commands.
     48   void If(Node* condition, BranchHint hint = BranchHint::kNone);
     49   void Then();
     50   void Else();
     51   void End();
     52 
     53  private:
     54   Environment* then_environment_;  // Environment after the 'then' body.
     55   Environment* else_environment_;  // Environment for the 'else' body.
     56 };
     57 
     58 
     59 // Tracks control flow for an iteration statement.
     60 class LoopBuilder final : public ControlBuilder {
     61  public:
     62   explicit LoopBuilder(AstGraphBuilder* builder)
     63       : ControlBuilder(builder),
     64         loop_environment_(nullptr),
     65         continue_environment_(nullptr),
     66         break_environment_(nullptr),
     67         assigned_(nullptr) {}
     68 
     69   // Primitive control commands.
     70   void BeginLoop(BitVector* assigned, bool is_osr = false);
     71   void Continue();
     72   void EndBody();
     73   void EndLoop();
     74 
     75   // Primitive support for break.
     76   void Break() final;
     77 
     78   // Loop exit support. Used to introduce explicit loop exit control
     79   // node and variable markers.
     80   void ExitLoop(Node** extra_value_to_rename = nullptr);
     81 
     82   // Compound control commands for conditional break.
     83   void BreakUnless(Node* condition);
     84   void BreakWhen(Node* condition);
     85 
     86  private:
     87   Environment* loop_environment_;      // Environment of the loop header.
     88   Environment* continue_environment_;  // Environment after the loop body.
     89   Environment* break_environment_;     // Environment after the loop exits.
     90   BitVector* assigned_;                // Assigned values in the environment.
     91 };
     92 
     93 
     94 // Tracks control flow for a switch statement.
     95 class SwitchBuilder final : public ControlBuilder {
     96  public:
     97   explicit SwitchBuilder(AstGraphBuilder* builder, int case_count)
     98       : ControlBuilder(builder),
     99         body_environment_(nullptr),
    100         label_environment_(nullptr),
    101         break_environment_(nullptr),
    102         body_environments_(case_count, zone()) {}
    103 
    104   // Primitive control commands.
    105   void BeginSwitch();
    106   void BeginLabel(int index, Node* condition);
    107   void EndLabel();
    108   void DefaultAt(int index);
    109   void BeginCase(int index);
    110   void EndCase();
    111   void EndSwitch();
    112 
    113   // Primitive support for break.
    114   void Break() final;
    115 
    116   // The number of cases within a switch is statically known.
    117   size_t case_count() const { return body_environments_.size(); }
    118 
    119  private:
    120   Environment* body_environment_;   // Environment after last case body.
    121   Environment* label_environment_;  // Environment for next label condition.
    122   Environment* break_environment_;  // Environment after the switch exits.
    123   ZoneVector<Environment*> body_environments_;
    124 };
    125 
    126 
    127 // Tracks control flow for a block statement.
    128 class BlockBuilder final : public ControlBuilder {
    129  public:
    130   explicit BlockBuilder(AstGraphBuilder* builder)
    131       : ControlBuilder(builder), break_environment_(nullptr) {}
    132 
    133   // Primitive control commands.
    134   void BeginBlock();
    135   void EndBlock();
    136 
    137   // Primitive support for break.
    138   void Break() final;
    139 
    140   // Compound control commands for conditional break.
    141   void BreakWhen(Node* condition, BranchHint = BranchHint::kNone);
    142   void BreakUnless(Node* condition, BranchHint hint = BranchHint::kNone);
    143 
    144  private:
    145   Environment* break_environment_;  // Environment after the block exits.
    146 };
    147 
    148 
    149 // Tracks control flow for a try-catch statement.
    150 class TryCatchBuilder final : public ControlBuilder {
    151  public:
    152   explicit TryCatchBuilder(AstGraphBuilder* builder)
    153       : ControlBuilder(builder),
    154         catch_environment_(nullptr),
    155         exit_environment_(nullptr),
    156         exception_node_(nullptr) {}
    157 
    158   // Primitive control commands.
    159   void BeginTry();
    160   void Throw(Node* exception);
    161   void EndTry();
    162   void EndCatch();
    163 
    164   // Returns the exception value inside the 'catch' body.
    165   Node* GetExceptionNode() const { return exception_node_; }
    166 
    167  private:
    168   Environment* catch_environment_;  // Environment for the 'catch' body.
    169   Environment* exit_environment_;   // Environment after the statement.
    170   Node* exception_node_;            // Node for exception in 'catch' body.
    171 };
    172 
    173 
    174 // Tracks control flow for a try-finally statement.
    175 class TryFinallyBuilder final : public ControlBuilder {
    176  public:
    177   explicit TryFinallyBuilder(AstGraphBuilder* builder)
    178       : ControlBuilder(builder),
    179         finally_environment_(nullptr),
    180         token_node_(nullptr),
    181         value_node_(nullptr) {}
    182 
    183   // Primitive control commands.
    184   void BeginTry();
    185   void LeaveTry(Node* token, Node* value);
    186   void EndTry(Node* token, Node* value);
    187   void EndFinally();
    188 
    189   // Returns the dispatch token value inside the 'finally' body.
    190   Node* GetDispatchTokenNode() const { return token_node_; }
    191 
    192   // Returns the saved result value inside the 'finally' body.
    193   Node* GetResultValueNode() const { return value_node_; }
    194 
    195  private:
    196   Environment* finally_environment_;  // Environment for the 'finally' body.
    197   Node* token_node_;                  // Node for token in 'finally' body.
    198   Node* value_node_;                  // Node for value in 'finally' body.
    199 };
    200 
    201 }  // namespace compiler
    202 }  // namespace internal
    203 }  // namespace v8
    204 
    205 #endif  // V8_COMPILER_CONTROL_BUILDERS_H_
    206