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_; |
}; |