LCOV - code coverage report
Current view: top level - src/ast - prettyprinter.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 297 353 84.1 %
Date: 2019-01-20 Functions: 47 68 69.1 %

          Line data    Source code
       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.
       4             : 
       5             : #include "src/ast/prettyprinter.h"
       6             : 
       7             : #include <stdarg.h>
       8             : 
       9             : #include "src/ast/ast-value-factory.h"
      10             : #include "src/ast/scopes.h"
      11             : #include "src/base/platform/platform.h"
      12             : #include "src/globals.h"
      13             : #include "src/objects-inl.h"
      14             : #include "src/string-builder-inl.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : 
      19        6330 : CallPrinter::CallPrinter(Isolate* isolate, bool is_user_js)
      20        6330 :     : builder_(new IncrementalStringBuilder(isolate)) {
      21        6330 :   isolate_ = isolate;
      22        6330 :   position_ = 0;
      23        6330 :   num_prints_ = 0;
      24        6330 :   found_ = false;
      25        6330 :   done_ = false;
      26        6330 :   is_call_error_ = false;
      27        6330 :   is_iterator_error_ = false;
      28        6330 :   is_async_iterator_error_ = false;
      29        6330 :   is_user_js_ = is_user_js;
      30        6330 :   function_kind_ = kNormalFunction;
      31             :   InitializeAstVisitor(isolate);
      32        6330 : }
      33             : 
      34             : CallPrinter::~CallPrinter() = default;
      35             : 
      36        6330 : CallPrinter::ErrorHint CallPrinter::GetErrorHint() const {
      37        6330 :   if (is_call_error_) {
      38        5718 :     if (is_iterator_error_) return ErrorHint::kCallAndNormalIterator;
      39        5664 :     if (is_async_iterator_error_) return ErrorHint::kCallAndAsyncIterator;
      40             :   } else {
      41         612 :     if (is_iterator_error_) return ErrorHint::kNormalIterator;
      42         567 :     if (is_async_iterator_error_) return ErrorHint::kAsyncIterator;
      43             :   }
      44        6222 :   return ErrorHint::kNone;
      45             : }
      46             : 
      47        6330 : Handle<String> CallPrinter::Print(FunctionLiteral* program, int position) {
      48        6330 :   num_prints_ = 0;
      49        6330 :   position_ = position;
      50        6330 :   Find(program);
      51       12660 :   return builder_->Finish().ToHandleChecked();
      52             : }
      53             : 
      54             : 
      55      197986 : void CallPrinter::Find(AstNode* node, bool print) {
      56      197986 :   if (found_) {
      57       13600 :     if (print) {
      58       11767 :       int prev_num_prints = num_prints_;
      59       11767 :       Visit(node);
      60      209753 :       if (prev_num_prints != num_prints_) return;
      61             :     }
      62        1887 :     Print("(intermediate value)");
      63             :   } else {
      64      184386 :     Visit(node);
      65             :   }
      66             : }
      67             : 
      68       94358 : void CallPrinter::Print(const char* str) {
      69      188716 :   if (!found_ || done_) return;
      70        9170 :   num_prints_++;
      71             :   builder_->AppendCString(str);
      72             : }
      73             : 
      74       96809 : void CallPrinter::Print(Handle<String> str) {
      75      193618 :   if (!found_ || done_) return;
      76        9230 :   num_prints_++;
      77        9230 :   builder_->AppendString(str);
      78             : }
      79             : 
      80           0 : void CallPrinter::VisitBlock(Block* node) {
      81       13844 :   FindStatements(node->statements());
      82           0 : }
      83             : 
      84             : 
      85           0 : void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {}
      86             : 
      87             : 
      88           0 : void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {}
      89             : 
      90             : 
      91       25762 : void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) {
      92       25762 :   Find(node->expression());
      93       25762 : }
      94             : 
      95             : 
      96           0 : void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {}
      97             : 
      98             : 
      99          36 : void CallPrinter::VisitSloppyBlockFunctionStatement(
     100          36 :     SloppyBlockFunctionStatement* node) {
     101          36 :   Find(node->statement());
     102          36 : }
     103             : 
     104             : 
     105         309 : void CallPrinter::VisitIfStatement(IfStatement* node) {
     106         103 :   Find(node->condition());
     107         103 :   Find(node->then_statement());
     108         103 :   if (node->HasElseStatement()) {
     109          18 :     Find(node->else_statement());
     110             :   }
     111         103 : }
     112             : 
     113             : 
     114           0 : void CallPrinter::VisitContinueStatement(ContinueStatement* node) {}
     115             : 
     116             : 
     117           0 : void CallPrinter::VisitBreakStatement(BreakStatement* node) {}
     118             : 
     119             : 
     120        2507 : void CallPrinter::VisitReturnStatement(ReturnStatement* node) {
     121        2507 :   Find(node->expression());
     122        2507 : }
     123             : 
     124             : 
     125          28 : void CallPrinter::VisitWithStatement(WithStatement* node) {
     126          14 :   Find(node->expression());
     127          14 :   Find(node->statement());
     128          14 : }
     129             : 
     130             : 
     131          18 : void CallPrinter::VisitSwitchStatement(SwitchStatement* node) {
     132          18 :   Find(node->tag());
     133          63 :   for (CaseClause* clause : *node->cases()) {
     134          27 :     if (!clause->is_default()) Find(clause->label());
     135          27 :     FindStatements(clause->statements());
     136             :   }
     137          18 : }
     138             : 
     139             : 
     140          18 : void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
     141           9 :   Find(node->body());
     142           9 :   Find(node->cond());
     143           9 : }
     144             : 
     145             : 
     146           9 : void CallPrinter::VisitWhileStatement(WhileStatement* node) {
     147           9 :   Find(node->cond());
     148           9 :   Find(node->body());
     149           9 : }
     150             : 
     151             : 
     152         957 : void CallPrinter::VisitForStatement(ForStatement* node) {
     153         319 :   if (node->init() != nullptr) {
     154         310 :     Find(node->init());
     155             :   }
     156         319 :   if (node->cond() != nullptr) Find(node->cond());
     157         319 :   if (node->next() != nullptr) Find(node->next());
     158         319 :   Find(node->body());
     159         319 : }
     160             : 
     161             : 
     162          27 : void CallPrinter::VisitForInStatement(ForInStatement* node) {
     163          27 :   Find(node->each());
     164          27 :   Find(node->subject());
     165          27 :   Find(node->body());
     166          27 : }
     167             : 
     168             : 
     169         828 : void CallPrinter::VisitForOfStatement(ForOfStatement* node) {
     170        1548 :   Find(node->each());
     171             : 
     172             :   // Check the subject's position in case there was a GetIterator error.
     173             :   bool was_found = false;
     174         774 :   if (node->subject()->position() == position_) {
     175          54 :     is_async_iterator_error_ = node->type() == IteratorType::kAsync;
     176          54 :     is_iterator_error_ = !is_async_iterator_error_;
     177          54 :     was_found = !found_;
     178          54 :     if (was_found) {
     179          54 :       found_ = true;
     180             :     }
     181             :   }
     182         774 :   Find(node->subject(), true);
     183         774 :   if (was_found) {
     184          54 :     done_ = true;
     185          54 :     found_ = false;
     186             :   }
     187             : 
     188         774 :   Find(node->body());
     189         774 : }
     190             : 
     191             : 
     192        4740 : void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
     193        2370 :   Find(node->try_block());
     194        2370 :   Find(node->catch_block());
     195        2370 : }
     196             : 
     197             : 
     198         288 : void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
     199         144 :   Find(node->try_block());
     200         144 :   Find(node->finally_block());
     201         144 : }
     202             : 
     203             : 
     204           0 : void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {}
     205             : 
     206             : 
     207        6735 : void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
     208        6735 :   FunctionKind last_function_kind = function_kind_;
     209        6735 :   function_kind_ = node->kind();
     210        6735 :   FindStatements(node->body());
     211        6735 :   function_kind_ = last_function_kind;
     212        6735 : }
     213             : 
     214             : 
     215        4347 : void CallPrinter::VisitClassLiteral(ClassLiteral* node) {
     216        1449 :   if (node->extends()) Find(node->extends());
     217        4347 :   for (int i = 0; i < node->properties()->length(); i++) {
     218        1449 :     Find(node->properties()->at(i)->value());
     219             :   }
     220        1449 : }
     221             : 
     222           0 : void CallPrinter::VisitInitializeClassMembersStatement(
     223           0 :     InitializeClassMembersStatement* node) {
     224           0 :   for (int i = 0; i < node->fields()->length(); i++) {
     225           0 :     Find(node->fields()->at(i)->value());
     226             :   }
     227           0 : }
     228             : 
     229           0 : void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {}
     230             : 
     231             : 
     232           0 : void CallPrinter::VisitDoExpression(DoExpression* node) { Find(node->block()); }
     233             : 
     234             : 
     235         405 : void CallPrinter::VisitConditional(Conditional* node) {
     236         135 :   Find(node->condition());
     237         135 :   Find(node->then_expression());
     238         135 :   Find(node->else_expression());
     239         135 : }
     240             : 
     241             : 
     242       15816 : void CallPrinter::VisitLiteral(Literal* node) {
     243             :   // TODO(adamk): Teach Literal how to print its values without
     244             :   // allocating on the heap.
     245       15816 :   PrintLiteral(node->BuildValue(isolate_), true);
     246       15816 : }
     247             : 
     248             : 
     249        1764 : void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
     250         252 :   Print("/");
     251         252 :   PrintLiteral(node->pattern(), false);
     252         252 :   Print("/");
     253         252 :   if (node->flags() & RegExp::kGlobal) Print("g");
     254         252 :   if (node->flags() & RegExp::kIgnoreCase) Print("i");
     255         252 :   if (node->flags() & RegExp::kMultiline) Print("m");
     256         252 :   if (node->flags() & RegExp::kUnicode) Print("u");
     257         252 :   if (node->flags() & RegExp::kSticky) Print("y");
     258         252 : }
     259             : 
     260             : 
     261        2831 : void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) {
     262        2831 :   Print("{");
     263        6931 :   for (int i = 0; i < node->properties()->length(); i++) {
     264        4100 :     Find(node->properties()->at(i)->value());
     265             :   }
     266        2831 :   Print("}");
     267        2831 : }
     268             : 
     269             : 
     270        1703 : void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) {
     271        1703 :   Print("[");
     272       10883 :   for (int i = 0; i < node->values()->length(); i++) {
     273        9180 :     if (i != 0) Print(",");
     274        9180 :     Expression* subexpr = node->values()->at(i);
     275        9540 :     Spread* spread = subexpr->AsSpread();
     276        9540 :     if (spread != nullptr && !found_ &&
     277         720 :         position_ == spread->expression()->position()) {
     278           0 :       found_ = true;
     279           0 :       is_iterator_error_ = true;
     280           0 :       Find(spread->expression(), true);
     281           0 :       done_ = true;
     282        1703 :       return;
     283             :     }
     284        9180 :     Find(subexpr, true);
     285             :   }
     286        1703 :   Print("]");
     287             : }
     288             : 
     289             : 
     290       56512 : void CallPrinter::VisitVariableProxy(VariableProxy* node) {
     291       56512 :   if (is_user_js_) {
     292       56512 :     PrintLiteral(node->name(), false);
     293             :   } else {
     294             :     // Variable names of non-user code are meaningless due to minification.
     295           0 :     Print("(var)");
     296             :   }
     297       56512 : }
     298             : 
     299             : 
     300       25731 : void CallPrinter::VisitAssignment(Assignment* node) {
     301        8475 :   Find(node->target());
     302        8475 :   if (node->target()->IsArrayLiteral()) {
     303             :     // Special case the visit for destructuring array assignment.
     304             :     bool was_found = false;
     305         306 :     if (node->value()->position() == position_) {
     306          54 :       is_iterator_error_ = true;
     307          54 :       was_found = !found_;
     308          54 :       if (was_found) {
     309          54 :         found_ = true;
     310             :       }
     311             :     }
     312         306 :     Find(node->value(), true);
     313         306 :     if (was_found) {
     314          54 :       done_ = true;
     315          54 :       found_ = false;
     316             :     }
     317             :   } else {
     318        8169 :     Find(node->value());
     319             :   }
     320        8475 : }
     321             : 
     322           0 : void CallPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
     323           0 :   VisitAssignment(node);
     324           0 : }
     325             : 
     326         189 : void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); }
     327             : 
     328          54 : void CallPrinter::VisitYieldStar(YieldStar* node) {
     329         108 :   if (!found_ && position_ == node->expression()->position()) {
     330           0 :     found_ = true;
     331           0 :     if (IsAsyncFunction(function_kind_))
     332           0 :       is_async_iterator_error_ = true;
     333             :     else
     334           0 :       is_iterator_error_ = true;
     335           0 :     Print("yield* ");
     336             :   }
     337          54 :   Find(node->expression());
     338          54 : }
     339             : 
     340          72 : void CallPrinter::VisitAwait(Await* node) { Find(node->expression()); }
     341             : 
     342          81 : void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); }
     343             : 
     344             : 
     345       62798 : void CallPrinter::VisitProperty(Property* node) {
     346             :   Expression* key = node->key();
     347       31399 :   Literal* literal = key->AsLiteral();
     348       94197 :   if (literal != nullptr &&
     349      124354 :       literal->BuildValue(isolate_)->IsInternalizedString()) {
     350       30520 :     Find(node->obj(), true);
     351       30520 :     Print(".");
     352             :     // TODO(adamk): Teach Literal how to print its values without
     353             :     // allocating on the heap.
     354       30520 :     PrintLiteral(literal->BuildValue(isolate_), false);
     355             :   } else {
     356         879 :     Find(node->obj(), true);
     357         879 :     Print("[");
     358         879 :     Find(key, true);
     359         879 :     Print("]");
     360             :   }
     361       31399 : }
     362             : 
     363           0 : void CallPrinter::VisitResolvedProperty(ResolvedProperty* node) {}
     364             : 
     365       37372 : void CallPrinter::VisitCall(Call* node) {
     366             :   bool was_found = false;
     367       18686 :   if (node->position() == position_) {
     368        3865 :     is_call_error_ = true;
     369        3865 :     was_found = !found_;
     370             :   }
     371       18686 :   if (was_found) {
     372             :     // Bail out if the error is caused by a direct call to a variable in
     373             :     // non-user JS code. The variable name is meaningless due to minification.
     374        3811 :     if (!is_user_js_ && node->expression()->IsVariableProxy()) {
     375           0 :       done_ = true;
     376       18686 :       return;
     377             :     }
     378        3811 :     found_ = true;
     379             :   }
     380       18686 :   Find(node->expression(), true);
     381       18686 :   if (!was_found && !is_iterator_error_) Print("(...)");
     382       18686 :   FindArguments(node->arguments());
     383       18686 :   if (was_found) {
     384        3811 :     done_ = true;
     385        3811 :     found_ = false;
     386             :   }
     387             : }
     388             : 
     389             : 
     390        5080 : void CallPrinter::VisitCallNew(CallNew* node) {
     391             :   bool was_found = false;
     392        2540 :   if (node->position() == position_) {
     393        1853 :     is_call_error_ = true;
     394        1853 :     was_found = !found_;
     395             :   }
     396        2540 :   if (was_found) {
     397             :     // Bail out if the error is caused by a direct call to a variable in
     398             :     // non-user JS code. The variable name is meaningless due to minification.
     399        1853 :     if (!is_user_js_ && node->expression()->IsVariableProxy()) {
     400           0 :       done_ = true;
     401        2540 :       return;
     402             :     }
     403        1853 :     found_ = true;
     404             :   }
     405        5080 :   Find(node->expression(), was_found || is_iterator_error_);
     406        2540 :   FindArguments(node->arguments());
     407        2540 :   if (was_found) {
     408        1853 :     done_ = true;
     409        1853 :     found_ = false;
     410             :   }
     411             : }
     412             : 
     413             : 
     414         378 : void CallPrinter::VisitCallRuntime(CallRuntime* node) {
     415         378 :   FindArguments(node->arguments());
     416         378 : }
     417             : 
     418             : 
     419         846 : void CallPrinter::VisitUnaryOperation(UnaryOperation* node) {
     420             :   Token::Value op = node->op();
     421             :   bool needsSpace =
     422         423 :       op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
     423         423 :   Print("(");
     424         423 :   Print(Token::String(op));
     425         423 :   if (needsSpace) Print(" ");
     426         423 :   Find(node->expression(), true);
     427         423 :   Print(")");
     428         423 : }
     429             : 
     430             : 
     431        1011 : void CallPrinter::VisitCountOperation(CountOperation* node) {
     432         337 :   Print("(");
     433         346 :   if (node->is_prefix()) Print(Token::String(node->op()));
     434         337 :   Find(node->expression(), true);
     435         665 :   if (node->is_postfix()) Print(Token::String(node->op()));
     436         337 :   Print(")");
     437         337 : }
     438             : 
     439             : 
     440        1116 : void CallPrinter::VisitBinaryOperation(BinaryOperation* node) {
     441         279 :   Print("(");
     442         279 :   Find(node->left(), true);
     443         279 :   Print(" ");
     444         279 :   Print(Token::String(node->op()));
     445         279 :   Print(" ");
     446         279 :   Find(node->right(), true);
     447         279 :   Print(")");
     448         279 : }
     449             : 
     450         180 : void CallPrinter::VisitNaryOperation(NaryOperation* node) {
     451          45 :   Print("(");
     452          45 :   Find(node->first(), true);
     453         270 :   for (size_t i = 0; i < node->subsequent_length(); ++i) {
     454          90 :     Print(" ");
     455          90 :     Print(Token::String(node->op()));
     456          90 :     Print(" ");
     457          90 :     Find(node->subsequent(i), true);
     458             :   }
     459          45 :   Print(")");
     460          45 : }
     461             : 
     462        5432 : void CallPrinter::VisitCompareOperation(CompareOperation* node) {
     463        1358 :   Print("(");
     464        1358 :   Find(node->left(), true);
     465        1358 :   Print(" ");
     466        1358 :   Print(Token::String(node->op()));
     467        1358 :   Print(" ");
     468        1358 :   Find(node->right(), true);
     469        1358 :   Print(")");
     470        1358 : }
     471             : 
     472             : 
     473         738 : void CallPrinter::VisitSpread(Spread* node) {
     474         369 :   Print("(...");
     475         369 :   Find(node->expression(), true);
     476         369 :   Print(")");
     477         369 : }
     478             : 
     479           0 : void CallPrinter::VisitStoreInArrayLiteral(StoreInArrayLiteral* node) {
     480           0 :   Find(node->array());
     481           0 :   Find(node->index());
     482           0 :   Find(node->value());
     483           0 : }
     484             : 
     485           0 : void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
     486           0 :   UNREACHABLE();
     487             : }
     488             : 
     489           0 : void CallPrinter::VisitGetTemplateObject(GetTemplateObject* node) {}
     490             : 
     491           0 : void CallPrinter::VisitTemplateLiteral(TemplateLiteral* node) {
     492           0 :   for (Expression* substitution : *node->substitutions()) {
     493           0 :     Find(substitution, true);
     494             :   }
     495           0 : }
     496             : 
     497           0 : void CallPrinter::VisitImportCallExpression(ImportCallExpression* node) {
     498           0 :   Print("ImportCall(");
     499           0 :   Find(node->argument(), true);
     500           0 :   Print(")");
     501           0 : }
     502             : 
     503           0 : void CallPrinter::VisitThisFunction(ThisFunction* node) {}
     504             : 
     505             : 
     506           0 : void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
     507             : 
     508             : 
     509           0 : void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {
     510           9 :   Print("super");
     511           0 : }
     512             : 
     513             : 
     514       80263 : void CallPrinter::FindStatements(const ZonePtrList<Statement>* statements) {
     515       41212 :   if (statements == nullptr) return;
     516       98708 :   for (int i = 0; i < statements->length(); i++) {
     517       39051 :     Find(statements->at(i));
     518             :   }
     519             : }
     520             : 
     521       62033 : void CallPrinter::FindArguments(const ZonePtrList<Expression>* arguments) {
     522       43208 :   if (found_) return;
     523       65176 :   for (int i = 0; i < arguments->length(); i++) {
     524       24747 :     Find(arguments->at(i));
     525             :   }
     526             : }
     527             : 
     528      103100 : void CallPrinter::PrintLiteral(Handle<Object> value, bool quote) {
     529      206200 :   if (value->IsString()) {
     530       92216 :     if (quote) Print("\"");
     531       92216 :     Print(Handle<String>::cast(value));
     532       92216 :     if (quote) Print("\"");
     533       32652 :   } else if (value->IsNull(isolate_)) {
     534         720 :     Print("null");
     535       30492 :   } else if (value->IsTrue(isolate_)) {
     536        2349 :     Print("true");
     537       23445 :   } else if (value->IsFalse(isolate_)) {
     538        2952 :     Print("false");
     539       14589 :   } else if (value->IsUndefined(isolate_)) {
     540         261 :     Print("undefined");
     541        9204 :   } else if (value->IsNumber()) {
     542        4593 :     Print(isolate_->factory()->NumberToString(value));
     543          18 :   } else if (value->IsSymbol()) {
     544             :     // Symbols can only occur as literals if they were inserted by the parser.
     545           0 :     PrintLiteral(handle(Handle<Symbol>::cast(value)->name(), isolate_), false);
     546             :   }
     547      103100 : }
     548             : 
     549             : 
     550           0 : void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) {
     551           0 :   PrintLiteral(value->string(), quote);
     552           0 : }
     553             : 
     554             : 
     555             : //-----------------------------------------------------------------------------
     556             : 
     557             : 
     558             : #ifdef DEBUG
     559             : 
     560             : const char* AstPrinter::Print(AstNode* node) {
     561             :   Init();
     562             :   Visit(node);
     563             :   return output_;
     564             : }
     565             : 
     566             : void AstPrinter::Init() {
     567             :   if (size_ == 0) {
     568             :     DCHECK_NULL(output_);
     569             :     const int initial_size = 256;
     570             :     output_ = NewArray<char>(initial_size);
     571             :     size_ = initial_size;
     572             :   }
     573             :   output_[0] = '\0';
     574             :   pos_ = 0;
     575             : }
     576             : 
     577             : void AstPrinter::Print(const char* format, ...) {
     578             :   for (;;) {
     579             :     va_list arguments;
     580             :     va_start(arguments, format);
     581             :     int n = VSNPrintF(Vector<char>(output_, size_) + pos_,
     582             :                       format,
     583             :                       arguments);
     584             :     va_end(arguments);
     585             : 
     586             :     if (n >= 0) {
     587             :       // there was enough space - we are done
     588             :       pos_ += n;
     589             :       return;
     590             :     } else {
     591             :       // there was not enough space - allocate more and try again
     592             :       const int slack = 32;
     593             :       int new_size = size_ + (size_ >> 1) + slack;
     594             :       char* new_output = NewArray<char>(new_size);
     595             :       MemCopy(new_output, output_, pos_);
     596             :       DeleteArray(output_);
     597             :       output_ = new_output;
     598             :       size_ = new_size;
     599             :     }
     600             :   }
     601             : }
     602             : 
     603             : void AstPrinter::PrintLabels(ZonePtrList<const AstRawString>* labels) {
     604             :   if (labels != nullptr) {
     605             :     for (int i = 0; i < labels->length(); i++) {
     606             :       PrintLiteral(labels->at(i), false);
     607             :       Print(": ");
     608             :     }
     609             :   }
     610             : }
     611             : 
     612             : void AstPrinter::PrintLiteral(Literal* literal, bool quote) {
     613             :   switch (literal->type()) {
     614             :     case Literal::kString:
     615             :       PrintLiteral(literal->AsRawString(), quote);
     616             :       break;
     617             :     case Literal::kSymbol:
     618             :       const char* symbol;
     619             :       switch (literal->AsSymbol()) {
     620             :         case AstSymbol::kHomeObjectSymbol:
     621             :           symbol = "HomeObjectSymbol";
     622             :       }
     623             :       Print("%s", symbol);
     624             :       break;
     625             :     case Literal::kSmi:
     626             :       Print("%d", Smi::ToInt(literal->AsSmiLiteral()));
     627             :       break;
     628             :     case Literal::kHeapNumber:
     629             :       Print("%g", literal->AsNumber());
     630             :       break;
     631             :     case Literal::kBigInt:
     632             :       Print("%sn", literal->AsBigInt().c_str());
     633             :       break;
     634             :     case Literal::kNull:
     635             :       Print("null");
     636             :       break;
     637             :     case Literal::kUndefined:
     638             :       Print("undefined");
     639             :       break;
     640             :     case Literal::kTheHole:
     641             :       Print("the hole");
     642             :       break;
     643             :     case Literal::kBoolean:
     644             :       if (literal->ToBooleanIsTrue()) {
     645             :         Print("true");
     646             :       } else {
     647             :         Print("false");
     648             :       }
     649             :       break;
     650             :   }
     651             : }
     652             : 
     653             : void AstPrinter::PrintLiteral(const AstRawString* value, bool quote) {
     654             :   if (quote) Print("\"");
     655             :   if (value != nullptr) {
     656             :     const char* format = value->is_one_byte() ? "%c" : "%lc";
     657             :     const int increment = value->is_one_byte() ? 1 : 2;
     658             :     const unsigned char* raw_bytes = value->raw_data();
     659             :     for (int i = 0; i < value->length(); i += increment) {
     660             :       Print(format, raw_bytes[i]);
     661             :     }
     662             :   }
     663             :   if (quote) Print("\"");
     664             : }
     665             : 
     666             : void AstPrinter::PrintLiteral(const AstConsString* value, bool quote) {
     667             :   if (quote) Print("\"");
     668             :   if (value != nullptr) {
     669             :     std::forward_list<const AstRawString*> strings = value->ToRawStrings();
     670             :     for (const AstRawString* string : strings) {
     671             :       PrintLiteral(string, false);
     672             :     }
     673             :   }
     674             :   if (quote) Print("\"");
     675             : }
     676             : 
     677             : //-----------------------------------------------------------------------------
     678             : 
     679             : class IndentedScope {
     680             :  public:
     681             :   IndentedScope(AstPrinter* printer, const char* txt)
     682             :       : ast_printer_(printer) {
     683             :     ast_printer_->PrintIndented(txt);
     684             :     ast_printer_->Print("\n");
     685             :     ast_printer_->inc_indent();
     686             :   }
     687             : 
     688             :   IndentedScope(AstPrinter* printer, const char* txt, int pos)
     689             :       : ast_printer_(printer) {
     690             :     ast_printer_->PrintIndented(txt);
     691             :     ast_printer_->Print(" at %d\n", pos);
     692             :     ast_printer_->inc_indent();
     693             :   }
     694             : 
     695             :   virtual ~IndentedScope() {
     696             :     ast_printer_->dec_indent();
     697             :   }
     698             : 
     699             :  private:
     700             :   AstPrinter* ast_printer_;
     701             : };
     702             : 
     703             : 
     704             : //-----------------------------------------------------------------------------
     705             : 
     706             : AstPrinter::AstPrinter(uintptr_t stack_limit)
     707             :     : output_(nullptr), size_(0), pos_(0), indent_(0) {
     708             :   InitializeAstVisitor(stack_limit);
     709             : }
     710             : 
     711             : AstPrinter::~AstPrinter() {
     712             :   DCHECK_EQ(indent_, 0);
     713             :   DeleteArray(output_);
     714             : }
     715             : 
     716             : 
     717             : void AstPrinter::PrintIndented(const char* txt) {
     718             :   for (int i = 0; i < indent_; i++) {
     719             :     Print(". ");
     720             :   }
     721             :   Print("%s", txt);
     722             : }
     723             : 
     724             : void AstPrinter::PrintLiteralIndented(const char* info, Literal* literal,
     725             :                                       bool quote) {
     726             :   PrintIndented(info);
     727             :   Print(" ");
     728             :   PrintLiteral(literal, quote);
     729             :   Print("\n");
     730             : }
     731             : 
     732             : void AstPrinter::PrintLiteralIndented(const char* info,
     733             :                                       const AstRawString* value, bool quote) {
     734             :   PrintIndented(info);
     735             :   Print(" ");
     736             :   PrintLiteral(value, quote);
     737             :   Print("\n");
     738             : }
     739             : 
     740             : void AstPrinter::PrintLiteralIndented(const char* info,
     741             :                                       const AstConsString* value, bool quote) {
     742             :   PrintIndented(info);
     743             :   Print(" ");
     744             :   PrintLiteral(value, quote);
     745             :   Print("\n");
     746             : }
     747             : 
     748             : void AstPrinter::PrintLiteralWithModeIndented(const char* info, Variable* var,
     749             :                                               const AstRawString* value) {
     750             :   if (var == nullptr) {
     751             :     PrintLiteralIndented(info, value, true);
     752             :   } else {
     753             :     EmbeddedVector<char, 256> buf;
     754             :     int pos =
     755             :         SNPrintF(buf, "%s (%p) (mode = %s, assigned = %s", info,
     756             :                  reinterpret_cast<void*>(var), VariableMode2String(var->mode()),
     757             :                  var->maybe_assigned() == kMaybeAssigned ? "true" : "false");
     758             :     SNPrintF(buf + pos, ")");
     759             :     PrintLiteralIndented(buf.start(), value, true);
     760             :   }
     761             : }
     762             : 
     763             : void AstPrinter::PrintLabelsIndented(ZonePtrList<const AstRawString>* labels,
     764             :                                      const char* prefix) {
     765             :   if (labels == nullptr || labels->length() == 0) return;
     766             :   PrintIndented(prefix);
     767             :   Print("LABELS ");
     768             :   PrintLabels(labels);
     769             :   Print("\n");
     770             : }
     771             : 
     772             : 
     773             : void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
     774             :   if (node != nullptr) {
     775             :     IndentedScope indent(this, s, node->position());
     776             :     Visit(node);
     777             :   }
     778             : }
     779             : 
     780             : 
     781             : const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
     782             :   Init();
     783             :   { IndentedScope indent(this, "FUNC", program->position());
     784             :     PrintIndented("KIND");
     785             :     Print(" %d\n", program->kind());
     786             :     PrintIndented("SUSPEND COUNT");
     787             :     Print(" %d\n", program->suspend_count());
     788             :     PrintLiteralIndented("NAME", program->raw_name(), true);
     789             :     if (program->raw_inferred_name()) {
     790             :       PrintLiteralIndented("INFERRED NAME", program->raw_inferred_name(), true);
     791             :     }
     792             :     if (program->requires_instance_members_initializer()) {
     793             :       Print(" REQUIRES INSTANCE FIELDS INITIALIZER\n");
     794             :     }
     795             :     PrintParameters(program->scope());
     796             :     PrintDeclarations(program->scope()->declarations());
     797             :     PrintStatements(program->body());
     798             :   }
     799             :   return output_;
     800             : }
     801             : 
     802             : 
     803             : void AstPrinter::PrintOut(Isolate* isolate, AstNode* node) {
     804             :   AstPrinter printer(isolate->stack_guard()->real_climit());
     805             :   printer.Init();
     806             :   printer.Visit(node);
     807             :   PrintF("%s", printer.output_);
     808             : }
     809             : 
     810             : void AstPrinter::PrintDeclarations(Declaration::List* declarations) {
     811             :   if (!declarations->is_empty()) {
     812             :     IndentedScope indent(this, "DECLS");
     813             :     for (Declaration* decl : *declarations) Visit(decl);
     814             :   }
     815             : }
     816             : 
     817             : void AstPrinter::PrintParameters(DeclarationScope* scope) {
     818             :   if (scope->num_parameters() > 0) {
     819             :     IndentedScope indent(this, "PARAMS");
     820             :     for (int i = 0; i < scope->num_parameters(); i++) {
     821             :       PrintLiteralWithModeIndented("VAR", scope->parameter(i),
     822             :                                    scope->parameter(i)->raw_name());
     823             :     }
     824             :   }
     825             : }
     826             : 
     827             : void AstPrinter::PrintStatements(const ZonePtrList<Statement>* statements) {
     828             :   for (int i = 0; i < statements->length(); i++) {
     829             :     Visit(statements->at(i));
     830             :   }
     831             : }
     832             : 
     833             : void AstPrinter::PrintArguments(const ZonePtrList<Expression>* arguments) {
     834             :   for (int i = 0; i < arguments->length(); i++) {
     835             :     Visit(arguments->at(i));
     836             :   }
     837             : }
     838             : 
     839             : 
     840             : void AstPrinter::VisitBlock(Block* node) {
     841             :   const char* block_txt =
     842             :       node->ignore_completion_value() ? "BLOCK NOCOMPLETIONS" : "BLOCK";
     843             :   IndentedScope indent(this, block_txt, node->position());
     844             :   PrintLabelsIndented(node->labels());
     845             :   PrintStatements(node->statements());
     846             : }
     847             : 
     848             : 
     849             : // TODO(svenpanne) Start with IndentedScope.
     850             : void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
     851             :   PrintLiteralWithModeIndented("VARIABLE", node->var(),
     852             :                                node->var()->raw_name());
     853             : }
     854             : 
     855             : 
     856             : // TODO(svenpanne) Start with IndentedScope.
     857             : void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
     858             :   PrintIndented("FUNCTION ");
     859             :   PrintLiteral(node->var()->raw_name(), true);
     860             :   Print(" = function ");
     861             :   PrintLiteral(node->fun()->raw_name(), false);
     862             :   Print("\n");
     863             : }
     864             : 
     865             : 
     866             : void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
     867             :   IndentedScope indent(this, "EXPRESSION STATEMENT", node->position());
     868             :   Visit(node->expression());
     869             : }
     870             : 
     871             : 
     872             : void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
     873             :   IndentedScope indent(this, "EMPTY", node->position());
     874             : }
     875             : 
     876             : 
     877             : void AstPrinter::VisitSloppyBlockFunctionStatement(
     878             :     SloppyBlockFunctionStatement* node) {
     879             :   Visit(node->statement());
     880             : }
     881             : 
     882             : 
     883             : void AstPrinter::VisitIfStatement(IfStatement* node) {
     884             :   IndentedScope indent(this, "IF", node->position());
     885             :   PrintIndentedVisit("CONDITION", node->condition());
     886             :   PrintIndentedVisit("THEN", node->then_statement());
     887             :   if (node->HasElseStatement()) {
     888             :     PrintIndentedVisit("ELSE", node->else_statement());
     889             :   }
     890             : }
     891             : 
     892             : 
     893             : void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
     894             :   IndentedScope indent(this, "CONTINUE", node->position());
     895             :   PrintLabelsIndented(node->target()->labels());
     896             : }
     897             : 
     898             : 
     899             : void AstPrinter::VisitBreakStatement(BreakStatement* node) {
     900             :   IndentedScope indent(this, "BREAK", node->position());
     901             :   PrintLabelsIndented(node->target()->labels());
     902             : }
     903             : 
     904             : 
     905             : void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
     906             :   IndentedScope indent(this, "RETURN", node->position());
     907             :   Visit(node->expression());
     908             : }
     909             : 
     910             : 
     911             : void AstPrinter::VisitWithStatement(WithStatement* node) {
     912             :   IndentedScope indent(this, "WITH", node->position());
     913             :   PrintIndentedVisit("OBJECT", node->expression());
     914             :   PrintIndentedVisit("BODY", node->statement());
     915             : }
     916             : 
     917             : 
     918             : void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
     919             :   IndentedScope indent(this, "SWITCH", node->position());
     920             :   PrintLabelsIndented(node->labels());
     921             :   PrintIndentedVisit("TAG", node->tag());
     922             :   for (CaseClause* clause : *node->cases()) {
     923             :     if (clause->is_default()) {
     924             :       IndentedScope indent(this, "DEFAULT");
     925             :       PrintStatements(clause->statements());
     926             :     } else {
     927             :       IndentedScope indent(this, "CASE");
     928             :       Visit(clause->label());
     929             :       PrintStatements(clause->statements());
     930             :     }
     931             :   }
     932             : }
     933             : 
     934             : 
     935             : void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
     936             :   IndentedScope indent(this, "DO", node->position());
     937             :   PrintLabelsIndented(node->labels());
     938             :   PrintLabelsIndented(node->own_labels(), "OWN ");
     939             :   PrintIndentedVisit("BODY", node->body());
     940             :   PrintIndentedVisit("COND", node->cond());
     941             : }
     942             : 
     943             : 
     944             : void AstPrinter::VisitWhileStatement(WhileStatement* node) {
     945             :   IndentedScope indent(this, "WHILE", node->position());
     946             :   PrintLabelsIndented(node->labels());
     947             :   PrintLabelsIndented(node->own_labels(), "OWN ");
     948             :   PrintIndentedVisit("COND", node->cond());
     949             :   PrintIndentedVisit("BODY", node->body());
     950             : }
     951             : 
     952             : 
     953             : void AstPrinter::VisitForStatement(ForStatement* node) {
     954             :   IndentedScope indent(this, "FOR", node->position());
     955             :   PrintLabelsIndented(node->labels());
     956             :   PrintLabelsIndented(node->own_labels(), "OWN ");
     957             :   if (node->init()) PrintIndentedVisit("INIT", node->init());
     958             :   if (node->cond()) PrintIndentedVisit("COND", node->cond());
     959             :   PrintIndentedVisit("BODY", node->body());
     960             :   if (node->next()) PrintIndentedVisit("NEXT", node->next());
     961             : }
     962             : 
     963             : 
     964             : void AstPrinter::VisitForInStatement(ForInStatement* node) {
     965             :   IndentedScope indent(this, "FOR IN", node->position());
     966             :   PrintLabelsIndented(node->labels());
     967             :   PrintLabelsIndented(node->own_labels(), "OWN ");
     968             :   PrintIndentedVisit("FOR", node->each());
     969             :   PrintIndentedVisit("IN", node->subject());
     970             :   PrintIndentedVisit("BODY", node->body());
     971             : }
     972             : 
     973             : 
     974             : void AstPrinter::VisitForOfStatement(ForOfStatement* node) {
     975             :   IndentedScope indent(this, "FOR OF", node->position());
     976             :   PrintLabelsIndented(node->labels());
     977             :   PrintLabelsIndented(node->own_labels(), "OWN ");
     978             :   const char* for_type;
     979             :   switch (node->type()) {
     980             :     case IteratorType::kNormal:
     981             :       for_type = "FOR";
     982             :       break;
     983             :     case IteratorType::kAsync:
     984             :       for_type = "FOR AWAIT";
     985             :       break;
     986             :   }
     987             :   PrintIndentedVisit(for_type, node->each());
     988             :   PrintIndentedVisit("OF", node->subject());
     989             :   PrintIndentedVisit("BODY", node->body());
     990             : }
     991             : 
     992             : 
     993             : void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
     994             :   IndentedScope indent(this, "TRY CATCH", node->position());
     995             :   PrintIndentedVisit("TRY", node->try_block());
     996             :   PrintIndented("CATCH PREDICTION");
     997             :   const char* prediction = "";
     998             :   switch (node->GetCatchPrediction(HandlerTable::UNCAUGHT)) {
     999             :     case HandlerTable::UNCAUGHT:
    1000             :       prediction = "UNCAUGHT";
    1001             :       break;
    1002             :     case HandlerTable::CAUGHT:
    1003             :       prediction = "CAUGHT";
    1004             :       break;
    1005             :     case HandlerTable::DESUGARING:
    1006             :       prediction = "DESUGARING";
    1007             :       break;
    1008             :     case HandlerTable::ASYNC_AWAIT:
    1009             :       prediction = "ASYNC_AWAIT";
    1010             :       break;
    1011             :     case HandlerTable::PROMISE:
    1012             :       // Catch prediction resulting in promise rejections aren't
    1013             :       // parsed by the parser.
    1014             :       UNREACHABLE();
    1015             :   }
    1016             :   Print(" %s\n", prediction);
    1017             :   if (node->scope()) {
    1018             :     PrintLiteralWithModeIndented("CATCHVAR", node->scope()->catch_variable(),
    1019             :                                  node->scope()->catch_variable()->raw_name());
    1020             :   }
    1021             :   PrintIndentedVisit("CATCH", node->catch_block());
    1022             : }
    1023             : 
    1024             : void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
    1025             :   IndentedScope indent(this, "TRY FINALLY", node->position());
    1026             :   PrintIndentedVisit("TRY", node->try_block());
    1027             :   PrintIndentedVisit("FINALLY", node->finally_block());
    1028             : }
    1029             : 
    1030             : void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
    1031             :   IndentedScope indent(this, "DEBUGGER", node->position());
    1032             : }
    1033             : 
    1034             : 
    1035             : void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
    1036             :   IndentedScope indent(this, "FUNC LITERAL", node->position());
    1037             :   PrintLiteralIndented("NAME", node->raw_name(), false);
    1038             :   PrintLiteralIndented("INFERRED NAME", node->raw_inferred_name(), false);
    1039             :   // We don't want to see the function literal in this case: it
    1040             :   // will be printed via PrintProgram when the code for it is
    1041             :   // generated.
    1042             :   // PrintParameters(node->scope());
    1043             :   // PrintStatements(node->body());
    1044             : }
    1045             : 
    1046             : 
    1047             : void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
    1048             :   IndentedScope indent(this, "CLASS LITERAL", node->position());
    1049             :   PrintLiteralIndented("NAME", node->constructor()->raw_name(), false);
    1050             :   if (node->extends() != nullptr) {
    1051             :     PrintIndentedVisit("EXTENDS", node->extends());
    1052             :   }
    1053             :   if (node->static_fields_initializer() != nullptr) {
    1054             :     PrintIndentedVisit("STATIC FIELDS INITIALIZER",
    1055             :                        node->static_fields_initializer());
    1056             :   }
    1057             :   if (node->instance_members_initializer_function() != nullptr) {
    1058             :     PrintIndentedVisit("INSTANCE ELEMENTS INITIALIZER",
    1059             :                        node->instance_members_initializer_function());
    1060             :   }
    1061             :   PrintClassProperties(node->properties());
    1062             : }
    1063             : 
    1064             : void AstPrinter::VisitInitializeClassMembersStatement(
    1065             :     InitializeClassMembersStatement* node) {
    1066             :   IndentedScope indent(this, "INITIALIZE CLASS ELEMENTS", node->position());
    1067             :   PrintClassProperties(node->fields());
    1068             : }
    1069             : 
    1070             : void AstPrinter::PrintClassProperties(
    1071             :     const ZonePtrList<ClassLiteral::Property>* properties) {
    1072             :   for (int i = 0; i < properties->length(); i++) {
    1073             :     ClassLiteral::Property* property = properties->at(i);
    1074             :     const char* prop_kind = nullptr;
    1075             :     switch (property->kind()) {
    1076             :       case ClassLiteral::Property::METHOD:
    1077             :         prop_kind = "METHOD";
    1078             :         break;
    1079             :       case ClassLiteral::Property::GETTER:
    1080             :         prop_kind = "GETTER";
    1081             :         break;
    1082             :       case ClassLiteral::Property::SETTER:
    1083             :         prop_kind = "SETTER";
    1084             :         break;
    1085             :       case ClassLiteral::Property::FIELD:
    1086             :         prop_kind = "FIELD";
    1087             :         break;
    1088             :     }
    1089             :     EmbeddedVector<char, 128> buf;
    1090             :     SNPrintF(buf, "PROPERTY%s%s - %s", property->is_static() ? " - STATIC" : "",
    1091             :              property->is_private() ? " - PRIVATE" : " - PUBLIC", prop_kind);
    1092             :     IndentedScope prop(this, buf.start());
    1093             :     PrintIndentedVisit("KEY", properties->at(i)->key());
    1094             :     PrintIndentedVisit("VALUE", properties->at(i)->value());
    1095             :   }
    1096             : }
    1097             : 
    1098             : 
    1099             : void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
    1100             :   IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position());
    1101             :   PrintLiteralIndented("NAME", node->raw_name(), false);
    1102             : }
    1103             : 
    1104             : 
    1105             : void AstPrinter::VisitDoExpression(DoExpression* node) {
    1106             :   IndentedScope indent(this, "DO EXPRESSION", node->position());
    1107             :   PrintStatements(node->block()->statements());
    1108             : }
    1109             : 
    1110             : 
    1111             : void AstPrinter::VisitConditional(Conditional* node) {
    1112             :   IndentedScope indent(this, "CONDITIONAL", node->position());
    1113             :   PrintIndentedVisit("CONDITION", node->condition());
    1114             :   PrintIndentedVisit("THEN", node->then_expression());
    1115             :   PrintIndentedVisit("ELSE", node->else_expression());
    1116             : }
    1117             : 
    1118             : 
    1119             : void AstPrinter::VisitLiteral(Literal* node) {
    1120             :   PrintLiteralIndented("LITERAL", node, true);
    1121             : }
    1122             : 
    1123             : 
    1124             : void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
    1125             :   IndentedScope indent(this, "REGEXP LITERAL", node->position());
    1126             :   PrintLiteralIndented("PATTERN", node->raw_pattern(), false);
    1127             :   int i = 0;
    1128             :   EmbeddedVector<char, 128> buf;
    1129             :   if (node->flags() & RegExp::kGlobal) buf[i++] = 'g';
    1130             :   if (node->flags() & RegExp::kIgnoreCase) buf[i++] = 'i';
    1131             :   if (node->flags() & RegExp::kMultiline) buf[i++] = 'm';
    1132             :   if (node->flags() & RegExp::kUnicode) buf[i++] = 'u';
    1133             :   if (node->flags() & RegExp::kSticky) buf[i++] = 'y';
    1134             :   buf[i] = '\0';
    1135             :   PrintIndented("FLAGS ");
    1136             :   Print("%s", buf.start());
    1137             :   Print("\n");
    1138             : }
    1139             : 
    1140             : 
    1141             : void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
    1142             :   IndentedScope indent(this, "OBJ LITERAL", node->position());
    1143             :   PrintObjectProperties(node->properties());
    1144             : }
    1145             : 
    1146             : void AstPrinter::PrintObjectProperties(
    1147             :     const ZonePtrList<ObjectLiteral::Property>* properties) {
    1148             :   for (int i = 0; i < properties->length(); i++) {
    1149             :     ObjectLiteral::Property* property = properties->at(i);
    1150             :     const char* prop_kind = nullptr;
    1151             :     switch (property->kind()) {
    1152             :       case ObjectLiteral::Property::CONSTANT:
    1153             :         prop_kind = "CONSTANT";
    1154             :         break;
    1155             :       case ObjectLiteral::Property::COMPUTED:
    1156             :         prop_kind = "COMPUTED";
    1157             :         break;
    1158             :       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
    1159             :         prop_kind = "MATERIALIZED_LITERAL";
    1160             :         break;
    1161             :       case ObjectLiteral::Property::PROTOTYPE:
    1162             :         prop_kind = "PROTOTYPE";
    1163             :         break;
    1164             :       case ObjectLiteral::Property::GETTER:
    1165             :         prop_kind = "GETTER";
    1166             :         break;
    1167             :       case ObjectLiteral::Property::SETTER:
    1168             :         prop_kind = "SETTER";
    1169             :         break;
    1170             :       case ObjectLiteral::Property::SPREAD:
    1171             :         prop_kind = "SPREAD";
    1172             :         break;
    1173             :     }
    1174             :     EmbeddedVector<char, 128> buf;
    1175             :     SNPrintF(buf, "PROPERTY - %s", prop_kind);
    1176             :     IndentedScope prop(this, buf.start());
    1177             :     PrintIndentedVisit("KEY", properties->at(i)->key());
    1178             :     PrintIndentedVisit("VALUE", properties->at(i)->value());
    1179             :   }
    1180             : }
    1181             : 
    1182             : 
    1183             : void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
    1184             :   IndentedScope indent(this, "ARRAY LITERAL", node->position());
    1185             :   if (node->values()->length() > 0) {
    1186             :     IndentedScope indent(this, "VALUES", node->position());
    1187             :     for (int i = 0; i < node->values()->length(); i++) {
    1188             :       Visit(node->values()->at(i));
    1189             :     }
    1190             :   }
    1191             : }
    1192             : 
    1193             : 
    1194             : void AstPrinter::VisitVariableProxy(VariableProxy* node) {
    1195             :   EmbeddedVector<char, 128> buf;
    1196             :   int pos = SNPrintF(buf, "VAR PROXY");
    1197             : 
    1198             :   if (!node->is_resolved()) {
    1199             :     SNPrintF(buf + pos, " unresolved");
    1200             :     PrintLiteralWithModeIndented(buf.start(), nullptr, node->raw_name());
    1201             :   } else {
    1202             :     Variable* var = node->var();
    1203             :     switch (var->location()) {
    1204             :       case VariableLocation::UNALLOCATED:
    1205             :         SNPrintF(buf + pos, " unallocated");
    1206             :         break;
    1207             :       case VariableLocation::PARAMETER:
    1208             :         SNPrintF(buf + pos, " parameter[%d]", var->index());
    1209             :         break;
    1210             :       case VariableLocation::LOCAL:
    1211             :         SNPrintF(buf + pos, " local[%d]", var->index());
    1212             :         break;
    1213             :       case VariableLocation::CONTEXT:
    1214             :         SNPrintF(buf + pos, " context[%d]", var->index());
    1215             :         break;
    1216             :       case VariableLocation::LOOKUP:
    1217             :         SNPrintF(buf + pos, " lookup");
    1218             :         break;
    1219             :       case VariableLocation::MODULE:
    1220             :         SNPrintF(buf + pos, " module");
    1221             :         break;
    1222             :     }
    1223             :     PrintLiteralWithModeIndented(buf.start(), var, node->raw_name());
    1224             :   }
    1225             : }
    1226             : 
    1227             : 
    1228             : void AstPrinter::VisitAssignment(Assignment* node) {
    1229             :   IndentedScope indent(this, Token::Name(node->op()), node->position());
    1230             :   Visit(node->target());
    1231             :   Visit(node->value());
    1232             : }
    1233             : 
    1234             : void AstPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
    1235             :   VisitAssignment(node);
    1236             : }
    1237             : 
    1238             : void AstPrinter::VisitYield(Yield* node) {
    1239             :   EmbeddedVector<char, 128> buf;
    1240             :   SNPrintF(buf, "YIELD");
    1241             :   IndentedScope indent(this, buf.start(), node->position());
    1242             :   Visit(node->expression());
    1243             : }
    1244             : 
    1245             : void AstPrinter::VisitYieldStar(YieldStar* node) {
    1246             :   EmbeddedVector<char, 128> buf;
    1247             :   SNPrintF(buf, "YIELD_STAR");
    1248             :   IndentedScope indent(this, buf.start(), node->position());
    1249             :   Visit(node->expression());
    1250             : }
    1251             : 
    1252             : void AstPrinter::VisitAwait(Await* node) {
    1253             :   EmbeddedVector<char, 128> buf;
    1254             :   SNPrintF(buf, "AWAIT");
    1255             :   IndentedScope indent(this, buf.start(), node->position());
    1256             :   Visit(node->expression());
    1257             : }
    1258             : 
    1259             : void AstPrinter::VisitThrow(Throw* node) {
    1260             :   IndentedScope indent(this, "THROW", node->position());
    1261             :   Visit(node->exception());
    1262             : }
    1263             : 
    1264             : void AstPrinter::VisitProperty(Property* node) {
    1265             :   EmbeddedVector<char, 128> buf;
    1266             :   SNPrintF(buf, "PROPERTY");
    1267             :   IndentedScope indent(this, buf.start(), node->position());
    1268             : 
    1269             :   Visit(node->obj());
    1270             :   AssignType property_kind = Property::GetAssignType(node);
    1271             :   if (property_kind == NAMED_PROPERTY ||
    1272             :       property_kind == NAMED_SUPER_PROPERTY) {
    1273             :     PrintLiteralIndented("NAME", node->key()->AsLiteral(), false);
    1274             :   } else {
    1275             :     DCHECK(property_kind == KEYED_PROPERTY ||
    1276             :            property_kind == KEYED_SUPER_PROPERTY);
    1277             :     PrintIndentedVisit("KEY", node->key());
    1278             :   }
    1279             : }
    1280             : 
    1281             : void AstPrinter::VisitResolvedProperty(ResolvedProperty* node) {
    1282             :   EmbeddedVector<char, 128> buf;
    1283             :   SNPrintF(buf, "RESOLVED-PROPERTY");
    1284             :   IndentedScope indent(this, buf.start(), node->position());
    1285             : 
    1286             :   PrintIndentedVisit("RECEIVER", node->object());
    1287             :   PrintIndentedVisit("PROPERTY", node->property());
    1288             : }
    1289             : 
    1290             : void AstPrinter::VisitCall(Call* node) {
    1291             :   EmbeddedVector<char, 128> buf;
    1292             :   SNPrintF(buf, "CALL");
    1293             :   IndentedScope indent(this, buf.start());
    1294             : 
    1295             :   Visit(node->expression());
    1296             :   PrintArguments(node->arguments());
    1297             : }
    1298             : 
    1299             : 
    1300             : void AstPrinter::VisitCallNew(CallNew* node) {
    1301             :   IndentedScope indent(this, "CALL NEW", node->position());
    1302             :   Visit(node->expression());
    1303             :   PrintArguments(node->arguments());
    1304             : }
    1305             : 
    1306             : 
    1307             : void AstPrinter::VisitCallRuntime(CallRuntime* node) {
    1308             :   EmbeddedVector<char, 128> buf;
    1309             :   SNPrintF(buf, "CALL RUNTIME %s%s", node->debug_name(),
    1310             :            node->is_jsruntime() ? " (JS function)" : "");
    1311             :   IndentedScope indent(this, buf.start(), node->position());
    1312             :   PrintArguments(node->arguments());
    1313             : }
    1314             : 
    1315             : 
    1316             : void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
    1317             :   IndentedScope indent(this, Token::Name(node->op()), node->position());
    1318             :   Visit(node->expression());
    1319             : }
    1320             : 
    1321             : 
    1322             : void AstPrinter::VisitCountOperation(CountOperation* node) {
    1323             :   EmbeddedVector<char, 128> buf;
    1324             :   SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
    1325             :            Token::Name(node->op()));
    1326             :   IndentedScope indent(this, buf.start(), node->position());
    1327             :   Visit(node->expression());
    1328             : }
    1329             : 
    1330             : 
    1331             : void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
    1332             :   IndentedScope indent(this, Token::Name(node->op()), node->position());
    1333             :   Visit(node->left());
    1334             :   Visit(node->right());
    1335             : }
    1336             : 
    1337             : void AstPrinter::VisitNaryOperation(NaryOperation* node) {
    1338             :   IndentedScope indent(this, Token::Name(node->op()), node->position());
    1339             :   Visit(node->first());
    1340             :   for (size_t i = 0; i < node->subsequent_length(); ++i) {
    1341             :     Visit(node->subsequent(i));
    1342             :   }
    1343             : }
    1344             : 
    1345             : void AstPrinter::VisitCompareOperation(CompareOperation* node) {
    1346             :   IndentedScope indent(this, Token::Name(node->op()), node->position());
    1347             :   Visit(node->left());
    1348             :   Visit(node->right());
    1349             : }
    1350             : 
    1351             : 
    1352             : void AstPrinter::VisitSpread(Spread* node) {
    1353             :   IndentedScope indent(this, "SPREAD", node->position());
    1354             :   Visit(node->expression());
    1355             : }
    1356             : 
    1357             : void AstPrinter::VisitStoreInArrayLiteral(StoreInArrayLiteral* node) {
    1358             :   IndentedScope indent(this, "STORE IN ARRAY LITERAL", node->position());
    1359             :   PrintIndentedVisit("ARRAY", node->array());
    1360             :   PrintIndentedVisit("INDEX", node->index());
    1361             :   PrintIndentedVisit("VALUE", node->value());
    1362             : }
    1363             : 
    1364             : void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
    1365             :   IndentedScope indent(this, "()", node->position());
    1366             : }
    1367             : 
    1368             : void AstPrinter::VisitGetTemplateObject(GetTemplateObject* node) {
    1369             :   IndentedScope indent(this, "GET-TEMPLATE-OBJECT", node->position());
    1370             : }
    1371             : 
    1372             : void AstPrinter::VisitTemplateLiteral(TemplateLiteral* node) {
    1373             :   IndentedScope indent(this, "TEMPLATE-LITERAL", node->position());
    1374             :   const AstRawString* string = node->string_parts()->first();
    1375             :   if (!string->IsEmpty()) PrintLiteralIndented("SPAN", string, true);
    1376             :   for (int i = 0; i < node->substitutions()->length();) {
    1377             :     PrintIndentedVisit("EXPR", node->substitutions()->at(i++));
    1378             :     if (i < node->string_parts()->length()) {
    1379             :       string = node->string_parts()->at(i);
    1380             :       if (!string->IsEmpty()) PrintLiteralIndented("SPAN", string, true);
    1381             :     }
    1382             :   }
    1383             : }
    1384             : 
    1385             : void AstPrinter::VisitImportCallExpression(ImportCallExpression* node) {
    1386             :   IndentedScope indent(this, "IMPORT-CALL", node->position());
    1387             :   Visit(node->argument());
    1388             : }
    1389             : 
    1390             : void AstPrinter::VisitThisFunction(ThisFunction* node) {
    1391             :   IndentedScope indent(this, "THIS-FUNCTION", node->position());
    1392             : }
    1393             : 
    1394             : 
    1395             : void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
    1396             :   IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE", node->position());
    1397             : }
    1398             : 
    1399             : 
    1400             : void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
    1401             :   IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position());
    1402             : }
    1403             : 
    1404             : 
    1405             : #endif  // DEBUG
    1406             : 
    1407             : }  // namespace internal
    1408      183867 : }  // namespace v8

Generated by: LCOV version 1.10