OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 | 44 |
45 class CodeGenSelector: public AstVisitor { | 45 class CodeGenSelector: public AstVisitor { |
46 public: | 46 public: |
47 enum CodeGenTag { NORMAL, FAST }; | 47 enum CodeGenTag { NORMAL, FAST }; |
48 | 48 |
49 CodeGenSelector() : has_supported_syntax_(true) {} | 49 CodeGenSelector() : has_supported_syntax_(true) {} |
50 | 50 |
51 CodeGenTag Select(FunctionLiteral* fun); | 51 CodeGenTag Select(FunctionLiteral* fun); |
52 | 52 |
53 private: | 53 private: |
| 54 void VisitDeclarations(ZoneList<Declaration*>* decls); |
54 void VisitStatements(ZoneList<Statement*>* stmts); | 55 void VisitStatements(ZoneList<Statement*>* stmts); |
55 | 56 |
56 // AST node visit functions. | 57 // AST node visit functions. |
57 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); | 58 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); |
58 AST_NODE_LIST(DECLARE_VISIT) | 59 AST_NODE_LIST(DECLARE_VISIT) |
59 #undef DECLARE_VISIT | 60 #undef DECLARE_VISIT |
60 | 61 |
61 bool has_supported_syntax_; | 62 bool has_supported_syntax_; |
62 | 63 |
63 DISALLOW_COPY_AND_ASSIGN(CodeGenSelector); | 64 DISALLOW_COPY_AND_ASSIGN(CodeGenSelector); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 // Signal a stack overflow by returning a null handle. The stack | 101 // Signal a stack overflow by returning a null handle. The stack |
101 // overflow exception will be thrown by the caller. | 102 // overflow exception will be thrown by the caller. |
102 return Handle<Code>::null(); | 103 return Handle<Code>::null(); |
103 } | 104 } |
104 | 105 |
105 // Generate code and return it. | 106 // Generate code and return it. |
106 if (FLAG_fast_compiler) { | 107 if (FLAG_fast_compiler) { |
107 CodeGenSelector selector; | 108 CodeGenSelector selector; |
108 CodeGenSelector::CodeGenTag code_gen = selector.Select(literal); | 109 CodeGenSelector::CodeGenTag code_gen = selector.Select(literal); |
109 if (code_gen == CodeGenSelector::FAST) { | 110 if (code_gen == CodeGenSelector::FAST) { |
110 return FastCodeGenerator::MakeCode(literal, script); | 111 return FastCodeGenerator::MakeCode(literal, script, is_eval); |
111 } | 112 } |
112 ASSERT(code_gen == CodeGenSelector::NORMAL); | 113 ASSERT(code_gen == CodeGenSelector::NORMAL); |
113 } | 114 } |
114 return CodeGenerator::MakeCode(literal, script, is_eval); | 115 return CodeGenerator::MakeCode(literal, script, is_eval); |
115 } | 116 } |
116 | 117 |
117 | 118 |
118 static bool IsValidJSON(FunctionLiteral* lit) { | 119 static bool IsValidJSON(FunctionLiteral* lit) { |
119 if (lit->body()->length() != 1) | 120 if (lit->body()->length() != 1) |
120 return false; | 121 return false; |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 | 444 |
444 // Check the function has compiled code. | 445 // Check the function has compiled code. |
445 ASSERT(shared->is_compiled()); | 446 ASSERT(shared->is_compiled()); |
446 return true; | 447 return true; |
447 } | 448 } |
448 | 449 |
449 | 450 |
450 CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) { | 451 CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) { |
451 Scope* scope = fun->scope(); | 452 Scope* scope = fun->scope(); |
452 | 453 |
453 if (!scope->is_global_scope()) return NORMAL; | 454 if (!scope->is_global_scope()) { |
| 455 if (FLAG_trace_bailout) PrintF("Non-global scope\n"); |
| 456 return NORMAL; |
| 457 } |
454 ASSERT(scope->num_heap_slots() == 0); | 458 ASSERT(scope->num_heap_slots() == 0); |
455 ASSERT(scope->arguments() == NULL); | 459 ASSERT(scope->arguments() == NULL); |
456 | 460 |
457 if (!scope->declarations()->is_empty()) return NORMAL; | 461 if (fun->materialized_literal_count() > 0) { |
458 if (fun->materialized_literal_count() > 0) return NORMAL; | 462 if (FLAG_trace_bailout) PrintF("Unsupported literal\n"); |
| 463 return NORMAL; |
| 464 } |
459 | 465 |
460 has_supported_syntax_ = true; | 466 has_supported_syntax_ = true; |
| 467 VisitDeclarations(fun->scope()->declarations()); |
| 468 if (!has_supported_syntax_) return NORMAL; |
| 469 |
461 VisitStatements(fun->body()); | 470 VisitStatements(fun->body()); |
462 return has_supported_syntax_ ? FAST : NORMAL; | 471 return has_supported_syntax_ ? FAST : NORMAL; |
463 } | 472 } |
464 | 473 |
465 | 474 |
466 #define BAILOUT(reason) \ | 475 #define BAILOUT(reason) \ |
467 do { \ | 476 do { \ |
468 if (FLAG_trace_bailout) { \ | 477 if (FLAG_trace_bailout) { \ |
469 PrintF("%s\n", reason); \ | 478 PrintF("%s\n", reason); \ |
470 } \ | 479 } \ |
471 has_supported_syntax_ = false; \ | 480 has_supported_syntax_ = false; \ |
472 return; \ | 481 return; \ |
473 } while (false) | 482 } while (false) |
474 | 483 |
475 | 484 |
476 #define CHECK_BAILOUT \ | 485 #define CHECK_BAILOUT \ |
477 do { \ | 486 do { \ |
478 if (!has_supported_syntax_) return; \ | 487 if (!has_supported_syntax_) return; \ |
479 } while (false) | 488 } while (false) |
480 | 489 |
481 | 490 |
| 491 void CodeGenSelector::VisitDeclarations(ZoneList<Declaration*>* decls) { |
| 492 for (int i = 0; i < decls->length(); i++) { |
| 493 Visit(decls->at(i)); |
| 494 CHECK_BAILOUT; |
| 495 } |
| 496 } |
| 497 |
| 498 |
482 void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) { | 499 void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) { |
483 for (int i = 0, len = stmts->length(); i < len; i++) { | 500 for (int i = 0, len = stmts->length(); i < len; i++) { |
| 501 Visit(stmts->at(i)); |
484 CHECK_BAILOUT; | 502 CHECK_BAILOUT; |
485 Visit(stmts->at(i)); | |
486 } | 503 } |
487 } | 504 } |
488 | 505 |
489 | 506 |
490 void CodeGenSelector::VisitDeclaration(Declaration* decl) { | 507 void CodeGenSelector::VisitDeclaration(Declaration* decl) { |
491 BAILOUT("Declaration"); | 508 Variable* var = decl->proxy()->var(); |
| 509 if (!var->is_global() || var->mode() == Variable::CONST) { |
| 510 BAILOUT("Non-global declaration"); |
| 511 } |
492 } | 512 } |
493 | 513 |
494 | 514 |
495 void CodeGenSelector::VisitBlock(Block* stmt) { | 515 void CodeGenSelector::VisitBlock(Block* stmt) { |
496 BAILOUT("Block"); | 516 VisitStatements(stmt->statements()); |
497 } | 517 } |
498 | 518 |
499 | 519 |
500 void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) { | 520 void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) { |
501 Expression* expr = stmt->expression(); | 521 Expression* expr = stmt->expression(); |
502 Visit(expr); | 522 Visit(expr); |
503 CHECK_BAILOUT; | 523 CHECK_BAILOUT; |
504 expr->set_location(Location::Nowhere()); | 524 expr->set_location(Location::Nowhere()); |
505 } | 525 } |
506 | 526 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 BAILOUT("TryFinallyStatement"); | 594 BAILOUT("TryFinallyStatement"); |
575 } | 595 } |
576 | 596 |
577 | 597 |
578 void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) { | 598 void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) { |
579 BAILOUT("DebuggerStatement"); | 599 BAILOUT("DebuggerStatement"); |
580 } | 600 } |
581 | 601 |
582 | 602 |
583 void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) { | 603 void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) { |
584 BAILOUT("FunctionLiteral"); | 604 if (!expr->AllowsLazyCompilation()) { |
| 605 BAILOUT("FunctionLiteral does not allow lazy compilation"); |
| 606 } |
585 } | 607 } |
586 | 608 |
587 | 609 |
588 void CodeGenSelector::VisitFunctionBoilerplateLiteral( | 610 void CodeGenSelector::VisitFunctionBoilerplateLiteral( |
589 FunctionBoilerplateLiteral* expr) { | 611 FunctionBoilerplateLiteral* expr) { |
590 BAILOUT("FunctionBoilerplateLiteral"); | 612 BAILOUT("FunctionBoilerplateLiteral"); |
591 } | 613 } |
592 | 614 |
593 | 615 |
594 void CodeGenSelector::VisitConditional(Conditional* expr) { | 616 void CodeGenSelector::VisitConditional(Conditional* expr) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 BAILOUT("Throw"); | 689 BAILOUT("Throw"); |
668 } | 690 } |
669 | 691 |
670 | 692 |
671 void CodeGenSelector::VisitProperty(Property* expr) { | 693 void CodeGenSelector::VisitProperty(Property* expr) { |
672 BAILOUT("Property"); | 694 BAILOUT("Property"); |
673 } | 695 } |
674 | 696 |
675 | 697 |
676 void CodeGenSelector::VisitCall(Call* expr) { | 698 void CodeGenSelector::VisitCall(Call* expr) { |
677 BAILOUT("Call"); | 699 Expression* fun = expr->expression(); |
| 700 ZoneList<Expression*>* args = expr->arguments(); |
| 701 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 702 |
| 703 // Check for supported calls |
| 704 if (var != NULL && var->is_possibly_eval()) { |
| 705 BAILOUT("Call to a function named 'eval'"); |
| 706 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 707 // ---------------------------------- |
| 708 // JavaScript example: 'foo(1, 2, 3)' // foo is global |
| 709 // ---------------------------------- |
| 710 } else { |
| 711 BAILOUT("Call to a non-global function"); |
| 712 } |
| 713 // Check all arguments to the call |
| 714 for (int i = 0; i < args->length(); i++) { |
| 715 Visit(args->at(i)); |
| 716 CHECK_BAILOUT; |
| 717 } |
678 } | 718 } |
679 | 719 |
680 | 720 |
681 void CodeGenSelector::VisitCallNew(CallNew* expr) { | 721 void CodeGenSelector::VisitCallNew(CallNew* expr) { |
682 BAILOUT("CallNew"); | 722 BAILOUT("CallNew"); |
683 } | 723 } |
684 | 724 |
685 | 725 |
686 void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) { | 726 void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) { |
687 BAILOUT("CallRuntime"); | 727 // In case of JS runtime function bail out. |
| 728 if (expr->function() == NULL) BAILOUT("CallRuntime"); |
| 729 // Check for inline runtime call |
| 730 if (expr->name()->Get(0) == '_' && |
| 731 CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { |
| 732 BAILOUT("InlineRuntimeCall"); |
| 733 } |
| 734 for (int i = 0; i < expr->arguments()->length(); i++) { |
| 735 Visit(expr->arguments()->at(i)); |
| 736 CHECK_BAILOUT; |
| 737 } |
688 } | 738 } |
689 | 739 |
690 | 740 |
691 void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) { | 741 void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) { |
692 BAILOUT("UnaryOperation"); | 742 BAILOUT("UnaryOperation"); |
693 } | 743 } |
694 | 744 |
695 | 745 |
696 void CodeGenSelector::VisitCountOperation(CountOperation* expr) { | 746 void CodeGenSelector::VisitCountOperation(CountOperation* expr) { |
697 BAILOUT("CountOperation"); | 747 BAILOUT("CountOperation"); |
(...skipping 12 matching lines...) Expand all Loading... |
710 | 760 |
711 void CodeGenSelector::VisitThisFunction(ThisFunction* expr) { | 761 void CodeGenSelector::VisitThisFunction(ThisFunction* expr) { |
712 BAILOUT("ThisFunction"); | 762 BAILOUT("ThisFunction"); |
713 } | 763 } |
714 | 764 |
715 #undef BAILOUT | 765 #undef BAILOUT |
716 #undef CHECK_BAILOUT | 766 #undef CHECK_BAILOUT |
717 | 767 |
718 | 768 |
719 } } // namespace v8::internal | 769 } } // namespace v8::internal |
OLD | NEW |