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/scopes.h"
15 class AstNumberingVisitor FINAL : public AstVisitor {
17 explicit AstNumberingVisitor(Isolate* isolate, Zone* zone)
19 next_id_(BailoutId::FirstUsable().ToInt()),
21 ic_slot_cache_(FLAG_vector_ics ? 4 : 0),
22 dont_optimize_reason_(kNoReason) {
23 InitializeAstVisitor(isolate, zone);
26 bool Renumber(FunctionLiteral* node);
29 // AST node visitor interface.
30 #define DEFINE_VISIT(type) virtual void Visit##type(type* node) OVERRIDE;
31 AST_NODE_LIST(DEFINE_VISIT)
34 bool Finish(FunctionLiteral* node);
36 void VisitStatements(ZoneList<Statement*>* statements) OVERRIDE;
37 void VisitDeclarations(ZoneList<Declaration*>* declarations) OVERRIDE;
38 void VisitArguments(ZoneList<Expression*>* arguments);
39 void VisitObjectLiteralProperty(ObjectLiteralProperty* property);
41 int ReserveIdRange(int n) {
47 void IncrementNodeCount() { properties_.add_node_count(1); }
48 void DisableSelfOptimization() {
49 properties_.flags()->Add(kDontSelfOptimize);
51 void DisableOptimization(BailoutReason reason) {
52 dont_optimize_reason_ = reason;
53 DisableSelfOptimization();
55 void DisableCaching(BailoutReason reason) {
56 dont_optimize_reason_ = reason;
57 DisableSelfOptimization();
58 properties_.flags()->Add(kDontCache);
61 template <typename Node>
62 void ReserveFeedbackSlots(Node* node) {
63 FeedbackVectorRequirements reqs =
64 node->ComputeFeedbackRequirements(isolate(), &ic_slot_cache_);
65 if (reqs.slots() > 0) {
66 node->SetFirstFeedbackSlot(FeedbackVectorSlot(properties_.slots()));
67 properties_.increase_slots(reqs.slots());
69 if (reqs.ic_slots() > 0) {
70 int ic_slots = properties_.ic_slots();
71 node->SetFirstFeedbackICSlot(FeedbackVectorICSlot(ic_slots),
73 properties_.increase_ic_slots(reqs.ic_slots());
74 if (FLAG_vector_ics) {
75 for (int i = 0; i < reqs.ic_slots(); i++) {
76 properties_.SetKind(ic_slots + i, node->FeedbackICSlotKind(i));
82 BailoutReason dont_optimize_reason() const { return dont_optimize_reason_; }
85 AstProperties properties_;
86 // The slot cache allows us to reuse certain vector IC slots. It's only used
87 // if FLAG_vector_ics is true.
88 ICSlotCache ic_slot_cache_;
89 BailoutReason dont_optimize_reason_;
91 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
92 DISALLOW_COPY_AND_ASSIGN(AstNumberingVisitor);
96 void AstNumberingVisitor::VisitVariableDeclaration(VariableDeclaration* node) {
98 VisitVariableProxy(node->proxy());
102 void AstNumberingVisitor::VisitExportDeclaration(ExportDeclaration* node) {
103 IncrementNodeCount();
104 DisableOptimization(kExportDeclaration);
105 VisitVariableProxy(node->proxy());
109 void AstNumberingVisitor::VisitModuleUrl(ModuleUrl* node) {
110 IncrementNodeCount();
111 DisableOptimization(kModuleUrl);
115 void AstNumberingVisitor::VisitEmptyStatement(EmptyStatement* node) {
116 IncrementNodeCount();
120 void AstNumberingVisitor::VisitContinueStatement(ContinueStatement* node) {
121 IncrementNodeCount();
125 void AstNumberingVisitor::VisitBreakStatement(BreakStatement* node) {
126 IncrementNodeCount();
130 void AstNumberingVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
131 IncrementNodeCount();
132 DisableOptimization(kDebuggerStatement);
133 node->set_base_id(ReserveIdRange(DebuggerStatement::num_ids()));
137 void AstNumberingVisitor::VisitNativeFunctionLiteral(
138 NativeFunctionLiteral* node) {
139 IncrementNodeCount();
140 DisableOptimization(kNativeFunctionLiteral);
141 node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids()));
145 void AstNumberingVisitor::VisitLiteral(Literal* node) {
146 IncrementNodeCount();
147 node->set_base_id(ReserveIdRange(Literal::num_ids()));
151 void AstNumberingVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
152 IncrementNodeCount();
153 node->set_base_id(ReserveIdRange(RegExpLiteral::num_ids()));
157 void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) {
158 IncrementNodeCount();
159 if (node->var()->IsLookupSlot()) {
160 DisableOptimization(kReferenceToAVariableWhichRequiresDynamicLookup);
162 ReserveFeedbackSlots(node);
163 node->set_base_id(ReserveIdRange(VariableProxy::num_ids()));
167 void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
168 IncrementNodeCount();
169 node->set_base_id(ReserveIdRange(ThisFunction::num_ids()));
173 void AstNumberingVisitor::VisitSuperReference(SuperReference* node) {
174 IncrementNodeCount();
175 DisableOptimization(kSuperReference);
176 ReserveFeedbackSlots(node);
177 node->set_base_id(ReserveIdRange(SuperReference::num_ids()));
178 Visit(node->this_var());
182 void AstNumberingVisitor::VisitModuleDeclaration(ModuleDeclaration* node) {
183 IncrementNodeCount();
184 DisableOptimization(kModuleDeclaration);
185 VisitVariableProxy(node->proxy());
186 Visit(node->module());
190 void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) {
191 IncrementNodeCount();
192 DisableOptimization(kImportDeclaration);
193 VisitVariableProxy(node->proxy());
197 void AstNumberingVisitor::VisitModulePath(ModulePath* node) {
198 IncrementNodeCount();
199 DisableOptimization(kModulePath);
200 Visit(node->module());
204 void AstNumberingVisitor::VisitModuleStatement(ModuleStatement* node) {
205 IncrementNodeCount();
206 DisableOptimization(kModuleStatement);
211 void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) {
212 IncrementNodeCount();
213 Visit(node->expression());
217 void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) {
218 IncrementNodeCount();
219 Visit(node->expression());
223 void AstNumberingVisitor::VisitYield(Yield* node) {
224 IncrementNodeCount();
225 DisableOptimization(kYield);
226 ReserveFeedbackSlots(node);
227 node->set_base_id(ReserveIdRange(Yield::num_ids()));
228 Visit(node->generator_object());
229 Visit(node->expression());
233 void AstNumberingVisitor::VisitThrow(Throw* node) {
234 IncrementNodeCount();
235 node->set_base_id(ReserveIdRange(Throw::num_ids()));
236 Visit(node->exception());
240 void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) {
241 IncrementNodeCount();
242 node->set_base_id(ReserveIdRange(UnaryOperation::num_ids()));
243 Visit(node->expression());
247 void AstNumberingVisitor::VisitCountOperation(CountOperation* node) {
248 IncrementNodeCount();
249 node->set_base_id(ReserveIdRange(CountOperation::num_ids()));
250 Visit(node->expression());
254 void AstNumberingVisitor::VisitBlock(Block* node) {
255 IncrementNodeCount();
256 node->set_base_id(ReserveIdRange(Block::num_ids()));
257 if (node->scope() != NULL) VisitDeclarations(node->scope()->declarations());
258 VisitStatements(node->statements());
262 void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) {
263 IncrementNodeCount();
264 VisitVariableProxy(node->proxy());
265 VisitFunctionLiteral(node->fun());
269 void AstNumberingVisitor::VisitModuleLiteral(ModuleLiteral* node) {
270 IncrementNodeCount();
271 DisableCaching(kModuleLiteral);
272 VisitBlock(node->body());
276 void AstNumberingVisitor::VisitCallRuntime(CallRuntime* node) {
277 IncrementNodeCount();
278 ReserveFeedbackSlots(node);
279 if (node->is_jsruntime()) {
280 // Don't try to optimize JS runtime calls because we bailout on them.
281 DisableOptimization(kCallToAJavaScriptRuntimeFunction);
283 node->set_base_id(ReserveIdRange(CallRuntime::num_ids()));
284 VisitArguments(node->arguments());
288 void AstNumberingVisitor::VisitWithStatement(WithStatement* node) {
289 IncrementNodeCount();
290 DisableOptimization(kWithStatement);
291 node->set_base_id(ReserveIdRange(WithStatement::num_ids()));
292 Visit(node->expression());
293 Visit(node->statement());
297 void AstNumberingVisitor::VisitDoWhileStatement(DoWhileStatement* node) {
298 IncrementNodeCount();
299 DisableSelfOptimization();
300 node->set_base_id(ReserveIdRange(DoWhileStatement::num_ids()));
306 void AstNumberingVisitor::VisitWhileStatement(WhileStatement* node) {
307 IncrementNodeCount();
308 DisableSelfOptimization();
309 node->set_base_id(ReserveIdRange(WhileStatement::num_ids()));
315 void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
316 IncrementNodeCount();
317 DisableOptimization(kTryCatchStatement);
318 Visit(node->try_block());
319 Visit(node->catch_block());
323 void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
324 IncrementNodeCount();
325 DisableOptimization(kTryFinallyStatement);
326 Visit(node->try_block());
327 Visit(node->finally_block());
331 void AstNumberingVisitor::VisitProperty(Property* node) {
332 IncrementNodeCount();
333 ReserveFeedbackSlots(node);
334 node->set_base_id(ReserveIdRange(Property::num_ids()));
340 void AstNumberingVisitor::VisitAssignment(Assignment* node) {
341 IncrementNodeCount();
342 node->set_base_id(ReserveIdRange(Assignment::num_ids()));
343 if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
344 Visit(node->target());
345 Visit(node->value());
349 void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
350 IncrementNodeCount();
351 node->set_base_id(ReserveIdRange(BinaryOperation::num_ids()));
353 Visit(node->right());
357 void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
358 IncrementNodeCount();
359 node->set_base_id(ReserveIdRange(CompareOperation::num_ids()));
361 Visit(node->right());
365 void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
366 IncrementNodeCount();
367 DisableSelfOptimization();
368 ReserveFeedbackSlots(node);
369 node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
371 Visit(node->enumerable());
376 void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
377 IncrementNodeCount();
378 DisableOptimization(kForOfStatement);
379 node->set_base_id(ReserveIdRange(ForOfStatement::num_ids()));
380 Visit(node->assign_iterator());
381 Visit(node->next_result());
382 Visit(node->result_done());
383 Visit(node->assign_each());
388 void AstNumberingVisitor::VisitConditional(Conditional* node) {
389 IncrementNodeCount();
390 node->set_base_id(ReserveIdRange(Conditional::num_ids()));
391 Visit(node->condition());
392 Visit(node->then_expression());
393 Visit(node->else_expression());
397 void AstNumberingVisitor::VisitIfStatement(IfStatement* node) {
398 IncrementNodeCount();
399 node->set_base_id(ReserveIdRange(IfStatement::num_ids()));
400 Visit(node->condition());
401 Visit(node->then_statement());
402 if (node->HasElseStatement()) {
403 Visit(node->else_statement());
408 void AstNumberingVisitor::VisitSwitchStatement(SwitchStatement* node) {
409 IncrementNodeCount();
410 node->set_base_id(ReserveIdRange(SwitchStatement::num_ids()));
412 ZoneList<CaseClause*>* cases = node->cases();
413 for (int i = 0; i < cases->length(); i++) {
414 VisitCaseClause(cases->at(i));
419 void AstNumberingVisitor::VisitCaseClause(CaseClause* node) {
420 IncrementNodeCount();
421 node->set_base_id(ReserveIdRange(CaseClause::num_ids()));
422 if (!node->is_default()) Visit(node->label());
423 VisitStatements(node->statements());
427 void AstNumberingVisitor::VisitForStatement(ForStatement* node) {
428 IncrementNodeCount();
429 DisableSelfOptimization();
430 node->set_base_id(ReserveIdRange(ForStatement::num_ids()));
431 if (node->init() != NULL) Visit(node->init());
432 if (node->cond() != NULL) Visit(node->cond());
433 if (node->next() != NULL) Visit(node->next());
438 void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
439 IncrementNodeCount();
440 DisableOptimization(kClassLiteral);
441 node->set_base_id(ReserveIdRange(node->num_ids()));
442 if (node->extends()) Visit(node->extends());
443 if (node->constructor()) Visit(node->constructor());
444 if (node->class_variable_proxy()) {
445 VisitVariableProxy(node->class_variable_proxy());
447 for (int i = 0; i < node->properties()->length(); i++) {
448 VisitObjectLiteralProperty(node->properties()->at(i));
453 void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
454 IncrementNodeCount();
455 node->set_base_id(ReserveIdRange(node->num_ids()));
456 for (int i = 0; i < node->properties()->length(); i++) {
457 VisitObjectLiteralProperty(node->properties()->at(i));
462 void AstNumberingVisitor::VisitObjectLiteralProperty(
463 ObjectLiteralProperty* node) {
464 if (node->is_computed_name()) DisableOptimization(kComputedPropertyName);
466 Visit(node->value());
470 void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
471 IncrementNodeCount();
472 node->set_base_id(ReserveIdRange(node->num_ids()));
473 for (int i = 0; i < node->values()->length(); i++) {
474 Visit(node->values()->at(i));
479 void AstNumberingVisitor::VisitCall(Call* node) {
480 IncrementNodeCount();
481 ReserveFeedbackSlots(node);
482 node->set_base_id(ReserveIdRange(Call::num_ids()));
483 Visit(node->expression());
484 VisitArguments(node->arguments());
488 void AstNumberingVisitor::VisitCallNew(CallNew* node) {
489 IncrementNodeCount();
490 ReserveFeedbackSlots(node);
491 node->set_base_id(ReserveIdRange(CallNew::num_ids()));
492 Visit(node->expression());
493 VisitArguments(node->arguments());
497 void AstNumberingVisitor::VisitStatements(ZoneList<Statement*>* statements) {
498 if (statements == NULL) return;
499 for (int i = 0; i < statements->length(); i++) {
500 Visit(statements->at(i));
505 void AstNumberingVisitor::VisitDeclarations(
506 ZoneList<Declaration*>* declarations) {
507 for (int i = 0; i < declarations->length(); i++) {
508 Visit(declarations->at(i));
513 void AstNumberingVisitor::VisitArguments(ZoneList<Expression*>* arguments) {
514 for (int i = 0; i < arguments->length(); i++) {
515 Visit(arguments->at(i));
520 void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
521 IncrementNodeCount();
522 node->set_base_id(ReserveIdRange(FunctionLiteral::num_ids()));
523 // We don't recurse into the declarations or body of the function literal:
524 // you have to separately Renumber() each FunctionLiteral that you compile.
528 bool AstNumberingVisitor::Finish(FunctionLiteral* node) {
529 node->set_ast_properties(&properties_);
530 node->set_dont_optimize_reason(dont_optimize_reason());
531 return !HasStackOverflow();
535 bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
536 Scope* scope = node->scope();
538 if (scope->HasIllegalRedeclaration()) {
539 scope->VisitIllegalRedeclaration(this);
540 DisableOptimization(kFunctionWithIllegalRedeclaration);
543 if (scope->calls_eval()) DisableOptimization(kFunctionCallsEval);
544 if (scope->arguments() != NULL && !scope->arguments()->IsStackAllocated()) {
545 DisableOptimization(kContextAllocatedArguments);
548 VisitDeclarations(scope->declarations());
549 if (scope->is_function_scope() && scope->function() != NULL) {
550 // Visit the name of the named function expression.
551 Visit(scope->function());
553 VisitStatements(node->body());
559 bool AstNumbering::Renumber(Isolate* isolate, Zone* zone,
560 FunctionLiteral* function) {
561 AstNumberingVisitor visitor(isolate, zone);
562 return visitor.Renumber(function);
565 } // namespace v8::internal