Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Side by Side Diff: src/compiler.cc

Issue 549108: Rename the toplevel code generator from "Fast" to "Full". It was... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/fast-codegen-arm.cc ('k') | src/fast-codegen.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 24 matching lines...) Expand all
35 #include "fast-codegen.h" 35 #include "fast-codegen.h"
36 #include "oprofile-agent.h" 36 #include "oprofile-agent.h"
37 #include "rewriter.h" 37 #include "rewriter.h"
38 #include "scopes.h" 38 #include "scopes.h"
39 #include "usage-analyzer.h" 39 #include "usage-analyzer.h"
40 40
41 namespace v8 { 41 namespace v8 {
42 namespace internal { 42 namespace internal {
43 43
44 44
45 class CodeGenSelector: public AstVisitor {
46 public:
47 enum CodeGenTag { NORMAL, FAST };
48
49 CodeGenSelector() : has_supported_syntax_(true) {}
50
51 CodeGenTag Select(FunctionLiteral* fun);
52
53 private:
54 void VisitDeclarations(ZoneList<Declaration*>* decls);
55 void VisitStatements(ZoneList<Statement*>* stmts);
56
57 // AST node visit functions.
58 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
59 AST_NODE_LIST(DECLARE_VISIT)
60 #undef DECLARE_VISIT
61
62 bool has_supported_syntax_;
63
64 DISALLOW_COPY_AND_ASSIGN(CodeGenSelector);
65 };
66
67
68 static Handle<Code> MakeCode(FunctionLiteral* literal, 45 static Handle<Code> MakeCode(FunctionLiteral* literal,
69 Handle<Script> script, 46 Handle<Script> script,
70 Handle<Context> context, 47 Handle<Context> context,
71 bool is_eval, 48 bool is_eval,
72 Handle<SharedFunctionInfo> shared) { 49 Handle<SharedFunctionInfo> shared) {
73 ASSERT(literal != NULL); 50 ASSERT(literal != NULL);
74 51
75 // Rewrite the AST by introducing .result assignments where needed. 52 // Rewrite the AST by introducing .result assignments where needed.
76 if (!Rewriter::Process(literal) || !AnalyzeVariableUsage(literal)) { 53 if (!Rewriter::Process(literal) || !AnalyzeVariableUsage(literal)) {
77 // Signal a stack overflow by returning a null handle. The stack 54 // Signal a stack overflow by returning a null handle. The stack
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 // generator for code in the global scope. Otherwise obey the 87 // generator for code in the global scope. Otherwise obey the
111 // explicit hint in the shared function info. 88 // explicit hint in the shared function info.
112 // If always_fast_compiler is true, always try the fast compiler. 89 // If always_fast_compiler is true, always try the fast compiler.
113 if (shared.is_null() && !literal->scope()->is_global_scope() && 90 if (shared.is_null() && !literal->scope()->is_global_scope() &&
114 !FLAG_always_fast_compiler) { 91 !FLAG_always_fast_compiler) {
115 if (FLAG_trace_bailout) PrintF("Non-global scope\n"); 92 if (FLAG_trace_bailout) PrintF("Non-global scope\n");
116 } else if (!shared.is_null() && !shared->try_fast_codegen() && 93 } else if (!shared.is_null() && !shared->try_fast_codegen() &&
117 !FLAG_always_fast_compiler) { 94 !FLAG_always_fast_compiler) {
118 if (FLAG_trace_bailout) PrintF("No hint to try fast\n"); 95 if (FLAG_trace_bailout) PrintF("No hint to try fast\n");
119 } else { 96 } else {
120 CodeGenSelector selector; 97 FullCodeGenSyntaxChecker checker;
121 CodeGenSelector::CodeGenTag code_gen = selector.Select(literal); 98 checker.Check(literal);
122 if (code_gen == CodeGenSelector::FAST) { 99 if (checker.has_supported_syntax()) {
123 return FastCodeGenerator::MakeCode(literal, script, is_eval); 100 return FullCodeGenerator::MakeCode(literal, script, is_eval);
124 } 101 }
125 ASSERT(code_gen == CodeGenSelector::NORMAL);
126 } 102 }
127 } 103 }
128 return CodeGenerator::MakeCode(literal, script, is_eval); 104 return CodeGenerator::MakeCode(literal, script, is_eval);
129 } 105 }
130 106
131 107
132 static bool IsValidJSON(FunctionLiteral* lit) { 108 static bool IsValidJSON(FunctionLiteral* lit) {
133 if (lit->body()->length() != 1) 109 if (lit->body()->length() != 1)
134 return false; 110 return false;
135 Statement* stmt = lit->body()->at(0); 111 Statement* stmt = lit->body()->at(0);
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 } else { 463 } else {
488 // The bodies of function literals have not yet been visited by 464 // The bodies of function literals have not yet been visited by
489 // the AST optimizer/analyzer. 465 // the AST optimizer/analyzer.
490 if (!Rewriter::Optimize(literal)) { 466 if (!Rewriter::Optimize(literal)) {
491 return Handle<JSFunction>::null(); 467 return Handle<JSFunction>::null();
492 } 468 }
493 469
494 // Generate code and return it. 470 // Generate code and return it.
495 bool is_compiled = false; 471 bool is_compiled = false;
496 if (FLAG_fast_compiler && literal->try_fast_codegen()) { 472 if (FLAG_fast_compiler && literal->try_fast_codegen()) {
497 CodeGenSelector selector; 473 FullCodeGenSyntaxChecker checker;
498 CodeGenSelector::CodeGenTag code_gen = selector.Select(literal); 474 checker.Check(literal);
499 if (code_gen == CodeGenSelector::FAST) { 475 if (checker.has_supported_syntax()) {
500 code = FastCodeGenerator::MakeCode(literal, 476 code = FullCodeGenerator::MakeCode(literal,
501 script, 477 script,
502 false); // Not eval. 478 false); // Not eval.
503 is_compiled = true; 479 is_compiled = true;
504 } 480 }
505 } 481 }
506 482
507 if (!is_compiled) { 483 if (!is_compiled) {
508 // We didn't try the fast compiler, or we failed to select it. 484 // We didn't try the fast compiler, or we failed to select it.
509 code = CodeGenerator::MakeCode(literal, 485 code = CodeGenerator::MakeCode(literal,
510 script, 486 script,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 fun->shared()->set_is_expression(lit->is_expression()); 540 fun->shared()->set_is_expression(lit->is_expression());
565 fun->shared()->set_is_toplevel(is_toplevel); 541 fun->shared()->set_is_toplevel(is_toplevel);
566 fun->shared()->set_inferred_name(*lit->inferred_name()); 542 fun->shared()->set_inferred_name(*lit->inferred_name());
567 fun->shared()->SetThisPropertyAssignmentsInfo( 543 fun->shared()->SetThisPropertyAssignmentsInfo(
568 lit->has_only_simple_this_property_assignments(), 544 lit->has_only_simple_this_property_assignments(),
569 *lit->this_property_assignments()); 545 *lit->this_property_assignments());
570 fun->shared()->set_try_fast_codegen(lit->try_fast_codegen()); 546 fun->shared()->set_try_fast_codegen(lit->try_fast_codegen());
571 } 547 }
572 548
573 549
574 CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) {
575 Scope* scope = fun->scope();
576
577 if (scope->num_heap_slots() > 0) {
578 // We support functions with a local context if they do not have
579 // parameters that need to be copied into the context.
580 for (int i = 0, len = scope->num_parameters(); i < len; i++) {
581 Slot* slot = scope->parameter(i)->slot();
582 if (slot != NULL && slot->type() == Slot::CONTEXT) {
583 if (FLAG_trace_bailout) {
584 PrintF("Function has context-allocated parameters.\n");
585 }
586 return NORMAL;
587 }
588 }
589 }
590
591 has_supported_syntax_ = true;
592 VisitDeclarations(scope->declarations());
593 if (!has_supported_syntax_) return NORMAL;
594
595 VisitStatements(fun->body());
596 return has_supported_syntax_ ? FAST : NORMAL;
597 }
598
599
600 #define BAILOUT(reason) \
601 do { \
602 if (FLAG_trace_bailout) { \
603 PrintF("%s\n", reason); \
604 } \
605 has_supported_syntax_ = false; \
606 return; \
607 } while (false)
608
609
610 #define CHECK_BAILOUT \
611 do { \
612 if (!has_supported_syntax_) return; \
613 } while (false)
614
615
616 void CodeGenSelector::VisitDeclarations(ZoneList<Declaration*>* decls) {
617 for (int i = 0; i < decls->length(); i++) {
618 Visit(decls->at(i));
619 CHECK_BAILOUT;
620 }
621 }
622
623
624 void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) {
625 for (int i = 0, len = stmts->length(); i < len; i++) {
626 Visit(stmts->at(i));
627 CHECK_BAILOUT;
628 }
629 }
630
631
632 void CodeGenSelector::VisitDeclaration(Declaration* decl) {
633 Property* prop = decl->proxy()->AsProperty();
634 if (prop != NULL) {
635 Visit(prop->obj());
636 Visit(prop->key());
637 }
638
639 if (decl->fun() != NULL) {
640 Visit(decl->fun());
641 }
642 }
643
644
645 void CodeGenSelector::VisitBlock(Block* stmt) {
646 VisitStatements(stmt->statements());
647 }
648
649
650 void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) {
651 Visit(stmt->expression());
652 }
653
654
655 void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) {}
656
657
658 void CodeGenSelector::VisitIfStatement(IfStatement* stmt) {
659 Visit(stmt->condition());
660 CHECK_BAILOUT;
661 Visit(stmt->then_statement());
662 CHECK_BAILOUT;
663 Visit(stmt->else_statement());
664 }
665
666
667 void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {}
668
669
670 void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {}
671
672
673 void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) {
674 Visit(stmt->expression());
675 }
676
677
678 void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) {
679 Visit(stmt->expression());
680 }
681
682
683 void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) {}
684
685
686 void CodeGenSelector::VisitSwitchStatement(SwitchStatement* stmt) {
687 BAILOUT("SwitchStatement");
688 }
689
690
691 void CodeGenSelector::VisitDoWhileStatement(DoWhileStatement* stmt) {
692 Visit(stmt->cond());
693 CHECK_BAILOUT;
694 Visit(stmt->body());
695 }
696
697
698 void CodeGenSelector::VisitWhileStatement(WhileStatement* stmt) {
699 Visit(stmt->cond());
700 CHECK_BAILOUT;
701 Visit(stmt->body());
702 }
703
704
705 void CodeGenSelector::VisitForStatement(ForStatement* stmt) {
706 BAILOUT("ForStatement");
707 }
708
709
710 void CodeGenSelector::VisitForInStatement(ForInStatement* stmt) {
711 BAILOUT("ForInStatement");
712 }
713
714
715 void CodeGenSelector::VisitTryCatchStatement(TryCatchStatement* stmt) {
716 Visit(stmt->try_block());
717 CHECK_BAILOUT;
718 Visit(stmt->catch_block());
719 }
720
721
722 void CodeGenSelector::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
723 Visit(stmt->try_block());
724 CHECK_BAILOUT;
725 Visit(stmt->finally_block());
726 }
727
728
729 void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {}
730
731
732 void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {}
733
734
735 void CodeGenSelector::VisitFunctionBoilerplateLiteral(
736 FunctionBoilerplateLiteral* expr) {
737 BAILOUT("FunctionBoilerplateLiteral");
738 }
739
740
741 void CodeGenSelector::VisitConditional(Conditional* expr) {
742 Visit(expr->condition());
743 CHECK_BAILOUT;
744 Visit(expr->then_expression());
745 CHECK_BAILOUT;
746 Visit(expr->else_expression());
747 }
748
749
750 void CodeGenSelector::VisitSlot(Slot* expr) {
751 UNREACHABLE();
752 }
753
754
755 void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
756 Variable* var = expr->var();
757 if (!var->is_global()) {
758 Slot* slot = var->slot();
759 if (slot != NULL) {
760 Slot::Type type = slot->type();
761 // When LOOKUP slots are enabled, some currently dead code
762 // implementing unary typeof will become live.
763 if (type == Slot::LOOKUP) {
764 BAILOUT("Lookup slot");
765 }
766 } else {
767 // If not global or a slot, it is a parameter rewritten to an explicit
768 // property reference on the (shadow) arguments object.
769 #ifdef DEBUG
770 Property* property = var->AsProperty();
771 ASSERT_NOT_NULL(property);
772 Variable* object = property->obj()->AsVariableProxy()->AsVariable();
773 ASSERT_NOT_NULL(object);
774 ASSERT_NOT_NULL(object->slot());
775 ASSERT_NOT_NULL(property->key()->AsLiteral());
776 ASSERT(property->key()->AsLiteral()->handle()->IsSmi());
777 #endif
778 }
779 }
780 }
781
782
783 void CodeGenSelector::VisitLiteral(Literal* expr) {}
784
785
786 void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {}
787
788
789 void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) {
790 ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
791
792 for (int i = 0, len = properties->length(); i < len; i++) {
793 ObjectLiteral::Property* property = properties->at(i);
794 if (property->IsCompileTimeValue()) continue;
795 Visit(property->key());
796 CHECK_BAILOUT;
797 Visit(property->value());
798 CHECK_BAILOUT;
799 }
800 }
801
802
803 void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) {
804 ZoneList<Expression*>* subexprs = expr->values();
805 for (int i = 0, len = subexprs->length(); i < len; i++) {
806 Expression* subexpr = subexprs->at(i);
807 if (subexpr->AsLiteral() != NULL) continue;
808 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
809 Visit(subexpr);
810 CHECK_BAILOUT;
811 }
812 }
813
814
815 void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) {
816 Visit(expr->key());
817 CHECK_BAILOUT;
818 Visit(expr->value());
819 }
820
821
822 void CodeGenSelector::VisitAssignment(Assignment* expr) {
823 // We support plain non-compound assignments to properties, parameters and
824 // non-context (stack-allocated) locals, and global variables.
825 Token::Value op = expr->op();
826 if (op == Token::INIT_CONST) BAILOUT("initialize constant");
827
828 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
829 Property* prop = expr->target()->AsProperty();
830 ASSERT(var == NULL || prop == NULL);
831 if (var != NULL) {
832 if (var->mode() == Variable::CONST) {
833 BAILOUT("Assignment to const");
834 }
835 // All global variables are supported.
836 if (!var->is_global()) {
837 ASSERT(var->slot() != NULL);
838 Slot::Type type = var->slot()->type();
839 if (type == Slot::LOOKUP) {
840 BAILOUT("Lookup slot");
841 }
842 }
843 } else if (prop != NULL) {
844 Visit(prop->obj());
845 CHECK_BAILOUT;
846 Visit(prop->key());
847 CHECK_BAILOUT;
848 } else {
849 // This is a throw reference error.
850 BAILOUT("non-variable/non-property assignment");
851 }
852
853 Visit(expr->value());
854 }
855
856
857 void CodeGenSelector::VisitThrow(Throw* expr) {
858 Visit(expr->exception());
859 }
860
861
862 void CodeGenSelector::VisitProperty(Property* expr) {
863 Visit(expr->obj());
864 CHECK_BAILOUT;
865 Visit(expr->key());
866 }
867
868
869 void CodeGenSelector::VisitCall(Call* expr) {
870 Expression* fun = expr->expression();
871 ZoneList<Expression*>* args = expr->arguments();
872 Variable* var = fun->AsVariableProxy()->AsVariable();
873
874 // Check for supported calls
875 if (var != NULL && var->is_possibly_eval()) {
876 BAILOUT("call to the identifier 'eval'");
877 } else if (var != NULL && !var->is_this() && var->is_global()) {
878 // Calls to global variables are supported.
879 } else if (var != NULL && var->slot() != NULL &&
880 var->slot()->type() == Slot::LOOKUP) {
881 BAILOUT("call to a lookup slot");
882 } else if (fun->AsProperty() != NULL) {
883 Property* prop = fun->AsProperty();
884 Visit(prop->obj());
885 CHECK_BAILOUT;
886 Visit(prop->key());
887 CHECK_BAILOUT;
888 } else {
889 // Otherwise the call is supported if the function expression is.
890 Visit(fun);
891 }
892 // Check all arguments to the call.
893 for (int i = 0; i < args->length(); i++) {
894 Visit(args->at(i));
895 CHECK_BAILOUT;
896 }
897 }
898
899
900 void CodeGenSelector::VisitCallNew(CallNew* expr) {
901 Visit(expr->expression());
902 CHECK_BAILOUT;
903 ZoneList<Expression*>* args = expr->arguments();
904 // Check all arguments to the call
905 for (int i = 0; i < args->length(); i++) {
906 Visit(args->at(i));
907 CHECK_BAILOUT;
908 }
909 }
910
911
912 void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) {
913 // Check for inline runtime call
914 if (expr->name()->Get(0) == '_' &&
915 CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) {
916 BAILOUT("inlined runtime call");
917 }
918 // Check all arguments to the call. (Relies on TEMP meaning STACK.)
919 for (int i = 0; i < expr->arguments()->length(); i++) {
920 Visit(expr->arguments()->at(i));
921 CHECK_BAILOUT;
922 }
923 }
924
925
926 void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) {
927 switch (expr->op()) {
928 case Token::VOID:
929 case Token::NOT:
930 case Token::TYPEOF:
931 Visit(expr->expression());
932 break;
933 case Token::BIT_NOT:
934 BAILOUT("UnaryOperation: BIT_NOT");
935 case Token::DELETE:
936 BAILOUT("UnaryOperation: DELETE");
937 case Token::ADD:
938 BAILOUT("UnaryOperation: ADD");
939 case Token::SUB:
940 BAILOUT("UnaryOperation: SUB");
941 default:
942 UNREACHABLE();
943 }
944 }
945
946
947 void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
948 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
949 Property* prop = expr->expression()->AsProperty();
950 ASSERT(var == NULL || prop == NULL);
951 if (var != NULL) {
952 // All global variables are supported.
953 if (!var->is_global()) {
954 ASSERT(var->slot() != NULL);
955 Slot::Type type = var->slot()->type();
956 if (type == Slot::LOOKUP) {
957 BAILOUT("CountOperation with lookup slot");
958 }
959 }
960 } else if (prop != NULL) {
961 Visit(prop->obj());
962 CHECK_BAILOUT;
963 Visit(prop->key());
964 CHECK_BAILOUT;
965 } else {
966 // This is a throw reference error.
967 BAILOUT("CountOperation non-variable/non-property expression");
968 }
969 }
970
971
972 void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) {
973 Visit(expr->left());
974 CHECK_BAILOUT;
975 Visit(expr->right());
976 }
977
978
979 void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) {
980 Visit(expr->left());
981 CHECK_BAILOUT;
982 Visit(expr->right());
983 }
984
985
986 void CodeGenSelector::VisitThisFunction(ThisFunction* expr) {}
987
988 #undef BAILOUT
989 #undef CHECK_BAILOUT
990
991
992 } } // namespace v8::internal 550 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/fast-codegen-arm.cc ('k') | src/fast-codegen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698