| 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 |