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 28 matching lines...) Expand all Loading... | |
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 { | 45 class CodeGenSelector: public AstVisitor { |
46 public: | 46 public: |
47 enum CodeGenTag { NORMAL, FAST }; | 47 enum CodeGenTag { NORMAL, FAST }; |
48 | 48 |
49 CodeGenSelector() | 49 CodeGenSelector() : has_supported_syntax_(true) {} |
50 : has_supported_syntax_(true), | |
51 context_(Expression::kUninitialized) { | |
52 } | |
53 | 50 |
54 CodeGenTag Select(FunctionLiteral* fun); | 51 CodeGenTag Select(FunctionLiteral* fun); |
55 | 52 |
56 private: | 53 private: |
57 // Visit an expression in a given expression context. | |
58 void ProcessExpression(Expression* expr, Expression::Context context) { | |
59 ASSERT(expr->context() == Expression::kUninitialized || | |
60 expr->context() == context); | |
61 Expression::Context saved = context_; | |
62 context_ = context; | |
63 Visit(expr); | |
64 expr->set_context(context); | |
65 context_ = saved; | |
66 } | |
67 | |
68 void VisitDeclarations(ZoneList<Declaration*>* decls); | 54 void VisitDeclarations(ZoneList<Declaration*>* decls); |
69 void VisitStatements(ZoneList<Statement*>* stmts); | 55 void VisitStatements(ZoneList<Statement*>* stmts); |
70 | 56 |
71 // AST node visit functions. | 57 // AST node visit functions. |
72 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); | 58 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); |
73 AST_NODE_LIST(DECLARE_VISIT) | 59 AST_NODE_LIST(DECLARE_VISIT) |
74 #undef DECLARE_VISIT | 60 #undef DECLARE_VISIT |
75 | 61 |
76 bool has_supported_syntax_; | 62 bool has_supported_syntax_; |
77 | 63 |
78 // The desired expression context of the currently visited expression. | |
79 Expression::Context context_; | |
80 | |
81 DISALLOW_COPY_AND_ASSIGN(CodeGenSelector); | 64 DISALLOW_COPY_AND_ASSIGN(CodeGenSelector); |
82 }; | 65 }; |
83 | 66 |
84 | 67 |
85 static Handle<Code> MakeCode(FunctionLiteral* literal, | 68 static Handle<Code> MakeCode(FunctionLiteral* literal, |
86 Handle<Script> script, | 69 Handle<Script> script, |
87 Handle<Context> context, | 70 Handle<Context> context, |
88 bool is_eval, | 71 bool is_eval, |
89 Handle<SharedFunctionInfo> shared) { | 72 Handle<SharedFunctionInfo> shared) { |
90 ASSERT(literal != NULL); | 73 ASSERT(literal != NULL); |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
642 for (int i = 0, len = stmts->length(); i < len; i++) { | 625 for (int i = 0, len = stmts->length(); i < len; i++) { |
643 Visit(stmts->at(i)); | 626 Visit(stmts->at(i)); |
644 CHECK_BAILOUT; | 627 CHECK_BAILOUT; |
645 } | 628 } |
646 } | 629 } |
647 | 630 |
648 | 631 |
649 void CodeGenSelector::VisitDeclaration(Declaration* decl) { | 632 void CodeGenSelector::VisitDeclaration(Declaration* decl) { |
650 Property* prop = decl->proxy()->AsProperty(); | 633 Property* prop = decl->proxy()->AsProperty(); |
651 if (prop != NULL) { | 634 if (prop != NULL) { |
652 ProcessExpression(prop->obj(), Expression::kValue); | 635 Visit(prop->obj()); |
653 ProcessExpression(prop->key(), Expression::kValue); | 636 Visit(prop->key()); |
654 } | 637 } |
655 | 638 |
656 if (decl->fun() != NULL) { | 639 if (decl->fun() != NULL) { |
657 ProcessExpression(decl->fun(), Expression::kValue); | 640 Visit(decl->fun()); |
658 } | 641 } |
659 } | 642 } |
660 | 643 |
661 | 644 |
662 void CodeGenSelector::VisitBlock(Block* stmt) { | 645 void CodeGenSelector::VisitBlock(Block* stmt) { |
663 VisitStatements(stmt->statements()); | 646 VisitStatements(stmt->statements()); |
664 } | 647 } |
665 | 648 |
666 | 649 |
667 void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) { | 650 void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) { |
668 ProcessExpression(stmt->expression(), Expression::kEffect); | 651 Visit(stmt->expression()); |
669 } | 652 } |
670 | 653 |
671 | 654 |
672 void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) { | 655 void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) {} |
673 // EmptyStatement is supported. | |
674 } | |
675 | 656 |
676 | 657 |
677 void CodeGenSelector::VisitIfStatement(IfStatement* stmt) { | 658 void CodeGenSelector::VisitIfStatement(IfStatement* stmt) { |
678 ProcessExpression(stmt->condition(), Expression::kTest); | 659 Visit(stmt->condition()); |
679 CHECK_BAILOUT; | 660 CHECK_BAILOUT; |
680 Visit(stmt->then_statement()); | 661 Visit(stmt->then_statement()); |
681 CHECK_BAILOUT; | 662 CHECK_BAILOUT; |
682 Visit(stmt->else_statement()); | 663 Visit(stmt->else_statement()); |
683 } | 664 } |
684 | 665 |
685 | 666 |
686 void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) { | 667 void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {} |
687 } | |
688 | 668 |
689 | 669 |
690 void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) { | 670 void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {} |
691 } | |
692 | 671 |
693 | 672 |
694 void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) { | 673 void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) { |
695 ProcessExpression(stmt->expression(), Expression::kValue); | 674 Visit(stmt->expression()); |
696 } | 675 } |
697 | 676 |
698 | 677 |
699 void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) { | 678 void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) { |
700 ProcessExpression(stmt->expression(), Expression::kValue); | 679 Visit(stmt->expression()); |
701 } | 680 } |
702 | 681 |
703 | 682 |
704 void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) { | 683 void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) {} |
705 // Supported. | |
706 } | |
707 | 684 |
708 | 685 |
709 void CodeGenSelector::VisitSwitchStatement(SwitchStatement* stmt) { | 686 void CodeGenSelector::VisitSwitchStatement(SwitchStatement* stmt) { |
710 BAILOUT("SwitchStatement"); | 687 BAILOUT("SwitchStatement"); |
711 } | 688 } |
712 | 689 |
713 | 690 |
714 void CodeGenSelector::VisitDoWhileStatement(DoWhileStatement* stmt) { | 691 void CodeGenSelector::VisitDoWhileStatement(DoWhileStatement* stmt) { |
715 // We do not handle loops with breaks or continue statements in their | 692 Visit(stmt->cond()); |
716 // body. We will bailout when we hit those statements in the body. | |
717 ProcessExpression(stmt->cond(), Expression::kTest); | |
718 CHECK_BAILOUT; | 693 CHECK_BAILOUT; |
719 Visit(stmt->body()); | 694 Visit(stmt->body()); |
720 } | 695 } |
721 | 696 |
722 | 697 |
723 void CodeGenSelector::VisitWhileStatement(WhileStatement* stmt) { | 698 void CodeGenSelector::VisitWhileStatement(WhileStatement* stmt) { |
724 // We do not handle loops with breaks or continue statements in their | 699 Visit(stmt->cond()); |
725 // body. We will bailout when we hit those statements in the body. | |
726 ProcessExpression(stmt->cond(), Expression::kTest); | |
727 CHECK_BAILOUT; | 700 CHECK_BAILOUT; |
728 Visit(stmt->body()); | 701 Visit(stmt->body()); |
729 } | 702 } |
730 | 703 |
731 | 704 |
732 void CodeGenSelector::VisitForStatement(ForStatement* stmt) { | 705 void CodeGenSelector::VisitForStatement(ForStatement* stmt) { |
733 BAILOUT("ForStatement"); | 706 BAILOUT("ForStatement"); |
734 } | 707 } |
735 | 708 |
736 | 709 |
737 void CodeGenSelector::VisitForInStatement(ForInStatement* stmt) { | 710 void CodeGenSelector::VisitForInStatement(ForInStatement* stmt) { |
738 BAILOUT("ForInStatement"); | 711 BAILOUT("ForInStatement"); |
739 } | 712 } |
740 | 713 |
741 | 714 |
742 void CodeGenSelector::VisitTryCatchStatement(TryCatchStatement* stmt) { | 715 void CodeGenSelector::VisitTryCatchStatement(TryCatchStatement* stmt) { |
743 Visit(stmt->try_block()); | 716 Visit(stmt->try_block()); |
744 CHECK_BAILOUT; | 717 CHECK_BAILOUT; |
745 Visit(stmt->catch_block()); | 718 Visit(stmt->catch_block()); |
746 } | 719 } |
747 | 720 |
748 | 721 |
749 void CodeGenSelector::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 722 void CodeGenSelector::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
750 Visit(stmt->try_block()); | 723 Visit(stmt->try_block()); |
751 CHECK_BAILOUT; | 724 CHECK_BAILOUT; |
752 Visit(stmt->finally_block()); | 725 Visit(stmt->finally_block()); |
753 } | 726 } |
754 | 727 |
755 | 728 |
756 void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) { | 729 void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {} |
757 // Debugger statement is supported. | |
758 } | |
759 | 730 |
760 | 731 |
761 void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) { | 732 void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {} |
762 // Function literal is supported. | |
763 } | |
764 | 733 |
765 | 734 |
766 void CodeGenSelector::VisitFunctionBoilerplateLiteral( | 735 void CodeGenSelector::VisitFunctionBoilerplateLiteral( |
767 FunctionBoilerplateLiteral* expr) { | 736 FunctionBoilerplateLiteral* expr) { |
768 BAILOUT("FunctionBoilerplateLiteral"); | 737 BAILOUT("FunctionBoilerplateLiteral"); |
769 } | 738 } |
770 | 739 |
771 | 740 |
772 void CodeGenSelector::VisitConditional(Conditional* expr) { | 741 void CodeGenSelector::VisitConditional(Conditional* expr) { |
773 ProcessExpression(expr->condition(), Expression::kTest); | 742 Visit(expr->condition()); |
774 CHECK_BAILOUT; | 743 CHECK_BAILOUT; |
775 ProcessExpression(expr->then_expression(), context_); | 744 Visit(expr->then_expression()); |
776 CHECK_BAILOUT; | 745 CHECK_BAILOUT; |
777 ProcessExpression(expr->else_expression(), context_); | 746 Visit(expr->else_expression()); |
778 } | 747 } |
779 | 748 |
780 | 749 |
781 void CodeGenSelector::VisitSlot(Slot* expr) { | 750 void CodeGenSelector::VisitSlot(Slot* expr) { |
782 UNREACHABLE(); | 751 UNREACHABLE(); |
783 } | 752 } |
784 | 753 |
785 | 754 |
786 void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) { | 755 void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) { |
787 Expression* rewrite = expr->var()->rewrite(); | 756 Variable* var = expr->var(); |
788 // A rewrite of NULL indicates a global variable. | 757 if (!var->is_global()) { |
fschneider
2010/01/19 12:36:10
This is clearer than before and should be fine.
I
| |
789 if (rewrite != NULL) { | 758 Slot* slot = var->slot(); |
790 // Non-global. | |
791 Slot* slot = rewrite->AsSlot(); | |
792 if (slot != NULL) { | 759 if (slot != NULL) { |
793 Slot::Type type = slot->type(); | 760 Slot::Type type = slot->type(); |
794 // When LOOKUP slots are enabled, some currently dead code | 761 // When LOOKUP slots are enabled, some currently dead code |
795 // implementing unary typeof will become live. | 762 // implementing unary typeof will become live. |
796 if (type == Slot::LOOKUP) { | 763 if (type == Slot::LOOKUP) { |
797 BAILOUT("Lookup slot"); | 764 BAILOUT("Lookup slot"); |
798 } | 765 } |
799 } else { | 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. | |
800 #ifdef DEBUG | 769 #ifdef DEBUG |
801 // Only remaining possibility is a property where the object is | 770 Property* property = var->AsProperty(); |
802 // a slotted variable and the key is a smi. | |
803 Property* property = rewrite->AsProperty(); | |
804 ASSERT_NOT_NULL(property); | 771 ASSERT_NOT_NULL(property); |
805 Variable* object = property->obj()->AsVariableProxy()->AsVariable(); | 772 Variable* object = property->obj()->AsVariableProxy()->AsVariable(); |
806 ASSERT_NOT_NULL(object); | 773 ASSERT_NOT_NULL(object); |
807 ASSERT_NOT_NULL(object->slot()); | 774 ASSERT_NOT_NULL(object->slot()); |
808 ASSERT_NOT_NULL(property->key()->AsLiteral()); | 775 ASSERT_NOT_NULL(property->key()->AsLiteral()); |
809 ASSERT(property->key()->AsLiteral()->handle()->IsSmi()); | 776 ASSERT(property->key()->AsLiteral()->handle()->IsSmi()); |
810 #endif | 777 #endif |
811 } | 778 } |
812 } | 779 } |
813 } | 780 } |
814 | 781 |
815 | 782 |
816 void CodeGenSelector::VisitLiteral(Literal* expr) { | 783 void CodeGenSelector::VisitLiteral(Literal* expr) {} |
817 /* Nothing to do. */ | |
818 } | |
819 | 784 |
820 | 785 |
821 void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) { | 786 void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {} |
822 /* Nothing to do. */ | |
823 } | |
824 | 787 |
825 | 788 |
826 void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) { | 789 void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) { |
827 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); | 790 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); |
828 | 791 |
829 for (int i = 0, len = properties->length(); i < len; i++) { | 792 for (int i = 0, len = properties->length(); i < len; i++) { |
830 ObjectLiteral::Property* property = properties->at(i); | 793 ObjectLiteral::Property* property = properties->at(i); |
831 if (property->IsCompileTimeValue()) continue; | 794 if (property->IsCompileTimeValue()) continue; |
832 | 795 Visit(property->key()); |
833 switch (property->kind()) { | 796 CHECK_BAILOUT; |
834 case ObjectLiteral::Property::CONSTANT: | 797 Visit(property->value()); |
835 UNREACHABLE(); | |
836 | |
837 // For (non-compile-time) materialized literals and computed | |
838 // properties with symbolic keys we will use an IC and therefore not | |
839 // generate code for the key. | |
840 case ObjectLiteral::Property::COMPUTED: // Fall through. | |
841 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | |
842 if (property->key()->handle()->IsSymbol()) { | |
843 break; | |
844 } | |
845 // Fall through. | |
846 | |
847 // In all other cases we need the key's value on the stack | |
848 // for a runtime call. (Relies on TEMP meaning STACK.) | |
849 case ObjectLiteral::Property::GETTER: // Fall through. | |
850 case ObjectLiteral::Property::SETTER: // Fall through. | |
851 case ObjectLiteral::Property::PROTOTYPE: | |
852 ProcessExpression(property->key(), Expression::kValue); | |
853 CHECK_BAILOUT; | |
854 break; | |
855 } | |
856 ProcessExpression(property->value(), Expression::kValue); | |
857 CHECK_BAILOUT; | 798 CHECK_BAILOUT; |
858 } | 799 } |
859 } | 800 } |
860 | 801 |
861 | 802 |
862 void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) { | 803 void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) { |
863 ZoneList<Expression*>* subexprs = expr->values(); | 804 ZoneList<Expression*>* subexprs = expr->values(); |
864 for (int i = 0, len = subexprs->length(); i < len; i++) { | 805 for (int i = 0, len = subexprs->length(); i < len; i++) { |
865 Expression* subexpr = subexprs->at(i); | 806 Expression* subexpr = subexprs->at(i); |
866 if (subexpr->AsLiteral() != NULL) continue; | 807 if (subexpr->AsLiteral() != NULL) continue; |
867 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 808 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
868 ProcessExpression(subexpr, Expression::kValue); | 809 Visit(subexpr); |
869 CHECK_BAILOUT; | 810 CHECK_BAILOUT; |
870 } | 811 } |
871 } | 812 } |
872 | 813 |
873 | 814 |
874 void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 815 void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
875 ProcessExpression(expr->key(), Expression::kValue); | 816 Visit(expr->key()); |
876 CHECK_BAILOUT; | 817 CHECK_BAILOUT; |
877 ProcessExpression(expr->value(), Expression::kValue); | 818 Visit(expr->value()); |
878 } | 819 } |
879 | 820 |
880 | 821 |
881 void CodeGenSelector::VisitAssignment(Assignment* expr) { | 822 void CodeGenSelector::VisitAssignment(Assignment* expr) { |
882 // We support plain non-compound assignments to properties, parameters and | 823 // We support plain non-compound assignments to properties, parameters and |
883 // non-context (stack-allocated) locals, and global variables. | 824 // non-context (stack-allocated) locals, and global variables. |
884 Token::Value op = expr->op(); | 825 Token::Value op = expr->op(); |
885 if (op == Token::INIT_CONST) BAILOUT("initialize constant"); | 826 if (op == Token::INIT_CONST) BAILOUT("initialize constant"); |
886 | 827 |
887 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 828 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
888 Property* prop = expr->target()->AsProperty(); | 829 Property* prop = expr->target()->AsProperty(); |
889 ASSERT(var == NULL || prop == NULL); | 830 ASSERT(var == NULL || prop == NULL); |
890 if (var != NULL) { | 831 if (var != NULL) { |
891 if (var->mode() == Variable::CONST) { | 832 if (var->mode() == Variable::CONST) { |
892 BAILOUT("Assignment to const"); | 833 BAILOUT("Assignment to const"); |
893 } | 834 } |
894 // All global variables are supported. | 835 // All global variables are supported. |
895 if (!var->is_global()) { | 836 if (!var->is_global()) { |
896 ASSERT(var->slot() != NULL); | 837 ASSERT(var->slot() != NULL); |
897 Slot::Type type = var->slot()->type(); | 838 Slot::Type type = var->slot()->type(); |
898 if (type == Slot::LOOKUP) { | 839 if (type == Slot::LOOKUP) { |
899 BAILOUT("Lookup slot"); | 840 BAILOUT("Lookup slot"); |
900 } | 841 } |
901 } | 842 } |
902 } else if (prop != NULL) { | 843 } else if (prop != NULL) { |
903 ProcessExpression(prop->obj(), Expression::kValue); | 844 Visit(prop->obj()); |
904 CHECK_BAILOUT; | 845 CHECK_BAILOUT; |
905 // We will only visit the key during code generation for keyed property | 846 Visit(prop->key()); |
906 // stores. Leave its expression context uninitialized for named | 847 CHECK_BAILOUT; |
907 // property stores. | |
908 if (!prop->key()->IsPropertyName()) { | |
909 ProcessExpression(prop->key(), Expression::kValue); | |
910 CHECK_BAILOUT; | |
911 } | |
912 } else { | 848 } else { |
913 // This is a throw reference error. | 849 // This is a throw reference error. |
914 BAILOUT("non-variable/non-property assignment"); | 850 BAILOUT("non-variable/non-property assignment"); |
915 } | 851 } |
916 | 852 |
917 ProcessExpression(expr->value(), Expression::kValue); | 853 Visit(expr->value()); |
918 } | 854 } |
919 | 855 |
920 | 856 |
921 void CodeGenSelector::VisitThrow(Throw* expr) { | 857 void CodeGenSelector::VisitThrow(Throw* expr) { |
922 ProcessExpression(expr->exception(), Expression::kValue); | 858 Visit(expr->exception()); |
923 } | 859 } |
924 | 860 |
925 | 861 |
926 void CodeGenSelector::VisitProperty(Property* expr) { | 862 void CodeGenSelector::VisitProperty(Property* expr) { |
927 ProcessExpression(expr->obj(), Expression::kValue); | 863 Visit(expr->obj()); |
928 CHECK_BAILOUT; | 864 CHECK_BAILOUT; |
929 ProcessExpression(expr->key(), Expression::kValue); | 865 Visit(expr->key()); |
930 } | 866 } |
931 | 867 |
932 | 868 |
933 void CodeGenSelector::VisitCall(Call* expr) { | 869 void CodeGenSelector::VisitCall(Call* expr) { |
934 Expression* fun = expr->expression(); | 870 Expression* fun = expr->expression(); |
935 ZoneList<Expression*>* args = expr->arguments(); | 871 ZoneList<Expression*>* args = expr->arguments(); |
936 Variable* var = fun->AsVariableProxy()->AsVariable(); | 872 Variable* var = fun->AsVariableProxy()->AsVariable(); |
937 | 873 |
938 // Check for supported calls | 874 // Check for supported calls |
939 if (var != NULL && var->is_possibly_eval()) { | 875 if (var != NULL && var->is_possibly_eval()) { |
940 BAILOUT("call to the identifier 'eval'"); | 876 BAILOUT("call to the identifier 'eval'"); |
941 } else if (var != NULL && !var->is_this() && var->is_global()) { | 877 } else if (var != NULL && !var->is_this() && var->is_global()) { |
942 // Calls to global variables are supported. | 878 // Calls to global variables are supported. |
943 } else if (var != NULL && var->slot() != NULL && | 879 } else if (var != NULL && var->slot() != NULL && |
944 var->slot()->type() == Slot::LOOKUP) { | 880 var->slot()->type() == Slot::LOOKUP) { |
945 BAILOUT("call to a lookup slot"); | 881 BAILOUT("call to a lookup slot"); |
946 } else if (fun->AsProperty() != NULL) { | 882 } else if (fun->AsProperty() != NULL) { |
947 Property* prop = fun->AsProperty(); | 883 Property* prop = fun->AsProperty(); |
948 Literal* literal_key = prop->key()->AsLiteral(); | 884 Literal* literal_key = prop->key()->AsLiteral(); |
949 if (literal_key != NULL && literal_key->handle()->IsSymbol()) { | 885 Visit(prop->obj()); |
950 ProcessExpression(prop->obj(), Expression::kValue); | 886 CHECK_BAILOUT; |
951 CHECK_BAILOUT; | 887 Visit(prop->key()); |
952 } else { | 888 CHECK_BAILOUT; |
953 ProcessExpression(prop->obj(), Expression::kValue); | |
954 CHECK_BAILOUT; | |
955 ProcessExpression(prop->key(), Expression::kValue); | |
956 CHECK_BAILOUT; | |
957 } | |
958 } else { | 889 } else { |
959 // Otherwise the call is supported if the function expression is. | 890 // Otherwise the call is supported if the function expression is. |
960 ProcessExpression(fun, Expression::kValue); | 891 Visit(fun); |
961 } | 892 } |
962 // Check all arguments to the call. | 893 // Check all arguments to the call. |
963 for (int i = 0; i < args->length(); i++) { | 894 for (int i = 0; i < args->length(); i++) { |
964 ProcessExpression(args->at(i), Expression::kValue); | 895 Visit(args->at(i)); |
965 CHECK_BAILOUT; | 896 CHECK_BAILOUT; |
966 } | 897 } |
967 } | 898 } |
968 | 899 |
969 | 900 |
970 void CodeGenSelector::VisitCallNew(CallNew* expr) { | 901 void CodeGenSelector::VisitCallNew(CallNew* expr) { |
971 ProcessExpression(expr->expression(), Expression::kValue); | 902 Visit(expr->expression()); |
972 CHECK_BAILOUT; | 903 CHECK_BAILOUT; |
973 ZoneList<Expression*>* args = expr->arguments(); | 904 ZoneList<Expression*>* args = expr->arguments(); |
974 // Check all arguments to the call | 905 // Check all arguments to the call |
975 for (int i = 0; i < args->length(); i++) { | 906 for (int i = 0; i < args->length(); i++) { |
976 ProcessExpression(args->at(i), Expression::kValue); | 907 Visit(args->at(i)); |
977 CHECK_BAILOUT; | 908 CHECK_BAILOUT; |
978 } | 909 } |
979 } | 910 } |
980 | 911 |
981 | 912 |
982 void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) { | 913 void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) { |
983 // Check for inline runtime call | 914 // Check for inline runtime call |
984 if (expr->name()->Get(0) == '_' && | 915 if (expr->name()->Get(0) == '_' && |
985 CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { | 916 CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { |
986 BAILOUT("inlined runtime call"); | 917 BAILOUT("inlined runtime call"); |
987 } | 918 } |
988 // Check all arguments to the call. (Relies on TEMP meaning STACK.) | 919 // Check all arguments to the call. (Relies on TEMP meaning STACK.) |
989 for (int i = 0; i < expr->arguments()->length(); i++) { | 920 for (int i = 0; i < expr->arguments()->length(); i++) { |
990 ProcessExpression(expr->arguments()->at(i), Expression::kValue); | 921 Visit(expr->arguments()->at(i)); |
991 CHECK_BAILOUT; | 922 CHECK_BAILOUT; |
992 } | 923 } |
993 } | 924 } |
994 | 925 |
995 | 926 |
996 void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) { | 927 void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) { |
997 switch (expr->op()) { | 928 switch (expr->op()) { |
998 case Token::VOID: | 929 case Token::VOID: |
999 ProcessExpression(expr->expression(), Expression::kEffect); | 930 case Token::NOT: |
931 case Token::TYPEOF: | |
932 Visit(expr->expression()); | |
1000 break; | 933 break; |
1001 case Token::NOT: | 934 case BIT_NOT: |
1002 ProcessExpression(expr->expression(), Expression::kTest); | 935 BAILOUT("UnaryOperataion: BIT_NOT"); |
1003 break; | 936 case DELETE: |
1004 case Token::TYPEOF: | 937 BAILOUT("UnaryOperataion: DELETE"); |
1005 ProcessExpression(expr->expression(), Expression::kValue); | |
1006 break; | |
1007 default: | 938 default: |
1008 BAILOUT("UnaryOperation"); | 939 UNREACHABLE(); |
1009 } | 940 } |
1010 } | 941 } |
1011 | 942 |
1012 | 943 |
1013 void CodeGenSelector::VisitCountOperation(CountOperation* expr) { | 944 void CodeGenSelector::VisitCountOperation(CountOperation* expr) { |
1014 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 945 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
1015 Property* prop = expr->expression()->AsProperty(); | 946 Property* prop = expr->expression()->AsProperty(); |
1016 ASSERT(var == NULL || prop == NULL); | 947 ASSERT(var == NULL || prop == NULL); |
1017 if (var != NULL) { | 948 if (var != NULL) { |
1018 // All global variables are supported. | 949 // All global variables are supported. |
1019 if (!var->is_global()) { | 950 if (!var->is_global()) { |
1020 ASSERT(var->slot() != NULL); | 951 ASSERT(var->slot() != NULL); |
1021 Slot::Type type = var->slot()->type(); | 952 Slot::Type type = var->slot()->type(); |
1022 if (type == Slot::LOOKUP) { | 953 if (type == Slot::LOOKUP) { |
1023 BAILOUT("CountOperation with lookup slot"); | 954 BAILOUT("CountOperation with lookup slot"); |
1024 } | 955 } |
1025 } | 956 } |
1026 } else if (prop != NULL) { | 957 } else if (prop != NULL) { |
1027 ProcessExpression(prop->obj(), Expression::kValue); | 958 Visit(prop->obj()); |
1028 CHECK_BAILOUT; | 959 CHECK_BAILOUT; |
1029 // We will only visit the key during code generation for keyed property | 960 Visit(prop->key()); |
1030 // stores. Leave its expression context uninitialized for named | 961 CHECK_BAILOUT; |
1031 // property stores. | |
1032 if (!prop->key()->IsPropertyName()) { | |
1033 ProcessExpression(prop->key(), Expression::kValue); | |
1034 CHECK_BAILOUT; | |
1035 } | |
1036 } else { | 962 } else { |
1037 // This is a throw reference error. | 963 // This is a throw reference error. |
1038 BAILOUT("CountOperation non-variable/non-property expression"); | 964 BAILOUT("CountOperation non-variable/non-property expression"); |
1039 } | 965 } |
1040 } | 966 } |
1041 | 967 |
1042 | 968 |
1043 void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) { | 969 void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) { |
1044 switch (expr->op()) { | 970 Visit(expr->left()); |
1045 case Token::COMMA: | 971 CHECK_BAILOUT; |
1046 ProcessExpression(expr->left(), Expression::kEffect); | 972 Visit(expr->right()); |
1047 CHECK_BAILOUT; | |
1048 ProcessExpression(expr->right(), context_); | |
1049 break; | |
1050 | |
1051 case Token::OR: | |
1052 switch (context_) { | |
1053 case Expression::kUninitialized: | |
1054 UNREACHABLE(); | |
1055 case Expression::kEffect: // Fall through. | |
1056 case Expression::kTest: // Fall through. | |
1057 case Expression::kTestValue: | |
1058 // The left subexpression's value is not needed, it is in a pure | |
1059 // test context. | |
1060 ProcessExpression(expr->left(), Expression::kTest); | |
1061 break; | |
1062 case Expression::kValue: // Fall through. | |
1063 case Expression::kValueTest: | |
1064 // The left subexpression's value is needed, it is in a hybrid | |
1065 // value/test context. | |
1066 ProcessExpression(expr->left(), Expression::kValueTest); | |
1067 break; | |
1068 } | |
1069 CHECK_BAILOUT; | |
1070 ProcessExpression(expr->right(), context_); | |
1071 break; | |
1072 | |
1073 case Token::AND: | |
1074 switch (context_) { | |
1075 case Expression::kUninitialized: | |
1076 UNREACHABLE(); | |
1077 case Expression::kEffect: // Fall through. | |
1078 case Expression::kTest: // Fall through. | |
1079 case Expression::kValueTest: | |
1080 // The left subexpression's value is not needed, it is in a pure | |
1081 // test context. | |
1082 ProcessExpression(expr->left(), Expression::kTest); | |
1083 break; | |
1084 case Expression::kValue: // Fall through. | |
1085 case Expression::kTestValue: | |
1086 // The left subexpression's value is needed, it is in a hybrid | |
1087 // test/value context. | |
1088 ProcessExpression(expr->left(), Expression::kTestValue); | |
1089 break; | |
1090 } | |
1091 CHECK_BAILOUT; | |
1092 ProcessExpression(expr->right(), context_); | |
1093 break; | |
1094 | |
1095 case Token::ADD: | |
1096 case Token::SUB: | |
1097 case Token::DIV: | |
1098 case Token::MOD: | |
1099 case Token::MUL: | |
1100 case Token::BIT_OR: | |
1101 case Token::BIT_AND: | |
1102 case Token::BIT_XOR: | |
1103 case Token::SHL: | |
1104 case Token::SHR: | |
1105 case Token::SAR: | |
1106 ProcessExpression(expr->left(), Expression::kValue); | |
1107 CHECK_BAILOUT; | |
1108 ProcessExpression(expr->right(), Expression::kValue); | |
1109 break; | |
1110 | |
1111 default: | |
1112 BAILOUT("Unsupported binary operation"); | |
1113 } | |
1114 } | 973 } |
1115 | 974 |
1116 | 975 |
1117 void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) { | 976 void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) { |
1118 ProcessExpression(expr->left(), Expression::kValue); | 977 Visit(expr->left()); |
1119 CHECK_BAILOUT; | 978 CHECK_BAILOUT; |
1120 ProcessExpression(expr->right(), Expression::kValue); | 979 Visit(expr->right()); |
1121 } | 980 } |
1122 | 981 |
1123 | 982 |
1124 void CodeGenSelector::VisitThisFunction(ThisFunction* expr) { | 983 void CodeGenSelector::VisitThisFunction(ThisFunction* expr) {} |
1125 // ThisFunction is supported. | |
1126 } | |
1127 | 984 |
1128 #undef BAILOUT | 985 #undef BAILOUT |
1129 #undef CHECK_BAILOUT | 986 #undef CHECK_BAILOUT |
1130 | 987 |
1131 | 988 |
1132 } } // namespace v8::internal | 989 } } // namespace v8::internal |
OLD | NEW |