Chromium Code Reviews| Index: src/compiler/ast-graph-builder.h |
| diff --git a/src/compiler/ast-graph-builder.h b/src/compiler/ast-graph-builder.h |
| index 175228dd88c43225151b0d310e51bf291ab2bd4d..c21d4dee52b30dc85b8fc5ebd03fe7dfdbedbcf3 100644 |
| --- a/src/compiler/ast-graph-builder.h |
| +++ b/src/compiler/ast-graph-builder.h |
| @@ -19,6 +19,8 @@ class ControlBuilder; |
| class Graph; |
| class LoopAssignmentAnalysis; |
| class LoopBuilder; |
| +class TryCatchBuilder; |
| +class TryFinallyBuilder; |
| // The AstGraphBuilder produces a high-level IR graph, based on an |
| // underlying AST. The produced graph can either be compiled into a |
| @@ -37,8 +39,12 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor { |
| class AstEffectContext; |
| class AstValueContext; |
| class AstTestContext; |
| - class BreakableScope; |
| class ContextScope; |
|
titzer
2015/02/02 09:47:29
Do this class and its subclasses really need to be
Michael Starzinger
2015/02/02 14:47:41
Acknowledged. As discussed offline, it gives acces
|
| + class ControlScope; |
| + class ControlScopeForBreakable; |
| + class ControlScopeForIteration; |
| + class ControlScopeForCatch; |
| + class ControlScopeForFinally; |
| class Environment; |
| Environment* environment() { |
| @@ -47,11 +53,11 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor { |
| } |
| AstContext* ast_context() const { return ast_context_; } |
| - BreakableScope* breakable() const { return breakable_; } |
| + ControlScope* execution_control() const { return execution_control_; } |
| ContextScope* execution_context() const { return execution_context_; } |
| void set_ast_context(AstContext* ctx) { ast_context_ = ctx; } |
| - void set_breakable(BreakableScope* brk) { breakable_ = brk; } |
| + void set_execution_control(ControlScope* ctrl) { execution_control_ = ctrl; } |
| void set_execution_context(ContextScope* ctx) { execution_context_ = ctx; } |
| // Support for control flow builders. The concrete type of the environment |
| @@ -110,6 +116,10 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor { |
| Node* BuildHoleCheckThrow(Node* value, Variable* var, Node* not_hole, |
| BailoutId bailout_id); |
| + // Builders for non-local control flow. |
| + Node* BuildReturn(Node* return_value); |
| + Node* BuildThrow(Node* exception_value); |
| + |
| // Builders for binary operations. |
| Node* BuildBinaryOp(Node* left, Node* right, Token::Value op); |
| @@ -135,8 +145,8 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor { |
| // List of global declarations for functions and variables. |
| ZoneVector<Handle<Object>> globals_; |
| - // Stack of breakable statements entered by the visitor. |
| - BreakableScope* breakable_; |
| + // Stack of control scopes currently entered by the visitor. |
| + ControlScope* execution_control_; |
| // Stack of context objects pushed onto the chain by the visitor. |
| ContextScope* execution_context_; |
| @@ -389,39 +399,119 @@ class AstGraphBuilder::AstTestContext FINAL : public AstContext { |
| }; |
| -// Scoped class tracking breakable statements entered by the visitor. Allows to |
| -// properly 'break' and 'continue' iteration statements as well as to 'break' |
| -// from blocks within switch statements. |
| -class AstGraphBuilder::BreakableScope BASE_EMBEDDED { |
| +// Scoped class tracking control statements entered by the visitor. There are |
| +// different types of statements participating in this stack to properly track |
| +// local as well as non-local control flow: |
| +// - IterationStatement : Allows proper 'break' and 'continue' behavior. |
| +// - BreakableStatement : Allows 'break' from block and switch statements. |
| +// - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges. |
| +// - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'. |
| +class AstGraphBuilder::ControlScope BASE_EMBEDDED { |
| public: |
| - BreakableScope(AstGraphBuilder* owner, BreakableStatement* target, |
| - ControlBuilder* control, int drop_extra) |
| + ControlScope(AstGraphBuilder* owner, int drop_extra) |
|
titzer
2015/02/02 09:47:29
{owner} is a bad name. Would prefer the more verbo
Michael Starzinger
2015/02/02 14:47:41
Done. As discussed offline, used {builder} instead
|
| : owner_(owner), |
| - target_(target), |
| - next_(owner->breakable()), |
| - control_(control), |
| + next_(owner->execution_control()), |
| drop_extra_(drop_extra) { |
| - owner_->set_breakable(this); // Push. |
| + owner_->set_execution_control(this); // Push. |
| } |
| - ~BreakableScope() { |
| - owner_->set_breakable(next_); // Pop. |
| + virtual ~ControlScope() { |
| + owner_->set_execution_control(next_); // Pop. |
| } |
| // Either 'break' or 'continue' the target statement. |
| void BreakTarget(BreakableStatement* target); |
| void ContinueTarget(BreakableStatement* target); |
| + // Either 'return' or 'throw' the given value. |
| + void ReturnValue(Node* return_value); |
| + void ThrowValue(Node* exception_value); |
| + |
| + class DeferredCommands; |
| + |
| + protected: |
| + enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW }; |
| + |
| + // Performs one of the above commands on this stack of control scopes. This |
| + // walks through the stack giving each scope a chance to execute or defer the |
| + // given command by overriding the {Execute} method appropriately. Note that |
| + // this also drops extra operands from the environment for each skipped scope. |
| + void PerformCommand(Command cmd, Statement* stmt, Node* value); |
|
titzer
2015/02/02 09:47:29
{stmt} is called {target} in all the subclasses.
Michael Starzinger
2015/02/02 14:47:41
Done. Here and in the occurrences below.
|
| + |
| + // Interface to execute a given command in this scope. Returning {true} here |
| + // indicates successful execution whereas {false} requests to skip scope. |
| + virtual bool Execute(Command cmd, Statement* stmt, Node* value); |
| + |
| + Environment* environment() { return owner_->environment(); } |
| + AstGraphBuilder* owner() const { return owner_; } |
| + int drop_extra() const { return drop_extra_; } |
| + |
| private: |
| AstGraphBuilder* owner_; |
| + ControlScope* next_; |
| + int drop_extra_; |
| +}; |
| + |
| + |
| +// Control scope implementation for a BreakableStatement. |
| +class AstGraphBuilder::ControlScopeForBreakable : public ControlScope { |
| + public: |
| + ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target, |
| + ControlBuilder* control) |
| + : ControlScope(owner, 0), target_(target), control_(control) {} |
| + |
| + protected: |
| + virtual bool Execute(Command cmd, Statement* stmt, Node* value) OVERRIDE; |
| + |
| + private: |
| BreakableStatement* target_; |
| - BreakableScope* next_; |
| ControlBuilder* control_; |
| - int drop_extra_; |
| +}; |
| - // Find the correct scope for the target statement. Note that this also drops |
| - // extra operands from the environment for each scope skipped along the way. |
| - BreakableScope* FindBreakable(BreakableStatement* target); |
| + |
| +// Control scope implementation for an IterationStatement. |
| +class AstGraphBuilder::ControlScopeForIteration : public ControlScope { |
| + public: |
| + ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target, |
| + LoopBuilder* control, int drop_extra) |
| + : ControlScope(owner, drop_extra), target_(target), control_(control) {} |
| + |
| + protected: |
| + virtual bool Execute(Command cmd, Statement* stmt, Node* value) OVERRIDE; |
| + |
| + private: |
| + BreakableStatement* target_; |
| + LoopBuilder* control_; |
| +}; |
| + |
| + |
| +// Control scope implementation for a TryCatchStatement. |
| +class AstGraphBuilder::ControlScopeForCatch : public ControlScope { |
| + public: |
| + ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control) |
| + : ControlScope(owner, 0), control_(control) {} |
| + |
| + protected: |
| + virtual bool Execute(Command cmd, Statement* stmt, Node* value) OVERRIDE; |
| + |
| + private: |
| + TryCatchBuilder* control_; |
| +}; |
| + |
| + |
| +// Control scope implementation for a TryFinallyStatement. |
| +class AstGraphBuilder::ControlScopeForFinally : public ControlScope { |
| + public: |
| + ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands, |
| + TryFinallyBuilder* control) |
| + : ControlScope(owner, 0), commands_(commands), control_(control) {} |
| + |
| + protected: |
| + virtual bool Execute(Command cmd, Statement* stmt, Node* value) OVERRIDE; |
| + |
| + private: |
| + DeferredCommands* commands_; |
| + TryFinallyBuilder* control_; |
| }; |