Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(494)

Side by Side Diff: src/parser.cc

Issue 7134014: Stop using with explicitly to implement try/catch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/parser.h ('k') | src/prettyprinter.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1888 matching lines...) Expand 10 before | Expand all | Expand 10 after
1899 ExpectSemicolon(CHECK_OK); 1899 ExpectSemicolon(CHECK_OK);
1900 return new(zone()) ReturnStatement(GetLiteralUndefined()); 1900 return new(zone()) ReturnStatement(GetLiteralUndefined());
1901 } 1901 }
1902 1902
1903 Expression* expr = ParseExpression(true, CHECK_OK); 1903 Expression* expr = ParseExpression(true, CHECK_OK);
1904 ExpectSemicolon(CHECK_OK); 1904 ExpectSemicolon(CHECK_OK);
1905 return new(zone()) ReturnStatement(expr); 1905 return new(zone()) ReturnStatement(expr);
1906 } 1906 }
1907 1907
1908 1908
1909 Block* Parser::WithHelper(Expression* obj, 1909 Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) {
1910 ZoneStringList* labels,
1911 bool is_catch_block,
1912 bool* ok) {
1913 // Parse the statement and collect escaping labels. 1910 // Parse the statement and collect escaping labels.
1914 ZoneList<Label*>* target_list = new(zone()) ZoneList<Label*>(0); 1911 TargetCollector collector;
1915 TargetCollector collector(target_list);
1916 Statement* stat; 1912 Statement* stat;
1917 { Target target(&this->target_stack_, &collector); 1913 { Target target(&this->target_stack_, &collector);
1918 with_nesting_level_++; 1914 with_nesting_level_++;
1919 top_scope_->RecordWithStatement(); 1915 top_scope_->RecordWithStatement();
1920 stat = ParseStatement(labels, CHECK_OK); 1916 stat = ParseStatement(labels, CHECK_OK);
1921 with_nesting_level_--; 1917 with_nesting_level_--;
1922 } 1918 }
1923 // Create resulting block with two statements. 1919 // Create resulting block with two statements.
1924 // 1: Evaluate the with expression. 1920 // 1: Evaluate the with expression.
1925 // 2: The try-finally block evaluating the body. 1921 // 2: The try-finally block evaluating the body.
1926 Block* result = new(zone()) Block(NULL, 2, false); 1922 Block* result = new(zone()) Block(NULL, 2, false);
1927 1923
1928 if (result != NULL) { 1924 if (result != NULL) {
1929 result->AddStatement(new(zone()) WithEnterStatement(obj, is_catch_block)); 1925 result->AddStatement(new(zone()) WithEnterStatement(obj));
1930 1926
1931 // Create body block. 1927 // Create body block.
1932 Block* body = new(zone()) Block(NULL, 1, false); 1928 Block* body = new(zone()) Block(NULL, 1, false);
1933 body->AddStatement(stat); 1929 body->AddStatement(stat);
1934 1930
1935 // Create exit block. 1931 // Create exit block.
1936 Block* exit = new(zone()) Block(NULL, 1, false); 1932 Block* exit = new(zone()) Block(NULL, 1, false);
1937 exit->AddStatement(new(zone()) WithExitStatement()); 1933 exit->AddStatement(new(zone()) WithExitStatement());
1938 1934
1939 // Return a try-finally statement. 1935 // Return a try-finally statement.
(...skipping 14 matching lines...) Expand all
1954 if (top_scope_->is_strict_mode()) { 1950 if (top_scope_->is_strict_mode()) {
1955 ReportMessage("strict_mode_with", Vector<const char*>::empty()); 1951 ReportMessage("strict_mode_with", Vector<const char*>::empty());
1956 *ok = false; 1952 *ok = false;
1957 return NULL; 1953 return NULL;
1958 } 1954 }
1959 1955
1960 Expect(Token::LPAREN, CHECK_OK); 1956 Expect(Token::LPAREN, CHECK_OK);
1961 Expression* expr = ParseExpression(true, CHECK_OK); 1957 Expression* expr = ParseExpression(true, CHECK_OK);
1962 Expect(Token::RPAREN, CHECK_OK); 1958 Expect(Token::RPAREN, CHECK_OK);
1963 1959
1964 return WithHelper(expr, labels, false, CHECK_OK); 1960 return WithHelper(expr, labels, CHECK_OK);
1965 } 1961 }
1966 1962
1967 1963
1968 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { 1964 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
1969 // CaseClause :: 1965 // CaseClause ::
1970 // 'case' Expression ':' Statement* 1966 // 'case' Expression ':' Statement*
1971 // 'default' ':' Statement* 1967 // 'default' ':' Statement*
1972 1968
1973 Expression* label = NULL; // NULL expression indicates default case 1969 Expression* label = NULL; // NULL expression indicates default case
1974 if (peek() == Token::CASE) { 1970 if (peek() == Token::CASE) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
2050 // 'try' Block Catch Finally 2046 // 'try' Block Catch Finally
2051 // 2047 //
2052 // Catch :: 2048 // Catch ::
2053 // 'catch' '(' Identifier ')' Block 2049 // 'catch' '(' Identifier ')' Block
2054 // 2050 //
2055 // Finally :: 2051 // Finally ::
2056 // 'finally' Block 2052 // 'finally' Block
2057 2053
2058 Expect(Token::TRY, CHECK_OK); 2054 Expect(Token::TRY, CHECK_OK);
2059 2055
2060 ZoneList<Label*>* target_list = new(zone()) ZoneList<Label*>(0); 2056 TargetCollector try_collector;
2061 TargetCollector collector(target_list);
2062 Block* try_block; 2057 Block* try_block;
2063 2058
2064 { Target target(&this->target_stack_, &collector); 2059 { Target target(&this->target_stack_, &try_collector);
2065 try_block = ParseBlock(NULL, CHECK_OK); 2060 try_block = ParseBlock(NULL, CHECK_OK);
2066 } 2061 }
2067 2062
2068 Block* catch_block = NULL;
2069 Variable* catch_var = NULL;
2070 Block* finally_block = NULL;
2071
2072 Token::Value tok = peek(); 2063 Token::Value tok = peek();
2073 if (tok != Token::CATCH && tok != Token::FINALLY) { 2064 if (tok != Token::CATCH && tok != Token::FINALLY) {
2074 ReportMessage("no_catch_or_finally", Vector<const char*>::empty()); 2065 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2075 *ok = false; 2066 *ok = false;
2076 return NULL; 2067 return NULL;
2077 } 2068 }
2078 2069
2079 // If we can break out from the catch block and there is a finally block, 2070 // If we can break out from the catch block and there is a finally block,
2080 // then we will need to collect jump targets from the catch block. Since 2071 // then we will need to collect escaping targets from the catch
2081 // we don't know yet if there will be a finally block, we always collect 2072 // block. Since we don't know yet if there will be a finally block, we
2082 // the jump targets. 2073 // always collect the targets.
2083 ZoneList<Label*>* catch_target_list = new(zone()) ZoneList<Label*>(0); 2074 TargetCollector catch_collector;
2084 TargetCollector catch_collector(catch_target_list); 2075 Block* catch_block = NULL;
2085 bool has_catch = false; 2076 Handle<String> name;
2086 if (tok == Token::CATCH) { 2077 if (tok == Token::CATCH) {
2087 has_catch = true;
2088 Consume(Token::CATCH); 2078 Consume(Token::CATCH);
2089 2079
2090 Expect(Token::LPAREN, CHECK_OK); 2080 Expect(Token::LPAREN, CHECK_OK);
2091 Handle<String> name = ParseIdentifier(CHECK_OK); 2081 name = ParseIdentifier(CHECK_OK);
2092 2082
2093 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) { 2083 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
2094 ReportMessage("strict_catch_variable", Vector<const char*>::empty()); 2084 ReportMessage("strict_catch_variable", Vector<const char*>::empty());
2095 *ok = false; 2085 *ok = false;
2096 return NULL; 2086 return NULL;
2097 } 2087 }
2098 2088
2099 Expect(Token::RPAREN, CHECK_OK); 2089 Expect(Token::RPAREN, CHECK_OK);
2100 2090
2101 if (peek() == Token::LBRACE) { 2091 if (peek() == Token::LBRACE) {
2102 // Allocate a temporary for holding the finally state while 2092 // Rewrite the catch body B to a single statement block
Mads Ager (chromium) 2011/06/08 13:27:46 Indentation.
2103 // executing the finally block. 2093 // { try B finally { PopContext }}.
2104 catch_var = 2094 Block* inner_body;
2105 top_scope_->NewTemporary(isolate()->factory()->catch_var_symbol()); 2095 // We need to collect escapes from the body for both the inner
2106 Literal* name_literal = new(zone()) Literal(name); 2096 // try/finally used to pop the catch context and any possible outer
2107 VariableProxy* catch_var_use = new(zone()) VariableProxy(catch_var); 2097 // try/finally.
2108 Expression* obj = 2098 TargetCollector inner_collector;
2109 new(zone()) CatchExtensionObject(name_literal, catch_var_use);
2110 { Target target(&this->target_stack_, &catch_collector); 2099 { Target target(&this->target_stack_, &catch_collector);
2111 catch_block = WithHelper(obj, NULL, true, CHECK_OK); 2100 { Target target(&this->target_stack_, &inner_collector);
2101 ++with_nesting_level_;
2102 top_scope_->RecordWithStatement();
2103 inner_body = ParseBlock(NULL, CHECK_OK);
2104 --with_nesting_level_;
2105 }
2112 } 2106 }
2107
2108 // Create exit block.
2109 Block* inner_finally = new(zone()) Block(NULL, 1, false);
2110 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.
2111
2112 // Create a try/finally statement.
2113 TryFinallyStatement* inner_try_finally =
2114 new(zone()) TryFinallyStatement(inner_body, inner_finally);
2115 inner_try_finally->set_escaping_targets(inner_collector.targets());
2116
2117 catch_block = new (zone()) Block(NULL, 1, false);
2118 catch_block->AddStatement(inner_try_finally);
2113 } else { 2119 } else {
2114 Expect(Token::LBRACE, CHECK_OK); 2120 Expect(Token::LBRACE, CHECK_OK);
2115 } 2121 }
2116 2122
2117 tok = peek(); 2123 tok = peek();
2118 } 2124 }
2119 2125
2120 if (tok == Token::FINALLY || !has_catch) { 2126 Block* finally_block = NULL;
2127 if (tok == Token::FINALLY || catch_block == NULL) {
2121 Consume(Token::FINALLY); 2128 Consume(Token::FINALLY);
2122 // Declare a variable for holding the finally state while
2123 // executing the finally block.
2124 finally_block = ParseBlock(NULL, CHECK_OK); 2129 finally_block = ParseBlock(NULL, CHECK_OK);
2125 } 2130 }
2126 2131
2127 // Simplify the AST nodes by converting: 2132 // Simplify the AST nodes by converting:
2128 // 'try { } catch { } finally { }' 2133 // 'try B0 catch B1 finally B2'
2129 // to: 2134 // to:
2130 // 'try { try { } catch { } } finally { }' 2135 // 'try { try B0 catch B1 } finally B2'
2131 2136
2132 if (catch_block != NULL && finally_block != NULL) { 2137 if (catch_block != NULL && finally_block != NULL) {
2133 VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var);
2134 TryCatchStatement* statement = 2138 TryCatchStatement* statement =
2135 new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block); 2139 new(zone()) TryCatchStatement(try_block, name, catch_block);
2136 statement->set_escaping_targets(collector.targets()); 2140 statement->set_escaping_targets(try_collector.targets());
2137 try_block = new(zone()) Block(NULL, 1, false); 2141 try_block = new(zone()) Block(NULL, 1, false);
2138 try_block->AddStatement(statement); 2142 try_block->AddStatement(statement);
2139 catch_block = NULL; 2143 catch_block = NULL;
2140 } 2144 }
2141 2145
2142 TryStatement* result = NULL; 2146 TryStatement* result = NULL;
2143 if (catch_block != NULL) { 2147 if (catch_block != NULL) {
2144 ASSERT(finally_block == NULL); 2148 ASSERT(finally_block == NULL);
2145 VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var);
2146 result = 2149 result =
2147 new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block); 2150 new(zone()) TryCatchStatement(try_block, name, catch_block);
2148 result->set_escaping_targets(collector.targets());
2149 } else { 2151 } else {
2150 ASSERT(finally_block != NULL); 2152 ASSERT(finally_block != NULL);
2151 result = new(zone()) TryFinallyStatement(try_block, finally_block); 2153 result = new(zone()) TryFinallyStatement(try_block, finally_block);
2152 // Add the jump targets of the try block and the catch block. 2154 // Combine the jump targets of the try block and the possible catch block.
2153 for (int i = 0; i < collector.targets()->length(); i++) { 2155 try_collector.targets()->AddAll(*catch_collector.targets());
2154 catch_collector.AddTarget(collector.targets()->at(i));
2155 }
2156 result->set_escaping_targets(catch_collector.targets());
2157 } 2156 }
2158 2157
2158 result->set_escaping_targets(try_collector.targets());
2159 return result; 2159 return result;
2160 } 2160 }
2161 2161
2162 2162
2163 DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels, 2163 DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2164 bool* ok) { 2164 bool* ok) {
2165 // DoStatement :: 2165 // DoStatement ::
2166 // 'do' Statement 'while' '(' Expression ')' ';' 2166 // 'do' Statement 'while' '(' Expression ')' ';'
2167 2167
2168 DoWhileStatement* loop = new(zone()) DoWhileStatement(labels); 2168 DoWhileStatement* loop = new(zone()) DoWhileStatement(labels);
(...skipping 2821 matching lines...) Expand 10 before | Expand all | Expand 10 after
4990 info->is_global(), 4990 info->is_global(),
4991 info->StrictMode()); 4991 info->StrictMode());
4992 } 4992 }
4993 } 4993 }
4994 4994
4995 info->SetFunction(result); 4995 info->SetFunction(result);
4996 return (result != NULL); 4996 return (result != NULL);
4997 } 4997 }
4998 4998
4999 } } // namespace v8::internal 4999 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/prettyprinter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698