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 
14 namespace v8 {
15 namespace internal {
16 
CallPrinter(Isolate * isolate,bool is_builtin)17 CallPrinter::CallPrinter(Isolate* isolate, bool is_builtin)
18     : builder_(isolate) {
19   isolate_ = isolate;
20   position_ = 0;
21   num_prints_ = 0;
22   found_ = false;
23   done_ = false;
24   is_builtin_ = is_builtin;
25   InitializeAstVisitor(isolate);
26 }
27 
Print(FunctionLiteral * program,int position)28 Handle<String> CallPrinter::Print(FunctionLiteral* program, int position) {
29   num_prints_ = 0;
30   position_ = position;
31   Find(program);
32   return builder_.Finish().ToHandleChecked();
33 }
34 
35 
Find(AstNode * node,bool print)36 void CallPrinter::Find(AstNode* node, bool print) {
37   if (done_) return;
38   if (found_) {
39     if (print) {
40       int prev_num_prints = num_prints_;
41       Visit(node);
42       if (prev_num_prints != num_prints_) return;
43     }
44     Print("(intermediate value)");
45   } else {
46     Visit(node);
47   }
48 }
49 
Print(const char * str)50 void CallPrinter::Print(const char* str) {
51   if (!found_ || done_) return;
52   num_prints_++;
53   builder_.AppendCString(str);
54 }
55 
Print(Handle<String> str)56 void CallPrinter::Print(Handle<String> str) {
57   if (!found_ || done_) return;
58   num_prints_++;
59   builder_.AppendString(str);
60 }
61 
VisitBlock(Block * node)62 void CallPrinter::VisitBlock(Block* node) {
63   FindStatements(node->statements());
64 }
65 
66 
VisitVariableDeclaration(VariableDeclaration * node)67 void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {}
68 
69 
VisitFunctionDeclaration(FunctionDeclaration * node)70 void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {}
71 
72 
VisitExpressionStatement(ExpressionStatement * node)73 void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) {
74   Find(node->expression());
75 }
76 
77 
VisitEmptyStatement(EmptyStatement * node)78 void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {}
79 
80 
VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement * node)81 void CallPrinter::VisitSloppyBlockFunctionStatement(
82     SloppyBlockFunctionStatement* node) {
83   Find(node->statement());
84 }
85 
86 
VisitIfStatement(IfStatement * node)87 void CallPrinter::VisitIfStatement(IfStatement* node) {
88   Find(node->condition());
89   Find(node->then_statement());
90   if (node->HasElseStatement()) {
91     Find(node->else_statement());
92   }
93 }
94 
95 
VisitContinueStatement(ContinueStatement * node)96 void CallPrinter::VisitContinueStatement(ContinueStatement* node) {}
97 
98 
VisitBreakStatement(BreakStatement * node)99 void CallPrinter::VisitBreakStatement(BreakStatement* node) {}
100 
101 
VisitReturnStatement(ReturnStatement * node)102 void CallPrinter::VisitReturnStatement(ReturnStatement* node) {
103   Find(node->expression());
104 }
105 
106 
VisitWithStatement(WithStatement * node)107 void CallPrinter::VisitWithStatement(WithStatement* node) {
108   Find(node->expression());
109   Find(node->statement());
110 }
111 
112 
VisitSwitchStatement(SwitchStatement * node)113 void CallPrinter::VisitSwitchStatement(SwitchStatement* node) {
114   Find(node->tag());
115   ZoneList<CaseClause*>* cases = node->cases();
116   for (int i = 0; i < cases->length(); i++) Find(cases->at(i));
117 }
118 
119 
VisitCaseClause(CaseClause * clause)120 void CallPrinter::VisitCaseClause(CaseClause* clause) {
121   if (!clause->is_default()) {
122     Find(clause->label());
123   }
124   FindStatements(clause->statements());
125 }
126 
127 
VisitDoWhileStatement(DoWhileStatement * node)128 void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
129   Find(node->body());
130   Find(node->cond());
131 }
132 
133 
VisitWhileStatement(WhileStatement * node)134 void CallPrinter::VisitWhileStatement(WhileStatement* node) {
135   Find(node->cond());
136   Find(node->body());
137 }
138 
139 
VisitForStatement(ForStatement * node)140 void CallPrinter::VisitForStatement(ForStatement* node) {
141   if (node->init() != NULL) {
142     Find(node->init());
143   }
144   if (node->cond() != NULL) Find(node->cond());
145   if (node->next() != NULL) Find(node->next());
146   Find(node->body());
147 }
148 
149 
VisitForInStatement(ForInStatement * node)150 void CallPrinter::VisitForInStatement(ForInStatement* node) {
151   Find(node->each());
152   Find(node->enumerable());
153   Find(node->body());
154 }
155 
156 
VisitForOfStatement(ForOfStatement * node)157 void CallPrinter::VisitForOfStatement(ForOfStatement* node) {
158   Find(node->assign_iterator());
159   Find(node->next_result());
160   Find(node->result_done());
161   Find(node->assign_each());
162   Find(node->body());
163 }
164 
165 
VisitTryCatchStatement(TryCatchStatement * node)166 void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
167   Find(node->try_block());
168   Find(node->catch_block());
169 }
170 
171 
VisitTryFinallyStatement(TryFinallyStatement * node)172 void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
173   Find(node->try_block());
174   Find(node->finally_block());
175 }
176 
177 
VisitDebuggerStatement(DebuggerStatement * node)178 void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {}
179 
180 
VisitFunctionLiteral(FunctionLiteral * node)181 void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
182   FindStatements(node->body());
183 }
184 
185 
VisitClassLiteral(ClassLiteral * node)186 void CallPrinter::VisitClassLiteral(ClassLiteral* node) {
187   if (node->extends()) Find(node->extends());
188   for (int i = 0; i < node->properties()->length(); i++) {
189     Find(node->properties()->at(i)->value());
190   }
191 }
192 
193 
VisitNativeFunctionLiteral(NativeFunctionLiteral * node)194 void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {}
195 
196 
VisitDoExpression(DoExpression * node)197 void CallPrinter::VisitDoExpression(DoExpression* node) { Find(node->block()); }
198 
199 
VisitConditional(Conditional * node)200 void CallPrinter::VisitConditional(Conditional* node) {
201   Find(node->condition());
202   Find(node->then_expression());
203   Find(node->else_expression());
204 }
205 
206 
VisitLiteral(Literal * node)207 void CallPrinter::VisitLiteral(Literal* node) {
208   PrintLiteral(node->value(), true);
209 }
210 
211 
VisitRegExpLiteral(RegExpLiteral * node)212 void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
213   Print("/");
214   PrintLiteral(node->pattern(), false);
215   Print("/");
216   if (node->flags() & RegExp::kGlobal) Print("g");
217   if (node->flags() & RegExp::kIgnoreCase) Print("i");
218   if (node->flags() & RegExp::kMultiline) Print("m");
219   if (node->flags() & RegExp::kUnicode) Print("u");
220   if (node->flags() & RegExp::kSticky) Print("y");
221 }
222 
223 
VisitObjectLiteral(ObjectLiteral * node)224 void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) {
225   for (int i = 0; i < node->properties()->length(); i++) {
226     Find(node->properties()->at(i)->value());
227   }
228 }
229 
230 
VisitArrayLiteral(ArrayLiteral * node)231 void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) {
232   Print("[");
233   for (int i = 0; i < node->values()->length(); i++) {
234     if (i != 0) Print(",");
235     Find(node->values()->at(i), true);
236   }
237   Print("]");
238 }
239 
240 
VisitVariableProxy(VariableProxy * node)241 void CallPrinter::VisitVariableProxy(VariableProxy* node) {
242   if (is_builtin_) {
243     // Variable names of builtins are meaningless due to minification.
244     Print("(var)");
245   } else {
246     PrintLiteral(node->name(), false);
247   }
248 }
249 
250 
VisitAssignment(Assignment * node)251 void CallPrinter::VisitAssignment(Assignment* node) {
252   Find(node->target());
253   Find(node->value());
254 }
255 
256 
VisitYield(Yield * node)257 void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); }
258 
259 
VisitThrow(Throw * node)260 void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); }
261 
262 
VisitProperty(Property * node)263 void CallPrinter::VisitProperty(Property* node) {
264   Expression* key = node->key();
265   Literal* literal = key->AsLiteral();
266   if (literal != NULL && literal->value()->IsInternalizedString()) {
267     Find(node->obj(), true);
268     Print(".");
269     PrintLiteral(literal->value(), false);
270   } else {
271     Find(node->obj(), true);
272     Print("[");
273     Find(key, true);
274     Print("]");
275   }
276 }
277 
278 
VisitCall(Call * node)279 void CallPrinter::VisitCall(Call* node) {
280   bool was_found = !found_ && node->position() == position_;
281   if (was_found) {
282     // Bail out if the error is caused by a direct call to a variable in builtin
283     // code. The variable name is meaningless due to minification.
284     if (is_builtin_ && node->expression()->IsVariableProxy()) {
285       done_ = true;
286       return;
287     }
288     found_ = true;
289   }
290   Find(node->expression(), true);
291   if (!was_found) Print("(...)");
292   FindArguments(node->arguments());
293   if (was_found) done_ = true;
294 }
295 
296 
VisitCallNew(CallNew * node)297 void CallPrinter::VisitCallNew(CallNew* node) {
298   bool was_found = !found_ && node->position() == position_;
299   if (was_found) {
300     // Bail out if the error is caused by a direct call to a variable in builtin
301     // code. The variable name is meaningless due to minification.
302     if (is_builtin_ && node->expression()->IsVariableProxy()) {
303       done_ = true;
304       return;
305     }
306     found_ = true;
307   }
308   Find(node->expression(), was_found);
309   FindArguments(node->arguments());
310   if (was_found) done_ = true;
311 }
312 
313 
VisitCallRuntime(CallRuntime * node)314 void CallPrinter::VisitCallRuntime(CallRuntime* node) {
315   FindArguments(node->arguments());
316 }
317 
318 
VisitUnaryOperation(UnaryOperation * node)319 void CallPrinter::VisitUnaryOperation(UnaryOperation* node) {
320   Token::Value op = node->op();
321   bool needsSpace =
322       op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
323   Print("(");
324   Print(Token::String(op));
325   if (needsSpace) Print(" ");
326   Find(node->expression(), true);
327   Print(")");
328 }
329 
330 
VisitCountOperation(CountOperation * node)331 void CallPrinter::VisitCountOperation(CountOperation* node) {
332   Print("(");
333   if (node->is_prefix()) Print(Token::String(node->op()));
334   Find(node->expression(), true);
335   if (node->is_postfix()) Print(Token::String(node->op()));
336   Print(")");
337 }
338 
339 
VisitBinaryOperation(BinaryOperation * node)340 void CallPrinter::VisitBinaryOperation(BinaryOperation* node) {
341   Print("(");
342   Find(node->left(), true);
343   Print(" ");
344   Print(Token::String(node->op()));
345   Print(" ");
346   Find(node->right(), true);
347   Print(")");
348 }
349 
350 
VisitCompareOperation(CompareOperation * node)351 void CallPrinter::VisitCompareOperation(CompareOperation* node) {
352   Print("(");
353   Find(node->left(), true);
354   Print(" ");
355   Print(Token::String(node->op()));
356   Print(" ");
357   Find(node->right(), true);
358   Print(")");
359 }
360 
361 
VisitSpread(Spread * node)362 void CallPrinter::VisitSpread(Spread* node) {
363   Print("(...");
364   Find(node->expression(), true);
365   Print(")");
366 }
367 
368 
VisitEmptyParentheses(EmptyParentheses * node)369 void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
370   UNREACHABLE();
371 }
372 
373 
VisitThisFunction(ThisFunction * node)374 void CallPrinter::VisitThisFunction(ThisFunction* node) {}
375 
376 
VisitSuperPropertyReference(SuperPropertyReference * node)377 void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
378 
379 
VisitSuperCallReference(SuperCallReference * node)380 void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {
381   Print("super");
382 }
383 
384 
VisitRewritableExpression(RewritableExpression * node)385 void CallPrinter::VisitRewritableExpression(RewritableExpression* node) {
386   Find(node->expression());
387 }
388 
389 
FindStatements(ZoneList<Statement * > * statements)390 void CallPrinter::FindStatements(ZoneList<Statement*>* statements) {
391   if (statements == NULL) return;
392   for (int i = 0; i < statements->length(); i++) {
393     Find(statements->at(i));
394   }
395 }
396 
397 
FindArguments(ZoneList<Expression * > * arguments)398 void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) {
399   if (found_) return;
400   for (int i = 0; i < arguments->length(); i++) {
401     Find(arguments->at(i));
402   }
403 }
404 
PrintLiteral(Handle<Object> value,bool quote)405 void CallPrinter::PrintLiteral(Handle<Object> value, bool quote) {
406   if (value->IsString()) {
407     if (quote) Print("\"");
408     Print(Handle<String>::cast(value));
409     if (quote) Print("\"");
410   } else if (value->IsNull(isolate_)) {
411     Print("null");
412   } else if (value->IsTrue(isolate_)) {
413     Print("true");
414   } else if (value->IsFalse(isolate_)) {
415     Print("false");
416   } else if (value->IsUndefined(isolate_)) {
417     Print("undefined");
418   } else if (value->IsNumber()) {
419     Print(isolate_->factory()->NumberToString(value));
420   } else if (value->IsSymbol()) {
421     // Symbols can only occur as literals if they were inserted by the parser.
422     PrintLiteral(handle(Handle<Symbol>::cast(value)->name(), isolate_), false);
423   }
424 }
425 
426 
PrintLiteral(const AstRawString * value,bool quote)427 void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) {
428   PrintLiteral(value->string(), quote);
429 }
430 
431 
432 //-----------------------------------------------------------------------------
433 
434 
435 #ifdef DEBUG
436 
437 // A helper for ast nodes that use FeedbackVectorSlots.
FormatSlotNode(Vector<char> * buf,Expression * node,const char * node_name,FeedbackVectorSlot slot)438 static int FormatSlotNode(Vector<char>* buf, Expression* node,
439                           const char* node_name, FeedbackVectorSlot slot) {
440   int pos = SNPrintF(*buf, "%s", node_name);
441   if (!slot.IsInvalid()) {
442     pos += SNPrintF(*buf + pos, " Slot(%d)", slot.ToInt());
443   }
444   return pos;
445 }
446 
Print(AstNode * node)447 const char* AstPrinter::Print(AstNode* node) {
448   Init();
449   Visit(node);
450   return output_;
451 }
452 
Init()453 void AstPrinter::Init() {
454   if (size_ == 0) {
455     DCHECK(output_ == NULL);
456     const int initial_size = 256;
457     output_ = NewArray<char>(initial_size);
458     size_ = initial_size;
459   }
460   output_[0] = '\0';
461   pos_ = 0;
462 }
463 
Print(const char * format,...)464 void AstPrinter::Print(const char* format, ...) {
465   for (;;) {
466     va_list arguments;
467     va_start(arguments, format);
468     int n = VSNPrintF(Vector<char>(output_, size_) + pos_,
469                       format,
470                       arguments);
471     va_end(arguments);
472 
473     if (n >= 0) {
474       // there was enough space - we are done
475       pos_ += n;
476       return;
477     } else {
478       // there was not enough space - allocate more and try again
479       const int slack = 32;
480       int new_size = size_ + (size_ >> 1) + slack;
481       char* new_output = NewArray<char>(new_size);
482       MemCopy(new_output, output_, pos_);
483       DeleteArray(output_);
484       output_ = new_output;
485       size_ = new_size;
486     }
487   }
488 }
489 
PrintLabels(ZoneList<const AstRawString * > * labels)490 void AstPrinter::PrintLabels(ZoneList<const AstRawString*>* labels) {
491   if (labels != NULL) {
492     for (int i = 0; i < labels->length(); i++) {
493       PrintLiteral(labels->at(i), false);
494       Print(": ");
495     }
496   }
497 }
498 
PrintLiteral(Handle<Object> value,bool quote)499 void AstPrinter::PrintLiteral(Handle<Object> value, bool quote) {
500   Object* object = *value;
501   if (object->IsString()) {
502     String* string = String::cast(object);
503     if (quote) Print("\"");
504     for (int i = 0; i < string->length(); i++) {
505       Print("%c", string->Get(i));
506     }
507     if (quote) Print("\"");
508   } else if (object->IsNull(isolate_)) {
509     Print("null");
510   } else if (object->IsTrue(isolate_)) {
511     Print("true");
512   } else if (object->IsFalse(isolate_)) {
513     Print("false");
514   } else if (object->IsUndefined(isolate_)) {
515     Print("undefined");
516   } else if (object->IsNumber()) {
517     Print("%g", object->Number());
518   } else if (object->IsJSObject()) {
519     // regular expression
520     if (object->IsJSFunction()) {
521       Print("JS-Function");
522     } else if (object->IsJSArray()) {
523       Print("JS-array[%u]",
524             Smi::cast(JSArray::cast(object)->length())->value());
525     } else if (object->IsJSObject()) {
526       Print("JS-Object");
527     } else {
528       Print("?UNKNOWN?");
529     }
530   } else if (object->IsFixedArray()) {
531     Print("FixedArray");
532   } else if (object->IsSymbol()) {
533     // Symbols can only occur as literals if they were inserted by the parser.
534     Symbol* symbol = Symbol::cast(object);
535     if (symbol->name()->IsString()) {
536       int length = 0;
537       String* string = String::cast(symbol->name());
538       std::unique_ptr<char[]> desc = string->ToCString(
539           ALLOW_NULLS, FAST_STRING_TRAVERSAL, 0, string->length(), &length);
540       Print("Symbol(%*s)", length, desc.get());
541     } else {
542       Print("Symbol()");
543     }
544   } else {
545     Print("<unknown literal %p>", static_cast<void*>(object));
546   }
547 }
548 
PrintLiteral(const AstRawString * value,bool quote)549 void AstPrinter::PrintLiteral(const AstRawString* value, bool quote) {
550   PrintLiteral(value->string(), quote);
551 }
552 
553 
554 //-----------------------------------------------------------------------------
555 
556 class IndentedScope BASE_EMBEDDED {
557  public:
IndentedScope(AstPrinter * printer,const char * txt)558   IndentedScope(AstPrinter* printer, const char* txt)
559       : ast_printer_(printer) {
560     ast_printer_->PrintIndented(txt);
561     ast_printer_->Print("\n");
562     ast_printer_->inc_indent();
563   }
564 
IndentedScope(AstPrinter * printer,const char * txt,int pos)565   IndentedScope(AstPrinter* printer, const char* txt, int pos)
566       : ast_printer_(printer) {
567     ast_printer_->PrintIndented(txt);
568     ast_printer_->Print(" at %d\n", pos);
569     ast_printer_->inc_indent();
570   }
571 
~IndentedScope()572   virtual ~IndentedScope() {
573     ast_printer_->dec_indent();
574   }
575 
576  private:
577   AstPrinter* ast_printer_;
578 };
579 
580 
581 //-----------------------------------------------------------------------------
582 
AstPrinter(Isolate * isolate)583 AstPrinter::AstPrinter(Isolate* isolate)
584     : isolate_(isolate), output_(nullptr), size_(0), pos_(0), indent_(0) {
585   InitializeAstVisitor(isolate);
586 }
587 
~AstPrinter()588 AstPrinter::~AstPrinter() {
589   DCHECK(indent_ == 0);
590   DeleteArray(output_);
591 }
592 
593 
PrintIndented(const char * txt)594 void AstPrinter::PrintIndented(const char* txt) {
595   for (int i = 0; i < indent_; i++) {
596     Print(". ");
597   }
598   Print("%s", txt);
599 }
600 
601 
PrintLiteralIndented(const char * info,Handle<Object> value,bool quote)602 void AstPrinter::PrintLiteralIndented(const char* info,
603                                       Handle<Object> value,
604                                       bool quote) {
605   PrintIndented(info);
606   Print(" ");
607   PrintLiteral(value, quote);
608   Print("\n");
609 }
610 
611 
PrintLiteralWithModeIndented(const char * info,Variable * var,Handle<Object> value)612 void AstPrinter::PrintLiteralWithModeIndented(const char* info,
613                                               Variable* var,
614                                               Handle<Object> value) {
615   if (var == NULL) {
616     PrintLiteralIndented(info, value, true);
617   } else {
618     EmbeddedVector<char, 256> buf;
619     int pos =
620         SNPrintF(buf, "%s (mode = %s", info, VariableMode2String(var->mode()));
621     SNPrintF(buf + pos, ")");
622     PrintLiteralIndented(buf.start(), value, true);
623   }
624 }
625 
626 
PrintLabelsIndented(ZoneList<const AstRawString * > * labels)627 void AstPrinter::PrintLabelsIndented(ZoneList<const AstRawString*>* labels) {
628   if (labels == NULL || labels->length() == 0) return;
629   PrintIndented("LABELS ");
630   PrintLabels(labels);
631   Print("\n");
632 }
633 
634 
PrintIndentedVisit(const char * s,AstNode * node)635 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
636   IndentedScope indent(this, s, node->position());
637   Visit(node);
638 }
639 
640 
PrintProgram(FunctionLiteral * program)641 const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
642   Init();
643   { IndentedScope indent(this, "FUNC", program->position());
644     PrintIndented("KIND");
645     Print(" %d\n", program->kind());
646     PrintIndented("YIELD COUNT");
647     Print(" %d\n", program->yield_count());
648     PrintLiteralIndented("NAME", program->name(), true);
649     PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
650     PrintParameters(program->scope());
651     PrintDeclarations(program->scope()->declarations());
652     PrintStatements(program->body());
653   }
654   return output_;
655 }
656 
657 
PrintOut(Isolate * isolate,AstNode * node)658 void AstPrinter::PrintOut(Isolate* isolate, AstNode* node) {
659   AstPrinter printer(isolate);
660   printer.Init();
661   printer.Visit(node);
662   PrintF("%s", printer.output_);
663 }
664 
PrintDeclarations(Declaration::List * declarations)665 void AstPrinter::PrintDeclarations(Declaration::List* declarations) {
666   if (!declarations->is_empty()) {
667     IndentedScope indent(this, "DECLS");
668     for (Declaration* decl : *declarations) Visit(decl);
669   }
670 }
671 
PrintParameters(DeclarationScope * scope)672 void AstPrinter::PrintParameters(DeclarationScope* scope) {
673   if (scope->num_parameters() > 0) {
674     IndentedScope indent(this, "PARAMS");
675     for (int i = 0; i < scope->num_parameters(); i++) {
676       PrintLiteralWithModeIndented("VAR", scope->parameter(i),
677                                    scope->parameter(i)->name());
678     }
679   }
680 }
681 
682 
PrintStatements(ZoneList<Statement * > * statements)683 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
684   for (int i = 0; i < statements->length(); i++) {
685     Visit(statements->at(i));
686   }
687 }
688 
689 
PrintArguments(ZoneList<Expression * > * arguments)690 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
691   for (int i = 0; i < arguments->length(); i++) {
692     Visit(arguments->at(i));
693   }
694 }
695 
696 
VisitBlock(Block * node)697 void AstPrinter::VisitBlock(Block* node) {
698   const char* block_txt =
699       node->ignore_completion_value() ? "BLOCK NOCOMPLETIONS" : "BLOCK";
700   IndentedScope indent(this, block_txt, node->position());
701   PrintStatements(node->statements());
702 }
703 
704 
705 // TODO(svenpanne) Start with IndentedScope.
VisitVariableDeclaration(VariableDeclaration * node)706 void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
707   PrintLiteralWithModeIndented("VARIABLE", node->proxy()->var(),
708                                node->proxy()->name());
709 }
710 
711 
712 // TODO(svenpanne) Start with IndentedScope.
VisitFunctionDeclaration(FunctionDeclaration * node)713 void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
714   PrintIndented("FUNCTION ");
715   PrintLiteral(node->proxy()->name(), true);
716   Print(" = function ");
717   PrintLiteral(node->fun()->name(), false);
718   Print("\n");
719 }
720 
721 
VisitExpressionStatement(ExpressionStatement * node)722 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
723   IndentedScope indent(this, "EXPRESSION STATEMENT", node->position());
724   Visit(node->expression());
725 }
726 
727 
VisitEmptyStatement(EmptyStatement * node)728 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
729   IndentedScope indent(this, "EMPTY", node->position());
730 }
731 
732 
VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement * node)733 void AstPrinter::VisitSloppyBlockFunctionStatement(
734     SloppyBlockFunctionStatement* node) {
735   Visit(node->statement());
736 }
737 
738 
VisitIfStatement(IfStatement * node)739 void AstPrinter::VisitIfStatement(IfStatement* node) {
740   IndentedScope indent(this, "IF", node->position());
741   PrintIndentedVisit("CONDITION", node->condition());
742   PrintIndentedVisit("THEN", node->then_statement());
743   if (node->HasElseStatement()) {
744     PrintIndentedVisit("ELSE", node->else_statement());
745   }
746 }
747 
748 
VisitContinueStatement(ContinueStatement * node)749 void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
750   IndentedScope indent(this, "CONTINUE", node->position());
751   PrintLabelsIndented(node->target()->labels());
752 }
753 
754 
VisitBreakStatement(BreakStatement * node)755 void AstPrinter::VisitBreakStatement(BreakStatement* node) {
756   IndentedScope indent(this, "BREAK", node->position());
757   PrintLabelsIndented(node->target()->labels());
758 }
759 
760 
VisitReturnStatement(ReturnStatement * node)761 void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
762   IndentedScope indent(this, "RETURN", node->position());
763   Visit(node->expression());
764 }
765 
766 
VisitWithStatement(WithStatement * node)767 void AstPrinter::VisitWithStatement(WithStatement* node) {
768   IndentedScope indent(this, "WITH", node->position());
769   PrintIndentedVisit("OBJECT", node->expression());
770   PrintIndentedVisit("BODY", node->statement());
771 }
772 
773 
VisitSwitchStatement(SwitchStatement * node)774 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
775   IndentedScope indent(this, "SWITCH", node->position());
776   PrintLabelsIndented(node->labels());
777   PrintIndentedVisit("TAG", node->tag());
778   for (int i = 0; i < node->cases()->length(); i++) {
779     Visit(node->cases()->at(i));
780   }
781 }
782 
783 
VisitCaseClause(CaseClause * clause)784 void AstPrinter::VisitCaseClause(CaseClause* clause) {
785   if (clause->is_default()) {
786     IndentedScope indent(this, "DEFAULT", clause->position());
787     PrintStatements(clause->statements());
788   } else {
789     IndentedScope indent(this, "CASE", clause->position());
790     Visit(clause->label());
791     PrintStatements(clause->statements());
792   }
793 }
794 
795 
VisitDoWhileStatement(DoWhileStatement * node)796 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
797   IndentedScope indent(this, "DO", node->position());
798   PrintIndented("YIELD COUNT");
799   Print(" %d\n", node->yield_count());
800   PrintLabelsIndented(node->labels());
801   PrintIndentedVisit("BODY", node->body());
802   PrintIndentedVisit("COND", node->cond());
803 }
804 
805 
VisitWhileStatement(WhileStatement * node)806 void AstPrinter::VisitWhileStatement(WhileStatement* node) {
807   IndentedScope indent(this, "WHILE", node->position());
808   PrintIndented("YIELD COUNT");
809   Print(" %d\n", node->yield_count());
810   PrintLabelsIndented(node->labels());
811   PrintIndentedVisit("COND", node->cond());
812   PrintIndentedVisit("BODY", node->body());
813 }
814 
815 
VisitForStatement(ForStatement * node)816 void AstPrinter::VisitForStatement(ForStatement* node) {
817   IndentedScope indent(this, "FOR", node->position());
818   PrintIndented("YIELD COUNT");
819   Print(" %d\n", node->yield_count());
820   PrintLabelsIndented(node->labels());
821   if (node->init()) PrintIndentedVisit("INIT", node->init());
822   if (node->cond()) PrintIndentedVisit("COND", node->cond());
823   PrintIndentedVisit("BODY", node->body());
824   if (node->next()) PrintIndentedVisit("NEXT", node->next());
825 }
826 
827 
VisitForInStatement(ForInStatement * node)828 void AstPrinter::VisitForInStatement(ForInStatement* node) {
829   IndentedScope indent(this, "FOR IN", node->position());
830   PrintIndented("YIELD COUNT");
831   Print(" %d\n", node->yield_count());
832   PrintIndentedVisit("FOR", node->each());
833   PrintIndentedVisit("IN", node->enumerable());
834   PrintIndentedVisit("BODY", node->body());
835 }
836 
837 
VisitForOfStatement(ForOfStatement * node)838 void AstPrinter::VisitForOfStatement(ForOfStatement* node) {
839   IndentedScope indent(this, "FOR OF", node->position());
840   PrintIndented("YIELD COUNT");
841   Print(" %d\n", node->yield_count());
842   PrintIndentedVisit("INIT", node->assign_iterator());
843   PrintIndentedVisit("NEXT", node->next_result());
844   PrintIndentedVisit("DONE", node->result_done());
845   PrintIndentedVisit("EACH", node->assign_each());
846   PrintIndentedVisit("BODY", node->body());
847 }
848 
849 
VisitTryCatchStatement(TryCatchStatement * node)850 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
851   IndentedScope indent(this, "TRY CATCH", node->position());
852   PrintTryStatement(node);
853   PrintLiteralWithModeIndented("CATCHVAR",
854                                node->variable(),
855                                node->variable()->name());
856   PrintIndentedVisit("CATCH", node->catch_block());
857 }
858 
859 
VisitTryFinallyStatement(TryFinallyStatement * node)860 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
861   IndentedScope indent(this, "TRY FINALLY", node->position());
862   PrintTryStatement(node);
863   PrintIndentedVisit("FINALLY", node->finally_block());
864 }
865 
PrintTryStatement(TryStatement * node)866 void AstPrinter::PrintTryStatement(TryStatement* node) {
867   PrintIndentedVisit("TRY", node->try_block());
868   PrintIndented("CATCH PREDICTION");
869   const char* prediction = "";
870   switch (node->catch_prediction()) {
871     case HandlerTable::UNCAUGHT:
872       prediction = "UNCAUGHT";
873       break;
874     case HandlerTable::CAUGHT:
875       prediction = "CAUGHT";
876       break;
877     case HandlerTable::PROMISE:
878       prediction = "PROMISE";
879       break;
880     case HandlerTable::DESUGARING:
881       prediction = "DESUGARING";
882       break;
883     case HandlerTable::ASYNC_AWAIT:
884       prediction = "ASYNC_AWAIT";
885       break;
886   }
887   Print(" %s\n", prediction);
888 }
889 
VisitDebuggerStatement(DebuggerStatement * node)890 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
891   IndentedScope indent(this, "DEBUGGER", node->position());
892 }
893 
894 
VisitFunctionLiteral(FunctionLiteral * node)895 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
896   IndentedScope indent(this, "FUNC LITERAL", node->position());
897   PrintLiteralIndented("NAME", node->name(), false);
898   PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
899   PrintParameters(node->scope());
900   // We don't want to see the function literal in this case: it
901   // will be printed via PrintProgram when the code for it is
902   // generated.
903   // PrintStatements(node->body());
904 }
905 
906 
VisitClassLiteral(ClassLiteral * node)907 void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
908   IndentedScope indent(this, "CLASS LITERAL", node->position());
909   PrintLiteralIndented("NAME", node->constructor()->name(), false);
910   if (node->extends() != nullptr) {
911     PrintIndentedVisit("EXTENDS", node->extends());
912   }
913   PrintClassProperties(node->properties());
914 }
915 
PrintClassProperties(ZoneList<ClassLiteral::Property * > * properties)916 void AstPrinter::PrintClassProperties(
917     ZoneList<ClassLiteral::Property*>* properties) {
918   for (int i = 0; i < properties->length(); i++) {
919     ClassLiteral::Property* property = properties->at(i);
920     const char* prop_kind = nullptr;
921     switch (property->kind()) {
922       case ClassLiteral::Property::METHOD:
923         prop_kind = "METHOD";
924         break;
925       case ClassLiteral::Property::GETTER:
926         prop_kind = "GETTER";
927         break;
928       case ClassLiteral::Property::SETTER:
929         prop_kind = "SETTER";
930         break;
931       case ClassLiteral::Property::FIELD:
932         prop_kind = "FIELD";
933         break;
934     }
935     EmbeddedVector<char, 128> buf;
936     SNPrintF(buf, "PROPERTY%s - %s", property->is_static() ? " - STATIC" : "",
937              prop_kind);
938     IndentedScope prop(this, buf.start());
939     PrintIndentedVisit("KEY", properties->at(i)->key());
940     PrintIndentedVisit("VALUE", properties->at(i)->value());
941   }
942 }
943 
944 
VisitNativeFunctionLiteral(NativeFunctionLiteral * node)945 void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
946   IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position());
947   PrintLiteralIndented("NAME", node->name(), false);
948 }
949 
950 
VisitDoExpression(DoExpression * node)951 void AstPrinter::VisitDoExpression(DoExpression* node) {
952   IndentedScope indent(this, "DO EXPRESSION", node->position());
953   PrintStatements(node->block()->statements());
954 }
955 
956 
VisitConditional(Conditional * node)957 void AstPrinter::VisitConditional(Conditional* node) {
958   IndentedScope indent(this, "CONDITIONAL", node->position());
959   PrintIndentedVisit("CONDITION", node->condition());
960   PrintIndentedVisit("THEN", node->then_expression());
961   PrintIndentedVisit("ELSE", node->else_expression());
962 }
963 
964 
965 // TODO(svenpanne) Start with IndentedScope.
VisitLiteral(Literal * node)966 void AstPrinter::VisitLiteral(Literal* node) {
967   PrintLiteralIndented("LITERAL", node->value(), true);
968 }
969 
970 
VisitRegExpLiteral(RegExpLiteral * node)971 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
972   IndentedScope indent(this, "REGEXP LITERAL", node->position());
973   EmbeddedVector<char, 128> buf;
974   SNPrintF(buf, "literal_index = %d\n", node->literal_index());
975   PrintIndented(buf.start());
976   PrintLiteralIndented("PATTERN", node->pattern(), false);
977   int i = 0;
978   if (node->flags() & RegExp::kGlobal) buf[i++] = 'g';
979   if (node->flags() & RegExp::kIgnoreCase) buf[i++] = 'i';
980   if (node->flags() & RegExp::kMultiline) buf[i++] = 'm';
981   if (node->flags() & RegExp::kUnicode) buf[i++] = 'u';
982   if (node->flags() & RegExp::kSticky) buf[i++] = 'y';
983   buf[i] = '\0';
984   PrintIndented("FLAGS ");
985   Print("%s", buf.start());
986   Print("\n");
987 }
988 
989 
VisitObjectLiteral(ObjectLiteral * node)990 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
991   IndentedScope indent(this, "OBJ LITERAL", node->position());
992   EmbeddedVector<char, 128> buf;
993   SNPrintF(buf, "literal_index = %d\n", node->literal_index());
994   PrintIndented(buf.start());
995   PrintObjectProperties(node->properties());
996 }
997 
PrintObjectProperties(ZoneList<ObjectLiteral::Property * > * properties)998 void AstPrinter::PrintObjectProperties(
999     ZoneList<ObjectLiteral::Property*>* properties) {
1000   for (int i = 0; i < properties->length(); i++) {
1001     ObjectLiteral::Property* property = properties->at(i);
1002     const char* prop_kind = nullptr;
1003     switch (property->kind()) {
1004       case ObjectLiteral::Property::CONSTANT:
1005         prop_kind = "CONSTANT";
1006         break;
1007       case ObjectLiteral::Property::COMPUTED:
1008         prop_kind = "COMPUTED";
1009         break;
1010       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1011         prop_kind = "MATERIALIZED_LITERAL";
1012         break;
1013       case ObjectLiteral::Property::PROTOTYPE:
1014         prop_kind = "PROTOTYPE";
1015         break;
1016       case ObjectLiteral::Property::GETTER:
1017         prop_kind = "GETTER";
1018         break;
1019       case ObjectLiteral::Property::SETTER:
1020         prop_kind = "SETTER";
1021         break;
1022     }
1023     EmbeddedVector<char, 128> buf;
1024     SNPrintF(buf, "PROPERTY - %s", prop_kind);
1025     IndentedScope prop(this, buf.start());
1026     PrintIndentedVisit("KEY", properties->at(i)->key());
1027     PrintIndentedVisit("VALUE", properties->at(i)->value());
1028   }
1029 }
1030 
1031 
VisitArrayLiteral(ArrayLiteral * node)1032 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
1033   IndentedScope indent(this, "ARRAY LITERAL", node->position());
1034 
1035   EmbeddedVector<char, 128> buf;
1036   SNPrintF(buf, "literal_index = %d\n", node->literal_index());
1037   PrintIndented(buf.start());
1038   if (node->values()->length() > 0) {
1039     IndentedScope indent(this, "VALUES", node->position());
1040     for (int i = 0; i < node->values()->length(); i++) {
1041       Visit(node->values()->at(i));
1042     }
1043   }
1044 }
1045 
1046 
VisitVariableProxy(VariableProxy * node)1047 void AstPrinter::VisitVariableProxy(VariableProxy* node) {
1048   EmbeddedVector<char, 128> buf;
1049   int pos =
1050       FormatSlotNode(&buf, node, "VAR PROXY", node->VariableFeedbackSlot());
1051 
1052   if (!node->is_resolved()) {
1053     SNPrintF(buf + pos, " unresolved");
1054     PrintLiteralWithModeIndented(buf.start(), nullptr, node->name());
1055   } else {
1056     Variable* var = node->var();
1057     switch (var->location()) {
1058       case VariableLocation::UNALLOCATED:
1059         SNPrintF(buf + pos, " unallocated");
1060         break;
1061       case VariableLocation::PARAMETER:
1062         SNPrintF(buf + pos, " parameter[%d]", var->index());
1063         break;
1064       case VariableLocation::LOCAL:
1065         SNPrintF(buf + pos, " local[%d]", var->index());
1066         break;
1067       case VariableLocation::CONTEXT:
1068         SNPrintF(buf + pos, " context[%d]", var->index());
1069         break;
1070       case VariableLocation::LOOKUP:
1071         SNPrintF(buf + pos, " lookup");
1072         break;
1073       case VariableLocation::MODULE:
1074         SNPrintF(buf + pos, " module");
1075         break;
1076     }
1077     PrintLiteralWithModeIndented(buf.start(), var, node->name());
1078   }
1079 }
1080 
1081 
VisitAssignment(Assignment * node)1082 void AstPrinter::VisitAssignment(Assignment* node) {
1083   IndentedScope indent(this, Token::Name(node->op()), node->position());
1084   Visit(node->target());
1085   Visit(node->value());
1086 }
1087 
1088 
VisitYield(Yield * node)1089 void AstPrinter::VisitYield(Yield* node) {
1090   EmbeddedVector<char, 128> buf;
1091   SNPrintF(buf, "YIELD id %d", node->yield_id());
1092   IndentedScope indent(this, buf.start(), node->position());
1093   Visit(node->expression());
1094 }
1095 
1096 
VisitThrow(Throw * node)1097 void AstPrinter::VisitThrow(Throw* node) {
1098   IndentedScope indent(this, "THROW", node->position());
1099   Visit(node->exception());
1100 }
1101 
1102 
VisitProperty(Property * node)1103 void AstPrinter::VisitProperty(Property* node) {
1104   EmbeddedVector<char, 128> buf;
1105   FormatSlotNode(&buf, node, "PROPERTY", node->PropertyFeedbackSlot());
1106   IndentedScope indent(this, buf.start(), node->position());
1107 
1108   Visit(node->obj());
1109   Literal* literal = node->key()->AsLiteral();
1110   if (literal != NULL && literal->value()->IsInternalizedString()) {
1111     PrintLiteralIndented("NAME", literal->value(), false);
1112   } else {
1113     PrintIndentedVisit("KEY", node->key());
1114   }
1115 }
1116 
1117 
VisitCall(Call * node)1118 void AstPrinter::VisitCall(Call* node) {
1119   EmbeddedVector<char, 128> buf;
1120   const char* name =
1121       node->tail_call_mode() == TailCallMode::kAllow ? "TAIL CALL" : "CALL";
1122   FormatSlotNode(&buf, node, name, node->CallFeedbackICSlot());
1123   IndentedScope indent(this, buf.start());
1124 
1125   Visit(node->expression());
1126   PrintArguments(node->arguments());
1127 }
1128 
1129 
VisitCallNew(CallNew * node)1130 void AstPrinter::VisitCallNew(CallNew* node) {
1131   IndentedScope indent(this, "CALL NEW", node->position());
1132   Visit(node->expression());
1133   PrintArguments(node->arguments());
1134 }
1135 
1136 
VisitCallRuntime(CallRuntime * node)1137 void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1138   EmbeddedVector<char, 128> buf;
1139   SNPrintF(buf, "CALL RUNTIME %s", node->debug_name());
1140   IndentedScope indent(this, buf.start(), node->position());
1141   PrintArguments(node->arguments());
1142 }
1143 
1144 
VisitUnaryOperation(UnaryOperation * node)1145 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1146   IndentedScope indent(this, Token::Name(node->op()), node->position());
1147   Visit(node->expression());
1148 }
1149 
1150 
VisitCountOperation(CountOperation * node)1151 void AstPrinter::VisitCountOperation(CountOperation* node) {
1152   EmbeddedVector<char, 128> buf;
1153   SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
1154            Token::Name(node->op()));
1155   IndentedScope indent(this, buf.start(), node->position());
1156   Visit(node->expression());
1157 }
1158 
1159 
VisitBinaryOperation(BinaryOperation * node)1160 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
1161   IndentedScope indent(this, Token::Name(node->op()), node->position());
1162   Visit(node->left());
1163   Visit(node->right());
1164 }
1165 
1166 
VisitCompareOperation(CompareOperation * node)1167 void AstPrinter::VisitCompareOperation(CompareOperation* node) {
1168   IndentedScope indent(this, Token::Name(node->op()), node->position());
1169   Visit(node->left());
1170   Visit(node->right());
1171 }
1172 
1173 
VisitSpread(Spread * node)1174 void AstPrinter::VisitSpread(Spread* node) {
1175   IndentedScope indent(this, "...", node->position());
1176   Visit(node->expression());
1177 }
1178 
1179 
VisitEmptyParentheses(EmptyParentheses * node)1180 void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
1181   IndentedScope indent(this, "()", node->position());
1182 }
1183 
1184 
VisitThisFunction(ThisFunction * node)1185 void AstPrinter::VisitThisFunction(ThisFunction* node) {
1186   IndentedScope indent(this, "THIS-FUNCTION", node->position());
1187 }
1188 
1189 
VisitSuperPropertyReference(SuperPropertyReference * node)1190 void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
1191   IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE", node->position());
1192 }
1193 
1194 
VisitSuperCallReference(SuperCallReference * node)1195 void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
1196   IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position());
1197 }
1198 
1199 
VisitRewritableExpression(RewritableExpression * node)1200 void AstPrinter::VisitRewritableExpression(RewritableExpression* node) {
1201   Visit(node->expression());
1202 }
1203 
1204 
1205 #endif  // DEBUG
1206 
1207 }  // namespace internal
1208 }  // namespace v8
1209