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

Side by Side Diff: src/rewriter.cc

Issue 1362333002: Clean up rewriter. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 2 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
« no previous file with comments | « no previous file | test/webkit/eval-throw-return.js » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/rewriter.h" 5 #include "src/rewriter.h"
6 6
7 #include "src/ast.h" 7 #include "src/ast.h"
8 #include "src/parser.h" 8 #include "src/parser.h"
9 #include "src/scopes.h" 9 #include "src/scopes.h"
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 13
14 class Processor: public AstVisitor { 14 class Processor: public AstVisitor {
15 public: 15 public:
16 Processor(Isolate* isolate, Variable* result, 16 Processor(Isolate* isolate, Variable* result,
17 AstValueFactory* ast_value_factory) 17 AstValueFactory* ast_value_factory)
18 : result_(result), 18 : result_(result),
19 result_assigned_(false), 19 result_assigned_(false),
20 is_set_(false), 20 is_set_(false),
21 in_try_(false),
22 factory_(ast_value_factory) { 21 factory_(ast_value_factory) {
23 InitializeAstVisitor(isolate, ast_value_factory->zone()); 22 InitializeAstVisitor(isolate, ast_value_factory->zone());
24 } 23 }
25 24
26 virtual ~Processor() { } 25 virtual ~Processor() { }
27 26
28 void Process(ZoneList<Statement*>* statements); 27 void Process(ZoneList<Statement*>* statements);
29 bool result_assigned() const { return result_assigned_; } 28 bool result_assigned() const { return result_assigned_; }
30 29
31 AstNodeFactory* factory() { return &factory_; } 30 AstNodeFactory* factory() { return &factory_; }
32 31
33 private: 32 private:
34 Variable* result_; 33 Variable* result_;
35 34
36 // We are not tracking result usage via the result_'s use 35 // We are not tracking result usage via the result_'s use
37 // counts (we leave the accurate computation to the 36 // counts (we leave the accurate computation to the
38 // usage analyzer). Instead we simple remember if 37 // usage analyzer). Instead we simple remember if
39 // there was ever an assignment to result_. 38 // there was ever an assignment to result_.
40 bool result_assigned_; 39 bool result_assigned_;
41 40
42 // To avoid storing to .result all the time, we eliminate some of 41 // To avoid storing to .result all the time, we eliminate some of
43 // the stores by keeping track of whether or not we're sure .result 42 // the stores by keeping track of whether or not we're sure .result
44 // will be overwritten anyway. This is a bit more tricky than what I 43 // will be overwritten anyway. This is a bit more tricky than what I
45 // was hoping for 44 // was hoping for.
46 bool is_set_; 45 bool is_set_;
47 bool in_try_;
48 46
49 AstNodeFactory factory_; 47 AstNodeFactory factory_;
50 48
51 Expression* SetResult(Expression* value) { 49 Expression* SetResult(Expression* value) {
52 result_assigned_ = true; 50 result_assigned_ = true;
53 VariableProxy* result_proxy = factory()->NewVariableProxy(result_); 51 VariableProxy* result_proxy = factory()->NewVariableProxy(result_);
54 return factory()->NewAssignment( 52 return factory()->NewAssignment(
55 Token::ASSIGN, result_proxy, value, RelocInfo::kNoPosition); 53 Token::ASSIGN, result_proxy, value, RelocInfo::kNoPosition);
56 } 54 }
57 55
(...skipping 23 matching lines...) Expand all
81 // a variable declaration with initialization expression is 'undefined' 79 // a variable declaration with initialization expression is 'undefined'
82 // with some JS VMs: For instance, using smjs, print(eval('var x = 7')) 80 // with some JS VMs: For instance, using smjs, print(eval('var x = 7'))
83 // returns 'undefined'. To obtain the same behavior with v8, we need 81 // returns 'undefined'. To obtain the same behavior with v8, we need
84 // to prevent rewriting in that case. 82 // to prevent rewriting in that case.
85 if (!node->ignore_completion_value()) Process(node->statements()); 83 if (!node->ignore_completion_value()) Process(node->statements());
86 } 84 }
87 85
88 86
89 void Processor::VisitExpressionStatement(ExpressionStatement* node) { 87 void Processor::VisitExpressionStatement(ExpressionStatement* node) {
90 // Rewrite : <x>; -> .result = <x>; 88 // Rewrite : <x>; -> .result = <x>;
91 if (!is_set_ && !node->expression()->IsThrow()) { 89 if (!is_set_) {
92 node->set_expression(SetResult(node->expression())); 90 node->set_expression(SetResult(node->expression()));
93 if (!in_try_) is_set_ = true; 91 is_set_ = true;
94 } 92 }
95 } 93 }
96 94
97 95
98 void Processor::VisitIfStatement(IfStatement* node) { 96 void Processor::VisitIfStatement(IfStatement* node) {
99 // Rewrite both then and else parts (reversed). 97 // Rewrite both branches.
100 bool save = is_set_; 98 bool set_after = is_set_;
99 Visit(node->then_statement());
100 bool set_in_then = is_set_;
101 is_set_ = set_after;
101 Visit(node->else_statement()); 102 Visit(node->else_statement());
102 bool set_after_then = is_set_; 103 is_set_ = is_set_ && set_in_then;
103 is_set_ = save;
104 Visit(node->then_statement());
105 is_set_ = is_set_ && set_after_then;
106 } 104 }
107 105
108 106
109 void Processor::VisitIterationStatement(IterationStatement* node) { 107 void Processor::VisitIterationStatement(IterationStatement* node) {
110 // Rewrite the body. 108 // Rewrite the body.
111 bool set_after_loop = is_set_; 109 bool set_after = is_set_;
110 is_set_ = false; // We are in a loop, so we can't rely on [set_after].
112 Visit(node->body()); 111 Visit(node->body());
113 is_set_ = is_set_ && set_after_loop; 112 is_set_ = is_set_ && set_after;
114 } 113 }
115 114
116 115
117 void Processor::VisitDoWhileStatement(DoWhileStatement* node) { 116 void Processor::VisitDoWhileStatement(DoWhileStatement* node) {
118 VisitIterationStatement(node); 117 VisitIterationStatement(node);
119 } 118 }
120 119
121 120
122 void Processor::VisitWhileStatement(WhileStatement* node) { 121 void Processor::VisitWhileStatement(WhileStatement* node) {
123 VisitIterationStatement(node); 122 VisitIterationStatement(node);
124 } 123 }
125 124
126 125
127 void Processor::VisitForStatement(ForStatement* node) { 126 void Processor::VisitForStatement(ForStatement* node) {
128 VisitIterationStatement(node); 127 VisitIterationStatement(node);
129 } 128 }
130 129
131 130
132 void Processor::VisitForInStatement(ForInStatement* node) { 131 void Processor::VisitForInStatement(ForInStatement* node) {
133 VisitIterationStatement(node); 132 VisitIterationStatement(node);
134 } 133 }
135 134
136 135
137 void Processor::VisitForOfStatement(ForOfStatement* node) { 136 void Processor::VisitForOfStatement(ForOfStatement* node) {
138 VisitIterationStatement(node); 137 VisitIterationStatement(node);
139 } 138 }
140 139
141 140
142 void Processor::VisitTryCatchStatement(TryCatchStatement* node) { 141 void Processor::VisitTryCatchStatement(TryCatchStatement* node) {
143 // Rewrite both try and catch blocks (reversed order). 142 // Rewrite both try and catch block.
144 bool set_after_catch = is_set_; 143 bool set_after = is_set_;
144 Visit(node->try_block());
145 bool set_in_try = is_set_;
146 is_set_ = set_after;
145 Visit(node->catch_block()); 147 Visit(node->catch_block());
146 is_set_ = is_set_ && set_after_catch; 148 is_set_ = is_set_ && set_in_try;
147 bool save = in_try_;
148 in_try_ = true;
149 Visit(node->try_block());
150 in_try_ = save;
151 } 149 }
152 150
153 151
154 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) { 152 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
155 // Rewrite both try and finally block (reversed order). 153 // Rewrite both try and finally block (in reverse order).
156 Visit(node->finally_block()); 154 Visit(node->finally_block());
157 bool save = in_try_;
158 in_try_ = true;
159 Visit(node->try_block()); 155 Visit(node->try_block());
160 in_try_ = save;
161 } 156 }
162 157
163 158
164 void Processor::VisitSwitchStatement(SwitchStatement* node) { 159 void Processor::VisitSwitchStatement(SwitchStatement* node) {
165 // Rewrite statements in all case clauses in reversed order. 160 // Rewrite statements in all case clauses (in reverse order).
166 ZoneList<CaseClause*>* clauses = node->cases(); 161 ZoneList<CaseClause*>* clauses = node->cases();
167 bool set_after_switch = is_set_; 162 bool set_after = is_set_;
168 for (int i = clauses->length() - 1; i >= 0; --i) { 163 for (int i = clauses->length() - 1; i >= 0; --i) {
169 CaseClause* clause = clauses->at(i); 164 CaseClause* clause = clauses->at(i);
170 Process(clause->statements()); 165 Process(clause->statements());
171 } 166 }
172 is_set_ = is_set_ && set_after_switch; 167 is_set_ = is_set_ && set_after;
173 } 168 }
174 169
175 170
176 void Processor::VisitContinueStatement(ContinueStatement* node) { 171 void Processor::VisitContinueStatement(ContinueStatement* node) {
177 is_set_ = false; 172 is_set_ = false;
178 } 173 }
179 174
180 175
181 void Processor::VisitBreakStatement(BreakStatement* node) { 176 void Processor::VisitBreakStatement(BreakStatement* node) {
182 is_set_ = false; 177 is_set_ = false;
183 } 178 }
184 179
185 180
186 void Processor::VisitWithStatement(WithStatement* node) { 181 void Processor::VisitWithStatement(WithStatement* node) {
187 bool set_after_body = is_set_;
188 Visit(node->statement()); 182 Visit(node->statement());
189 is_set_ = is_set_ && set_after_body;
190 } 183 }
191 184
192 185
193 void Processor::VisitSloppyBlockFunctionStatement( 186 void Processor::VisitSloppyBlockFunctionStatement(
194 SloppyBlockFunctionStatement* node) { 187 SloppyBlockFunctionStatement* node) {
195 Visit(node->statement()); 188 Visit(node->statement());
196 } 189 }
197 190
198 191
192 void Processor::VisitReturnStatement(ReturnStatement* node) { is_set_ = true; }
193
194
199 // Do nothing: 195 // Do nothing:
200 void Processor::VisitVariableDeclaration(VariableDeclaration* node) {}
201 void Processor::VisitFunctionDeclaration(FunctionDeclaration* node) {}
202 void Processor::VisitImportDeclaration(ImportDeclaration* node) {}
203 void Processor::VisitExportDeclaration(ExportDeclaration* node) {}
204 void Processor::VisitEmptyStatement(EmptyStatement* node) {} 196 void Processor::VisitEmptyStatement(EmptyStatement* node) {}
205 void Processor::VisitReturnStatement(ReturnStatement* node) {}
206 void Processor::VisitDebuggerStatement(DebuggerStatement* node) {} 197 void Processor::VisitDebuggerStatement(DebuggerStatement* node) {}
207 198
208 199
209 // Expressions are never visited yet. 200 // Expressions are never visited.
210 #define DEF_VISIT(type) \ 201 #define DEF_VISIT(type) \
211 void Processor::Visit##type(type* expr) { UNREACHABLE(); } 202 void Processor::Visit##type(type* expr) { UNREACHABLE(); }
212 EXPRESSION_NODE_LIST(DEF_VISIT) 203 EXPRESSION_NODE_LIST(DEF_VISIT)
213 #undef DEF_VISIT 204 #undef DEF_VISIT
214 205
215 206
207 // Declarations are never visited.
208 #define DEF_VISIT(type) \
209 void Processor::Visit##type(type* expr) { UNREACHABLE(); }
210 DECLARATION_NODE_LIST(DEF_VISIT)
211 #undef DEF_VISIT
212
213
216 // Assumes code has been parsed. Mutates the AST, so the AST should not 214 // Assumes code has been parsed. Mutates the AST, so the AST should not
217 // continue to be used in the case of failure. 215 // continue to be used in the case of failure.
218 bool Rewriter::Rewrite(ParseInfo* info) { 216 bool Rewriter::Rewrite(ParseInfo* info) {
219 FunctionLiteral* function = info->literal(); 217 FunctionLiteral* function = info->literal();
220 DCHECK(function != NULL); 218 DCHECK(function != NULL);
221 Scope* scope = function->scope(); 219 Scope* scope = function->scope();
222 DCHECK(scope != NULL); 220 DCHECK(scope != NULL);
223 if (!scope->is_script_scope() && !scope->is_eval_scope()) return true; 221 if (!scope->is_script_scope() && !scope->is_eval_scope()) return true;
224 222
225 ZoneList<Statement*>* body = function->body(); 223 ZoneList<Statement*>* body = function->body();
(...skipping 22 matching lines...) Expand all
248 body->Add(result_statement, info->zone()); 246 body->Add(result_statement, info->zone());
249 } 247 }
250 } 248 }
251 249
252 return true; 250 return true;
253 } 251 }
254 252
255 253
256 } // namespace internal 254 } // namespace internal
257 } // namespace v8 255 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/webkit/eval-throw-return.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698