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) { | 16 CallPrinter::CallPrinter(Isolate* isolate, bool is_builtin) { |
17 output_ = NULL; | 17 output_ = NULL; |
18 size_ = 0; | 18 size_ = 0; |
19 pos_ = 0; | 19 pos_ = 0; |
20 position_ = 0; | 20 position_ = 0; |
21 found_ = false; | 21 found_ = false; |
22 done_ = false; | 22 done_ = false; |
| 23 is_builtin_ = is_builtin; |
23 InitializeAstVisitor(isolate); | 24 InitializeAstVisitor(isolate); |
24 } | 25 } |
25 | 26 |
26 | 27 |
27 CallPrinter::~CallPrinter() { DeleteArray(output_); } | 28 CallPrinter::~CallPrinter() { DeleteArray(output_); } |
28 | 29 |
29 | 30 |
30 const char* CallPrinter::Print(FunctionLiteral* program, int position) { | 31 const char* CallPrinter::Print(FunctionLiteral* program, int position) { |
31 Init(); | 32 Init(); |
32 position_ = position; | 33 position_ = position; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 | 186 |
186 void CallPrinter::VisitForInStatement(ForInStatement* node) { | 187 void CallPrinter::VisitForInStatement(ForInStatement* node) { |
187 Find(node->each()); | 188 Find(node->each()); |
188 Find(node->enumerable()); | 189 Find(node->enumerable()); |
189 Find(node->body()); | 190 Find(node->body()); |
190 } | 191 } |
191 | 192 |
192 | 193 |
193 void CallPrinter::VisitForOfStatement(ForOfStatement* node) { | 194 void CallPrinter::VisitForOfStatement(ForOfStatement* node) { |
194 Find(node->each()); | 195 Find(node->each()); |
195 Find(node->iterable()); | 196 Find(node->assign_iterator()); |
196 Find(node->body()); | 197 Find(node->body()); |
| 198 Find(node->next_result()); |
197 } | 199 } |
198 | 200 |
199 | 201 |
200 void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) { | 202 void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) { |
201 Find(node->try_block()); | 203 Find(node->try_block()); |
202 Find(node->catch_block()); | 204 Find(node->catch_block()); |
203 } | 205 } |
204 | 206 |
205 | 207 |
206 void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { | 208 void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { |
(...skipping 25 matching lines...) Expand all Loading... |
232 | 234 |
233 | 235 |
234 void CallPrinter::VisitConditional(Conditional* node) { | 236 void CallPrinter::VisitConditional(Conditional* node) { |
235 Find(node->condition()); | 237 Find(node->condition()); |
236 Find(node->then_expression()); | 238 Find(node->then_expression()); |
237 Find(node->else_expression()); | 239 Find(node->else_expression()); |
238 } | 240 } |
239 | 241 |
240 | 242 |
241 void CallPrinter::VisitLiteral(Literal* node) { | 243 void CallPrinter::VisitLiteral(Literal* node) { |
242 PrintLiteral(node->value(), true); | 244 PrintLiteral(*node->value(), true); |
243 } | 245 } |
244 | 246 |
245 | 247 |
246 void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) { | 248 void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) { |
247 Print("/"); | 249 Print("/"); |
248 PrintLiteral(node->pattern(), false); | 250 PrintLiteral(*node->pattern(), false); |
249 Print("/"); | 251 Print("/"); |
250 if (node->flags() & RegExp::kGlobal) Print("g"); | 252 if (node->flags() & RegExp::kGlobal) Print("g"); |
251 if (node->flags() & RegExp::kIgnoreCase) Print("i"); | 253 if (node->flags() & RegExp::kIgnoreCase) Print("i"); |
252 if (node->flags() & RegExp::kMultiline) Print("m"); | 254 if (node->flags() & RegExp::kMultiline) Print("m"); |
253 if (node->flags() & RegExp::kUnicode) Print("u"); | 255 if (node->flags() & RegExp::kUnicode) Print("u"); |
254 if (node->flags() & RegExp::kSticky) Print("y"); | 256 if (node->flags() & RegExp::kSticky) Print("y"); |
255 } | 257 } |
256 | 258 |
257 | 259 |
258 void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) { | 260 void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) { |
259 for (int i = 0; i < node->properties()->length(); i++) { | 261 for (int i = 0; i < node->properties()->length(); i++) { |
260 Find(node->properties()->at(i)->value()); | 262 Find(node->properties()->at(i)->value()); |
261 } | 263 } |
262 } | 264 } |
263 | 265 |
264 | 266 |
265 void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) { | 267 void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) { |
266 Print("["); | 268 Print("["); |
267 for (int i = 0; i < node->values()->length(); i++) { | 269 for (int i = 0; i < node->values()->length(); i++) { |
268 if (i != 0) Print(","); | 270 if (i != 0) Print(","); |
269 Find(node->values()->at(i), true); | 271 Find(node->values()->at(i), true); |
270 } | 272 } |
271 Print("]"); | 273 Print("]"); |
272 } | 274 } |
273 | 275 |
274 | 276 |
275 void CallPrinter::VisitVariableProxy(VariableProxy* node) { | 277 void CallPrinter::VisitVariableProxy(VariableProxy* node) { |
276 PrintLiteral(node->name(), false); | 278 if (is_builtin_) { |
| 279 // Variable names of builtins are meaningless due to minification. |
| 280 Print("(var)"); |
| 281 } else { |
| 282 PrintLiteral(*node->name(), false); |
| 283 } |
277 } | 284 } |
278 | 285 |
279 | 286 |
280 void CallPrinter::VisitAssignment(Assignment* node) { | 287 void CallPrinter::VisitAssignment(Assignment* node) { |
281 Find(node->target()); | 288 Find(node->target()); |
282 Find(node->value()); | 289 Find(node->value()); |
283 } | 290 } |
284 | 291 |
285 | 292 |
286 void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); } | 293 void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); } |
287 | 294 |
288 | 295 |
289 void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); } | 296 void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); } |
290 | 297 |
291 | 298 |
292 void CallPrinter::VisitProperty(Property* node) { | 299 void CallPrinter::VisitProperty(Property* node) { |
293 Expression* key = node->key(); | 300 Expression* key = node->key(); |
294 Literal* literal = key->AsLiteral(); | 301 Literal* literal = key->AsLiteral(); |
295 if (literal != NULL && literal->value()->IsInternalizedString()) { | 302 if (literal != NULL && literal->value()->IsInternalizedString()) { |
296 Find(node->obj(), true); | 303 Find(node->obj(), true); |
297 Print("."); | 304 Print("."); |
298 PrintLiteral(literal->value(), false); | 305 PrintLiteral(*literal->value(), false); |
299 } else { | 306 } else { |
300 Find(node->obj(), true); | 307 Find(node->obj(), true); |
301 Print("["); | 308 Print("["); |
302 Find(key, true); | 309 Find(key, true); |
303 Print("]"); | 310 Print("]"); |
304 } | 311 } |
305 } | 312 } |
306 | 313 |
307 | 314 |
308 void CallPrinter::VisitCall(Call* node) { | 315 void CallPrinter::VisitCall(Call* node) { |
309 bool was_found = !found_ && node->position() == position_; | 316 bool was_found = !found_ && node->position() == position_; |
310 if (was_found) found_ = true; | 317 if (was_found) { |
| 318 // Bail out if the error is caused by a direct call to a variable in builtin |
| 319 // code. The variable name is meaningless due to minification. |
| 320 if (is_builtin_ && node->expression()->IsVariableProxy()) { |
| 321 done_ = true; |
| 322 return; |
| 323 } |
| 324 found_ = true; |
| 325 } |
311 Find(node->expression(), true); | 326 Find(node->expression(), true); |
312 if (!was_found) Print("(...)"); | 327 if (!was_found) Print("(...)"); |
313 FindArguments(node->arguments()); | 328 FindArguments(node->arguments()); |
314 if (was_found) done_ = true; | 329 if (was_found) done_ = true; |
315 } | 330 } |
316 | 331 |
317 | 332 |
318 void CallPrinter::VisitCallNew(CallNew* node) { | 333 void CallPrinter::VisitCallNew(CallNew* node) { |
319 bool was_found = !found_ && node->position() == position_; | 334 bool was_found = !found_ && node->position() == position_; |
320 if (was_found) found_ = true; | 335 if (was_found) { |
| 336 // Bail out if the error is caused by a direct call to a variable in builtin |
| 337 // code. The variable name is meaningless due to minification. |
| 338 if (is_builtin_ && node->expression()->IsVariableProxy()) { |
| 339 done_ = true; |
| 340 return; |
| 341 } |
| 342 found_ = true; |
| 343 } |
321 Find(node->expression(), was_found); | 344 Find(node->expression(), was_found); |
322 FindArguments(node->arguments()); | 345 FindArguments(node->arguments()); |
323 if (was_found) done_ = true; | 346 if (was_found) done_ = true; |
324 } | 347 } |
325 | 348 |
326 | 349 |
327 void CallPrinter::VisitCallRuntime(CallRuntime* node) { | 350 void CallPrinter::VisitCallRuntime(CallRuntime* node) { |
328 if (!node->is_jsruntime() && | 351 if (!node->is_jsruntime() && |
329 node->function() == | 352 node->function() == |
330 Runtime::FunctionForId(Runtime::kInlineDefaultConstructorCallSuper)) { | 353 Runtime::FunctionForId(Runtime::kInlineDefaultConstructorCallSuper)) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 | 429 |
407 | 430 |
408 void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) { | 431 void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) { |
409 if (found_) return; | 432 if (found_) return; |
410 for (int i = 0; i < arguments->length(); i++) { | 433 for (int i = 0; i < arguments->length(); i++) { |
411 Find(arguments->at(i)); | 434 Find(arguments->at(i)); |
412 } | 435 } |
413 } | 436 } |
414 | 437 |
415 | 438 |
416 void CallPrinter::PrintLiteral(Handle<Object> value, bool quote) { | 439 void CallPrinter::PrintLiteral(Object* value, bool quote) { |
417 Object* object = *value; | 440 Object* object = value; |
418 if (object->IsString()) { | 441 if (object->IsString()) { |
419 String* string = String::cast(object); | |
420 if (quote) Print("\""); | 442 if (quote) Print("\""); |
421 for (int i = 0; i < string->length(); i++) { | 443 Print("%s", String::cast(object)->ToCString().get()); |
422 Print("%c", string->Get(i)); | |
423 } | |
424 if (quote) Print("\""); | 444 if (quote) Print("\""); |
425 } else if (object->IsNull()) { | 445 } else if (object->IsNull()) { |
426 Print("null"); | 446 Print("null"); |
427 } else if (object->IsTrue()) { | 447 } else if (object->IsTrue()) { |
428 Print("true"); | 448 Print("true"); |
429 } else if (object->IsFalse()) { | 449 } else if (object->IsFalse()) { |
430 Print("false"); | 450 Print("false"); |
431 } else if (object->IsUndefined()) { | 451 } else if (object->IsUndefined()) { |
432 Print("undefined"); | 452 Print("undefined"); |
433 } else if (object->IsNumber()) { | 453 } else if (object->IsNumber()) { |
434 Print("%g", object->Number()); | 454 Print("%g", object->Number()); |
| 455 } else if (object->IsSymbol()) { |
| 456 // Symbols can only occur as literals if they were inserted by the parser. |
| 457 PrintLiteral(Symbol::cast(object)->name(), false); |
435 } | 458 } |
436 } | 459 } |
437 | 460 |
438 | 461 |
439 void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) { | 462 void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) { |
440 PrintLiteral(value->string(), quote); | 463 PrintLiteral(*value->string(), quote); |
441 } | 464 } |
442 | 465 |
443 | 466 |
444 //----------------------------------------------------------------------------- | 467 //----------------------------------------------------------------------------- |
445 | 468 |
446 | 469 |
447 #ifdef DEBUG | 470 #ifdef DEBUG |
448 | 471 |
449 // A helper for ast nodes that use FeedbackVectorSlots. | 472 // A helper for ast nodes that use FeedbackVectorSlots. |
450 static int FormatSlotNode(Vector<char>* buf, Expression* node, | 473 static int FormatSlotNode(Vector<char>* buf, Expression* node, |
(...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1656 | 1679 |
1657 void AstPrinter::VisitSuperCallReference(SuperCallReference* node) { | 1680 void AstPrinter::VisitSuperCallReference(SuperCallReference* node) { |
1658 IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position()); | 1681 IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position()); |
1659 } | 1682 } |
1660 | 1683 |
1661 | 1684 |
1662 #endif // DEBUG | 1685 #endif // DEBUG |
1663 | 1686 |
1664 } // namespace internal | 1687 } // namespace internal |
1665 } // namespace v8 | 1688 } // namespace v8 |
OLD | NEW |