Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |