| Index: src/full-codegen/full-codegen.h
|
| diff --git a/src/full-codegen/full-codegen.h b/src/full-codegen/full-codegen.h
|
| index e99462c19bf507175e025fa0926e2e6a2fad0837..f44e7784e65e9bda14084077824aa16336a4b1ad 100644
|
| --- a/src/full-codegen/full-codegen.h
|
| +++ b/src/full-codegen/full-codegen.h
|
| @@ -99,6 +99,7 @@ class FullCodeGenerator: public AstVisitor {
|
| private:
|
| class Breakable;
|
| class Iteration;
|
| + class TryFinally;
|
|
|
| class TestContext;
|
|
|
| @@ -115,11 +116,13 @@ class FullCodeGenerator: public AstVisitor {
|
| codegen_->nesting_stack_ = previous_;
|
| }
|
|
|
| - virtual Breakable* AsBreakable() { return NULL; }
|
| - virtual Iteration* AsIteration() { return NULL; }
|
| + virtual Breakable* AsBreakable() { return nullptr; }
|
| + virtual Iteration* AsIteration() { return nullptr; }
|
| + virtual TryFinally* AsTryFinally() { return nullptr; }
|
|
|
| virtual bool IsContinueTarget(Statement* target) { return false; }
|
| virtual bool IsBreakTarget(Statement* target) { return false; }
|
| + virtual bool IsTryFinally() { return false; }
|
|
|
| // Notify the statement that we are exiting it via break, continue, or
|
| // return and give it a chance to generate cleanup code. Return the
|
| @@ -217,14 +220,50 @@ class FullCodeGenerator: public AstVisitor {
|
| }
|
| };
|
|
|
| + class DeferredCommands {
|
| + public:
|
| + enum Command { kReturn, kThrow, kBreak, kContinue };
|
| + typedef int TokenId;
|
| + struct DeferredCommand {
|
| + Command command;
|
| + TokenId token;
|
| + Statement* target;
|
| + };
|
| +
|
| + DeferredCommands(FullCodeGenerator* codegen, Label* finally_entry)
|
| + : codegen_(codegen),
|
| + commands_(codegen->zone()),
|
| + return_token_(TokenDispenserForFinally::kInvalidToken),
|
| + throw_token_(TokenDispenserForFinally::kInvalidToken),
|
| + finally_entry_(finally_entry) {}
|
| +
|
| + void EmitCommands();
|
| +
|
| + void RecordBreak(Statement* target);
|
| + void RecordContinue(Statement* target);
|
| + void RecordReturn();
|
| + void RecordThrow();
|
| + void EmitFallThrough();
|
| +
|
| + private:
|
| + MacroAssembler* masm() { return codegen_->masm(); }
|
| + void EmitJumpToFinally(TokenId token);
|
| +
|
| + FullCodeGenerator* codegen_;
|
| + ZoneVector<DeferredCommand> commands_;
|
| + TokenDispenserForFinally dispenser_;
|
| + TokenId return_token_;
|
| + TokenId throw_token_;
|
| + Label* finally_entry_;
|
| + };
|
| +
|
| // The try block of a try/finally statement.
|
| class TryFinally : public NestedStatement {
|
| public:
|
| static const int kElementCount = TryBlockConstant::kElementCount;
|
|
|
| - TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
|
| - : NestedStatement(codegen), finally_entry_(finally_entry) {
|
| - }
|
| + TryFinally(FullCodeGenerator* codegen, DeferredCommands* commands)
|
| + : NestedStatement(codegen), deferred_commands_(commands) {}
|
|
|
| NestedStatement* Exit(int* stack_depth, int* context_length) override;
|
| NestedStatement* AccumulateDepth(int* stack_depth) override {
|
| @@ -232,8 +271,13 @@ class FullCodeGenerator: public AstVisitor {
|
| return previous_;
|
| }
|
|
|
| + bool IsTryFinally() override { return true; }
|
| + TryFinally* AsTryFinally() override { return this; }
|
| +
|
| + DeferredCommands* deferred_commands() { return deferred_commands_; }
|
| +
|
| private:
|
| - Label* finally_entry_;
|
| + DeferredCommands* deferred_commands_;
|
| };
|
|
|
| // The finally block of a try/finally statement.
|
| @@ -455,8 +499,9 @@ class FullCodeGenerator: public AstVisitor {
|
|
|
| // Emit code to pop values from the stack associated with nested statements
|
| // like try/catch, try/finally, etc, running the finallies and unwinding the
|
| - // handlers as needed.
|
| - void EmitUnwindBeforeReturn();
|
| + // handlers as needed. Also emits the return sequence if necessary (i.e.,
|
| + // if the return is not delayed by a finally block).
|
| + void EmitUnwindAndReturn();
|
|
|
| // Platform-specific return sequence
|
| void EmitReturnSequence();
|
| @@ -669,6 +714,9 @@ class FullCodeGenerator: public AstVisitor {
|
| void ExitFinallyBlock();
|
| void ClearPendingMessage();
|
|
|
| + void EmitContinue(Statement* target);
|
| + void EmitBreak(Statement* target);
|
| +
|
| // Loop nesting counter.
|
| int loop_depth() { return loop_depth_; }
|
| void increment_loop_depth() { loop_depth_++; }
|
|
|