OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 | 131 |
132 return instr; | 132 return instr; |
133 } | 133 } |
134 | 134 |
135 | 135 |
136 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, | 136 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, |
137 RemovableSimulate removable) { | 137 RemovableSimulate removable) { |
138 ASSERT(HasEnvironment()); | 138 ASSERT(HasEnvironment()); |
139 HEnvironment* environment = last_environment(); | 139 HEnvironment* environment = last_environment(); |
140 ASSERT(ast_id.IsNone() || | 140 ASSERT(ast_id.IsNone() || |
141 ast_id == BailoutId::StubEntry() || | |
142 environment->closure()->shared()->VerifyBailoutId(ast_id)); | 141 environment->closure()->shared()->VerifyBailoutId(ast_id)); |
143 | 142 |
144 int push_count = environment->push_count(); | 143 int push_count = environment->push_count(); |
145 int pop_count = environment->pop_count(); | 144 int pop_count = environment->pop_count(); |
146 | 145 |
147 HSimulate* instr = | 146 HSimulate* instr = |
148 new(zone()) HSimulate(ast_id, pop_count, zone(), removable); | 147 new(zone()) HSimulate(ast_id, pop_count, zone(), removable); |
149 // Order of pushed values: newest (top of stack) first. This allows | 148 // Order of pushed values: newest (top of stack) first. This allows |
150 // HSimulate::MergeInto() to easily append additional pushed values | 149 // HSimulate::MergeInto() to easily append additional pushed values |
151 // that are older (from further down the stack). | 150 // that are older (from further down the stack). |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 HConstant* HGraph::GetConstantFalse() { | 614 HConstant* HGraph::GetConstantFalse() { |
616 return GetConstant(&constant_false_, isolate()->factory()->false_value()); | 615 return GetConstant(&constant_false_, isolate()->factory()->false_value()); |
617 } | 616 } |
618 | 617 |
619 | 618 |
620 HConstant* HGraph::GetConstantHole() { | 619 HConstant* HGraph::GetConstantHole() { |
621 return GetConstant(&constant_hole_, isolate()->factory()->the_hole_value()); | 620 return GetConstant(&constant_hole_, isolate()->factory()->the_hole_value()); |
622 } | 621 } |
623 | 622 |
624 | 623 |
625 HGraph* HGraphBuilder::CreateGraph() { | 624 HGraphBuilder::HGraphBuilder(CompilationInfo* info, |
626 graph_ = new(zone()) HGraph(info_); | 625 TypeFeedbackOracle* oracle) |
627 if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info_); | 626 : function_state_(NULL), |
628 HPhase phase("H_Block building"); | |
629 set_current_block(graph()->entry_block()); | |
630 if (!BuildGraph()) return NULL; | |
631 return graph_; | |
632 } | |
633 | |
634 | |
635 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | |
636 ASSERT(current_block() != NULL); | |
637 current_block()->AddInstruction(instr); | |
638 return instr; | |
639 } | |
640 | |
641 | |
642 void HGraphBuilder::AddSimulate(BailoutId id, | |
643 RemovableSimulate removable) { | |
644 ASSERT(current_block() != NULL); | |
645 current_block()->AddSimulate(id, removable); | |
646 } | |
647 | |
648 | |
649 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( | |
650 HValue* external_elements, | |
651 HValue* checked_key, | |
652 HValue* val, | |
653 HValue* dependency, | |
654 ElementsKind elements_kind, | |
655 bool is_store) { | |
656 Zone* zone = this->zone(); | |
657 if (is_store) { | |
658 ASSERT(val != NULL); | |
659 switch (elements_kind) { | |
660 case EXTERNAL_PIXEL_ELEMENTS: { | |
661 val = AddInstruction(new(zone) HClampToUint8(val)); | |
662 break; | |
663 } | |
664 case EXTERNAL_BYTE_ELEMENTS: | |
665 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
666 case EXTERNAL_SHORT_ELEMENTS: | |
667 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
668 case EXTERNAL_INT_ELEMENTS: | |
669 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | |
670 break; | |
671 } | |
672 case EXTERNAL_FLOAT_ELEMENTS: | |
673 case EXTERNAL_DOUBLE_ELEMENTS: | |
674 break; | |
675 case FAST_SMI_ELEMENTS: | |
676 case FAST_ELEMENTS: | |
677 case FAST_DOUBLE_ELEMENTS: | |
678 case FAST_HOLEY_SMI_ELEMENTS: | |
679 case FAST_HOLEY_ELEMENTS: | |
680 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
681 case DICTIONARY_ELEMENTS: | |
682 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
683 UNREACHABLE(); | |
684 break; | |
685 } | |
686 return new(zone) HStoreKeyed(external_elements, checked_key, | |
687 val, elements_kind); | |
688 } else { | |
689 ASSERT(val == NULL); | |
690 HLoadKeyed* load = | |
691 new(zone) HLoadKeyed( | |
692 external_elements, checked_key, dependency, elements_kind); | |
693 if (FLAG_opt_safe_uint32_operations && | |
694 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | |
695 graph()->RecordUint32Instruction(load); | |
696 } | |
697 return load; | |
698 } | |
699 } | |
700 | |
701 | |
702 HInstruction* HGraphBuilder::BuildFastElementAccess( | |
703 HValue* elements, | |
704 HValue* checked_key, | |
705 HValue* val, | |
706 HValue* load_dependency, | |
707 ElementsKind elements_kind, | |
708 bool is_store) { | |
709 Zone* zone = this->zone(); | |
710 if (is_store) { | |
711 ASSERT(val != NULL); | |
712 switch (elements_kind) { | |
713 case FAST_SMI_ELEMENTS: | |
714 case FAST_HOLEY_SMI_ELEMENTS: | |
715 // Smi-only arrays need a smi check. | |
716 AddInstruction(new(zone) HCheckSmi(val)); | |
717 // Fall through. | |
718 case FAST_ELEMENTS: | |
719 case FAST_HOLEY_ELEMENTS: | |
720 case FAST_DOUBLE_ELEMENTS: | |
721 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
722 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); | |
723 default: | |
724 UNREACHABLE(); | |
725 return NULL; | |
726 } | |
727 } | |
728 // It's an element load (!is_store). | |
729 return new(zone) HLoadKeyed(elements, | |
730 checked_key, | |
731 load_dependency, | |
732 elements_kind); | |
733 } | |
734 | |
735 | |
736 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | |
737 HValue* object, | |
738 HValue* key, | |
739 HValue* val, | |
740 HCheckMaps* mapcheck, | |
741 bool is_js_array, | |
742 ElementsKind elements_kind, | |
743 bool is_store) { | |
744 Zone* zone = this->zone(); | |
745 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | |
746 // on a HElementsTransition instruction. The flag can also be removed if the | |
747 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | |
748 // ElementsKind transitions. Finally, the dependency can be removed for stores | |
749 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | |
750 // generated store code. | |
751 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | |
752 (elements_kind == FAST_ELEMENTS && is_store)) { | |
753 if (mapcheck != NULL) { | |
754 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | |
755 } | |
756 } | |
757 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | |
758 bool fast_elements = IsFastObjectElementsKind(elements_kind); | |
759 HInstruction* elements = | |
760 AddInstruction(new(zone) HLoadElements(object, mapcheck)); | |
761 if (is_store && (fast_elements || fast_smi_only_elements)) { | |
762 HCheckMaps* check_cow_map = new(zone) HCheckMaps( | |
763 elements, Isolate::Current()->factory()->fixed_array_map(), zone); | |
764 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | |
765 AddInstruction(check_cow_map); | |
766 } | |
767 HInstruction* length = NULL; | |
768 HInstruction* checked_key = NULL; | |
769 if (IsExternalArrayElementsKind(elements_kind)) { | |
770 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | |
771 checked_key = AddInstruction(new(zone) HBoundsCheck(key, length, | |
772 ALLOW_SMI_KEY)); | |
773 HLoadExternalArrayPointer* external_elements = | |
774 new(zone) HLoadExternalArrayPointer(elements); | |
775 AddInstruction(external_elements); | |
776 return BuildExternalArrayElementAccess( | |
777 external_elements, checked_key, val, mapcheck, | |
778 elements_kind, is_store); | |
779 } | |
780 ASSERT(fast_smi_only_elements || | |
781 fast_elements || | |
782 IsFastDoubleElementsKind(elements_kind)); | |
783 if (is_js_array) { | |
784 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, | |
785 HType::Smi())); | |
786 } else { | |
787 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | |
788 } | |
789 checked_key = AddInstruction(new(zone) HBoundsCheck(key, length, | |
790 ALLOW_SMI_KEY)); | |
791 return BuildFastElementAccess(elements, checked_key, val, mapcheck, | |
792 elements_kind, is_store); | |
793 } | |
794 | |
795 | |
796 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | |
797 TypeFeedbackOracle* oracle) | |
798 : HGraphBuilder(info), | |
799 function_state_(NULL), | |
800 initial_function_state_(this, info, oracle, NORMAL_RETURN), | 627 initial_function_state_(this, info, oracle, NORMAL_RETURN), |
801 ast_context_(NULL), | 628 ast_context_(NULL), |
802 break_scope_(NULL), | 629 break_scope_(NULL), |
| 630 graph_(NULL), |
| 631 current_block_(NULL), |
803 inlined_count_(0), | 632 inlined_count_(0), |
804 globals_(10, info->zone()), | 633 globals_(10, info->zone()), |
| 634 zone_(info->zone()), |
805 inline_bailout_(false) { | 635 inline_bailout_(false) { |
806 // This is not initialized in the initializer list because the | 636 // This is not initialized in the initializer list because the |
807 // constructor for the initial state relies on function_state_ == NULL | 637 // constructor for the initial state relies on function_state_ == NULL |
808 // to know it's the initial state. | 638 // to know it's the initial state. |
809 function_state_= &initial_function_state_; | 639 function_state_= &initial_function_state_; |
810 InitializeAstVisitor(); | |
811 } | 640 } |
812 | 641 |
813 | 642 HBasicBlock* HGraphBuilder::CreateJoin(HBasicBlock* first, |
814 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, | 643 HBasicBlock* second, |
815 HBasicBlock* second, | 644 BailoutId join_id) { |
816 BailoutId join_id) { | |
817 if (first == NULL) { | 645 if (first == NULL) { |
818 return second; | 646 return second; |
819 } else if (second == NULL) { | 647 } else if (second == NULL) { |
820 return first; | 648 return first; |
821 } else { | 649 } else { |
822 HBasicBlock* join_block = graph()->CreateBasicBlock(); | 650 HBasicBlock* join_block = graph_->CreateBasicBlock(); |
823 first->Goto(join_block); | 651 first->Goto(join_block); |
824 second->Goto(join_block); | 652 second->Goto(join_block); |
825 join_block->SetJoinId(join_id); | 653 join_block->SetJoinId(join_id); |
826 return join_block; | 654 return join_block; |
827 } | 655 } |
828 } | 656 } |
829 | 657 |
830 | 658 |
831 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement, | 659 HBasicBlock* HGraphBuilder::JoinContinue(IterationStatement* statement, |
832 HBasicBlock* exit_block, | 660 HBasicBlock* exit_block, |
833 HBasicBlock* continue_block) { | 661 HBasicBlock* continue_block) { |
834 if (continue_block != NULL) { | 662 if (continue_block != NULL) { |
835 if (exit_block != NULL) exit_block->Goto(continue_block); | 663 if (exit_block != NULL) exit_block->Goto(continue_block); |
836 continue_block->SetJoinId(statement->ContinueId()); | 664 continue_block->SetJoinId(statement->ContinueId()); |
837 return continue_block; | 665 return continue_block; |
838 } | 666 } |
839 return exit_block; | 667 return exit_block; |
840 } | 668 } |
841 | 669 |
842 | 670 |
843 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement, | 671 HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement, |
844 HBasicBlock* loop_entry, | 672 HBasicBlock* loop_entry, |
845 HBasicBlock* body_exit, | 673 HBasicBlock* body_exit, |
846 HBasicBlock* loop_successor, | 674 HBasicBlock* loop_successor, |
847 HBasicBlock* break_block) { | 675 HBasicBlock* break_block) { |
848 if (body_exit != NULL) body_exit->Goto(loop_entry); | 676 if (body_exit != NULL) body_exit->Goto(loop_entry); |
849 loop_entry->PostProcessLoopHeader(statement); | 677 loop_entry->PostProcessLoopHeader(statement); |
850 if (break_block != NULL) { | 678 if (break_block != NULL) { |
851 if (loop_successor != NULL) loop_successor->Goto(break_block); | 679 if (loop_successor != NULL) loop_successor->Goto(break_block); |
852 break_block->SetJoinId(statement->ExitId()); | 680 break_block->SetJoinId(statement->ExitId()); |
853 return break_block; | 681 return break_block; |
854 } | 682 } |
855 return loop_successor; | 683 return loop_successor; |
856 } | 684 } |
857 | 685 |
(...skipping 10 matching lines...) Expand all Loading... |
868 entry_block_(NULL), | 696 entry_block_(NULL), |
869 blocks_(8, info->zone()), | 697 blocks_(8, info->zone()), |
870 values_(16, info->zone()), | 698 values_(16, info->zone()), |
871 phi_list_(NULL), | 699 phi_list_(NULL), |
872 uint32_instructions_(NULL), | 700 uint32_instructions_(NULL), |
873 info_(info), | 701 info_(info), |
874 zone_(info->zone()), | 702 zone_(info->zone()), |
875 is_recursive_(false), | 703 is_recursive_(false), |
876 use_optimistic_licm_(false), | 704 use_optimistic_licm_(false), |
877 type_change_checksum_(0) { | 705 type_change_checksum_(0) { |
878 if (info->IsStub()) { | 706 start_environment_ = |
879 start_environment_ = | 707 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); |
880 new(zone_) HEnvironment(zone_); | |
881 } else { | |
882 start_environment_ = | |
883 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); | |
884 } | |
885 start_environment_->set_ast_id(BailoutId::FunctionEntry()); | 708 start_environment_->set_ast_id(BailoutId::FunctionEntry()); |
886 entry_block_ = CreateBasicBlock(); | 709 entry_block_ = CreateBasicBlock(); |
887 entry_block_->SetInitialEnvironment(start_environment_); | 710 entry_block_->SetInitialEnvironment(start_environment_); |
888 } | 711 } |
889 | 712 |
890 | 713 |
891 HBasicBlock* HGraph::CreateBasicBlock() { | 714 HBasicBlock* HGraph::CreateBasicBlock() { |
892 HBasicBlock* result = new(zone()) HBasicBlock(this); | 715 HBasicBlock* result = new(zone()) HBasicBlock(this); |
893 blocks_.Add(result, zone()); | 716 blocks_.Add(result, zone()); |
894 return result; | 717 return result; |
(...skipping 2168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3063 visited.Clear(); | 2886 visited.Clear(); |
3064 } | 2887 } |
3065 } | 2888 } |
3066 } | 2889 } |
3067 } | 2890 } |
3068 } | 2891 } |
3069 | 2892 |
3070 | 2893 |
3071 // Implementation of utility class to encapsulate the translation state for | 2894 // Implementation of utility class to encapsulate the translation state for |
3072 // a (possibly inlined) function. | 2895 // a (possibly inlined) function. |
3073 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, | 2896 FunctionState::FunctionState(HGraphBuilder* owner, |
3074 CompilationInfo* info, | 2897 CompilationInfo* info, |
3075 TypeFeedbackOracle* oracle, | 2898 TypeFeedbackOracle* oracle, |
3076 InliningKind inlining_kind) | 2899 InliningKind inlining_kind) |
3077 : owner_(owner), | 2900 : owner_(owner), |
3078 compilation_info_(info), | 2901 compilation_info_(info), |
3079 oracle_(oracle), | 2902 oracle_(oracle), |
3080 call_context_(NULL), | 2903 call_context_(NULL), |
3081 inlining_kind_(inlining_kind), | 2904 inlining_kind_(inlining_kind), |
3082 function_return_(NULL), | 2905 function_return_(NULL), |
3083 test_context_(NULL), | 2906 test_context_(NULL), |
(...skipping 28 matching lines...) Expand all Loading... |
3112 | 2935 |
3113 | 2936 |
3114 FunctionState::~FunctionState() { | 2937 FunctionState::~FunctionState() { |
3115 delete test_context_; | 2938 delete test_context_; |
3116 owner_->set_function_state(outer_); | 2939 owner_->set_function_state(outer_); |
3117 } | 2940 } |
3118 | 2941 |
3119 | 2942 |
3120 // Implementation of utility classes to represent an expression's context in | 2943 // Implementation of utility classes to represent an expression's context in |
3121 // the AST. | 2944 // the AST. |
3122 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind) | 2945 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) |
3123 : owner_(owner), | 2946 : owner_(owner), |
3124 kind_(kind), | 2947 kind_(kind), |
3125 outer_(owner->ast_context()), | 2948 outer_(owner->ast_context()), |
3126 for_typeof_(false) { | 2949 for_typeof_(false) { |
3127 owner->set_ast_context(this); // Push. | 2950 owner->set_ast_context(this); // Push. |
3128 #ifdef DEBUG | 2951 #ifdef DEBUG |
3129 ASSERT(owner->environment()->frame_type() == JS_FUNCTION); | 2952 ASSERT(owner->environment()->frame_type() == JS_FUNCTION); |
3130 original_length_ = owner->environment()->length(); | 2953 original_length_ = owner->environment()->length(); |
3131 #endif | 2954 #endif |
3132 } | 2955 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3223 owner()->set_current_block(materialize_false); | 3046 owner()->set_current_block(materialize_false); |
3224 owner()->Push(owner()->graph()->GetConstantFalse()); | 3047 owner()->Push(owner()->graph()->GetConstantFalse()); |
3225 HBasicBlock* join = | 3048 HBasicBlock* join = |
3226 owner()->CreateJoin(materialize_true, materialize_false, ast_id); | 3049 owner()->CreateJoin(materialize_true, materialize_false, ast_id); |
3227 owner()->set_current_block(join); | 3050 owner()->set_current_block(join); |
3228 } | 3051 } |
3229 | 3052 |
3230 | 3053 |
3231 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 3054 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
3232 ASSERT(!instr->IsControlInstruction()); | 3055 ASSERT(!instr->IsControlInstruction()); |
3233 HOptimizedGraphBuilder* builder = owner(); | 3056 HGraphBuilder* builder = owner(); |
3234 builder->AddInstruction(instr); | 3057 builder->AddInstruction(instr); |
3235 // We expect a simulate after every expression with side effects, though | 3058 // We expect a simulate after every expression with side effects, though |
3236 // this one isn't actually needed (and wouldn't work if it were targeted). | 3059 // this one isn't actually needed (and wouldn't work if it were targeted). |
3237 if (instr->HasObservableSideEffects()) { | 3060 if (instr->HasObservableSideEffects()) { |
3238 builder->Push(instr); | 3061 builder->Push(instr); |
3239 builder->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 3062 builder->AddSimulate(ast_id, REMOVABLE_SIMULATE); |
3240 builder->Pop(); | 3063 builder->Pop(); |
3241 } | 3064 } |
3242 BuildBranch(instr); | 3065 BuildBranch(instr); |
3243 } | 3066 } |
(...skipping 10 matching lines...) Expand all Loading... |
3254 empty_false->Goto(if_false(), owner()->function_state()); | 3077 empty_false->Goto(if_false(), owner()->function_state()); |
3255 owner()->set_current_block(NULL); | 3078 owner()->set_current_block(NULL); |
3256 } | 3079 } |
3257 | 3080 |
3258 | 3081 |
3259 void TestContext::BuildBranch(HValue* value) { | 3082 void TestContext::BuildBranch(HValue* value) { |
3260 // We expect the graph to be in edge-split form: there is no edge that | 3083 // We expect the graph to be in edge-split form: there is no edge that |
3261 // connects a branch node to a join node. We conservatively ensure that | 3084 // connects a branch node to a join node. We conservatively ensure that |
3262 // property by always adding an empty block on the outgoing edges of this | 3085 // property by always adding an empty block on the outgoing edges of this |
3263 // branch. | 3086 // branch. |
3264 HOptimizedGraphBuilder* builder = owner(); | 3087 HGraphBuilder* builder = owner(); |
3265 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { | 3088 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { |
3266 builder->Bailout("arguments object value in a test context"); | 3089 builder->Bailout("arguments object value in a test context"); |
3267 } | 3090 } |
3268 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | 3091 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
3269 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | 3092 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
3270 TypeFeedbackId test_id = condition()->test_id(); | 3093 TypeFeedbackId test_id = condition()->test_id(); |
3271 ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id)); | 3094 ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id)); |
3272 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); | 3095 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); |
3273 builder->current_block()->Finish(test); | 3096 builder->current_block()->Finish(test); |
3274 | 3097 |
3275 empty_true->Goto(if_true(), owner()->function_state()); | 3098 empty_true->Goto(if_true(), owner()->function_state()); |
3276 empty_false->Goto(if_false(), owner()->function_state()); | 3099 empty_false->Goto(if_false(), owner()->function_state()); |
3277 builder->set_current_block(NULL); | 3100 builder->set_current_block(NULL); |
3278 } | 3101 } |
3279 | 3102 |
3280 | 3103 |
3281 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. | 3104 // HGraphBuilder infrastructure for bailing out and checking bailouts. |
3282 #define CHECK_BAILOUT(call) \ | 3105 #define CHECK_BAILOUT(call) \ |
3283 do { \ | 3106 do { \ |
3284 call; \ | 3107 call; \ |
3285 if (HasStackOverflow()) return; \ | 3108 if (HasStackOverflow()) return; \ |
3286 } while (false) | 3109 } while (false) |
3287 | 3110 |
3288 | 3111 |
3289 #define CHECK_ALIVE(call) \ | 3112 #define CHECK_ALIVE(call) \ |
3290 do { \ | 3113 do { \ |
3291 call; \ | 3114 call; \ |
3292 if (HasStackOverflow() || current_block() == NULL) return; \ | 3115 if (HasStackOverflow() || current_block() == NULL) return; \ |
3293 } while (false) | 3116 } while (false) |
3294 | 3117 |
3295 | 3118 |
3296 void HOptimizedGraphBuilder::Bailout(const char* reason) { | 3119 void HGraphBuilder::Bailout(const char* reason) { |
3297 info()->set_bailout_reason(reason); | 3120 info()->set_bailout_reason(reason); |
3298 SetStackOverflow(); | 3121 SetStackOverflow(); |
3299 } | 3122 } |
3300 | 3123 |
3301 | 3124 |
3302 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { | 3125 void HGraphBuilder::VisitForEffect(Expression* expr) { |
3303 EffectContext for_effect(this); | 3126 EffectContext for_effect(this); |
3304 Visit(expr); | 3127 Visit(expr); |
3305 } | 3128 } |
3306 | 3129 |
3307 | 3130 |
3308 void HOptimizedGraphBuilder::VisitForValue(Expression* expr, | 3131 void HGraphBuilder::VisitForValue(Expression* expr, ArgumentsAllowedFlag flag) { |
3309 ArgumentsAllowedFlag flag) { | |
3310 ValueContext for_value(this, flag); | 3132 ValueContext for_value(this, flag); |
3311 Visit(expr); | 3133 Visit(expr); |
3312 } | 3134 } |
3313 | 3135 |
3314 | 3136 |
3315 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) { | 3137 void HGraphBuilder::VisitForTypeOf(Expression* expr) { |
3316 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 3138 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
3317 for_value.set_for_typeof(true); | 3139 for_value.set_for_typeof(true); |
3318 Visit(expr); | 3140 Visit(expr); |
3319 } | 3141 } |
3320 | 3142 |
3321 | 3143 |
3322 | 3144 |
3323 void HOptimizedGraphBuilder::VisitForControl(Expression* expr, | 3145 void HGraphBuilder::VisitForControl(Expression* expr, |
3324 HBasicBlock* true_block, | 3146 HBasicBlock* true_block, |
3325 HBasicBlock* false_block) { | 3147 HBasicBlock* false_block) { |
3326 TestContext for_test(this, expr, oracle(), true_block, false_block); | 3148 TestContext for_test(this, expr, oracle(), true_block, false_block); |
3327 Visit(expr); | 3149 Visit(expr); |
3328 } | 3150 } |
3329 | 3151 |
3330 | 3152 |
3331 void HOptimizedGraphBuilder::VisitArgument(Expression* expr) { | 3153 void HGraphBuilder::VisitArgument(Expression* expr) { |
3332 CHECK_ALIVE(VisitForValue(expr)); | 3154 CHECK_ALIVE(VisitForValue(expr)); |
3333 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); | 3155 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); |
3334 } | 3156 } |
3335 | 3157 |
3336 | 3158 |
3337 void HOptimizedGraphBuilder::VisitArgumentList( | 3159 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { |
3338 ZoneList<Expression*>* arguments) { | |
3339 for (int i = 0; i < arguments->length(); i++) { | 3160 for (int i = 0; i < arguments->length(); i++) { |
3340 CHECK_ALIVE(VisitArgument(arguments->at(i))); | 3161 CHECK_ALIVE(VisitArgument(arguments->at(i))); |
3341 } | 3162 } |
3342 } | 3163 } |
3343 | 3164 |
3344 | 3165 |
3345 void HOptimizedGraphBuilder::VisitExpressions( | 3166 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { |
3346 ZoneList<Expression*>* exprs) { | |
3347 for (int i = 0; i < exprs->length(); ++i) { | 3167 for (int i = 0; i < exprs->length(); ++i) { |
3348 CHECK_ALIVE(VisitForValue(exprs->at(i))); | 3168 CHECK_ALIVE(VisitForValue(exprs->at(i))); |
3349 } | 3169 } |
3350 } | 3170 } |
3351 | 3171 |
3352 | 3172 |
3353 bool HOptimizedGraphBuilder::BuildGraph() { | 3173 HGraph* HGraphBuilder::CreateGraph() { |
3354 Scope* scope = info()->scope(); | 3174 graph_ = new(zone()) HGraph(info()); |
3355 if (scope->HasIllegalRedeclaration()) { | 3175 if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info()); |
3356 Bailout("function with illegal redeclaration"); | |
3357 return false; | |
3358 } | |
3359 if (scope->calls_eval()) { | |
3360 Bailout("function calls eval"); | |
3361 return false; | |
3362 } | |
3363 SetUpScope(scope); | |
3364 | 3176 |
3365 // Add an edge to the body entry. This is warty: the graph's start | 3177 { |
3366 // environment will be used by the Lithium translation as the initial | 3178 HPhase phase("H_Block building"); |
3367 // environment on graph entry, but it has now been mutated by the | 3179 current_block_ = graph()->entry_block(); |
3368 // Hydrogen translation of the instructions in the start block. This | |
3369 // environment uses values which have not been defined yet. These | |
3370 // Hydrogen instructions will then be replayed by the Lithium | |
3371 // translation, so they cannot have an environment effect. The edge to | |
3372 // the body's entry block (along with some special logic for the start | |
3373 // block in HInstruction::InsertAfter) seals the start block from | |
3374 // getting unwanted instructions inserted. | |
3375 // | |
3376 // TODO(kmillikin): Fix this. Stop mutating the initial environment. | |
3377 // Make the Hydrogen instructions in the initial block into Hydrogen | |
3378 // values (but not instructions), present in the initial environment and | |
3379 // not replayed by the Lithium translation. | |
3380 HEnvironment* initial_env = environment()->CopyWithoutHistory(); | |
3381 HBasicBlock* body_entry = CreateBasicBlock(initial_env); | |
3382 current_block()->Goto(body_entry); | |
3383 body_entry->SetJoinId(BailoutId::FunctionEntry()); | |
3384 set_current_block(body_entry); | |
3385 | 3180 |
3386 // Handle implicit declaration of the function name in named function | 3181 Scope* scope = info()->scope(); |
3387 // expressions before other declarations. | 3182 if (scope->HasIllegalRedeclaration()) { |
3388 if (scope->is_function_scope() && scope->function() != NULL) { | 3183 Bailout("function with illegal redeclaration"); |
3389 VisitVariableDeclaration(scope->function()); | 3184 return NULL; |
3390 } | 3185 } |
3391 VisitDeclarations(scope->declarations()); | 3186 if (scope->calls_eval()) { |
3392 AddSimulate(BailoutId::Declarations()); | 3187 Bailout("function calls eval"); |
| 3188 return NULL; |
| 3189 } |
| 3190 SetUpScope(scope); |
3393 | 3191 |
3394 HValue* context = environment()->LookupContext(); | 3192 // Add an edge to the body entry. This is warty: the graph's start |
3395 AddInstruction( | 3193 // environment will be used by the Lithium translation as the initial |
3396 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); | 3194 // environment on graph entry, but it has now been mutated by the |
| 3195 // Hydrogen translation of the instructions in the start block. This |
| 3196 // environment uses values which have not been defined yet. These |
| 3197 // Hydrogen instructions will then be replayed by the Lithium |
| 3198 // translation, so they cannot have an environment effect. The edge to |
| 3199 // the body's entry block (along with some special logic for the start |
| 3200 // block in HInstruction::InsertAfter) seals the start block from |
| 3201 // getting unwanted instructions inserted. |
| 3202 // |
| 3203 // TODO(kmillikin): Fix this. Stop mutating the initial environment. |
| 3204 // Make the Hydrogen instructions in the initial block into Hydrogen |
| 3205 // values (but not instructions), present in the initial environment and |
| 3206 // not replayed by the Lithium translation. |
| 3207 HEnvironment* initial_env = environment()->CopyWithoutHistory(); |
| 3208 HBasicBlock* body_entry = CreateBasicBlock(initial_env); |
| 3209 current_block()->Goto(body_entry); |
| 3210 body_entry->SetJoinId(BailoutId::FunctionEntry()); |
| 3211 set_current_block(body_entry); |
3397 | 3212 |
3398 VisitStatements(info()->function()->body()); | 3213 // Handle implicit declaration of the function name in named function |
3399 if (HasStackOverflow()) return false; | 3214 // expressions before other declarations. |
| 3215 if (scope->is_function_scope() && scope->function() != NULL) { |
| 3216 VisitVariableDeclaration(scope->function()); |
| 3217 } |
| 3218 VisitDeclarations(scope->declarations()); |
| 3219 AddSimulate(BailoutId::Declarations()); |
3400 | 3220 |
3401 if (current_block() != NULL) { | 3221 HValue* context = environment()->LookupContext(); |
3402 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); | 3222 AddInstruction( |
3403 current_block()->FinishExit(instr); | 3223 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); |
3404 set_current_block(NULL); | 3224 |
| 3225 VisitStatements(info()->function()->body()); |
| 3226 if (HasStackOverflow()) return NULL; |
| 3227 |
| 3228 if (current_block() != NULL) { |
| 3229 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); |
| 3230 current_block()->FinishExit(instr); |
| 3231 set_current_block(NULL); |
| 3232 } |
| 3233 |
| 3234 // If the checksum of the number of type info changes is the same as the |
| 3235 // last time this function was compiled, then this recompile is likely not |
| 3236 // due to missing/inadequate type feedback, but rather too aggressive |
| 3237 // optimization. Disable optimistic LICM in that case. |
| 3238 Handle<Code> unoptimized_code(info()->shared_info()->code()); |
| 3239 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 3240 Handle<TypeFeedbackInfo> type_info( |
| 3241 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); |
| 3242 int checksum = type_info->own_type_change_checksum(); |
| 3243 int composite_checksum = graph()->update_type_change_checksum(checksum); |
| 3244 graph()->set_use_optimistic_licm( |
| 3245 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
| 3246 type_info->set_inlined_type_change_checksum(composite_checksum); |
3405 } | 3247 } |
3406 | 3248 |
3407 // If the checksum of the number of type info changes is the same as the | 3249 return graph(); |
3408 // last time this function was compiled, then this recompile is likely not | |
3409 // due to missing/inadequate type feedback, but rather too aggressive | |
3410 // optimization. Disable optimistic LICM in that case. | |
3411 Handle<Code> unoptimized_code(info()->shared_info()->code()); | |
3412 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | |
3413 Handle<TypeFeedbackInfo> type_info( | |
3414 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | |
3415 int checksum = type_info->own_type_change_checksum(); | |
3416 int composite_checksum = graph()->update_type_change_checksum(checksum); | |
3417 graph()->set_use_optimistic_licm( | |
3418 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | |
3419 type_info->set_inlined_type_change_checksum(composite_checksum); | |
3420 | |
3421 return true; | |
3422 } | 3250 } |
3423 | 3251 |
3424 | |
3425 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { | 3252 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { |
3426 *bailout_reason = SmartArrayPointer<char>(); | 3253 *bailout_reason = SmartArrayPointer<char>(); |
3427 OrderBlocks(); | 3254 OrderBlocks(); |
3428 AssignDominators(); | 3255 AssignDominators(); |
3429 | 3256 |
3430 #ifdef DEBUG | 3257 #ifdef DEBUG |
3431 // Do a full verify after building the graph and computing dominators. | 3258 // Do a full verify after building the graph and computing dominators. |
3432 Verify(true); | 3259 Verify(true); |
3433 #endif | 3260 #endif |
3434 | 3261 |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3938 } | 3765 } |
3939 instr->DeleteAndReplaceWith(NULL); | 3766 instr->DeleteAndReplaceWith(NULL); |
3940 for (int i = 0; i < instr->OperandCount(); ++i) { | 3767 for (int i = 0; i < instr->OperandCount(); ++i) { |
3941 HValue* operand = instr->OperandAt(i); | 3768 HValue* operand = instr->OperandAt(i); |
3942 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); | 3769 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); |
3943 } | 3770 } |
3944 } | 3771 } |
3945 } | 3772 } |
3946 | 3773 |
3947 | 3774 |
3948 void HOptimizedGraphBuilder::AddPhi(HPhi* instr) { | 3775 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 3776 ASSERT(current_block() != NULL); |
| 3777 current_block()->AddInstruction(instr); |
| 3778 return instr; |
| 3779 } |
| 3780 |
| 3781 |
| 3782 void HGraphBuilder::AddSimulate(BailoutId ast_id, RemovableSimulate removable) { |
| 3783 ASSERT(current_block() != NULL); |
| 3784 current_block()->AddSimulate(ast_id, removable); |
| 3785 } |
| 3786 |
| 3787 |
| 3788 void HGraphBuilder::AddPhi(HPhi* instr) { |
3949 ASSERT(current_block() != NULL); | 3789 ASSERT(current_block() != NULL); |
3950 current_block()->AddPhi(instr); | 3790 current_block()->AddPhi(instr); |
3951 } | 3791 } |
3952 | 3792 |
3953 | 3793 |
3954 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { | 3794 void HGraphBuilder::PushAndAdd(HInstruction* instr) { |
3955 Push(instr); | 3795 Push(instr); |
3956 AddInstruction(instr); | 3796 AddInstruction(instr); |
3957 } | 3797 } |
3958 | 3798 |
3959 | 3799 |
3960 template <class Instruction> | 3800 template <class Instruction> |
3961 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { | 3801 HInstruction* HGraphBuilder::PreProcessCall(Instruction* call) { |
3962 int count = call->argument_count(); | 3802 int count = call->argument_count(); |
3963 ZoneList<HValue*> arguments(count, zone()); | 3803 ZoneList<HValue*> arguments(count, zone()); |
3964 for (int i = 0; i < count; ++i) { | 3804 for (int i = 0; i < count; ++i) { |
3965 arguments.Add(Pop(), zone()); | 3805 arguments.Add(Pop(), zone()); |
3966 } | 3806 } |
3967 | 3807 |
3968 while (!arguments.is_empty()) { | 3808 while (!arguments.is_empty()) { |
3969 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); | 3809 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); |
3970 } | 3810 } |
3971 return call; | 3811 return call; |
3972 } | 3812 } |
3973 | 3813 |
3974 | 3814 |
3975 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { | 3815 void HGraphBuilder::SetUpScope(Scope* scope) { |
3976 HConstant* undefined_constant = new(zone()) HConstant( | 3816 HConstant* undefined_constant = new(zone()) HConstant( |
3977 isolate()->factory()->undefined_value(), Representation::Tagged()); | 3817 isolate()->factory()->undefined_value(), Representation::Tagged()); |
3978 AddInstruction(undefined_constant); | 3818 AddInstruction(undefined_constant); |
3979 graph()->set_undefined_constant(undefined_constant); | 3819 graph_->set_undefined_constant(undefined_constant); |
3980 | 3820 |
3981 HArgumentsObject* object = new(zone()) HArgumentsObject; | 3821 HArgumentsObject* object = new(zone()) HArgumentsObject; |
3982 AddInstruction(object); | 3822 AddInstruction(object); |
3983 graph()->SetArgumentsObject(object); | 3823 graph()->SetArgumentsObject(object); |
3984 | 3824 |
3985 // Set the initial values of parameters including "this". "This" has | 3825 // Set the initial values of parameters including "this". "This" has |
3986 // parameter index 0. | 3826 // parameter index 0. |
3987 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); | 3827 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); |
3988 | 3828 |
3989 for (int i = 0; i < environment()->parameter_count(); ++i) { | 3829 for (int i = 0; i < environment()->parameter_count(); ++i) { |
(...skipping 18 matching lines...) Expand all Loading... |
4008 if (!scope->arguments()->IsStackAllocated()) { | 3848 if (!scope->arguments()->IsStackAllocated()) { |
4009 return Bailout("context-allocated arguments"); | 3849 return Bailout("context-allocated arguments"); |
4010 } | 3850 } |
4011 | 3851 |
4012 environment()->Bind(scope->arguments(), | 3852 environment()->Bind(scope->arguments(), |
4013 graph()->GetArgumentsObject()); | 3853 graph()->GetArgumentsObject()); |
4014 } | 3854 } |
4015 } | 3855 } |
4016 | 3856 |
4017 | 3857 |
4018 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { | 3858 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { |
4019 for (int i = 0; i < statements->length(); i++) { | 3859 for (int i = 0; i < statements->length(); i++) { |
4020 CHECK_ALIVE(Visit(statements->at(i))); | 3860 CHECK_ALIVE(Visit(statements->at(i))); |
4021 } | 3861 } |
4022 } | 3862 } |
4023 | 3863 |
4024 | 3864 |
4025 HBasicBlock* HOptimizedGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 3865 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
4026 HBasicBlock* b = graph()->CreateBasicBlock(); | 3866 HBasicBlock* b = graph()->CreateBasicBlock(); |
4027 b->SetInitialEnvironment(env); | 3867 b->SetInitialEnvironment(env); |
4028 return b; | 3868 return b; |
4029 } | 3869 } |
4030 | 3870 |
4031 | 3871 |
4032 HBasicBlock* HOptimizedGraphBuilder::CreateLoopHeaderBlock() { | 3872 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
4033 HBasicBlock* header = graph()->CreateBasicBlock(); | 3873 HBasicBlock* header = graph()->CreateBasicBlock(); |
4034 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 3874 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
4035 header->SetInitialEnvironment(entry_env); | 3875 header->SetInitialEnvironment(entry_env); |
4036 header->AttachLoopInformation(); | 3876 header->AttachLoopInformation(); |
4037 return header; | 3877 return header; |
4038 } | 3878 } |
4039 | 3879 |
4040 | 3880 |
4041 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { | 3881 void HGraphBuilder::VisitBlock(Block* stmt) { |
4042 ASSERT(!HasStackOverflow()); | 3882 ASSERT(!HasStackOverflow()); |
4043 ASSERT(current_block() != NULL); | 3883 ASSERT(current_block() != NULL); |
4044 ASSERT(current_block()->HasPredecessor()); | 3884 ASSERT(current_block()->HasPredecessor()); |
4045 if (stmt->scope() != NULL) { | 3885 if (stmt->scope() != NULL) { |
4046 return Bailout("ScopedBlock"); | 3886 return Bailout("ScopedBlock"); |
4047 } | 3887 } |
4048 BreakAndContinueInfo break_info(stmt); | 3888 BreakAndContinueInfo break_info(stmt); |
4049 { BreakAndContinueScope push(&break_info, this); | 3889 { BreakAndContinueScope push(&break_info, this); |
4050 CHECK_BAILOUT(VisitStatements(stmt->statements())); | 3890 CHECK_BAILOUT(VisitStatements(stmt->statements())); |
4051 } | 3891 } |
4052 HBasicBlock* break_block = break_info.break_block(); | 3892 HBasicBlock* break_block = break_info.break_block(); |
4053 if (break_block != NULL) { | 3893 if (break_block != NULL) { |
4054 if (current_block() != NULL) current_block()->Goto(break_block); | 3894 if (current_block() != NULL) current_block()->Goto(break_block); |
4055 break_block->SetJoinId(stmt->ExitId()); | 3895 break_block->SetJoinId(stmt->ExitId()); |
4056 set_current_block(break_block); | 3896 set_current_block(break_block); |
4057 } | 3897 } |
4058 } | 3898 } |
4059 | 3899 |
4060 | 3900 |
4061 void HOptimizedGraphBuilder::VisitExpressionStatement( | 3901 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { |
4062 ExpressionStatement* stmt) { | |
4063 ASSERT(!HasStackOverflow()); | 3902 ASSERT(!HasStackOverflow()); |
4064 ASSERT(current_block() != NULL); | 3903 ASSERT(current_block() != NULL); |
4065 ASSERT(current_block()->HasPredecessor()); | 3904 ASSERT(current_block()->HasPredecessor()); |
4066 VisitForEffect(stmt->expression()); | 3905 VisitForEffect(stmt->expression()); |
4067 } | 3906 } |
4068 | 3907 |
4069 | 3908 |
4070 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { | 3909 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { |
4071 ASSERT(!HasStackOverflow()); | 3910 ASSERT(!HasStackOverflow()); |
4072 ASSERT(current_block() != NULL); | 3911 ASSERT(current_block() != NULL); |
4073 ASSERT(current_block()->HasPredecessor()); | 3912 ASSERT(current_block()->HasPredecessor()); |
4074 } | 3913 } |
4075 | 3914 |
4076 | 3915 |
4077 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 3916 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
4078 ASSERT(!HasStackOverflow()); | 3917 ASSERT(!HasStackOverflow()); |
4079 ASSERT(current_block() != NULL); | 3918 ASSERT(current_block() != NULL); |
4080 ASSERT(current_block()->HasPredecessor()); | 3919 ASSERT(current_block()->HasPredecessor()); |
4081 if (stmt->condition()->ToBooleanIsTrue()) { | 3920 if (stmt->condition()->ToBooleanIsTrue()) { |
4082 AddSimulate(stmt->ThenId()); | 3921 AddSimulate(stmt->ThenId()); |
4083 Visit(stmt->then_statement()); | 3922 Visit(stmt->then_statement()); |
4084 } else if (stmt->condition()->ToBooleanIsFalse()) { | 3923 } else if (stmt->condition()->ToBooleanIsFalse()) { |
4085 AddSimulate(stmt->ElseId()); | 3924 AddSimulate(stmt->ElseId()); |
4086 Visit(stmt->else_statement()); | 3925 Visit(stmt->else_statement()); |
4087 } else { | 3926 } else { |
(...skipping 18 matching lines...) Expand all Loading... |
4106 } else { | 3945 } else { |
4107 cond_false = NULL; | 3946 cond_false = NULL; |
4108 } | 3947 } |
4109 | 3948 |
4110 HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId()); | 3949 HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId()); |
4111 set_current_block(join); | 3950 set_current_block(join); |
4112 } | 3951 } |
4113 } | 3952 } |
4114 | 3953 |
4115 | 3954 |
4116 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get( | 3955 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( |
4117 BreakableStatement* stmt, | 3956 BreakableStatement* stmt, |
4118 BreakType type, | 3957 BreakType type, |
4119 int* drop_extra) { | 3958 int* drop_extra) { |
4120 *drop_extra = 0; | 3959 *drop_extra = 0; |
4121 BreakAndContinueScope* current = this; | 3960 BreakAndContinueScope* current = this; |
4122 while (current != NULL && current->info()->target() != stmt) { | 3961 while (current != NULL && current->info()->target() != stmt) { |
4123 *drop_extra += current->info()->drop_extra(); | 3962 *drop_extra += current->info()->drop_extra(); |
4124 current = current->next(); | 3963 current = current->next(); |
4125 } | 3964 } |
4126 ASSERT(current != NULL); // Always found (unless stack is malformed). | 3965 ASSERT(current != NULL); // Always found (unless stack is malformed). |
(...skipping 18 matching lines...) Expand all Loading... |
4145 block = current->owner()->graph()->CreateBasicBlock(); | 3984 block = current->owner()->graph()->CreateBasicBlock(); |
4146 current->info()->set_continue_block(block); | 3985 current->info()->set_continue_block(block); |
4147 } | 3986 } |
4148 break; | 3987 break; |
4149 } | 3988 } |
4150 | 3989 |
4151 return block; | 3990 return block; |
4152 } | 3991 } |
4153 | 3992 |
4154 | 3993 |
4155 void HOptimizedGraphBuilder::VisitContinueStatement( | 3994 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
4156 ContinueStatement* stmt) { | |
4157 ASSERT(!HasStackOverflow()); | 3995 ASSERT(!HasStackOverflow()); |
4158 ASSERT(current_block() != NULL); | 3996 ASSERT(current_block() != NULL); |
4159 ASSERT(current_block()->HasPredecessor()); | 3997 ASSERT(current_block()->HasPredecessor()); |
4160 int drop_extra = 0; | 3998 int drop_extra = 0; |
4161 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), | 3999 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), |
4162 CONTINUE, | 4000 CONTINUE, |
4163 &drop_extra); | 4001 &drop_extra); |
4164 Drop(drop_extra); | 4002 Drop(drop_extra); |
4165 current_block()->Goto(continue_block); | 4003 current_block()->Goto(continue_block); |
4166 set_current_block(NULL); | 4004 set_current_block(NULL); |
4167 } | 4005 } |
4168 | 4006 |
4169 | 4007 |
4170 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 4008 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
4171 ASSERT(!HasStackOverflow()); | 4009 ASSERT(!HasStackOverflow()); |
4172 ASSERT(current_block() != NULL); | 4010 ASSERT(current_block() != NULL); |
4173 ASSERT(current_block()->HasPredecessor()); | 4011 ASSERT(current_block()->HasPredecessor()); |
4174 int drop_extra = 0; | 4012 int drop_extra = 0; |
4175 HBasicBlock* break_block = break_scope()->Get(stmt->target(), | 4013 HBasicBlock* break_block = break_scope()->Get(stmt->target(), |
4176 BREAK, | 4014 BREAK, |
4177 &drop_extra); | 4015 &drop_extra); |
4178 Drop(drop_extra); | 4016 Drop(drop_extra); |
4179 current_block()->Goto(break_block); | 4017 current_block()->Goto(break_block); |
4180 set_current_block(NULL); | 4018 set_current_block(NULL); |
4181 } | 4019 } |
4182 | 4020 |
4183 | 4021 |
4184 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 4022 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
4185 ASSERT(!HasStackOverflow()); | 4023 ASSERT(!HasStackOverflow()); |
4186 ASSERT(current_block() != NULL); | 4024 ASSERT(current_block() != NULL); |
4187 ASSERT(current_block()->HasPredecessor()); | 4025 ASSERT(current_block()->HasPredecessor()); |
4188 FunctionState* state = function_state(); | 4026 FunctionState* state = function_state(); |
4189 AstContext* context = call_context(); | 4027 AstContext* context = call_context(); |
4190 if (context == NULL) { | 4028 if (context == NULL) { |
4191 // Not an inlined return, so an actual one. | 4029 // Not an inlined return, so an actual one. |
4192 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4030 CHECK_ALIVE(VisitForValue(stmt->expression())); |
4193 HValue* result = environment()->Pop(); | 4031 HValue* result = environment()->Pop(); |
4194 current_block()->FinishExit(new(zone()) HReturn(result)); | 4032 current_block()->FinishExit(new(zone()) HReturn(result)); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4246 } else { | 4084 } else { |
4247 ASSERT(context->IsValue()); | 4085 ASSERT(context->IsValue()); |
4248 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4086 CHECK_ALIVE(VisitForValue(stmt->expression())); |
4249 current_block()->AddLeaveInlined(Pop(), state); | 4087 current_block()->AddLeaveInlined(Pop(), state); |
4250 } | 4088 } |
4251 } | 4089 } |
4252 set_current_block(NULL); | 4090 set_current_block(NULL); |
4253 } | 4091 } |
4254 | 4092 |
4255 | 4093 |
4256 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 4094 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
4257 ASSERT(!HasStackOverflow()); | 4095 ASSERT(!HasStackOverflow()); |
4258 ASSERT(current_block() != NULL); | 4096 ASSERT(current_block() != NULL); |
4259 ASSERT(current_block()->HasPredecessor()); | 4097 ASSERT(current_block()->HasPredecessor()); |
4260 return Bailout("WithStatement"); | 4098 return Bailout("WithStatement"); |
4261 } | 4099 } |
4262 | 4100 |
4263 | 4101 |
4264 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 4102 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
4265 ASSERT(!HasStackOverflow()); | 4103 ASSERT(!HasStackOverflow()); |
4266 ASSERT(current_block() != NULL); | 4104 ASSERT(current_block() != NULL); |
4267 ASSERT(current_block()->HasPredecessor()); | 4105 ASSERT(current_block()->HasPredecessor()); |
4268 // We only optimize switch statements with smi-literal smi comparisons, | 4106 // We only optimize switch statements with smi-literal smi comparisons, |
4269 // with a bounded number of clauses. | 4107 // with a bounded number of clauses. |
4270 const int kCaseClauseLimit = 128; | 4108 const int kCaseClauseLimit = 128; |
4271 ZoneList<CaseClause*>* clauses = stmt->cases(); | 4109 ZoneList<CaseClause*>* clauses = stmt->cases(); |
4272 int clause_count = clauses->length(); | 4110 int clause_count = clauses->length(); |
4273 if (clause_count > kCaseClauseLimit) { | 4111 if (clause_count > kCaseClauseLimit) { |
4274 return Bailout("SwitchStatement: too many clauses"); | 4112 return Bailout("SwitchStatement: too many clauses"); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4440 stmt->ExitId())); | 4278 stmt->ExitId())); |
4441 } else { | 4279 } else { |
4442 if (fall_through_block != NULL) fall_through_block->Goto(break_block); | 4280 if (fall_through_block != NULL) fall_through_block->Goto(break_block); |
4443 if (last_block != NULL) last_block->Goto(break_block); | 4281 if (last_block != NULL) last_block->Goto(break_block); |
4444 break_block->SetJoinId(stmt->ExitId()); | 4282 break_block->SetJoinId(stmt->ExitId()); |
4445 set_current_block(break_block); | 4283 set_current_block(break_block); |
4446 } | 4284 } |
4447 } | 4285 } |
4448 | 4286 |
4449 | 4287 |
4450 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { | 4288 bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { |
4451 return statement->OsrEntryId() == info()->osr_ast_id(); | 4289 return statement->OsrEntryId() == info()->osr_ast_id(); |
4452 } | 4290 } |
4453 | 4291 |
4454 | 4292 |
4455 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | 4293 bool HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { |
4456 if (!HasOsrEntryAt(statement)) return false; | 4294 if (!HasOsrEntryAt(statement)) return false; |
4457 | 4295 |
4458 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); | 4296 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); |
4459 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); | 4297 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); |
4460 HValue* true_value = graph()->GetConstantTrue(); | 4298 HValue* true_value = graph()->GetConstantTrue(); |
4461 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); | 4299 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); |
4462 current_block()->Finish(test); | 4300 current_block()->Finish(test); |
4463 | 4301 |
4464 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); | 4302 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); |
4465 non_osr_entry->Goto(loop_predecessor); | 4303 non_osr_entry->Goto(loop_predecessor); |
(...skipping 29 matching lines...) Expand all Loading... |
4495 HContext* context = new(zone()) HContext; | 4333 HContext* context = new(zone()) HContext; |
4496 AddInstruction(context); | 4334 AddInstruction(context); |
4497 environment()->BindContext(context); | 4335 environment()->BindContext(context); |
4498 current_block()->Goto(loop_predecessor); | 4336 current_block()->Goto(loop_predecessor); |
4499 loop_predecessor->SetJoinId(statement->EntryId()); | 4337 loop_predecessor->SetJoinId(statement->EntryId()); |
4500 set_current_block(loop_predecessor); | 4338 set_current_block(loop_predecessor); |
4501 return true; | 4339 return true; |
4502 } | 4340 } |
4503 | 4341 |
4504 | 4342 |
4505 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 4343 void HGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
4506 HBasicBlock* loop_entry, | 4344 HBasicBlock* loop_entry, |
4507 BreakAndContinueInfo* break_info) { | 4345 BreakAndContinueInfo* break_info) { |
4508 BreakAndContinueScope push(break_info, this); | 4346 BreakAndContinueScope push(break_info, this); |
4509 AddSimulate(stmt->StackCheckId()); | 4347 AddSimulate(stmt->StackCheckId()); |
4510 HValue* context = environment()->LookupContext(); | 4348 HValue* context = environment()->LookupContext(); |
4511 HStackCheck* stack_check = | 4349 HStackCheck* stack_check = |
4512 new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch); | 4350 new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch); |
4513 AddInstruction(stack_check); | 4351 AddInstruction(stack_check); |
4514 ASSERT(loop_entry->IsLoopHeader()); | 4352 ASSERT(loop_entry->IsLoopHeader()); |
4515 loop_entry->loop_information()->set_stack_check(stack_check); | 4353 loop_entry->loop_information()->set_stack_check(stack_check); |
4516 CHECK_BAILOUT(Visit(stmt->body())); | 4354 CHECK_BAILOUT(Visit(stmt->body())); |
4517 } | 4355 } |
4518 | 4356 |
4519 | 4357 |
4520 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 4358 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
4521 ASSERT(!HasStackOverflow()); | 4359 ASSERT(!HasStackOverflow()); |
4522 ASSERT(current_block() != NULL); | 4360 ASSERT(current_block() != NULL); |
4523 ASSERT(current_block()->HasPredecessor()); | 4361 ASSERT(current_block()->HasPredecessor()); |
4524 ASSERT(current_block() != NULL); | 4362 ASSERT(current_block() != NULL); |
4525 bool osr_entry = PreProcessOsrEntry(stmt); | 4363 bool osr_entry = PreProcessOsrEntry(stmt); |
4526 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4364 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
4527 current_block()->Goto(loop_entry); | 4365 current_block()->Goto(loop_entry); |
4528 set_current_block(loop_entry); | 4366 set_current_block(loop_entry); |
4529 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | 4367 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); |
4530 | 4368 |
(...skipping 22 matching lines...) Expand all Loading... |
4553 } | 4391 } |
4554 HBasicBlock* loop_exit = CreateLoop(stmt, | 4392 HBasicBlock* loop_exit = CreateLoop(stmt, |
4555 loop_entry, | 4393 loop_entry, |
4556 body_exit, | 4394 body_exit, |
4557 loop_successor, | 4395 loop_successor, |
4558 break_info.break_block()); | 4396 break_info.break_block()); |
4559 set_current_block(loop_exit); | 4397 set_current_block(loop_exit); |
4560 } | 4398 } |
4561 | 4399 |
4562 | 4400 |
4563 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 4401 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
4564 ASSERT(!HasStackOverflow()); | 4402 ASSERT(!HasStackOverflow()); |
4565 ASSERT(current_block() != NULL); | 4403 ASSERT(current_block() != NULL); |
4566 ASSERT(current_block()->HasPredecessor()); | 4404 ASSERT(current_block()->HasPredecessor()); |
4567 ASSERT(current_block() != NULL); | 4405 ASSERT(current_block() != NULL); |
4568 bool osr_entry = PreProcessOsrEntry(stmt); | 4406 bool osr_entry = PreProcessOsrEntry(stmt); |
4569 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4407 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
4570 current_block()->Goto(loop_entry); | 4408 current_block()->Goto(loop_entry); |
4571 set_current_block(loop_entry); | 4409 set_current_block(loop_entry); |
4572 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | 4410 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); |
4573 | 4411 |
(...skipping 23 matching lines...) Expand all Loading... |
4597 JoinContinue(stmt, current_block(), break_info.continue_block()); | 4435 JoinContinue(stmt, current_block(), break_info.continue_block()); |
4598 HBasicBlock* loop_exit = CreateLoop(stmt, | 4436 HBasicBlock* loop_exit = CreateLoop(stmt, |
4599 loop_entry, | 4437 loop_entry, |
4600 body_exit, | 4438 body_exit, |
4601 loop_successor, | 4439 loop_successor, |
4602 break_info.break_block()); | 4440 break_info.break_block()); |
4603 set_current_block(loop_exit); | 4441 set_current_block(loop_exit); |
4604 } | 4442 } |
4605 | 4443 |
4606 | 4444 |
4607 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { | 4445 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
4608 ASSERT(!HasStackOverflow()); | 4446 ASSERT(!HasStackOverflow()); |
4609 ASSERT(current_block() != NULL); | 4447 ASSERT(current_block() != NULL); |
4610 ASSERT(current_block()->HasPredecessor()); | 4448 ASSERT(current_block()->HasPredecessor()); |
4611 if (stmt->init() != NULL) { | 4449 if (stmt->init() != NULL) { |
4612 CHECK_ALIVE(Visit(stmt->init())); | 4450 CHECK_ALIVE(Visit(stmt->init())); |
4613 } | 4451 } |
4614 ASSERT(current_block() != NULL); | 4452 ASSERT(current_block() != NULL); |
4615 bool osr_entry = PreProcessOsrEntry(stmt); | 4453 bool osr_entry = PreProcessOsrEntry(stmt); |
4616 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4454 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
4617 current_block()->Goto(loop_entry); | 4455 current_block()->Goto(loop_entry); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4649 | 4487 |
4650 HBasicBlock* loop_exit = CreateLoop(stmt, | 4488 HBasicBlock* loop_exit = CreateLoop(stmt, |
4651 loop_entry, | 4489 loop_entry, |
4652 body_exit, | 4490 body_exit, |
4653 loop_successor, | 4491 loop_successor, |
4654 break_info.break_block()); | 4492 break_info.break_block()); |
4655 set_current_block(loop_exit); | 4493 set_current_block(loop_exit); |
4656 } | 4494 } |
4657 | 4495 |
4658 | 4496 |
4659 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 4497 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
4660 ASSERT(!HasStackOverflow()); | 4498 ASSERT(!HasStackOverflow()); |
4661 ASSERT(current_block() != NULL); | 4499 ASSERT(current_block() != NULL); |
4662 ASSERT(current_block()->HasPredecessor()); | 4500 ASSERT(current_block()->HasPredecessor()); |
4663 | 4501 |
4664 if (!FLAG_optimize_for_in) { | 4502 if (!FLAG_optimize_for_in) { |
4665 return Bailout("ForInStatement optimization is disabled"); | 4503 return Bailout("ForInStatement optimization is disabled"); |
4666 } | 4504 } |
4667 | 4505 |
4668 if (!oracle()->IsForInFastCase(stmt)) { | 4506 if (!oracle()->IsForInFastCase(stmt)) { |
4669 return Bailout("ForInStatement is not fast case"); | 4507 return Bailout("ForInStatement is not fast case"); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4770 HBasicBlock* loop_exit = CreateLoop(stmt, | 4608 HBasicBlock* loop_exit = CreateLoop(stmt, |
4771 loop_entry, | 4609 loop_entry, |
4772 body_exit, | 4610 body_exit, |
4773 loop_successor, | 4611 loop_successor, |
4774 break_info.break_block()); | 4612 break_info.break_block()); |
4775 | 4613 |
4776 set_current_block(loop_exit); | 4614 set_current_block(loop_exit); |
4777 } | 4615 } |
4778 | 4616 |
4779 | 4617 |
4780 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 4618 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
4781 ASSERT(!HasStackOverflow()); | 4619 ASSERT(!HasStackOverflow()); |
4782 ASSERT(current_block() != NULL); | 4620 ASSERT(current_block() != NULL); |
4783 ASSERT(current_block()->HasPredecessor()); | 4621 ASSERT(current_block()->HasPredecessor()); |
4784 return Bailout("TryCatchStatement"); | 4622 return Bailout("TryCatchStatement"); |
4785 } | 4623 } |
4786 | 4624 |
4787 | 4625 |
4788 void HOptimizedGraphBuilder::VisitTryFinallyStatement( | 4626 void HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
4789 TryFinallyStatement* stmt) { | |
4790 ASSERT(!HasStackOverflow()); | 4627 ASSERT(!HasStackOverflow()); |
4791 ASSERT(current_block() != NULL); | 4628 ASSERT(current_block() != NULL); |
4792 ASSERT(current_block()->HasPredecessor()); | 4629 ASSERT(current_block()->HasPredecessor()); |
4793 return Bailout("TryFinallyStatement"); | 4630 return Bailout("TryFinallyStatement"); |
4794 } | 4631 } |
4795 | 4632 |
4796 | 4633 |
4797 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 4634 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
4798 ASSERT(!HasStackOverflow()); | 4635 ASSERT(!HasStackOverflow()); |
4799 ASSERT(current_block() != NULL); | 4636 ASSERT(current_block() != NULL); |
4800 ASSERT(current_block()->HasPredecessor()); | 4637 ASSERT(current_block()->HasPredecessor()); |
4801 return Bailout("DebuggerStatement"); | 4638 return Bailout("DebuggerStatement"); |
4802 } | 4639 } |
4803 | 4640 |
4804 | 4641 |
4805 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( | 4642 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( |
4806 Code* unoptimized_code, FunctionLiteral* expr) { | 4643 Code* unoptimized_code, FunctionLiteral* expr) { |
4807 int start_position = expr->start_position(); | 4644 int start_position = expr->start_position(); |
4808 RelocIterator it(unoptimized_code); | 4645 RelocIterator it(unoptimized_code); |
4809 for (;!it.done(); it.next()) { | 4646 for (;!it.done(); it.next()) { |
4810 RelocInfo* rinfo = it.rinfo(); | 4647 RelocInfo* rinfo = it.rinfo(); |
4811 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; | 4648 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; |
4812 Object* obj = rinfo->target_object(); | 4649 Object* obj = rinfo->target_object(); |
4813 if (obj->IsSharedFunctionInfo()) { | 4650 if (obj->IsSharedFunctionInfo()) { |
4814 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 4651 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
4815 if (shared->start_position() == start_position) { | 4652 if (shared->start_position() == start_position) { |
4816 return Handle<SharedFunctionInfo>(shared); | 4653 return Handle<SharedFunctionInfo>(shared); |
4817 } | 4654 } |
4818 } | 4655 } |
4819 } | 4656 } |
4820 | 4657 |
4821 return Handle<SharedFunctionInfo>(); | 4658 return Handle<SharedFunctionInfo>(); |
4822 } | 4659 } |
4823 | 4660 |
4824 | 4661 |
4825 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 4662 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
4826 ASSERT(!HasStackOverflow()); | 4663 ASSERT(!HasStackOverflow()); |
4827 ASSERT(current_block() != NULL); | 4664 ASSERT(current_block() != NULL); |
4828 ASSERT(current_block()->HasPredecessor()); | 4665 ASSERT(current_block()->HasPredecessor()); |
4829 Handle<SharedFunctionInfo> shared_info = | 4666 Handle<SharedFunctionInfo> shared_info = |
4830 SearchSharedFunctionInfo(info()->shared_info()->code(), | 4667 SearchSharedFunctionInfo(info()->shared_info()->code(), |
4831 expr); | 4668 expr); |
4832 if (shared_info.is_null()) { | 4669 if (shared_info.is_null()) { |
4833 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); | 4670 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); |
4834 } | 4671 } |
4835 // We also have a stack overflow if the recursive compilation did. | 4672 // We also have a stack overflow if the recursive compilation did. |
4836 if (HasStackOverflow()) return; | 4673 if (HasStackOverflow()) return; |
4837 HValue* context = environment()->LookupContext(); | 4674 HValue* context = environment()->LookupContext(); |
4838 HFunctionLiteral* instr = | 4675 HFunctionLiteral* instr = |
4839 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 4676 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
4840 return ast_context()->ReturnInstruction(instr, expr->id()); | 4677 return ast_context()->ReturnInstruction(instr, expr->id()); |
4841 } | 4678 } |
4842 | 4679 |
4843 | 4680 |
4844 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( | 4681 void HGraphBuilder::VisitSharedFunctionInfoLiteral( |
4845 SharedFunctionInfoLiteral* expr) { | 4682 SharedFunctionInfoLiteral* expr) { |
4846 ASSERT(!HasStackOverflow()); | 4683 ASSERT(!HasStackOverflow()); |
4847 ASSERT(current_block() != NULL); | 4684 ASSERT(current_block() != NULL); |
4848 ASSERT(current_block()->HasPredecessor()); | 4685 ASSERT(current_block()->HasPredecessor()); |
4849 return Bailout("SharedFunctionInfoLiteral"); | 4686 return Bailout("SharedFunctionInfoLiteral"); |
4850 } | 4687 } |
4851 | 4688 |
4852 | 4689 |
4853 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { | 4690 void HGraphBuilder::VisitConditional(Conditional* expr) { |
4854 ASSERT(!HasStackOverflow()); | 4691 ASSERT(!HasStackOverflow()); |
4855 ASSERT(current_block() != NULL); | 4692 ASSERT(current_block() != NULL); |
4856 ASSERT(current_block()->HasPredecessor()); | 4693 ASSERT(current_block()->HasPredecessor()); |
4857 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 4694 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
4858 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 4695 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
4859 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); | 4696 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); |
4860 | 4697 |
4861 // Visit the true and false subexpressions in the same AST context as the | 4698 // Visit the true and false subexpressions in the same AST context as the |
4862 // whole expression. | 4699 // whole expression. |
4863 if (cond_true->HasPredecessor()) { | 4700 if (cond_true->HasPredecessor()) { |
(...skipping 17 matching lines...) Expand all Loading... |
4881 if (!ast_context()->IsTest()) { | 4718 if (!ast_context()->IsTest()) { |
4882 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); | 4719 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); |
4883 set_current_block(join); | 4720 set_current_block(join); |
4884 if (join != NULL && !ast_context()->IsEffect()) { | 4721 if (join != NULL && !ast_context()->IsEffect()) { |
4885 return ast_context()->ReturnValue(Pop()); | 4722 return ast_context()->ReturnValue(Pop()); |
4886 } | 4723 } |
4887 } | 4724 } |
4888 } | 4725 } |
4889 | 4726 |
4890 | 4727 |
4891 HOptimizedGraphBuilder::GlobalPropertyAccess | 4728 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( |
4892 HOptimizedGraphBuilder::LookupGlobalProperty( | 4729 Variable* var, LookupResult* lookup, bool is_store) { |
4893 Variable* var, LookupResult* lookup, bool is_store) { | |
4894 if (var->is_this() || !info()->has_global_object()) { | 4730 if (var->is_this() || !info()->has_global_object()) { |
4895 return kUseGeneric; | 4731 return kUseGeneric; |
4896 } | 4732 } |
4897 Handle<GlobalObject> global(info()->global_object()); | 4733 Handle<GlobalObject> global(info()->global_object()); |
4898 global->Lookup(*var->name(), lookup); | 4734 global->Lookup(*var->name(), lookup); |
4899 if (!lookup->IsNormal() || | 4735 if (!lookup->IsNormal() || |
4900 (is_store && lookup->IsReadOnly()) || | 4736 (is_store && lookup->IsReadOnly()) || |
4901 lookup->holder() != *global) { | 4737 lookup->holder() != *global) { |
4902 return kUseGeneric; | 4738 return kUseGeneric; |
4903 } | 4739 } |
4904 | 4740 |
4905 return kUseCell; | 4741 return kUseCell; |
4906 } | 4742 } |
4907 | 4743 |
4908 | 4744 |
4909 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 4745 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
4910 ASSERT(var->IsContextSlot()); | 4746 ASSERT(var->IsContextSlot()); |
4911 HValue* context = environment()->LookupContext(); | 4747 HValue* context = environment()->LookupContext(); |
4912 int length = info()->scope()->ContextChainLength(var->scope()); | 4748 int length = info()->scope()->ContextChainLength(var->scope()); |
4913 while (length-- > 0) { | 4749 while (length-- > 0) { |
4914 HInstruction* context_instruction = new(zone()) HOuterContext(context); | 4750 HInstruction* context_instruction = new(zone()) HOuterContext(context); |
4915 AddInstruction(context_instruction); | 4751 AddInstruction(context_instruction); |
4916 context = context_instruction; | 4752 context = context_instruction; |
4917 } | 4753 } |
4918 return context; | 4754 return context; |
4919 } | 4755 } |
4920 | 4756 |
4921 | 4757 |
4922 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 4758 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
4923 ASSERT(!HasStackOverflow()); | 4759 ASSERT(!HasStackOverflow()); |
4924 ASSERT(current_block() != NULL); | 4760 ASSERT(current_block() != NULL); |
4925 ASSERT(current_block()->HasPredecessor()); | 4761 ASSERT(current_block()->HasPredecessor()); |
4926 Variable* variable = expr->var(); | 4762 Variable* variable = expr->var(); |
4927 switch (variable->location()) { | 4763 switch (variable->location()) { |
4928 case Variable::UNALLOCATED: { | 4764 case Variable::UNALLOCATED: { |
4929 if (IsLexicalVariableMode(variable->mode())) { | 4765 if (IsLexicalVariableMode(variable->mode())) { |
4930 // TODO(rossberg): should this be an ASSERT? | 4766 // TODO(rossberg): should this be an ASSERT? |
4931 return Bailout("reference to global lexical variable"); | 4767 return Bailout("reference to global lexical variable"); |
4932 } | 4768 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4985 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); | 4821 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); |
4986 return ast_context()->ReturnInstruction(instr, expr->id()); | 4822 return ast_context()->ReturnInstruction(instr, expr->id()); |
4987 } | 4823 } |
4988 | 4824 |
4989 case Variable::LOOKUP: | 4825 case Variable::LOOKUP: |
4990 return Bailout("reference to a variable which requires dynamic lookup"); | 4826 return Bailout("reference to a variable which requires dynamic lookup"); |
4991 } | 4827 } |
4992 } | 4828 } |
4993 | 4829 |
4994 | 4830 |
4995 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { | 4831 void HGraphBuilder::VisitLiteral(Literal* expr) { |
4996 ASSERT(!HasStackOverflow()); | 4832 ASSERT(!HasStackOverflow()); |
4997 ASSERT(current_block() != NULL); | 4833 ASSERT(current_block() != NULL); |
4998 ASSERT(current_block()->HasPredecessor()); | 4834 ASSERT(current_block()->HasPredecessor()); |
4999 HConstant* instr = | 4835 HConstant* instr = |
5000 new(zone()) HConstant(expr->handle(), Representation::None()); | 4836 new(zone()) HConstant(expr->handle(), Representation::None()); |
5001 return ast_context()->ReturnInstruction(instr, expr->id()); | 4837 return ast_context()->ReturnInstruction(instr, expr->id()); |
5002 } | 4838 } |
5003 | 4839 |
5004 | 4840 |
5005 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 4841 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
5006 ASSERT(!HasStackOverflow()); | 4842 ASSERT(!HasStackOverflow()); |
5007 ASSERT(current_block() != NULL); | 4843 ASSERT(current_block() != NULL); |
5008 ASSERT(current_block()->HasPredecessor()); | 4844 ASSERT(current_block()->HasPredecessor()); |
5009 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4845 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
5010 Handle<FixedArray> literals(closure->literals()); | 4846 Handle<FixedArray> literals(closure->literals()); |
5011 HValue* context = environment()->LookupContext(); | 4847 HValue* context = environment()->LookupContext(); |
5012 | 4848 |
5013 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, | 4849 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, |
5014 literals, | 4850 literals, |
5015 expr->pattern(), | 4851 expr->pattern(), |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5154 } | 4990 } |
5155 } | 4991 } |
5156 } | 4992 } |
5157 } | 4993 } |
5158 | 4994 |
5159 *total_size += boilerplate->map()->instance_size(); | 4995 *total_size += boilerplate->map()->instance_size(); |
5160 return true; | 4996 return true; |
5161 } | 4997 } |
5162 | 4998 |
5163 | 4999 |
5164 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 5000 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
5165 ASSERT(!HasStackOverflow()); | 5001 ASSERT(!HasStackOverflow()); |
5166 ASSERT(current_block() != NULL); | 5002 ASSERT(current_block() != NULL); |
5167 ASSERT(current_block()->HasPredecessor()); | 5003 ASSERT(current_block()->HasPredecessor()); |
5168 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 5004 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
5169 HValue* context = environment()->LookupContext(); | 5005 HValue* context = environment()->LookupContext(); |
5170 HInstruction* literal; | 5006 HInstruction* literal; |
5171 | 5007 |
5172 // Check whether to use fast or slow deep-copying for boilerplate. | 5008 // Check whether to use fast or slow deep-copying for boilerplate. |
5173 int total_size = 0; | 5009 int total_size = 0; |
5174 int max_properties = HFastLiteral::kMaxLiteralProperties; | 5010 int max_properties = HFastLiteral::kMaxLiteralProperties; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5259 // (e.g. because of code motion). | 5095 // (e.g. because of code motion). |
5260 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); | 5096 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); |
5261 AddInstruction(result); | 5097 AddInstruction(result); |
5262 return ast_context()->ReturnValue(result); | 5098 return ast_context()->ReturnValue(result); |
5263 } else { | 5099 } else { |
5264 return ast_context()->ReturnValue(Pop()); | 5100 return ast_context()->ReturnValue(Pop()); |
5265 } | 5101 } |
5266 } | 5102 } |
5267 | 5103 |
5268 | 5104 |
5269 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 5105 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
5270 ASSERT(!HasStackOverflow()); | 5106 ASSERT(!HasStackOverflow()); |
5271 ASSERT(current_block() != NULL); | 5107 ASSERT(current_block() != NULL); |
5272 ASSERT(current_block()->HasPredecessor()); | 5108 ASSERT(current_block()->HasPredecessor()); |
5273 ZoneList<Expression*>* subexprs = expr->values(); | 5109 ZoneList<Expression*>* subexprs = expr->values(); |
5274 int length = subexprs->length(); | 5110 int length = subexprs->length(); |
5275 HValue* context = environment()->LookupContext(); | 5111 HValue* context = environment()->LookupContext(); |
5276 HInstruction* literal; | 5112 HInstruction* literal; |
5277 | 5113 |
5278 Handle<FixedArray> literals(environment()->closure()->literals()); | 5114 Handle<FixedArray> literals(environment()->closure()->literals()); |
5279 Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); | 5115 Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5393 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); | 5229 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); |
5394 if (lookup->IsField()) { | 5230 if (lookup->IsField()) { |
5395 return lookup->GetLocalFieldIndexFromMap(*type); | 5231 return lookup->GetLocalFieldIndexFromMap(*type); |
5396 } else { | 5232 } else { |
5397 Map* transition = lookup->GetTransitionMapFromMap(*type); | 5233 Map* transition = lookup->GetTransitionMapFromMap(*type); |
5398 return transition->PropertyIndexFor(*name) - type->inobject_properties(); | 5234 return transition->PropertyIndexFor(*name) - type->inobject_properties(); |
5399 } | 5235 } |
5400 } | 5236 } |
5401 | 5237 |
5402 | 5238 |
5403 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, | 5239 void HGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
5404 Handle<Map> map) { | 5240 Handle<Map> map) { |
5405 AddInstruction(new(zone()) HCheckNonSmi(object)); | 5241 AddInstruction(new(zone()) HCheckNonSmi(object)); |
5406 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | 5242 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
5407 } | 5243 } |
5408 | 5244 |
5409 | 5245 |
5410 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 5246 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, |
5411 HValue* object, | 5247 Handle<String> name, |
5412 Handle<String> name, | 5248 HValue* value, |
5413 HValue* value, | 5249 Handle<Map> map, |
5414 Handle<Map> map, | 5250 LookupResult* lookup) { |
5415 LookupResult* lookup) { | |
5416 ASSERT(lookup->IsFound()); | 5251 ASSERT(lookup->IsFound()); |
5417 // If the property does not exist yet, we have to check that it wasn't made | 5252 // If the property does not exist yet, we have to check that it wasn't made |
5418 // readonly or turned into a setter by some meanwhile modifications on the | 5253 // readonly or turned into a setter by some meanwhile modifications on the |
5419 // prototype chain. | 5254 // prototype chain. |
5420 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { | 5255 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { |
5421 Object* proto = map->prototype(); | 5256 Object* proto = map->prototype(); |
5422 // First check that the prototype chain isn't affected already. | 5257 // First check that the prototype chain isn't affected already. |
5423 LookupResult proto_result(isolate()); | 5258 LookupResult proto_result(isolate()); |
5424 proto->Lookup(*name, &proto_result); | 5259 proto->Lookup(*name, &proto_result); |
5425 if (proto_result.IsProperty()) { | 5260 if (proto_result.IsProperty()) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5457 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 5292 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
5458 instr->set_transition(transition); | 5293 instr->set_transition(transition); |
5459 // TODO(fschneider): Record the new map type of the object in the IR to | 5294 // TODO(fschneider): Record the new map type of the object in the IR to |
5460 // enable elimination of redundant checks after the transition store. | 5295 // enable elimination of redundant checks after the transition store. |
5461 instr->SetGVNFlag(kChangesMaps); | 5296 instr->SetGVNFlag(kChangesMaps); |
5462 } | 5297 } |
5463 return instr; | 5298 return instr; |
5464 } | 5299 } |
5465 | 5300 |
5466 | 5301 |
5467 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( | 5302 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, |
5468 HValue* object, | 5303 Handle<String> name, |
5469 Handle<String> name, | 5304 HValue* value) { |
5470 HValue* value) { | |
5471 HValue* context = environment()->LookupContext(); | 5305 HValue* context = environment()->LookupContext(); |
5472 return new(zone()) HStoreNamedGeneric( | 5306 return new(zone()) HStoreNamedGeneric( |
5473 context, | 5307 context, |
5474 object, | 5308 object, |
5475 name, | 5309 name, |
5476 value, | 5310 value, |
5477 function_strict_mode_flag()); | 5311 function_strict_mode_flag()); |
5478 } | 5312 } |
5479 | 5313 |
5480 | 5314 |
5481 HInstruction* HOptimizedGraphBuilder::BuildCallSetter( | 5315 HInstruction* HGraphBuilder::BuildCallSetter(HValue* object, |
5482 HValue* object, | 5316 HValue* value, |
5483 HValue* value, | 5317 Handle<Map> map, |
5484 Handle<Map> map, | 5318 Handle<JSFunction> setter, |
5485 Handle<JSFunction> setter, | 5319 Handle<JSObject> holder) { |
5486 Handle<JSObject> holder) { | |
5487 AddCheckConstantFunction(holder, object, map); | 5320 AddCheckConstantFunction(holder, object, map); |
5488 AddInstruction(new(zone()) HPushArgument(object)); | 5321 AddInstruction(new(zone()) HPushArgument(object)); |
5489 AddInstruction(new(zone()) HPushArgument(value)); | 5322 AddInstruction(new(zone()) HPushArgument(value)); |
5490 return new(zone()) HCallConstantFunction(setter, 2); | 5323 return new(zone()) HCallConstantFunction(setter, 2); |
5491 } | 5324 } |
5492 | 5325 |
5493 | 5326 |
5494 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( | 5327 HInstruction* HGraphBuilder::BuildStoreNamedMonomorphic(HValue* object, |
5495 HValue* object, | 5328 Handle<String> name, |
5496 Handle<String> name, | 5329 HValue* value, |
5497 HValue* value, | 5330 Handle<Map> map) { |
5498 Handle<Map> map) { | |
5499 // Handle a store to a known field. | 5331 // Handle a store to a known field. |
5500 LookupResult lookup(isolate()); | 5332 LookupResult lookup(isolate()); |
5501 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 5333 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
5502 AddCheckMapsWithTransitions(object, map); | 5334 AddCheckMapsWithTransitions(object, map); |
5503 return BuildStoreNamedField(object, name, value, map, &lookup); | 5335 return BuildStoreNamedField(object, name, value, map, &lookup); |
5504 } | 5336 } |
5505 | 5337 |
5506 // No luck, do a generic store. | 5338 // No luck, do a generic store. |
5507 return BuildStoreNamedGeneric(object, name, value); | 5339 return BuildStoreNamedGeneric(object, name, value); |
5508 } | 5340 } |
5509 | 5341 |
5510 | 5342 |
5511 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 5343 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
5512 Property* expr, | 5344 HValue* object, |
5513 HValue* object, | 5345 SmallMapList* types, |
5514 SmallMapList* types, | 5346 Handle<String> name) { |
5515 Handle<String> name) { | |
5516 int count = 0; | 5347 int count = 0; |
5517 int previous_field_offset = 0; | 5348 int previous_field_offset = 0; |
5518 bool previous_field_is_in_object = false; | 5349 bool previous_field_is_in_object = false; |
5519 bool is_monomorphic_field = true; | 5350 bool is_monomorphic_field = true; |
5520 Handle<Map> map; | 5351 Handle<Map> map; |
5521 LookupResult lookup(isolate()); | 5352 LookupResult lookup(isolate()); |
5522 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 5353 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
5523 map = types->at(i); | 5354 map = types->at(i); |
5524 if (ComputeLoadStoreField(map, name, &lookup, false)) { | 5355 if (ComputeLoadStoreField(map, name, &lookup, false)) { |
5525 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); | 5356 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5557 types, | 5388 types, |
5558 name, | 5389 name, |
5559 zone()); | 5390 zone()); |
5560 } | 5391 } |
5561 | 5392 |
5562 instr->set_position(expr->position()); | 5393 instr->set_position(expr->position()); |
5563 return ast_context()->ReturnInstruction(instr, expr->id()); | 5394 return ast_context()->ReturnInstruction(instr, expr->id()); |
5564 } | 5395 } |
5565 | 5396 |
5566 | 5397 |
5567 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 5398 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, |
5568 Assignment* expr, | 5399 HValue* object, |
5569 HValue* object, | 5400 HValue* value, |
5570 HValue* value, | 5401 SmallMapList* types, |
5571 SmallMapList* types, | 5402 Handle<String> name) { |
5572 Handle<String> name) { | |
5573 // TODO(ager): We should recognize when the prototype chains for different | 5403 // TODO(ager): We should recognize when the prototype chains for different |
5574 // maps are identical. In that case we can avoid repeatedly generating the | 5404 // maps are identical. In that case we can avoid repeatedly generating the |
5575 // same prototype map checks. | 5405 // same prototype map checks. |
5576 int count = 0; | 5406 int count = 0; |
5577 HBasicBlock* join = NULL; | 5407 HBasicBlock* join = NULL; |
5578 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 5408 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
5579 Handle<Map> map = types->at(i); | 5409 Handle<Map> map = types->at(i); |
5580 LookupResult lookup(isolate()); | 5410 LookupResult lookup(isolate()); |
5581 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 5411 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
5582 if (count == 0) { | 5412 if (count == 0) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5634 } | 5464 } |
5635 } | 5465 } |
5636 | 5466 |
5637 ASSERT(join != NULL); | 5467 ASSERT(join != NULL); |
5638 join->SetJoinId(expr->id()); | 5468 join->SetJoinId(expr->id()); |
5639 set_current_block(join); | 5469 set_current_block(join); |
5640 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 5470 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
5641 } | 5471 } |
5642 | 5472 |
5643 | 5473 |
5644 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 5474 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
5645 Property* prop = expr->target()->AsProperty(); | 5475 Property* prop = expr->target()->AsProperty(); |
5646 ASSERT(prop != NULL); | 5476 ASSERT(prop != NULL); |
5647 expr->RecordTypeFeedback(oracle(), zone()); | 5477 expr->RecordTypeFeedback(oracle(), zone()); |
5648 CHECK_ALIVE(VisitForValue(prop->obj())); | 5478 CHECK_ALIVE(VisitForValue(prop->obj())); |
5649 | 5479 |
5650 if (prop->key()->IsPropertyName()) { | 5480 if (prop->key()->IsPropertyName()) { |
5651 // Named store. | 5481 // Named store. |
5652 CHECK_ALIVE(VisitForValue(expr->value())); | 5482 CHECK_ALIVE(VisitForValue(expr->value())); |
5653 HValue* value = environment()->ExpressionStackAt(0); | 5483 HValue* value = environment()->ExpressionStackAt(0); |
5654 HValue* object = environment()->ExpressionStackAt(1); | 5484 HValue* object = environment()->ExpressionStackAt(1); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5717 ASSERT(has_side_effects); // Stores always have side effects. | 5547 ASSERT(has_side_effects); // Stores always have side effects. |
5718 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5548 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5719 return ast_context()->ReturnValue(Pop()); | 5549 return ast_context()->ReturnValue(Pop()); |
5720 } | 5550 } |
5721 } | 5551 } |
5722 | 5552 |
5723 | 5553 |
5724 // Because not every expression has a position and there is not common | 5554 // Because not every expression has a position and there is not common |
5725 // superclass of Assignment and CountOperation, we cannot just pass the | 5555 // superclass of Assignment and CountOperation, we cannot just pass the |
5726 // owning expression instead of position and ast_id separately. | 5556 // owning expression instead of position and ast_id separately. |
5727 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 5557 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
5728 Variable* var, | 5558 HValue* value, |
5729 HValue* value, | 5559 int position, |
5730 int position, | 5560 BailoutId ast_id) { |
5731 BailoutId ast_id) { | |
5732 LookupResult lookup(isolate()); | 5561 LookupResult lookup(isolate()); |
5733 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 5562 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
5734 if (type == kUseCell) { | 5563 if (type == kUseCell) { |
5735 Handle<GlobalObject> global(info()->global_object()); | 5564 Handle<GlobalObject> global(info()->global_object()); |
5736 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 5565 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
5737 HInstruction* instr = | 5566 HInstruction* instr = |
5738 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); | 5567 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); |
5739 instr->set_position(position); | 5568 instr->set_position(position); |
5740 AddInstruction(instr); | 5569 AddInstruction(instr); |
5741 if (instr->HasObservableSideEffects()) { | 5570 if (instr->HasObservableSideEffects()) { |
(...skipping 10 matching lines...) Expand all Loading... |
5752 value, | 5581 value, |
5753 function_strict_mode_flag()); | 5582 function_strict_mode_flag()); |
5754 instr->set_position(position); | 5583 instr->set_position(position); |
5755 AddInstruction(instr); | 5584 AddInstruction(instr); |
5756 ASSERT(instr->HasObservableSideEffects()); | 5585 ASSERT(instr->HasObservableSideEffects()); |
5757 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 5586 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
5758 } | 5587 } |
5759 } | 5588 } |
5760 | 5589 |
5761 | 5590 |
5762 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5591 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
5763 Expression* target = expr->target(); | 5592 Expression* target = expr->target(); |
5764 VariableProxy* proxy = target->AsVariableProxy(); | 5593 VariableProxy* proxy = target->AsVariableProxy(); |
5765 Property* prop = target->AsProperty(); | 5594 Property* prop = target->AsProperty(); |
5766 ASSERT(proxy == NULL || prop == NULL); | 5595 ASSERT(proxy == NULL || prop == NULL); |
5767 | 5596 |
5768 // We have a second position recorded in the FullCodeGenerator to have | 5597 // We have a second position recorded in the FullCodeGenerator to have |
5769 // type feedback for the binary operation. | 5598 // type feedback for the binary operation. |
5770 BinaryOperation* operation = expr->binary_operation(); | 5599 BinaryOperation* operation = expr->binary_operation(); |
5771 | 5600 |
5772 if (proxy != NULL) { | 5601 if (proxy != NULL) { |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5949 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5778 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5950 return ast_context()->ReturnValue(Pop()); | 5779 return ast_context()->ReturnValue(Pop()); |
5951 } | 5780 } |
5952 | 5781 |
5953 } else { | 5782 } else { |
5954 return Bailout("invalid lhs in compound assignment"); | 5783 return Bailout("invalid lhs in compound assignment"); |
5955 } | 5784 } |
5956 } | 5785 } |
5957 | 5786 |
5958 | 5787 |
5959 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 5788 void HGraphBuilder::VisitAssignment(Assignment* expr) { |
5960 ASSERT(!HasStackOverflow()); | 5789 ASSERT(!HasStackOverflow()); |
5961 ASSERT(current_block() != NULL); | 5790 ASSERT(current_block() != NULL); |
5962 ASSERT(current_block()->HasPredecessor()); | 5791 ASSERT(current_block()->HasPredecessor()); |
5963 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 5792 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
5964 Property* prop = expr->target()->AsProperty(); | 5793 Property* prop = expr->target()->AsProperty(); |
5965 ASSERT(proxy == NULL || prop == NULL); | 5794 ASSERT(proxy == NULL || prop == NULL); |
5966 | 5795 |
5967 if (expr->is_compound()) { | 5796 if (expr->is_compound()) { |
5968 HandleCompoundAssignment(expr); | 5797 HandleCompoundAssignment(expr); |
5969 return; | 5798 return; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6076 | 5905 |
6077 case Variable::LOOKUP: | 5906 case Variable::LOOKUP: |
6078 return Bailout("assignment to LOOKUP variable"); | 5907 return Bailout("assignment to LOOKUP variable"); |
6079 } | 5908 } |
6080 } else { | 5909 } else { |
6081 return Bailout("invalid left-hand side in assignment"); | 5910 return Bailout("invalid left-hand side in assignment"); |
6082 } | 5911 } |
6083 } | 5912 } |
6084 | 5913 |
6085 | 5914 |
6086 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { | 5915 void HGraphBuilder::VisitThrow(Throw* expr) { |
6087 ASSERT(!HasStackOverflow()); | 5916 ASSERT(!HasStackOverflow()); |
6088 ASSERT(current_block() != NULL); | 5917 ASSERT(current_block() != NULL); |
6089 ASSERT(current_block()->HasPredecessor()); | 5918 ASSERT(current_block()->HasPredecessor()); |
6090 // We don't optimize functions with invalid left-hand sides in | 5919 // We don't optimize functions with invalid left-hand sides in |
6091 // assignments, count operations, or for-in. Consequently throw can | 5920 // assignments, count operations, or for-in. Consequently throw can |
6092 // currently only occur in an effect context. | 5921 // currently only occur in an effect context. |
6093 ASSERT(ast_context()->IsEffect()); | 5922 ASSERT(ast_context()->IsEffect()); |
6094 CHECK_ALIVE(VisitForValue(expr->exception())); | 5923 CHECK_ALIVE(VisitForValue(expr->exception())); |
6095 | 5924 |
6096 HValue* context = environment()->LookupContext(); | 5925 HValue* context = environment()->LookupContext(); |
6097 HValue* value = environment()->Pop(); | 5926 HValue* value = environment()->Pop(); |
6098 HThrow* instr = new(zone()) HThrow(context, value); | 5927 HThrow* instr = new(zone()) HThrow(context, value); |
6099 instr->set_position(expr->position()); | 5928 instr->set_position(expr->position()); |
6100 AddInstruction(instr); | 5929 AddInstruction(instr); |
6101 AddSimulate(expr->id()); | 5930 AddSimulate(expr->id()); |
6102 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5931 current_block()->FinishExit(new(zone()) HAbnormalExit); |
6103 set_current_block(NULL); | 5932 set_current_block(NULL); |
6104 } | 5933 } |
6105 | 5934 |
6106 | 5935 |
6107 HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField( | 5936 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
6108 HValue* object, | 5937 Handle<Map> map, |
6109 Handle<Map> map, | 5938 LookupResult* lookup) { |
6110 LookupResult* lookup) { | |
6111 int index = lookup->GetLocalFieldIndexFromMap(*map); | 5939 int index = lookup->GetLocalFieldIndexFromMap(*map); |
6112 if (index < 0) { | 5940 if (index < 0) { |
6113 // Negative property indices are in-object properties, indexed | 5941 // Negative property indices are in-object properties, indexed |
6114 // from the end of the fixed part of the object. | 5942 // from the end of the fixed part of the object. |
6115 int offset = (index * kPointerSize) + map->instance_size(); | 5943 int offset = (index * kPointerSize) + map->instance_size(); |
6116 return new(zone()) HLoadNamedField(object, true, offset); | 5944 return new(zone()) HLoadNamedField(object, true, offset); |
6117 } else { | 5945 } else { |
6118 // Non-negative property indices are in the properties array. | 5946 // Non-negative property indices are in the properties array. |
6119 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 5947 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
6120 return new(zone()) HLoadNamedField(object, false, offset); | 5948 return new(zone()) HLoadNamedField(object, false, offset); |
6121 } | 5949 } |
6122 } | 5950 } |
6123 | 5951 |
6124 | 5952 |
6125 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5953 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* object, |
6126 HValue* object, | 5954 Handle<String> name, |
6127 Handle<String> name, | 5955 Property* expr) { |
6128 Property* expr) { | |
6129 if (expr->IsUninitialized() && !FLAG_always_opt) { | 5956 if (expr->IsUninitialized() && !FLAG_always_opt) { |
6130 AddInstruction(new(zone()) HSoftDeoptimize); | 5957 AddInstruction(new(zone()) HSoftDeoptimize); |
6131 current_block()->MarkAsDeoptimizing(); | 5958 current_block()->MarkAsDeoptimizing(); |
6132 } | 5959 } |
6133 HValue* context = environment()->LookupContext(); | 5960 HValue* context = environment()->LookupContext(); |
6134 return new(zone()) HLoadNamedGeneric(context, object, name); | 5961 return new(zone()) HLoadNamedGeneric(context, object, name); |
6135 } | 5962 } |
6136 | 5963 |
6137 | 5964 |
6138 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 5965 HInstruction* HGraphBuilder::BuildCallGetter(HValue* object, |
6139 HValue* object, | 5966 Handle<Map> map, |
6140 Handle<Map> map, | 5967 Handle<JSFunction> getter, |
6141 Handle<JSFunction> getter, | 5968 Handle<JSObject> holder) { |
6142 Handle<JSObject> holder) { | |
6143 AddCheckConstantFunction(holder, object, map); | 5969 AddCheckConstantFunction(holder, object, map); |
6144 AddInstruction(new(zone()) HPushArgument(object)); | 5970 AddInstruction(new(zone()) HPushArgument(object)); |
6145 return new(zone()) HCallConstantFunction(getter, 1); | 5971 return new(zone()) HCallConstantFunction(getter, 1); |
6146 } | 5972 } |
6147 | 5973 |
6148 | 5974 |
6149 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( | 5975 HInstruction* HGraphBuilder::BuildLoadNamedMonomorphic(HValue* object, |
6150 HValue* object, | 5976 Handle<String> name, |
6151 Handle<String> name, | 5977 Property* expr, |
6152 Property* expr, | 5978 Handle<Map> map) { |
6153 Handle<Map> map) { | |
6154 // Handle a load from a known field. | 5979 // Handle a load from a known field. |
6155 ASSERT(!map->is_dictionary_map()); | 5980 ASSERT(!map->is_dictionary_map()); |
6156 LookupResult lookup(isolate()); | 5981 LookupResult lookup(isolate()); |
6157 map->LookupDescriptor(NULL, *name, &lookup); | 5982 map->LookupDescriptor(NULL, *name, &lookup); |
6158 if (lookup.IsField()) { | 5983 if (lookup.IsField()) { |
6159 AddCheckMapsWithTransitions(object, map); | 5984 AddCheckMapsWithTransitions(object, map); |
6160 return BuildLoadNamedField(object, map, &lookup); | 5985 return BuildLoadNamedField(object, map, &lookup); |
6161 } | 5986 } |
6162 | 5987 |
6163 // Handle a load of a constant known function. | 5988 // Handle a load of a constant known function. |
(...skipping 13 matching lines...) Expand all Loading... |
6177 HInstruction* holder_value = | 6002 HInstruction* holder_value = |
6178 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder)); | 6003 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder)); |
6179 return BuildLoadNamedField(holder_value, holder_map, &lookup); | 6004 return BuildLoadNamedField(holder_value, holder_map, &lookup); |
6180 } | 6005 } |
6181 | 6006 |
6182 // No luck, do a generic load. | 6007 // No luck, do a generic load. |
6183 return BuildLoadNamedGeneric(object, name, expr); | 6008 return BuildLoadNamedGeneric(object, name, expr); |
6184 } | 6009 } |
6185 | 6010 |
6186 | 6011 |
6187 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 6012 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
6188 HValue* key) { | 6013 HValue* key) { |
6189 HValue* context = environment()->LookupContext(); | 6014 HValue* context = environment()->LookupContext(); |
6190 return new(zone()) HLoadKeyedGeneric(context, object, key); | 6015 return new(zone()) HLoadKeyedGeneric(context, object, key); |
6191 } | 6016 } |
6192 | 6017 |
6193 | 6018 |
6194 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 6019 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( |
6195 HValue* object, | 6020 HValue* external_elements, |
6196 HValue* key, | 6021 HValue* checked_key, |
6197 HValue* val, | 6022 HValue* val, |
6198 HValue* dependency, | 6023 HValue* dependency, |
6199 Handle<Map> map, | 6024 ElementsKind elements_kind, |
6200 bool is_store) { | 6025 bool is_store) { |
| 6026 if (is_store) { |
| 6027 ASSERT(val != NULL); |
| 6028 switch (elements_kind) { |
| 6029 case EXTERNAL_PIXEL_ELEMENTS: { |
| 6030 val = AddInstruction(new(zone()) HClampToUint8(val)); |
| 6031 break; |
| 6032 } |
| 6033 case EXTERNAL_BYTE_ELEMENTS: |
| 6034 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 6035 case EXTERNAL_SHORT_ELEMENTS: |
| 6036 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 6037 case EXTERNAL_INT_ELEMENTS: |
| 6038 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 6039 break; |
| 6040 } |
| 6041 case EXTERNAL_FLOAT_ELEMENTS: |
| 6042 case EXTERNAL_DOUBLE_ELEMENTS: |
| 6043 break; |
| 6044 case FAST_SMI_ELEMENTS: |
| 6045 case FAST_ELEMENTS: |
| 6046 case FAST_DOUBLE_ELEMENTS: |
| 6047 case FAST_HOLEY_SMI_ELEMENTS: |
| 6048 case FAST_HOLEY_ELEMENTS: |
| 6049 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 6050 case DICTIONARY_ELEMENTS: |
| 6051 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 6052 UNREACHABLE(); |
| 6053 break; |
| 6054 } |
| 6055 return new(zone()) HStoreKeyed(external_elements, |
| 6056 checked_key, |
| 6057 val, |
| 6058 elements_kind); |
| 6059 } else { |
| 6060 ASSERT(val == NULL); |
| 6061 HLoadKeyed* load = |
| 6062 new(zone()) HLoadKeyed( |
| 6063 external_elements, checked_key, dependency, elements_kind); |
| 6064 if (FLAG_opt_safe_uint32_operations && |
| 6065 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 6066 graph()->RecordUint32Instruction(load); |
| 6067 } |
| 6068 return load; |
| 6069 } |
| 6070 } |
| 6071 |
| 6072 |
| 6073 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, |
| 6074 HValue* checked_key, |
| 6075 HValue* val, |
| 6076 HValue* load_dependency, |
| 6077 ElementsKind elements_kind, |
| 6078 bool is_store) { |
| 6079 if (is_store) { |
| 6080 ASSERT(val != NULL); |
| 6081 switch (elements_kind) { |
| 6082 case FAST_SMI_ELEMENTS: |
| 6083 case FAST_HOLEY_SMI_ELEMENTS: |
| 6084 // Smi-only arrays need a smi check. |
| 6085 AddInstruction(new(zone()) HCheckSmi(val)); |
| 6086 // Fall through. |
| 6087 case FAST_ELEMENTS: |
| 6088 case FAST_HOLEY_ELEMENTS: |
| 6089 case FAST_DOUBLE_ELEMENTS: |
| 6090 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 6091 return new(zone()) HStoreKeyed( |
| 6092 elements, checked_key, val, elements_kind); |
| 6093 default: |
| 6094 UNREACHABLE(); |
| 6095 return NULL; |
| 6096 } |
| 6097 } |
| 6098 // It's an element load (!is_store). |
| 6099 return new(zone()) HLoadKeyed(elements, |
| 6100 checked_key, |
| 6101 load_dependency, |
| 6102 elements_kind); |
| 6103 } |
| 6104 |
| 6105 |
| 6106 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, |
| 6107 HValue* key, |
| 6108 HValue* val, |
| 6109 HValue* dependency, |
| 6110 Handle<Map> map, |
| 6111 bool is_store) { |
6201 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, | 6112 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, |
6202 zone(), dependency); | 6113 zone(), dependency); |
6203 AddInstruction(mapcheck); | 6114 AddInstruction(mapcheck); |
6204 if (dependency) { | 6115 if (dependency) { |
6205 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 6116 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
6206 } | 6117 } |
6207 return BuildUncheckedMonomorphicElementAccess( | 6118 return BuildUncheckedMonomorphicElementAccess(object, key, val, |
6208 object, key, val, | 6119 mapcheck, map, is_store); |
6209 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | |
6210 map->elements_kind(), is_store); | |
6211 } | 6120 } |
6212 | 6121 |
6213 | 6122 |
6214 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( | 6123 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
6215 HValue* object, | 6124 HValue* object, |
6216 HValue* key, | 6125 HValue* key, |
6217 HValue* val, | 6126 HValue* val, |
| 6127 HCheckMaps* mapcheck, |
| 6128 Handle<Map> map, |
| 6129 bool is_store) { |
| 6130 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
| 6131 // on a HElementsTransition instruction. The flag can also be removed if the |
| 6132 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
| 6133 // ElementsKind transitions. Finally, the dependency can be removed for stores |
| 6134 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
| 6135 // generated store code. |
| 6136 if ((map->elements_kind() == FAST_HOLEY_ELEMENTS) || |
| 6137 (map->elements_kind() == FAST_ELEMENTS && is_store)) { |
| 6138 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
| 6139 } |
| 6140 bool fast_smi_only_elements = map->has_fast_smi_elements(); |
| 6141 bool fast_elements = map->has_fast_object_elements(); |
| 6142 HInstruction* elements = |
| 6143 AddInstruction(new(zone()) HLoadElements(object, mapcheck)); |
| 6144 if (is_store && (fast_elements || fast_smi_only_elements)) { |
| 6145 HCheckMaps* check_cow_map = new(zone()) HCheckMaps( |
| 6146 elements, isolate()->factory()->fixed_array_map(), zone()); |
| 6147 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 6148 AddInstruction(check_cow_map); |
| 6149 } |
| 6150 HInstruction* length = NULL; |
| 6151 HInstruction* checked_key = NULL; |
| 6152 if (map->has_external_array_elements()) { |
| 6153 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
| 6154 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, |
| 6155 ALLOW_SMI_KEY)); |
| 6156 HLoadExternalArrayPointer* external_elements = |
| 6157 new(zone()) HLoadExternalArrayPointer(elements); |
| 6158 AddInstruction(external_elements); |
| 6159 return BuildExternalArrayElementAccess( |
| 6160 external_elements, checked_key, val, mapcheck, |
| 6161 map->elements_kind(), is_store); |
| 6162 } |
| 6163 ASSERT(fast_smi_only_elements || |
| 6164 fast_elements || |
| 6165 map->has_fast_double_elements()); |
| 6166 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 6167 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck, |
| 6168 HType::Smi())); |
| 6169 } else { |
| 6170 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
| 6171 } |
| 6172 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, |
| 6173 ALLOW_SMI_KEY)); |
| 6174 return BuildFastElementAccess(elements, checked_key, val, mapcheck, |
| 6175 map->elements_kind(), is_store); |
| 6176 } |
| 6177 |
| 6178 |
| 6179 HInstruction* HGraphBuilder::TryBuildConsolidatedElementLoad( |
| 6180 HValue* object, |
| 6181 HValue* key, |
| 6182 HValue* val, |
6218 SmallMapList* maps) { | 6183 SmallMapList* maps) { |
6219 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | 6184 // For polymorphic loads of similar elements kinds (i.e. all tagged or all |
6220 // double), always use the "worst case" code without a transition. This is | 6185 // double), always use the "worst case" code without a transition. This is |
6221 // much faster than transitioning the elements to the worst case, trading a | 6186 // much faster than transitioning the elements to the worst case, trading a |
6222 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. | 6187 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. |
6223 bool has_double_maps = false; | 6188 bool has_double_maps = false; |
6224 bool has_smi_or_object_maps = false; | 6189 bool has_smi_or_object_maps = false; |
6225 bool has_js_array_access = false; | 6190 bool has_js_array_access = false; |
6226 bool has_non_js_array_access = false; | 6191 bool has_non_js_array_access = false; |
6227 Handle<Map> most_general_consolidated_map; | 6192 Handle<Map> most_general_consolidated_map; |
(...skipping 24 matching lines...) Expand all Loading... |
6252 most_general_consolidated_map->elements_kind(), | 6217 most_general_consolidated_map->elements_kind(), |
6253 map->elements_kind())) { | 6218 map->elements_kind())) { |
6254 most_general_consolidated_map = map; | 6219 most_general_consolidated_map = map; |
6255 } | 6220 } |
6256 } | 6221 } |
6257 if (!has_double_maps && !has_smi_or_object_maps) return NULL; | 6222 if (!has_double_maps && !has_smi_or_object_maps) return NULL; |
6258 | 6223 |
6259 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); | 6224 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); |
6260 AddInstruction(check_maps); | 6225 AddInstruction(check_maps); |
6261 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 6226 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
6262 object, key, val, check_maps, | 6227 object, key, val, check_maps, most_general_consolidated_map, false); |
6263 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | |
6264 most_general_consolidated_map->elements_kind(), | |
6265 false); | |
6266 return instr; | 6228 return instr; |
6267 } | 6229 } |
6268 | 6230 |
6269 | 6231 |
6270 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 6232 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, |
6271 HValue* object, | 6233 HValue* key, |
6272 HValue* key, | 6234 HValue* val, |
6273 HValue* val, | 6235 Expression* prop, |
6274 Expression* prop, | 6236 BailoutId ast_id, |
6275 BailoutId ast_id, | 6237 int position, |
6276 int position, | 6238 bool is_store, |
6277 bool is_store, | 6239 bool* has_side_effects) { |
6278 bool* has_side_effects) { | |
6279 *has_side_effects = false; | 6240 *has_side_effects = false; |
6280 AddInstruction(new(zone()) HCheckNonSmi(object)); | 6241 AddInstruction(new(zone()) HCheckNonSmi(object)); |
6281 SmallMapList* maps = prop->GetReceiverTypes(); | 6242 SmallMapList* maps = prop->GetReceiverTypes(); |
6282 bool todo_external_array = false; | 6243 bool todo_external_array = false; |
6283 | 6244 |
6284 if (!is_store) { | 6245 if (!is_store) { |
6285 HInstruction* consolidated_load = | 6246 HInstruction* consolidated_load = |
6286 TryBuildConsolidatedElementLoad(object, key, val, maps); | 6247 TryBuildConsolidatedElementLoad(object, key, val, maps); |
6287 if (consolidated_load != NULL) { | 6248 if (consolidated_load != NULL) { |
6288 AddInstruction(consolidated_load); | 6249 AddInstruction(consolidated_load); |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6453 elements, checked_key, val, elements_kind_branch, | 6414 elements, checked_key, val, elements_kind_branch, |
6454 elements_kind, is_store)); | 6415 elements_kind, is_store)); |
6455 } else if (elements_kind == DICTIONARY_ELEMENTS) { | 6416 } else if (elements_kind == DICTIONARY_ELEMENTS) { |
6456 if (is_store) { | 6417 if (is_store) { |
6457 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 6418 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
6458 } else { | 6419 } else { |
6459 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 6420 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
6460 } | 6421 } |
6461 } else { // External array elements. | 6422 } else { // External array elements. |
6462 access = AddInstruction(BuildExternalArrayElementAccess( | 6423 access = AddInstruction(BuildExternalArrayElementAccess( |
6463 external_elements, checked_key, val, | 6424 external_elements, checked_key, val, elements_kind_branch, |
6464 elements_kind_branch, elements_kind, is_store)); | 6425 elements_kind, is_store)); |
6465 } | 6426 } |
6466 *has_side_effects |= access->HasObservableSideEffects(); | 6427 *has_side_effects |= access->HasObservableSideEffects(); |
6467 if (position != RelocInfo::kNoPosition) access->set_position(position); | 6428 if (position != RelocInfo::kNoPosition) access->set_position(position); |
6468 if (!is_store) { | 6429 if (!is_store) { |
6469 Push(access); | 6430 Push(access); |
6470 } | 6431 } |
6471 current_block()->Goto(join); | 6432 current_block()->Goto(join); |
6472 set_current_block(if_false); | 6433 set_current_block(if_false); |
6473 } | 6434 } |
6474 } | 6435 } |
6475 | 6436 |
6476 // Deopt if none of the cases matched. | 6437 // Deopt if none of the cases matched. |
6477 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 6438 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); |
6478 join->SetJoinId(ast_id); | 6439 join->SetJoinId(ast_id); |
6479 set_current_block(join); | 6440 set_current_block(join); |
6480 return is_store ? NULL : Pop(); | 6441 return is_store ? NULL : Pop(); |
6481 } | 6442 } |
6482 | 6443 |
6483 | 6444 |
6484 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 6445 HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj, |
6485 HValue* obj, | 6446 HValue* key, |
6486 HValue* key, | 6447 HValue* val, |
6487 HValue* val, | 6448 Expression* expr, |
6488 Expression* expr, | 6449 BailoutId ast_id, |
6489 BailoutId ast_id, | 6450 int position, |
6490 int position, | 6451 bool is_store, |
6491 bool is_store, | 6452 bool* has_side_effects) { |
6492 bool* has_side_effects) { | |
6493 ASSERT(!expr->IsPropertyName()); | 6453 ASSERT(!expr->IsPropertyName()); |
6494 HInstruction* instr = NULL; | 6454 HInstruction* instr = NULL; |
6495 if (expr->IsMonomorphic()) { | 6455 if (expr->IsMonomorphic()) { |
6496 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 6456 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
6497 if (map->has_slow_elements_kind()) { | 6457 if (map->has_slow_elements_kind()) { |
6498 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 6458 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
6499 : BuildLoadKeyedGeneric(obj, key); | 6459 : BuildLoadKeyedGeneric(obj, key); |
6500 } else { | 6460 } else { |
6501 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 6461 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
6502 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); | 6462 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); |
6503 } | 6463 } |
6504 } else if (expr->GetReceiverTypes() != NULL && | 6464 } else if (expr->GetReceiverTypes() != NULL && |
6505 !expr->GetReceiverTypes()->is_empty()) { | 6465 !expr->GetReceiverTypes()->is_empty()) { |
6506 return HandlePolymorphicElementAccess( | 6466 return HandlePolymorphicElementAccess( |
6507 obj, key, val, expr, ast_id, position, is_store, has_side_effects); | 6467 obj, key, val, expr, ast_id, position, is_store, has_side_effects); |
6508 } else { | 6468 } else { |
6509 if (is_store) { | 6469 if (is_store) { |
6510 instr = BuildStoreKeyedGeneric(obj, key, val); | 6470 instr = BuildStoreKeyedGeneric(obj, key, val); |
6511 } else { | 6471 } else { |
6512 instr = BuildLoadKeyedGeneric(obj, key); | 6472 instr = BuildLoadKeyedGeneric(obj, key); |
6513 } | 6473 } |
6514 } | 6474 } |
6515 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 6475 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
6516 AddInstruction(instr); | 6476 AddInstruction(instr); |
6517 *has_side_effects = instr->HasObservableSideEffects(); | 6477 *has_side_effects = instr->HasObservableSideEffects(); |
6518 return instr; | 6478 return instr; |
6519 } | 6479 } |
6520 | 6480 |
6521 | 6481 |
6522 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( | 6482 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, |
6523 HValue* object, | 6483 HValue* key, |
6524 HValue* key, | 6484 HValue* value) { |
6525 HValue* value) { | |
6526 HValue* context = environment()->LookupContext(); | 6485 HValue* context = environment()->LookupContext(); |
6527 return new(zone()) HStoreKeyedGeneric( | 6486 return new(zone()) HStoreKeyedGeneric( |
6528 context, | 6487 context, |
6529 object, | 6488 object, |
6530 key, | 6489 key, |
6531 value, | 6490 value, |
6532 function_strict_mode_flag()); | 6491 function_strict_mode_flag()); |
6533 } | 6492 } |
6534 | 6493 |
6535 | 6494 |
6536 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { | 6495 void HGraphBuilder::EnsureArgumentsArePushedForAccess() { |
6537 // Outermost function already has arguments on the stack. | 6496 // Outermost function already has arguments on the stack. |
6538 if (function_state()->outer() == NULL) return; | 6497 if (function_state()->outer() == NULL) return; |
6539 | 6498 |
6540 if (function_state()->arguments_pushed()) return; | 6499 if (function_state()->arguments_pushed()) return; |
6541 | 6500 |
6542 // Push arguments when entering inlined function. | 6501 // Push arguments when entering inlined function. |
6543 HEnterInlined* entry = function_state()->entry(); | 6502 HEnterInlined* entry = function_state()->entry(); |
6544 entry->set_arguments_pushed(); | 6503 entry->set_arguments_pushed(); |
6545 | 6504 |
6546 ZoneList<HValue*>* arguments_values = entry->arguments_values(); | 6505 ZoneList<HValue*>* arguments_values = entry->arguments_values(); |
6547 | 6506 |
6548 HInstruction* insert_after = entry; | 6507 HInstruction* insert_after = entry; |
6549 for (int i = 0; i < arguments_values->length(); i++) { | 6508 for (int i = 0; i < arguments_values->length(); i++) { |
6550 HValue* argument = arguments_values->at(i); | 6509 HValue* argument = arguments_values->at(i); |
6551 HInstruction* push_argument = new(zone()) HPushArgument(argument); | 6510 HInstruction* push_argument = new(zone()) HPushArgument(argument); |
6552 push_argument->InsertAfter(insert_after); | 6511 push_argument->InsertAfter(insert_after); |
6553 insert_after = push_argument; | 6512 insert_after = push_argument; |
6554 } | 6513 } |
6555 | 6514 |
6556 HArgumentsElements* arguments_elements = | 6515 HArgumentsElements* arguments_elements = |
6557 new(zone()) HArgumentsElements(true); | 6516 new(zone()) HArgumentsElements(true); |
6558 arguments_elements->ClearFlag(HValue::kUseGVN); | 6517 arguments_elements->ClearFlag(HValue::kUseGVN); |
6559 arguments_elements->InsertAfter(insert_after); | 6518 arguments_elements->InsertAfter(insert_after); |
6560 function_state()->set_arguments_elements(arguments_elements); | 6519 function_state()->set_arguments_elements(arguments_elements); |
6561 } | 6520 } |
6562 | 6521 |
6563 | 6522 |
6564 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) { | 6523 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { |
6565 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 6524 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
6566 if (proxy == NULL) return false; | 6525 if (proxy == NULL) return false; |
6567 if (!proxy->var()->IsStackAllocated()) return false; | 6526 if (!proxy->var()->IsStackAllocated()) return false; |
6568 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { | 6527 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { |
6569 return false; | 6528 return false; |
6570 } | 6529 } |
6571 | 6530 |
6572 HInstruction* result = NULL; | 6531 HInstruction* result = NULL; |
6573 if (expr->key()->IsPropertyName()) { | 6532 if (expr->key()->IsPropertyName()) { |
6574 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6533 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6613 HInstruction* checked_key = | 6572 HInstruction* checked_key = |
6614 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 6573 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
6615 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 6574 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
6616 } | 6575 } |
6617 } | 6576 } |
6618 ast_context()->ReturnInstruction(result, expr->id()); | 6577 ast_context()->ReturnInstruction(result, expr->id()); |
6619 return true; | 6578 return true; |
6620 } | 6579 } |
6621 | 6580 |
6622 | 6581 |
6623 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 6582 void HGraphBuilder::VisitProperty(Property* expr) { |
6624 ASSERT(!HasStackOverflow()); | 6583 ASSERT(!HasStackOverflow()); |
6625 ASSERT(current_block() != NULL); | 6584 ASSERT(current_block() != NULL); |
6626 ASSERT(current_block()->HasPredecessor()); | 6585 ASSERT(current_block()->HasPredecessor()); |
6627 expr->RecordTypeFeedback(oracle(), zone()); | 6586 expr->RecordTypeFeedback(oracle(), zone()); |
6628 | 6587 |
6629 if (TryArgumentsAccess(expr)) return; | 6588 if (TryArgumentsAccess(expr)) return; |
6630 | 6589 |
6631 CHECK_ALIVE(VisitForValue(expr->obj())); | 6590 CHECK_ALIVE(VisitForValue(expr->obj())); |
6632 | 6591 |
6633 HInstruction* instr = NULL; | 6592 HInstruction* instr = NULL; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6704 Drop(1); | 6663 Drop(1); |
6705 } | 6664 } |
6706 } | 6665 } |
6707 return ast_context()->ReturnValue(load); | 6666 return ast_context()->ReturnValue(load); |
6708 } | 6667 } |
6709 instr->set_position(expr->position()); | 6668 instr->set_position(expr->position()); |
6710 return ast_context()->ReturnInstruction(instr, expr->id()); | 6669 return ast_context()->ReturnInstruction(instr, expr->id()); |
6711 } | 6670 } |
6712 | 6671 |
6713 | 6672 |
6714 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 6673 void HGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
6715 Handle<Map> receiver_map) { | 6674 Handle<Map> receiver_map) { |
6716 if (!holder.is_null()) { | 6675 if (!holder.is_null()) { |
6717 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6676 AddInstruction(new(zone()) HCheckPrototypeMaps( |
6718 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); | 6677 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); |
6719 } | 6678 } |
6720 } | 6679 } |
6721 | 6680 |
6722 | 6681 |
6723 void HOptimizedGraphBuilder::AddCheckConstantFunction( | 6682 void HGraphBuilder::AddCheckConstantFunction(Handle<JSObject> holder, |
6724 Handle<JSObject> holder, | 6683 HValue* receiver, |
6725 HValue* receiver, | 6684 Handle<Map> receiver_map) { |
6726 Handle<Map> receiver_map) { | |
6727 // Constant functions have the nice property that the map will change if they | 6685 // Constant functions have the nice property that the map will change if they |
6728 // are overwritten. Therefore it is enough to check the map of the holder and | 6686 // are overwritten. Therefore it is enough to check the map of the holder and |
6729 // its prototypes. | 6687 // its prototypes. |
6730 AddCheckMapsWithTransitions(receiver, receiver_map); | 6688 AddCheckMapsWithTransitions(receiver, receiver_map); |
6731 AddCheckPrototypeMaps(holder, receiver_map); | 6689 AddCheckPrototypeMaps(holder, receiver_map); |
6732 } | 6690 } |
6733 | 6691 |
6734 | 6692 |
6735 class FunctionSorter { | 6693 class FunctionSorter { |
6736 public: | 6694 public: |
(...skipping 21 matching lines...) Expand all Loading... |
6758 FunctionSorter const* function1 = reinterpret_cast<FunctionSorter const*>(a); | 6716 FunctionSorter const* function1 = reinterpret_cast<FunctionSorter const*>(a); |
6759 FunctionSorter const* function2 = reinterpret_cast<FunctionSorter const*>(b); | 6717 FunctionSorter const* function2 = reinterpret_cast<FunctionSorter const*>(b); |
6760 int diff = function1->ticks() - function2->ticks(); | 6718 int diff = function1->ticks() - function2->ticks(); |
6761 if (diff != 0) return -diff; | 6719 if (diff != 0) return -diff; |
6762 diff = function1->ast_length() - function2->ast_length(); | 6720 diff = function1->ast_length() - function2->ast_length(); |
6763 if (diff != 0) return diff; | 6721 if (diff != 0) return diff; |
6764 return function1->src_length() - function2->src_length(); | 6722 return function1->src_length() - function2->src_length(); |
6765 } | 6723 } |
6766 | 6724 |
6767 | 6725 |
6768 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( | 6726 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, |
6769 Call* expr, | 6727 HValue* receiver, |
6770 HValue* receiver, | 6728 SmallMapList* types, |
6771 SmallMapList* types, | 6729 Handle<String> name) { |
6772 Handle<String> name) { | |
6773 // TODO(ager): We should recognize when the prototype chains for different | 6730 // TODO(ager): We should recognize when the prototype chains for different |
6774 // maps are identical. In that case we can avoid repeatedly generating the | 6731 // maps are identical. In that case we can avoid repeatedly generating the |
6775 // same prototype map checks. | 6732 // same prototype map checks. |
6776 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6733 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
6777 HBasicBlock* join = NULL; | 6734 HBasicBlock* join = NULL; |
6778 FunctionSorter order[kMaxCallPolymorphism]; | 6735 FunctionSorter order[kMaxCallPolymorphism]; |
6779 int ordered_functions = 0; | 6736 int ordered_functions = 0; |
6780 for (int i = 0; | 6737 for (int i = 0; |
6781 i < types->length() && ordered_functions < kMaxCallPolymorphism; | 6738 i < types->length() && ordered_functions < kMaxCallPolymorphism; |
6782 ++i) { | 6739 ++i) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6864 if (join->HasPredecessor()) { | 6821 if (join->HasPredecessor()) { |
6865 set_current_block(join); | 6822 set_current_block(join); |
6866 join->SetJoinId(expr->id()); | 6823 join->SetJoinId(expr->id()); |
6867 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 6824 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
6868 } else { | 6825 } else { |
6869 set_current_block(NULL); | 6826 set_current_block(NULL); |
6870 } | 6827 } |
6871 } | 6828 } |
6872 | 6829 |
6873 | 6830 |
6874 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target, | 6831 void HGraphBuilder::TraceInline(Handle<JSFunction> target, |
6875 Handle<JSFunction> caller, | 6832 Handle<JSFunction> caller, |
6876 const char* reason) { | 6833 const char* reason) { |
6877 if (FLAG_trace_inlining) { | 6834 if (FLAG_trace_inlining) { |
6878 SmartArrayPointer<char> target_name = | 6835 SmartArrayPointer<char> target_name = |
6879 target->shared()->DebugName()->ToCString(); | 6836 target->shared()->DebugName()->ToCString(); |
6880 SmartArrayPointer<char> caller_name = | 6837 SmartArrayPointer<char> caller_name = |
6881 caller->shared()->DebugName()->ToCString(); | 6838 caller->shared()->DebugName()->ToCString(); |
6882 if (reason == NULL) { | 6839 if (reason == NULL) { |
6883 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); | 6840 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); |
6884 } else { | 6841 } else { |
6885 PrintF("Did not inline %s called from %s (%s).\n", | 6842 PrintF("Did not inline %s called from %s (%s).\n", |
6886 *target_name, *caller_name, reason); | 6843 *target_name, *caller_name, reason); |
6887 } | 6844 } |
6888 } | 6845 } |
6889 } | 6846 } |
6890 | 6847 |
6891 | 6848 |
6892 static const int kNotInlinable = 1000000000; | 6849 static const int kNotInlinable = 1000000000; |
6893 | 6850 |
6894 | 6851 |
6895 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { | 6852 int HGraphBuilder::InliningAstSize(Handle<JSFunction> target) { |
6896 if (!FLAG_use_inlining) return kNotInlinable; | 6853 if (!FLAG_use_inlining) return kNotInlinable; |
6897 | 6854 |
6898 // Precondition: call is monomorphic and we have found a target with the | 6855 // Precondition: call is monomorphic and we have found a target with the |
6899 // appropriate arity. | 6856 // appropriate arity. |
6900 Handle<JSFunction> caller = info()->closure(); | 6857 Handle<JSFunction> caller = info()->closure(); |
6901 Handle<SharedFunctionInfo> target_shared(target->shared()); | 6858 Handle<SharedFunctionInfo> target_shared(target->shared()); |
6902 | 6859 |
6903 // Do a quick check on source code length to avoid parsing large | 6860 // Do a quick check on source code length to avoid parsing large |
6904 // inlining candidates. | 6861 // inlining candidates. |
6905 if (target_shared->SourceSize() > | 6862 if (target_shared->SourceSize() > |
(...skipping 10 matching lines...) Expand all Loading... |
6916 if (target_shared->dont_inline() || target_shared->dont_optimize()) { | 6873 if (target_shared->dont_inline() || target_shared->dont_optimize()) { |
6917 TraceInline(target, caller, "target contains unsupported syntax [early]"); | 6874 TraceInline(target, caller, "target contains unsupported syntax [early]"); |
6918 return kNotInlinable; | 6875 return kNotInlinable; |
6919 } | 6876 } |
6920 | 6877 |
6921 int nodes_added = target_shared->ast_node_count(); | 6878 int nodes_added = target_shared->ast_node_count(); |
6922 return nodes_added; | 6879 return nodes_added; |
6923 } | 6880 } |
6924 | 6881 |
6925 | 6882 |
6926 bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, | 6883 bool HGraphBuilder::TryInline(CallKind call_kind, |
6927 Handle<JSFunction> target, | 6884 Handle<JSFunction> target, |
6928 int arguments_count, | 6885 int arguments_count, |
6929 HValue* implicit_return_value, | 6886 HValue* implicit_return_value, |
6930 BailoutId ast_id, | 6887 BailoutId ast_id, |
6931 BailoutId return_id, | 6888 BailoutId return_id, |
6932 InliningKind inlining_kind) { | 6889 InliningKind inlining_kind) { |
6933 int nodes_added = InliningAstSize(target); | 6890 int nodes_added = InliningAstSize(target); |
6934 if (nodes_added == kNotInlinable) return false; | 6891 if (nodes_added == kNotInlinable) return false; |
6935 | 6892 |
6936 Handle<JSFunction> caller = info()->closure(); | 6893 Handle<JSFunction> caller = info()->closure(); |
6937 | 6894 |
6938 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { | 6895 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { |
6939 TraceInline(target, caller, "target AST is too large [early]"); | 6896 TraceInline(target, caller, "target AST is too large [early]"); |
6940 return false; | 6897 return false; |
6941 } | 6898 } |
6942 | 6899 |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7231 function_return()->SetJoinId(ast_id); | 7188 function_return()->SetJoinId(ast_id); |
7232 set_current_block(function_return()); | 7189 set_current_block(function_return()); |
7233 } else { | 7190 } else { |
7234 set_current_block(NULL); | 7191 set_current_block(NULL); |
7235 } | 7192 } |
7236 delete target_state; | 7193 delete target_state; |
7237 return true; | 7194 return true; |
7238 } | 7195 } |
7239 | 7196 |
7240 | 7197 |
7241 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { | 7198 bool HGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { |
7242 // The function call we are inlining is a method call if the call | 7199 // The function call we are inlining is a method call if the call |
7243 // is a property call. | 7200 // is a property call. |
7244 CallKind call_kind = (expr->expression()->AsProperty() == NULL) | 7201 CallKind call_kind = (expr->expression()->AsProperty() == NULL) |
7245 ? CALL_AS_FUNCTION | 7202 ? CALL_AS_FUNCTION |
7246 : CALL_AS_METHOD; | 7203 : CALL_AS_METHOD; |
7247 | 7204 |
7248 return TryInline(call_kind, | 7205 return TryInline(call_kind, |
7249 expr->target(), | 7206 expr->target(), |
7250 expr->arguments()->length(), | 7207 expr->arguments()->length(), |
7251 NULL, | 7208 NULL, |
7252 expr->id(), | 7209 expr->id(), |
7253 expr->ReturnId(), | 7210 expr->ReturnId(), |
7254 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); | 7211 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); |
7255 } | 7212 } |
7256 | 7213 |
7257 | 7214 |
7258 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, | 7215 bool HGraphBuilder::TryInlineConstruct(CallNew* expr, |
7259 HValue* implicit_return_value) { | 7216 HValue* implicit_return_value) { |
7260 return TryInline(CALL_AS_FUNCTION, | 7217 return TryInline(CALL_AS_FUNCTION, |
7261 expr->target(), | 7218 expr->target(), |
7262 expr->arguments()->length(), | 7219 expr->arguments()->length(), |
7263 implicit_return_value, | 7220 implicit_return_value, |
7264 expr->id(), | 7221 expr->id(), |
7265 expr->ReturnId(), | 7222 expr->ReturnId(), |
7266 CONSTRUCT_CALL_RETURN); | 7223 CONSTRUCT_CALL_RETURN); |
7267 } | 7224 } |
7268 | 7225 |
7269 | 7226 |
7270 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, | 7227 bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, |
7271 Property* prop) { | 7228 Property* prop) { |
7272 return TryInline(CALL_AS_METHOD, | 7229 return TryInline(CALL_AS_METHOD, |
7273 getter, | 7230 getter, |
7274 0, | 7231 0, |
7275 NULL, | 7232 NULL, |
7276 prop->id(), | 7233 prop->id(), |
7277 prop->LoadId(), | 7234 prop->LoadId(), |
7278 GETTER_CALL_RETURN); | 7235 GETTER_CALL_RETURN); |
7279 } | 7236 } |
7280 | 7237 |
7281 | 7238 |
7282 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, | 7239 bool HGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, |
7283 Assignment* assignment, | 7240 Assignment* assignment, |
7284 HValue* implicit_return_value) { | 7241 HValue* implicit_return_value) { |
7285 return TryInline(CALL_AS_METHOD, | 7242 return TryInline(CALL_AS_METHOD, |
7286 setter, | 7243 setter, |
7287 1, | 7244 1, |
7288 implicit_return_value, | 7245 implicit_return_value, |
7289 assignment->id(), | 7246 assignment->id(), |
7290 assignment->AssignmentId(), | 7247 assignment->AssignmentId(), |
7291 SETTER_CALL_RETURN); | 7248 SETTER_CALL_RETURN); |
7292 } | 7249 } |
7293 | 7250 |
7294 | 7251 |
7295 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, | 7252 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) { |
7296 bool drop_extra) { | |
7297 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 7253 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
7298 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 7254 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
7299 switch (id) { | 7255 switch (id) { |
7300 case kMathExp: | 7256 case kMathExp: |
7301 if (!FLAG_fast_math) break; | 7257 if (!FLAG_fast_math) break; |
7302 // Fall through if FLAG_fast_math. | 7258 // Fall through if FLAG_fast_math. |
7303 case kMathRound: | 7259 case kMathRound: |
7304 case kMathAbs: | 7260 case kMathAbs: |
7305 case kMathSqrt: | 7261 case kMathSqrt: |
7306 case kMathLog: | 7262 case kMathLog: |
(...skipping 13 matching lines...) Expand all Loading... |
7320 } | 7276 } |
7321 break; | 7277 break; |
7322 default: | 7278 default: |
7323 // Not supported for inlining yet. | 7279 // Not supported for inlining yet. |
7324 break; | 7280 break; |
7325 } | 7281 } |
7326 return false; | 7282 return false; |
7327 } | 7283 } |
7328 | 7284 |
7329 | 7285 |
7330 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( | 7286 bool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr, |
7331 Call* expr, | 7287 HValue* receiver, |
7332 HValue* receiver, | 7288 Handle<Map> receiver_map, |
7333 Handle<Map> receiver_map, | 7289 CheckType check_type) { |
7334 CheckType check_type) { | |
7335 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); | 7290 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); |
7336 // Try to inline calls like Math.* as operations in the calling function. | 7291 // Try to inline calls like Math.* as operations in the calling function. |
7337 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 7292 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
7338 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 7293 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
7339 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7294 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
7340 switch (id) { | 7295 switch (id) { |
7341 case kStringCharCodeAt: | 7296 case kStringCharCodeAt: |
7342 case kStringCharAt: | 7297 case kStringCharAt: |
7343 if (argument_count == 2 && check_type == STRING_CHECK) { | 7298 if (argument_count == 2 && check_type == STRING_CHECK) { |
7344 HValue* index = Pop(); | 7299 HValue* index = Pop(); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7454 } | 7409 } |
7455 break; | 7410 break; |
7456 default: | 7411 default: |
7457 // Not yet supported for inlining. | 7412 // Not yet supported for inlining. |
7458 break; | 7413 break; |
7459 } | 7414 } |
7460 return false; | 7415 return false; |
7461 } | 7416 } |
7462 | 7417 |
7463 | 7418 |
7464 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { | 7419 bool HGraphBuilder::TryCallApply(Call* expr) { |
7465 Expression* callee = expr->expression(); | 7420 Expression* callee = expr->expression(); |
7466 Property* prop = callee->AsProperty(); | 7421 Property* prop = callee->AsProperty(); |
7467 ASSERT(prop != NULL); | 7422 ASSERT(prop != NULL); |
7468 | 7423 |
7469 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { | 7424 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { |
7470 return false; | 7425 return false; |
7471 } | 7426 } |
7472 Handle<Map> function_map = expr->GetReceiverTypes()->first(); | 7427 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
7473 if (function_map->instance_type() != JS_FUNCTION_TYPE || | 7428 if (function_map->instance_type() != JS_FUNCTION_TYPE || |
7474 !expr->target()->shared()->HasBuiltinFunctionId() || | 7429 !expr->target()->shared()->HasBuiltinFunctionId() || |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7582 return NULL; | 7537 return NULL; |
7583 } | 7538 } |
7584 current = next; | 7539 current = next; |
7585 } | 7540 } |
7586 } | 7541 } |
7587 | 7542 |
7588 return kinds[first_index]; | 7543 return kinds[first_index]; |
7589 } | 7544 } |
7590 | 7545 |
7591 | 7546 |
7592 void HOptimizedGraphBuilder::VisitCall(Call* expr) { | 7547 void HGraphBuilder::VisitCall(Call* expr) { |
7593 ASSERT(!HasStackOverflow()); | 7548 ASSERT(!HasStackOverflow()); |
7594 ASSERT(current_block() != NULL); | 7549 ASSERT(current_block() != NULL); |
7595 ASSERT(current_block()->HasPredecessor()); | 7550 ASSERT(current_block()->HasPredecessor()); |
7596 Expression* callee = expr->expression(); | 7551 Expression* callee = expr->expression(); |
7597 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7552 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
7598 HInstruction* call = NULL; | 7553 HInstruction* call = NULL; |
7599 | 7554 |
7600 Property* prop = callee->AsProperty(); | 7555 Property* prop = callee->AsProperty(); |
7601 if (prop != NULL) { | 7556 if (prop != NULL) { |
7602 if (!prop->key()->IsPropertyName()) { | 7557 if (!prop->key()->IsPropertyName()) { |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7812 | 7767 |
7813 | 7768 |
7814 // Checks whether allocation using the given constructor can be inlined. | 7769 // Checks whether allocation using the given constructor can be inlined. |
7815 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 7770 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
7816 return constructor->has_initial_map() && | 7771 return constructor->has_initial_map() && |
7817 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 7772 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
7818 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; | 7773 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; |
7819 } | 7774 } |
7820 | 7775 |
7821 | 7776 |
7822 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 7777 void HGraphBuilder::VisitCallNew(CallNew* expr) { |
7823 ASSERT(!HasStackOverflow()); | 7778 ASSERT(!HasStackOverflow()); |
7824 ASSERT(current_block() != NULL); | 7779 ASSERT(current_block() != NULL); |
7825 ASSERT(current_block()->HasPredecessor()); | 7780 ASSERT(current_block()->HasPredecessor()); |
7826 expr->RecordTypeFeedback(oracle()); | 7781 expr->RecordTypeFeedback(oracle()); |
7827 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 7782 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
7828 HValue* context = environment()->LookupContext(); | 7783 HValue* context = environment()->LookupContext(); |
7829 | 7784 |
7830 if (FLAG_inline_construct && | 7785 if (FLAG_inline_construct && |
7831 expr->IsMonomorphic() && | 7786 expr->IsMonomorphic() && |
7832 IsAllocationInlineable(expr->target())) { | 7787 IsAllocationInlineable(expr->target())) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7876 new(zone()) HCallNew(context, constructor, argument_count); | 7831 new(zone()) HCallNew(context, constructor, argument_count); |
7877 Drop(argument_count); | 7832 Drop(argument_count); |
7878 call->set_position(expr->position()); | 7833 call->set_position(expr->position()); |
7879 return ast_context()->ReturnInstruction(call, expr->id()); | 7834 return ast_context()->ReturnInstruction(call, expr->id()); |
7880 } | 7835 } |
7881 } | 7836 } |
7882 | 7837 |
7883 | 7838 |
7884 // Support for generating inlined runtime functions. | 7839 // Support for generating inlined runtime functions. |
7885 | 7840 |
7886 // Lookup table for generators for runtime calls that are generated inline. | 7841 // Lookup table for generators for runtime calls that are generated inline. |
7887 // Elements of the table are member pointers to functions of | 7842 // Elements of the table are member pointers to functions of HGraphBuilder. |
7888 // HOptimizedGraphBuilder. | |
7889 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ | 7843 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ |
7890 &HOptimizedGraphBuilder::Generate##Name, | 7844 &HGraphBuilder::Generate##Name, |
7891 | 7845 |
7892 const HOptimizedGraphBuilder::InlineFunctionGenerator | 7846 const HGraphBuilder::InlineFunctionGenerator |
7893 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = { | 7847 HGraphBuilder::kInlineFunctionGenerators[] = { |
7894 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 7848 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
7895 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 7849 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
7896 }; | 7850 }; |
7897 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 7851 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
7898 | 7852 |
7899 | 7853 |
7900 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 7854 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
7901 ASSERT(!HasStackOverflow()); | 7855 ASSERT(!HasStackOverflow()); |
7902 ASSERT(current_block() != NULL); | 7856 ASSERT(current_block() != NULL); |
7903 ASSERT(current_block()->HasPredecessor()); | 7857 ASSERT(current_block()->HasPredecessor()); |
7904 if (expr->is_jsruntime()) { | 7858 if (expr->is_jsruntime()) { |
7905 return Bailout("call to a JavaScript runtime function"); | 7859 return Bailout("call to a JavaScript runtime function"); |
7906 } | 7860 } |
7907 | 7861 |
7908 const Runtime::Function* function = expr->function(); | 7862 const Runtime::Function* function = expr->function(); |
7909 ASSERT(function != NULL); | 7863 ASSERT(function != NULL); |
7910 if (function->intrinsic_type == Runtime::INLINE) { | 7864 if (function->intrinsic_type == Runtime::INLINE) { |
(...skipping 17 matching lines...) Expand all Loading... |
7928 Handle<String> name = expr->name(); | 7882 Handle<String> name = expr->name(); |
7929 int argument_count = expr->arguments()->length(); | 7883 int argument_count = expr->arguments()->length(); |
7930 HCallRuntime* call = | 7884 HCallRuntime* call = |
7931 new(zone()) HCallRuntime(context, name, function, argument_count); | 7885 new(zone()) HCallRuntime(context, name, function, argument_count); |
7932 Drop(argument_count); | 7886 Drop(argument_count); |
7933 return ast_context()->ReturnInstruction(call, expr->id()); | 7887 return ast_context()->ReturnInstruction(call, expr->id()); |
7934 } | 7888 } |
7935 } | 7889 } |
7936 | 7890 |
7937 | 7891 |
7938 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 7892 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
7939 ASSERT(!HasStackOverflow()); | 7893 ASSERT(!HasStackOverflow()); |
7940 ASSERT(current_block() != NULL); | 7894 ASSERT(current_block() != NULL); |
7941 ASSERT(current_block()->HasPredecessor()); | 7895 ASSERT(current_block()->HasPredecessor()); |
7942 switch (expr->op()) { | 7896 switch (expr->op()) { |
7943 case Token::DELETE: return VisitDelete(expr); | 7897 case Token::DELETE: return VisitDelete(expr); |
7944 case Token::VOID: return VisitVoid(expr); | 7898 case Token::VOID: return VisitVoid(expr); |
7945 case Token::TYPEOF: return VisitTypeof(expr); | 7899 case Token::TYPEOF: return VisitTypeof(expr); |
7946 case Token::ADD: return VisitAdd(expr); | 7900 case Token::ADD: return VisitAdd(expr); |
7947 case Token::SUB: return VisitSub(expr); | 7901 case Token::SUB: return VisitSub(expr); |
7948 case Token::BIT_NOT: return VisitBitNot(expr); | 7902 case Token::BIT_NOT: return VisitBitNot(expr); |
7949 case Token::NOT: return VisitNot(expr); | 7903 case Token::NOT: return VisitNot(expr); |
7950 default: UNREACHABLE(); | 7904 default: UNREACHABLE(); |
7951 } | 7905 } |
7952 } | 7906 } |
7953 | 7907 |
7954 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { | 7908 void HGraphBuilder::VisitDelete(UnaryOperation* expr) { |
7955 Property* prop = expr->expression()->AsProperty(); | 7909 Property* prop = expr->expression()->AsProperty(); |
7956 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7910 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
7957 if (prop != NULL) { | 7911 if (prop != NULL) { |
7958 CHECK_ALIVE(VisitForValue(prop->obj())); | 7912 CHECK_ALIVE(VisitForValue(prop->obj())); |
7959 CHECK_ALIVE(VisitForValue(prop->key())); | 7913 CHECK_ALIVE(VisitForValue(prop->key())); |
7960 HValue* key = Pop(); | 7914 HValue* key = Pop(); |
7961 HValue* obj = Pop(); | 7915 HValue* obj = Pop(); |
7962 HValue* context = environment()->LookupContext(); | 7916 HValue* context = environment()->LookupContext(); |
7963 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); | 7917 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); |
7964 return ast_context()->ReturnInstruction(instr, expr->id()); | 7918 return ast_context()->ReturnInstruction(instr, expr->id()); |
(...skipping 14 matching lines...) Expand all Loading... |
7979 } | 7933 } |
7980 } else { | 7934 } else { |
7981 // Result of deleting non-property, non-variable reference is true. | 7935 // Result of deleting non-property, non-variable reference is true. |
7982 // Evaluate the subexpression for side effects. | 7936 // Evaluate the subexpression for side effects. |
7983 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7937 CHECK_ALIVE(VisitForEffect(expr->expression())); |
7984 return ast_context()->ReturnValue(graph()->GetConstantTrue()); | 7938 return ast_context()->ReturnValue(graph()->GetConstantTrue()); |
7985 } | 7939 } |
7986 } | 7940 } |
7987 | 7941 |
7988 | 7942 |
7989 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { | 7943 void HGraphBuilder::VisitVoid(UnaryOperation* expr) { |
7990 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7944 CHECK_ALIVE(VisitForEffect(expr->expression())); |
7991 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 7945 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
7992 } | 7946 } |
7993 | 7947 |
7994 | 7948 |
7995 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 7949 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
7996 CHECK_ALIVE(VisitForTypeOf(expr->expression())); | 7950 CHECK_ALIVE(VisitForTypeOf(expr->expression())); |
7997 HValue* value = Pop(); | 7951 HValue* value = Pop(); |
7998 HValue* context = environment()->LookupContext(); | 7952 HValue* context = environment()->LookupContext(); |
7999 HInstruction* instr = new(zone()) HTypeof(context, value); | 7953 HInstruction* instr = new(zone()) HTypeof(context, value); |
8000 return ast_context()->ReturnInstruction(instr, expr->id()); | 7954 return ast_context()->ReturnInstruction(instr, expr->id()); |
8001 } | 7955 } |
8002 | 7956 |
8003 | 7957 |
8004 void HOptimizedGraphBuilder::VisitAdd(UnaryOperation* expr) { | 7958 void HGraphBuilder::VisitAdd(UnaryOperation* expr) { |
8005 CHECK_ALIVE(VisitForValue(expr->expression())); | 7959 CHECK_ALIVE(VisitForValue(expr->expression())); |
8006 HValue* value = Pop(); | 7960 HValue* value = Pop(); |
8007 HValue* context = environment()->LookupContext(); | 7961 HValue* context = environment()->LookupContext(); |
8008 HInstruction* instr = | 7962 HInstruction* instr = |
8009 new(zone()) HMul(context, value, graph()->GetConstant1()); | 7963 new(zone()) HMul(context, value, graph_->GetConstant1()); |
8010 return ast_context()->ReturnInstruction(instr, expr->id()); | 7964 return ast_context()->ReturnInstruction(instr, expr->id()); |
8011 } | 7965 } |
8012 | 7966 |
8013 | 7967 |
8014 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { | 7968 void HGraphBuilder::VisitSub(UnaryOperation* expr) { |
8015 CHECK_ALIVE(VisitForValue(expr->expression())); | 7969 CHECK_ALIVE(VisitForValue(expr->expression())); |
8016 HValue* value = Pop(); | 7970 HValue* value = Pop(); |
8017 HValue* context = environment()->LookupContext(); | 7971 HValue* context = environment()->LookupContext(); |
8018 HInstruction* instr = | 7972 HInstruction* instr = |
8019 new(zone()) HMul(context, value, graph()->GetConstantMinus1()); | 7973 new(zone()) HMul(context, value, graph_->GetConstantMinus1()); |
8020 TypeInfo info = oracle()->UnaryType(expr); | 7974 TypeInfo info = oracle()->UnaryType(expr); |
8021 Representation rep = ToRepresentation(info); | 7975 Representation rep = ToRepresentation(info); |
8022 if (info.IsUninitialized()) { | 7976 if (info.IsUninitialized()) { |
8023 AddInstruction(new(zone()) HSoftDeoptimize); | 7977 AddInstruction(new(zone()) HSoftDeoptimize); |
8024 current_block()->MarkAsDeoptimizing(); | 7978 current_block()->MarkAsDeoptimizing(); |
8025 info = TypeInfo::Unknown(); | 7979 info = TypeInfo::Unknown(); |
8026 } | 7980 } |
8027 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); | 7981 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); |
8028 return ast_context()->ReturnInstruction(instr, expr->id()); | 7982 return ast_context()->ReturnInstruction(instr, expr->id()); |
8029 } | 7983 } |
8030 | 7984 |
8031 | 7985 |
8032 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 7986 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
8033 CHECK_ALIVE(VisitForValue(expr->expression())); | 7987 CHECK_ALIVE(VisitForValue(expr->expression())); |
8034 HValue* value = Pop(); | 7988 HValue* value = Pop(); |
8035 TypeInfo info = oracle()->UnaryType(expr); | 7989 TypeInfo info = oracle()->UnaryType(expr); |
8036 if (info.IsUninitialized()) { | 7990 if (info.IsUninitialized()) { |
8037 AddInstruction(new(zone()) HSoftDeoptimize); | 7991 AddInstruction(new(zone()) HSoftDeoptimize); |
8038 current_block()->MarkAsDeoptimizing(); | 7992 current_block()->MarkAsDeoptimizing(); |
8039 } | 7993 } |
8040 HInstruction* instr = new(zone()) HBitNot(value); | 7994 HInstruction* instr = new(zone()) HBitNot(value); |
8041 return ast_context()->ReturnInstruction(instr, expr->id()); | 7995 return ast_context()->ReturnInstruction(instr, expr->id()); |
8042 } | 7996 } |
8043 | 7997 |
8044 | 7998 |
8045 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 7999 void HGraphBuilder::VisitNot(UnaryOperation* expr) { |
8046 if (ast_context()->IsTest()) { | 8000 if (ast_context()->IsTest()) { |
8047 TestContext* context = TestContext::cast(ast_context()); | 8001 TestContext* context = TestContext::cast(ast_context()); |
8048 VisitForControl(expr->expression(), | 8002 VisitForControl(expr->expression(), |
8049 context->if_false(), | 8003 context->if_false(), |
8050 context->if_true()); | 8004 context->if_true()); |
8051 return; | 8005 return; |
8052 } | 8006 } |
8053 | 8007 |
8054 if (ast_context()->IsEffect()) { | 8008 if (ast_context()->IsEffect()) { |
8055 VisitForEffect(expr->expression()); | 8009 VisitForEffect(expr->expression()); |
(...skipping 23 matching lines...) Expand all Loading... |
8079 materialize_true = NULL; | 8033 materialize_true = NULL; |
8080 } | 8034 } |
8081 | 8035 |
8082 HBasicBlock* join = | 8036 HBasicBlock* join = |
8083 CreateJoin(materialize_false, materialize_true, expr->id()); | 8037 CreateJoin(materialize_false, materialize_true, expr->id()); |
8084 set_current_block(join); | 8038 set_current_block(join); |
8085 if (join != NULL) return ast_context()->ReturnValue(Pop()); | 8039 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
8086 } | 8040 } |
8087 | 8041 |
8088 | 8042 |
8089 HInstruction* HOptimizedGraphBuilder::BuildIncrement( | 8043 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input, |
8090 bool returns_original_input, | 8044 CountOperation* expr) { |
8091 CountOperation* expr) { | |
8092 // The input to the count operation is on top of the expression stack. | 8045 // The input to the count operation is on top of the expression stack. |
8093 TypeInfo info = oracle()->IncrementType(expr); | 8046 TypeInfo info = oracle()->IncrementType(expr); |
8094 Representation rep = ToRepresentation(info); | 8047 Representation rep = ToRepresentation(info); |
8095 if (rep.IsTagged()) { | 8048 if (rep.IsTagged()) { |
8096 rep = Representation::Integer32(); | 8049 rep = Representation::Integer32(); |
8097 } | 8050 } |
8098 | 8051 |
8099 if (returns_original_input) { | 8052 if (returns_original_input) { |
8100 // We need an explicit HValue representing ToNumber(input). The | 8053 // We need an explicit HValue representing ToNumber(input). The |
8101 // actual HChange instruction we need is (sometimes) added in a later | 8054 // actual HChange instruction we need is (sometimes) added in a later |
8102 // phase, so it is not available now to be used as an input to HAdd and | 8055 // phase, so it is not available now to be used as an input to HAdd and |
8103 // as the return value. | 8056 // as the return value. |
8104 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); | 8057 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); |
8105 AddInstruction(number_input); | 8058 AddInstruction(number_input); |
8106 Push(number_input); | 8059 Push(number_input); |
8107 } | 8060 } |
8108 | 8061 |
8109 // The addition has no side effects, so we do not need | 8062 // The addition has no side effects, so we do not need |
8110 // to simulate the expression stack after this instruction. | 8063 // to simulate the expression stack after this instruction. |
8111 // Any later failures deopt to the load of the input or earlier. | 8064 // Any later failures deopt to the load of the input or earlier. |
8112 HConstant* delta = (expr->op() == Token::INC) | 8065 HConstant* delta = (expr->op() == Token::INC) |
8113 ? graph()->GetConstant1() | 8066 ? graph_->GetConstant1() |
8114 : graph()->GetConstantMinus1(); | 8067 : graph_->GetConstantMinus1(); |
8115 HValue* context = environment()->LookupContext(); | 8068 HValue* context = environment()->LookupContext(); |
8116 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); | 8069 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); |
8117 // We can't insert a simulate here, because it would break deoptimization, | 8070 // We can't insert a simulate here, because it would break deoptimization, |
8118 // so the HAdd must not have side effects, so we must freeze its | 8071 // so the HAdd must not have side effects, so we must freeze its |
8119 // representation. | 8072 // representation. |
8120 instr->AssumeRepresentation(rep); | 8073 instr->AssumeRepresentation(rep); |
8121 instr->ClearAllSideEffects(); | 8074 instr->ClearAllSideEffects(); |
8122 AddInstruction(instr); | 8075 AddInstruction(instr); |
8123 return instr; | 8076 return instr; |
8124 } | 8077 } |
8125 | 8078 |
8126 | 8079 |
8127 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 8080 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
8128 ASSERT(!HasStackOverflow()); | 8081 ASSERT(!HasStackOverflow()); |
8129 ASSERT(current_block() != NULL); | 8082 ASSERT(current_block() != NULL); |
8130 ASSERT(current_block()->HasPredecessor()); | 8083 ASSERT(current_block()->HasPredecessor()); |
8131 Expression* target = expr->expression(); | 8084 Expression* target = expr->expression(); |
8132 VariableProxy* proxy = target->AsVariableProxy(); | 8085 VariableProxy* proxy = target->AsVariableProxy(); |
8133 Property* prop = target->AsProperty(); | 8086 Property* prop = target->AsProperty(); |
8134 if (proxy == NULL && prop == NULL) { | 8087 if (proxy == NULL && prop == NULL) { |
8135 return Bailout("invalid lhs in count operation"); | 8088 return Bailout("invalid lhs in count operation"); |
8136 } | 8089 } |
8137 | 8090 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8201 return Bailout("lookup variable in count operation"); | 8154 return Bailout("lookup variable in count operation"); |
8202 } | 8155 } |
8203 | 8156 |
8204 } else { | 8157 } else { |
8205 // Argument of the count operation is a property. | 8158 // Argument of the count operation is a property. |
8206 ASSERT(prop != NULL); | 8159 ASSERT(prop != NULL); |
8207 prop->RecordTypeFeedback(oracle(), zone()); | 8160 prop->RecordTypeFeedback(oracle(), zone()); |
8208 | 8161 |
8209 if (prop->key()->IsPropertyName()) { | 8162 if (prop->key()->IsPropertyName()) { |
8210 // Named property. | 8163 // Named property. |
8211 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 8164 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
8212 | 8165 |
8213 CHECK_ALIVE(VisitForValue(prop->obj())); | 8166 CHECK_ALIVE(VisitForValue(prop->obj())); |
8214 HValue* object = Top(); | 8167 HValue* object = Top(); |
8215 | 8168 |
8216 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 8169 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
8217 Handle<Map> map; | 8170 Handle<Map> map; |
8218 HInstruction* load; | 8171 HInstruction* load; |
8219 bool monomorphic = prop->IsMonomorphic(); | 8172 bool monomorphic = prop->IsMonomorphic(); |
8220 if (monomorphic) { | 8173 if (monomorphic) { |
8221 map = prop->GetReceiverTypes()->first(); | 8174 map = prop->GetReceiverTypes()->first(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8262 // of the operation, and the placeholder with the original value if | 8215 // of the operation, and the placeholder with the original value if |
8263 // necessary. | 8216 // necessary. |
8264 environment()->SetExpressionStackAt(0, after); | 8217 environment()->SetExpressionStackAt(0, after); |
8265 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 8218 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
8266 if (store->HasObservableSideEffects()) { | 8219 if (store->HasObservableSideEffects()) { |
8267 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 8220 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
8268 } | 8221 } |
8269 | 8222 |
8270 } else { | 8223 } else { |
8271 // Keyed property. | 8224 // Keyed property. |
8272 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 8225 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
8273 | 8226 |
8274 CHECK_ALIVE(VisitForValue(prop->obj())); | 8227 CHECK_ALIVE(VisitForValue(prop->obj())); |
8275 CHECK_ALIVE(VisitForValue(prop->key())); | 8228 CHECK_ALIVE(VisitForValue(prop->key())); |
8276 HValue* obj = environment()->ExpressionStackAt(1); | 8229 HValue* obj = environment()->ExpressionStackAt(1); |
8277 HValue* key = environment()->ExpressionStackAt(0); | 8230 HValue* key = environment()->ExpressionStackAt(0); |
8278 | 8231 |
8279 bool has_side_effects = false; | 8232 bool has_side_effects = false; |
8280 HValue* load = HandleKeyedElementAccess( | 8233 HValue* load = HandleKeyedElementAccess( |
8281 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 8234 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
8282 false, // is_store | 8235 false, // is_store |
(...skipping 19 matching lines...) Expand all Loading... |
8302 ASSERT(has_side_effects); // Stores always have side effects. | 8255 ASSERT(has_side_effects); // Stores always have side effects. |
8303 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 8256 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
8304 } | 8257 } |
8305 } | 8258 } |
8306 | 8259 |
8307 Drop(returns_original_input ? 2 : 1); | 8260 Drop(returns_original_input ? 2 : 1); |
8308 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 8261 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
8309 } | 8262 } |
8310 | 8263 |
8311 | 8264 |
8312 HStringCharCodeAt* HOptimizedGraphBuilder::BuildStringCharCodeAt( | 8265 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context, |
8313 HValue* context, | 8266 HValue* string, |
8314 HValue* string, | 8267 HValue* index) { |
8315 HValue* index) { | |
8316 AddInstruction(new(zone()) HCheckNonSmi(string)); | 8268 AddInstruction(new(zone()) HCheckNonSmi(string)); |
8317 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 8269 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
8318 HStringLength* length = new(zone()) HStringLength(string); | 8270 HStringLength* length = new(zone()) HStringLength(string); |
8319 AddInstruction(length); | 8271 AddInstruction(length); |
8320 HInstruction* checked_index = | 8272 HInstruction* checked_index = |
8321 AddInstruction(new(zone()) HBoundsCheck(index, length)); | 8273 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
8322 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 8274 return new(zone()) HStringCharCodeAt(context, string, checked_index); |
8323 } | 8275 } |
8324 | 8276 |
8325 // Checks if the given shift amounts have form: (sa) and (32 - sa). | 8277 // Checks if the given shift amounts have form: (sa) and (32 - sa). |
8326 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 8278 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
8327 HValue* const32_minus_sa) { | 8279 HValue* const32_minus_sa) { |
8328 if (!const32_minus_sa->IsSub()) return false; | 8280 if (!const32_minus_sa->IsSub()) return false; |
8329 HSub* sub = HSub::cast(const32_minus_sa); | 8281 HSub* sub = HSub::cast(const32_minus_sa); |
8330 HValue* const32 = sub->left(); | 8282 HValue* const32 = sub->left(); |
8331 if (!const32->IsConstant() || | 8283 if (!const32->IsConstant() || |
8332 HConstant::cast(const32)->Integer32Value() != 32) { | 8284 HConstant::cast(const32)->Integer32Value() != 32) { |
8333 return false; | 8285 return false; |
8334 } | 8286 } |
8335 return (sub->right() == sa); | 8287 return (sub->right() == sa); |
8336 } | 8288 } |
8337 | 8289 |
8338 | 8290 |
8339 // Checks if the left and the right are shift instructions with the oposite | 8291 // Checks if the left and the right are shift instructions with the oposite |
8340 // directions that can be replaced by one rotate right instruction or not. | 8292 // directions that can be replaced by one rotate right instruction or not. |
8341 // Returns the operand and the shift amount for the rotate instruction in the | 8293 // Returns the operand and the shift amount for the rotate instruction in the |
8342 // former case. | 8294 // former case. |
8343 bool HOptimizedGraphBuilder::MatchRotateRight(HValue* left, | 8295 bool HGraphBuilder::MatchRotateRight(HValue* left, |
8344 HValue* right, | 8296 HValue* right, |
8345 HValue** operand, | 8297 HValue** operand, |
8346 HValue** shift_amount) { | 8298 HValue** shift_amount) { |
8347 HShl* shl; | 8299 HShl* shl; |
8348 HShr* shr; | 8300 HShr* shr; |
8349 if (left->IsShl() && right->IsShr()) { | 8301 if (left->IsShl() && right->IsShr()) { |
8350 shl = HShl::cast(left); | 8302 shl = HShl::cast(left); |
8351 shr = HShr::cast(right); | 8303 shr = HShr::cast(right); |
8352 } else if (left->IsShr() && right->IsShl()) { | 8304 } else if (left->IsShr() && right->IsShl()) { |
8353 shl = HShl::cast(right); | 8305 shl = HShl::cast(right); |
8354 shr = HShr::cast(left); | 8306 shr = HShr::cast(left); |
8355 } else { | 8307 } else { |
8356 return false; | 8308 return false; |
(...skipping 14 matching lines...) Expand all Loading... |
8371 HConstant* right_const = HConstant::cast(right); | 8323 HConstant* right_const = HConstant::cast(right); |
8372 if (right_const->HasInteger32Value() && | 8324 if (right_const->HasInteger32Value() && |
8373 (right_const->Integer32Value() & 0x1f) != 0) { | 8325 (right_const->Integer32Value() & 0x1f) != 0) { |
8374 return false; | 8326 return false; |
8375 } | 8327 } |
8376 } | 8328 } |
8377 return true; | 8329 return true; |
8378 } | 8330 } |
8379 | 8331 |
8380 | 8332 |
8381 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 8333 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
8382 BinaryOperation* expr, | 8334 HValue* left, |
8383 HValue* left, | 8335 HValue* right) { |
8384 HValue* right) { | |
8385 HValue* context = environment()->LookupContext(); | 8336 HValue* context = environment()->LookupContext(); |
8386 TypeInfo left_info, right_info, result_info, combined_info; | 8337 TypeInfo left_info, right_info, result_info, combined_info; |
8387 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); | 8338 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); |
8388 Representation left_rep = ToRepresentation(left_info); | 8339 Representation left_rep = ToRepresentation(left_info); |
8389 Representation right_rep = ToRepresentation(right_info); | 8340 Representation right_rep = ToRepresentation(right_info); |
8390 Representation result_rep = ToRepresentation(result_info); | 8341 Representation result_rep = ToRepresentation(result_info); |
8391 if (left_info.IsUninitialized()) { | 8342 if (left_info.IsUninitialized()) { |
8392 // Can't have initialized one but not the other. | 8343 // Can't have initialized one but not the other. |
8393 ASSERT(right_info.IsUninitialized()); | 8344 ASSERT(right_info.IsUninitialized()); |
8394 AddInstruction(new(zone()) HSoftDeoptimize); | 8345 AddInstruction(new(zone()) HSoftDeoptimize); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8467 if (call == NULL) return false; | 8418 if (call == NULL) return false; |
8468 Literal* literal = expr->right()->AsLiteral(); | 8419 Literal* literal = expr->right()->AsLiteral(); |
8469 if (literal == NULL) return false; | 8420 if (literal == NULL) return false; |
8470 if (!literal->handle()->IsString()) return false; | 8421 if (!literal->handle()->IsString()) return false; |
8471 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; | 8422 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; |
8472 ASSERT(call->arguments()->length() == 1); | 8423 ASSERT(call->arguments()->length() == 1); |
8473 return true; | 8424 return true; |
8474 } | 8425 } |
8475 | 8426 |
8476 | 8427 |
8477 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 8428 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
8478 ASSERT(!HasStackOverflow()); | 8429 ASSERT(!HasStackOverflow()); |
8479 ASSERT(current_block() != NULL); | 8430 ASSERT(current_block() != NULL); |
8480 ASSERT(current_block()->HasPredecessor()); | 8431 ASSERT(current_block()->HasPredecessor()); |
8481 switch (expr->op()) { | 8432 switch (expr->op()) { |
8482 case Token::COMMA: | 8433 case Token::COMMA: |
8483 return VisitComma(expr); | 8434 return VisitComma(expr); |
8484 case Token::OR: | 8435 case Token::OR: |
8485 case Token::AND: | 8436 case Token::AND: |
8486 return VisitLogicalExpression(expr); | 8437 return VisitLogicalExpression(expr); |
8487 default: | 8438 default: |
8488 return VisitArithmeticExpression(expr); | 8439 return VisitArithmeticExpression(expr); |
8489 } | 8440 } |
8490 } | 8441 } |
8491 | 8442 |
8492 | 8443 |
8493 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) { | 8444 void HGraphBuilder::VisitComma(BinaryOperation* expr) { |
8494 CHECK_ALIVE(VisitForEffect(expr->left())); | 8445 CHECK_ALIVE(VisitForEffect(expr->left())); |
8495 // Visit the right subexpression in the same AST context as the entire | 8446 // Visit the right subexpression in the same AST context as the entire |
8496 // expression. | 8447 // expression. |
8497 Visit(expr->right()); | 8448 Visit(expr->right()); |
8498 } | 8449 } |
8499 | 8450 |
8500 | 8451 |
8501 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { | 8452 void HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { |
8502 bool is_logical_and = expr->op() == Token::AND; | 8453 bool is_logical_and = expr->op() == Token::AND; |
8503 if (ast_context()->IsTest()) { | 8454 if (ast_context()->IsTest()) { |
8504 TestContext* context = TestContext::cast(ast_context()); | 8455 TestContext* context = TestContext::cast(ast_context()); |
8505 // Translate left subexpression. | 8456 // Translate left subexpression. |
8506 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 8457 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
8507 if (is_logical_and) { | 8458 if (is_logical_and) { |
8508 CHECK_BAILOUT(VisitForControl(expr->left(), | 8459 CHECK_BAILOUT(VisitForControl(expr->left(), |
8509 eval_right, | 8460 eval_right, |
8510 context->if_false())); | 8461 context->if_false())); |
8511 } else { | 8462 } else { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8581 | 8532 |
8582 HBasicBlock* join_block = | 8533 HBasicBlock* join_block = |
8583 CreateJoin(empty_block, right_block, expr->id()); | 8534 CreateJoin(empty_block, right_block, expr->id()); |
8584 set_current_block(join_block); | 8535 set_current_block(join_block); |
8585 // We did not materialize any value in the predecessor environments, | 8536 // We did not materialize any value in the predecessor environments, |
8586 // so there is no need to handle it here. | 8537 // so there is no need to handle it here. |
8587 } | 8538 } |
8588 } | 8539 } |
8589 | 8540 |
8590 | 8541 |
8591 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { | 8542 void HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { |
8592 CHECK_ALIVE(VisitForValue(expr->left())); | 8543 CHECK_ALIVE(VisitForValue(expr->left())); |
8593 CHECK_ALIVE(VisitForValue(expr->right())); | 8544 CHECK_ALIVE(VisitForValue(expr->right())); |
8594 HValue* right = Pop(); | 8545 HValue* right = Pop(); |
8595 HValue* left = Pop(); | 8546 HValue* left = Pop(); |
8596 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 8547 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
8597 instr->set_position(expr->position()); | 8548 instr->set_position(expr->position()); |
8598 return ast_context()->ReturnInstruction(instr, expr->id()); | 8549 return ast_context()->ReturnInstruction(instr, expr->id()); |
8599 } | 8550 } |
8600 | 8551 |
8601 | 8552 |
8602 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) { | 8553 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { |
8603 if (info.IsUninitialized()) return Representation::None(); | 8554 if (info.IsUninitialized()) return Representation::None(); |
8604 if (info.IsSmi()) return Representation::Integer32(); | 8555 if (info.IsSmi()) return Representation::Integer32(); |
8605 if (info.IsInteger32()) return Representation::Integer32(); | 8556 if (info.IsInteger32()) return Representation::Integer32(); |
8606 if (info.IsDouble()) return Representation::Double(); | 8557 if (info.IsDouble()) return Representation::Double(); |
8607 if (info.IsNumber()) return Representation::Double(); | 8558 if (info.IsNumber()) return Representation::Double(); |
8608 return Representation::Tagged(); | 8559 return Representation::Tagged(); |
8609 } | 8560 } |
8610 | 8561 |
8611 | 8562 |
8612 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 8563 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
8613 HTypeof* typeof_expr, | 8564 HTypeof* typeof_expr, |
8614 Handle<String> check) { | 8565 Handle<String> check) { |
8615 // Note: The HTypeof itself is removed during canonicalization, if possible. | 8566 // Note: The HTypeof itself is removed during canonicalization, if possible. |
8616 HValue* value = typeof_expr->value(); | 8567 HValue* value = typeof_expr->value(); |
8617 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); | 8568 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); |
8618 instr->set_position(expr->position()); | 8569 instr->set_position(expr->position()); |
8619 return ast_context()->ReturnControl(instr, expr->id()); | 8570 return ast_context()->ReturnControl(instr, expr->id()); |
8620 } | 8571 } |
8621 | 8572 |
8622 | 8573 |
8623 static bool MatchLiteralCompareNil(HValue* left, | 8574 static bool MatchLiteralCompareNil(HValue* left, |
8624 Token::Value op, | 8575 Token::Value op, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8674 | 8625 |
8675 static bool IsLiteralCompareBool(HValue* left, | 8626 static bool IsLiteralCompareBool(HValue* left, |
8676 Token::Value op, | 8627 Token::Value op, |
8677 HValue* right) { | 8628 HValue* right) { |
8678 return op == Token::EQ_STRICT && | 8629 return op == Token::EQ_STRICT && |
8679 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || | 8630 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || |
8680 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); | 8631 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); |
8681 } | 8632 } |
8682 | 8633 |
8683 | 8634 |
8684 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 8635 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
8685 ASSERT(!HasStackOverflow()); | 8636 ASSERT(!HasStackOverflow()); |
8686 ASSERT(current_block() != NULL); | 8637 ASSERT(current_block() != NULL); |
8687 ASSERT(current_block()->HasPredecessor()); | 8638 ASSERT(current_block()->HasPredecessor()); |
8688 if (IsClassOfTest(expr)) { | 8639 if (IsClassOfTest(expr)) { |
8689 CallRuntime* call = expr->left()->AsCallRuntime(); | 8640 CallRuntime* call = expr->left()->AsCallRuntime(); |
8690 ASSERT(call->arguments()->length() == 1); | 8641 ASSERT(call->arguments()->length() == 1); |
8691 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8642 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8692 HValue* value = Pop(); | 8643 HValue* value = Pop(); |
8693 Literal* literal = expr->right()->AsLiteral(); | 8644 Literal* literal = expr->right()->AsLiteral(); |
8694 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 8645 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8827 HCompareIDAndBranch* result = | 8778 HCompareIDAndBranch* result = |
8828 new(zone()) HCompareIDAndBranch(left, right, op); | 8779 new(zone()) HCompareIDAndBranch(left, right, op); |
8829 result->set_observed_input_representation(left_rep, right_rep); | 8780 result->set_observed_input_representation(left_rep, right_rep); |
8830 result->set_position(expr->position()); | 8781 result->set_position(expr->position()); |
8831 return ast_context()->ReturnControl(result, expr->id()); | 8782 return ast_context()->ReturnControl(result, expr->id()); |
8832 } | 8783 } |
8833 } | 8784 } |
8834 } | 8785 } |
8835 | 8786 |
8836 | 8787 |
8837 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 8788 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
8838 HValue* value, | 8789 HValue* value, |
8839 NilValue nil) { | 8790 NilValue nil) { |
8840 ASSERT(!HasStackOverflow()); | 8791 ASSERT(!HasStackOverflow()); |
8841 ASSERT(current_block() != NULL); | 8792 ASSERT(current_block() != NULL); |
8842 ASSERT(current_block()->HasPredecessor()); | 8793 ASSERT(current_block()->HasPredecessor()); |
8843 EqualityKind kind = | 8794 EqualityKind kind = |
8844 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; | 8795 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; |
8845 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); | 8796 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); |
8846 instr->set_position(expr->position()); | 8797 instr->set_position(expr->position()); |
8847 return ast_context()->ReturnControl(instr, expr->id()); | 8798 return ast_context()->ReturnControl(instr, expr->id()); |
8848 } | 8799 } |
8849 | 8800 |
8850 | 8801 |
8851 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 8802 HInstruction* HGraphBuilder::BuildThisFunction() { |
8852 // If we share optimized code between different closures, the | 8803 // If we share optimized code between different closures, the |
8853 // this-function is not a constant, except inside an inlined body. | 8804 // this-function is not a constant, except inside an inlined body. |
8854 if (function_state()->outer() != NULL) { | 8805 if (function_state()->outer() != NULL) { |
8855 return new(zone()) HConstant( | 8806 return new(zone()) HConstant( |
8856 function_state()->compilation_info()->closure(), | 8807 function_state()->compilation_info()->closure(), |
8857 Representation::Tagged()); | 8808 Representation::Tagged()); |
8858 } else { | 8809 } else { |
8859 return new(zone()) HThisFunction; | 8810 return new(zone()) HThisFunction; |
8860 } | 8811 } |
8861 } | 8812 } |
8862 | 8813 |
8863 | 8814 |
8864 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 8815 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
8865 ASSERT(!HasStackOverflow()); | 8816 ASSERT(!HasStackOverflow()); |
8866 ASSERT(current_block() != NULL); | 8817 ASSERT(current_block() != NULL); |
8867 ASSERT(current_block()->HasPredecessor()); | 8818 ASSERT(current_block()->HasPredecessor()); |
8868 HInstruction* instr = BuildThisFunction(); | 8819 HInstruction* instr = BuildThisFunction(); |
8869 return ast_context()->ReturnInstruction(instr, expr->id()); | 8820 return ast_context()->ReturnInstruction(instr, expr->id()); |
8870 } | 8821 } |
8871 | 8822 |
8872 | 8823 |
8873 void HOptimizedGraphBuilder::VisitDeclarations( | 8824 void HGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) { |
8874 ZoneList<Declaration*>* declarations) { | |
8875 ASSERT(globals_.is_empty()); | 8825 ASSERT(globals_.is_empty()); |
8876 AstVisitor::VisitDeclarations(declarations); | 8826 AstVisitor::VisitDeclarations(declarations); |
8877 if (!globals_.is_empty()) { | 8827 if (!globals_.is_empty()) { |
8878 Handle<FixedArray> array = | 8828 Handle<FixedArray> array = |
8879 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 8829 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
8880 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 8830 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
8881 int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | | 8831 int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | |
8882 DeclareGlobalsNativeFlag::encode(info()->is_native()) | | 8832 DeclareGlobalsNativeFlag::encode(info()->is_native()) | |
8883 DeclareGlobalsLanguageMode::encode(info()->language_mode()); | 8833 DeclareGlobalsLanguageMode::encode(info()->language_mode()); |
8884 HInstruction* result = new(zone()) HDeclareGlobals( | 8834 HInstruction* result = new(zone()) HDeclareGlobals( |
8885 environment()->LookupContext(), array, flags); | 8835 environment()->LookupContext(), array, flags); |
8886 AddInstruction(result); | 8836 AddInstruction(result); |
8887 globals_.Clear(); | 8837 globals_.Clear(); |
8888 } | 8838 } |
8889 } | 8839 } |
8890 | 8840 |
8891 | 8841 |
8892 void HOptimizedGraphBuilder::VisitVariableDeclaration( | 8842 void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* declaration) { |
8893 VariableDeclaration* declaration) { | |
8894 VariableProxy* proxy = declaration->proxy(); | 8843 VariableProxy* proxy = declaration->proxy(); |
8895 VariableMode mode = declaration->mode(); | 8844 VariableMode mode = declaration->mode(); |
8896 Variable* variable = proxy->var(); | 8845 Variable* variable = proxy->var(); |
8897 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; | 8846 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; |
8898 switch (variable->location()) { | 8847 switch (variable->location()) { |
8899 case Variable::UNALLOCATED: | 8848 case Variable::UNALLOCATED: |
8900 globals_.Add(variable->name(), zone()); | 8849 globals_.Add(variable->name(), zone()); |
8901 globals_.Add(variable->binding_needs_init() | 8850 globals_.Add(variable->binding_needs_init() |
8902 ? isolate()->factory()->the_hole_value() | 8851 ? isolate()->factory()->the_hole_value() |
8903 : isolate()->factory()->undefined_value(), zone()); | 8852 : isolate()->factory()->undefined_value(), zone()); |
(...skipping 16 matching lines...) Expand all Loading... |
8920 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8869 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
8921 } | 8870 } |
8922 } | 8871 } |
8923 break; | 8872 break; |
8924 case Variable::LOOKUP: | 8873 case Variable::LOOKUP: |
8925 return Bailout("unsupported lookup slot in declaration"); | 8874 return Bailout("unsupported lookup slot in declaration"); |
8926 } | 8875 } |
8927 } | 8876 } |
8928 | 8877 |
8929 | 8878 |
8930 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 8879 void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* declaration) { |
8931 FunctionDeclaration* declaration) { | |
8932 VariableProxy* proxy = declaration->proxy(); | 8880 VariableProxy* proxy = declaration->proxy(); |
8933 Variable* variable = proxy->var(); | 8881 Variable* variable = proxy->var(); |
8934 switch (variable->location()) { | 8882 switch (variable->location()) { |
8935 case Variable::UNALLOCATED: { | 8883 case Variable::UNALLOCATED: { |
8936 globals_.Add(variable->name(), zone()); | 8884 globals_.Add(variable->name(), zone()); |
8937 Handle<SharedFunctionInfo> function = | 8885 Handle<SharedFunctionInfo> function = |
8938 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); | 8886 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); |
8939 // Check for stack-overflow exception. | 8887 // Check for stack-overflow exception. |
8940 if (function.is_null()) return SetStackOverflow(); | 8888 if (function.is_null()) return SetStackOverflow(); |
8941 globals_.Add(function, zone()); | 8889 globals_.Add(function, zone()); |
(...skipping 17 matching lines...) Expand all Loading... |
8959 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8907 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
8960 } | 8908 } |
8961 break; | 8909 break; |
8962 } | 8910 } |
8963 case Variable::LOOKUP: | 8911 case Variable::LOOKUP: |
8964 return Bailout("unsupported lookup slot in declaration"); | 8912 return Bailout("unsupported lookup slot in declaration"); |
8965 } | 8913 } |
8966 } | 8914 } |
8967 | 8915 |
8968 | 8916 |
8969 void HOptimizedGraphBuilder::VisitModuleDeclaration( | 8917 void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
8970 ModuleDeclaration* declaration) { | |
8971 UNREACHABLE(); | 8918 UNREACHABLE(); |
8972 } | 8919 } |
8973 | 8920 |
8974 | 8921 |
8975 void HOptimizedGraphBuilder::VisitImportDeclaration( | 8922 void HGraphBuilder::VisitImportDeclaration(ImportDeclaration* declaration) { |
8976 ImportDeclaration* declaration) { | |
8977 UNREACHABLE(); | 8923 UNREACHABLE(); |
8978 } | 8924 } |
8979 | 8925 |
8980 | 8926 |
8981 void HOptimizedGraphBuilder::VisitExportDeclaration( | 8927 void HGraphBuilder::VisitExportDeclaration(ExportDeclaration* declaration) { |
8982 ExportDeclaration* declaration) { | |
8983 UNREACHABLE(); | 8928 UNREACHABLE(); |
8984 } | 8929 } |
8985 | 8930 |
8986 | 8931 |
8987 void HOptimizedGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) { | 8932 void HGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) { |
8988 UNREACHABLE(); | 8933 UNREACHABLE(); |
8989 } | 8934 } |
8990 | 8935 |
8991 | 8936 |
8992 void HOptimizedGraphBuilder::VisitModuleVariable(ModuleVariable* module) { | 8937 void HGraphBuilder::VisitModuleVariable(ModuleVariable* module) { |
8993 UNREACHABLE(); | 8938 UNREACHABLE(); |
8994 } | 8939 } |
8995 | 8940 |
8996 | 8941 |
8997 void HOptimizedGraphBuilder::VisitModulePath(ModulePath* module) { | 8942 void HGraphBuilder::VisitModulePath(ModulePath* module) { |
8998 UNREACHABLE(); | 8943 UNREACHABLE(); |
8999 } | 8944 } |
9000 | 8945 |
9001 | 8946 |
9002 void HOptimizedGraphBuilder::VisitModuleUrl(ModuleUrl* module) { | 8947 void HGraphBuilder::VisitModuleUrl(ModuleUrl* module) { |
9003 UNREACHABLE(); | 8948 UNREACHABLE(); |
9004 } | 8949 } |
9005 | 8950 |
9006 | 8951 |
9007 void HOptimizedGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { | 8952 void HGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { |
9008 UNREACHABLE(); | 8953 UNREACHABLE(); |
9009 } | 8954 } |
9010 | 8955 |
9011 | 8956 |
9012 // Generators for inline runtime functions. | 8957 // Generators for inline runtime functions. |
9013 // Support for types. | 8958 // Support for types. |
9014 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) { | 8959 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { |
9015 ASSERT(call->arguments()->length() == 1); | 8960 ASSERT(call->arguments()->length() == 1); |
9016 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8961 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9017 HValue* value = Pop(); | 8962 HValue* value = Pop(); |
9018 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); | 8963 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); |
9019 return ast_context()->ReturnControl(result, call->id()); | 8964 return ast_context()->ReturnControl(result, call->id()); |
9020 } | 8965 } |
9021 | 8966 |
9022 | 8967 |
9023 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { | 8968 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { |
9024 ASSERT(call->arguments()->length() == 1); | 8969 ASSERT(call->arguments()->length() == 1); |
9025 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8970 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9026 HValue* value = Pop(); | 8971 HValue* value = Pop(); |
9027 HHasInstanceTypeAndBranch* result = | 8972 HHasInstanceTypeAndBranch* result = |
9028 new(zone()) HHasInstanceTypeAndBranch(value, | 8973 new(zone()) HHasInstanceTypeAndBranch(value, |
9029 FIRST_SPEC_OBJECT_TYPE, | 8974 FIRST_SPEC_OBJECT_TYPE, |
9030 LAST_SPEC_OBJECT_TYPE); | 8975 LAST_SPEC_OBJECT_TYPE); |
9031 return ast_context()->ReturnControl(result, call->id()); | 8976 return ast_context()->ReturnControl(result, call->id()); |
9032 } | 8977 } |
9033 | 8978 |
9034 | 8979 |
9035 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) { | 8980 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { |
9036 ASSERT(call->arguments()->length() == 1); | 8981 ASSERT(call->arguments()->length() == 1); |
9037 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8982 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9038 HValue* value = Pop(); | 8983 HValue* value = Pop(); |
9039 HHasInstanceTypeAndBranch* result = | 8984 HHasInstanceTypeAndBranch* result = |
9040 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); | 8985 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); |
9041 return ast_context()->ReturnControl(result, call->id()); | 8986 return ast_context()->ReturnControl(result, call->id()); |
9042 } | 8987 } |
9043 | 8988 |
9044 | 8989 |
9045 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { | 8990 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { |
9046 ASSERT(call->arguments()->length() == 1); | 8991 ASSERT(call->arguments()->length() == 1); |
9047 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8992 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9048 HValue* value = Pop(); | 8993 HValue* value = Pop(); |
9049 HHasCachedArrayIndexAndBranch* result = | 8994 HHasCachedArrayIndexAndBranch* result = |
9050 new(zone()) HHasCachedArrayIndexAndBranch(value); | 8995 new(zone()) HHasCachedArrayIndexAndBranch(value); |
9051 return ast_context()->ReturnControl(result, call->id()); | 8996 return ast_context()->ReturnControl(result, call->id()); |
9052 } | 8997 } |
9053 | 8998 |
9054 | 8999 |
9055 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) { | 9000 void HGraphBuilder::GenerateIsArray(CallRuntime* call) { |
9056 ASSERT(call->arguments()->length() == 1); | 9001 ASSERT(call->arguments()->length() == 1); |
9057 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9002 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9058 HValue* value = Pop(); | 9003 HValue* value = Pop(); |
9059 HHasInstanceTypeAndBranch* result = | 9004 HHasInstanceTypeAndBranch* result = |
9060 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); | 9005 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); |
9061 return ast_context()->ReturnControl(result, call->id()); | 9006 return ast_context()->ReturnControl(result, call->id()); |
9062 } | 9007 } |
9063 | 9008 |
9064 | 9009 |
9065 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) { | 9010 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { |
9066 ASSERT(call->arguments()->length() == 1); | 9011 ASSERT(call->arguments()->length() == 1); |
9067 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9012 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9068 HValue* value = Pop(); | 9013 HValue* value = Pop(); |
9069 HHasInstanceTypeAndBranch* result = | 9014 HHasInstanceTypeAndBranch* result = |
9070 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE); | 9015 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE); |
9071 return ast_context()->ReturnControl(result, call->id()); | 9016 return ast_context()->ReturnControl(result, call->id()); |
9072 } | 9017 } |
9073 | 9018 |
9074 | 9019 |
9075 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) { | 9020 void HGraphBuilder::GenerateIsObject(CallRuntime* call) { |
9076 ASSERT(call->arguments()->length() == 1); | 9021 ASSERT(call->arguments()->length() == 1); |
9077 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9022 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9078 HValue* value = Pop(); | 9023 HValue* value = Pop(); |
9079 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); | 9024 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); |
9080 return ast_context()->ReturnControl(result, call->id()); | 9025 return ast_context()->ReturnControl(result, call->id()); |
9081 } | 9026 } |
9082 | 9027 |
9083 | 9028 |
9084 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { | 9029 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
9085 return Bailout("inlined runtime function: IsNonNegativeSmi"); | 9030 return Bailout("inlined runtime function: IsNonNegativeSmi"); |
9086 } | 9031 } |
9087 | 9032 |
9088 | 9033 |
9089 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { | 9034 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
9090 ASSERT(call->arguments()->length() == 1); | 9035 ASSERT(call->arguments()->length() == 1); |
9091 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9036 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9092 HValue* value = Pop(); | 9037 HValue* value = Pop(); |
9093 HIsUndetectableAndBranch* result = | 9038 HIsUndetectableAndBranch* result = |
9094 new(zone()) HIsUndetectableAndBranch(value); | 9039 new(zone()) HIsUndetectableAndBranch(value); |
9095 return ast_context()->ReturnControl(result, call->id()); | 9040 return ast_context()->ReturnControl(result, call->id()); |
9096 } | 9041 } |
9097 | 9042 |
9098 | 9043 |
9099 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 9044 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
9100 CallRuntime* call) { | 9045 CallRuntime* call) { |
9101 return Bailout( | 9046 return Bailout( |
9102 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | 9047 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
9103 } | 9048 } |
9104 | 9049 |
9105 | 9050 |
9106 // Support for construct call checks. | 9051 // Support for construct call checks. |
9107 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { | 9052 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { |
9108 ASSERT(call->arguments()->length() == 0); | 9053 ASSERT(call->arguments()->length() == 0); |
9109 if (function_state()->outer() != NULL) { | 9054 if (function_state()->outer() != NULL) { |
9110 // We are generating graph for inlined function. | 9055 // We are generating graph for inlined function. |
9111 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN | 9056 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN |
9112 ? graph()->GetConstantTrue() | 9057 ? graph()->GetConstantTrue() |
9113 : graph()->GetConstantFalse(); | 9058 : graph()->GetConstantFalse(); |
9114 return ast_context()->ReturnValue(value); | 9059 return ast_context()->ReturnValue(value); |
9115 } else { | 9060 } else { |
9116 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, | 9061 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, |
9117 call->id()); | 9062 call->id()); |
9118 } | 9063 } |
9119 } | 9064 } |
9120 | 9065 |
9121 | 9066 |
9122 // Support for arguments.length and arguments[?]. | 9067 // Support for arguments.length and arguments[?]. |
9123 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 9068 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
9124 // Our implementation of arguments (based on this stack frame or an | 9069 // Our implementation of arguments (based on this stack frame or an |
9125 // adapter below it) does not work for inlined functions. This runtime | 9070 // adapter below it) does not work for inlined functions. This runtime |
9126 // function is blacklisted by AstNode::IsInlineable. | 9071 // function is blacklisted by AstNode::IsInlineable. |
9127 ASSERT(function_state()->outer() == NULL); | 9072 ASSERT(function_state()->outer() == NULL); |
9128 ASSERT(call->arguments()->length() == 0); | 9073 ASSERT(call->arguments()->length() == 0); |
9129 HInstruction* elements = AddInstruction( | 9074 HInstruction* elements = AddInstruction( |
9130 new(zone()) HArgumentsElements(false)); | 9075 new(zone()) HArgumentsElements(false)); |
9131 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); | 9076 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); |
9132 return ast_context()->ReturnInstruction(result, call->id()); | 9077 return ast_context()->ReturnInstruction(result, call->id()); |
9133 } | 9078 } |
9134 | 9079 |
9135 | 9080 |
9136 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { | 9081 void HGraphBuilder::GenerateArguments(CallRuntime* call) { |
9137 // Our implementation of arguments (based on this stack frame or an | 9082 // Our implementation of arguments (based on this stack frame or an |
9138 // adapter below it) does not work for inlined functions. This runtime | 9083 // adapter below it) does not work for inlined functions. This runtime |
9139 // function is blacklisted by AstNode::IsInlineable. | 9084 // function is blacklisted by AstNode::IsInlineable. |
9140 ASSERT(function_state()->outer() == NULL); | 9085 ASSERT(function_state()->outer() == NULL); |
9141 ASSERT(call->arguments()->length() == 1); | 9086 ASSERT(call->arguments()->length() == 1); |
9142 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9087 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9143 HValue* index = Pop(); | 9088 HValue* index = Pop(); |
9144 HInstruction* elements = AddInstruction( | 9089 HInstruction* elements = AddInstruction( |
9145 new(zone()) HArgumentsElements(false)); | 9090 new(zone()) HArgumentsElements(false)); |
9146 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); | 9091 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
9147 HInstruction* checked_index = | 9092 HInstruction* checked_index = |
9148 AddInstruction(new(zone()) HBoundsCheck(index, length)); | 9093 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
9149 HAccessArgumentsAt* result = | 9094 HAccessArgumentsAt* result = |
9150 new(zone()) HAccessArgumentsAt(elements, length, checked_index); | 9095 new(zone()) HAccessArgumentsAt(elements, length, checked_index); |
9151 return ast_context()->ReturnInstruction(result, call->id()); | 9096 return ast_context()->ReturnInstruction(result, call->id()); |
9152 } | 9097 } |
9153 | 9098 |
9154 | 9099 |
9155 // Support for accessing the class and value fields of an object. | 9100 // Support for accessing the class and value fields of an object. |
9156 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { | 9101 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { |
9157 // The special form detected by IsClassOfTest is detected before we get here | 9102 // The special form detected by IsClassOfTest is detected before we get here |
9158 // and does not cause a bailout. | 9103 // and does not cause a bailout. |
9159 return Bailout("inlined runtime function: ClassOf"); | 9104 return Bailout("inlined runtime function: ClassOf"); |
9160 } | 9105 } |
9161 | 9106 |
9162 | 9107 |
9163 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { | 9108 void HGraphBuilder::GenerateValueOf(CallRuntime* call) { |
9164 ASSERT(call->arguments()->length() == 1); | 9109 ASSERT(call->arguments()->length() == 1); |
9165 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9110 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9166 HValue* value = Pop(); | 9111 HValue* value = Pop(); |
9167 HValueOf* result = new(zone()) HValueOf(value); | 9112 HValueOf* result = new(zone()) HValueOf(value); |
9168 return ast_context()->ReturnInstruction(result, call->id()); | 9113 return ast_context()->ReturnInstruction(result, call->id()); |
9169 } | 9114 } |
9170 | 9115 |
9171 | 9116 |
9172 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) { | 9117 void HGraphBuilder::GenerateDateField(CallRuntime* call) { |
9173 ASSERT(call->arguments()->length() == 2); | 9118 ASSERT(call->arguments()->length() == 2); |
9174 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); | 9119 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); |
9175 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle())); | 9120 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle())); |
9176 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9121 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9177 HValue* date = Pop(); | 9122 HValue* date = Pop(); |
9178 HDateField* result = new(zone()) HDateField(date, index); | 9123 HDateField* result = new(zone()) HDateField(date, index); |
9179 return ast_context()->ReturnInstruction(result, call->id()); | 9124 return ast_context()->ReturnInstruction(result, call->id()); |
9180 } | 9125 } |
9181 | 9126 |
9182 | 9127 |
9183 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { | 9128 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { |
9184 ASSERT(call->arguments()->length() == 2); | 9129 ASSERT(call->arguments()->length() == 2); |
9185 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9130 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9186 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9131 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9187 HValue* value = Pop(); | 9132 HValue* value = Pop(); |
9188 HValue* object = Pop(); | 9133 HValue* object = Pop(); |
9189 // Check if object is a not a smi. | 9134 // Check if object is a not a smi. |
9190 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object); | 9135 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object); |
9191 HBasicBlock* if_smi = graph()->CreateBasicBlock(); | 9136 HBasicBlock* if_smi = graph()->CreateBasicBlock(); |
9192 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); | 9137 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); |
9193 HBasicBlock* join = graph()->CreateBasicBlock(); | 9138 HBasicBlock* join = graph()->CreateBasicBlock(); |
(...skipping 22 matching lines...) Expand all Loading... |
9216 true, // in-object store. | 9161 true, // in-object store. |
9217 JSValue::kValueOffset)); | 9162 JSValue::kValueOffset)); |
9218 if_js_value->Goto(join); | 9163 if_js_value->Goto(join); |
9219 join->SetJoinId(call->id()); | 9164 join->SetJoinId(call->id()); |
9220 set_current_block(join); | 9165 set_current_block(join); |
9221 return ast_context()->ReturnValue(value); | 9166 return ast_context()->ReturnValue(value); |
9222 } | 9167 } |
9223 | 9168 |
9224 | 9169 |
9225 // Fast support for charCodeAt(n). | 9170 // Fast support for charCodeAt(n). |
9226 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 9171 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
9227 ASSERT(call->arguments()->length() == 2); | 9172 ASSERT(call->arguments()->length() == 2); |
9228 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9173 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9229 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9174 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9230 HValue* index = Pop(); | 9175 HValue* index = Pop(); |
9231 HValue* string = Pop(); | 9176 HValue* string = Pop(); |
9232 HValue* context = environment()->LookupContext(); | 9177 HValue* context = environment()->LookupContext(); |
9233 HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index); | 9178 HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index); |
9234 return ast_context()->ReturnInstruction(result, call->id()); | 9179 return ast_context()->ReturnInstruction(result, call->id()); |
9235 } | 9180 } |
9236 | 9181 |
9237 | 9182 |
9238 // Fast support for string.charAt(n) and string[n]. | 9183 // Fast support for string.charAt(n) and string[n]. |
9239 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { | 9184 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
9240 ASSERT(call->arguments()->length() == 1); | 9185 ASSERT(call->arguments()->length() == 1); |
9241 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9186 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9242 HValue* char_code = Pop(); | 9187 HValue* char_code = Pop(); |
9243 HValue* context = environment()->LookupContext(); | 9188 HValue* context = environment()->LookupContext(); |
9244 HStringCharFromCode* result = | 9189 HStringCharFromCode* result = |
9245 new(zone()) HStringCharFromCode(context, char_code); | 9190 new(zone()) HStringCharFromCode(context, char_code); |
9246 return ast_context()->ReturnInstruction(result, call->id()); | 9191 return ast_context()->ReturnInstruction(result, call->id()); |
9247 } | 9192 } |
9248 | 9193 |
9249 | 9194 |
9250 // Fast support for string.charAt(n) and string[n]. | 9195 // Fast support for string.charAt(n) and string[n]. |
9251 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { | 9196 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
9252 ASSERT(call->arguments()->length() == 2); | 9197 ASSERT(call->arguments()->length() == 2); |
9253 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9198 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9254 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9199 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9255 HValue* index = Pop(); | 9200 HValue* index = Pop(); |
9256 HValue* string = Pop(); | 9201 HValue* string = Pop(); |
9257 HValue* context = environment()->LookupContext(); | 9202 HValue* context = environment()->LookupContext(); |
9258 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); | 9203 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); |
9259 AddInstruction(char_code); | 9204 AddInstruction(char_code); |
9260 HStringCharFromCode* result = | 9205 HStringCharFromCode* result = |
9261 new(zone()) HStringCharFromCode(context, char_code); | 9206 new(zone()) HStringCharFromCode(context, char_code); |
9262 return ast_context()->ReturnInstruction(result, call->id()); | 9207 return ast_context()->ReturnInstruction(result, call->id()); |
9263 } | 9208 } |
9264 | 9209 |
9265 | 9210 |
9266 // Fast support for object equality testing. | 9211 // Fast support for object equality testing. |
9267 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 9212 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
9268 ASSERT(call->arguments()->length() == 2); | 9213 ASSERT(call->arguments()->length() == 2); |
9269 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9214 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9270 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9215 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9271 HValue* right = Pop(); | 9216 HValue* right = Pop(); |
9272 HValue* left = Pop(); | 9217 HValue* left = Pop(); |
9273 HCompareObjectEqAndBranch* result = | 9218 HCompareObjectEqAndBranch* result = |
9274 new(zone()) HCompareObjectEqAndBranch(left, right); | 9219 new(zone()) HCompareObjectEqAndBranch(left, right); |
9275 return ast_context()->ReturnControl(result, call->id()); | 9220 return ast_context()->ReturnControl(result, call->id()); |
9276 } | 9221 } |
9277 | 9222 |
9278 | 9223 |
9279 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { | 9224 void HGraphBuilder::GenerateLog(CallRuntime* call) { |
9280 // %_Log is ignored in optimized code. | 9225 // %_Log is ignored in optimized code. |
9281 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 9226 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
9282 } | 9227 } |
9283 | 9228 |
9284 | 9229 |
9285 // Fast support for Math.random(). | 9230 // Fast support for Math.random(). |
9286 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | 9231 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
9287 HValue* context = environment()->LookupContext(); | 9232 HValue* context = environment()->LookupContext(); |
9288 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 9233 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
9289 AddInstruction(global_object); | 9234 AddInstruction(global_object); |
9290 HRandom* result = new(zone()) HRandom(global_object); | 9235 HRandom* result = new(zone()) HRandom(global_object); |
9291 return ast_context()->ReturnInstruction(result, call->id()); | 9236 return ast_context()->ReturnInstruction(result, call->id()); |
9292 } | 9237 } |
9293 | 9238 |
9294 | 9239 |
9295 // Fast support for StringAdd. | 9240 // Fast support for StringAdd. |
9296 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 9241 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
9297 ASSERT_EQ(2, call->arguments()->length()); | 9242 ASSERT_EQ(2, call->arguments()->length()); |
9298 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9243 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9299 HValue* context = environment()->LookupContext(); | 9244 HValue* context = environment()->LookupContext(); |
9300 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); | 9245 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); |
9301 Drop(2); | 9246 Drop(2); |
9302 return ast_context()->ReturnInstruction(result, call->id()); | 9247 return ast_context()->ReturnInstruction(result, call->id()); |
9303 } | 9248 } |
9304 | 9249 |
9305 | 9250 |
9306 // Fast support for SubString. | 9251 // Fast support for SubString. |
9307 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 9252 void HGraphBuilder::GenerateSubString(CallRuntime* call) { |
9308 ASSERT_EQ(3, call->arguments()->length()); | 9253 ASSERT_EQ(3, call->arguments()->length()); |
9309 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9254 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9310 HValue* context = environment()->LookupContext(); | 9255 HValue* context = environment()->LookupContext(); |
9311 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); | 9256 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
9312 Drop(3); | 9257 Drop(3); |
9313 return ast_context()->ReturnInstruction(result, call->id()); | 9258 return ast_context()->ReturnInstruction(result, call->id()); |
9314 } | 9259 } |
9315 | 9260 |
9316 | 9261 |
9317 // Fast support for StringCompare. | 9262 // Fast support for StringCompare. |
9318 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 9263 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
9319 ASSERT_EQ(2, call->arguments()->length()); | 9264 ASSERT_EQ(2, call->arguments()->length()); |
9320 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9265 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9321 HValue* context = environment()->LookupContext(); | 9266 HValue* context = environment()->LookupContext(); |
9322 HCallStub* result = | 9267 HCallStub* result = |
9323 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); | 9268 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); |
9324 Drop(2); | 9269 Drop(2); |
9325 return ast_context()->ReturnInstruction(result, call->id()); | 9270 return ast_context()->ReturnInstruction(result, call->id()); |
9326 } | 9271 } |
9327 | 9272 |
9328 | 9273 |
9329 // Support for direct calls from JavaScript to native RegExp code. | 9274 // Support for direct calls from JavaScript to native RegExp code. |
9330 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 9275 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
9331 ASSERT_EQ(4, call->arguments()->length()); | 9276 ASSERT_EQ(4, call->arguments()->length()); |
9332 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9277 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9333 HValue* context = environment()->LookupContext(); | 9278 HValue* context = environment()->LookupContext(); |
9334 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); | 9279 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
9335 Drop(4); | 9280 Drop(4); |
9336 return ast_context()->ReturnInstruction(result, call->id()); | 9281 return ast_context()->ReturnInstruction(result, call->id()); |
9337 } | 9282 } |
9338 | 9283 |
9339 | 9284 |
9340 // Construct a RegExp exec result with two in-object properties. | 9285 // Construct a RegExp exec result with two in-object properties. |
9341 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 9286 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
9342 ASSERT_EQ(3, call->arguments()->length()); | 9287 ASSERT_EQ(3, call->arguments()->length()); |
9343 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9288 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9344 HValue* context = environment()->LookupContext(); | 9289 HValue* context = environment()->LookupContext(); |
9345 HCallStub* result = | 9290 HCallStub* result = |
9346 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | 9291 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
9347 Drop(3); | 9292 Drop(3); |
9348 return ast_context()->ReturnInstruction(result, call->id()); | 9293 return ast_context()->ReturnInstruction(result, call->id()); |
9349 } | 9294 } |
9350 | 9295 |
9351 | 9296 |
9352 // Support for fast native caches. | 9297 // Support for fast native caches. |
9353 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9298 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
9354 return Bailout("inlined runtime function: GetFromCache"); | 9299 return Bailout("inlined runtime function: GetFromCache"); |
9355 } | 9300 } |
9356 | 9301 |
9357 | 9302 |
9358 // Fast support for number to string. | 9303 // Fast support for number to string. |
9359 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 9304 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
9360 ASSERT_EQ(1, call->arguments()->length()); | 9305 ASSERT_EQ(1, call->arguments()->length()); |
9361 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9306 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9362 HValue* context = environment()->LookupContext(); | 9307 HValue* context = environment()->LookupContext(); |
9363 HCallStub* result = | 9308 HCallStub* result = |
9364 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 9309 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
9365 Drop(1); | 9310 Drop(1); |
9366 return ast_context()->ReturnInstruction(result, call->id()); | 9311 return ast_context()->ReturnInstruction(result, call->id()); |
9367 } | 9312 } |
9368 | 9313 |
9369 | 9314 |
9370 // Fast call for custom callbacks. | 9315 // Fast call for custom callbacks. |
9371 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 9316 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
9372 // 1 ~ The function to call is not itself an argument to the call. | 9317 // 1 ~ The function to call is not itself an argument to the call. |
9373 int arg_count = call->arguments()->length() - 1; | 9318 int arg_count = call->arguments()->length() - 1; |
9374 ASSERT(arg_count >= 1); // There's always at least a receiver. | 9319 ASSERT(arg_count >= 1); // There's always at least a receiver. |
9375 | 9320 |
9376 for (int i = 0; i < arg_count; ++i) { | 9321 for (int i = 0; i < arg_count; ++i) { |
9377 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); | 9322 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); |
9378 } | 9323 } |
9379 CHECK_ALIVE(VisitForValue(call->arguments()->last())); | 9324 CHECK_ALIVE(VisitForValue(call->arguments()->last())); |
9380 | 9325 |
9381 HValue* function = Pop(); | 9326 HValue* function = Pop(); |
(...skipping 23 matching lines...) Expand all Loading... |
9405 Push(call_result); | 9350 Push(call_result); |
9406 if_nonfunction->Goto(join); | 9351 if_nonfunction->Goto(join); |
9407 | 9352 |
9408 set_current_block(join); | 9353 set_current_block(join); |
9409 join->SetJoinId(call->id()); | 9354 join->SetJoinId(call->id()); |
9410 return ast_context()->ReturnValue(Pop()); | 9355 return ast_context()->ReturnValue(Pop()); |
9411 } | 9356 } |
9412 | 9357 |
9413 | 9358 |
9414 // Fast call to math functions. | 9359 // Fast call to math functions. |
9415 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { | 9360 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { |
9416 ASSERT_EQ(2, call->arguments()->length()); | 9361 ASSERT_EQ(2, call->arguments()->length()); |
9417 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9362 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9418 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9363 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9419 HValue* right = Pop(); | 9364 HValue* right = Pop(); |
9420 HValue* left = Pop(); | 9365 HValue* left = Pop(); |
9421 HPower* result = new(zone()) HPower(left, right); | 9366 HPower* result = new(zone()) HPower(left, right); |
9422 return ast_context()->ReturnInstruction(result, call->id()); | 9367 return ast_context()->ReturnInstruction(result, call->id()); |
9423 } | 9368 } |
9424 | 9369 |
9425 | 9370 |
9426 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { | 9371 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { |
9427 ASSERT_EQ(1, call->arguments()->length()); | 9372 ASSERT_EQ(1, call->arguments()->length()); |
9428 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9373 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9429 HValue* context = environment()->LookupContext(); | 9374 HValue* context = environment()->LookupContext(); |
9430 HCallStub* result = | 9375 HCallStub* result = |
9431 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9376 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9432 result->set_transcendental_type(TranscendentalCache::SIN); | 9377 result->set_transcendental_type(TranscendentalCache::SIN); |
9433 Drop(1); | 9378 Drop(1); |
9434 return ast_context()->ReturnInstruction(result, call->id()); | 9379 return ast_context()->ReturnInstruction(result, call->id()); |
9435 } | 9380 } |
9436 | 9381 |
9437 | 9382 |
9438 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) { | 9383 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { |
9439 ASSERT_EQ(1, call->arguments()->length()); | 9384 ASSERT_EQ(1, call->arguments()->length()); |
9440 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9385 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9441 HValue* context = environment()->LookupContext(); | 9386 HValue* context = environment()->LookupContext(); |
9442 HCallStub* result = | 9387 HCallStub* result = |
9443 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9388 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9444 result->set_transcendental_type(TranscendentalCache::COS); | 9389 result->set_transcendental_type(TranscendentalCache::COS); |
9445 Drop(1); | 9390 Drop(1); |
9446 return ast_context()->ReturnInstruction(result, call->id()); | 9391 return ast_context()->ReturnInstruction(result, call->id()); |
9447 } | 9392 } |
9448 | 9393 |
9449 | 9394 |
9450 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) { | 9395 void HGraphBuilder::GenerateMathTan(CallRuntime* call) { |
9451 ASSERT_EQ(1, call->arguments()->length()); | 9396 ASSERT_EQ(1, call->arguments()->length()); |
9452 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9397 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9453 HValue* context = environment()->LookupContext(); | 9398 HValue* context = environment()->LookupContext(); |
9454 HCallStub* result = | 9399 HCallStub* result = |
9455 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9400 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9456 result->set_transcendental_type(TranscendentalCache::TAN); | 9401 result->set_transcendental_type(TranscendentalCache::TAN); |
9457 Drop(1); | 9402 Drop(1); |
9458 return ast_context()->ReturnInstruction(result, call->id()); | 9403 return ast_context()->ReturnInstruction(result, call->id()); |
9459 } | 9404 } |
9460 | 9405 |
9461 | 9406 |
9462 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { | 9407 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { |
9463 ASSERT_EQ(1, call->arguments()->length()); | 9408 ASSERT_EQ(1, call->arguments()->length()); |
9464 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9409 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9465 HValue* context = environment()->LookupContext(); | 9410 HValue* context = environment()->LookupContext(); |
9466 HCallStub* result = | 9411 HCallStub* result = |
9467 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9412 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9468 result->set_transcendental_type(TranscendentalCache::LOG); | 9413 result->set_transcendental_type(TranscendentalCache::LOG); |
9469 Drop(1); | 9414 Drop(1); |
9470 return ast_context()->ReturnInstruction(result, call->id()); | 9415 return ast_context()->ReturnInstruction(result, call->id()); |
9471 } | 9416 } |
9472 | 9417 |
9473 | 9418 |
9474 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 9419 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
9475 return Bailout("inlined runtime function: MathSqrt"); | 9420 return Bailout("inlined runtime function: MathSqrt"); |
9476 } | 9421 } |
9477 | 9422 |
9478 | 9423 |
9479 // Check whether two RegExps are equivalent | 9424 // Check whether two RegExps are equivalent |
9480 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 9425 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
9481 return Bailout("inlined runtime function: IsRegExpEquivalent"); | 9426 return Bailout("inlined runtime function: IsRegExpEquivalent"); |
9482 } | 9427 } |
9483 | 9428 |
9484 | 9429 |
9485 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { | 9430 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
9486 ASSERT(call->arguments()->length() == 1); | 9431 ASSERT(call->arguments()->length() == 1); |
9487 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9432 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9488 HValue* value = Pop(); | 9433 HValue* value = Pop(); |
9489 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); | 9434 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); |
9490 return ast_context()->ReturnInstruction(result, call->id()); | 9435 return ast_context()->ReturnInstruction(result, call->id()); |
9491 } | 9436 } |
9492 | 9437 |
9493 | 9438 |
9494 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { | 9439 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { |
9495 return Bailout("inlined runtime function: FastAsciiArrayJoin"); | 9440 return Bailout("inlined runtime function: FastAsciiArrayJoin"); |
9496 } | 9441 } |
9497 | 9442 |
9498 | 9443 |
9499 #undef CHECK_BAILOUT | 9444 #undef CHECK_BAILOUT |
9500 #undef CHECK_ALIVE | 9445 #undef CHECK_ALIVE |
9501 | 9446 |
9502 | 9447 |
9503 HEnvironment::HEnvironment(HEnvironment* outer, | 9448 HEnvironment::HEnvironment(HEnvironment* outer, |
9504 Scope* scope, | 9449 Scope* scope, |
9505 Handle<JSFunction> closure, | 9450 Handle<JSFunction> closure, |
9506 Zone* zone) | 9451 Zone* zone) |
9507 : closure_(closure), | 9452 : closure_(closure), |
9508 values_(0, zone), | 9453 values_(0, zone), |
9509 assigned_variables_(4, zone), | 9454 assigned_variables_(4, zone), |
9510 frame_type_(JS_FUNCTION), | 9455 frame_type_(JS_FUNCTION), |
9511 parameter_count_(0), | 9456 parameter_count_(0), |
9512 specials_count_(1), | 9457 specials_count_(1), |
9513 local_count_(0), | 9458 local_count_(0), |
9514 outer_(outer), | 9459 outer_(outer), |
9515 entry_(NULL), | 9460 entry_(NULL), |
9516 pop_count_(0), | 9461 pop_count_(0), |
9517 push_count_(0), | 9462 push_count_(0), |
9518 ast_id_(BailoutId::None()), | 9463 ast_id_(BailoutId::None()), |
9519 zone_(zone) { | 9464 zone_(zone) { |
9520 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); | 9465 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); |
9521 } | 9466 } |
9522 | 9467 |
9523 | 9468 |
9524 HEnvironment::HEnvironment(Zone* zone) | |
9525 : values_(0, zone), | |
9526 assigned_variables_(0, zone), | |
9527 frame_type_(STUB), | |
9528 parameter_count_(0), | |
9529 specials_count_(0), | |
9530 local_count_(0), | |
9531 outer_(NULL), | |
9532 entry_(NULL), | |
9533 pop_count_(0), | |
9534 push_count_(0), | |
9535 ast_id_(BailoutId::None()), | |
9536 zone_(zone) { | |
9537 Initialize(0, 0, 0); | |
9538 } | |
9539 | |
9540 | |
9541 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone) | 9469 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone) |
9542 : values_(0, zone), | 9470 : values_(0, zone), |
9543 assigned_variables_(0, zone), | 9471 assigned_variables_(0, zone), |
9544 frame_type_(JS_FUNCTION), | 9472 frame_type_(JS_FUNCTION), |
9545 parameter_count_(0), | 9473 parameter_count_(0), |
9546 specials_count_(1), | 9474 specials_count_(1), |
9547 local_count_(0), | 9475 local_count_(0), |
9548 outer_(NULL), | 9476 outer_(NULL), |
9549 entry_(NULL), | 9477 entry_(NULL), |
9550 pop_count_(0), | 9478 pop_count_(0), |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9798 | 9726 |
9799 | 9727 |
9800 void HEnvironment::PrintToStd() { | 9728 void HEnvironment::PrintToStd() { |
9801 HeapStringAllocator string_allocator; | 9729 HeapStringAllocator string_allocator; |
9802 StringStream trace(&string_allocator); | 9730 StringStream trace(&string_allocator); |
9803 PrintTo(&trace); | 9731 PrintTo(&trace); |
9804 PrintF("%s", *trace.ToCString()); | 9732 PrintF("%s", *trace.ToCString()); |
9805 } | 9733 } |
9806 | 9734 |
9807 | 9735 |
9808 void HTracer::TraceCompilation(CompilationInfo* info) { | 9736 void HTracer::TraceCompilation(FunctionLiteral* function) { |
9809 Tag tag(this, "compilation"); | 9737 Tag tag(this, "compilation"); |
9810 if (info->IsOptimizing()) { | 9738 Handle<String> name = function->debug_name(); |
9811 Handle<String> name = info->function()->debug_name(); | 9739 PrintStringProperty("name", *name->ToCString()); |
9812 PrintStringProperty("name", *name->ToCString()); | 9740 PrintStringProperty("method", *name->ToCString()); |
9813 PrintStringProperty("method", *name->ToCString()); | |
9814 } else { | |
9815 CodeStub::Major major_key = info->code_stub()->MajorKey(); | |
9816 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); | |
9817 PrintStringProperty("method", "stub"); | |
9818 } | |
9819 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); | 9741 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); |
9820 } | 9742 } |
9821 | 9743 |
9822 | 9744 |
9823 void HTracer::TraceLithium(const char* name, LChunk* chunk) { | 9745 void HTracer::TraceLithium(const char* name, LChunk* chunk) { |
9824 Trace(name, chunk->graph(), chunk); | 9746 Trace(name, chunk->graph(), chunk); |
9825 } | 9747 } |
9826 | 9748 |
9827 | 9749 |
9828 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { | 9750 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10137 } | 10059 } |
10138 } | 10060 } |
10139 | 10061 |
10140 #ifdef DEBUG | 10062 #ifdef DEBUG |
10141 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10063 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
10142 if (allocator_ != NULL) allocator_->Verify(); | 10064 if (allocator_ != NULL) allocator_->Verify(); |
10143 #endif | 10065 #endif |
10144 } | 10066 } |
10145 | 10067 |
10146 } } // namespace v8::internal | 10068 } } // namespace v8::internal |
OLD | NEW |