| // Copyright 2013 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef V8_COMPILER_CONTROL_BUILDERS_H_ |
| #define V8_COMPILER_CONTROL_BUILDERS_H_ |
| |
| #include "src/compiler/ast-graph-builder.h" |
| #include "src/compiler/node.h" |
| |
| namespace v8 { |
| namespace internal { |
| namespace compiler { |
| |
| // Base class for all control builders. Also provides a common interface for |
| // control builders to handle 'break' statements when they are used to model |
| // breakable statements. |
| class ControlBuilder { |
| public: |
| explicit ControlBuilder(AstGraphBuilder* builder) : builder_(builder) {} |
| virtual ~ControlBuilder() {} |
| |
| // Interface for break. |
| virtual void Break() { UNREACHABLE(); } |
| |
| protected: |
| typedef AstGraphBuilder Builder; |
| typedef AstGraphBuilder::Environment Environment; |
| |
| Zone* zone() const { return builder_->local_zone(); } |
| Environment* environment() { return builder_->environment(); } |
| void set_environment(Environment* env) { builder_->set_environment(env); } |
| Node* the_hole() const { return builder_->jsgraph()->TheHoleConstant(); } |
| |
| Builder* builder_; |
| }; |
| |
| |
| // Tracks control flow for a conditional statement. |
| class IfBuilder final : public ControlBuilder { |
| public: |
| explicit IfBuilder(AstGraphBuilder* builder) |
| : ControlBuilder(builder), |
| then_environment_(nullptr), |
| else_environment_(nullptr) {} |
| |
| // Primitive control commands. |
| void If(Node* condition, BranchHint hint = BranchHint::kNone); |
| void Then(); |
| void Else(); |
| void End(); |
| |
| private: |
| Environment* then_environment_; // Environment after the 'then' body. |
| Environment* else_environment_; // Environment for the 'else' body. |
| }; |
| |
| |
| // Tracks control flow for an iteration statement. |
| class LoopBuilder final : public ControlBuilder { |
| public: |
| explicit LoopBuilder(AstGraphBuilder* builder) |
| : ControlBuilder(builder), |
| loop_environment_(nullptr), |
| continue_environment_(nullptr), |
| break_environment_(nullptr), |
| assigned_(nullptr) {} |
| |
| // Primitive control commands. |
| void BeginLoop(BitVector* assigned, bool is_osr = false); |
| void Continue(); |
| void EndBody(); |
| void EndLoop(); |
| |
| // Primitive support for break. |
| void Break() final; |
| |
| // Loop exit support. Used to introduce explicit loop exit control |
| // node and variable markers. |
| void ExitLoop(Node** extra_value_to_rename = nullptr); |
| |
| // Compound control commands for conditional break. |
| void BreakUnless(Node* condition); |
| void BreakWhen(Node* condition); |
| |
| private: |
| Environment* loop_environment_; // Environment of the loop header. |
| Environment* continue_environment_; // Environment after the loop body. |
| Environment* break_environment_; // Environment after the loop exits. |
| BitVector* assigned_; // Assigned values in the environment. |
| }; |
| |
| |
| // Tracks control flow for a switch statement. |
| class SwitchBuilder final : public ControlBuilder { |
| public: |
| explicit SwitchBuilder(AstGraphBuilder* builder, int case_count) |
| : ControlBuilder(builder), |
| body_environment_(nullptr), |
| label_environment_(nullptr), |
| break_environment_(nullptr), |
| body_environments_(case_count, zone()) {} |
| |
| // Primitive control commands. |
| void BeginSwitch(); |
| void BeginLabel(int index, Node* condition); |
| void EndLabel(); |
| void DefaultAt(int index); |
| void BeginCase(int index); |
| void EndCase(); |
| void EndSwitch(); |
| |
| // Primitive support for break. |
| void Break() final; |
| |
| // The number of cases within a switch is statically known. |
| size_t case_count() const { return body_environments_.size(); } |
| |
| private: |
| Environment* body_environment_; // Environment after last case body. |
| Environment* label_environment_; // Environment for next label condition. |
| Environment* break_environment_; // Environment after the switch exits. |
| ZoneVector<Environment*> body_environments_; |
| }; |
| |
| |
| // Tracks control flow for a block statement. |
| class BlockBuilder final : public ControlBuilder { |
| public: |
| explicit BlockBuilder(AstGraphBuilder* builder) |
| : ControlBuilder(builder), break_environment_(nullptr) {} |
| |
| // Primitive control commands. |
| void BeginBlock(); |
| void EndBlock(); |
| |
| // Primitive support for break. |
| void Break() final; |
| |
| // Compound control commands for conditional break. |
| void BreakWhen(Node* condition, BranchHint = BranchHint::kNone); |
| void BreakUnless(Node* condition, BranchHint hint = BranchHint::kNone); |
| |
| private: |
| Environment* break_environment_; // Environment after the block exits. |
| }; |
| |
| |
| // Tracks control flow for a try-catch statement. |
| class TryCatchBuilder final : public ControlBuilder { |
| public: |
| explicit TryCatchBuilder(AstGraphBuilder* builder) |
| : ControlBuilder(builder), |
| catch_environment_(nullptr), |
| exit_environment_(nullptr), |
| exception_node_(nullptr) {} |
| |
| // Primitive control commands. |
| void BeginTry(); |
| void Throw(Node* exception); |
| void EndTry(); |
| void EndCatch(); |
| |
| // Returns the exception value inside the 'catch' body. |
| Node* GetExceptionNode() const { return exception_node_; } |
| |
| private: |
| Environment* catch_environment_; // Environment for the 'catch' body. |
| Environment* exit_environment_; // Environment after the statement. |
| Node* exception_node_; // Node for exception in 'catch' body. |
| }; |
| |
| |
| // Tracks control flow for a try-finally statement. |
| class TryFinallyBuilder final : public ControlBuilder { |
| public: |
| explicit TryFinallyBuilder(AstGraphBuilder* builder) |
| : ControlBuilder(builder), |
| finally_environment_(nullptr), |
| token_node_(nullptr), |
| value_node_(nullptr) {} |
| |
| // Primitive control commands. |
| void BeginTry(); |
| void LeaveTry(Node* token, Node* value); |
| void EndTry(Node* token, Node* value); |
| void EndFinally(); |
| |
| // Returns the dispatch token value inside the 'finally' body. |
| Node* GetDispatchTokenNode() const { return token_node_; } |
| |
| // Returns the saved result value inside the 'finally' body. |
| Node* GetResultValueNode() const { return value_node_; } |
| |
| private: |
| Environment* finally_environment_; // Environment for the 'finally' body. |
| Node* token_node_; // Node for token in 'finally' body. |
| Node* value_node_; // Node for value in 'finally' body. |
| }; |
| |
| } // namespace compiler |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_COMPILER_CONTROL_BUILDERS_H_ |