ast-numbering.cc 15.8 KB
Newer Older
1 2 3 4 5
// 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/ast-numbering.h"
6 7

#include "src/ast.h"
8 9 10 11 12
#include "src/scopes.h"

namespace v8 {
namespace internal {

13
class AstNumberingVisitor final : public AstVisitor {
14
 public:
15
  AstNumberingVisitor(Isolate* isolate, Zone* zone)
16 17
      : AstVisitor(),
        next_id_(BailoutId::FirstUsable().ToInt()),
18
        properties_(zone),
jkummerow's avatar
jkummerow committed
19
        ic_slot_cache_(zone),
20
        dont_optimize_reason_(kNoReason) {
21
    InitializeAstVisitor(isolate, zone);
22 23
  }

24
  bool Renumber(FunctionLiteral* node);
25 26 27

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

32 33
  bool Finish(FunctionLiteral* node);

34 35 36 37
  void VisitVariableProxyReference(VariableProxy* node);
  void VisitPropertyReference(Property* node);
  void VisitReference(Expression* expr);

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

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

49
  void IncrementNodeCount() { properties_.add_node_count(1); }
50
  void DisableSelfOptimization() {
51
    properties_.flags() |= AstProperties::kDontSelfOptimize;
52
  }
53 54 55 56
  void DisableOptimization(BailoutReason reason) {
    dont_optimize_reason_ = reason;
    DisableSelfOptimization();
  }
57 58
  void DisableCrankshaft(BailoutReason reason) {
    if (FLAG_turbo_shipping) {
59 60 61 62
      properties_.flags() |= AstProperties::kDontCrankshaft;
    } else {
      dont_optimize_reason_ = reason;
      DisableSelfOptimization();
63 64
    }
  }
65

66 67
  template <typename Node>
  void ReserveFeedbackSlots(Node* node) {
68 69
    node->AssignFeedbackVectorSlots(isolate(), properties_.get_spec(),
                                    &ic_slot_cache_);
70 71
  }

72
  BailoutReason dont_optimize_reason() const { return dont_optimize_reason_; }
73

74
  int next_id_;
75
  AstProperties properties_;
76
  // The slot cache allows us to reuse certain vector IC slots.
77
  ICSlotCache ic_slot_cache_;
78
  BailoutReason dont_optimize_reason_;
79 80 81 82 83 84 85

  DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
  DISALLOW_COPY_AND_ASSIGN(AstNumberingVisitor);
};


void AstNumberingVisitor::VisitVariableDeclaration(VariableDeclaration* node) {
86
  IncrementNodeCount();
87 88 89 90 91
  VisitVariableProxy(node->proxy());
}


void AstNumberingVisitor::VisitExportDeclaration(ExportDeclaration* node) {
92
  IncrementNodeCount();
93
  DisableOptimization(kExportDeclaration);
94 95 96 97
  VisitVariableProxy(node->proxy());
}


98 99 100
void AstNumberingVisitor::VisitEmptyStatement(EmptyStatement* node) {
  IncrementNodeCount();
}
101 102


103 104 105 106 107 108 109
void AstNumberingVisitor::VisitSloppyBlockFunctionStatement(
    SloppyBlockFunctionStatement* node) {
  IncrementNodeCount();
  Visit(node->statement());
}


110 111 112
void AstNumberingVisitor::VisitContinueStatement(ContinueStatement* node) {
  IncrementNodeCount();
}
113 114


115 116 117
void AstNumberingVisitor::VisitBreakStatement(BreakStatement* node) {
  IncrementNodeCount();
}
118 119 120


void AstNumberingVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
121
  IncrementNodeCount();
122
  DisableOptimization(kDebuggerStatement);
123 124 125 126 127 128
  node->set_base_id(ReserveIdRange(DebuggerStatement::num_ids()));
}


void AstNumberingVisitor::VisitNativeFunctionLiteral(
    NativeFunctionLiteral* node) {
129
  IncrementNodeCount();
130
  DisableOptimization(kNativeFunctionLiteral);
131 132 133 134 135
  node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids()));
}


void AstNumberingVisitor::VisitLiteral(Literal* node) {
136
  IncrementNodeCount();
137 138 139 140 141
  node->set_base_id(ReserveIdRange(Literal::num_ids()));
}


void AstNumberingVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
142
  IncrementNodeCount();
143 144 145 146
  node->set_base_id(ReserveIdRange(RegExpLiteral::num_ids()));
}


147
void AstNumberingVisitor::VisitVariableProxyReference(VariableProxy* node) {
148
  IncrementNodeCount();
149
  if (node->var()->IsLookupSlot()) {
150
    DisableCrankshaft(kReferenceToAVariableWhichRequiresDynamicLookup);
151
  }
152 153 154 155
  node->set_base_id(ReserveIdRange(VariableProxy::num_ids()));
}


156 157 158 159 160 161
void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) {
  VisitVariableProxyReference(node);
  ReserveFeedbackSlots(node);
}


162
void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
163
  IncrementNodeCount();
164 165 166 167
  node->set_base_id(ReserveIdRange(ThisFunction::num_ids()));
}


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


178 179 180 181 182 183 184 185 186 187
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());
}


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


void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) {
196
  IncrementNodeCount();
197 198 199 200 201
  Visit(node->expression());
}


void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) {
202
  IncrementNodeCount();
203 204 205 206 207
  Visit(node->expression());
}


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


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


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


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


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


void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) {
248
  IncrementNodeCount();
249 250 251 252 253 254
  VisitVariableProxy(node->proxy());
  VisitFunctionLiteral(node->fun());
}


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


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


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


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


void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
294
  IncrementNodeCount();
295
  DisableOptimization(kTryCatchStatement);
296
  node->set_base_id(ReserveIdRange(TryCatchStatement::num_ids()));
297 298 299 300 301 302
  Visit(node->try_block());
  Visit(node->catch_block());
}


void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
303
  IncrementNodeCount();
304
  DisableOptimization(kTryFinallyStatement);
305
  node->set_base_id(ReserveIdRange(TryFinallyStatement::num_ids()));
306 307 308 309 310
  Visit(node->try_block());
  Visit(node->finally_block());
}


311
void AstNumberingVisitor::VisitPropertyReference(Property* node) {
312
  IncrementNodeCount();
313 314 315 316 317 318
  node->set_base_id(ReserveIdRange(Property::num_ids()));
  Visit(node->key());
  Visit(node->obj());
}


319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
void AstNumberingVisitor::VisitReference(Expression* expr) {
  DCHECK(expr->IsProperty() || expr->IsVariableProxy());
  if (expr->IsProperty()) {
    VisitPropertyReference(expr->AsProperty());
  } else {
    VisitVariableProxyReference(expr->AsVariableProxy());
  }
}


void AstNumberingVisitor::VisitProperty(Property* node) {
  VisitPropertyReference(node);
  ReserveFeedbackSlots(node);
}


335
void AstNumberingVisitor::VisitAssignment(Assignment* node) {
336
  IncrementNodeCount();
337 338
  node->set_base_id(ReserveIdRange(Assignment::num_ids()));
  if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
339
  VisitReference(node->target());
340
  Visit(node->value());
341
  ReserveFeedbackSlots(node);
342 343 344 345
}


void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
346
  IncrementNodeCount();
347 348 349 350 351 352 353
  node->set_base_id(ReserveIdRange(BinaryOperation::num_ids()));
  Visit(node->left());
  Visit(node->right());
}


void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
354
  IncrementNodeCount();
355 356 357 358 359 360
  node->set_base_id(ReserveIdRange(CompareOperation::num_ids()));
  Visit(node->left());
  Visit(node->right());
}


arv's avatar
arv committed
361 362 363 364 365
void AstNumberingVisitor::VisitSpread(Spread* node) {
  IncrementNodeCount();
  DisableOptimization(kSpread);
  Visit(node->expression());
}
366 367


368 369 370 371 372
void AstNumberingVisitor::VisitEmptyParentheses(EmptyParentheses* node) {
  UNREACHABLE();
}


373
void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
374
  IncrementNodeCount();
375
  DisableSelfOptimization();
376 377 378 379
  node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
  Visit(node->each());
  Visit(node->enumerable());
  Visit(node->body());
380
  ReserveFeedbackSlots(node);
381 382 383 384
}


void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
385
  IncrementNodeCount();
386
  DisableCrankshaft(kForOfStatement);
387 388 389 390 391 392
  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());
393
  ReserveFeedbackSlots(node);
394 395 396 397
}


void AstNumberingVisitor::VisitConditional(Conditional* node) {
398
  IncrementNodeCount();
399 400 401 402 403 404 405 406
  node->set_base_id(ReserveIdRange(Conditional::num_ids()));
  Visit(node->condition());
  Visit(node->then_expression());
  Visit(node->else_expression());
}


void AstNumberingVisitor::VisitIfStatement(IfStatement* node) {
407
  IncrementNodeCount();
408 409 410 411 412 413 414 415 416 417
  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) {
418
  IncrementNodeCount();
419 420 421 422 423 424 425 426 427 428
  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) {
429
  IncrementNodeCount();
430 431 432 433 434 435 436
  node->set_base_id(ReserveIdRange(CaseClause::num_ids()));
  if (!node->is_default()) Visit(node->label());
  VisitStatements(node->statements());
}


void AstNumberingVisitor::VisitForStatement(ForStatement* node) {
437
  IncrementNodeCount();
438
  DisableSelfOptimization();
439 440 441 442 443 444 445 446 447
  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) {
448
  IncrementNodeCount();
449
  DisableCrankshaft(kClassLiteral);
450
  node->set_base_id(ReserveIdRange(node->num_ids()));
451 452
  if (node->extends()) Visit(node->extends());
  if (node->constructor()) Visit(node->constructor());
453 454 455
  if (node->class_variable_proxy()) {
    VisitVariableProxy(node->class_variable_proxy());
  }
456 457 458
  for (int i = 0; i < node->properties()->length(); i++) {
    VisitObjectLiteralProperty(node->properties()->at(i));
  }
459
  ReserveFeedbackSlots(node);
460 461 462 463
}


void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
464
  IncrementNodeCount();
465
  node->set_base_id(ReserveIdRange(node->num_ids()));
466 467 468
  for (int i = 0; i < node->properties()->length(); i++) {
    VisitObjectLiteralProperty(node->properties()->at(i));
  }
469
  node->BuildConstantProperties(isolate());
470 471 472 473
  // 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());
474
  ReserveFeedbackSlots(node);
475 476 477 478 479
}


void AstNumberingVisitor::VisitObjectLiteralProperty(
    ObjectLiteralProperty* node) {
480
  if (node->is_computed_name()) DisableCrankshaft(kComputedPropertyName);
481 482 483 484 485 486
  Visit(node->key());
  Visit(node->value());
}


void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
487
  IncrementNodeCount();
488 489 490 491 492 493 494 495
  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) {
496
  IncrementNodeCount();
497
  ReserveFeedbackSlots(node);
498 499 500 501 502 503 504
  node->set_base_id(ReserveIdRange(Call::num_ids()));
  Visit(node->expression());
  VisitArguments(node->arguments());
}


void AstNumberingVisitor::VisitCallNew(CallNew* node) {
505
  IncrementNodeCount();
506
  ReserveFeedbackSlots(node);
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
  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) {
537
  IncrementNodeCount();
538 539 540 541 542 543
  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.
}


544 545 546 547 548 549
bool AstNumberingVisitor::Finish(FunctionLiteral* node) {
  node->set_ast_properties(&properties_);
  node->set_dont_optimize_reason(dont_optimize_reason());
  return !HasStackOverflow();
}

550

551
bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
552
  Scope* scope = node->scope();
553 554

  if (scope->HasIllegalRedeclaration()) {
555
    Visit(scope->GetIllegalRedeclaration());
556
    DisableOptimization(kFunctionWithIllegalRedeclaration);
557 558
    return Finish(node);
  }
559
  if (scope->calls_eval()) DisableOptimization(kFunctionCallsEval);
560
  if (scope->arguments() != NULL && !scope->arguments()->IsStackAllocated()) {
561
    DisableCrankshaft(kContextAllocatedArguments);
562 563
  }

564 565
  VisitDeclarations(scope->declarations());
  VisitStatements(node->body());
566

567
  return Finish(node);
568 569 570
}


571 572 573
bool AstNumbering::Renumber(Isolate* isolate, Zone* zone,
                            FunctionLiteral* function) {
  AstNumberingVisitor visitor(isolate, zone);
574
  return visitor.Renumber(function);
575
}
576 577
}  // namespace internal
}  // namespace v8