ast-numbering.cc 15.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/v8.h"

#include "src/ast.h"
#include "src/ast-numbering.h"
#include "src/scopes.h"

namespace v8 {
namespace internal {


15
class AstNumberingVisitor final : public AstVisitor {
16
 public:
17
  explicit AstNumberingVisitor(Isolate* isolate, Zone* zone)
18 19
      : AstVisitor(),
        next_id_(BailoutId::FirstUsable().ToInt()),
20
        properties_(zone),
21
        ic_slot_cache_(4),
22
        dont_optimize_reason_(kNoReason) {
23
    InitializeAstVisitor(isolate, zone);
24 25
  }

26
  bool Renumber(FunctionLiteral* node);
27 28 29

 private:
// AST node visitor interface.
30
#define DEFINE_VISIT(type) virtual void Visit##type(type* node) override;
31 32 33
  AST_NODE_LIST(DEFINE_VISIT)
#undef DEFINE_VISIT

34 35
  bool Finish(FunctionLiteral* node);

36 37
  void VisitStatements(ZoneList<Statement*>* statements) override;
  void VisitDeclarations(ZoneList<Declaration*>* declarations) override;
38 39 40 41 42 43 44 45 46
  void VisitArguments(ZoneList<Expression*>* arguments);
  void VisitObjectLiteralProperty(ObjectLiteralProperty* property);

  int ReserveIdRange(int n) {
    int tmp = next_id_;
    next_id_ += n;
    return tmp;
  }

47
  void IncrementNodeCount() { properties_.add_node_count(1); }
48 49
  void DisableSelfOptimization() {
    properties_.flags()->Add(kDontSelfOptimize);
50
  }
51 52 53 54
  void DisableOptimization(BailoutReason reason) {
    dont_optimize_reason_ = reason;
    DisableSelfOptimization();
  }
55 56 57 58 59 60 61
  void DisableCrankshaft(BailoutReason reason) {
    if (FLAG_turbo_shipping) {
      return properties_.flags()->Add(kDontCrankshaft);
    }
    dont_optimize_reason_ = reason;
    DisableSelfOptimization();
  }
62
  void DisableCaching(BailoutReason reason) {
63
    dont_optimize_reason_ = reason;
64
    DisableSelfOptimization();
65 66 67
    properties_.flags()->Add(kDontCache);
  }

68 69
  template <typename Node>
  void ReserveFeedbackSlots(Node* node) {
70
    FeedbackVectorRequirements reqs =
71
        node->ComputeFeedbackRequirements(isolate(), &ic_slot_cache_);
72
    if (reqs.slots() > 0) {
73 74
      node->SetFirstFeedbackSlot(FeedbackVectorSlot(properties_.slots()));
      properties_.increase_slots(reqs.slots());
75 76
    }
    if (reqs.ic_slots() > 0) {
77
      int ic_slots = properties_.ic_slots();
78 79
      node->SetFirstFeedbackICSlot(FeedbackVectorICSlot(ic_slots),
                                   &ic_slot_cache_);
80
      properties_.increase_ic_slots(reqs.ic_slots());
81 82
      for (int i = 0; i < reqs.ic_slots(); i++) {
        properties_.SetKind(ic_slots + i, node->FeedbackICSlotKind(i));
83
      }
84 85 86
    }
  }

87
  BailoutReason dont_optimize_reason() const { return dont_optimize_reason_; }
88

89
  int next_id_;
90
  AstProperties properties_;
91
  // The slot cache allows us to reuse certain vector IC slots.
92
  ICSlotCache ic_slot_cache_;
93
  BailoutReason dont_optimize_reason_;
94 95 96 97 98 99 100

  DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
  DISALLOW_COPY_AND_ASSIGN(AstNumberingVisitor);
};


void AstNumberingVisitor::VisitVariableDeclaration(VariableDeclaration* node) {
101
  IncrementNodeCount();
102 103 104 105 106
  VisitVariableProxy(node->proxy());
}


void AstNumberingVisitor::VisitExportDeclaration(ExportDeclaration* node) {
107
  IncrementNodeCount();
108
  DisableOptimization(kExportDeclaration);
109 110 111 112
  VisitVariableProxy(node->proxy());
}


113 114 115
void AstNumberingVisitor::VisitEmptyStatement(EmptyStatement* node) {
  IncrementNodeCount();
}
116 117


118 119 120
void AstNumberingVisitor::VisitContinueStatement(ContinueStatement* node) {
  IncrementNodeCount();
}
121 122


123 124 125
void AstNumberingVisitor::VisitBreakStatement(BreakStatement* node) {
  IncrementNodeCount();
}
126 127 128


void AstNumberingVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
129
  IncrementNodeCount();
130
  DisableOptimization(kDebuggerStatement);
131 132 133 134 135 136
  node->set_base_id(ReserveIdRange(DebuggerStatement::num_ids()));
}


void AstNumberingVisitor::VisitNativeFunctionLiteral(
    NativeFunctionLiteral* node) {
137
  IncrementNodeCount();
138
  DisableOptimization(kNativeFunctionLiteral);
139 140 141 142 143
  node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids()));
}


void AstNumberingVisitor::VisitLiteral(Literal* node) {
144
  IncrementNodeCount();
145 146 147 148 149
  node->set_base_id(ReserveIdRange(Literal::num_ids()));
}


void AstNumberingVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
150
  IncrementNodeCount();
151 152 153 154 155
  node->set_base_id(ReserveIdRange(RegExpLiteral::num_ids()));
}


void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) {
156
  IncrementNodeCount();
157
  if (node->var()->IsLookupSlot()) {
158
    DisableCrankshaft(kReferenceToAVariableWhichRequiresDynamicLookup);
159
  }
160
  ReserveFeedbackSlots(node);
161 162 163 164 165
  node->set_base_id(ReserveIdRange(VariableProxy::num_ids()));
}


void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
166
  IncrementNodeCount();
167 168 169 170
  node->set_base_id(ReserveIdRange(ThisFunction::num_ids()));
}


171 172
void AstNumberingVisitor::VisitSuperPropertyReference(
    SuperPropertyReference* node) {
173
  IncrementNodeCount();
174
  DisableOptimization(kSuperReference);
175
  node->set_base_id(ReserveIdRange(SuperPropertyReference::num_ids()));
176
  Visit(node->this_var());
177
  Visit(node->home_object());
178 179 180
}


181 182 183 184 185 186 187 188 189 190
void AstNumberingVisitor::VisitSuperCallReference(SuperCallReference* node) {
  IncrementNodeCount();
  DisableOptimization(kSuperReference);
  node->set_base_id(ReserveIdRange(SuperCallReference::num_ids()));
  Visit(node->this_var());
  Visit(node->new_target_var());
  Visit(node->this_function_var());
}


191
void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) {
192
  IncrementNodeCount();
193
  DisableOptimization(kImportDeclaration);
194 195 196 197 198
  VisitVariableProxy(node->proxy());
}


void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) {
199
  IncrementNodeCount();
200 201 202 203 204
  Visit(node->expression());
}


void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) {
205
  IncrementNodeCount();
206 207 208 209 210
  Visit(node->expression());
}


void AstNumberingVisitor::VisitYield(Yield* node) {
211
  IncrementNodeCount();
212
  DisableOptimization(kYield);
213
  ReserveFeedbackSlots(node);
214 215 216 217 218 219 220
  node->set_base_id(ReserveIdRange(Yield::num_ids()));
  Visit(node->generator_object());
  Visit(node->expression());
}


void AstNumberingVisitor::VisitThrow(Throw* node) {
221
  IncrementNodeCount();
222 223 224 225 226 227
  node->set_base_id(ReserveIdRange(Throw::num_ids()));
  Visit(node->exception());
}


void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) {
228
  IncrementNodeCount();
229 230 231 232 233 234
  node->set_base_id(ReserveIdRange(UnaryOperation::num_ids()));
  Visit(node->expression());
}


void AstNumberingVisitor::VisitCountOperation(CountOperation* node) {
235
  IncrementNodeCount();
236 237
  node->set_base_id(ReserveIdRange(CountOperation::num_ids()));
  Visit(node->expression());
238
  ReserveFeedbackSlots(node);
239 240 241 242
}


void AstNumberingVisitor::VisitBlock(Block* node) {
243
  IncrementNodeCount();
244 245 246 247 248 249 250
  node->set_base_id(ReserveIdRange(Block::num_ids()));
  if (node->scope() != NULL) VisitDeclarations(node->scope()->declarations());
  VisitStatements(node->statements());
}


void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) {
251
  IncrementNodeCount();
252 253 254 255 256 257
  VisitVariableProxy(node->proxy());
  VisitFunctionLiteral(node->fun());
}


void AstNumberingVisitor::VisitCallRuntime(CallRuntime* node) {
258
  IncrementNodeCount();
259
  ReserveFeedbackSlots(node);
260 261
  if (node->is_jsruntime()) {
    // Don't try to optimize JS runtime calls because we bailout on them.
262
    DisableOptimization(kCallToAJavaScriptRuntimeFunction);
263
  }
264 265 266 267 268 269
  node->set_base_id(ReserveIdRange(CallRuntime::num_ids()));
  VisitArguments(node->arguments());
}


void AstNumberingVisitor::VisitWithStatement(WithStatement* node) {
270
  IncrementNodeCount();
271
  DisableCrankshaft(kWithStatement);
272
  node->set_base_id(ReserveIdRange(WithStatement::num_ids()));
273 274 275 276 277 278
  Visit(node->expression());
  Visit(node->statement());
}


void AstNumberingVisitor::VisitDoWhileStatement(DoWhileStatement* node) {
279
  IncrementNodeCount();
280
  DisableSelfOptimization();
281 282 283 284 285 286 287
  node->set_base_id(ReserveIdRange(DoWhileStatement::num_ids()));
  Visit(node->body());
  Visit(node->cond());
}


void AstNumberingVisitor::VisitWhileStatement(WhileStatement* node) {
288
  IncrementNodeCount();
289
  DisableSelfOptimization();
290 291 292 293 294 295 296
  node->set_base_id(ReserveIdRange(WhileStatement::num_ids()));
  Visit(node->cond());
  Visit(node->body());
}


void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
297
  IncrementNodeCount();
298
  DisableOptimization(kTryCatchStatement);
299 300 301 302 303 304
  Visit(node->try_block());
  Visit(node->catch_block());
}


void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
305
  IncrementNodeCount();
306
  DisableOptimization(kTryFinallyStatement);
307 308 309 310 311 312
  Visit(node->try_block());
  Visit(node->finally_block());
}


void AstNumberingVisitor::VisitProperty(Property* node) {
313
  IncrementNodeCount();
314
  ReserveFeedbackSlots(node);
315 316 317 318 319 320 321
  node->set_base_id(ReserveIdRange(Property::num_ids()));
  Visit(node->key());
  Visit(node->obj());
}


void AstNumberingVisitor::VisitAssignment(Assignment* node) {
322
  IncrementNodeCount();
323 324 325 326
  node->set_base_id(ReserveIdRange(Assignment::num_ids()));
  if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
  Visit(node->target());
  Visit(node->value());
327
  ReserveFeedbackSlots(node);
328 329 330 331
}


void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
332
  IncrementNodeCount();
333 334 335 336 337 338 339
  node->set_base_id(ReserveIdRange(BinaryOperation::num_ids()));
  Visit(node->left());
  Visit(node->right());
}


void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
340
  IncrementNodeCount();
341 342 343 344 345 346
  node->set_base_id(ReserveIdRange(CompareOperation::num_ids()));
  Visit(node->left());
  Visit(node->right());
}


arv's avatar
arv committed
347 348 349 350 351
void AstNumberingVisitor::VisitSpread(Spread* node) {
  IncrementNodeCount();
  DisableOptimization(kSpread);
  Visit(node->expression());
}
352 353


354
void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
355
  IncrementNodeCount();
356
  DisableSelfOptimization();
357 358 359 360
  node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
  Visit(node->each());
  Visit(node->enumerable());
  Visit(node->body());
361
  ReserveFeedbackSlots(node);
362 363 364 365
}


void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
366
  IncrementNodeCount();
367
  DisableCrankshaft(kForOfStatement);
368 369 370 371 372 373
  node->set_base_id(ReserveIdRange(ForOfStatement::num_ids()));
  Visit(node->assign_iterator());
  Visit(node->next_result());
  Visit(node->result_done());
  Visit(node->assign_each());
  Visit(node->body());
374
  ReserveFeedbackSlots(node);
375 376 377 378
}


void AstNumberingVisitor::VisitConditional(Conditional* node) {
379
  IncrementNodeCount();
380 381 382 383 384 385 386 387
  node->set_base_id(ReserveIdRange(Conditional::num_ids()));
  Visit(node->condition());
  Visit(node->then_expression());
  Visit(node->else_expression());
}


void AstNumberingVisitor::VisitIfStatement(IfStatement* node) {
388
  IncrementNodeCount();
389 390 391 392 393 394 395 396 397 398
  node->set_base_id(ReserveIdRange(IfStatement::num_ids()));
  Visit(node->condition());
  Visit(node->then_statement());
  if (node->HasElseStatement()) {
    Visit(node->else_statement());
  }
}


void AstNumberingVisitor::VisitSwitchStatement(SwitchStatement* node) {
399
  IncrementNodeCount();
400 401 402 403 404 405 406 407 408 409
  node->set_base_id(ReserveIdRange(SwitchStatement::num_ids()));
  Visit(node->tag());
  ZoneList<CaseClause*>* cases = node->cases();
  for (int i = 0; i < cases->length(); i++) {
    VisitCaseClause(cases->at(i));
  }
}


void AstNumberingVisitor::VisitCaseClause(CaseClause* node) {
410
  IncrementNodeCount();
411 412 413 414 415 416 417
  node->set_base_id(ReserveIdRange(CaseClause::num_ids()));
  if (!node->is_default()) Visit(node->label());
  VisitStatements(node->statements());
}


void AstNumberingVisitor::VisitForStatement(ForStatement* node) {
418
  IncrementNodeCount();
419
  DisableSelfOptimization();
420 421 422 423 424 425 426 427 428
  node->set_base_id(ReserveIdRange(ForStatement::num_ids()));
  if (node->init() != NULL) Visit(node->init());
  if (node->cond() != NULL) Visit(node->cond());
  if (node->next() != NULL) Visit(node->next());
  Visit(node->body());
}


void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
429
  IncrementNodeCount();
430
  DisableCrankshaft(kClassLiteral);
431
  node->set_base_id(ReserveIdRange(node->num_ids()));
432 433
  if (node->extends()) Visit(node->extends());
  if (node->constructor()) Visit(node->constructor());
434 435 436
  if (node->class_variable_proxy()) {
    VisitVariableProxy(node->class_variable_proxy());
  }
437 438 439
  for (int i = 0; i < node->properties()->length(); i++) {
    VisitObjectLiteralProperty(node->properties()->at(i));
  }
440
  ReserveFeedbackSlots(node);
441 442 443 444
}


void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
445
  IncrementNodeCount();
446
  node->set_base_id(ReserveIdRange(node->num_ids()));
447 448 449
  for (int i = 0; i < node->properties()->length(); i++) {
    VisitObjectLiteralProperty(node->properties()->at(i));
  }
450
  node->BuildConstantProperties(isolate());
451 452 453 454
  // Mark all computed expressions that are bound to a key that
  // is shadowed by a later occurrence of the same key. For the
  // marked expressions, no store code will be is emitted.
  node->CalculateEmitStore(zone());
455
  ReserveFeedbackSlots(node);
456 457 458 459 460
}


void AstNumberingVisitor::VisitObjectLiteralProperty(
    ObjectLiteralProperty* node) {
461
  if (node->is_computed_name()) DisableCrankshaft(kComputedPropertyName);
462 463 464 465 466 467
  Visit(node->key());
  Visit(node->value());
}


void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
468
  IncrementNodeCount();
469 470 471 472 473 474 475 476
  node->set_base_id(ReserveIdRange(node->num_ids()));
  for (int i = 0; i < node->values()->length(); i++) {
    Visit(node->values()->at(i));
  }
}


void AstNumberingVisitor::VisitCall(Call* node) {
477
  IncrementNodeCount();
478
  ReserveFeedbackSlots(node);
479 480 481 482 483 484 485
  node->set_base_id(ReserveIdRange(Call::num_ids()));
  Visit(node->expression());
  VisitArguments(node->arguments());
}


void AstNumberingVisitor::VisitCallNew(CallNew* node) {
486
  IncrementNodeCount();
487
  ReserveFeedbackSlots(node);
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
  node->set_base_id(ReserveIdRange(CallNew::num_ids()));
  Visit(node->expression());
  VisitArguments(node->arguments());
}


void AstNumberingVisitor::VisitStatements(ZoneList<Statement*>* statements) {
  if (statements == NULL) return;
  for (int i = 0; i < statements->length(); i++) {
    Visit(statements->at(i));
  }
}


void AstNumberingVisitor::VisitDeclarations(
    ZoneList<Declaration*>* declarations) {
  for (int i = 0; i < declarations->length(); i++) {
    Visit(declarations->at(i));
  }
}


void AstNumberingVisitor::VisitArguments(ZoneList<Expression*>* arguments) {
  for (int i = 0; i < arguments->length(); i++) {
    Visit(arguments->at(i));
  }
}


void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
518
  IncrementNodeCount();
519 520 521 522 523 524
  node->set_base_id(ReserveIdRange(FunctionLiteral::num_ids()));
  // We don't recurse into the declarations or body of the function literal:
  // you have to separately Renumber() each FunctionLiteral that you compile.
}


525 526 527 528 529 530
bool AstNumberingVisitor::Finish(FunctionLiteral* node) {
  node->set_ast_properties(&properties_);
  node->set_dont_optimize_reason(dont_optimize_reason());
  return !HasStackOverflow();
}

531

532
bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
533
  Scope* scope = node->scope();
534 535 536

  if (scope->HasIllegalRedeclaration()) {
    scope->VisitIllegalRedeclaration(this);
537
    DisableOptimization(kFunctionWithIllegalRedeclaration);
538 539
    return Finish(node);
  }
540
  if (scope->calls_eval()) DisableOptimization(kFunctionCallsEval);
541
  if (scope->arguments() != NULL && !scope->arguments()->IsStackAllocated()) {
542
    DisableCrankshaft(kContextAllocatedArguments);
543 544
  }

545 546 547 548 549 550
  VisitDeclarations(scope->declarations());
  if (scope->is_function_scope() && scope->function() != NULL) {
    // Visit the name of the named function expression.
    Visit(scope->function());
  }
  VisitStatements(node->body());
551

552
  return Finish(node);
553 554 555
}


556 557 558
bool AstNumbering::Renumber(Isolate* isolate, Zone* zone,
                            FunctionLiteral* function) {
  AstNumberingVisitor visitor(isolate, zone);
559
  return visitor.Renumber(function);
560
}
561 562
}  // namespace internal
}  // namespace v8