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