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() : has_supported_syntax_(true) {} | 49 CodeGenSelector() |
50 : has_supported_syntax_(true), | |
51 location_(Location::Nowhere()) { | |
fschneider
2009/10/28 10:06:01
I'm not sure: Should this match the default locati
Kevin Millikin (Chromium)
2009/10/28 11:39:38
Possibly. I wanted it to be nowhere when not insi
| |
52 } | |
50 | 53 |
51 CodeGenTag Select(FunctionLiteral* fun); | 54 CodeGenTag Select(FunctionLiteral* fun); |
52 | 55 |
53 private: | 56 private: |
54 void VisitDeclarations(ZoneList<Declaration*>* decls); | 57 void VisitDeclarations(ZoneList<Declaration*>* decls); |
55 void VisitStatements(ZoneList<Statement*>* stmts); | 58 void VisitStatements(ZoneList<Statement*>* stmts); |
56 | 59 |
60 // Visit an expression in effect context with a desired location of | |
61 // nowhere. | |
62 void VisitAsEffect(Expression* expr); | |
63 | |
64 // Visit an expression in value context with a desired location of | |
65 // temporary. | |
66 void VisitAsValue(Expression* expr); | |
67 | |
57 // AST node visit functions. | 68 // AST node visit functions. |
58 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); | 69 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); |
59 AST_NODE_LIST(DECLARE_VISIT) | 70 AST_NODE_LIST(DECLARE_VISIT) |
60 #undef DECLARE_VISIT | 71 #undef DECLARE_VISIT |
61 | 72 |
62 bool has_supported_syntax_; | 73 bool has_supported_syntax_; |
63 | 74 |
75 // The desired location of the currently visited expression. | |
76 Location location_; | |
77 | |
64 DISALLOW_COPY_AND_ASSIGN(CodeGenSelector); | 78 DISALLOW_COPY_AND_ASSIGN(CodeGenSelector); |
65 }; | 79 }; |
66 | 80 |
67 | 81 |
68 static Handle<Code> MakeCode(FunctionLiteral* literal, | 82 static Handle<Code> MakeCode(FunctionLiteral* literal, |
69 Handle<Script> script, | 83 Handle<Script> script, |
70 Handle<Context> context, | 84 Handle<Context> context, |
71 bool is_eval) { | 85 bool is_eval) { |
72 ASSERT(literal != NULL); | 86 ASSERT(literal != NULL); |
73 | 87 |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
492 | 506 |
493 | 507 |
494 void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) { | 508 void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) { |
495 for (int i = 0, len = stmts->length(); i < len; i++) { | 509 for (int i = 0, len = stmts->length(); i < len; i++) { |
496 Visit(stmts->at(i)); | 510 Visit(stmts->at(i)); |
497 CHECK_BAILOUT; | 511 CHECK_BAILOUT; |
498 } | 512 } |
499 } | 513 } |
500 | 514 |
501 | 515 |
516 void CodeGenSelector::VisitAsEffect(Expression* expr) { | |
517 if (location_.is_nowhere()) { | |
518 Visit(expr); | |
519 } else { | |
520 Location saved = location_; | |
521 location_ = Location::Nowhere(); | |
522 Visit(expr); | |
523 location_ = saved; | |
524 } | |
525 } | |
526 | |
527 | |
528 void CodeGenSelector::VisitAsValue(Expression* expr) { | |
529 if (location_.is_temporary()) { | |
530 Visit(expr); | |
531 } else { | |
532 Location saved = location_; | |
533 location_ = Location::Temporary(); | |
534 Visit(expr); | |
535 location_ = saved; | |
536 } | |
537 } | |
538 | |
539 | |
502 void CodeGenSelector::VisitDeclaration(Declaration* decl) { | 540 void CodeGenSelector::VisitDeclaration(Declaration* decl) { |
503 Variable* var = decl->proxy()->var(); | 541 Variable* var = decl->proxy()->var(); |
504 if (!var->is_global() || var->mode() == Variable::CONST) { | 542 if (!var->is_global() || var->mode() == Variable::CONST) { |
505 BAILOUT("Non-global declaration"); | 543 BAILOUT("Non-global declaration"); |
506 } | 544 } |
507 } | 545 } |
508 | 546 |
509 | 547 |
510 void CodeGenSelector::VisitBlock(Block* stmt) { | 548 void CodeGenSelector::VisitBlock(Block* stmt) { |
511 VisitStatements(stmt->statements()); | 549 VisitStatements(stmt->statements()); |
512 } | 550 } |
513 | 551 |
514 | 552 |
515 void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) { | 553 void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) { |
516 Expression* expr = stmt->expression(); | 554 VisitAsEffect(stmt->expression()); |
517 Visit(expr); | |
518 CHECK_BAILOUT; | |
519 expr->set_location(Location::Nowhere()); | |
520 } | 555 } |
521 | 556 |
522 | 557 |
523 void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) { | 558 void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) { |
524 // EmptyStatement is supported. | 559 // EmptyStatement is supported. |
525 } | 560 } |
526 | 561 |
527 | 562 |
528 void CodeGenSelector::VisitIfStatement(IfStatement* stmt) { | 563 void CodeGenSelector::VisitIfStatement(IfStatement* stmt) { |
529 BAILOUT("IfStatement"); | 564 BAILOUT("IfStatement"); |
530 } | 565 } |
531 | 566 |
532 | 567 |
533 void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) { | 568 void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) { |
534 BAILOUT("ContinueStatement"); | 569 BAILOUT("ContinueStatement"); |
535 } | 570 } |
536 | 571 |
537 | 572 |
538 void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) { | 573 void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) { |
539 BAILOUT("BreakStatement"); | 574 BAILOUT("BreakStatement"); |
540 } | 575 } |
541 | 576 |
542 | 577 |
543 void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) { | 578 void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) { |
544 Visit(stmt->expression()); | 579 VisitAsValue(stmt->expression()); |
545 } | 580 } |
546 | 581 |
547 | 582 |
548 void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) { | 583 void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) { |
549 BAILOUT("WithEnterStatement"); | 584 BAILOUT("WithEnterStatement"); |
550 } | 585 } |
551 | 586 |
552 | 587 |
553 void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) { | 588 void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) { |
554 BAILOUT("WithExitStatement"); | 589 BAILOUT("WithExitStatement"); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
592 | 627 |
593 void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) { | 628 void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) { |
594 BAILOUT("DebuggerStatement"); | 629 BAILOUT("DebuggerStatement"); |
595 } | 630 } |
596 | 631 |
597 | 632 |
598 void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) { | 633 void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) { |
599 if (!expr->AllowsLazyCompilation()) { | 634 if (!expr->AllowsLazyCompilation()) { |
600 BAILOUT("FunctionLiteral does not allow lazy compilation"); | 635 BAILOUT("FunctionLiteral does not allow lazy compilation"); |
601 } | 636 } |
637 expr->set_location(location_); | |
602 } | 638 } |
603 | 639 |
604 | 640 |
605 void CodeGenSelector::VisitFunctionBoilerplateLiteral( | 641 void CodeGenSelector::VisitFunctionBoilerplateLiteral( |
606 FunctionBoilerplateLiteral* expr) { | 642 FunctionBoilerplateLiteral* expr) { |
607 BAILOUT("FunctionBoilerplateLiteral"); | 643 BAILOUT("FunctionBoilerplateLiteral"); |
608 } | 644 } |
609 | 645 |
610 | 646 |
611 void CodeGenSelector::VisitConditional(Conditional* expr) { | 647 void CodeGenSelector::VisitConditional(Conditional* expr) { |
612 BAILOUT("Conditional"); | 648 BAILOUT("Conditional"); |
613 } | 649 } |
614 | 650 |
615 | 651 |
616 void CodeGenSelector::VisitSlot(Slot* expr) { | 652 void CodeGenSelector::VisitSlot(Slot* expr) { |
617 Slot::Type type = expr->type(); | 653 UNREACHABLE(); |
618 if (type != Slot::PARAMETER && type != Slot::LOCAL) { | |
619 BAILOUT("non-parameter/non-local slot reference"); | |
620 } | |
621 } | 654 } |
622 | 655 |
623 | 656 |
624 void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) { | 657 void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) { |
625 Expression* rewrite = expr->var()->rewrite(); | 658 Expression* rewrite = expr->var()->rewrite(); |
626 if (rewrite != NULL) Visit(rewrite); | 659 // A rewrite of NULL indicates a global variable. |
660 if (rewrite != NULL) { | |
661 Slot* slot = rewrite->AsSlot(); | |
662 if (slot != NULL) { | |
663 Slot::Type type = slot->type(); | |
664 if (type != Slot::PARAMETER && type != Slot::LOCAL) { | |
665 BAILOUT("non-parameter/non-local slot reference"); | |
666 } | |
William Hesse
2009/10/28 10:28:54
Control flow is tricky here. Reversing sense of s
Kevin Millikin (Chromium)
2009/10/28 11:39:38
I see what you mean. I've changed it.
| |
667 } else { | |
668 BAILOUT("non-global/non-slot variable reference"); | |
669 } | |
670 } | |
671 expr->set_location(location_); | |
627 } | 672 } |
628 | 673 |
629 | 674 |
630 void CodeGenSelector::VisitLiteral(Literal* expr) { | 675 void CodeGenSelector::VisitLiteral(Literal* expr) { |
631 // Literals are supported. | 676 expr->set_location(location_); |
632 } | 677 } |
633 | 678 |
634 | 679 |
635 void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) { | 680 void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) { |
636 // RegexpLiterals are supported. | 681 expr->set_location(location_); |
637 } | 682 } |
638 | 683 |
639 | 684 |
640 void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) { | 685 void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) { |
641 for (int i = 0; i < expr->properties()->length(); i++) { | 686 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); |
642 ObjectLiteral::Property* property = expr->properties()->at(i); | 687 |
643 Visit(property->key()); | 688 for (int i = 0, len = properties->length(); i < len; i++) { |
644 CHECK_BAILOUT; | 689 ObjectLiteral::Property* property = properties->at(i); |
645 Visit(property->value()); | 690 if (property->IsCompileTimeValue()) continue; |
691 | |
692 switch (property->kind()) { | |
693 case ObjectLiteral::Property::CONSTANT: | |
694 UNREACHABLE(); | |
695 | |
696 // For (non-compile-time) materialized literals and computed | |
697 // properties with symbolic keys we will use an IC and therefore not | |
698 // generate code for the key. | |
699 case ObjectLiteral::Property::COMPUTED: // Fall through. | |
700 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | |
701 if (property->key()->handle()->IsSymbol()) { | |
702 break; | |
703 } | |
704 // Fall through. | |
705 | |
706 // In all other cases we need the key's value on the stack | |
707 // for a runtime call. (Relies on TEMP meaning STACK.) | |
708 case ObjectLiteral::Property::GETTER: // Fall through. | |
709 case ObjectLiteral::Property::SETTER: // Fall through. | |
710 case ObjectLiteral::Property::PROTOTYPE: | |
711 VisitAsValue(property->key()); | |
712 CHECK_BAILOUT; | |
713 break; | |
714 } | |
715 VisitAsValue(property->value()); | |
646 CHECK_BAILOUT; | 716 CHECK_BAILOUT; |
647 } | 717 } |
718 expr->set_location(location_); | |
648 } | 719 } |
649 | 720 |
650 | 721 |
651 void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) { | 722 void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) { |
652 ZoneList<Expression*>* subexprs = expr->values(); | 723 ZoneList<Expression*>* subexprs = expr->values(); |
653 for (int i = 0, len = subexprs->length(); i < len; i++) { | 724 for (int i = 0, len = subexprs->length(); i < len; i++) { |
654 Expression* subexpr = subexprs->at(i); | 725 Expression* subexpr = subexprs->at(i); |
655 if (subexpr->AsLiteral() != NULL) continue; | 726 if (subexpr->AsLiteral() != NULL) continue; |
656 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 727 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
657 Visit(subexpr); | 728 VisitAsValue(subexpr); |
658 CHECK_BAILOUT; | 729 CHECK_BAILOUT; |
659 } | 730 } |
731 expr->set_location(location_); | |
660 } | 732 } |
661 | 733 |
662 | 734 |
663 void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 735 void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
664 BAILOUT("CatchExtensionObject"); | 736 BAILOUT("CatchExtensionObject"); |
665 } | 737 } |
666 | 738 |
667 | 739 |
668 void CodeGenSelector::VisitAssignment(Assignment* expr) { | 740 void CodeGenSelector::VisitAssignment(Assignment* expr) { |
669 // We support plain non-compound assignments to parameters and | 741 // We support plain non-compound assignments to parameters and |
670 // non-context (stack-allocated) locals. | 742 // non-context (stack-allocated) locals. |
671 if (expr->starts_initialization_block()) BAILOUT("initialization block"); | 743 if (expr->starts_initialization_block() || |
744 expr->ends_initialization_block()) { | |
745 BAILOUT("initialization block start"); | |
746 } | |
672 | 747 |
673 Token::Value op = expr->op(); | 748 Token::Value op = expr->op(); |
674 if (op == Token::INIT_CONST) BAILOUT("initialize constant"); | 749 if (op == Token::INIT_CONST) BAILOUT("initialize constant"); |
675 if (op != Token::ASSIGN && op != Token::INIT_VAR) { | 750 if (op != Token::ASSIGN && op != Token::INIT_VAR) { |
676 BAILOUT("compound assignment"); | 751 BAILOUT("compound assignment"); |
677 } | 752 } |
678 | 753 |
679 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 754 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
680 if (var == NULL) BAILOUT("non-variable assignment"); | 755 if (var == NULL) BAILOUT("non-variable assignment"); |
681 | 756 |
682 if (!var->is_global()) { | 757 if (!var->is_global()) { |
683 ASSERT(var->slot() != NULL); | 758 ASSERT(var->slot() != NULL); |
684 Slot::Type type = var->slot()->type(); | 759 Slot::Type type = var->slot()->type(); |
685 if (type != Slot::PARAMETER && type != Slot::LOCAL) { | 760 if (type != Slot::PARAMETER && type != Slot::LOCAL) { |
686 BAILOUT("non-parameter/non-local slot assignment"); | 761 BAILOUT("non-parameter/non-local slot assignment"); |
687 } | 762 } |
688 } | 763 } |
689 | 764 |
690 Visit(expr->value()); | 765 VisitAsValue(expr->value()); |
766 expr->set_location(location_); | |
691 } | 767 } |
692 | 768 |
693 | 769 |
694 void CodeGenSelector::VisitThrow(Throw* expr) { | 770 void CodeGenSelector::VisitThrow(Throw* expr) { |
695 BAILOUT("Throw"); | 771 BAILOUT("Throw"); |
696 } | 772 } |
697 | 773 |
698 | 774 |
699 void CodeGenSelector::VisitProperty(Property* expr) { | 775 void CodeGenSelector::VisitProperty(Property* expr) { |
700 Visit(expr->obj()); | 776 Visit(expr->obj()); |
701 CHECK_BAILOUT; | 777 CHECK_BAILOUT; |
702 Visit(expr->key()); | 778 Visit(expr->key()); |
fschneider
2009/10/28 10:06:01
Also set location here:
expr->set_location(locati
Kevin Millikin (Chromium)
2009/10/28 11:39:38
You're right. Svn update can't rewrite these :)
| |
703 } | 779 } |
704 | 780 |
705 | 781 |
706 void CodeGenSelector::VisitCall(Call* expr) { | 782 void CodeGenSelector::VisitCall(Call* expr) { |
707 Expression* fun = expr->expression(); | 783 Expression* fun = expr->expression(); |
708 ZoneList<Expression*>* args = expr->arguments(); | 784 ZoneList<Expression*>* args = expr->arguments(); |
709 Variable* var = fun->AsVariableProxy()->AsVariable(); | 785 Variable* var = fun->AsVariableProxy()->AsVariable(); |
710 | 786 |
711 // Check for supported calls | 787 // Check for supported calls |
712 if (var != NULL && var->is_possibly_eval()) { | 788 if (var != NULL && var->is_possibly_eval()) { |
713 BAILOUT("Call to a function named 'eval'"); | 789 BAILOUT("Call to a function named 'eval'"); |
714 } else if (var != NULL && !var->is_this() && var->is_global()) { | 790 } else if (var != NULL && !var->is_this() && var->is_global()) { |
715 // ---------------------------------- | 791 // ---------------------------------- |
716 // JavaScript example: 'foo(1, 2, 3)' // foo is global | 792 // JavaScript example: 'foo(1, 2, 3)' // foo is global |
717 // ---------------------------------- | 793 // ---------------------------------- |
718 } else { | 794 } else { |
719 BAILOUT("Call to a non-global function"); | 795 BAILOUT("Call to a non-global function"); |
720 } | 796 } |
721 // Check all arguments to the call | 797 // Check all arguments to the call. (Relies on TEMP meaning STACK.) |
722 for (int i = 0; i < args->length(); i++) { | 798 for (int i = 0; i < args->length(); i++) { |
723 Visit(args->at(i)); | 799 VisitAsValue(args->at(i)); |
724 CHECK_BAILOUT; | 800 CHECK_BAILOUT; |
725 } | 801 } |
802 expr->set_location(location_); | |
726 } | 803 } |
727 | 804 |
728 | 805 |
729 void CodeGenSelector::VisitCallNew(CallNew* expr) { | 806 void CodeGenSelector::VisitCallNew(CallNew* expr) { |
730 Visit(expr->expression()); | 807 Visit(expr->expression()); |
731 CHECK_BAILOUT; | 808 CHECK_BAILOUT; |
732 ZoneList<Expression*>* args = expr->arguments(); | 809 ZoneList<Expression*>* args = expr->arguments(); |
733 // Check all arguments to the call | 810 // Check all arguments to the call |
734 for (int i = 0; i < args->length(); i++) { | 811 for (int i = 0; i < args->length(); i++) { |
735 Visit(args->at(i)); | 812 Visit(args->at(i)); |
736 CHECK_BAILOUT; | 813 CHECK_BAILOUT; |
737 } | 814 } |
fschneider
2009/10/28 10:06:01
Also set location here: expr->set_location(locatio
| |
738 } | 815 } |
739 | 816 |
740 | 817 |
741 void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) { | 818 void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) { |
742 // In case of JS runtime function bail out. | 819 // In case of JS runtime function bail out. |
743 if (expr->function() == NULL) BAILOUT("CallRuntime"); | 820 if (expr->function() == NULL) BAILOUT("call JS runtime function"); |
744 // Check for inline runtime call | 821 // Check for inline runtime call |
745 if (expr->name()->Get(0) == '_' && | 822 if (expr->name()->Get(0) == '_' && |
746 CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { | 823 CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { |
747 BAILOUT("InlineRuntimeCall"); | 824 BAILOUT("inlined runtime call"); |
748 } | 825 } |
826 // Check all arguments to the call. (Relies on TEMP meaning STACK.) | |
749 for (int i = 0; i < expr->arguments()->length(); i++) { | 827 for (int i = 0; i < expr->arguments()->length(); i++) { |
750 Visit(expr->arguments()->at(i)); | 828 VisitAsValue(expr->arguments()->at(i)); |
751 CHECK_BAILOUT; | 829 CHECK_BAILOUT; |
752 } | 830 } |
831 expr->set_location(location_); | |
753 } | 832 } |
754 | 833 |
755 | 834 |
756 void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) { | 835 void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) { |
757 BAILOUT("UnaryOperation"); | 836 BAILOUT("UnaryOperation"); |
758 } | 837 } |
759 | 838 |
760 | 839 |
761 void CodeGenSelector::VisitCountOperation(CountOperation* expr) { | 840 void CodeGenSelector::VisitCountOperation(CountOperation* expr) { |
762 BAILOUT("CountOperation"); | 841 BAILOUT("CountOperation"); |
763 } | 842 } |
764 | 843 |
765 | 844 |
766 void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) { | 845 void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) { |
767 switch (expr->op()) { | 846 switch (expr->op()) { |
768 case Token::OR: | 847 case Token::OR: |
769 Visit(expr->left()); | 848 VisitAsValue(expr->left()); |
770 CHECK_BAILOUT; | 849 CHECK_BAILOUT; |
850 // The location for the right subexpression is the same as for the | |
851 // whole expression. | |
771 Visit(expr->right()); | 852 Visit(expr->right()); |
772 break; | 853 break; |
773 | 854 |
774 default: | 855 default: |
775 BAILOUT("Unsupported binary operation"); | 856 BAILOUT("Unsupported binary operation"); |
776 } | 857 } |
858 expr->set_location(location_); | |
777 } | 859 } |
778 | 860 |
779 | 861 |
780 void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) { | 862 void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) { |
781 BAILOUT("CompareOperation"); | 863 BAILOUT("CompareOperation"); |
782 } | 864 } |
783 | 865 |
784 | 866 |
785 void CodeGenSelector::VisitThisFunction(ThisFunction* expr) { | 867 void CodeGenSelector::VisitThisFunction(ThisFunction* expr) { |
786 BAILOUT("ThisFunction"); | 868 BAILOUT("ThisFunction"); |
787 } | 869 } |
788 | 870 |
789 #undef BAILOUT | 871 #undef BAILOUT |
790 #undef CHECK_BAILOUT | 872 #undef CHECK_BAILOUT |
791 | 873 |
792 | 874 |
793 } } // namespace v8::internal | 875 } } // namespace v8::internal |
OLD | NEW |