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