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 |