ast-numbering.cc 18.1 KB
Newer Older
1 2 3 4
// 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.

5
#include "src/ast/ast-numbering.h"
6

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

namespace v8 {
namespace internal {

13
class AstNumberingVisitor final : public AstVisitor<AstNumberingVisitor> {
14
 public:
15
  AstNumberingVisitor(Isolate* isolate, Zone* zone)
16
      : isolate_(isolate),
17
        zone_(zone),
18
        next_id_(BailoutId::FirstUsable().ToInt()),
19
        yield_count_(0),
20
        properties_(zone),
21
        slot_cache_(zone),
22
        dont_optimize_reason_(kNoReason),
23
        catch_prediction_(HandlerTable::UNCAUGHT) {
24
    InitializeAstVisitor(isolate);
25 26
  }

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

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

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

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

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

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

62 63
  template <typename Node>
  void ReserveFeedbackSlots(Node* node) {
64
    node->AssignFeedbackVectorSlots(isolate_, properties_.get_spec(),
65
                                    &slot_cache_);
66 67
  }

68
  BailoutReason dont_optimize_reason() const { return dont_optimize_reason_; }
69

70
  Isolate* isolate_;
71
  Zone* zone_;
72
  int next_id_;
73
  int yield_count_;
74
  AstProperties properties_;
75 76
  // The slot cache allows us to reuse certain feedback vector slots.
  FeedbackVectorSlotCache slot_cache_;
77
  BailoutReason dont_optimize_reason_;
78
  HandlerTable::CatchPrediction catch_prediction_;
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
  VisitVariableProxy(node->proxy());
}


91 92 93
void AstNumberingVisitor::VisitEmptyStatement(EmptyStatement* node) {
  IncrementNodeCount();
}
94 95


96 97 98 99 100 101 102
void AstNumberingVisitor::VisitSloppyBlockFunctionStatement(
    SloppyBlockFunctionStatement* node) {
  IncrementNodeCount();
  Visit(node->statement());
}


103 104 105
void AstNumberingVisitor::VisitContinueStatement(ContinueStatement* node) {
  IncrementNodeCount();
}
106 107


108 109 110
void AstNumberingVisitor::VisitBreakStatement(BreakStatement* node) {
  IncrementNodeCount();
}
111 112 113


void AstNumberingVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
114
  IncrementNodeCount();
115
  DisableOptimization(kDebuggerStatement);
116 117 118 119 120 121
  node->set_base_id(ReserveIdRange(DebuggerStatement::num_ids()));
}


void AstNumberingVisitor::VisitNativeFunctionLiteral(
    NativeFunctionLiteral* node) {
122
  IncrementNodeCount();
123
  DisableOptimization(kNativeFunctionLiteral);
124 125 126 127
  node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids()));
}


128 129 130 131 132 133 134 135
void AstNumberingVisitor::VisitDoExpression(DoExpression* node) {
  IncrementNodeCount();
  node->set_base_id(ReserveIdRange(DoExpression::num_ids()));
  Visit(node->block());
  Visit(node->result());
}


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


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


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


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


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


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


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


189
void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) {
190
  IncrementNodeCount();
191 192 193 194 195
  Visit(node->expression());
}


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


void AstNumberingVisitor::VisitYield(Yield* node) {
202
  node->set_yield_id(yield_count_);
203
  yield_count_++;
204
  IncrementNodeCount();
205 206 207 208 209 210 211
  node->set_base_id(ReserveIdRange(Yield::num_ids()));
  Visit(node->generator_object());
  Visit(node->expression());
}


void AstNumberingVisitor::VisitThrow(Throw* node) {
212
  IncrementNodeCount();
213 214 215 216 217 218
  node->set_base_id(ReserveIdRange(Throw::num_ids()));
  Visit(node->exception());
}


void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) {
219
  IncrementNodeCount();
220 221 222 223 224 225
  node->set_base_id(ReserveIdRange(UnaryOperation::num_ids()));
  Visit(node->expression());
}


void AstNumberingVisitor::VisitCountOperation(CountOperation* node) {
226
  IncrementNodeCount();
227 228
  node->set_base_id(ReserveIdRange(CountOperation::num_ids()));
  Visit(node->expression());
229
  ReserveFeedbackSlots(node);
230 231 232 233
}


void AstNumberingVisitor::VisitBlock(Block* node) {
234
  IncrementNodeCount();
235 236 237 238 239 240 241
  node->set_base_id(ReserveIdRange(Block::num_ids()));
  if (node->scope() != NULL) VisitDeclarations(node->scope()->declarations());
  VisitStatements(node->statements());
}


void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) {
242
  IncrementNodeCount();
243 244 245 246 247 248
  VisitVariableProxy(node->proxy());
  VisitFunctionLiteral(node->fun());
}


void AstNumberingVisitor::VisitCallRuntime(CallRuntime* node) {
249
  IncrementNodeCount();
250 251
  node->set_base_id(ReserveIdRange(CallRuntime::num_ids()));
  VisitArguments(node->arguments());
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
  // To support catch prediction within async/await:
  //
  // The AstNumberingVisitor is when catch prediction currently occurs, and it
  // is the only common point that has access to this information. The parser
  // just doesn't know yet. Take the following two cases of catch prediction:
  //
  // try { await fn(); } catch (e) { }
  // try { await fn(); } finally { }
  //
  // When parsing the await that we want to mark as caught or uncaught, it's
  // not yet known whether it will be followed by a 'finally' or a 'catch.
  // The AstNumberingVisitor is what learns whether it is caught. To make
  // the information available later to the runtime, the AstNumberingVisitor
  // has to stash it somewhere. Changing the runtime function into another
  // one in ast-numbering seemed like a simple and straightforward solution to
  // that problem.
  if (node->is_jsruntime() &&
      node->context_index() == Context::ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX &&
      catch_prediction_ == HandlerTable::ASYNC_AWAIT) {
    node->set_context_index(Context::ASYNC_FUNCTION_AWAIT_UNCAUGHT_INDEX);
  }
273 274 275 276
}


void AstNumberingVisitor::VisitWithStatement(WithStatement* node) {
277
  IncrementNodeCount();
278
  DisableCrankshaft(kWithStatement);
279
  node->set_base_id(ReserveIdRange(WithStatement::num_ids()));
280 281 282 283 284 285
  Visit(node->expression());
  Visit(node->statement());
}


void AstNumberingVisitor::VisitDoWhileStatement(DoWhileStatement* node) {
286
  IncrementNodeCount();
287
  DisableSelfOptimization();
288
  node->set_base_id(ReserveIdRange(DoWhileStatement::num_ids()));
289
  node->set_first_yield_id(yield_count_);
290 291
  Visit(node->body());
  Visit(node->cond());
292
  node->set_yield_count(yield_count_ - node->first_yield_id());
293 294 295 296
}


void AstNumberingVisitor::VisitWhileStatement(WhileStatement* node) {
297
  IncrementNodeCount();
298
  DisableSelfOptimization();
299
  node->set_base_id(ReserveIdRange(WhileStatement::num_ids()));
300
  node->set_first_yield_id(yield_count_);
301 302
  Visit(node->cond());
  Visit(node->body());
303
  node->set_yield_count(yield_count_ - node->first_yield_id());
304 305 306 307
}


void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
308
  IncrementNodeCount();
309
  DisableCrankshaft(kTryCatchStatement);
310
  {
311 312 313 314 315 316 317 318
    const HandlerTable::CatchPrediction old_prediction = catch_prediction_;
    // This node uses its own prediction, unless it's "uncaught", in which case
    // we adopt the prediction of the outer try-block.
    HandlerTable::CatchPrediction catch_prediction = node->catch_prediction();
    if (catch_prediction != HandlerTable::UNCAUGHT) {
      catch_prediction_ = catch_prediction;
    }
    node->set_catch_prediction(catch_prediction_);
319
    Visit(node->try_block());
320
    catch_prediction_ = old_prediction;
321
  }
322 323 324 325 326
  Visit(node->catch_block());
}


void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
327
  IncrementNodeCount();
328
  DisableCrankshaft(kTryFinallyStatement);
329 330
  // We can't know whether the finally block will override ("catch") an
  // exception thrown in the try block, so we just adopt the outer prediction.
331
  node->set_catch_prediction(catch_prediction_);
332 333 334 335 336
  Visit(node->try_block());
  Visit(node->finally_block());
}


337
void AstNumberingVisitor::VisitPropertyReference(Property* node) {
338
  IncrementNodeCount();
339 340 341 342 343 344
  node->set_base_id(ReserveIdRange(Property::num_ids()));
  Visit(node->key());
  Visit(node->obj());
}


345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
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);
}


361
void AstNumberingVisitor::VisitAssignment(Assignment* node) {
362
  IncrementNodeCount();
363
  node->set_base_id(ReserveIdRange(Assignment::num_ids()));
364

365
  if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
366
  VisitReference(node->target());
367
  Visit(node->value());
368
  ReserveFeedbackSlots(node);
369 370 371 372
}


void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
373
  IncrementNodeCount();
374 375 376
  node->set_base_id(ReserveIdRange(BinaryOperation::num_ids()));
  Visit(node->left());
  Visit(node->right());
377
  ReserveFeedbackSlots(node);
378 379 380 381
}


void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
382
  IncrementNodeCount();
383 384 385
  node->set_base_id(ReserveIdRange(CompareOperation::num_ids()));
  Visit(node->left());
  Visit(node->right());
386
  ReserveFeedbackSlots(node);
387 388 389
}


390
void AstNumberingVisitor::VisitSpread(Spread* node) { UNREACHABLE(); }
391 392


393 394 395 396 397
void AstNumberingVisitor::VisitEmptyParentheses(EmptyParentheses* node) {
  UNREACHABLE();
}


398
void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
399
  IncrementNodeCount();
400
  DisableSelfOptimization();
401
  node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
402
  Visit(node->enumerable());  // Not part of loop.
403
  node->set_first_yield_id(yield_count_);
404 405
  Visit(node->each());
  Visit(node->body());
406
  node->set_yield_count(yield_count_ - node->first_yield_id());
407
  ReserveFeedbackSlots(node);
408 409 410 411
}


void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
412
  IncrementNodeCount();
413
  DisableCrankshaft(kForOfStatement);
414
  node->set_base_id(ReserveIdRange(ForOfStatement::num_ids()));
415
  Visit(node->assign_iterator());  // Not part of loop.
416
  node->set_first_yield_id(yield_count_);
417 418 419 420
  Visit(node->next_result());
  Visit(node->result_done());
  Visit(node->assign_each());
  Visit(node->body());
421
  node->set_yield_count(yield_count_ - node->first_yield_id());
422 423 424 425
}


void AstNumberingVisitor::VisitConditional(Conditional* node) {
426
  IncrementNodeCount();
427 428 429 430 431 432 433 434
  node->set_base_id(ReserveIdRange(Conditional::num_ids()));
  Visit(node->condition());
  Visit(node->then_expression());
  Visit(node->else_expression());
}


void AstNumberingVisitor::VisitIfStatement(IfStatement* node) {
435
  IncrementNodeCount();
436 437 438 439 440 441 442 443 444 445
  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) {
446
  IncrementNodeCount();
447 448 449 450 451 452 453 454 455 456
  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) {
457
  IncrementNodeCount();
458 459 460
  node->set_base_id(ReserveIdRange(CaseClause::num_ids()));
  if (!node->is_default()) Visit(node->label());
  VisitStatements(node->statements());
461
  ReserveFeedbackSlots(node);
462 463 464 465
}


void AstNumberingVisitor::VisitForStatement(ForStatement* node) {
466
  IncrementNodeCount();
467
  DisableSelfOptimization();
468
  node->set_base_id(ReserveIdRange(ForStatement::num_ids()));
469
  if (node->init() != NULL) Visit(node->init());  // Not part of loop.
470
  node->set_first_yield_id(yield_count_);
471 472 473
  if (node->cond() != NULL) Visit(node->cond());
  if (node->next() != NULL) Visit(node->next());
  Visit(node->body());
474
  node->set_yield_count(yield_count_ - node->first_yield_id());
475 476 477 478
}


void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
479
  IncrementNodeCount();
480
  DisableCrankshaft(kClassLiteral);
481
  node->set_base_id(ReserveIdRange(node->num_ids()));
482 483
  if (node->extends()) Visit(node->extends());
  if (node->constructor()) Visit(node->constructor());
484 485 486
  if (node->class_variable_proxy()) {
    VisitVariableProxy(node->class_variable_proxy());
  }
487
  for (int i = 0; i < node->properties()->length(); i++) {
488
    VisitLiteralProperty(node->properties()->at(i));
489
  }
490
  ReserveFeedbackSlots(node);
491 492 493 494
}


void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
495
  IncrementNodeCount();
496
  node->set_base_id(ReserveIdRange(node->num_ids()));
497
  for (int i = 0; i < node->properties()->length(); i++) {
498
    VisitLiteralProperty(node->properties()->at(i));
499
  }
500
  node->BuildConstantProperties(isolate_);
501 502 503
  // 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.
504
  node->CalculateEmitStore(zone_);
505
  ReserveFeedbackSlots(node);
506 507
}

508
void AstNumberingVisitor::VisitLiteralProperty(LiteralProperty* node) {
509
  if (node->is_computed_name()) DisableCrankshaft(kComputedPropertyName);
510 511 512 513 514
  Visit(node->key());
  Visit(node->value());
}

void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
515
  IncrementNodeCount();
516 517 518 519
  node->set_base_id(ReserveIdRange(node->num_ids()));
  for (int i = 0; i < node->values()->length(); i++) {
    Visit(node->values()->at(i));
  }
520
  node->BuildConstantElements(isolate_);
521
  ReserveFeedbackSlots(node);
522 523 524 525
}


void AstNumberingVisitor::VisitCall(Call* node) {
526
  IncrementNodeCount();
527
  ReserveFeedbackSlots(node);
528 529 530 531 532 533 534
  node->set_base_id(ReserveIdRange(Call::num_ids()));
  Visit(node->expression());
  VisitArguments(node->arguments());
}


void AstNumberingVisitor::VisitCallNew(CallNew* node) {
535
  IncrementNodeCount();
536
  ReserveFeedbackSlots(node);
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
  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) {
567
  IncrementNodeCount();
568 569 570 571 572 573
  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.
}


574 575
void AstNumberingVisitor::VisitRewritableExpression(
    RewritableExpression* node) {
576
  IncrementNodeCount();
577
  node->set_base_id(ReserveIdRange(RewritableExpression::num_ids()));
578 579 580 581
  Visit(node->expression());
}


582
bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
583
  DeclarationScope* scope = node->scope();
584
  if (scope->new_target_var()) DisableCrankshaft(kSuperReference);
bmeurer's avatar
bmeurer committed
585
  if (scope->calls_eval()) DisableCrankshaft(kFunctionCallsEval);
586
  if (scope->arguments() != NULL && !scope->arguments()->IsStackAllocated()) {
587
    DisableCrankshaft(kContextAllocatedArguments);
588 589
  }

590
  if (scope->rest_parameter() != nullptr) {
591 592 593
    DisableCrankshaft(kRestParameter);
  }

594
  if (IsGeneratorFunction(node->kind()) || IsAsyncFunction(node->kind())) {
595 596 597 598 599 600
    // Generators can be optimized if --turbo-from-bytecode is set.
    if (FLAG_turbo_from_bytecode) {
      DisableCrankshaft(kGenerator);
    } else {
      DisableOptimization(kGenerator);
    }
601 602
  }

603 604
  VisitDeclarations(scope->declarations());
  VisitStatements(node->body());
605

606 607 608 609
  node->set_ast_properties(&properties_);
  node->set_dont_optimize_reason(dont_optimize_reason());
  node->set_yield_count(yield_count_);
  return !HasStackOverflow();
610 611 612
}


613 614 615
bool AstNumbering::Renumber(Isolate* isolate, Zone* zone,
                            FunctionLiteral* function) {
  AstNumberingVisitor visitor(isolate, zone);
616
  return visitor.Renumber(function);
617
}
618 619
}  // namespace internal
}  // namespace v8