OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/ast/prettyprinter.h" | 5 #include "src/ast/prettyprinter.h" |
6 | 6 |
7 #include <stdarg.h> | 7 #include <stdarg.h> |
8 | 8 |
9 #include "src/ast/ast-value-factory.h" | 9 #include "src/ast/ast-value-factory.h" |
10 #include "src/ast/scopes.h" | 10 #include "src/ast/scopes.h" |
11 #include "src/base/platform/platform.h" | 11 #include "src/base/platform/platform.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 CallPrinter::CallPrinter(Isolate* isolate, bool is_builtin) { | 16 CallPrinter::CallPrinter(Isolate* isolate, bool is_builtin) |
| 17 : builder_(isolate) { |
17 isolate_ = isolate; | 18 isolate_ = isolate; |
18 output_ = NULL; | |
19 size_ = 0; | |
20 pos_ = 0; | |
21 position_ = 0; | 19 position_ = 0; |
| 20 num_prints_ = 0; |
22 found_ = false; | 21 found_ = false; |
23 done_ = false; | 22 done_ = false; |
24 is_builtin_ = is_builtin; | 23 is_builtin_ = is_builtin; |
25 InitializeAstVisitor(isolate); | 24 InitializeAstVisitor(isolate); |
26 } | 25 } |
27 | 26 |
28 | 27 Handle<String> CallPrinter::Print(FunctionLiteral* program, int position) { |
29 CallPrinter::~CallPrinter() { DeleteArray(output_); } | 28 num_prints_ = 0; |
30 | |
31 | |
32 const char* CallPrinter::Print(FunctionLiteral* program, int position) { | |
33 Init(); | |
34 position_ = position; | 29 position_ = position; |
35 Find(program); | 30 Find(program); |
36 return output_; | 31 return builder_.Finish().ToHandleChecked(); |
37 } | 32 } |
38 | 33 |
39 | 34 |
40 void CallPrinter::Find(AstNode* node, bool print) { | 35 void CallPrinter::Find(AstNode* node, bool print) { |
41 if (done_) return; | 36 if (done_) return; |
42 if (found_) { | 37 if (found_) { |
43 if (print) { | 38 if (print) { |
44 int start = pos_; | 39 int prev_num_prints = num_prints_; |
45 Visit(node); | 40 Visit(node); |
46 if (start != pos_) return; | 41 if (prev_num_prints != num_prints_) return; |
47 } | 42 } |
48 Print("(intermediate value)"); | 43 Print("(intermediate value)"); |
49 } else { | 44 } else { |
50 Visit(node); | 45 Visit(node); |
51 } | 46 } |
52 } | 47 } |
53 | 48 |
54 | 49 void CallPrinter::Print(const char* str) { |
55 void CallPrinter::Init() { | 50 if (!found_ || done_) return; |
56 if (size_ == 0) { | 51 num_prints_++; |
57 DCHECK(output_ == NULL); | 52 builder_.AppendCString(str); |
58 const int initial_size = 256; | |
59 output_ = NewArray<char>(initial_size); | |
60 size_ = initial_size; | |
61 } | |
62 output_[0] = '\0'; | |
63 pos_ = 0; | |
64 } | 53 } |
65 | 54 |
66 | 55 void CallPrinter::Print(Handle<String> str) { |
67 void CallPrinter::Print(const char* format, ...) { | |
68 if (!found_ || done_) return; | 56 if (!found_ || done_) return; |
69 for (;;) { | 57 num_prints_++; |
70 va_list arguments; | 58 builder_.AppendString(str); |
71 va_start(arguments, format); | |
72 int n = VSNPrintF(Vector<char>(output_, size_) + pos_, format, arguments); | |
73 va_end(arguments); | |
74 | |
75 if (n >= 0) { | |
76 // there was enough space - we are done | |
77 pos_ += n; | |
78 return; | |
79 } else { | |
80 // there was not enough space - allocate more and try again | |
81 const int slack = 32; | |
82 int new_size = size_ + (size_ >> 1) + slack; | |
83 char* new_output = NewArray<char>(new_size); | |
84 MemCopy(new_output, output_, pos_); | |
85 DeleteArray(output_); | |
86 output_ = new_output; | |
87 size_ = new_size; | |
88 } | |
89 } | |
90 } | 59 } |
91 | 60 |
92 | |
93 void CallPrinter::VisitBlock(Block* node) { | 61 void CallPrinter::VisitBlock(Block* node) { |
94 FindStatements(node->statements()); | 62 FindStatements(node->statements()); |
95 } | 63 } |
96 | 64 |
97 | 65 |
98 void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {} | 66 void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {} |
99 | 67 |
100 | 68 |
101 void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {} | 69 void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {} |
102 | 70 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 | 197 |
230 | 198 |
231 void CallPrinter::VisitConditional(Conditional* node) { | 199 void CallPrinter::VisitConditional(Conditional* node) { |
232 Find(node->condition()); | 200 Find(node->condition()); |
233 Find(node->then_expression()); | 201 Find(node->then_expression()); |
234 Find(node->else_expression()); | 202 Find(node->else_expression()); |
235 } | 203 } |
236 | 204 |
237 | 205 |
238 void CallPrinter::VisitLiteral(Literal* node) { | 206 void CallPrinter::VisitLiteral(Literal* node) { |
239 PrintLiteral(*node->value(), true); | 207 PrintLiteral(node->value(), true); |
240 } | 208 } |
241 | 209 |
242 | 210 |
243 void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) { | 211 void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) { |
244 Print("/"); | 212 Print("/"); |
245 PrintLiteral(*node->pattern(), false); | 213 PrintLiteral(node->pattern(), false); |
246 Print("/"); | 214 Print("/"); |
247 if (node->flags() & RegExp::kGlobal) Print("g"); | 215 if (node->flags() & RegExp::kGlobal) Print("g"); |
248 if (node->flags() & RegExp::kIgnoreCase) Print("i"); | 216 if (node->flags() & RegExp::kIgnoreCase) Print("i"); |
249 if (node->flags() & RegExp::kMultiline) Print("m"); | 217 if (node->flags() & RegExp::kMultiline) Print("m"); |
250 if (node->flags() & RegExp::kUnicode) Print("u"); | 218 if (node->flags() & RegExp::kUnicode) Print("u"); |
251 if (node->flags() & RegExp::kSticky) Print("y"); | 219 if (node->flags() & RegExp::kSticky) Print("y"); |
252 } | 220 } |
253 | 221 |
254 | 222 |
255 void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) { | 223 void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) { |
(...skipping 11 matching lines...) Expand all Loading... |
267 } | 235 } |
268 Print("]"); | 236 Print("]"); |
269 } | 237 } |
270 | 238 |
271 | 239 |
272 void CallPrinter::VisitVariableProxy(VariableProxy* node) { | 240 void CallPrinter::VisitVariableProxy(VariableProxy* node) { |
273 if (is_builtin_) { | 241 if (is_builtin_) { |
274 // Variable names of builtins are meaningless due to minification. | 242 // Variable names of builtins are meaningless due to minification. |
275 Print("(var)"); | 243 Print("(var)"); |
276 } else { | 244 } else { |
277 PrintLiteral(*node->name(), false); | 245 PrintLiteral(node->name(), false); |
278 } | 246 } |
279 } | 247 } |
280 | 248 |
281 | 249 |
282 void CallPrinter::VisitAssignment(Assignment* node) { | 250 void CallPrinter::VisitAssignment(Assignment* node) { |
283 Find(node->target()); | 251 Find(node->target()); |
284 Find(node->value()); | 252 Find(node->value()); |
285 } | 253 } |
286 | 254 |
287 | 255 |
288 void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); } | 256 void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); } |
289 | 257 |
290 | 258 |
291 void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); } | 259 void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); } |
292 | 260 |
293 | 261 |
294 void CallPrinter::VisitProperty(Property* node) { | 262 void CallPrinter::VisitProperty(Property* node) { |
295 Expression* key = node->key(); | 263 Expression* key = node->key(); |
296 Literal* literal = key->AsLiteral(); | 264 Literal* literal = key->AsLiteral(); |
297 if (literal != NULL && literal->value()->IsInternalizedString()) { | 265 if (literal != NULL && literal->value()->IsInternalizedString()) { |
298 Find(node->obj(), true); | 266 Find(node->obj(), true); |
299 Print("."); | 267 Print("."); |
300 PrintLiteral(*literal->value(), false); | 268 PrintLiteral(literal->value(), false); |
301 } else { | 269 } else { |
302 Find(node->obj(), true); | 270 Find(node->obj(), true); |
303 Print("["); | 271 Print("["); |
304 Find(key, true); | 272 Find(key, true); |
305 Print("]"); | 273 Print("]"); |
306 } | 274 } |
307 } | 275 } |
308 | 276 |
309 | 277 |
310 void CallPrinter::VisitCall(Call* node) { | 278 void CallPrinter::VisitCall(Call* node) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 | 312 |
345 void CallPrinter::VisitCallRuntime(CallRuntime* node) { | 313 void CallPrinter::VisitCallRuntime(CallRuntime* node) { |
346 FindArguments(node->arguments()); | 314 FindArguments(node->arguments()); |
347 } | 315 } |
348 | 316 |
349 | 317 |
350 void CallPrinter::VisitUnaryOperation(UnaryOperation* node) { | 318 void CallPrinter::VisitUnaryOperation(UnaryOperation* node) { |
351 Token::Value op = node->op(); | 319 Token::Value op = node->op(); |
352 bool needsSpace = | 320 bool needsSpace = |
353 op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID; | 321 op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID; |
354 Print("(%s%s", Token::String(op), needsSpace ? " " : ""); | 322 Print("("); |
| 323 Print(Token::String(op)); |
| 324 if (needsSpace) Print(" "); |
355 Find(node->expression(), true); | 325 Find(node->expression(), true); |
356 Print(")"); | 326 Print(")"); |
357 } | 327 } |
358 | 328 |
359 | 329 |
360 void CallPrinter::VisitCountOperation(CountOperation* node) { | 330 void CallPrinter::VisitCountOperation(CountOperation* node) { |
361 Print("("); | 331 Print("("); |
362 if (node->is_prefix()) Print("%s", Token::String(node->op())); | 332 if (node->is_prefix()) Print(Token::String(node->op())); |
363 Find(node->expression(), true); | 333 Find(node->expression(), true); |
364 if (node->is_postfix()) Print("%s", Token::String(node->op())); | 334 if (node->is_postfix()) Print(Token::String(node->op())); |
365 Print(")"); | 335 Print(")"); |
366 } | 336 } |
367 | 337 |
368 | 338 |
369 void CallPrinter::VisitBinaryOperation(BinaryOperation* node) { | 339 void CallPrinter::VisitBinaryOperation(BinaryOperation* node) { |
370 Print("("); | 340 Print("("); |
371 Find(node->left(), true); | 341 Find(node->left(), true); |
372 Print(" %s ", Token::String(node->op())); | 342 Print(" "); |
| 343 Print(Token::String(node->op())); |
| 344 Print(" "); |
373 Find(node->right(), true); | 345 Find(node->right(), true); |
374 Print(")"); | 346 Print(")"); |
375 } | 347 } |
376 | 348 |
377 | 349 |
378 void CallPrinter::VisitCompareOperation(CompareOperation* node) { | 350 void CallPrinter::VisitCompareOperation(CompareOperation* node) { |
379 Print("("); | 351 Print("("); |
380 Find(node->left(), true); | 352 Find(node->left(), true); |
381 Print(" %s ", Token::String(node->op())); | 353 Print(" "); |
| 354 Print(Token::String(node->op())); |
| 355 Print(" "); |
382 Find(node->right(), true); | 356 Find(node->right(), true); |
383 Print(")"); | 357 Print(")"); |
384 } | 358 } |
385 | 359 |
386 | 360 |
387 void CallPrinter::VisitSpread(Spread* node) { | 361 void CallPrinter::VisitSpread(Spread* node) { |
388 Print("(..."); | 362 Print("(..."); |
389 Find(node->expression(), true); | 363 Find(node->expression(), true); |
390 Print(")"); | 364 Print(")"); |
391 } | 365 } |
(...skipping 28 matching lines...) Expand all Loading... |
420 } | 394 } |
421 | 395 |
422 | 396 |
423 void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) { | 397 void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) { |
424 if (found_) return; | 398 if (found_) return; |
425 for (int i = 0; i < arguments->length(); i++) { | 399 for (int i = 0; i < arguments->length(); i++) { |
426 Find(arguments->at(i)); | 400 Find(arguments->at(i)); |
427 } | 401 } |
428 } | 402 } |
429 | 403 |
430 | 404 void CallPrinter::PrintLiteral(Handle<Object> value, bool quote) { |
431 void CallPrinter::PrintLiteral(Object* value, bool quote) { | 405 if (value->IsString()) { |
432 Object* object = value; | |
433 if (object->IsString()) { | |
434 if (quote) Print("\""); | 406 if (quote) Print("\""); |
435 Print("%s", String::cast(object)->ToCString().get()); | 407 Print(Handle<String>::cast(value)); |
436 if (quote) Print("\""); | 408 if (quote) Print("\""); |
437 } else if (object->IsNull(isolate_)) { | 409 } else if (value->IsNull(isolate_)) { |
438 Print("null"); | 410 Print("null"); |
439 } else if (object->IsTrue(isolate_)) { | 411 } else if (value->IsTrue(isolate_)) { |
440 Print("true"); | 412 Print("true"); |
441 } else if (object->IsFalse(isolate_)) { | 413 } else if (value->IsFalse(isolate_)) { |
442 Print("false"); | 414 Print("false"); |
443 } else if (object->IsUndefined(isolate_)) { | 415 } else if (value->IsUndefined(isolate_)) { |
444 Print("undefined"); | 416 Print("undefined"); |
445 } else if (object->IsNumber()) { | 417 } else if (value->IsNumber()) { |
446 Print("%g", object->Number()); | 418 Print(isolate_->factory()->NumberToString(value)); |
447 } else if (object->IsSymbol()) { | 419 } else if (value->IsSymbol()) { |
448 // Symbols can only occur as literals if they were inserted by the parser. | 420 // Symbols can only occur as literals if they were inserted by the parser. |
449 PrintLiteral(Symbol::cast(object)->name(), false); | 421 PrintLiteral(handle(Handle<Symbol>::cast(value)->name(), isolate_), false); |
450 } | 422 } |
451 } | 423 } |
452 | 424 |
453 | 425 |
454 void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) { | 426 void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) { |
455 PrintLiteral(*value->string(), quote); | 427 PrintLiteral(value->string(), quote); |
456 } | 428 } |
457 | 429 |
458 | 430 |
459 //----------------------------------------------------------------------------- | 431 //----------------------------------------------------------------------------- |
460 | 432 |
461 | 433 |
462 #ifdef DEBUG | 434 #ifdef DEBUG |
463 | 435 |
464 // A helper for ast nodes that use FeedbackVectorSlots. | 436 // A helper for ast nodes that use FeedbackVectorSlots. |
465 static int FormatSlotNode(Vector<char>* buf, Expression* node, | 437 static int FormatSlotNode(Vector<char>* buf, Expression* node, |
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1191 | 1163 |
1192 void AstPrinter::VisitRewritableExpression(RewritableExpression* node) { | 1164 void AstPrinter::VisitRewritableExpression(RewritableExpression* node) { |
1193 Visit(node->expression()); | 1165 Visit(node->expression()); |
1194 } | 1166 } |
1195 | 1167 |
1196 | 1168 |
1197 #endif // DEBUG | 1169 #endif // DEBUG |
1198 | 1170 |
1199 } // namespace internal | 1171 } // namespace internal |
1200 } // namespace v8 | 1172 } // namespace v8 |
OLD | NEW |