OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/ast-numbering.h" | |
6 | |
7 #include "src/ast.h" | |
8 #include "src/scopes.h" | |
9 | |
10 namespace v8 { | |
11 namespace internal { | |
12 | |
13 class AstNumberingVisitor final : public AstVisitor { | |
14 public: | |
15 AstNumberingVisitor(Isolate* isolate, Zone* zone) | |
16 : AstVisitor(), | |
17 isolate_(isolate), | |
18 zone_(zone), | |
19 next_id_(BailoutId::FirstUsable().ToInt()), | |
20 properties_(zone), | |
21 slot_cache_(zone), | |
22 dont_optimize_reason_(kNoReason) { | |
23 InitializeAstVisitor(isolate); | |
24 } | |
25 | |
26 bool Renumber(FunctionLiteral* node); | |
27 | |
28 private: | |
29 // AST node visitor interface. | |
30 #define DEFINE_VISIT(type) void Visit##type(type* node) override; | |
31 AST_NODE_LIST(DEFINE_VISIT) | |
32 #undef DEFINE_VISIT | |
33 | |
34 bool Finish(FunctionLiteral* node); | |
35 | |
36 void VisitVariableProxyReference(VariableProxy* node); | |
37 void VisitPropertyReference(Property* node); | |
38 void VisitReference(Expression* expr); | |
39 | |
40 void VisitStatements(ZoneList<Statement*>* statements) override; | |
41 void VisitDeclarations(ZoneList<Declaration*>* declarations) override; | |
42 void VisitArguments(ZoneList<Expression*>* arguments); | |
43 void VisitObjectLiteralProperty(ObjectLiteralProperty* property); | |
44 | |
45 int ReserveIdRange(int n) { | |
46 int tmp = next_id_; | |
47 next_id_ += n; | |
48 return tmp; | |
49 } | |
50 | |
51 void IncrementNodeCount() { properties_.add_node_count(1); } | |
52 void DisableSelfOptimization() { | |
53 properties_.flags() |= AstProperties::kDontSelfOptimize; | |
54 } | |
55 void DisableOptimization(BailoutReason reason) { | |
56 dont_optimize_reason_ = reason; | |
57 DisableSelfOptimization(); | |
58 } | |
59 void DisableCrankshaft(BailoutReason reason) { | |
60 if (FLAG_turbo_shipping) { | |
61 properties_.flags() |= AstProperties::kDontCrankshaft; | |
62 } else { | |
63 dont_optimize_reason_ = reason; | |
64 DisableSelfOptimization(); | |
65 } | |
66 } | |
67 | |
68 template <typename Node> | |
69 void ReserveFeedbackSlots(Node* node) { | |
70 node->AssignFeedbackVectorSlots(isolate_, properties_.get_spec(), | |
71 &slot_cache_); | |
72 } | |
73 | |
74 BailoutReason dont_optimize_reason() const { return dont_optimize_reason_; } | |
75 | |
76 Isolate* isolate_; | |
77 Zone* zone_; | |
78 int next_id_; | |
79 AstProperties properties_; | |
80 // The slot cache allows us to reuse certain feedback vector slots. | |
81 FeedbackVectorSlotCache slot_cache_; | |
82 BailoutReason dont_optimize_reason_; | |
83 | |
84 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | |
85 DISALLOW_COPY_AND_ASSIGN(AstNumberingVisitor); | |
86 }; | |
87 | |
88 | |
89 void AstNumberingVisitor::VisitVariableDeclaration(VariableDeclaration* node) { | |
90 IncrementNodeCount(); | |
91 VisitVariableProxy(node->proxy()); | |
92 } | |
93 | |
94 | |
95 void AstNumberingVisitor::VisitExportDeclaration(ExportDeclaration* node) { | |
96 IncrementNodeCount(); | |
97 DisableOptimization(kExportDeclaration); | |
98 VisitVariableProxy(node->proxy()); | |
99 } | |
100 | |
101 | |
102 void AstNumberingVisitor::VisitEmptyStatement(EmptyStatement* node) { | |
103 IncrementNodeCount(); | |
104 } | |
105 | |
106 | |
107 void AstNumberingVisitor::VisitSloppyBlockFunctionStatement( | |
108 SloppyBlockFunctionStatement* node) { | |
109 IncrementNodeCount(); | |
110 Visit(node->statement()); | |
111 } | |
112 | |
113 | |
114 void AstNumberingVisitor::VisitContinueStatement(ContinueStatement* node) { | |
115 IncrementNodeCount(); | |
116 } | |
117 | |
118 | |
119 void AstNumberingVisitor::VisitBreakStatement(BreakStatement* node) { | |
120 IncrementNodeCount(); | |
121 } | |
122 | |
123 | |
124 void AstNumberingVisitor::VisitDebuggerStatement(DebuggerStatement* node) { | |
125 IncrementNodeCount(); | |
126 DisableOptimization(kDebuggerStatement); | |
127 node->set_base_id(ReserveIdRange(DebuggerStatement::num_ids())); | |
128 } | |
129 | |
130 | |
131 void AstNumberingVisitor::VisitNativeFunctionLiteral( | |
132 NativeFunctionLiteral* node) { | |
133 IncrementNodeCount(); | |
134 DisableOptimization(kNativeFunctionLiteral); | |
135 node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids())); | |
136 } | |
137 | |
138 | |
139 void AstNumberingVisitor::VisitDoExpression(DoExpression* node) { | |
140 IncrementNodeCount(); | |
141 DisableCrankshaft(kDoExpression); | |
142 node->set_base_id(ReserveIdRange(DoExpression::num_ids())); | |
143 Visit(node->block()); | |
144 Visit(node->result()); | |
145 } | |
146 | |
147 | |
148 void AstNumberingVisitor::VisitLiteral(Literal* node) { | |
149 IncrementNodeCount(); | |
150 node->set_base_id(ReserveIdRange(Literal::num_ids())); | |
151 } | |
152 | |
153 | |
154 void AstNumberingVisitor::VisitRegExpLiteral(RegExpLiteral* node) { | |
155 IncrementNodeCount(); | |
156 node->set_base_id(ReserveIdRange(RegExpLiteral::num_ids())); | |
157 } | |
158 | |
159 | |
160 void AstNumberingVisitor::VisitVariableProxyReference(VariableProxy* node) { | |
161 IncrementNodeCount(); | |
162 if (node->var()->IsLookupSlot()) { | |
163 DisableCrankshaft(kReferenceToAVariableWhichRequiresDynamicLookup); | |
164 } | |
165 node->set_base_id(ReserveIdRange(VariableProxy::num_ids())); | |
166 } | |
167 | |
168 | |
169 void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) { | |
170 VisitVariableProxyReference(node); | |
171 ReserveFeedbackSlots(node); | |
172 } | |
173 | |
174 | |
175 void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) { | |
176 IncrementNodeCount(); | |
177 node->set_base_id(ReserveIdRange(ThisFunction::num_ids())); | |
178 } | |
179 | |
180 | |
181 void AstNumberingVisitor::VisitSuperPropertyReference( | |
182 SuperPropertyReference* node) { | |
183 IncrementNodeCount(); | |
184 DisableOptimization(kSuperReference); | |
185 node->set_base_id(ReserveIdRange(SuperPropertyReference::num_ids())); | |
186 Visit(node->this_var()); | |
187 Visit(node->home_object()); | |
188 } | |
189 | |
190 | |
191 void AstNumberingVisitor::VisitSuperCallReference(SuperCallReference* node) { | |
192 IncrementNodeCount(); | |
193 DisableOptimization(kSuperReference); | |
194 node->set_base_id(ReserveIdRange(SuperCallReference::num_ids())); | |
195 Visit(node->this_var()); | |
196 Visit(node->new_target_var()); | |
197 Visit(node->this_function_var()); | |
198 } | |
199 | |
200 | |
201 void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) { | |
202 IncrementNodeCount(); | |
203 DisableOptimization(kImportDeclaration); | |
204 VisitVariableProxy(node->proxy()); | |
205 } | |
206 | |
207 | |
208 void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) { | |
209 IncrementNodeCount(); | |
210 Visit(node->expression()); | |
211 } | |
212 | |
213 | |
214 void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) { | |
215 IncrementNodeCount(); | |
216 Visit(node->expression()); | |
217 } | |
218 | |
219 | |
220 void AstNumberingVisitor::VisitYield(Yield* node) { | |
221 IncrementNodeCount(); | |
222 DisableOptimization(kYield); | |
223 ReserveFeedbackSlots(node); | |
224 node->set_base_id(ReserveIdRange(Yield::num_ids())); | |
225 Visit(node->generator_object()); | |
226 Visit(node->expression()); | |
227 } | |
228 | |
229 | |
230 void AstNumberingVisitor::VisitThrow(Throw* node) { | |
231 IncrementNodeCount(); | |
232 node->set_base_id(ReserveIdRange(Throw::num_ids())); | |
233 Visit(node->exception()); | |
234 } | |
235 | |
236 | |
237 void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) { | |
238 IncrementNodeCount(); | |
239 node->set_base_id(ReserveIdRange(UnaryOperation::num_ids())); | |
240 Visit(node->expression()); | |
241 } | |
242 | |
243 | |
244 void AstNumberingVisitor::VisitCountOperation(CountOperation* node) { | |
245 IncrementNodeCount(); | |
246 node->set_base_id(ReserveIdRange(CountOperation::num_ids())); | |
247 Visit(node->expression()); | |
248 ReserveFeedbackSlots(node); | |
249 } | |
250 | |
251 | |
252 void AstNumberingVisitor::VisitBlock(Block* node) { | |
253 IncrementNodeCount(); | |
254 node->set_base_id(ReserveIdRange(Block::num_ids())); | |
255 if (node->scope() != NULL) VisitDeclarations(node->scope()->declarations()); | |
256 VisitStatements(node->statements()); | |
257 } | |
258 | |
259 | |
260 void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) { | |
261 IncrementNodeCount(); | |
262 VisitVariableProxy(node->proxy()); | |
263 VisitFunctionLiteral(node->fun()); | |
264 } | |
265 | |
266 | |
267 void AstNumberingVisitor::VisitCallRuntime(CallRuntime* node) { | |
268 IncrementNodeCount(); | |
269 ReserveFeedbackSlots(node); | |
270 if (node->is_jsruntime()) { | |
271 // Don't try to optimize JS runtime calls because we bailout on them. | |
272 DisableOptimization(kCallToAJavaScriptRuntimeFunction); | |
273 } | |
274 node->set_base_id(ReserveIdRange(CallRuntime::num_ids())); | |
275 VisitArguments(node->arguments()); | |
276 } | |
277 | |
278 | |
279 void AstNumberingVisitor::VisitWithStatement(WithStatement* node) { | |
280 IncrementNodeCount(); | |
281 DisableCrankshaft(kWithStatement); | |
282 node->set_base_id(ReserveIdRange(WithStatement::num_ids())); | |
283 Visit(node->expression()); | |
284 Visit(node->statement()); | |
285 } | |
286 | |
287 | |
288 void AstNumberingVisitor::VisitDoWhileStatement(DoWhileStatement* node) { | |
289 IncrementNodeCount(); | |
290 DisableSelfOptimization(); | |
291 node->set_base_id(ReserveIdRange(DoWhileStatement::num_ids())); | |
292 Visit(node->body()); | |
293 Visit(node->cond()); | |
294 } | |
295 | |
296 | |
297 void AstNumberingVisitor::VisitWhileStatement(WhileStatement* node) { | |
298 IncrementNodeCount(); | |
299 DisableSelfOptimization(); | |
300 node->set_base_id(ReserveIdRange(WhileStatement::num_ids())); | |
301 Visit(node->cond()); | |
302 Visit(node->body()); | |
303 } | |
304 | |
305 | |
306 void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) { | |
307 IncrementNodeCount(); | |
308 DisableOptimization(kTryCatchStatement); | |
309 node->set_base_id(ReserveIdRange(TryCatchStatement::num_ids())); | |
310 Visit(node->try_block()); | |
311 Visit(node->catch_block()); | |
312 } | |
313 | |
314 | |
315 void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) { | |
316 IncrementNodeCount(); | |
317 DisableOptimization(kTryFinallyStatement); | |
318 node->set_base_id(ReserveIdRange(TryFinallyStatement::num_ids())); | |
319 Visit(node->try_block()); | |
320 Visit(node->finally_block()); | |
321 } | |
322 | |
323 | |
324 void AstNumberingVisitor::VisitPropertyReference(Property* node) { | |
325 IncrementNodeCount(); | |
326 node->set_base_id(ReserveIdRange(Property::num_ids())); | |
327 Visit(node->key()); | |
328 Visit(node->obj()); | |
329 } | |
330 | |
331 | |
332 void AstNumberingVisitor::VisitReference(Expression* expr) { | |
333 DCHECK(expr->IsProperty() || expr->IsVariableProxy()); | |
334 if (expr->IsProperty()) { | |
335 VisitPropertyReference(expr->AsProperty()); | |
336 } else { | |
337 VisitVariableProxyReference(expr->AsVariableProxy()); | |
338 } | |
339 } | |
340 | |
341 | |
342 void AstNumberingVisitor::VisitProperty(Property* node) { | |
343 VisitPropertyReference(node); | |
344 ReserveFeedbackSlots(node); | |
345 } | |
346 | |
347 | |
348 void AstNumberingVisitor::VisitAssignment(Assignment* node) { | |
349 IncrementNodeCount(); | |
350 node->set_base_id(ReserveIdRange(Assignment::num_ids())); | |
351 if (node->is_compound()) VisitBinaryOperation(node->binary_operation()); | |
352 VisitReference(node->target()); | |
353 Visit(node->value()); | |
354 ReserveFeedbackSlots(node); | |
355 } | |
356 | |
357 | |
358 void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) { | |
359 IncrementNodeCount(); | |
360 node->set_base_id(ReserveIdRange(BinaryOperation::num_ids())); | |
361 Visit(node->left()); | |
362 Visit(node->right()); | |
363 } | |
364 | |
365 | |
366 void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) { | |
367 IncrementNodeCount(); | |
368 node->set_base_id(ReserveIdRange(CompareOperation::num_ids())); | |
369 Visit(node->left()); | |
370 Visit(node->right()); | |
371 } | |
372 | |
373 | |
374 void AstNumberingVisitor::VisitSpread(Spread* node) { | |
375 IncrementNodeCount(); | |
376 DisableCrankshaft(kSpread); | |
377 Visit(node->expression()); | |
378 } | |
379 | |
380 | |
381 void AstNumberingVisitor::VisitEmptyParentheses(EmptyParentheses* node) { | |
382 UNREACHABLE(); | |
383 } | |
384 | |
385 | |
386 void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) { | |
387 IncrementNodeCount(); | |
388 DisableSelfOptimization(); | |
389 node->set_base_id(ReserveIdRange(ForInStatement::num_ids())); | |
390 Visit(node->each()); | |
391 Visit(node->enumerable()); | |
392 Visit(node->body()); | |
393 ReserveFeedbackSlots(node); | |
394 } | |
395 | |
396 | |
397 void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) { | |
398 IncrementNodeCount(); | |
399 DisableCrankshaft(kForOfStatement); | |
400 node->set_base_id(ReserveIdRange(ForOfStatement::num_ids())); | |
401 Visit(node->assign_iterator()); | |
402 Visit(node->next_result()); | |
403 Visit(node->result_done()); | |
404 Visit(node->assign_each()); | |
405 Visit(node->body()); | |
406 ReserveFeedbackSlots(node); | |
407 } | |
408 | |
409 | |
410 void AstNumberingVisitor::VisitConditional(Conditional* node) { | |
411 IncrementNodeCount(); | |
412 node->set_base_id(ReserveIdRange(Conditional::num_ids())); | |
413 Visit(node->condition()); | |
414 Visit(node->then_expression()); | |
415 Visit(node->else_expression()); | |
416 } | |
417 | |
418 | |
419 void AstNumberingVisitor::VisitIfStatement(IfStatement* node) { | |
420 IncrementNodeCount(); | |
421 node->set_base_id(ReserveIdRange(IfStatement::num_ids())); | |
422 Visit(node->condition()); | |
423 Visit(node->then_statement()); | |
424 if (node->HasElseStatement()) { | |
425 Visit(node->else_statement()); | |
426 } | |
427 } | |
428 | |
429 | |
430 void AstNumberingVisitor::VisitSwitchStatement(SwitchStatement* node) { | |
431 IncrementNodeCount(); | |
432 node->set_base_id(ReserveIdRange(SwitchStatement::num_ids())); | |
433 Visit(node->tag()); | |
434 ZoneList<CaseClause*>* cases = node->cases(); | |
435 for (int i = 0; i < cases->length(); i++) { | |
436 VisitCaseClause(cases->at(i)); | |
437 } | |
438 } | |
439 | |
440 | |
441 void AstNumberingVisitor::VisitCaseClause(CaseClause* node) { | |
442 IncrementNodeCount(); | |
443 node->set_base_id(ReserveIdRange(CaseClause::num_ids())); | |
444 if (!node->is_default()) Visit(node->label()); | |
445 VisitStatements(node->statements()); | |
446 } | |
447 | |
448 | |
449 void AstNumberingVisitor::VisitForStatement(ForStatement* node) { | |
450 IncrementNodeCount(); | |
451 DisableSelfOptimization(); | |
452 node->set_base_id(ReserveIdRange(ForStatement::num_ids())); | |
453 if (node->init() != NULL) Visit(node->init()); | |
454 if (node->cond() != NULL) Visit(node->cond()); | |
455 if (node->next() != NULL) Visit(node->next()); | |
456 Visit(node->body()); | |
457 } | |
458 | |
459 | |
460 void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) { | |
461 IncrementNodeCount(); | |
462 DisableCrankshaft(kClassLiteral); | |
463 node->set_base_id(ReserveIdRange(node->num_ids())); | |
464 if (node->extends()) Visit(node->extends()); | |
465 if (node->constructor()) Visit(node->constructor()); | |
466 if (node->class_variable_proxy()) { | |
467 VisitVariableProxy(node->class_variable_proxy()); | |
468 } | |
469 for (int i = 0; i < node->properties()->length(); i++) { | |
470 VisitObjectLiteralProperty(node->properties()->at(i)); | |
471 } | |
472 ReserveFeedbackSlots(node); | |
473 } | |
474 | |
475 | |
476 void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) { | |
477 IncrementNodeCount(); | |
478 node->set_base_id(ReserveIdRange(node->num_ids())); | |
479 for (int i = 0; i < node->properties()->length(); i++) { | |
480 VisitObjectLiteralProperty(node->properties()->at(i)); | |
481 } | |
482 node->BuildConstantProperties(isolate_); | |
483 // Mark all computed expressions that are bound to a key that | |
484 // is shadowed by a later occurrence of the same key. For the | |
485 // marked expressions, no store code will be is emitted. | |
486 node->CalculateEmitStore(zone_); | |
487 ReserveFeedbackSlots(node); | |
488 } | |
489 | |
490 | |
491 void AstNumberingVisitor::VisitObjectLiteralProperty( | |
492 ObjectLiteralProperty* node) { | |
493 if (node->is_computed_name()) DisableCrankshaft(kComputedPropertyName); | |
494 Visit(node->key()); | |
495 Visit(node->value()); | |
496 } | |
497 | |
498 | |
499 void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) { | |
500 IncrementNodeCount(); | |
501 node->set_base_id(ReserveIdRange(node->num_ids())); | |
502 for (int i = 0; i < node->values()->length(); i++) { | |
503 Visit(node->values()->at(i)); | |
504 } | |
505 node->BuildConstantElements(isolate_); | |
506 ReserveFeedbackSlots(node); | |
507 } | |
508 | |
509 | |
510 void AstNumberingVisitor::VisitCall(Call* node) { | |
511 IncrementNodeCount(); | |
512 ReserveFeedbackSlots(node); | |
513 node->set_base_id(ReserveIdRange(Call::num_ids())); | |
514 Visit(node->expression()); | |
515 VisitArguments(node->arguments()); | |
516 } | |
517 | |
518 | |
519 void AstNumberingVisitor::VisitCallNew(CallNew* node) { | |
520 IncrementNodeCount(); | |
521 ReserveFeedbackSlots(node); | |
522 node->set_base_id(ReserveIdRange(CallNew::num_ids())); | |
523 Visit(node->expression()); | |
524 VisitArguments(node->arguments()); | |
525 } | |
526 | |
527 | |
528 void AstNumberingVisitor::VisitStatements(ZoneList<Statement*>* statements) { | |
529 if (statements == NULL) return; | |
530 for (int i = 0; i < statements->length(); i++) { | |
531 Visit(statements->at(i)); | |
532 } | |
533 } | |
534 | |
535 | |
536 void AstNumberingVisitor::VisitDeclarations( | |
537 ZoneList<Declaration*>* declarations) { | |
538 for (int i = 0; i < declarations->length(); i++) { | |
539 Visit(declarations->at(i)); | |
540 } | |
541 } | |
542 | |
543 | |
544 void AstNumberingVisitor::VisitArguments(ZoneList<Expression*>* arguments) { | |
545 for (int i = 0; i < arguments->length(); i++) { | |
546 Visit(arguments->at(i)); | |
547 } | |
548 } | |
549 | |
550 | |
551 void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) { | |
552 IncrementNodeCount(); | |
553 node->set_base_id(ReserveIdRange(FunctionLiteral::num_ids())); | |
554 // We don't recurse into the declarations or body of the function literal: | |
555 // you have to separately Renumber() each FunctionLiteral that you compile. | |
556 } | |
557 | |
558 | |
559 bool AstNumberingVisitor::Finish(FunctionLiteral* node) { | |
560 node->set_ast_properties(&properties_); | |
561 node->set_dont_optimize_reason(dont_optimize_reason()); | |
562 return !HasStackOverflow(); | |
563 } | |
564 | |
565 | |
566 bool AstNumberingVisitor::Renumber(FunctionLiteral* node) { | |
567 Scope* scope = node->scope(); | |
568 | |
569 if (scope->HasIllegalRedeclaration()) { | |
570 Visit(scope->GetIllegalRedeclaration()); | |
571 DisableOptimization(kFunctionWithIllegalRedeclaration); | |
572 return Finish(node); | |
573 } | |
574 if (scope->calls_eval()) DisableOptimization(kFunctionCallsEval); | |
575 if (scope->arguments() != NULL && !scope->arguments()->IsStackAllocated()) { | |
576 DisableCrankshaft(kContextAllocatedArguments); | |
577 } | |
578 | |
579 VisitDeclarations(scope->declarations()); | |
580 VisitStatements(node->body()); | |
581 | |
582 return Finish(node); | |
583 } | |
584 | |
585 | |
586 bool AstNumbering::Renumber(Isolate* isolate, Zone* zone, | |
587 FunctionLiteral* function) { | |
588 AstNumberingVisitor visitor(isolate, zone); | |
589 return visitor.Renumber(function); | |
590 } | |
591 } // namespace internal | |
592 } // namespace v8 | |
OLD | NEW |