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.
8 #include "src/ast-numbering.h"
9 #include "src/compiler.h"
10 #include "src/scopes.h"
16 class AstNumberingVisitor FINAL : public AstVisitor {
18 explicit AstNumberingVisitor(Isolate* isolate, Zone* zone)
20 next_id_(BailoutId::FirstUsable().ToInt()),
21 dont_optimize_reason_(kNoReason) {
22 InitializeAstVisitor(isolate, zone);
25 bool Renumber(FunctionLiteral* node);
28 // AST node visitor interface.
29 #define DEFINE_VISIT(type) virtual void Visit##type(type* node) OVERRIDE;
30 AST_NODE_LIST(DEFINE_VISIT)
33 bool Finish(FunctionLiteral* node);
35 void VisitStatements(ZoneList<Statement*>* statements) OVERRIDE;
36 void VisitDeclarations(ZoneList<Declaration*>* declarations) OVERRIDE;
37 void VisitArguments(ZoneList<Expression*>* arguments);
38 void VisitObjectLiteralProperty(ObjectLiteralProperty* property);
40 int ReserveIdRange(int n) {
46 void IncrementNodeCount() { properties_.add_node_count(1); }
47 void DisableSelfOptimization() {
48 properties_.flags()->Add(kDontSelfOptimize);
50 void DisableOptimization(BailoutReason reason) {
51 dont_optimize_reason_ = reason;
52 DisableSelfOptimization();
54 void DisableCaching(BailoutReason reason) {
55 dont_optimize_reason_ = reason;
56 DisableSelfOptimization();
57 properties_.flags()->Add(kDontCache);
60 template <typename Node>
61 void ReserveFeedbackSlots(Node* node) {
62 FeedbackVectorRequirements reqs =
63 node->ComputeFeedbackRequirements(isolate());
64 if (reqs.slots() > 0) {
65 node->SetFirstFeedbackSlot(FeedbackVectorSlot(properties_.slots()));
66 properties_.increase_slots(reqs.slots());
68 if (reqs.ic_slots() > 0) {
69 int ic_slots = properties_.ic_slots();
70 node->SetFirstFeedbackICSlot(FeedbackVectorICSlot(ic_slots));
71 properties_.increase_ic_slots(reqs.ic_slots());
72 if (FLAG_vector_ics) {
73 for (int i = 0; i < reqs.ic_slots(); i++) {
74 properties_.SetKind(ic_slots + i, node->FeedbackICSlotKind(i));
80 BailoutReason dont_optimize_reason() const { return dont_optimize_reason_; }
83 AstProperties properties_;
84 BailoutReason dont_optimize_reason_;
86 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
87 DISALLOW_COPY_AND_ASSIGN(AstNumberingVisitor);
91 void AstNumberingVisitor::VisitVariableDeclaration(VariableDeclaration* node) {
93 VisitVariableProxy(node->proxy());
97 void AstNumberingVisitor::VisitExportDeclaration(ExportDeclaration* node) {
99 DisableOptimization(kExportDeclaration);
100 VisitVariableProxy(node->proxy());
104 void AstNumberingVisitor::VisitModuleUrl(ModuleUrl* node) {
105 IncrementNodeCount();
106 DisableOptimization(kModuleUrl);
110 void AstNumberingVisitor::VisitEmptyStatement(EmptyStatement* node) {
111 IncrementNodeCount();
115 void AstNumberingVisitor::VisitContinueStatement(ContinueStatement* node) {
116 IncrementNodeCount();
120 void AstNumberingVisitor::VisitBreakStatement(BreakStatement* node) {
121 IncrementNodeCount();
125 void AstNumberingVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
126 IncrementNodeCount();
127 DisableOptimization(kDebuggerStatement);
128 node->set_base_id(ReserveIdRange(DebuggerStatement::num_ids()));
132 void AstNumberingVisitor::VisitNativeFunctionLiteral(
133 NativeFunctionLiteral* node) {
134 IncrementNodeCount();
135 DisableOptimization(kNativeFunctionLiteral);
136 node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids()));
140 void AstNumberingVisitor::VisitLiteral(Literal* node) {
141 IncrementNodeCount();
142 node->set_base_id(ReserveIdRange(Literal::num_ids()));
146 void AstNumberingVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
147 IncrementNodeCount();
148 node->set_base_id(ReserveIdRange(RegExpLiteral::num_ids()));
152 void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) {
153 IncrementNodeCount();
154 if (node->var()->IsLookupSlot()) {
155 DisableOptimization(kReferenceToAVariableWhichRequiresDynamicLookup);
157 ReserveFeedbackSlots(node);
158 node->set_base_id(ReserveIdRange(VariableProxy::num_ids()));
162 void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
163 IncrementNodeCount();
164 node->set_base_id(ReserveIdRange(ThisFunction::num_ids()));
168 void AstNumberingVisitor::VisitSuperReference(SuperReference* node) {
169 IncrementNodeCount();
170 DisableOptimization(kSuperReference);
171 ReserveFeedbackSlots(node);
172 node->set_base_id(ReserveIdRange(SuperReference::num_ids()));
173 Visit(node->this_var());
177 void AstNumberingVisitor::VisitModuleDeclaration(ModuleDeclaration* node) {
178 IncrementNodeCount();
179 DisableOptimization(kModuleDeclaration);
180 VisitVariableProxy(node->proxy());
181 Visit(node->module());
185 void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) {
186 IncrementNodeCount();
187 DisableOptimization(kImportDeclaration);
188 VisitVariableProxy(node->proxy());
189 Visit(node->module());
193 void AstNumberingVisitor::VisitModulePath(ModulePath* node) {
194 IncrementNodeCount();
195 DisableOptimization(kModulePath);
196 Visit(node->module());
200 void AstNumberingVisitor::VisitModuleStatement(ModuleStatement* node) {
201 IncrementNodeCount();
202 DisableOptimization(kModuleStatement);
207 void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) {
208 IncrementNodeCount();
209 Visit(node->expression());
213 void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) {
214 IncrementNodeCount();
215 Visit(node->expression());
219 void AstNumberingVisitor::VisitYield(Yield* node) {
220 IncrementNodeCount();
221 DisableOptimization(kYield);
222 ReserveFeedbackSlots(node);
223 node->set_base_id(ReserveIdRange(Yield::num_ids()));
224 Visit(node->generator_object());
225 Visit(node->expression());
229 void AstNumberingVisitor::VisitThrow(Throw* node) {
230 IncrementNodeCount();
231 node->set_base_id(ReserveIdRange(Throw::num_ids()));
232 Visit(node->exception());
236 void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) {
237 IncrementNodeCount();
238 node->set_base_id(ReserveIdRange(UnaryOperation::num_ids()));
239 Visit(node->expression());
243 void AstNumberingVisitor::VisitCountOperation(CountOperation* node) {
244 IncrementNodeCount();
245 node->set_base_id(ReserveIdRange(CountOperation::num_ids()));
246 Visit(node->expression());
250 void AstNumberingVisitor::VisitBlock(Block* node) {
251 IncrementNodeCount();
252 node->set_base_id(ReserveIdRange(Block::num_ids()));
253 if (node->scope() != NULL) VisitDeclarations(node->scope()->declarations());
254 VisitStatements(node->statements());
258 void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) {
259 IncrementNodeCount();
260 VisitVariableProxy(node->proxy());
261 VisitFunctionLiteral(node->fun());
265 void AstNumberingVisitor::VisitModuleLiteral(ModuleLiteral* node) {
266 IncrementNodeCount();
267 DisableCaching(kModuleLiteral);
268 VisitBlock(node->body());
272 void AstNumberingVisitor::VisitCallRuntime(CallRuntime* node) {
273 IncrementNodeCount();
274 ReserveFeedbackSlots(node);
275 if (node->is_jsruntime()) {
276 // Don't try to optimize JS runtime calls because we bailout on them.
277 DisableOptimization(kCallToAJavaScriptRuntimeFunction);
279 node->set_base_id(ReserveIdRange(CallRuntime::num_ids()));
280 VisitArguments(node->arguments());
284 void AstNumberingVisitor::VisitWithStatement(WithStatement* node) {
285 IncrementNodeCount();
286 DisableOptimization(kWithStatement);
287 node->set_base_id(ReserveIdRange(WithStatement::num_ids()));
288 Visit(node->expression());
289 Visit(node->statement());
293 void AstNumberingVisitor::VisitDoWhileStatement(DoWhileStatement* node) {
294 IncrementNodeCount();
295 DisableSelfOptimization();
296 node->set_base_id(ReserveIdRange(DoWhileStatement::num_ids()));
302 void AstNumberingVisitor::VisitWhileStatement(WhileStatement* node) {
303 IncrementNodeCount();
304 DisableSelfOptimization();
305 node->set_base_id(ReserveIdRange(WhileStatement::num_ids()));
311 void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
312 IncrementNodeCount();
313 DisableOptimization(kTryCatchStatement);
314 Visit(node->try_block());
315 Visit(node->catch_block());
319 void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
320 IncrementNodeCount();
321 DisableOptimization(kTryFinallyStatement);
322 Visit(node->try_block());
323 Visit(node->finally_block());
327 void AstNumberingVisitor::VisitProperty(Property* node) {
328 IncrementNodeCount();
329 ReserveFeedbackSlots(node);
330 node->set_base_id(ReserveIdRange(Property::num_ids()));
336 void AstNumberingVisitor::VisitAssignment(Assignment* node) {
337 IncrementNodeCount();
338 node->set_base_id(ReserveIdRange(Assignment::num_ids()));
339 if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
340 Visit(node->target());
341 Visit(node->value());
345 void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
346 IncrementNodeCount();
347 node->set_base_id(ReserveIdRange(BinaryOperation::num_ids()));
349 Visit(node->right());
353 void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
354 IncrementNodeCount();
355 node->set_base_id(ReserveIdRange(CompareOperation::num_ids()));
357 Visit(node->right());
361 void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
362 IncrementNodeCount();
363 DisableSelfOptimization();
364 ReserveFeedbackSlots(node);
365 node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
367 Visit(node->enumerable());
372 void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
373 IncrementNodeCount();
374 DisableOptimization(kForOfStatement);
375 node->set_base_id(ReserveIdRange(ForOfStatement::num_ids()));
376 Visit(node->assign_iterator());
377 Visit(node->next_result());
378 Visit(node->result_done());
379 Visit(node->assign_each());
384 void AstNumberingVisitor::VisitConditional(Conditional* node) {
385 IncrementNodeCount();
386 node->set_base_id(ReserveIdRange(Conditional::num_ids()));
387 Visit(node->condition());
388 Visit(node->then_expression());
389 Visit(node->else_expression());
393 void AstNumberingVisitor::VisitIfStatement(IfStatement* node) {
394 IncrementNodeCount();
395 node->set_base_id(ReserveIdRange(IfStatement::num_ids()));
396 Visit(node->condition());
397 Visit(node->then_statement());
398 if (node->HasElseStatement()) {
399 Visit(node->else_statement());
404 void AstNumberingVisitor::VisitSwitchStatement(SwitchStatement* node) {
405 IncrementNodeCount();
406 node->set_base_id(ReserveIdRange(SwitchStatement::num_ids()));
408 ZoneList<CaseClause*>* cases = node->cases();
409 for (int i = 0; i < cases->length(); i++) {
410 VisitCaseClause(cases->at(i));
415 void AstNumberingVisitor::VisitCaseClause(CaseClause* node) {
416 IncrementNodeCount();
417 node->set_base_id(ReserveIdRange(CaseClause::num_ids()));
418 if (!node->is_default()) Visit(node->label());
419 VisitStatements(node->statements());
423 void AstNumberingVisitor::VisitForStatement(ForStatement* node) {
424 IncrementNodeCount();
425 DisableSelfOptimization();
426 node->set_base_id(ReserveIdRange(ForStatement::num_ids()));
427 if (node->init() != NULL) Visit(node->init());
428 if (node->cond() != NULL) Visit(node->cond());
429 if (node->next() != NULL) Visit(node->next());
434 void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
435 IncrementNodeCount();
436 DisableOptimization(kClassLiteral);
437 node->set_base_id(ReserveIdRange(node->num_ids()));
438 if (node->extends()) Visit(node->extends());
439 if (node->constructor()) Visit(node->constructor());
440 if (node->class_variable_proxy()) {
441 VisitVariableProxy(node->class_variable_proxy());
443 for (int i = 0; i < node->properties()->length(); i++) {
444 VisitObjectLiteralProperty(node->properties()->at(i));
449 void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
450 IncrementNodeCount();
451 node->set_base_id(ReserveIdRange(node->num_ids()));
452 for (int i = 0; i < node->properties()->length(); i++) {
453 VisitObjectLiteralProperty(node->properties()->at(i));
458 void AstNumberingVisitor::VisitObjectLiteralProperty(
459 ObjectLiteralProperty* node) {
460 if (node->is_computed_name()) DisableOptimization(kComputedPropertyName);
462 Visit(node->value());
466 void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
467 IncrementNodeCount();
468 node->set_base_id(ReserveIdRange(node->num_ids()));
469 for (int i = 0; i < node->values()->length(); i++) {
470 Visit(node->values()->at(i));
475 void AstNumberingVisitor::VisitCall(Call* node) {
476 IncrementNodeCount();
477 ReserveFeedbackSlots(node);
478 node->set_base_id(ReserveIdRange(Call::num_ids()));
479 Visit(node->expression());
480 VisitArguments(node->arguments());
484 void AstNumberingVisitor::VisitCallNew(CallNew* node) {
485 IncrementNodeCount();
486 ReserveFeedbackSlots(node);
487 node->set_base_id(ReserveIdRange(CallNew::num_ids()));
488 Visit(node->expression());
489 VisitArguments(node->arguments());
493 void AstNumberingVisitor::VisitStatements(ZoneList<Statement*>* statements) {
494 if (statements == NULL) return;
495 for (int i = 0; i < statements->length(); i++) {
496 Visit(statements->at(i));
501 void AstNumberingVisitor::VisitDeclarations(
502 ZoneList<Declaration*>* declarations) {
503 for (int i = 0; i < declarations->length(); i++) {
504 Visit(declarations->at(i));
509 void AstNumberingVisitor::VisitArguments(ZoneList<Expression*>* arguments) {
510 for (int i = 0; i < arguments->length(); i++) {
511 Visit(arguments->at(i));
516 void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
517 IncrementNodeCount();
518 node->set_base_id(ReserveIdRange(FunctionLiteral::num_ids()));
519 // We don't recurse into the declarations or body of the function literal:
520 // you have to separately Renumber() each FunctionLiteral that you compile.
524 bool AstNumberingVisitor::Finish(FunctionLiteral* node) {
525 node->set_ast_properties(&properties_);
526 node->set_dont_optimize_reason(dont_optimize_reason());
527 return !HasStackOverflow();
531 bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
532 Scope* scope = node->scope();
534 if (scope->HasIllegalRedeclaration()) {
535 scope->VisitIllegalRedeclaration(this);
536 DisableOptimization(kFunctionWithIllegalRedeclaration);
539 if (scope->calls_eval()) DisableOptimization(kFunctionCallsEval);
540 if (scope->arguments() != NULL && !scope->arguments()->IsStackAllocated()) {
541 DisableOptimization(kContextAllocatedArguments);
544 VisitDeclarations(scope->declarations());
545 if (scope->is_function_scope() && scope->function() != NULL) {
546 // Visit the name of the named function expression.
547 Visit(scope->function());
549 VisitStatements(node->body());
555 bool AstNumbering::Renumber(Isolate* isolate, Zone* zone,
556 FunctionLiteral* function) {
557 AstNumberingVisitor visitor(isolate, zone);
558 return visitor.Renumber(function);
561 } // namespace v8::internal