Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index cce337fb46d448b23c60f958b88d644f7cc851e0..70d7be449bf127d05087342982a08f423833f751 100644 |
| --- a/src/parser.cc |
| +++ b/src/parser.cc |
| @@ -1906,13 +1906,9 @@ Statement* Parser::ParseReturnStatement(bool* ok) { |
| } |
| -Block* Parser::WithHelper(Expression* obj, |
| - ZoneStringList* labels, |
| - bool is_catch_block, |
| - bool* ok) { |
| +Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) { |
| // Parse the statement and collect escaping labels. |
| - ZoneList<Label*>* target_list = new(zone()) ZoneList<Label*>(0); |
| - TargetCollector collector(target_list); |
| + TargetCollector collector; |
| Statement* stat; |
| { Target target(&this->target_stack_, &collector); |
| with_nesting_level_++; |
| @@ -1926,7 +1922,7 @@ Block* Parser::WithHelper(Expression* obj, |
| Block* result = new(zone()) Block(NULL, 2, false); |
| if (result != NULL) { |
| - result->AddStatement(new(zone()) WithEnterStatement(obj, is_catch_block)); |
| + result->AddStatement(new(zone()) WithEnterStatement(obj)); |
| // Create body block. |
| Block* body = new(zone()) Block(NULL, 1, false); |
| @@ -1961,7 +1957,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { |
| Expression* expr = ParseExpression(true, CHECK_OK); |
| Expect(Token::RPAREN, CHECK_OK); |
| - return WithHelper(expr, labels, false, CHECK_OK); |
| + return WithHelper(expr, labels, CHECK_OK); |
| } |
| @@ -2057,18 +2053,13 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
| Expect(Token::TRY, CHECK_OK); |
| - ZoneList<Label*>* target_list = new(zone()) ZoneList<Label*>(0); |
| - TargetCollector collector(target_list); |
| + TargetCollector try_collector; |
| Block* try_block; |
| - { Target target(&this->target_stack_, &collector); |
| + { Target target(&this->target_stack_, &try_collector); |
| try_block = ParseBlock(NULL, CHECK_OK); |
| } |
| - Block* catch_block = NULL; |
| - Variable* catch_var = NULL; |
| - Block* finally_block = NULL; |
| - |
| Token::Value tok = peek(); |
| if (tok != Token::CATCH && tok != Token::FINALLY) { |
| ReportMessage("no_catch_or_finally", Vector<const char*>::empty()); |
| @@ -2077,18 +2068,17 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
| } |
| // If we can break out from the catch block and there is a finally block, |
| - // then we will need to collect jump targets from the catch block. Since |
| - // we don't know yet if there will be a finally block, we always collect |
| - // the jump targets. |
| - ZoneList<Label*>* catch_target_list = new(zone()) ZoneList<Label*>(0); |
| - TargetCollector catch_collector(catch_target_list); |
| - bool has_catch = false; |
| + // then we will need to collect escaping targets from the catch |
| + // block. Since we don't know yet if there will be a finally block, we |
| + // always collect the targets. |
| + TargetCollector catch_collector; |
| + Block* catch_block = NULL; |
| + Handle<String> name; |
| if (tok == Token::CATCH) { |
| - has_catch = true; |
| Consume(Token::CATCH); |
| Expect(Token::LPAREN, CHECK_OK); |
| - Handle<String> name = ParseIdentifier(CHECK_OK); |
| + name = ParseIdentifier(CHECK_OK); |
| if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) { |
| ReportMessage("strict_catch_variable", Vector<const char*>::empty()); |
| @@ -2099,17 +2089,33 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
| Expect(Token::RPAREN, CHECK_OK); |
| if (peek() == Token::LBRACE) { |
| - // Allocate a temporary for holding the finally state while |
| - // executing the finally block. |
| - catch_var = |
| - top_scope_->NewTemporary(isolate()->factory()->catch_var_symbol()); |
| - Literal* name_literal = new(zone()) Literal(name); |
| - VariableProxy* catch_var_use = new(zone()) VariableProxy(catch_var); |
| - Expression* obj = |
| - new(zone()) CatchExtensionObject(name_literal, catch_var_use); |
| + // Rewrite the catch body B to a single statement block |
|
Mads Ager (chromium)
2011/06/08 13:27:46
Indentation.
|
| + // { try B finally { PopContext }}. |
| + Block* inner_body; |
| + // We need to collect escapes from the body for both the inner |
| + // try/finally used to pop the catch context and any possible outer |
| + // try/finally. |
| + TargetCollector inner_collector; |
| { Target target(&this->target_stack_, &catch_collector); |
| - catch_block = WithHelper(obj, NULL, true, CHECK_OK); |
| + { Target target(&this->target_stack_, &inner_collector); |
| + ++with_nesting_level_; |
| + top_scope_->RecordWithStatement(); |
| + inner_body = ParseBlock(NULL, CHECK_OK); |
| + --with_nesting_level_; |
| + } |
| } |
| + |
| + // Create exit block. |
| + Block* inner_finally = new(zone()) Block(NULL, 1, false); |
| + inner_finally->AddStatement(new(zone()) WithExitStatement()); |
|
Kevin Millikin (Chromium)
2011/06/08 12:47:49
I'm still using WithExitStatement here. I'll rena
Mads Ager (chromium)
2011/06/08 13:27:46
PopContextStatement seems reasonable to me.
|
| + |
| + // Create a try/finally statement. |
| + TryFinallyStatement* inner_try_finally = |
| + new(zone()) TryFinallyStatement(inner_body, inner_finally); |
| + inner_try_finally->set_escaping_targets(inner_collector.targets()); |
| + |
| + catch_block = new (zone()) Block(NULL, 1, false); |
| + catch_block->AddStatement(inner_try_finally); |
| } else { |
| Expect(Token::LBRACE, CHECK_OK); |
| } |
| @@ -2117,23 +2123,21 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
| tok = peek(); |
| } |
| - if (tok == Token::FINALLY || !has_catch) { |
| + Block* finally_block = NULL; |
| + if (tok == Token::FINALLY || catch_block == NULL) { |
| Consume(Token::FINALLY); |
| - // Declare a variable for holding the finally state while |
| - // executing the finally block. |
| finally_block = ParseBlock(NULL, CHECK_OK); |
| } |
| // Simplify the AST nodes by converting: |
| - // 'try { } catch { } finally { }' |
| + // 'try B0 catch B1 finally B2' |
| // to: |
| - // 'try { try { } catch { } } finally { }' |
| + // 'try { try B0 catch B1 } finally B2' |
| if (catch_block != NULL && finally_block != NULL) { |
| - VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var); |
| TryCatchStatement* statement = |
| - new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block); |
| - statement->set_escaping_targets(collector.targets()); |
| + new(zone()) TryCatchStatement(try_block, name, catch_block); |
| + statement->set_escaping_targets(try_collector.targets()); |
| try_block = new(zone()) Block(NULL, 1, false); |
| try_block->AddStatement(statement); |
| catch_block = NULL; |
| @@ -2142,20 +2146,16 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
| TryStatement* result = NULL; |
| if (catch_block != NULL) { |
| ASSERT(finally_block == NULL); |
| - VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var); |
| result = |
| - new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block); |
| - result->set_escaping_targets(collector.targets()); |
| + new(zone()) TryCatchStatement(try_block, name, catch_block); |
| } else { |
| ASSERT(finally_block != NULL); |
| result = new(zone()) TryFinallyStatement(try_block, finally_block); |
| - // Add the jump targets of the try block and the catch block. |
| - for (int i = 0; i < collector.targets()->length(); i++) { |
| - catch_collector.AddTarget(collector.targets()->at(i)); |
| - } |
| - result->set_escaping_targets(catch_collector.targets()); |
| + // Combine the jump targets of the try block and the possible catch block. |
| + try_collector.targets()->AddAll(*catch_collector.targets()); |
| } |
| + result->set_escaping_targets(try_collector.targets()); |
| return result; |
| } |