Chromium Code Reviews| 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 |