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