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

Side by Side Diff: src/parsing/rewriter.cc

Issue 2427253003: Simplify and fix the rewriter (Closed)
Patch Set: Fix and add tests Created 4 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/mjsunit/es6/completion.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/parsing/rewriter.h" 5 #include "src/parsing/rewriter.h"
6 6
7 #include "src/ast/ast.h" 7 #include "src/ast/ast.h"
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/parsing/parse-info.h" 9 #include "src/parsing/parse-info.h"
10 #include "src/parsing/parser.h" 10 #include "src/parsing/parser.h"
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 node->set_expression(SetResult(node->expression())); 160 node->set_expression(SetResult(node->expression()));
161 is_set_ = true; 161 is_set_ = true;
162 } 162 }
163 replacement_ = node; 163 replacement_ = node;
164 } 164 }
165 165
166 166
167 void Processor::VisitIfStatement(IfStatement* node) { 167 void Processor::VisitIfStatement(IfStatement* node) {
168 // Rewrite both branches. 168 // Rewrite both branches.
169 bool set_after = is_set_; 169 bool set_after = is_set_;
170
170 Visit(node->then_statement()); 171 Visit(node->then_statement());
171 node->set_then_statement(replacement_); 172 node->set_then_statement(replacement_);
172 bool set_in_then = is_set_; 173 bool set_in_then = is_set_;
174
173 is_set_ = set_after; 175 is_set_ = set_after;
174 Visit(node->else_statement()); 176 Visit(node->else_statement());
175 node->set_else_statement(replacement_); 177 node->set_else_statement(replacement_);
176 is_set_ = is_set_ && set_in_then;
177 replacement_ = node;
178 178
179 if (!is_set_) { 179 replacement_ = set_in_then && is_set_ ? node : AssignUndefinedBefore(node);
180 is_set_ = true; 180 is_set_ = true;
181 replacement_ = AssignUndefinedBefore(node);
182 }
183 } 181 }
184 182
185 183
186 void Processor::VisitIterationStatement(IterationStatement* node) { 184 void Processor::VisitIterationStatement(IterationStatement* node) {
185 // The statement may have to produce a value, so always assign undefined
186 // before.
187 // TODO(verwaest): Omit it if we know that there's no break/continue leaving
188 // it early.
189 DCHECK(breakable_ || !is_set_);
187 BreakableScope scope(this); 190 BreakableScope scope(this);
188 // Rewrite the body. 191
189 bool set_after = is_set_;
190 is_set_ = false; // We are in a loop, so we can't rely on [set_after].
191 Visit(node->body()); 192 Visit(node->body());
192 node->set_body(replacement_); 193 node->set_body(replacement_);
193 is_set_ = is_set_ && set_after;
194 replacement_ = node;
195 194
196 if (!is_set_) { 195 replacement_ = AssignUndefinedBefore(node);
197 is_set_ = true; 196 is_set_ = true;
198 replacement_ = AssignUndefinedBefore(node);
199 }
200 } 197 }
201 198
202 199
203 void Processor::VisitDoWhileStatement(DoWhileStatement* node) { 200 void Processor::VisitDoWhileStatement(DoWhileStatement* node) {
204 VisitIterationStatement(node); 201 VisitIterationStatement(node);
205 } 202 }
206 203
207 204
208 void Processor::VisitWhileStatement(WhileStatement* node) { 205 void Processor::VisitWhileStatement(WhileStatement* node) {
209 VisitIterationStatement(node); 206 VisitIterationStatement(node);
(...skipping 11 matching lines...) Expand all
221 218
222 219
223 void Processor::VisitForOfStatement(ForOfStatement* node) { 220 void Processor::VisitForOfStatement(ForOfStatement* node) {
224 VisitIterationStatement(node); 221 VisitIterationStatement(node);
225 } 222 }
226 223
227 224
228 void Processor::VisitTryCatchStatement(TryCatchStatement* node) { 225 void Processor::VisitTryCatchStatement(TryCatchStatement* node) {
229 // Rewrite both try and catch block. 226 // Rewrite both try and catch block.
230 bool set_after = is_set_; 227 bool set_after = is_set_;
228
231 Visit(node->try_block()); 229 Visit(node->try_block());
232 node->set_try_block(static_cast<Block*>(replacement_)); 230 node->set_try_block(static_cast<Block*>(replacement_));
233 bool set_in_try = is_set_; 231 bool set_in_try = is_set_;
232
234 is_set_ = set_after; 233 is_set_ = set_after;
235 Visit(node->catch_block()); 234 Visit(node->catch_block());
236 node->set_catch_block(static_cast<Block*>(replacement_)); 235 node->set_catch_block(static_cast<Block*>(replacement_));
237 is_set_ = is_set_ && set_in_try;
238 replacement_ = node;
239 236
240 if (!is_set_) { 237 replacement_ = is_set_ && set_in_try ? node : AssignUndefinedBefore(node);
241 is_set_ = true; 238 is_set_ = true;
242 replacement_ = AssignUndefinedBefore(node);
243 }
244 } 239 }
245 240
246 241
247 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) { 242 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
248 // Rewrite both try and finally block (in reverse order). 243 // Only rewrite finally if it could contain 'break' or 'continue'. Always
249 bool set_after = is_set_; 244 // rewrite try.
250 is_set_ = true; // Don't normally need to assign in finally block. 245 if (breakable_) {
251 Visit(node->finally_block()); 246 bool set_after = is_set_;
252 node->set_finally_block(replacement_->AsBlock()); 247 // Only set result before a 'break' or 'continue'.
253 { // Save .result value at the beginning of the finally block and restore it 248 is_set_ = true;
254 // at the end again: ".backup = .result; ...; .result = .backup" 249 Visit(node->finally_block());
255 // This is necessary because the finally block does not normally contribute 250 node->set_finally_block(replacement_->AsBlock());
256 // to the completion value. 251 // Save .result value at the beginning of the finally block and restore it
257 CHECK_NOT_NULL(closure_scope()); 252 // at the end again: ".backup = .result; ...; .result = .backup"
258 Variable* backup = closure_scope()->NewTemporary( 253 // This is necessary because the finally block does not normally contribute
259 factory()->ast_value_factory()->dot_result_string()); 254 // to the completion value.
260 Expression* backup_proxy = factory()->NewVariableProxy(backup); 255 CHECK_NOT_NULL(closure_scope());
261 Expression* result_proxy = factory()->NewVariableProxy(result_); 256 Variable* backup = closure_scope()->NewTemporary(
262 Expression* save = factory()->NewAssignment( 257 factory()->ast_value_factory()->dot_result_string());
263 Token::ASSIGN, backup_proxy, result_proxy, kNoSourcePosition); 258 Expression* backup_proxy = factory()->NewVariableProxy(backup);
264 Expression* restore = factory()->NewAssignment( 259 Expression* result_proxy = factory()->NewVariableProxy(result_);
265 Token::ASSIGN, result_proxy, backup_proxy, kNoSourcePosition); 260 Expression* save = factory()->NewAssignment(
266 node->finally_block()->statements()->InsertAt( 261 Token::ASSIGN, backup_proxy, result_proxy, kNoSourcePosition);
267 0, factory()->NewExpressionStatement(save, kNoSourcePosition), zone()); 262 Expression* restore = factory()->NewAssignment(
268 node->finally_block()->statements()->Add( 263 Token::ASSIGN, result_proxy, backup_proxy, kNoSourcePosition);
269 factory()->NewExpressionStatement(restore, kNoSourcePosition), zone()); 264 node->finally_block()->statements()->InsertAt(
265 0, factory()->NewExpressionStatement(save, kNoSourcePosition), zone());
266 node->finally_block()->statements()->Add(
267 factory()->NewExpressionStatement(restore, kNoSourcePosition), zone());
268 is_set_ = set_after;
270 } 269 }
271 is_set_ = set_after;
272 Visit(node->try_block()); 270 Visit(node->try_block());
273 node->set_try_block(replacement_->AsBlock()); 271 node->set_try_block(replacement_->AsBlock());
274 replacement_ = node;
275 272
276 if (!is_set_) { 273 replacement_ = is_set_ ? node : AssignUndefinedBefore(node);
277 is_set_ = true; 274 is_set_ = true;
278 replacement_ = AssignUndefinedBefore(node);
279 }
280 } 275 }
281 276
282 277
283 void Processor::VisitSwitchStatement(SwitchStatement* node) { 278 void Processor::VisitSwitchStatement(SwitchStatement* node) {
279 // The statement may have to produce a value, so always assign undefined
280 // before.
281 // TODO(verwaest): Omit it if we know that there's no break/continue leaving
282 // it early.
283 DCHECK(breakable_ || !is_set_);
284 BreakableScope scope(this); 284 BreakableScope scope(this);
285 // Rewrite statements in all case clauses (in reverse order). 285 // Rewrite statements in all case clauses.
286 ZoneList<CaseClause*>* clauses = node->cases(); 286 ZoneList<CaseClause*>* clauses = node->cases();
287 bool set_after = is_set_;
288 for (int i = clauses->length() - 1; i >= 0; --i) { 287 for (int i = clauses->length() - 1; i >= 0; --i) {
289 CaseClause* clause = clauses->at(i); 288 CaseClause* clause = clauses->at(i);
290 Process(clause->statements()); 289 Process(clause->statements());
291 } 290 }
292 is_set_ = is_set_ && set_after;
293 replacement_ = node;
294 291
295 if (!is_set_) { 292 replacement_ = AssignUndefinedBefore(node);
296 is_set_ = true; 293 is_set_ = true;
297 replacement_ = AssignUndefinedBefore(node);
298 }
299 } 294 }
300 295
301 296
302 void Processor::VisitContinueStatement(ContinueStatement* node) { 297 void Processor::VisitContinueStatement(ContinueStatement* node) {
303 is_set_ = false; 298 is_set_ = false;
304 replacement_ = node; 299 replacement_ = node;
305 } 300 }
306 301
307 302
308 void Processor::VisitBreakStatement(BreakStatement* node) { 303 void Processor::VisitBreakStatement(BreakStatement* node) {
309 is_set_ = false; 304 is_set_ = false;
310 replacement_ = node; 305 replacement_ = node;
311 } 306 }
312 307
313 308
314 void Processor::VisitWithStatement(WithStatement* node) { 309 void Processor::VisitWithStatement(WithStatement* node) {
315 Visit(node->statement()); 310 Visit(node->statement());
316 node->set_statement(replacement_); 311 node->set_statement(replacement_);
317 replacement_ = node;
318 312
319 if (!is_set_) { 313 replacement_ = is_set_ ? node : AssignUndefinedBefore(node);
320 is_set_ = true; 314 is_set_ = true;
321 replacement_ = AssignUndefinedBefore(node);
322 }
323 } 315 }
324 316
325 317
326 void Processor::VisitSloppyBlockFunctionStatement( 318 void Processor::VisitSloppyBlockFunctionStatement(
327 SloppyBlockFunctionStatement* node) { 319 SloppyBlockFunctionStatement* node) {
328 Visit(node->statement()); 320 Visit(node->statement());
329 node->set_statement(replacement_); 321 node->set_statement(replacement_);
330 replacement_ = node; 322 replacement_ = node;
331 } 323 }
332 324
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 processor.SetResult(undef), expr->position()); 412 processor.SetResult(undef), expr->position());
421 body->Add(completion, factory->zone()); 413 body->Add(completion, factory->zone());
422 } 414 }
423 } 415 }
424 return true; 416 return true;
425 } 417 }
426 418
427 419
428 } // namespace internal 420 } // namespace internal
429 } // namespace v8 421 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/es6/completion.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698