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 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3928 } | 3755 } |
3929 instr->DeleteAndReplaceWith(NULL); | 3756 instr->DeleteAndReplaceWith(NULL); |
3930 for (int i = 0; i < instr->OperandCount(); ++i) { | 3757 for (int i = 0; i < instr->OperandCount(); ++i) { |
3931 HValue* operand = instr->OperandAt(i); | 3758 HValue* operand = instr->OperandAt(i); |
3932 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); | 3759 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); |
3933 } | 3760 } |
3934 } | 3761 } |
3935 } | 3762 } |
3936 | 3763 |
3937 | 3764 |
3938 void HOptimizedGraphBuilder::AddPhi(HPhi* instr) { | 3765 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 3766 ASSERT(current_block() != NULL); |
| 3767 current_block()->AddInstruction(instr); |
| 3768 return instr; |
| 3769 } |
| 3770 |
| 3771 |
| 3772 void HGraphBuilder::AddSimulate(BailoutId ast_id, RemovableSimulate removable) { |
| 3773 ASSERT(current_block() != NULL); |
| 3774 current_block()->AddSimulate(ast_id, removable); |
| 3775 } |
| 3776 |
| 3777 |
| 3778 void HGraphBuilder::AddPhi(HPhi* instr) { |
3939 ASSERT(current_block() != NULL); | 3779 ASSERT(current_block() != NULL); |
3940 current_block()->AddPhi(instr); | 3780 current_block()->AddPhi(instr); |
3941 } | 3781 } |
3942 | 3782 |
3943 | 3783 |
3944 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { | 3784 void HGraphBuilder::PushAndAdd(HInstruction* instr) { |
3945 Push(instr); | 3785 Push(instr); |
3946 AddInstruction(instr); | 3786 AddInstruction(instr); |
3947 } | 3787 } |
3948 | 3788 |
3949 | 3789 |
3950 template <class Instruction> | 3790 template <class Instruction> |
3951 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { | 3791 HInstruction* HGraphBuilder::PreProcessCall(Instruction* call) { |
3952 int count = call->argument_count(); | 3792 int count = call->argument_count(); |
3953 ZoneList<HValue*> arguments(count, zone()); | 3793 ZoneList<HValue*> arguments(count, zone()); |
3954 for (int i = 0; i < count; ++i) { | 3794 for (int i = 0; i < count; ++i) { |
3955 arguments.Add(Pop(), zone()); | 3795 arguments.Add(Pop(), zone()); |
3956 } | 3796 } |
3957 | 3797 |
3958 while (!arguments.is_empty()) { | 3798 while (!arguments.is_empty()) { |
3959 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); | 3799 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); |
3960 } | 3800 } |
3961 return call; | 3801 return call; |
3962 } | 3802 } |
3963 | 3803 |
3964 | 3804 |
3965 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { | 3805 void HGraphBuilder::SetUpScope(Scope* scope) { |
3966 HConstant* undefined_constant = new(zone()) HConstant( | 3806 HConstant* undefined_constant = new(zone()) HConstant( |
3967 isolate()->factory()->undefined_value(), Representation::Tagged()); | 3807 isolate()->factory()->undefined_value(), Representation::Tagged()); |
3968 AddInstruction(undefined_constant); | 3808 AddInstruction(undefined_constant); |
3969 graph()->set_undefined_constant(undefined_constant); | 3809 graph_->set_undefined_constant(undefined_constant); |
3970 | 3810 |
3971 HArgumentsObject* object = new(zone()) HArgumentsObject; | 3811 HArgumentsObject* object = new(zone()) HArgumentsObject; |
3972 AddInstruction(object); | 3812 AddInstruction(object); |
3973 graph()->SetArgumentsObject(object); | 3813 graph()->SetArgumentsObject(object); |
3974 | 3814 |
3975 // Set the initial values of parameters including "this". "This" has | 3815 // Set the initial values of parameters including "this". "This" has |
3976 // parameter index 0. | 3816 // parameter index 0. |
3977 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); | 3817 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); |
3978 | 3818 |
3979 for (int i = 0; i < environment()->parameter_count(); ++i) { | 3819 for (int i = 0; i < environment()->parameter_count(); ++i) { |
(...skipping 18 matching lines...) Expand all Loading... |
3998 if (!scope->arguments()->IsStackAllocated()) { | 3838 if (!scope->arguments()->IsStackAllocated()) { |
3999 return Bailout("context-allocated arguments"); | 3839 return Bailout("context-allocated arguments"); |
4000 } | 3840 } |
4001 | 3841 |
4002 environment()->Bind(scope->arguments(), | 3842 environment()->Bind(scope->arguments(), |
4003 graph()->GetArgumentsObject()); | 3843 graph()->GetArgumentsObject()); |
4004 } | 3844 } |
4005 } | 3845 } |
4006 | 3846 |
4007 | 3847 |
4008 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { | 3848 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { |
4009 for (int i = 0; i < statements->length(); i++) { | 3849 for (int i = 0; i < statements->length(); i++) { |
4010 CHECK_ALIVE(Visit(statements->at(i))); | 3850 CHECK_ALIVE(Visit(statements->at(i))); |
4011 } | 3851 } |
4012 } | 3852 } |
4013 | 3853 |
4014 | 3854 |
4015 HBasicBlock* HOptimizedGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 3855 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
4016 HBasicBlock* b = graph()->CreateBasicBlock(); | 3856 HBasicBlock* b = graph()->CreateBasicBlock(); |
4017 b->SetInitialEnvironment(env); | 3857 b->SetInitialEnvironment(env); |
4018 return b; | 3858 return b; |
4019 } | 3859 } |
4020 | 3860 |
4021 | 3861 |
4022 HBasicBlock* HOptimizedGraphBuilder::CreateLoopHeaderBlock() { | 3862 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
4023 HBasicBlock* header = graph()->CreateBasicBlock(); | 3863 HBasicBlock* header = graph()->CreateBasicBlock(); |
4024 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 3864 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
4025 header->SetInitialEnvironment(entry_env); | 3865 header->SetInitialEnvironment(entry_env); |
4026 header->AttachLoopInformation(); | 3866 header->AttachLoopInformation(); |
4027 return header; | 3867 return header; |
4028 } | 3868 } |
4029 | 3869 |
4030 | 3870 |
4031 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { | 3871 void HGraphBuilder::VisitBlock(Block* stmt) { |
4032 ASSERT(!HasStackOverflow()); | 3872 ASSERT(!HasStackOverflow()); |
4033 ASSERT(current_block() != NULL); | 3873 ASSERT(current_block() != NULL); |
4034 ASSERT(current_block()->HasPredecessor()); | 3874 ASSERT(current_block()->HasPredecessor()); |
4035 if (stmt->scope() != NULL) { | 3875 if (stmt->scope() != NULL) { |
4036 return Bailout("ScopedBlock"); | 3876 return Bailout("ScopedBlock"); |
4037 } | 3877 } |
4038 BreakAndContinueInfo break_info(stmt); | 3878 BreakAndContinueInfo break_info(stmt); |
4039 { BreakAndContinueScope push(&break_info, this); | 3879 { BreakAndContinueScope push(&break_info, this); |
4040 CHECK_BAILOUT(VisitStatements(stmt->statements())); | 3880 CHECK_BAILOUT(VisitStatements(stmt->statements())); |
4041 } | 3881 } |
4042 HBasicBlock* break_block = break_info.break_block(); | 3882 HBasicBlock* break_block = break_info.break_block(); |
4043 if (break_block != NULL) { | 3883 if (break_block != NULL) { |
4044 if (current_block() != NULL) current_block()->Goto(break_block); | 3884 if (current_block() != NULL) current_block()->Goto(break_block); |
4045 break_block->SetJoinId(stmt->ExitId()); | 3885 break_block->SetJoinId(stmt->ExitId()); |
4046 set_current_block(break_block); | 3886 set_current_block(break_block); |
4047 } | 3887 } |
4048 } | 3888 } |
4049 | 3889 |
4050 | 3890 |
4051 void HOptimizedGraphBuilder::VisitExpressionStatement( | 3891 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { |
4052 ExpressionStatement* stmt) { | |
4053 ASSERT(!HasStackOverflow()); | 3892 ASSERT(!HasStackOverflow()); |
4054 ASSERT(current_block() != NULL); | 3893 ASSERT(current_block() != NULL); |
4055 ASSERT(current_block()->HasPredecessor()); | 3894 ASSERT(current_block()->HasPredecessor()); |
4056 VisitForEffect(stmt->expression()); | 3895 VisitForEffect(stmt->expression()); |
4057 } | 3896 } |
4058 | 3897 |
4059 | 3898 |
4060 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { | 3899 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { |
4061 ASSERT(!HasStackOverflow()); | 3900 ASSERT(!HasStackOverflow()); |
4062 ASSERT(current_block() != NULL); | 3901 ASSERT(current_block() != NULL); |
4063 ASSERT(current_block()->HasPredecessor()); | 3902 ASSERT(current_block()->HasPredecessor()); |
4064 } | 3903 } |
4065 | 3904 |
4066 | 3905 |
4067 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 3906 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
4068 ASSERT(!HasStackOverflow()); | 3907 ASSERT(!HasStackOverflow()); |
4069 ASSERT(current_block() != NULL); | 3908 ASSERT(current_block() != NULL); |
4070 ASSERT(current_block()->HasPredecessor()); | 3909 ASSERT(current_block()->HasPredecessor()); |
4071 if (stmt->condition()->ToBooleanIsTrue()) { | 3910 if (stmt->condition()->ToBooleanIsTrue()) { |
4072 AddSimulate(stmt->ThenId()); | 3911 AddSimulate(stmt->ThenId()); |
4073 Visit(stmt->then_statement()); | 3912 Visit(stmt->then_statement()); |
4074 } else if (stmt->condition()->ToBooleanIsFalse()) { | 3913 } else if (stmt->condition()->ToBooleanIsFalse()) { |
4075 AddSimulate(stmt->ElseId()); | 3914 AddSimulate(stmt->ElseId()); |
4076 Visit(stmt->else_statement()); | 3915 Visit(stmt->else_statement()); |
4077 } else { | 3916 } else { |
(...skipping 18 matching lines...) Expand all Loading... |
4096 } else { | 3935 } else { |
4097 cond_false = NULL; | 3936 cond_false = NULL; |
4098 } | 3937 } |
4099 | 3938 |
4100 HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId()); | 3939 HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId()); |
4101 set_current_block(join); | 3940 set_current_block(join); |
4102 } | 3941 } |
4103 } | 3942 } |
4104 | 3943 |
4105 | 3944 |
4106 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get( | 3945 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( |
4107 BreakableStatement* stmt, | 3946 BreakableStatement* stmt, |
4108 BreakType type, | 3947 BreakType type, |
4109 int* drop_extra) { | 3948 int* drop_extra) { |
4110 *drop_extra = 0; | 3949 *drop_extra = 0; |
4111 BreakAndContinueScope* current = this; | 3950 BreakAndContinueScope* current = this; |
4112 while (current != NULL && current->info()->target() != stmt) { | 3951 while (current != NULL && current->info()->target() != stmt) { |
4113 *drop_extra += current->info()->drop_extra(); | 3952 *drop_extra += current->info()->drop_extra(); |
4114 current = current->next(); | 3953 current = current->next(); |
4115 } | 3954 } |
4116 ASSERT(current != NULL); // Always found (unless stack is malformed). | 3955 ASSERT(current != NULL); // Always found (unless stack is malformed). |
(...skipping 18 matching lines...) Expand all Loading... |
4135 block = current->owner()->graph()->CreateBasicBlock(); | 3974 block = current->owner()->graph()->CreateBasicBlock(); |
4136 current->info()->set_continue_block(block); | 3975 current->info()->set_continue_block(block); |
4137 } | 3976 } |
4138 break; | 3977 break; |
4139 } | 3978 } |
4140 | 3979 |
4141 return block; | 3980 return block; |
4142 } | 3981 } |
4143 | 3982 |
4144 | 3983 |
4145 void HOptimizedGraphBuilder::VisitContinueStatement( | 3984 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
4146 ContinueStatement* stmt) { | |
4147 ASSERT(!HasStackOverflow()); | 3985 ASSERT(!HasStackOverflow()); |
4148 ASSERT(current_block() != NULL); | 3986 ASSERT(current_block() != NULL); |
4149 ASSERT(current_block()->HasPredecessor()); | 3987 ASSERT(current_block()->HasPredecessor()); |
4150 int drop_extra = 0; | 3988 int drop_extra = 0; |
4151 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), | 3989 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), |
4152 CONTINUE, | 3990 CONTINUE, |
4153 &drop_extra); | 3991 &drop_extra); |
4154 Drop(drop_extra); | 3992 Drop(drop_extra); |
4155 current_block()->Goto(continue_block); | 3993 current_block()->Goto(continue_block); |
4156 set_current_block(NULL); | 3994 set_current_block(NULL); |
4157 } | 3995 } |
4158 | 3996 |
4159 | 3997 |
4160 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 3998 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
4161 ASSERT(!HasStackOverflow()); | 3999 ASSERT(!HasStackOverflow()); |
4162 ASSERT(current_block() != NULL); | 4000 ASSERT(current_block() != NULL); |
4163 ASSERT(current_block()->HasPredecessor()); | 4001 ASSERT(current_block()->HasPredecessor()); |
4164 int drop_extra = 0; | 4002 int drop_extra = 0; |
4165 HBasicBlock* break_block = break_scope()->Get(stmt->target(), | 4003 HBasicBlock* break_block = break_scope()->Get(stmt->target(), |
4166 BREAK, | 4004 BREAK, |
4167 &drop_extra); | 4005 &drop_extra); |
4168 Drop(drop_extra); | 4006 Drop(drop_extra); |
4169 current_block()->Goto(break_block); | 4007 current_block()->Goto(break_block); |
4170 set_current_block(NULL); | 4008 set_current_block(NULL); |
4171 } | 4009 } |
4172 | 4010 |
4173 | 4011 |
4174 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 4012 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
4175 ASSERT(!HasStackOverflow()); | 4013 ASSERT(!HasStackOverflow()); |
4176 ASSERT(current_block() != NULL); | 4014 ASSERT(current_block() != NULL); |
4177 ASSERT(current_block()->HasPredecessor()); | 4015 ASSERT(current_block()->HasPredecessor()); |
4178 FunctionState* state = function_state(); | 4016 FunctionState* state = function_state(); |
4179 AstContext* context = call_context(); | 4017 AstContext* context = call_context(); |
4180 if (context == NULL) { | 4018 if (context == NULL) { |
4181 // Not an inlined return, so an actual one. | 4019 // Not an inlined return, so an actual one. |
4182 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4020 CHECK_ALIVE(VisitForValue(stmt->expression())); |
4183 HValue* result = environment()->Pop(); | 4021 HValue* result = environment()->Pop(); |
4184 current_block()->FinishExit(new(zone()) HReturn(result)); | 4022 current_block()->FinishExit(new(zone()) HReturn(result)); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4236 } else { | 4074 } else { |
4237 ASSERT(context->IsValue()); | 4075 ASSERT(context->IsValue()); |
4238 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4076 CHECK_ALIVE(VisitForValue(stmt->expression())); |
4239 current_block()->AddLeaveInlined(Pop(), state); | 4077 current_block()->AddLeaveInlined(Pop(), state); |
4240 } | 4078 } |
4241 } | 4079 } |
4242 set_current_block(NULL); | 4080 set_current_block(NULL); |
4243 } | 4081 } |
4244 | 4082 |
4245 | 4083 |
4246 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 4084 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
4247 ASSERT(!HasStackOverflow()); | 4085 ASSERT(!HasStackOverflow()); |
4248 ASSERT(current_block() != NULL); | 4086 ASSERT(current_block() != NULL); |
4249 ASSERT(current_block()->HasPredecessor()); | 4087 ASSERT(current_block()->HasPredecessor()); |
4250 return Bailout("WithStatement"); | 4088 return Bailout("WithStatement"); |
4251 } | 4089 } |
4252 | 4090 |
4253 | 4091 |
4254 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 4092 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
4255 ASSERT(!HasStackOverflow()); | 4093 ASSERT(!HasStackOverflow()); |
4256 ASSERT(current_block() != NULL); | 4094 ASSERT(current_block() != NULL); |
4257 ASSERT(current_block()->HasPredecessor()); | 4095 ASSERT(current_block()->HasPredecessor()); |
4258 // We only optimize switch statements with smi-literal smi comparisons, | 4096 // We only optimize switch statements with smi-literal smi comparisons, |
4259 // with a bounded number of clauses. | 4097 // with a bounded number of clauses. |
4260 const int kCaseClauseLimit = 128; | 4098 const int kCaseClauseLimit = 128; |
4261 ZoneList<CaseClause*>* clauses = stmt->cases(); | 4099 ZoneList<CaseClause*>* clauses = stmt->cases(); |
4262 int clause_count = clauses->length(); | 4100 int clause_count = clauses->length(); |
4263 if (clause_count > kCaseClauseLimit) { | 4101 if (clause_count > kCaseClauseLimit) { |
4264 return Bailout("SwitchStatement: too many clauses"); | 4102 return Bailout("SwitchStatement: too many clauses"); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4430 stmt->ExitId())); | 4268 stmt->ExitId())); |
4431 } else { | 4269 } else { |
4432 if (fall_through_block != NULL) fall_through_block->Goto(break_block); | 4270 if (fall_through_block != NULL) fall_through_block->Goto(break_block); |
4433 if (last_block != NULL) last_block->Goto(break_block); | 4271 if (last_block != NULL) last_block->Goto(break_block); |
4434 break_block->SetJoinId(stmt->ExitId()); | 4272 break_block->SetJoinId(stmt->ExitId()); |
4435 set_current_block(break_block); | 4273 set_current_block(break_block); |
4436 } | 4274 } |
4437 } | 4275 } |
4438 | 4276 |
4439 | 4277 |
4440 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { | 4278 bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { |
4441 return statement->OsrEntryId() == info()->osr_ast_id(); | 4279 return statement->OsrEntryId() == info()->osr_ast_id(); |
4442 } | 4280 } |
4443 | 4281 |
4444 | 4282 |
4445 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | 4283 bool HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { |
4446 if (!HasOsrEntryAt(statement)) return false; | 4284 if (!HasOsrEntryAt(statement)) return false; |
4447 | 4285 |
4448 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); | 4286 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); |
4449 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); | 4287 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); |
4450 HValue* true_value = graph()->GetConstantTrue(); | 4288 HValue* true_value = graph()->GetConstantTrue(); |
4451 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); | 4289 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); |
4452 current_block()->Finish(test); | 4290 current_block()->Finish(test); |
4453 | 4291 |
4454 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); | 4292 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); |
4455 non_osr_entry->Goto(loop_predecessor); | 4293 non_osr_entry->Goto(loop_predecessor); |
(...skipping 29 matching lines...) Expand all Loading... |
4485 HContext* context = new(zone()) HContext; | 4323 HContext* context = new(zone()) HContext; |
4486 AddInstruction(context); | 4324 AddInstruction(context); |
4487 environment()->BindContext(context); | 4325 environment()->BindContext(context); |
4488 current_block()->Goto(loop_predecessor); | 4326 current_block()->Goto(loop_predecessor); |
4489 loop_predecessor->SetJoinId(statement->EntryId()); | 4327 loop_predecessor->SetJoinId(statement->EntryId()); |
4490 set_current_block(loop_predecessor); | 4328 set_current_block(loop_predecessor); |
4491 return true; | 4329 return true; |
4492 } | 4330 } |
4493 | 4331 |
4494 | 4332 |
4495 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 4333 void HGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
4496 HBasicBlock* loop_entry, | 4334 HBasicBlock* loop_entry, |
4497 BreakAndContinueInfo* break_info) { | 4335 BreakAndContinueInfo* break_info) { |
4498 BreakAndContinueScope push(break_info, this); | 4336 BreakAndContinueScope push(break_info, this); |
4499 AddSimulate(stmt->StackCheckId()); | 4337 AddSimulate(stmt->StackCheckId()); |
4500 HValue* context = environment()->LookupContext(); | 4338 HValue* context = environment()->LookupContext(); |
4501 HStackCheck* stack_check = | 4339 HStackCheck* stack_check = |
4502 new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch); | 4340 new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch); |
4503 AddInstruction(stack_check); | 4341 AddInstruction(stack_check); |
4504 ASSERT(loop_entry->IsLoopHeader()); | 4342 ASSERT(loop_entry->IsLoopHeader()); |
4505 loop_entry->loop_information()->set_stack_check(stack_check); | 4343 loop_entry->loop_information()->set_stack_check(stack_check); |
4506 CHECK_BAILOUT(Visit(stmt->body())); | 4344 CHECK_BAILOUT(Visit(stmt->body())); |
4507 } | 4345 } |
4508 | 4346 |
4509 | 4347 |
4510 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 4348 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
4511 ASSERT(!HasStackOverflow()); | 4349 ASSERT(!HasStackOverflow()); |
4512 ASSERT(current_block() != NULL); | 4350 ASSERT(current_block() != NULL); |
4513 ASSERT(current_block()->HasPredecessor()); | 4351 ASSERT(current_block()->HasPredecessor()); |
4514 ASSERT(current_block() != NULL); | 4352 ASSERT(current_block() != NULL); |
4515 bool osr_entry = PreProcessOsrEntry(stmt); | 4353 bool osr_entry = PreProcessOsrEntry(stmt); |
4516 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4354 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
4517 current_block()->Goto(loop_entry); | 4355 current_block()->Goto(loop_entry); |
4518 set_current_block(loop_entry); | 4356 set_current_block(loop_entry); |
4519 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | 4357 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); |
4520 | 4358 |
(...skipping 22 matching lines...) Expand all Loading... |
4543 } | 4381 } |
4544 HBasicBlock* loop_exit = CreateLoop(stmt, | 4382 HBasicBlock* loop_exit = CreateLoop(stmt, |
4545 loop_entry, | 4383 loop_entry, |
4546 body_exit, | 4384 body_exit, |
4547 loop_successor, | 4385 loop_successor, |
4548 break_info.break_block()); | 4386 break_info.break_block()); |
4549 set_current_block(loop_exit); | 4387 set_current_block(loop_exit); |
4550 } | 4388 } |
4551 | 4389 |
4552 | 4390 |
4553 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 4391 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
4554 ASSERT(!HasStackOverflow()); | 4392 ASSERT(!HasStackOverflow()); |
4555 ASSERT(current_block() != NULL); | 4393 ASSERT(current_block() != NULL); |
4556 ASSERT(current_block()->HasPredecessor()); | 4394 ASSERT(current_block()->HasPredecessor()); |
4557 ASSERT(current_block() != NULL); | 4395 ASSERT(current_block() != NULL); |
4558 bool osr_entry = PreProcessOsrEntry(stmt); | 4396 bool osr_entry = PreProcessOsrEntry(stmt); |
4559 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4397 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
4560 current_block()->Goto(loop_entry); | 4398 current_block()->Goto(loop_entry); |
4561 set_current_block(loop_entry); | 4399 set_current_block(loop_entry); |
4562 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | 4400 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); |
4563 | 4401 |
(...skipping 23 matching lines...) Expand all Loading... |
4587 JoinContinue(stmt, current_block(), break_info.continue_block()); | 4425 JoinContinue(stmt, current_block(), break_info.continue_block()); |
4588 HBasicBlock* loop_exit = CreateLoop(stmt, | 4426 HBasicBlock* loop_exit = CreateLoop(stmt, |
4589 loop_entry, | 4427 loop_entry, |
4590 body_exit, | 4428 body_exit, |
4591 loop_successor, | 4429 loop_successor, |
4592 break_info.break_block()); | 4430 break_info.break_block()); |
4593 set_current_block(loop_exit); | 4431 set_current_block(loop_exit); |
4594 } | 4432 } |
4595 | 4433 |
4596 | 4434 |
4597 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { | 4435 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
4598 ASSERT(!HasStackOverflow()); | 4436 ASSERT(!HasStackOverflow()); |
4599 ASSERT(current_block() != NULL); | 4437 ASSERT(current_block() != NULL); |
4600 ASSERT(current_block()->HasPredecessor()); | 4438 ASSERT(current_block()->HasPredecessor()); |
4601 if (stmt->init() != NULL) { | 4439 if (stmt->init() != NULL) { |
4602 CHECK_ALIVE(Visit(stmt->init())); | 4440 CHECK_ALIVE(Visit(stmt->init())); |
4603 } | 4441 } |
4604 ASSERT(current_block() != NULL); | 4442 ASSERT(current_block() != NULL); |
4605 bool osr_entry = PreProcessOsrEntry(stmt); | 4443 bool osr_entry = PreProcessOsrEntry(stmt); |
4606 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4444 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
4607 current_block()->Goto(loop_entry); | 4445 current_block()->Goto(loop_entry); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4639 | 4477 |
4640 HBasicBlock* loop_exit = CreateLoop(stmt, | 4478 HBasicBlock* loop_exit = CreateLoop(stmt, |
4641 loop_entry, | 4479 loop_entry, |
4642 body_exit, | 4480 body_exit, |
4643 loop_successor, | 4481 loop_successor, |
4644 break_info.break_block()); | 4482 break_info.break_block()); |
4645 set_current_block(loop_exit); | 4483 set_current_block(loop_exit); |
4646 } | 4484 } |
4647 | 4485 |
4648 | 4486 |
4649 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 4487 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
4650 ASSERT(!HasStackOverflow()); | 4488 ASSERT(!HasStackOverflow()); |
4651 ASSERT(current_block() != NULL); | 4489 ASSERT(current_block() != NULL); |
4652 ASSERT(current_block()->HasPredecessor()); | 4490 ASSERT(current_block()->HasPredecessor()); |
4653 | 4491 |
4654 if (!FLAG_optimize_for_in) { | 4492 if (!FLAG_optimize_for_in) { |
4655 return Bailout("ForInStatement optimization is disabled"); | 4493 return Bailout("ForInStatement optimization is disabled"); |
4656 } | 4494 } |
4657 | 4495 |
4658 if (!oracle()->IsForInFastCase(stmt)) { | 4496 if (!oracle()->IsForInFastCase(stmt)) { |
4659 return Bailout("ForInStatement is not fast case"); | 4497 return Bailout("ForInStatement is not fast case"); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4760 HBasicBlock* loop_exit = CreateLoop(stmt, | 4598 HBasicBlock* loop_exit = CreateLoop(stmt, |
4761 loop_entry, | 4599 loop_entry, |
4762 body_exit, | 4600 body_exit, |
4763 loop_successor, | 4601 loop_successor, |
4764 break_info.break_block()); | 4602 break_info.break_block()); |
4765 | 4603 |
4766 set_current_block(loop_exit); | 4604 set_current_block(loop_exit); |
4767 } | 4605 } |
4768 | 4606 |
4769 | 4607 |
4770 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 4608 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
4771 ASSERT(!HasStackOverflow()); | 4609 ASSERT(!HasStackOverflow()); |
4772 ASSERT(current_block() != NULL); | 4610 ASSERT(current_block() != NULL); |
4773 ASSERT(current_block()->HasPredecessor()); | 4611 ASSERT(current_block()->HasPredecessor()); |
4774 return Bailout("TryCatchStatement"); | 4612 return Bailout("TryCatchStatement"); |
4775 } | 4613 } |
4776 | 4614 |
4777 | 4615 |
4778 void HOptimizedGraphBuilder::VisitTryFinallyStatement( | 4616 void HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
4779 TryFinallyStatement* stmt) { | |
4780 ASSERT(!HasStackOverflow()); | 4617 ASSERT(!HasStackOverflow()); |
4781 ASSERT(current_block() != NULL); | 4618 ASSERT(current_block() != NULL); |
4782 ASSERT(current_block()->HasPredecessor()); | 4619 ASSERT(current_block()->HasPredecessor()); |
4783 return Bailout("TryFinallyStatement"); | 4620 return Bailout("TryFinallyStatement"); |
4784 } | 4621 } |
4785 | 4622 |
4786 | 4623 |
4787 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 4624 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
4788 ASSERT(!HasStackOverflow()); | 4625 ASSERT(!HasStackOverflow()); |
4789 ASSERT(current_block() != NULL); | 4626 ASSERT(current_block() != NULL); |
4790 ASSERT(current_block()->HasPredecessor()); | 4627 ASSERT(current_block()->HasPredecessor()); |
4791 return Bailout("DebuggerStatement"); | 4628 return Bailout("DebuggerStatement"); |
4792 } | 4629 } |
4793 | 4630 |
4794 | 4631 |
4795 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( | 4632 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( |
4796 Code* unoptimized_code, FunctionLiteral* expr) { | 4633 Code* unoptimized_code, FunctionLiteral* expr) { |
4797 int start_position = expr->start_position(); | 4634 int start_position = expr->start_position(); |
4798 RelocIterator it(unoptimized_code); | 4635 RelocIterator it(unoptimized_code); |
4799 for (;!it.done(); it.next()) { | 4636 for (;!it.done(); it.next()) { |
4800 RelocInfo* rinfo = it.rinfo(); | 4637 RelocInfo* rinfo = it.rinfo(); |
4801 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; | 4638 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; |
4802 Object* obj = rinfo->target_object(); | 4639 Object* obj = rinfo->target_object(); |
4803 if (obj->IsSharedFunctionInfo()) { | 4640 if (obj->IsSharedFunctionInfo()) { |
4804 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 4641 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
4805 if (shared->start_position() == start_position) { | 4642 if (shared->start_position() == start_position) { |
4806 return Handle<SharedFunctionInfo>(shared); | 4643 return Handle<SharedFunctionInfo>(shared); |
4807 } | 4644 } |
4808 } | 4645 } |
4809 } | 4646 } |
4810 | 4647 |
4811 return Handle<SharedFunctionInfo>(); | 4648 return Handle<SharedFunctionInfo>(); |
4812 } | 4649 } |
4813 | 4650 |
4814 | 4651 |
4815 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 4652 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
4816 ASSERT(!HasStackOverflow()); | 4653 ASSERT(!HasStackOverflow()); |
4817 ASSERT(current_block() != NULL); | 4654 ASSERT(current_block() != NULL); |
4818 ASSERT(current_block()->HasPredecessor()); | 4655 ASSERT(current_block()->HasPredecessor()); |
4819 Handle<SharedFunctionInfo> shared_info = | 4656 Handle<SharedFunctionInfo> shared_info = |
4820 SearchSharedFunctionInfo(info()->shared_info()->code(), | 4657 SearchSharedFunctionInfo(info()->shared_info()->code(), |
4821 expr); | 4658 expr); |
4822 if (shared_info.is_null()) { | 4659 if (shared_info.is_null()) { |
4823 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); | 4660 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); |
4824 } | 4661 } |
4825 // We also have a stack overflow if the recursive compilation did. | 4662 // We also have a stack overflow if the recursive compilation did. |
4826 if (HasStackOverflow()) return; | 4663 if (HasStackOverflow()) return; |
4827 HValue* context = environment()->LookupContext(); | 4664 HValue* context = environment()->LookupContext(); |
4828 HFunctionLiteral* instr = | 4665 HFunctionLiteral* instr = |
4829 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 4666 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
4830 return ast_context()->ReturnInstruction(instr, expr->id()); | 4667 return ast_context()->ReturnInstruction(instr, expr->id()); |
4831 } | 4668 } |
4832 | 4669 |
4833 | 4670 |
4834 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( | 4671 void HGraphBuilder::VisitSharedFunctionInfoLiteral( |
4835 SharedFunctionInfoLiteral* expr) { | 4672 SharedFunctionInfoLiteral* expr) { |
4836 ASSERT(!HasStackOverflow()); | 4673 ASSERT(!HasStackOverflow()); |
4837 ASSERT(current_block() != NULL); | 4674 ASSERT(current_block() != NULL); |
4838 ASSERT(current_block()->HasPredecessor()); | 4675 ASSERT(current_block()->HasPredecessor()); |
4839 return Bailout("SharedFunctionInfoLiteral"); | 4676 return Bailout("SharedFunctionInfoLiteral"); |
4840 } | 4677 } |
4841 | 4678 |
4842 | 4679 |
4843 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { | 4680 void HGraphBuilder::VisitConditional(Conditional* expr) { |
4844 ASSERT(!HasStackOverflow()); | 4681 ASSERT(!HasStackOverflow()); |
4845 ASSERT(current_block() != NULL); | 4682 ASSERT(current_block() != NULL); |
4846 ASSERT(current_block()->HasPredecessor()); | 4683 ASSERT(current_block()->HasPredecessor()); |
4847 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 4684 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
4848 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 4685 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
4849 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); | 4686 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); |
4850 | 4687 |
4851 // Visit the true and false subexpressions in the same AST context as the | 4688 // Visit the true and false subexpressions in the same AST context as the |
4852 // whole expression. | 4689 // whole expression. |
4853 if (cond_true->HasPredecessor()) { | 4690 if (cond_true->HasPredecessor()) { |
(...skipping 17 matching lines...) Expand all Loading... |
4871 if (!ast_context()->IsTest()) { | 4708 if (!ast_context()->IsTest()) { |
4872 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); | 4709 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); |
4873 set_current_block(join); | 4710 set_current_block(join); |
4874 if (join != NULL && !ast_context()->IsEffect()) { | 4711 if (join != NULL && !ast_context()->IsEffect()) { |
4875 return ast_context()->ReturnValue(Pop()); | 4712 return ast_context()->ReturnValue(Pop()); |
4876 } | 4713 } |
4877 } | 4714 } |
4878 } | 4715 } |
4879 | 4716 |
4880 | 4717 |
4881 HOptimizedGraphBuilder::GlobalPropertyAccess | 4718 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( |
4882 HOptimizedGraphBuilder::LookupGlobalProperty( | 4719 Variable* var, LookupResult* lookup, bool is_store) { |
4883 Variable* var, LookupResult* lookup, bool is_store) { | |
4884 if (var->is_this() || !info()->has_global_object()) { | 4720 if (var->is_this() || !info()->has_global_object()) { |
4885 return kUseGeneric; | 4721 return kUseGeneric; |
4886 } | 4722 } |
4887 Handle<GlobalObject> global(info()->global_object()); | 4723 Handle<GlobalObject> global(info()->global_object()); |
4888 global->Lookup(*var->name(), lookup); | 4724 global->Lookup(*var->name(), lookup); |
4889 if (!lookup->IsNormal() || | 4725 if (!lookup->IsNormal() || |
4890 (is_store && lookup->IsReadOnly()) || | 4726 (is_store && lookup->IsReadOnly()) || |
4891 lookup->holder() != *global) { | 4727 lookup->holder() != *global) { |
4892 return kUseGeneric; | 4728 return kUseGeneric; |
4893 } | 4729 } |
4894 | 4730 |
4895 return kUseCell; | 4731 return kUseCell; |
4896 } | 4732 } |
4897 | 4733 |
4898 | 4734 |
4899 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 4735 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
4900 ASSERT(var->IsContextSlot()); | 4736 ASSERT(var->IsContextSlot()); |
4901 HValue* context = environment()->LookupContext(); | 4737 HValue* context = environment()->LookupContext(); |
4902 int length = info()->scope()->ContextChainLength(var->scope()); | 4738 int length = info()->scope()->ContextChainLength(var->scope()); |
4903 while (length-- > 0) { | 4739 while (length-- > 0) { |
4904 HInstruction* context_instruction = new(zone()) HOuterContext(context); | 4740 HInstruction* context_instruction = new(zone()) HOuterContext(context); |
4905 AddInstruction(context_instruction); | 4741 AddInstruction(context_instruction); |
4906 context = context_instruction; | 4742 context = context_instruction; |
4907 } | 4743 } |
4908 return context; | 4744 return context; |
4909 } | 4745 } |
4910 | 4746 |
4911 | 4747 |
4912 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 4748 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
4913 ASSERT(!HasStackOverflow()); | 4749 ASSERT(!HasStackOverflow()); |
4914 ASSERT(current_block() != NULL); | 4750 ASSERT(current_block() != NULL); |
4915 ASSERT(current_block()->HasPredecessor()); | 4751 ASSERT(current_block()->HasPredecessor()); |
4916 Variable* variable = expr->var(); | 4752 Variable* variable = expr->var(); |
4917 switch (variable->location()) { | 4753 switch (variable->location()) { |
4918 case Variable::UNALLOCATED: { | 4754 case Variable::UNALLOCATED: { |
4919 if (IsLexicalVariableMode(variable->mode())) { | 4755 if (IsLexicalVariableMode(variable->mode())) { |
4920 // TODO(rossberg): should this be an ASSERT? | 4756 // TODO(rossberg): should this be an ASSERT? |
4921 return Bailout("reference to global lexical variable"); | 4757 return Bailout("reference to global lexical variable"); |
4922 } | 4758 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4975 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); | 4811 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); |
4976 return ast_context()->ReturnInstruction(instr, expr->id()); | 4812 return ast_context()->ReturnInstruction(instr, expr->id()); |
4977 } | 4813 } |
4978 | 4814 |
4979 case Variable::LOOKUP: | 4815 case Variable::LOOKUP: |
4980 return Bailout("reference to a variable which requires dynamic lookup"); | 4816 return Bailout("reference to a variable which requires dynamic lookup"); |
4981 } | 4817 } |
4982 } | 4818 } |
4983 | 4819 |
4984 | 4820 |
4985 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { | 4821 void HGraphBuilder::VisitLiteral(Literal* expr) { |
4986 ASSERT(!HasStackOverflow()); | 4822 ASSERT(!HasStackOverflow()); |
4987 ASSERT(current_block() != NULL); | 4823 ASSERT(current_block() != NULL); |
4988 ASSERT(current_block()->HasPredecessor()); | 4824 ASSERT(current_block()->HasPredecessor()); |
4989 HConstant* instr = | 4825 HConstant* instr = |
4990 new(zone()) HConstant(expr->handle(), Representation::None()); | 4826 new(zone()) HConstant(expr->handle(), Representation::None()); |
4991 return ast_context()->ReturnInstruction(instr, expr->id()); | 4827 return ast_context()->ReturnInstruction(instr, expr->id()); |
4992 } | 4828 } |
4993 | 4829 |
4994 | 4830 |
4995 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 4831 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* 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 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4835 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
5000 Handle<FixedArray> literals(closure->literals()); | 4836 Handle<FixedArray> literals(closure->literals()); |
5001 HValue* context = environment()->LookupContext(); | 4837 HValue* context = environment()->LookupContext(); |
5002 | 4838 |
5003 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, | 4839 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, |
5004 literals, | 4840 literals, |
5005 expr->pattern(), | 4841 expr->pattern(), |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5144 } | 4980 } |
5145 } | 4981 } |
5146 } | 4982 } |
5147 } | 4983 } |
5148 | 4984 |
5149 *total_size += boilerplate->map()->instance_size(); | 4985 *total_size += boilerplate->map()->instance_size(); |
5150 return true; | 4986 return true; |
5151 } | 4987 } |
5152 | 4988 |
5153 | 4989 |
5154 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 4990 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
5155 ASSERT(!HasStackOverflow()); | 4991 ASSERT(!HasStackOverflow()); |
5156 ASSERT(current_block() != NULL); | 4992 ASSERT(current_block() != NULL); |
5157 ASSERT(current_block()->HasPredecessor()); | 4993 ASSERT(current_block()->HasPredecessor()); |
5158 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4994 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
5159 HValue* context = environment()->LookupContext(); | 4995 HValue* context = environment()->LookupContext(); |
5160 HInstruction* literal; | 4996 HInstruction* literal; |
5161 | 4997 |
5162 // Check whether to use fast or slow deep-copying for boilerplate. | 4998 // Check whether to use fast or slow deep-copying for boilerplate. |
5163 int total_size = 0; | 4999 int total_size = 0; |
5164 int max_properties = HFastLiteral::kMaxLiteralProperties; | 5000 int max_properties = HFastLiteral::kMaxLiteralProperties; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5249 // (e.g. because of code motion). | 5085 // (e.g. because of code motion). |
5250 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); | 5086 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); |
5251 AddInstruction(result); | 5087 AddInstruction(result); |
5252 return ast_context()->ReturnValue(result); | 5088 return ast_context()->ReturnValue(result); |
5253 } else { | 5089 } else { |
5254 return ast_context()->ReturnValue(Pop()); | 5090 return ast_context()->ReturnValue(Pop()); |
5255 } | 5091 } |
5256 } | 5092 } |
5257 | 5093 |
5258 | 5094 |
5259 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 5095 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
5260 ASSERT(!HasStackOverflow()); | 5096 ASSERT(!HasStackOverflow()); |
5261 ASSERT(current_block() != NULL); | 5097 ASSERT(current_block() != NULL); |
5262 ASSERT(current_block()->HasPredecessor()); | 5098 ASSERT(current_block()->HasPredecessor()); |
5263 ZoneList<Expression*>* subexprs = expr->values(); | 5099 ZoneList<Expression*>* subexprs = expr->values(); |
5264 int length = subexprs->length(); | 5100 int length = subexprs->length(); |
5265 HValue* context = environment()->LookupContext(); | 5101 HValue* context = environment()->LookupContext(); |
5266 HInstruction* literal; | 5102 HInstruction* literal; |
5267 | 5103 |
5268 Handle<FixedArray> literals(environment()->closure()->literals()); | 5104 Handle<FixedArray> literals(environment()->closure()->literals()); |
5269 Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); | 5105 Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5383 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); | 5219 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); |
5384 if (lookup->IsField()) { | 5220 if (lookup->IsField()) { |
5385 return lookup->GetLocalFieldIndexFromMap(*type); | 5221 return lookup->GetLocalFieldIndexFromMap(*type); |
5386 } else { | 5222 } else { |
5387 Map* transition = lookup->GetTransitionMapFromMap(*type); | 5223 Map* transition = lookup->GetTransitionMapFromMap(*type); |
5388 return transition->PropertyIndexFor(*name) - type->inobject_properties(); | 5224 return transition->PropertyIndexFor(*name) - type->inobject_properties(); |
5389 } | 5225 } |
5390 } | 5226 } |
5391 | 5227 |
5392 | 5228 |
5393 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, | 5229 void HGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
5394 Handle<Map> map) { | 5230 Handle<Map> map) { |
5395 AddInstruction(new(zone()) HCheckNonSmi(object)); | 5231 AddInstruction(new(zone()) HCheckNonSmi(object)); |
5396 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | 5232 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
5397 } | 5233 } |
5398 | 5234 |
5399 | 5235 |
5400 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 5236 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, |
5401 HValue* object, | 5237 Handle<String> name, |
5402 Handle<String> name, | 5238 HValue* value, |
5403 HValue* value, | 5239 Handle<Map> map, |
5404 Handle<Map> map, | 5240 LookupResult* lookup) { |
5405 LookupResult* lookup) { | |
5406 ASSERT(lookup->IsFound()); | 5241 ASSERT(lookup->IsFound()); |
5407 // If the property does not exist yet, we have to check that it wasn't made | 5242 // If the property does not exist yet, we have to check that it wasn't made |
5408 // readonly or turned into a setter by some meanwhile modifications on the | 5243 // readonly or turned into a setter by some meanwhile modifications on the |
5409 // prototype chain. | 5244 // prototype chain. |
5410 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { | 5245 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { |
5411 Object* proto = map->prototype(); | 5246 Object* proto = map->prototype(); |
5412 // First check that the prototype chain isn't affected already. | 5247 // First check that the prototype chain isn't affected already. |
5413 LookupResult proto_result(isolate()); | 5248 LookupResult proto_result(isolate()); |
5414 proto->Lookup(*name, &proto_result); | 5249 proto->Lookup(*name, &proto_result); |
5415 if (proto_result.IsProperty()) { | 5250 if (proto_result.IsProperty()) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5447 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 5282 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
5448 instr->set_transition(transition); | 5283 instr->set_transition(transition); |
5449 // TODO(fschneider): Record the new map type of the object in the IR to | 5284 // TODO(fschneider): Record the new map type of the object in the IR to |
5450 // enable elimination of redundant checks after the transition store. | 5285 // enable elimination of redundant checks after the transition store. |
5451 instr->SetGVNFlag(kChangesMaps); | 5286 instr->SetGVNFlag(kChangesMaps); |
5452 } | 5287 } |
5453 return instr; | 5288 return instr; |
5454 } | 5289 } |
5455 | 5290 |
5456 | 5291 |
5457 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( | 5292 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, |
5458 HValue* object, | 5293 Handle<String> name, |
5459 Handle<String> name, | 5294 HValue* value) { |
5460 HValue* value) { | |
5461 HValue* context = environment()->LookupContext(); | 5295 HValue* context = environment()->LookupContext(); |
5462 return new(zone()) HStoreNamedGeneric( | 5296 return new(zone()) HStoreNamedGeneric( |
5463 context, | 5297 context, |
5464 object, | 5298 object, |
5465 name, | 5299 name, |
5466 value, | 5300 value, |
5467 function_strict_mode_flag()); | 5301 function_strict_mode_flag()); |
5468 } | 5302 } |
5469 | 5303 |
5470 | 5304 |
5471 HInstruction* HOptimizedGraphBuilder::BuildCallSetter( | 5305 HInstruction* HGraphBuilder::BuildCallSetter(HValue* object, |
5472 HValue* object, | 5306 HValue* value, |
5473 HValue* value, | 5307 Handle<Map> map, |
5474 Handle<Map> map, | 5308 Handle<JSFunction> setter, |
5475 Handle<JSFunction> setter, | 5309 Handle<JSObject> holder) { |
5476 Handle<JSObject> holder) { | |
5477 AddCheckConstantFunction(holder, object, map); | 5310 AddCheckConstantFunction(holder, object, map); |
5478 AddInstruction(new(zone()) HPushArgument(object)); | 5311 AddInstruction(new(zone()) HPushArgument(object)); |
5479 AddInstruction(new(zone()) HPushArgument(value)); | 5312 AddInstruction(new(zone()) HPushArgument(value)); |
5480 return new(zone()) HCallConstantFunction(setter, 2); | 5313 return new(zone()) HCallConstantFunction(setter, 2); |
5481 } | 5314 } |
5482 | 5315 |
5483 | 5316 |
5484 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( | 5317 HInstruction* HGraphBuilder::BuildStoreNamedMonomorphic(HValue* object, |
5485 HValue* object, | 5318 Handle<String> name, |
5486 Handle<String> name, | 5319 HValue* value, |
5487 HValue* value, | 5320 Handle<Map> map) { |
5488 Handle<Map> map) { | |
5489 // Handle a store to a known field. | 5321 // Handle a store to a known field. |
5490 LookupResult lookup(isolate()); | 5322 LookupResult lookup(isolate()); |
5491 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 5323 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
5492 AddCheckMapsWithTransitions(object, map); | 5324 AddCheckMapsWithTransitions(object, map); |
5493 return BuildStoreNamedField(object, name, value, map, &lookup); | 5325 return BuildStoreNamedField(object, name, value, map, &lookup); |
5494 } | 5326 } |
5495 | 5327 |
5496 // No luck, do a generic store. | 5328 // No luck, do a generic store. |
5497 return BuildStoreNamedGeneric(object, name, value); | 5329 return BuildStoreNamedGeneric(object, name, value); |
5498 } | 5330 } |
5499 | 5331 |
5500 | 5332 |
5501 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 5333 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
5502 Property* expr, | 5334 HValue* object, |
5503 HValue* object, | 5335 SmallMapList* types, |
5504 SmallMapList* types, | 5336 Handle<String> name) { |
5505 Handle<String> name) { | |
5506 int count = 0; | 5337 int count = 0; |
5507 int previous_field_offset = 0; | 5338 int previous_field_offset = 0; |
5508 bool previous_field_is_in_object = false; | 5339 bool previous_field_is_in_object = false; |
5509 bool is_monomorphic_field = true; | 5340 bool is_monomorphic_field = true; |
5510 Handle<Map> map; | 5341 Handle<Map> map; |
5511 LookupResult lookup(isolate()); | 5342 LookupResult lookup(isolate()); |
5512 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 5343 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
5513 map = types->at(i); | 5344 map = types->at(i); |
5514 if (ComputeLoadStoreField(map, name, &lookup, false)) { | 5345 if (ComputeLoadStoreField(map, name, &lookup, false)) { |
5515 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); | 5346 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5547 types, | 5378 types, |
5548 name, | 5379 name, |
5549 zone()); | 5380 zone()); |
5550 } | 5381 } |
5551 | 5382 |
5552 instr->set_position(expr->position()); | 5383 instr->set_position(expr->position()); |
5553 return ast_context()->ReturnInstruction(instr, expr->id()); | 5384 return ast_context()->ReturnInstruction(instr, expr->id()); |
5554 } | 5385 } |
5555 | 5386 |
5556 | 5387 |
5557 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 5388 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, |
5558 Assignment* expr, | 5389 HValue* object, |
5559 HValue* object, | 5390 HValue* value, |
5560 HValue* value, | 5391 SmallMapList* types, |
5561 SmallMapList* types, | 5392 Handle<String> name) { |
5562 Handle<String> name) { | |
5563 // TODO(ager): We should recognize when the prototype chains for different | 5393 // TODO(ager): We should recognize when the prototype chains for different |
5564 // maps are identical. In that case we can avoid repeatedly generating the | 5394 // maps are identical. In that case we can avoid repeatedly generating the |
5565 // same prototype map checks. | 5395 // same prototype map checks. |
5566 int count = 0; | 5396 int count = 0; |
5567 HBasicBlock* join = NULL; | 5397 HBasicBlock* join = NULL; |
5568 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 5398 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
5569 Handle<Map> map = types->at(i); | 5399 Handle<Map> map = types->at(i); |
5570 LookupResult lookup(isolate()); | 5400 LookupResult lookup(isolate()); |
5571 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 5401 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
5572 if (count == 0) { | 5402 if (count == 0) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5624 } | 5454 } |
5625 } | 5455 } |
5626 | 5456 |
5627 ASSERT(join != NULL); | 5457 ASSERT(join != NULL); |
5628 join->SetJoinId(expr->id()); | 5458 join->SetJoinId(expr->id()); |
5629 set_current_block(join); | 5459 set_current_block(join); |
5630 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 5460 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
5631 } | 5461 } |
5632 | 5462 |
5633 | 5463 |
5634 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 5464 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
5635 Property* prop = expr->target()->AsProperty(); | 5465 Property* prop = expr->target()->AsProperty(); |
5636 ASSERT(prop != NULL); | 5466 ASSERT(prop != NULL); |
5637 expr->RecordTypeFeedback(oracle(), zone()); | 5467 expr->RecordTypeFeedback(oracle(), zone()); |
5638 CHECK_ALIVE(VisitForValue(prop->obj())); | 5468 CHECK_ALIVE(VisitForValue(prop->obj())); |
5639 | 5469 |
5640 if (prop->key()->IsPropertyName()) { | 5470 if (prop->key()->IsPropertyName()) { |
5641 // Named store. | 5471 // Named store. |
5642 CHECK_ALIVE(VisitForValue(expr->value())); | 5472 CHECK_ALIVE(VisitForValue(expr->value())); |
5643 HValue* value = environment()->ExpressionStackAt(0); | 5473 HValue* value = environment()->ExpressionStackAt(0); |
5644 HValue* object = environment()->ExpressionStackAt(1); | 5474 HValue* object = environment()->ExpressionStackAt(1); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5707 ASSERT(has_side_effects); // Stores always have side effects. | 5537 ASSERT(has_side_effects); // Stores always have side effects. |
5708 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5538 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5709 return ast_context()->ReturnValue(Pop()); | 5539 return ast_context()->ReturnValue(Pop()); |
5710 } | 5540 } |
5711 } | 5541 } |
5712 | 5542 |
5713 | 5543 |
5714 // Because not every expression has a position and there is not common | 5544 // Because not every expression has a position and there is not common |
5715 // superclass of Assignment and CountOperation, we cannot just pass the | 5545 // superclass of Assignment and CountOperation, we cannot just pass the |
5716 // owning expression instead of position and ast_id separately. | 5546 // owning expression instead of position and ast_id separately. |
5717 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 5547 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
5718 Variable* var, | 5548 HValue* value, |
5719 HValue* value, | 5549 int position, |
5720 int position, | 5550 BailoutId ast_id) { |
5721 BailoutId ast_id) { | |
5722 LookupResult lookup(isolate()); | 5551 LookupResult lookup(isolate()); |
5723 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 5552 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
5724 if (type == kUseCell) { | 5553 if (type == kUseCell) { |
5725 Handle<GlobalObject> global(info()->global_object()); | 5554 Handle<GlobalObject> global(info()->global_object()); |
5726 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 5555 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
5727 HInstruction* instr = | 5556 HInstruction* instr = |
5728 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); | 5557 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); |
5729 instr->set_position(position); | 5558 instr->set_position(position); |
5730 AddInstruction(instr); | 5559 AddInstruction(instr); |
5731 if (instr->HasObservableSideEffects()) { | 5560 if (instr->HasObservableSideEffects()) { |
(...skipping 10 matching lines...) Expand all Loading... |
5742 value, | 5571 value, |
5743 function_strict_mode_flag()); | 5572 function_strict_mode_flag()); |
5744 instr->set_position(position); | 5573 instr->set_position(position); |
5745 AddInstruction(instr); | 5574 AddInstruction(instr); |
5746 ASSERT(instr->HasObservableSideEffects()); | 5575 ASSERT(instr->HasObservableSideEffects()); |
5747 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 5576 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
5748 } | 5577 } |
5749 } | 5578 } |
5750 | 5579 |
5751 | 5580 |
5752 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5581 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
5753 Expression* target = expr->target(); | 5582 Expression* target = expr->target(); |
5754 VariableProxy* proxy = target->AsVariableProxy(); | 5583 VariableProxy* proxy = target->AsVariableProxy(); |
5755 Property* prop = target->AsProperty(); | 5584 Property* prop = target->AsProperty(); |
5756 ASSERT(proxy == NULL || prop == NULL); | 5585 ASSERT(proxy == NULL || prop == NULL); |
5757 | 5586 |
5758 // We have a second position recorded in the FullCodeGenerator to have | 5587 // We have a second position recorded in the FullCodeGenerator to have |
5759 // type feedback for the binary operation. | 5588 // type feedback for the binary operation. |
5760 BinaryOperation* operation = expr->binary_operation(); | 5589 BinaryOperation* operation = expr->binary_operation(); |
5761 | 5590 |
5762 if (proxy != NULL) { | 5591 if (proxy != NULL) { |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5939 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5768 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5940 return ast_context()->ReturnValue(Pop()); | 5769 return ast_context()->ReturnValue(Pop()); |
5941 } | 5770 } |
5942 | 5771 |
5943 } else { | 5772 } else { |
5944 return Bailout("invalid lhs in compound assignment"); | 5773 return Bailout("invalid lhs in compound assignment"); |
5945 } | 5774 } |
5946 } | 5775 } |
5947 | 5776 |
5948 | 5777 |
5949 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 5778 void HGraphBuilder::VisitAssignment(Assignment* expr) { |
5950 ASSERT(!HasStackOverflow()); | 5779 ASSERT(!HasStackOverflow()); |
5951 ASSERT(current_block() != NULL); | 5780 ASSERT(current_block() != NULL); |
5952 ASSERT(current_block()->HasPredecessor()); | 5781 ASSERT(current_block()->HasPredecessor()); |
5953 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 5782 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
5954 Property* prop = expr->target()->AsProperty(); | 5783 Property* prop = expr->target()->AsProperty(); |
5955 ASSERT(proxy == NULL || prop == NULL); | 5784 ASSERT(proxy == NULL || prop == NULL); |
5956 | 5785 |
5957 if (expr->is_compound()) { | 5786 if (expr->is_compound()) { |
5958 HandleCompoundAssignment(expr); | 5787 HandleCompoundAssignment(expr); |
5959 return; | 5788 return; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6066 | 5895 |
6067 case Variable::LOOKUP: | 5896 case Variable::LOOKUP: |
6068 return Bailout("assignment to LOOKUP variable"); | 5897 return Bailout("assignment to LOOKUP variable"); |
6069 } | 5898 } |
6070 } else { | 5899 } else { |
6071 return Bailout("invalid left-hand side in assignment"); | 5900 return Bailout("invalid left-hand side in assignment"); |
6072 } | 5901 } |
6073 } | 5902 } |
6074 | 5903 |
6075 | 5904 |
6076 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { | 5905 void HGraphBuilder::VisitThrow(Throw* expr) { |
6077 ASSERT(!HasStackOverflow()); | 5906 ASSERT(!HasStackOverflow()); |
6078 ASSERT(current_block() != NULL); | 5907 ASSERT(current_block() != NULL); |
6079 ASSERT(current_block()->HasPredecessor()); | 5908 ASSERT(current_block()->HasPredecessor()); |
6080 // We don't optimize functions with invalid left-hand sides in | 5909 // We don't optimize functions with invalid left-hand sides in |
6081 // assignments, count operations, or for-in. Consequently throw can | 5910 // assignments, count operations, or for-in. Consequently throw can |
6082 // currently only occur in an effect context. | 5911 // currently only occur in an effect context. |
6083 ASSERT(ast_context()->IsEffect()); | 5912 ASSERT(ast_context()->IsEffect()); |
6084 CHECK_ALIVE(VisitForValue(expr->exception())); | 5913 CHECK_ALIVE(VisitForValue(expr->exception())); |
6085 | 5914 |
6086 HValue* context = environment()->LookupContext(); | 5915 HValue* context = environment()->LookupContext(); |
6087 HValue* value = environment()->Pop(); | 5916 HValue* value = environment()->Pop(); |
6088 HThrow* instr = new(zone()) HThrow(context, value); | 5917 HThrow* instr = new(zone()) HThrow(context, value); |
6089 instr->set_position(expr->position()); | 5918 instr->set_position(expr->position()); |
6090 AddInstruction(instr); | 5919 AddInstruction(instr); |
6091 AddSimulate(expr->id()); | 5920 AddSimulate(expr->id()); |
6092 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5921 current_block()->FinishExit(new(zone()) HAbnormalExit); |
6093 set_current_block(NULL); | 5922 set_current_block(NULL); |
6094 } | 5923 } |
6095 | 5924 |
6096 | 5925 |
6097 HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField( | 5926 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
6098 HValue* object, | 5927 Handle<Map> map, |
6099 Handle<Map> map, | 5928 LookupResult* lookup) { |
6100 LookupResult* lookup) { | |
6101 int index = lookup->GetLocalFieldIndexFromMap(*map); | 5929 int index = lookup->GetLocalFieldIndexFromMap(*map); |
6102 if (index < 0) { | 5930 if (index < 0) { |
6103 // Negative property indices are in-object properties, indexed | 5931 // Negative property indices are in-object properties, indexed |
6104 // from the end of the fixed part of the object. | 5932 // from the end of the fixed part of the object. |
6105 int offset = (index * kPointerSize) + map->instance_size(); | 5933 int offset = (index * kPointerSize) + map->instance_size(); |
6106 return new(zone()) HLoadNamedField(object, true, offset); | 5934 return new(zone()) HLoadNamedField(object, true, offset); |
6107 } else { | 5935 } else { |
6108 // Non-negative property indices are in the properties array. | 5936 // Non-negative property indices are in the properties array. |
6109 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 5937 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
6110 return new(zone()) HLoadNamedField(object, false, offset); | 5938 return new(zone()) HLoadNamedField(object, false, offset); |
6111 } | 5939 } |
6112 } | 5940 } |
6113 | 5941 |
6114 | 5942 |
6115 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5943 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* object, |
6116 HValue* object, | 5944 Handle<String> name, |
6117 Handle<String> name, | 5945 Property* expr) { |
6118 Property* expr) { | |
6119 if (expr->IsUninitialized() && !FLAG_always_opt) { | 5946 if (expr->IsUninitialized() && !FLAG_always_opt) { |
6120 AddInstruction(new(zone()) HSoftDeoptimize); | 5947 AddInstruction(new(zone()) HSoftDeoptimize); |
6121 current_block()->MarkAsDeoptimizing(); | 5948 current_block()->MarkAsDeoptimizing(); |
6122 } | 5949 } |
6123 HValue* context = environment()->LookupContext(); | 5950 HValue* context = environment()->LookupContext(); |
6124 return new(zone()) HLoadNamedGeneric(context, object, name); | 5951 return new(zone()) HLoadNamedGeneric(context, object, name); |
6125 } | 5952 } |
6126 | 5953 |
6127 | 5954 |
6128 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 5955 HInstruction* HGraphBuilder::BuildCallGetter(HValue* object, |
6129 HValue* object, | 5956 Handle<Map> map, |
6130 Handle<Map> map, | 5957 Handle<JSFunction> getter, |
6131 Handle<JSFunction> getter, | 5958 Handle<JSObject> holder) { |
6132 Handle<JSObject> holder) { | |
6133 AddCheckConstantFunction(holder, object, map); | 5959 AddCheckConstantFunction(holder, object, map); |
6134 AddInstruction(new(zone()) HPushArgument(object)); | 5960 AddInstruction(new(zone()) HPushArgument(object)); |
6135 return new(zone()) HCallConstantFunction(getter, 1); | 5961 return new(zone()) HCallConstantFunction(getter, 1); |
6136 } | 5962 } |
6137 | 5963 |
6138 | 5964 |
6139 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( | 5965 HInstruction* HGraphBuilder::BuildLoadNamedMonomorphic(HValue* object, |
6140 HValue* object, | 5966 Handle<String> name, |
6141 Handle<String> name, | 5967 Property* expr, |
6142 Property* expr, | 5968 Handle<Map> map) { |
6143 Handle<Map> map) { | |
6144 // Handle a load from a known field. | 5969 // Handle a load from a known field. |
6145 ASSERT(!map->is_dictionary_map()); | 5970 ASSERT(!map->is_dictionary_map()); |
6146 LookupResult lookup(isolate()); | 5971 LookupResult lookup(isolate()); |
6147 map->LookupDescriptor(NULL, *name, &lookup); | 5972 map->LookupDescriptor(NULL, *name, &lookup); |
6148 if (lookup.IsField()) { | 5973 if (lookup.IsField()) { |
6149 AddCheckMapsWithTransitions(object, map); | 5974 AddCheckMapsWithTransitions(object, map); |
6150 return BuildLoadNamedField(object, map, &lookup); | 5975 return BuildLoadNamedField(object, map, &lookup); |
6151 } | 5976 } |
6152 | 5977 |
6153 // Handle a load of a constant known function. | 5978 // Handle a load of a constant known function. |
(...skipping 13 matching lines...) Expand all Loading... |
6167 HInstruction* holder_value = | 5992 HInstruction* holder_value = |
6168 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder)); | 5993 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder)); |
6169 return BuildLoadNamedField(holder_value, holder_map, &lookup); | 5994 return BuildLoadNamedField(holder_value, holder_map, &lookup); |
6170 } | 5995 } |
6171 | 5996 |
6172 // No luck, do a generic load. | 5997 // No luck, do a generic load. |
6173 return BuildLoadNamedGeneric(object, name, expr); | 5998 return BuildLoadNamedGeneric(object, name, expr); |
6174 } | 5999 } |
6175 | 6000 |
6176 | 6001 |
6177 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 6002 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
6178 HValue* key) { | 6003 HValue* key) { |
6179 HValue* context = environment()->LookupContext(); | 6004 HValue* context = environment()->LookupContext(); |
6180 return new(zone()) HLoadKeyedGeneric(context, object, key); | 6005 return new(zone()) HLoadKeyedGeneric(context, object, key); |
6181 } | 6006 } |
6182 | 6007 |
6183 | 6008 |
6184 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 6009 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( |
6185 HValue* object, | 6010 HValue* external_elements, |
6186 HValue* key, | 6011 HValue* checked_key, |
6187 HValue* val, | 6012 HValue* val, |
6188 HValue* dependency, | 6013 HValue* dependency, |
6189 Handle<Map> map, | 6014 ElementsKind elements_kind, |
6190 bool is_store) { | 6015 bool is_store) { |
| 6016 if (is_store) { |
| 6017 ASSERT(val != NULL); |
| 6018 switch (elements_kind) { |
| 6019 case EXTERNAL_PIXEL_ELEMENTS: { |
| 6020 val = AddInstruction(new(zone()) HClampToUint8(val)); |
| 6021 break; |
| 6022 } |
| 6023 case EXTERNAL_BYTE_ELEMENTS: |
| 6024 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 6025 case EXTERNAL_SHORT_ELEMENTS: |
| 6026 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 6027 case EXTERNAL_INT_ELEMENTS: |
| 6028 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 6029 break; |
| 6030 } |
| 6031 case EXTERNAL_FLOAT_ELEMENTS: |
| 6032 case EXTERNAL_DOUBLE_ELEMENTS: |
| 6033 break; |
| 6034 case FAST_SMI_ELEMENTS: |
| 6035 case FAST_ELEMENTS: |
| 6036 case FAST_DOUBLE_ELEMENTS: |
| 6037 case FAST_HOLEY_SMI_ELEMENTS: |
| 6038 case FAST_HOLEY_ELEMENTS: |
| 6039 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 6040 case DICTIONARY_ELEMENTS: |
| 6041 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 6042 UNREACHABLE(); |
| 6043 break; |
| 6044 } |
| 6045 return new(zone()) HStoreKeyed(external_elements, |
| 6046 checked_key, |
| 6047 val, |
| 6048 elements_kind); |
| 6049 } else { |
| 6050 ASSERT(val == NULL); |
| 6051 HLoadKeyed* load = |
| 6052 new(zone()) HLoadKeyed( |
| 6053 external_elements, checked_key, dependency, elements_kind); |
| 6054 if (FLAG_opt_safe_uint32_operations && |
| 6055 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 6056 graph()->RecordUint32Instruction(load); |
| 6057 } |
| 6058 return load; |
| 6059 } |
| 6060 } |
| 6061 |
| 6062 |
| 6063 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, |
| 6064 HValue* checked_key, |
| 6065 HValue* val, |
| 6066 HValue* load_dependency, |
| 6067 ElementsKind elements_kind, |
| 6068 bool is_store) { |
| 6069 if (is_store) { |
| 6070 ASSERT(val != NULL); |
| 6071 switch (elements_kind) { |
| 6072 case FAST_SMI_ELEMENTS: |
| 6073 case FAST_HOLEY_SMI_ELEMENTS: |
| 6074 // Smi-only arrays need a smi check. |
| 6075 AddInstruction(new(zone()) HCheckSmi(val)); |
| 6076 // Fall through. |
| 6077 case FAST_ELEMENTS: |
| 6078 case FAST_HOLEY_ELEMENTS: |
| 6079 case FAST_DOUBLE_ELEMENTS: |
| 6080 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 6081 return new(zone()) HStoreKeyed( |
| 6082 elements, checked_key, val, elements_kind); |
| 6083 default: |
| 6084 UNREACHABLE(); |
| 6085 return NULL; |
| 6086 } |
| 6087 } |
| 6088 // It's an element load (!is_store). |
| 6089 return new(zone()) HLoadKeyed(elements, |
| 6090 checked_key, |
| 6091 load_dependency, |
| 6092 elements_kind); |
| 6093 } |
| 6094 |
| 6095 |
| 6096 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, |
| 6097 HValue* key, |
| 6098 HValue* val, |
| 6099 HValue* dependency, |
| 6100 Handle<Map> map, |
| 6101 bool is_store) { |
6191 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, | 6102 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, |
6192 zone(), dependency); | 6103 zone(), dependency); |
6193 AddInstruction(mapcheck); | 6104 AddInstruction(mapcheck); |
6194 if (dependency) { | 6105 if (dependency) { |
6195 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 6106 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
6196 } | 6107 } |
6197 return BuildUncheckedMonomorphicElementAccess( | 6108 return BuildUncheckedMonomorphicElementAccess(object, key, val, |
6198 object, key, val, | 6109 mapcheck, map, is_store); |
6199 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | |
6200 map->elements_kind(), is_store); | |
6201 } | 6110 } |
6202 | 6111 |
6203 | 6112 |
6204 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( | 6113 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
6205 HValue* object, | 6114 HValue* object, |
6206 HValue* key, | 6115 HValue* key, |
6207 HValue* val, | 6116 HValue* val, |
| 6117 HCheckMaps* mapcheck, |
| 6118 Handle<Map> map, |
| 6119 bool is_store) { |
| 6120 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
| 6121 // on a HElementsTransition instruction. The flag can also be removed if the |
| 6122 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
| 6123 // ElementsKind transitions. Finally, the dependency can be removed for stores |
| 6124 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
| 6125 // generated store code. |
| 6126 if ((map->elements_kind() == FAST_HOLEY_ELEMENTS) || |
| 6127 (map->elements_kind() == FAST_ELEMENTS && is_store)) { |
| 6128 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
| 6129 } |
| 6130 bool fast_smi_only_elements = map->has_fast_smi_elements(); |
| 6131 bool fast_elements = map->has_fast_object_elements(); |
| 6132 HInstruction* elements = |
| 6133 AddInstruction(new(zone()) HLoadElements(object, mapcheck)); |
| 6134 if (is_store && (fast_elements || fast_smi_only_elements)) { |
| 6135 HCheckMaps* check_cow_map = new(zone()) HCheckMaps( |
| 6136 elements, isolate()->factory()->fixed_array_map(), zone()); |
| 6137 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 6138 AddInstruction(check_cow_map); |
| 6139 } |
| 6140 HInstruction* length = NULL; |
| 6141 HInstruction* checked_key = NULL; |
| 6142 if (map->has_external_array_elements()) { |
| 6143 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
| 6144 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, |
| 6145 ALLOW_SMI_KEY)); |
| 6146 HLoadExternalArrayPointer* external_elements = |
| 6147 new(zone()) HLoadExternalArrayPointer(elements); |
| 6148 AddInstruction(external_elements); |
| 6149 return BuildExternalArrayElementAccess( |
| 6150 external_elements, checked_key, val, mapcheck, |
| 6151 map->elements_kind(), is_store); |
| 6152 } |
| 6153 ASSERT(fast_smi_only_elements || |
| 6154 fast_elements || |
| 6155 map->has_fast_double_elements()); |
| 6156 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 6157 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck, |
| 6158 HType::Smi())); |
| 6159 } else { |
| 6160 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
| 6161 } |
| 6162 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, |
| 6163 ALLOW_SMI_KEY)); |
| 6164 return BuildFastElementAccess(elements, checked_key, val, mapcheck, |
| 6165 map->elements_kind(), is_store); |
| 6166 } |
| 6167 |
| 6168 |
| 6169 HInstruction* HGraphBuilder::TryBuildConsolidatedElementLoad( |
| 6170 HValue* object, |
| 6171 HValue* key, |
| 6172 HValue* val, |
6208 SmallMapList* maps) { | 6173 SmallMapList* maps) { |
6209 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | 6174 // For polymorphic loads of similar elements kinds (i.e. all tagged or all |
6210 // double), always use the "worst case" code without a transition. This is | 6175 // double), always use the "worst case" code without a transition. This is |
6211 // much faster than transitioning the elements to the worst case, trading a | 6176 // much faster than transitioning the elements to the worst case, trading a |
6212 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. | 6177 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. |
6213 bool has_double_maps = false; | 6178 bool has_double_maps = false; |
6214 bool has_smi_or_object_maps = false; | 6179 bool has_smi_or_object_maps = false; |
6215 bool has_js_array_access = false; | 6180 bool has_js_array_access = false; |
6216 bool has_non_js_array_access = false; | 6181 bool has_non_js_array_access = false; |
6217 Handle<Map> most_general_consolidated_map; | 6182 Handle<Map> most_general_consolidated_map; |
(...skipping 24 matching lines...) Expand all Loading... |
6242 most_general_consolidated_map->elements_kind(), | 6207 most_general_consolidated_map->elements_kind(), |
6243 map->elements_kind())) { | 6208 map->elements_kind())) { |
6244 most_general_consolidated_map = map; | 6209 most_general_consolidated_map = map; |
6245 } | 6210 } |
6246 } | 6211 } |
6247 if (!has_double_maps && !has_smi_or_object_maps) return NULL; | 6212 if (!has_double_maps && !has_smi_or_object_maps) return NULL; |
6248 | 6213 |
6249 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); | 6214 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); |
6250 AddInstruction(check_maps); | 6215 AddInstruction(check_maps); |
6251 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 6216 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
6252 object, key, val, check_maps, | 6217 object, key, val, check_maps, most_general_consolidated_map, false); |
6253 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | |
6254 most_general_consolidated_map->elements_kind(), | |
6255 false); | |
6256 return instr; | 6218 return instr; |
6257 } | 6219 } |
6258 | 6220 |
6259 | 6221 |
6260 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 6222 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, |
6261 HValue* object, | 6223 HValue* key, |
6262 HValue* key, | 6224 HValue* val, |
6263 HValue* val, | 6225 Expression* prop, |
6264 Expression* prop, | 6226 BailoutId ast_id, |
6265 BailoutId ast_id, | 6227 int position, |
6266 int position, | 6228 bool is_store, |
6267 bool is_store, | 6229 bool* has_side_effects) { |
6268 bool* has_side_effects) { | |
6269 *has_side_effects = false; | 6230 *has_side_effects = false; |
6270 AddInstruction(new(zone()) HCheckNonSmi(object)); | 6231 AddInstruction(new(zone()) HCheckNonSmi(object)); |
6271 SmallMapList* maps = prop->GetReceiverTypes(); | 6232 SmallMapList* maps = prop->GetReceiverTypes(); |
6272 bool todo_external_array = false; | 6233 bool todo_external_array = false; |
6273 | 6234 |
6274 if (!is_store) { | 6235 if (!is_store) { |
6275 HInstruction* consolidated_load = | 6236 HInstruction* consolidated_load = |
6276 TryBuildConsolidatedElementLoad(object, key, val, maps); | 6237 TryBuildConsolidatedElementLoad(object, key, val, maps); |
6277 if (consolidated_load != NULL) { | 6238 if (consolidated_load != NULL) { |
6278 AddInstruction(consolidated_load); | 6239 AddInstruction(consolidated_load); |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6443 elements, checked_key, val, elements_kind_branch, | 6404 elements, checked_key, val, elements_kind_branch, |
6444 elements_kind, is_store)); | 6405 elements_kind, is_store)); |
6445 } else if (elements_kind == DICTIONARY_ELEMENTS) { | 6406 } else if (elements_kind == DICTIONARY_ELEMENTS) { |
6446 if (is_store) { | 6407 if (is_store) { |
6447 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 6408 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
6448 } else { | 6409 } else { |
6449 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 6410 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
6450 } | 6411 } |
6451 } else { // External array elements. | 6412 } else { // External array elements. |
6452 access = AddInstruction(BuildExternalArrayElementAccess( | 6413 access = AddInstruction(BuildExternalArrayElementAccess( |
6453 external_elements, checked_key, val, | 6414 external_elements, checked_key, val, elements_kind_branch, |
6454 elements_kind_branch, elements_kind, is_store)); | 6415 elements_kind, is_store)); |
6455 } | 6416 } |
6456 *has_side_effects |= access->HasObservableSideEffects(); | 6417 *has_side_effects |= access->HasObservableSideEffects(); |
6457 if (position != RelocInfo::kNoPosition) access->set_position(position); | 6418 if (position != RelocInfo::kNoPosition) access->set_position(position); |
6458 if (!is_store) { | 6419 if (!is_store) { |
6459 Push(access); | 6420 Push(access); |
6460 } | 6421 } |
6461 current_block()->Goto(join); | 6422 current_block()->Goto(join); |
6462 set_current_block(if_false); | 6423 set_current_block(if_false); |
6463 } | 6424 } |
6464 } | 6425 } |
6465 | 6426 |
6466 // Deopt if none of the cases matched. | 6427 // Deopt if none of the cases matched. |
6467 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 6428 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); |
6468 join->SetJoinId(ast_id); | 6429 join->SetJoinId(ast_id); |
6469 set_current_block(join); | 6430 set_current_block(join); |
6470 return is_store ? NULL : Pop(); | 6431 return is_store ? NULL : Pop(); |
6471 } | 6432 } |
6472 | 6433 |
6473 | 6434 |
6474 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 6435 HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj, |
6475 HValue* obj, | 6436 HValue* key, |
6476 HValue* key, | 6437 HValue* val, |
6477 HValue* val, | 6438 Expression* expr, |
6478 Expression* expr, | 6439 BailoutId ast_id, |
6479 BailoutId ast_id, | 6440 int position, |
6480 int position, | 6441 bool is_store, |
6481 bool is_store, | 6442 bool* has_side_effects) { |
6482 bool* has_side_effects) { | |
6483 ASSERT(!expr->IsPropertyName()); | 6443 ASSERT(!expr->IsPropertyName()); |
6484 HInstruction* instr = NULL; | 6444 HInstruction* instr = NULL; |
6485 if (expr->IsMonomorphic()) { | 6445 if (expr->IsMonomorphic()) { |
6486 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 6446 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
6487 if (map->has_slow_elements_kind()) { | 6447 if (map->has_slow_elements_kind()) { |
6488 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 6448 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
6489 : BuildLoadKeyedGeneric(obj, key); | 6449 : BuildLoadKeyedGeneric(obj, key); |
6490 } else { | 6450 } else { |
6491 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 6451 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
6492 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); | 6452 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); |
6493 } | 6453 } |
6494 } else if (expr->GetReceiverTypes() != NULL && | 6454 } else if (expr->GetReceiverTypes() != NULL && |
6495 !expr->GetReceiverTypes()->is_empty()) { | 6455 !expr->GetReceiverTypes()->is_empty()) { |
6496 return HandlePolymorphicElementAccess( | 6456 return HandlePolymorphicElementAccess( |
6497 obj, key, val, expr, ast_id, position, is_store, has_side_effects); | 6457 obj, key, val, expr, ast_id, position, is_store, has_side_effects); |
6498 } else { | 6458 } else { |
6499 if (is_store) { | 6459 if (is_store) { |
6500 instr = BuildStoreKeyedGeneric(obj, key, val); | 6460 instr = BuildStoreKeyedGeneric(obj, key, val); |
6501 } else { | 6461 } else { |
6502 instr = BuildLoadKeyedGeneric(obj, key); | 6462 instr = BuildLoadKeyedGeneric(obj, key); |
6503 } | 6463 } |
6504 } | 6464 } |
6505 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 6465 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
6506 AddInstruction(instr); | 6466 AddInstruction(instr); |
6507 *has_side_effects = instr->HasObservableSideEffects(); | 6467 *has_side_effects = instr->HasObservableSideEffects(); |
6508 return instr; | 6468 return instr; |
6509 } | 6469 } |
6510 | 6470 |
6511 | 6471 |
6512 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( | 6472 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, |
6513 HValue* object, | 6473 HValue* key, |
6514 HValue* key, | 6474 HValue* value) { |
6515 HValue* value) { | |
6516 HValue* context = environment()->LookupContext(); | 6475 HValue* context = environment()->LookupContext(); |
6517 return new(zone()) HStoreKeyedGeneric( | 6476 return new(zone()) HStoreKeyedGeneric( |
6518 context, | 6477 context, |
6519 object, | 6478 object, |
6520 key, | 6479 key, |
6521 value, | 6480 value, |
6522 function_strict_mode_flag()); | 6481 function_strict_mode_flag()); |
6523 } | 6482 } |
6524 | 6483 |
6525 | 6484 |
6526 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { | 6485 void HGraphBuilder::EnsureArgumentsArePushedForAccess() { |
6527 // Outermost function already has arguments on the stack. | 6486 // Outermost function already has arguments on the stack. |
6528 if (function_state()->outer() == NULL) return; | 6487 if (function_state()->outer() == NULL) return; |
6529 | 6488 |
6530 if (function_state()->arguments_pushed()) return; | 6489 if (function_state()->arguments_pushed()) return; |
6531 | 6490 |
6532 // Push arguments when entering inlined function. | 6491 // Push arguments when entering inlined function. |
6533 HEnterInlined* entry = function_state()->entry(); | 6492 HEnterInlined* entry = function_state()->entry(); |
6534 entry->set_arguments_pushed(); | 6493 entry->set_arguments_pushed(); |
6535 | 6494 |
6536 ZoneList<HValue*>* arguments_values = entry->arguments_values(); | 6495 ZoneList<HValue*>* arguments_values = entry->arguments_values(); |
6537 | 6496 |
6538 HInstruction* insert_after = entry; | 6497 HInstruction* insert_after = entry; |
6539 for (int i = 0; i < arguments_values->length(); i++) { | 6498 for (int i = 0; i < arguments_values->length(); i++) { |
6540 HValue* argument = arguments_values->at(i); | 6499 HValue* argument = arguments_values->at(i); |
6541 HInstruction* push_argument = new(zone()) HPushArgument(argument); | 6500 HInstruction* push_argument = new(zone()) HPushArgument(argument); |
6542 push_argument->InsertAfter(insert_after); | 6501 push_argument->InsertAfter(insert_after); |
6543 insert_after = push_argument; | 6502 insert_after = push_argument; |
6544 } | 6503 } |
6545 | 6504 |
6546 HArgumentsElements* arguments_elements = | 6505 HArgumentsElements* arguments_elements = |
6547 new(zone()) HArgumentsElements(true); | 6506 new(zone()) HArgumentsElements(true); |
6548 arguments_elements->ClearFlag(HValue::kUseGVN); | 6507 arguments_elements->ClearFlag(HValue::kUseGVN); |
6549 arguments_elements->InsertAfter(insert_after); | 6508 arguments_elements->InsertAfter(insert_after); |
6550 function_state()->set_arguments_elements(arguments_elements); | 6509 function_state()->set_arguments_elements(arguments_elements); |
6551 } | 6510 } |
6552 | 6511 |
6553 | 6512 |
6554 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) { | 6513 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { |
6555 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 6514 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
6556 if (proxy == NULL) return false; | 6515 if (proxy == NULL) return false; |
6557 if (!proxy->var()->IsStackAllocated()) return false; | 6516 if (!proxy->var()->IsStackAllocated()) return false; |
6558 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { | 6517 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { |
6559 return false; | 6518 return false; |
6560 } | 6519 } |
6561 | 6520 |
6562 HInstruction* result = NULL; | 6521 HInstruction* result = NULL; |
6563 if (expr->key()->IsPropertyName()) { | 6522 if (expr->key()->IsPropertyName()) { |
6564 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6523 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6603 HInstruction* checked_key = | 6562 HInstruction* checked_key = |
6604 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 6563 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
6605 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 6564 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
6606 } | 6565 } |
6607 } | 6566 } |
6608 ast_context()->ReturnInstruction(result, expr->id()); | 6567 ast_context()->ReturnInstruction(result, expr->id()); |
6609 return true; | 6568 return true; |
6610 } | 6569 } |
6611 | 6570 |
6612 | 6571 |
6613 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 6572 void HGraphBuilder::VisitProperty(Property* expr) { |
6614 ASSERT(!HasStackOverflow()); | 6573 ASSERT(!HasStackOverflow()); |
6615 ASSERT(current_block() != NULL); | 6574 ASSERT(current_block() != NULL); |
6616 ASSERT(current_block()->HasPredecessor()); | 6575 ASSERT(current_block()->HasPredecessor()); |
6617 expr->RecordTypeFeedback(oracle(), zone()); | 6576 expr->RecordTypeFeedback(oracle(), zone()); |
6618 | 6577 |
6619 if (TryArgumentsAccess(expr)) return; | 6578 if (TryArgumentsAccess(expr)) return; |
6620 | 6579 |
6621 CHECK_ALIVE(VisitForValue(expr->obj())); | 6580 CHECK_ALIVE(VisitForValue(expr->obj())); |
6622 | 6581 |
6623 HInstruction* instr = NULL; | 6582 HInstruction* instr = NULL; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6694 Drop(1); | 6653 Drop(1); |
6695 } | 6654 } |
6696 } | 6655 } |
6697 return ast_context()->ReturnValue(load); | 6656 return ast_context()->ReturnValue(load); |
6698 } | 6657 } |
6699 instr->set_position(expr->position()); | 6658 instr->set_position(expr->position()); |
6700 return ast_context()->ReturnInstruction(instr, expr->id()); | 6659 return ast_context()->ReturnInstruction(instr, expr->id()); |
6701 } | 6660 } |
6702 | 6661 |
6703 | 6662 |
6704 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 6663 void HGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
6705 Handle<Map> receiver_map) { | 6664 Handle<Map> receiver_map) { |
6706 if (!holder.is_null()) { | 6665 if (!holder.is_null()) { |
6707 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6666 AddInstruction(new(zone()) HCheckPrototypeMaps( |
6708 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); | 6667 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); |
6709 } | 6668 } |
6710 } | 6669 } |
6711 | 6670 |
6712 | 6671 |
6713 void HOptimizedGraphBuilder::AddCheckConstantFunction( | 6672 void HGraphBuilder::AddCheckConstantFunction(Handle<JSObject> holder, |
6714 Handle<JSObject> holder, | 6673 HValue* receiver, |
6715 HValue* receiver, | 6674 Handle<Map> receiver_map) { |
6716 Handle<Map> receiver_map) { | |
6717 // Constant functions have the nice property that the map will change if they | 6675 // Constant functions have the nice property that the map will change if they |
6718 // are overwritten. Therefore it is enough to check the map of the holder and | 6676 // are overwritten. Therefore it is enough to check the map of the holder and |
6719 // its prototypes. | 6677 // its prototypes. |
6720 AddCheckMapsWithTransitions(receiver, receiver_map); | 6678 AddCheckMapsWithTransitions(receiver, receiver_map); |
6721 AddCheckPrototypeMaps(holder, receiver_map); | 6679 AddCheckPrototypeMaps(holder, receiver_map); |
6722 } | 6680 } |
6723 | 6681 |
6724 | 6682 |
6725 class FunctionSorter { | 6683 class FunctionSorter { |
6726 public: | 6684 public: |
(...skipping 21 matching lines...) Expand all Loading... |
6748 FunctionSorter const* function1 = reinterpret_cast<FunctionSorter const*>(a); | 6706 FunctionSorter const* function1 = reinterpret_cast<FunctionSorter const*>(a); |
6749 FunctionSorter const* function2 = reinterpret_cast<FunctionSorter const*>(b); | 6707 FunctionSorter const* function2 = reinterpret_cast<FunctionSorter const*>(b); |
6750 int diff = function1->ticks() - function2->ticks(); | 6708 int diff = function1->ticks() - function2->ticks(); |
6751 if (diff != 0) return -diff; | 6709 if (diff != 0) return -diff; |
6752 diff = function1->ast_length() - function2->ast_length(); | 6710 diff = function1->ast_length() - function2->ast_length(); |
6753 if (diff != 0) return diff; | 6711 if (diff != 0) return diff; |
6754 return function1->src_length() - function2->src_length(); | 6712 return function1->src_length() - function2->src_length(); |
6755 } | 6713 } |
6756 | 6714 |
6757 | 6715 |
6758 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( | 6716 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, |
6759 Call* expr, | 6717 HValue* receiver, |
6760 HValue* receiver, | 6718 SmallMapList* types, |
6761 SmallMapList* types, | 6719 Handle<String> name) { |
6762 Handle<String> name) { | |
6763 // TODO(ager): We should recognize when the prototype chains for different | 6720 // TODO(ager): We should recognize when the prototype chains for different |
6764 // maps are identical. In that case we can avoid repeatedly generating the | 6721 // maps are identical. In that case we can avoid repeatedly generating the |
6765 // same prototype map checks. | 6722 // same prototype map checks. |
6766 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6723 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
6767 HBasicBlock* join = NULL; | 6724 HBasicBlock* join = NULL; |
6768 FunctionSorter order[kMaxCallPolymorphism]; | 6725 FunctionSorter order[kMaxCallPolymorphism]; |
6769 int ordered_functions = 0; | 6726 int ordered_functions = 0; |
6770 for (int i = 0; | 6727 for (int i = 0; |
6771 i < types->length() && ordered_functions < kMaxCallPolymorphism; | 6728 i < types->length() && ordered_functions < kMaxCallPolymorphism; |
6772 ++i) { | 6729 ++i) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6854 if (join->HasPredecessor()) { | 6811 if (join->HasPredecessor()) { |
6855 set_current_block(join); | 6812 set_current_block(join); |
6856 join->SetJoinId(expr->id()); | 6813 join->SetJoinId(expr->id()); |
6857 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 6814 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
6858 } else { | 6815 } else { |
6859 set_current_block(NULL); | 6816 set_current_block(NULL); |
6860 } | 6817 } |
6861 } | 6818 } |
6862 | 6819 |
6863 | 6820 |
6864 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target, | 6821 void HGraphBuilder::TraceInline(Handle<JSFunction> target, |
6865 Handle<JSFunction> caller, | 6822 Handle<JSFunction> caller, |
6866 const char* reason) { | 6823 const char* reason) { |
6867 if (FLAG_trace_inlining) { | 6824 if (FLAG_trace_inlining) { |
6868 SmartArrayPointer<char> target_name = | 6825 SmartArrayPointer<char> target_name = |
6869 target->shared()->DebugName()->ToCString(); | 6826 target->shared()->DebugName()->ToCString(); |
6870 SmartArrayPointer<char> caller_name = | 6827 SmartArrayPointer<char> caller_name = |
6871 caller->shared()->DebugName()->ToCString(); | 6828 caller->shared()->DebugName()->ToCString(); |
6872 if (reason == NULL) { | 6829 if (reason == NULL) { |
6873 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); | 6830 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); |
6874 } else { | 6831 } else { |
6875 PrintF("Did not inline %s called from %s (%s).\n", | 6832 PrintF("Did not inline %s called from %s (%s).\n", |
6876 *target_name, *caller_name, reason); | 6833 *target_name, *caller_name, reason); |
6877 } | 6834 } |
6878 } | 6835 } |
6879 } | 6836 } |
6880 | 6837 |
6881 | 6838 |
6882 static const int kNotInlinable = 1000000000; | 6839 static const int kNotInlinable = 1000000000; |
6883 | 6840 |
6884 | 6841 |
6885 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { | 6842 int HGraphBuilder::InliningAstSize(Handle<JSFunction> target) { |
6886 if (!FLAG_use_inlining) return kNotInlinable; | 6843 if (!FLAG_use_inlining) return kNotInlinable; |
6887 | 6844 |
6888 // Precondition: call is monomorphic and we have found a target with the | 6845 // Precondition: call is monomorphic and we have found a target with the |
6889 // appropriate arity. | 6846 // appropriate arity. |
6890 Handle<JSFunction> caller = info()->closure(); | 6847 Handle<JSFunction> caller = info()->closure(); |
6891 Handle<SharedFunctionInfo> target_shared(target->shared()); | 6848 Handle<SharedFunctionInfo> target_shared(target->shared()); |
6892 | 6849 |
6893 // Do a quick check on source code length to avoid parsing large | 6850 // Do a quick check on source code length to avoid parsing large |
6894 // inlining candidates. | 6851 // inlining candidates. |
6895 if (target_shared->SourceSize() > | 6852 if (target_shared->SourceSize() > |
(...skipping 10 matching lines...) Expand all Loading... |
6906 if (target_shared->dont_inline() || target_shared->dont_optimize()) { | 6863 if (target_shared->dont_inline() || target_shared->dont_optimize()) { |
6907 TraceInline(target, caller, "target contains unsupported syntax [early]"); | 6864 TraceInline(target, caller, "target contains unsupported syntax [early]"); |
6908 return kNotInlinable; | 6865 return kNotInlinable; |
6909 } | 6866 } |
6910 | 6867 |
6911 int nodes_added = target_shared->ast_node_count(); | 6868 int nodes_added = target_shared->ast_node_count(); |
6912 return nodes_added; | 6869 return nodes_added; |
6913 } | 6870 } |
6914 | 6871 |
6915 | 6872 |
6916 bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, | 6873 bool HGraphBuilder::TryInline(CallKind call_kind, |
6917 Handle<JSFunction> target, | 6874 Handle<JSFunction> target, |
6918 int arguments_count, | 6875 int arguments_count, |
6919 HValue* implicit_return_value, | 6876 HValue* implicit_return_value, |
6920 BailoutId ast_id, | 6877 BailoutId ast_id, |
6921 BailoutId return_id, | 6878 BailoutId return_id, |
6922 InliningKind inlining_kind) { | 6879 InliningKind inlining_kind) { |
6923 int nodes_added = InliningAstSize(target); | 6880 int nodes_added = InliningAstSize(target); |
6924 if (nodes_added == kNotInlinable) return false; | 6881 if (nodes_added == kNotInlinable) return false; |
6925 | 6882 |
6926 Handle<JSFunction> caller = info()->closure(); | 6883 Handle<JSFunction> caller = info()->closure(); |
6927 | 6884 |
6928 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { | 6885 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { |
6929 TraceInline(target, caller, "target AST is too large [early]"); | 6886 TraceInline(target, caller, "target AST is too large [early]"); |
6930 return false; | 6887 return false; |
6931 } | 6888 } |
6932 | 6889 |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7221 function_return()->SetJoinId(ast_id); | 7178 function_return()->SetJoinId(ast_id); |
7222 set_current_block(function_return()); | 7179 set_current_block(function_return()); |
7223 } else { | 7180 } else { |
7224 set_current_block(NULL); | 7181 set_current_block(NULL); |
7225 } | 7182 } |
7226 delete target_state; | 7183 delete target_state; |
7227 return true; | 7184 return true; |
7228 } | 7185 } |
7229 | 7186 |
7230 | 7187 |
7231 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { | 7188 bool HGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { |
7232 // The function call we are inlining is a method call if the call | 7189 // The function call we are inlining is a method call if the call |
7233 // is a property call. | 7190 // is a property call. |
7234 CallKind call_kind = (expr->expression()->AsProperty() == NULL) | 7191 CallKind call_kind = (expr->expression()->AsProperty() == NULL) |
7235 ? CALL_AS_FUNCTION | 7192 ? CALL_AS_FUNCTION |
7236 : CALL_AS_METHOD; | 7193 : CALL_AS_METHOD; |
7237 | 7194 |
7238 return TryInline(call_kind, | 7195 return TryInline(call_kind, |
7239 expr->target(), | 7196 expr->target(), |
7240 expr->arguments()->length(), | 7197 expr->arguments()->length(), |
7241 NULL, | 7198 NULL, |
7242 expr->id(), | 7199 expr->id(), |
7243 expr->ReturnId(), | 7200 expr->ReturnId(), |
7244 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); | 7201 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); |
7245 } | 7202 } |
7246 | 7203 |
7247 | 7204 |
7248 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, | 7205 bool HGraphBuilder::TryInlineConstruct(CallNew* expr, |
7249 HValue* implicit_return_value) { | 7206 HValue* implicit_return_value) { |
7250 return TryInline(CALL_AS_FUNCTION, | 7207 return TryInline(CALL_AS_FUNCTION, |
7251 expr->target(), | 7208 expr->target(), |
7252 expr->arguments()->length(), | 7209 expr->arguments()->length(), |
7253 implicit_return_value, | 7210 implicit_return_value, |
7254 expr->id(), | 7211 expr->id(), |
7255 expr->ReturnId(), | 7212 expr->ReturnId(), |
7256 CONSTRUCT_CALL_RETURN); | 7213 CONSTRUCT_CALL_RETURN); |
7257 } | 7214 } |
7258 | 7215 |
7259 | 7216 |
7260 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, | 7217 bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, |
7261 Property* prop) { | 7218 Property* prop) { |
7262 return TryInline(CALL_AS_METHOD, | 7219 return TryInline(CALL_AS_METHOD, |
7263 getter, | 7220 getter, |
7264 0, | 7221 0, |
7265 NULL, | 7222 NULL, |
7266 prop->id(), | 7223 prop->id(), |
7267 prop->LoadId(), | 7224 prop->LoadId(), |
7268 GETTER_CALL_RETURN); | 7225 GETTER_CALL_RETURN); |
7269 } | 7226 } |
7270 | 7227 |
7271 | 7228 |
7272 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, | 7229 bool HGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, |
7273 Assignment* assignment, | 7230 Assignment* assignment, |
7274 HValue* implicit_return_value) { | 7231 HValue* implicit_return_value) { |
7275 return TryInline(CALL_AS_METHOD, | 7232 return TryInline(CALL_AS_METHOD, |
7276 setter, | 7233 setter, |
7277 1, | 7234 1, |
7278 implicit_return_value, | 7235 implicit_return_value, |
7279 assignment->id(), | 7236 assignment->id(), |
7280 assignment->AssignmentId(), | 7237 assignment->AssignmentId(), |
7281 SETTER_CALL_RETURN); | 7238 SETTER_CALL_RETURN); |
7282 } | 7239 } |
7283 | 7240 |
7284 | 7241 |
7285 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, | 7242 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) { |
7286 bool drop_extra) { | |
7287 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 7243 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
7288 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 7244 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
7289 switch (id) { | 7245 switch (id) { |
7290 case kMathExp: | 7246 case kMathExp: |
7291 if (!FLAG_fast_math) break; | 7247 if (!FLAG_fast_math) break; |
7292 // Fall through if FLAG_fast_math. | 7248 // Fall through if FLAG_fast_math. |
7293 case kMathRound: | 7249 case kMathRound: |
7294 case kMathAbs: | 7250 case kMathAbs: |
7295 case kMathSqrt: | 7251 case kMathSqrt: |
7296 case kMathLog: | 7252 case kMathLog: |
(...skipping 13 matching lines...) Expand all Loading... |
7310 } | 7266 } |
7311 break; | 7267 break; |
7312 default: | 7268 default: |
7313 // Not supported for inlining yet. | 7269 // Not supported for inlining yet. |
7314 break; | 7270 break; |
7315 } | 7271 } |
7316 return false; | 7272 return false; |
7317 } | 7273 } |
7318 | 7274 |
7319 | 7275 |
7320 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( | 7276 bool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr, |
7321 Call* expr, | 7277 HValue* receiver, |
7322 HValue* receiver, | 7278 Handle<Map> receiver_map, |
7323 Handle<Map> receiver_map, | 7279 CheckType check_type) { |
7324 CheckType check_type) { | |
7325 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); | 7280 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); |
7326 // Try to inline calls like Math.* as operations in the calling function. | 7281 // Try to inline calls like Math.* as operations in the calling function. |
7327 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 7282 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
7328 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 7283 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
7329 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7284 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
7330 switch (id) { | 7285 switch (id) { |
7331 case kStringCharCodeAt: | 7286 case kStringCharCodeAt: |
7332 case kStringCharAt: | 7287 case kStringCharAt: |
7333 if (argument_count == 2 && check_type == STRING_CHECK) { | 7288 if (argument_count == 2 && check_type == STRING_CHECK) { |
7334 HValue* index = Pop(); | 7289 HValue* index = Pop(); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7444 } | 7399 } |
7445 break; | 7400 break; |
7446 default: | 7401 default: |
7447 // Not yet supported for inlining. | 7402 // Not yet supported for inlining. |
7448 break; | 7403 break; |
7449 } | 7404 } |
7450 return false; | 7405 return false; |
7451 } | 7406 } |
7452 | 7407 |
7453 | 7408 |
7454 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { | 7409 bool HGraphBuilder::TryCallApply(Call* expr) { |
7455 Expression* callee = expr->expression(); | 7410 Expression* callee = expr->expression(); |
7456 Property* prop = callee->AsProperty(); | 7411 Property* prop = callee->AsProperty(); |
7457 ASSERT(prop != NULL); | 7412 ASSERT(prop != NULL); |
7458 | 7413 |
7459 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { | 7414 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { |
7460 return false; | 7415 return false; |
7461 } | 7416 } |
7462 Handle<Map> function_map = expr->GetReceiverTypes()->first(); | 7417 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
7463 if (function_map->instance_type() != JS_FUNCTION_TYPE || | 7418 if (function_map->instance_type() != JS_FUNCTION_TYPE || |
7464 !expr->target()->shared()->HasBuiltinFunctionId() || | 7419 !expr->target()->shared()->HasBuiltinFunctionId() || |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7572 return NULL; | 7527 return NULL; |
7573 } | 7528 } |
7574 current = next; | 7529 current = next; |
7575 } | 7530 } |
7576 } | 7531 } |
7577 | 7532 |
7578 return kinds[first_index]; | 7533 return kinds[first_index]; |
7579 } | 7534 } |
7580 | 7535 |
7581 | 7536 |
7582 void HOptimizedGraphBuilder::VisitCall(Call* expr) { | 7537 void HGraphBuilder::VisitCall(Call* expr) { |
7583 ASSERT(!HasStackOverflow()); | 7538 ASSERT(!HasStackOverflow()); |
7584 ASSERT(current_block() != NULL); | 7539 ASSERT(current_block() != NULL); |
7585 ASSERT(current_block()->HasPredecessor()); | 7540 ASSERT(current_block()->HasPredecessor()); |
7586 Expression* callee = expr->expression(); | 7541 Expression* callee = expr->expression(); |
7587 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7542 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
7588 HInstruction* call = NULL; | 7543 HInstruction* call = NULL; |
7589 | 7544 |
7590 Property* prop = callee->AsProperty(); | 7545 Property* prop = callee->AsProperty(); |
7591 if (prop != NULL) { | 7546 if (prop != NULL) { |
7592 if (!prop->key()->IsPropertyName()) { | 7547 if (!prop->key()->IsPropertyName()) { |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7802 | 7757 |
7803 | 7758 |
7804 // Checks whether allocation using the given constructor can be inlined. | 7759 // Checks whether allocation using the given constructor can be inlined. |
7805 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 7760 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
7806 return constructor->has_initial_map() && | 7761 return constructor->has_initial_map() && |
7807 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 7762 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
7808 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; | 7763 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; |
7809 } | 7764 } |
7810 | 7765 |
7811 | 7766 |
7812 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 7767 void HGraphBuilder::VisitCallNew(CallNew* expr) { |
7813 ASSERT(!HasStackOverflow()); | 7768 ASSERT(!HasStackOverflow()); |
7814 ASSERT(current_block() != NULL); | 7769 ASSERT(current_block() != NULL); |
7815 ASSERT(current_block()->HasPredecessor()); | 7770 ASSERT(current_block()->HasPredecessor()); |
7816 expr->RecordTypeFeedback(oracle()); | 7771 expr->RecordTypeFeedback(oracle()); |
7817 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 7772 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
7818 HValue* context = environment()->LookupContext(); | 7773 HValue* context = environment()->LookupContext(); |
7819 | 7774 |
7820 if (FLAG_inline_construct && | 7775 if (FLAG_inline_construct && |
7821 expr->IsMonomorphic() && | 7776 expr->IsMonomorphic() && |
7822 IsAllocationInlineable(expr->target())) { | 7777 IsAllocationInlineable(expr->target())) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7866 new(zone()) HCallNew(context, constructor, argument_count); | 7821 new(zone()) HCallNew(context, constructor, argument_count); |
7867 Drop(argument_count); | 7822 Drop(argument_count); |
7868 call->set_position(expr->position()); | 7823 call->set_position(expr->position()); |
7869 return ast_context()->ReturnInstruction(call, expr->id()); | 7824 return ast_context()->ReturnInstruction(call, expr->id()); |
7870 } | 7825 } |
7871 } | 7826 } |
7872 | 7827 |
7873 | 7828 |
7874 // Support for generating inlined runtime functions. | 7829 // Support for generating inlined runtime functions. |
7875 | 7830 |
7876 // Lookup table for generators for runtime calls that are generated inline. | 7831 // Lookup table for generators for runtime calls that are generated inline. |
7877 // Elements of the table are member pointers to functions of | 7832 // Elements of the table are member pointers to functions of HGraphBuilder. |
7878 // HOptimizedGraphBuilder. | |
7879 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ | 7833 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ |
7880 &HOptimizedGraphBuilder::Generate##Name, | 7834 &HGraphBuilder::Generate##Name, |
7881 | 7835 |
7882 const HOptimizedGraphBuilder::InlineFunctionGenerator | 7836 const HGraphBuilder::InlineFunctionGenerator |
7883 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = { | 7837 HGraphBuilder::kInlineFunctionGenerators[] = { |
7884 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 7838 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
7885 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 7839 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
7886 }; | 7840 }; |
7887 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 7841 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
7888 | 7842 |
7889 | 7843 |
7890 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 7844 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
7891 ASSERT(!HasStackOverflow()); | 7845 ASSERT(!HasStackOverflow()); |
7892 ASSERT(current_block() != NULL); | 7846 ASSERT(current_block() != NULL); |
7893 ASSERT(current_block()->HasPredecessor()); | 7847 ASSERT(current_block()->HasPredecessor()); |
7894 if (expr->is_jsruntime()) { | 7848 if (expr->is_jsruntime()) { |
7895 return Bailout("call to a JavaScript runtime function"); | 7849 return Bailout("call to a JavaScript runtime function"); |
7896 } | 7850 } |
7897 | 7851 |
7898 const Runtime::Function* function = expr->function(); | 7852 const Runtime::Function* function = expr->function(); |
7899 ASSERT(function != NULL); | 7853 ASSERT(function != NULL); |
7900 if (function->intrinsic_type == Runtime::INLINE) { | 7854 if (function->intrinsic_type == Runtime::INLINE) { |
(...skipping 17 matching lines...) Expand all Loading... |
7918 Handle<String> name = expr->name(); | 7872 Handle<String> name = expr->name(); |
7919 int argument_count = expr->arguments()->length(); | 7873 int argument_count = expr->arguments()->length(); |
7920 HCallRuntime* call = | 7874 HCallRuntime* call = |
7921 new(zone()) HCallRuntime(context, name, function, argument_count); | 7875 new(zone()) HCallRuntime(context, name, function, argument_count); |
7922 Drop(argument_count); | 7876 Drop(argument_count); |
7923 return ast_context()->ReturnInstruction(call, expr->id()); | 7877 return ast_context()->ReturnInstruction(call, expr->id()); |
7924 } | 7878 } |
7925 } | 7879 } |
7926 | 7880 |
7927 | 7881 |
7928 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 7882 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
7929 ASSERT(!HasStackOverflow()); | 7883 ASSERT(!HasStackOverflow()); |
7930 ASSERT(current_block() != NULL); | 7884 ASSERT(current_block() != NULL); |
7931 ASSERT(current_block()->HasPredecessor()); | 7885 ASSERT(current_block()->HasPredecessor()); |
7932 switch (expr->op()) { | 7886 switch (expr->op()) { |
7933 case Token::DELETE: return VisitDelete(expr); | 7887 case Token::DELETE: return VisitDelete(expr); |
7934 case Token::VOID: return VisitVoid(expr); | 7888 case Token::VOID: return VisitVoid(expr); |
7935 case Token::TYPEOF: return VisitTypeof(expr); | 7889 case Token::TYPEOF: return VisitTypeof(expr); |
7936 case Token::ADD: return VisitAdd(expr); | 7890 case Token::ADD: return VisitAdd(expr); |
7937 case Token::SUB: return VisitSub(expr); | 7891 case Token::SUB: return VisitSub(expr); |
7938 case Token::BIT_NOT: return VisitBitNot(expr); | 7892 case Token::BIT_NOT: return VisitBitNot(expr); |
7939 case Token::NOT: return VisitNot(expr); | 7893 case Token::NOT: return VisitNot(expr); |
7940 default: UNREACHABLE(); | 7894 default: UNREACHABLE(); |
7941 } | 7895 } |
7942 } | 7896 } |
7943 | 7897 |
7944 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { | 7898 void HGraphBuilder::VisitDelete(UnaryOperation* expr) { |
7945 Property* prop = expr->expression()->AsProperty(); | 7899 Property* prop = expr->expression()->AsProperty(); |
7946 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7900 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
7947 if (prop != NULL) { | 7901 if (prop != NULL) { |
7948 CHECK_ALIVE(VisitForValue(prop->obj())); | 7902 CHECK_ALIVE(VisitForValue(prop->obj())); |
7949 CHECK_ALIVE(VisitForValue(prop->key())); | 7903 CHECK_ALIVE(VisitForValue(prop->key())); |
7950 HValue* key = Pop(); | 7904 HValue* key = Pop(); |
7951 HValue* obj = Pop(); | 7905 HValue* obj = Pop(); |
7952 HValue* context = environment()->LookupContext(); | 7906 HValue* context = environment()->LookupContext(); |
7953 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); | 7907 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); |
7954 return ast_context()->ReturnInstruction(instr, expr->id()); | 7908 return ast_context()->ReturnInstruction(instr, expr->id()); |
(...skipping 14 matching lines...) Expand all Loading... |
7969 } | 7923 } |
7970 } else { | 7924 } else { |
7971 // Result of deleting non-property, non-variable reference is true. | 7925 // Result of deleting non-property, non-variable reference is true. |
7972 // Evaluate the subexpression for side effects. | 7926 // Evaluate the subexpression for side effects. |
7973 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7927 CHECK_ALIVE(VisitForEffect(expr->expression())); |
7974 return ast_context()->ReturnValue(graph()->GetConstantTrue()); | 7928 return ast_context()->ReturnValue(graph()->GetConstantTrue()); |
7975 } | 7929 } |
7976 } | 7930 } |
7977 | 7931 |
7978 | 7932 |
7979 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { | 7933 void HGraphBuilder::VisitVoid(UnaryOperation* expr) { |
7980 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7934 CHECK_ALIVE(VisitForEffect(expr->expression())); |
7981 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 7935 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
7982 } | 7936 } |
7983 | 7937 |
7984 | 7938 |
7985 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 7939 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
7986 CHECK_ALIVE(VisitForTypeOf(expr->expression())); | 7940 CHECK_ALIVE(VisitForTypeOf(expr->expression())); |
7987 HValue* value = Pop(); | 7941 HValue* value = Pop(); |
7988 HValue* context = environment()->LookupContext(); | 7942 HValue* context = environment()->LookupContext(); |
7989 HInstruction* instr = new(zone()) HTypeof(context, value); | 7943 HInstruction* instr = new(zone()) HTypeof(context, value); |
7990 return ast_context()->ReturnInstruction(instr, expr->id()); | 7944 return ast_context()->ReturnInstruction(instr, expr->id()); |
7991 } | 7945 } |
7992 | 7946 |
7993 | 7947 |
7994 void HOptimizedGraphBuilder::VisitAdd(UnaryOperation* expr) { | 7948 void HGraphBuilder::VisitAdd(UnaryOperation* expr) { |
7995 CHECK_ALIVE(VisitForValue(expr->expression())); | 7949 CHECK_ALIVE(VisitForValue(expr->expression())); |
7996 HValue* value = Pop(); | 7950 HValue* value = Pop(); |
7997 HValue* context = environment()->LookupContext(); | 7951 HValue* context = environment()->LookupContext(); |
7998 HInstruction* instr = | 7952 HInstruction* instr = |
7999 new(zone()) HMul(context, value, graph()->GetConstant1()); | 7953 new(zone()) HMul(context, value, graph_->GetConstant1()); |
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::VisitSub(UnaryOperation* expr) { | 7958 void HGraphBuilder::VisitSub(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()->GetConstantMinus1()); | 7963 new(zone()) HMul(context, value, graph_->GetConstantMinus1()); |
8010 TypeInfo info = oracle()->UnaryType(expr); | 7964 TypeInfo info = oracle()->UnaryType(expr); |
8011 Representation rep = ToRepresentation(info); | 7965 Representation rep = ToRepresentation(info); |
8012 if (info.IsUninitialized()) { | 7966 if (info.IsUninitialized()) { |
8013 AddInstruction(new(zone()) HSoftDeoptimize); | 7967 AddInstruction(new(zone()) HSoftDeoptimize); |
8014 current_block()->MarkAsDeoptimizing(); | 7968 current_block()->MarkAsDeoptimizing(); |
8015 info = TypeInfo::Unknown(); | 7969 info = TypeInfo::Unknown(); |
8016 } | 7970 } |
8017 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); | 7971 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); |
8018 return ast_context()->ReturnInstruction(instr, expr->id()); | 7972 return ast_context()->ReturnInstruction(instr, expr->id()); |
8019 } | 7973 } |
8020 | 7974 |
8021 | 7975 |
8022 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 7976 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
8023 CHECK_ALIVE(VisitForValue(expr->expression())); | 7977 CHECK_ALIVE(VisitForValue(expr->expression())); |
8024 HValue* value = Pop(); | 7978 HValue* value = Pop(); |
8025 TypeInfo info = oracle()->UnaryType(expr); | 7979 TypeInfo info = oracle()->UnaryType(expr); |
8026 if (info.IsUninitialized()) { | 7980 if (info.IsUninitialized()) { |
8027 AddInstruction(new(zone()) HSoftDeoptimize); | 7981 AddInstruction(new(zone()) HSoftDeoptimize); |
8028 current_block()->MarkAsDeoptimizing(); | 7982 current_block()->MarkAsDeoptimizing(); |
8029 } | 7983 } |
8030 HInstruction* instr = new(zone()) HBitNot(value); | 7984 HInstruction* instr = new(zone()) HBitNot(value); |
8031 return ast_context()->ReturnInstruction(instr, expr->id()); | 7985 return ast_context()->ReturnInstruction(instr, expr->id()); |
8032 } | 7986 } |
8033 | 7987 |
8034 | 7988 |
8035 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 7989 void HGraphBuilder::VisitNot(UnaryOperation* expr) { |
8036 if (ast_context()->IsTest()) { | 7990 if (ast_context()->IsTest()) { |
8037 TestContext* context = TestContext::cast(ast_context()); | 7991 TestContext* context = TestContext::cast(ast_context()); |
8038 VisitForControl(expr->expression(), | 7992 VisitForControl(expr->expression(), |
8039 context->if_false(), | 7993 context->if_false(), |
8040 context->if_true()); | 7994 context->if_true()); |
8041 return; | 7995 return; |
8042 } | 7996 } |
8043 | 7997 |
8044 if (ast_context()->IsEffect()) { | 7998 if (ast_context()->IsEffect()) { |
8045 VisitForEffect(expr->expression()); | 7999 VisitForEffect(expr->expression()); |
(...skipping 23 matching lines...) Expand all Loading... |
8069 materialize_true = NULL; | 8023 materialize_true = NULL; |
8070 } | 8024 } |
8071 | 8025 |
8072 HBasicBlock* join = | 8026 HBasicBlock* join = |
8073 CreateJoin(materialize_false, materialize_true, expr->id()); | 8027 CreateJoin(materialize_false, materialize_true, expr->id()); |
8074 set_current_block(join); | 8028 set_current_block(join); |
8075 if (join != NULL) return ast_context()->ReturnValue(Pop()); | 8029 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
8076 } | 8030 } |
8077 | 8031 |
8078 | 8032 |
8079 HInstruction* HOptimizedGraphBuilder::BuildIncrement( | 8033 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input, |
8080 bool returns_original_input, | 8034 CountOperation* expr) { |
8081 CountOperation* expr) { | |
8082 // The input to the count operation is on top of the expression stack. | 8035 // The input to the count operation is on top of the expression stack. |
8083 TypeInfo info = oracle()->IncrementType(expr); | 8036 TypeInfo info = oracle()->IncrementType(expr); |
8084 Representation rep = ToRepresentation(info); | 8037 Representation rep = ToRepresentation(info); |
8085 if (rep.IsTagged()) { | 8038 if (rep.IsTagged()) { |
8086 rep = Representation::Integer32(); | 8039 rep = Representation::Integer32(); |
8087 } | 8040 } |
8088 | 8041 |
8089 if (returns_original_input) { | 8042 if (returns_original_input) { |
8090 // We need an explicit HValue representing ToNumber(input). The | 8043 // We need an explicit HValue representing ToNumber(input). The |
8091 // actual HChange instruction we need is (sometimes) added in a later | 8044 // actual HChange instruction we need is (sometimes) added in a later |
8092 // phase, so it is not available now to be used as an input to HAdd and | 8045 // phase, so it is not available now to be used as an input to HAdd and |
8093 // as the return value. | 8046 // as the return value. |
8094 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); | 8047 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); |
8095 AddInstruction(number_input); | 8048 AddInstruction(number_input); |
8096 Push(number_input); | 8049 Push(number_input); |
8097 } | 8050 } |
8098 | 8051 |
8099 // The addition has no side effects, so we do not need | 8052 // The addition has no side effects, so we do not need |
8100 // to simulate the expression stack after this instruction. | 8053 // to simulate the expression stack after this instruction. |
8101 // Any later failures deopt to the load of the input or earlier. | 8054 // Any later failures deopt to the load of the input or earlier. |
8102 HConstant* delta = (expr->op() == Token::INC) | 8055 HConstant* delta = (expr->op() == Token::INC) |
8103 ? graph()->GetConstant1() | 8056 ? graph_->GetConstant1() |
8104 : graph()->GetConstantMinus1(); | 8057 : graph_->GetConstantMinus1(); |
8105 HValue* context = environment()->LookupContext(); | 8058 HValue* context = environment()->LookupContext(); |
8106 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); | 8059 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); |
8107 // We can't insert a simulate here, because it would break deoptimization, | 8060 // We can't insert a simulate here, because it would break deoptimization, |
8108 // so the HAdd must not have side effects, so we must freeze its | 8061 // so the HAdd must not have side effects, so we must freeze its |
8109 // representation. | 8062 // representation. |
8110 instr->AssumeRepresentation(rep); | 8063 instr->AssumeRepresentation(rep); |
8111 instr->ClearAllSideEffects(); | 8064 instr->ClearAllSideEffects(); |
8112 AddInstruction(instr); | 8065 AddInstruction(instr); |
8113 return instr; | 8066 return instr; |
8114 } | 8067 } |
8115 | 8068 |
8116 | 8069 |
8117 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 8070 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
8118 ASSERT(!HasStackOverflow()); | 8071 ASSERT(!HasStackOverflow()); |
8119 ASSERT(current_block() != NULL); | 8072 ASSERT(current_block() != NULL); |
8120 ASSERT(current_block()->HasPredecessor()); | 8073 ASSERT(current_block()->HasPredecessor()); |
8121 Expression* target = expr->expression(); | 8074 Expression* target = expr->expression(); |
8122 VariableProxy* proxy = target->AsVariableProxy(); | 8075 VariableProxy* proxy = target->AsVariableProxy(); |
8123 Property* prop = target->AsProperty(); | 8076 Property* prop = target->AsProperty(); |
8124 if (proxy == NULL && prop == NULL) { | 8077 if (proxy == NULL && prop == NULL) { |
8125 return Bailout("invalid lhs in count operation"); | 8078 return Bailout("invalid lhs in count operation"); |
8126 } | 8079 } |
8127 | 8080 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8191 return Bailout("lookup variable in count operation"); | 8144 return Bailout("lookup variable in count operation"); |
8192 } | 8145 } |
8193 | 8146 |
8194 } else { | 8147 } else { |
8195 // Argument of the count operation is a property. | 8148 // Argument of the count operation is a property. |
8196 ASSERT(prop != NULL); | 8149 ASSERT(prop != NULL); |
8197 prop->RecordTypeFeedback(oracle(), zone()); | 8150 prop->RecordTypeFeedback(oracle(), zone()); |
8198 | 8151 |
8199 if (prop->key()->IsPropertyName()) { | 8152 if (prop->key()->IsPropertyName()) { |
8200 // Named property. | 8153 // Named property. |
8201 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 8154 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
8202 | 8155 |
8203 CHECK_ALIVE(VisitForValue(prop->obj())); | 8156 CHECK_ALIVE(VisitForValue(prop->obj())); |
8204 HValue* object = Top(); | 8157 HValue* object = Top(); |
8205 | 8158 |
8206 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 8159 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
8207 Handle<Map> map; | 8160 Handle<Map> map; |
8208 HInstruction* load; | 8161 HInstruction* load; |
8209 bool monomorphic = prop->IsMonomorphic(); | 8162 bool monomorphic = prop->IsMonomorphic(); |
8210 if (monomorphic) { | 8163 if (monomorphic) { |
8211 map = prop->GetReceiverTypes()->first(); | 8164 map = prop->GetReceiverTypes()->first(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8252 // of the operation, and the placeholder with the original value if | 8205 // of the operation, and the placeholder with the original value if |
8253 // necessary. | 8206 // necessary. |
8254 environment()->SetExpressionStackAt(0, after); | 8207 environment()->SetExpressionStackAt(0, after); |
8255 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 8208 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
8256 if (store->HasObservableSideEffects()) { | 8209 if (store->HasObservableSideEffects()) { |
8257 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 8210 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
8258 } | 8211 } |
8259 | 8212 |
8260 } else { | 8213 } else { |
8261 // Keyed property. | 8214 // Keyed property. |
8262 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 8215 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
8263 | 8216 |
8264 CHECK_ALIVE(VisitForValue(prop->obj())); | 8217 CHECK_ALIVE(VisitForValue(prop->obj())); |
8265 CHECK_ALIVE(VisitForValue(prop->key())); | 8218 CHECK_ALIVE(VisitForValue(prop->key())); |
8266 HValue* obj = environment()->ExpressionStackAt(1); | 8219 HValue* obj = environment()->ExpressionStackAt(1); |
8267 HValue* key = environment()->ExpressionStackAt(0); | 8220 HValue* key = environment()->ExpressionStackAt(0); |
8268 | 8221 |
8269 bool has_side_effects = false; | 8222 bool has_side_effects = false; |
8270 HValue* load = HandleKeyedElementAccess( | 8223 HValue* load = HandleKeyedElementAccess( |
8271 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 8224 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
8272 false, // is_store | 8225 false, // is_store |
(...skipping 19 matching lines...) Expand all Loading... |
8292 ASSERT(has_side_effects); // Stores always have side effects. | 8245 ASSERT(has_side_effects); // Stores always have side effects. |
8293 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 8246 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
8294 } | 8247 } |
8295 } | 8248 } |
8296 | 8249 |
8297 Drop(returns_original_input ? 2 : 1); | 8250 Drop(returns_original_input ? 2 : 1); |
8298 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 8251 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
8299 } | 8252 } |
8300 | 8253 |
8301 | 8254 |
8302 HStringCharCodeAt* HOptimizedGraphBuilder::BuildStringCharCodeAt( | 8255 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context, |
8303 HValue* context, | 8256 HValue* string, |
8304 HValue* string, | 8257 HValue* index) { |
8305 HValue* index) { | |
8306 AddInstruction(new(zone()) HCheckNonSmi(string)); | 8258 AddInstruction(new(zone()) HCheckNonSmi(string)); |
8307 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 8259 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
8308 HStringLength* length = new(zone()) HStringLength(string); | 8260 HStringLength* length = new(zone()) HStringLength(string); |
8309 AddInstruction(length); | 8261 AddInstruction(length); |
8310 HInstruction* checked_index = | 8262 HInstruction* checked_index = |
8311 AddInstruction(new(zone()) HBoundsCheck(index, length)); | 8263 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
8312 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 8264 return new(zone()) HStringCharCodeAt(context, string, checked_index); |
8313 } | 8265 } |
8314 | 8266 |
8315 // Checks if the given shift amounts have form: (sa) and (32 - sa). | 8267 // Checks if the given shift amounts have form: (sa) and (32 - sa). |
8316 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 8268 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
8317 HValue* const32_minus_sa) { | 8269 HValue* const32_minus_sa) { |
8318 if (!const32_minus_sa->IsSub()) return false; | 8270 if (!const32_minus_sa->IsSub()) return false; |
8319 HSub* sub = HSub::cast(const32_minus_sa); | 8271 HSub* sub = HSub::cast(const32_minus_sa); |
8320 HValue* const32 = sub->left(); | 8272 HValue* const32 = sub->left(); |
8321 if (!const32->IsConstant() || | 8273 if (!const32->IsConstant() || |
8322 HConstant::cast(const32)->Integer32Value() != 32) { | 8274 HConstant::cast(const32)->Integer32Value() != 32) { |
8323 return false; | 8275 return false; |
8324 } | 8276 } |
8325 return (sub->right() == sa); | 8277 return (sub->right() == sa); |
8326 } | 8278 } |
8327 | 8279 |
8328 | 8280 |
8329 // Checks if the left and the right are shift instructions with the oposite | 8281 // Checks if the left and the right are shift instructions with the oposite |
8330 // directions that can be replaced by one rotate right instruction or not. | 8282 // directions that can be replaced by one rotate right instruction or not. |
8331 // Returns the operand and the shift amount for the rotate instruction in the | 8283 // Returns the operand and the shift amount for the rotate instruction in the |
8332 // former case. | 8284 // former case. |
8333 bool HOptimizedGraphBuilder::MatchRotateRight(HValue* left, | 8285 bool HGraphBuilder::MatchRotateRight(HValue* left, |
8334 HValue* right, | 8286 HValue* right, |
8335 HValue** operand, | 8287 HValue** operand, |
8336 HValue** shift_amount) { | 8288 HValue** shift_amount) { |
8337 HShl* shl; | 8289 HShl* shl; |
8338 HShr* shr; | 8290 HShr* shr; |
8339 if (left->IsShl() && right->IsShr()) { | 8291 if (left->IsShl() && right->IsShr()) { |
8340 shl = HShl::cast(left); | 8292 shl = HShl::cast(left); |
8341 shr = HShr::cast(right); | 8293 shr = HShr::cast(right); |
8342 } else if (left->IsShr() && right->IsShl()) { | 8294 } else if (left->IsShr() && right->IsShl()) { |
8343 shl = HShl::cast(right); | 8295 shl = HShl::cast(right); |
8344 shr = HShr::cast(left); | 8296 shr = HShr::cast(left); |
8345 } else { | 8297 } else { |
8346 return false; | 8298 return false; |
(...skipping 14 matching lines...) Expand all Loading... |
8361 HConstant* right_const = HConstant::cast(right); | 8313 HConstant* right_const = HConstant::cast(right); |
8362 if (right_const->HasInteger32Value() && | 8314 if (right_const->HasInteger32Value() && |
8363 (right_const->Integer32Value() & 0x1f) != 0) { | 8315 (right_const->Integer32Value() & 0x1f) != 0) { |
8364 return false; | 8316 return false; |
8365 } | 8317 } |
8366 } | 8318 } |
8367 return true; | 8319 return true; |
8368 } | 8320 } |
8369 | 8321 |
8370 | 8322 |
8371 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 8323 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
8372 BinaryOperation* expr, | 8324 HValue* left, |
8373 HValue* left, | 8325 HValue* right) { |
8374 HValue* right) { | |
8375 HValue* context = environment()->LookupContext(); | 8326 HValue* context = environment()->LookupContext(); |
8376 TypeInfo left_info, right_info, result_info, combined_info; | 8327 TypeInfo left_info, right_info, result_info, combined_info; |
8377 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); | 8328 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); |
8378 Representation left_rep = ToRepresentation(left_info); | 8329 Representation left_rep = ToRepresentation(left_info); |
8379 Representation right_rep = ToRepresentation(right_info); | 8330 Representation right_rep = ToRepresentation(right_info); |
8380 Representation result_rep = ToRepresentation(result_info); | 8331 Representation result_rep = ToRepresentation(result_info); |
8381 if (left_info.IsUninitialized()) { | 8332 if (left_info.IsUninitialized()) { |
8382 // Can't have initialized one but not the other. | 8333 // Can't have initialized one but not the other. |
8383 ASSERT(right_info.IsUninitialized()); | 8334 ASSERT(right_info.IsUninitialized()); |
8384 AddInstruction(new(zone()) HSoftDeoptimize); | 8335 AddInstruction(new(zone()) HSoftDeoptimize); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8457 if (call == NULL) return false; | 8408 if (call == NULL) return false; |
8458 Literal* literal = expr->right()->AsLiteral(); | 8409 Literal* literal = expr->right()->AsLiteral(); |
8459 if (literal == NULL) return false; | 8410 if (literal == NULL) return false; |
8460 if (!literal->handle()->IsString()) return false; | 8411 if (!literal->handle()->IsString()) return false; |
8461 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; | 8412 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; |
8462 ASSERT(call->arguments()->length() == 1); | 8413 ASSERT(call->arguments()->length() == 1); |
8463 return true; | 8414 return true; |
8464 } | 8415 } |
8465 | 8416 |
8466 | 8417 |
8467 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 8418 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
8468 ASSERT(!HasStackOverflow()); | 8419 ASSERT(!HasStackOverflow()); |
8469 ASSERT(current_block() != NULL); | 8420 ASSERT(current_block() != NULL); |
8470 ASSERT(current_block()->HasPredecessor()); | 8421 ASSERT(current_block()->HasPredecessor()); |
8471 switch (expr->op()) { | 8422 switch (expr->op()) { |
8472 case Token::COMMA: | 8423 case Token::COMMA: |
8473 return VisitComma(expr); | 8424 return VisitComma(expr); |
8474 case Token::OR: | 8425 case Token::OR: |
8475 case Token::AND: | 8426 case Token::AND: |
8476 return VisitLogicalExpression(expr); | 8427 return VisitLogicalExpression(expr); |
8477 default: | 8428 default: |
8478 return VisitArithmeticExpression(expr); | 8429 return VisitArithmeticExpression(expr); |
8479 } | 8430 } |
8480 } | 8431 } |
8481 | 8432 |
8482 | 8433 |
8483 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) { | 8434 void HGraphBuilder::VisitComma(BinaryOperation* expr) { |
8484 CHECK_ALIVE(VisitForEffect(expr->left())); | 8435 CHECK_ALIVE(VisitForEffect(expr->left())); |
8485 // Visit the right subexpression in the same AST context as the entire | 8436 // Visit the right subexpression in the same AST context as the entire |
8486 // expression. | 8437 // expression. |
8487 Visit(expr->right()); | 8438 Visit(expr->right()); |
8488 } | 8439 } |
8489 | 8440 |
8490 | 8441 |
8491 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { | 8442 void HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { |
8492 bool is_logical_and = expr->op() == Token::AND; | 8443 bool is_logical_and = expr->op() == Token::AND; |
8493 if (ast_context()->IsTest()) { | 8444 if (ast_context()->IsTest()) { |
8494 TestContext* context = TestContext::cast(ast_context()); | 8445 TestContext* context = TestContext::cast(ast_context()); |
8495 // Translate left subexpression. | 8446 // Translate left subexpression. |
8496 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 8447 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
8497 if (is_logical_and) { | 8448 if (is_logical_and) { |
8498 CHECK_BAILOUT(VisitForControl(expr->left(), | 8449 CHECK_BAILOUT(VisitForControl(expr->left(), |
8499 eval_right, | 8450 eval_right, |
8500 context->if_false())); | 8451 context->if_false())); |
8501 } else { | 8452 } else { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8571 | 8522 |
8572 HBasicBlock* join_block = | 8523 HBasicBlock* join_block = |
8573 CreateJoin(empty_block, right_block, expr->id()); | 8524 CreateJoin(empty_block, right_block, expr->id()); |
8574 set_current_block(join_block); | 8525 set_current_block(join_block); |
8575 // We did not materialize any value in the predecessor environments, | 8526 // We did not materialize any value in the predecessor environments, |
8576 // so there is no need to handle it here. | 8527 // so there is no need to handle it here. |
8577 } | 8528 } |
8578 } | 8529 } |
8579 | 8530 |
8580 | 8531 |
8581 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { | 8532 void HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { |
8582 CHECK_ALIVE(VisitForValue(expr->left())); | 8533 CHECK_ALIVE(VisitForValue(expr->left())); |
8583 CHECK_ALIVE(VisitForValue(expr->right())); | 8534 CHECK_ALIVE(VisitForValue(expr->right())); |
8584 HValue* right = Pop(); | 8535 HValue* right = Pop(); |
8585 HValue* left = Pop(); | 8536 HValue* left = Pop(); |
8586 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 8537 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
8587 instr->set_position(expr->position()); | 8538 instr->set_position(expr->position()); |
8588 return ast_context()->ReturnInstruction(instr, expr->id()); | 8539 return ast_context()->ReturnInstruction(instr, expr->id()); |
8589 } | 8540 } |
8590 | 8541 |
8591 | 8542 |
8592 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) { | 8543 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { |
8593 if (info.IsUninitialized()) return Representation::None(); | 8544 if (info.IsUninitialized()) return Representation::None(); |
8594 if (info.IsSmi()) return Representation::Integer32(); | 8545 if (info.IsSmi()) return Representation::Integer32(); |
8595 if (info.IsInteger32()) return Representation::Integer32(); | 8546 if (info.IsInteger32()) return Representation::Integer32(); |
8596 if (info.IsDouble()) return Representation::Double(); | 8547 if (info.IsDouble()) return Representation::Double(); |
8597 if (info.IsNumber()) return Representation::Double(); | 8548 if (info.IsNumber()) return Representation::Double(); |
8598 return Representation::Tagged(); | 8549 return Representation::Tagged(); |
8599 } | 8550 } |
8600 | 8551 |
8601 | 8552 |
8602 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 8553 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
8603 HTypeof* typeof_expr, | 8554 HTypeof* typeof_expr, |
8604 Handle<String> check) { | 8555 Handle<String> check) { |
8605 // Note: The HTypeof itself is removed during canonicalization, if possible. | 8556 // Note: The HTypeof itself is removed during canonicalization, if possible. |
8606 HValue* value = typeof_expr->value(); | 8557 HValue* value = typeof_expr->value(); |
8607 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); | 8558 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); |
8608 instr->set_position(expr->position()); | 8559 instr->set_position(expr->position()); |
8609 return ast_context()->ReturnControl(instr, expr->id()); | 8560 return ast_context()->ReturnControl(instr, expr->id()); |
8610 } | 8561 } |
8611 | 8562 |
8612 | 8563 |
8613 static bool MatchLiteralCompareNil(HValue* left, | 8564 static bool MatchLiteralCompareNil(HValue* left, |
8614 Token::Value op, | 8565 Token::Value op, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8664 | 8615 |
8665 static bool IsLiteralCompareBool(HValue* left, | 8616 static bool IsLiteralCompareBool(HValue* left, |
8666 Token::Value op, | 8617 Token::Value op, |
8667 HValue* right) { | 8618 HValue* right) { |
8668 return op == Token::EQ_STRICT && | 8619 return op == Token::EQ_STRICT && |
8669 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || | 8620 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || |
8670 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); | 8621 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); |
8671 } | 8622 } |
8672 | 8623 |
8673 | 8624 |
8674 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 8625 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
8675 ASSERT(!HasStackOverflow()); | 8626 ASSERT(!HasStackOverflow()); |
8676 ASSERT(current_block() != NULL); | 8627 ASSERT(current_block() != NULL); |
8677 ASSERT(current_block()->HasPredecessor()); | 8628 ASSERT(current_block()->HasPredecessor()); |
8678 if (IsClassOfTest(expr)) { | 8629 if (IsClassOfTest(expr)) { |
8679 CallRuntime* call = expr->left()->AsCallRuntime(); | 8630 CallRuntime* call = expr->left()->AsCallRuntime(); |
8680 ASSERT(call->arguments()->length() == 1); | 8631 ASSERT(call->arguments()->length() == 1); |
8681 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8632 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8682 HValue* value = Pop(); | 8633 HValue* value = Pop(); |
8683 Literal* literal = expr->right()->AsLiteral(); | 8634 Literal* literal = expr->right()->AsLiteral(); |
8684 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 8635 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8817 HCompareIDAndBranch* result = | 8768 HCompareIDAndBranch* result = |
8818 new(zone()) HCompareIDAndBranch(left, right, op); | 8769 new(zone()) HCompareIDAndBranch(left, right, op); |
8819 result->set_observed_input_representation(left_rep, right_rep); | 8770 result->set_observed_input_representation(left_rep, right_rep); |
8820 result->set_position(expr->position()); | 8771 result->set_position(expr->position()); |
8821 return ast_context()->ReturnControl(result, expr->id()); | 8772 return ast_context()->ReturnControl(result, expr->id()); |
8822 } | 8773 } |
8823 } | 8774 } |
8824 } | 8775 } |
8825 | 8776 |
8826 | 8777 |
8827 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 8778 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
8828 HValue* value, | 8779 HValue* value, |
8829 NilValue nil) { | 8780 NilValue nil) { |
8830 ASSERT(!HasStackOverflow()); | 8781 ASSERT(!HasStackOverflow()); |
8831 ASSERT(current_block() != NULL); | 8782 ASSERT(current_block() != NULL); |
8832 ASSERT(current_block()->HasPredecessor()); | 8783 ASSERT(current_block()->HasPredecessor()); |
8833 EqualityKind kind = | 8784 EqualityKind kind = |
8834 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; | 8785 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; |
8835 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); | 8786 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); |
8836 instr->set_position(expr->position()); | 8787 instr->set_position(expr->position()); |
8837 return ast_context()->ReturnControl(instr, expr->id()); | 8788 return ast_context()->ReturnControl(instr, expr->id()); |
8838 } | 8789 } |
8839 | 8790 |
8840 | 8791 |
8841 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 8792 HInstruction* HGraphBuilder::BuildThisFunction() { |
8842 // If we share optimized code between different closures, the | 8793 // If we share optimized code between different closures, the |
8843 // this-function is not a constant, except inside an inlined body. | 8794 // this-function is not a constant, except inside an inlined body. |
8844 if (function_state()->outer() != NULL) { | 8795 if (function_state()->outer() != NULL) { |
8845 return new(zone()) HConstant( | 8796 return new(zone()) HConstant( |
8846 function_state()->compilation_info()->closure(), | 8797 function_state()->compilation_info()->closure(), |
8847 Representation::Tagged()); | 8798 Representation::Tagged()); |
8848 } else { | 8799 } else { |
8849 return new(zone()) HThisFunction; | 8800 return new(zone()) HThisFunction; |
8850 } | 8801 } |
8851 } | 8802 } |
8852 | 8803 |
8853 | 8804 |
8854 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 8805 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
8855 ASSERT(!HasStackOverflow()); | 8806 ASSERT(!HasStackOverflow()); |
8856 ASSERT(current_block() != NULL); | 8807 ASSERT(current_block() != NULL); |
8857 ASSERT(current_block()->HasPredecessor()); | 8808 ASSERT(current_block()->HasPredecessor()); |
8858 HInstruction* instr = BuildThisFunction(); | 8809 HInstruction* instr = BuildThisFunction(); |
8859 return ast_context()->ReturnInstruction(instr, expr->id()); | 8810 return ast_context()->ReturnInstruction(instr, expr->id()); |
8860 } | 8811 } |
8861 | 8812 |
8862 | 8813 |
8863 void HOptimizedGraphBuilder::VisitDeclarations( | 8814 void HGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) { |
8864 ZoneList<Declaration*>* declarations) { | |
8865 ASSERT(globals_.is_empty()); | 8815 ASSERT(globals_.is_empty()); |
8866 AstVisitor::VisitDeclarations(declarations); | 8816 AstVisitor::VisitDeclarations(declarations); |
8867 if (!globals_.is_empty()) { | 8817 if (!globals_.is_empty()) { |
8868 Handle<FixedArray> array = | 8818 Handle<FixedArray> array = |
8869 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 8819 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
8870 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 8820 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
8871 int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | | 8821 int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | |
8872 DeclareGlobalsNativeFlag::encode(info()->is_native()) | | 8822 DeclareGlobalsNativeFlag::encode(info()->is_native()) | |
8873 DeclareGlobalsLanguageMode::encode(info()->language_mode()); | 8823 DeclareGlobalsLanguageMode::encode(info()->language_mode()); |
8874 HInstruction* result = new(zone()) HDeclareGlobals( | 8824 HInstruction* result = new(zone()) HDeclareGlobals( |
8875 environment()->LookupContext(), array, flags); | 8825 environment()->LookupContext(), array, flags); |
8876 AddInstruction(result); | 8826 AddInstruction(result); |
8877 globals_.Clear(); | 8827 globals_.Clear(); |
8878 } | 8828 } |
8879 } | 8829 } |
8880 | 8830 |
8881 | 8831 |
8882 void HOptimizedGraphBuilder::VisitVariableDeclaration( | 8832 void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* declaration) { |
8883 VariableDeclaration* declaration) { | |
8884 VariableProxy* proxy = declaration->proxy(); | 8833 VariableProxy* proxy = declaration->proxy(); |
8885 VariableMode mode = declaration->mode(); | 8834 VariableMode mode = declaration->mode(); |
8886 Variable* variable = proxy->var(); | 8835 Variable* variable = proxy->var(); |
8887 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; | 8836 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; |
8888 switch (variable->location()) { | 8837 switch (variable->location()) { |
8889 case Variable::UNALLOCATED: | 8838 case Variable::UNALLOCATED: |
8890 globals_.Add(variable->name(), zone()); | 8839 globals_.Add(variable->name(), zone()); |
8891 globals_.Add(variable->binding_needs_init() | 8840 globals_.Add(variable->binding_needs_init() |
8892 ? isolate()->factory()->the_hole_value() | 8841 ? isolate()->factory()->the_hole_value() |
8893 : isolate()->factory()->undefined_value(), zone()); | 8842 : isolate()->factory()->undefined_value(), zone()); |
(...skipping 16 matching lines...) Expand all Loading... |
8910 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8859 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
8911 } | 8860 } |
8912 } | 8861 } |
8913 break; | 8862 break; |
8914 case Variable::LOOKUP: | 8863 case Variable::LOOKUP: |
8915 return Bailout("unsupported lookup slot in declaration"); | 8864 return Bailout("unsupported lookup slot in declaration"); |
8916 } | 8865 } |
8917 } | 8866 } |
8918 | 8867 |
8919 | 8868 |
8920 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 8869 void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* declaration) { |
8921 FunctionDeclaration* declaration) { | |
8922 VariableProxy* proxy = declaration->proxy(); | 8870 VariableProxy* proxy = declaration->proxy(); |
8923 Variable* variable = proxy->var(); | 8871 Variable* variable = proxy->var(); |
8924 switch (variable->location()) { | 8872 switch (variable->location()) { |
8925 case Variable::UNALLOCATED: { | 8873 case Variable::UNALLOCATED: { |
8926 globals_.Add(variable->name(), zone()); | 8874 globals_.Add(variable->name(), zone()); |
8927 Handle<SharedFunctionInfo> function = | 8875 Handle<SharedFunctionInfo> function = |
8928 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); | 8876 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); |
8929 // Check for stack-overflow exception. | 8877 // Check for stack-overflow exception. |
8930 if (function.is_null()) return SetStackOverflow(); | 8878 if (function.is_null()) return SetStackOverflow(); |
8931 globals_.Add(function, zone()); | 8879 globals_.Add(function, zone()); |
(...skipping 17 matching lines...) Expand all Loading... |
8949 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8897 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
8950 } | 8898 } |
8951 break; | 8899 break; |
8952 } | 8900 } |
8953 case Variable::LOOKUP: | 8901 case Variable::LOOKUP: |
8954 return Bailout("unsupported lookup slot in declaration"); | 8902 return Bailout("unsupported lookup slot in declaration"); |
8955 } | 8903 } |
8956 } | 8904 } |
8957 | 8905 |
8958 | 8906 |
8959 void HOptimizedGraphBuilder::VisitModuleDeclaration( | 8907 void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
8960 ModuleDeclaration* declaration) { | |
8961 UNREACHABLE(); | 8908 UNREACHABLE(); |
8962 } | 8909 } |
8963 | 8910 |
8964 | 8911 |
8965 void HOptimizedGraphBuilder::VisitImportDeclaration( | 8912 void HGraphBuilder::VisitImportDeclaration(ImportDeclaration* declaration) { |
8966 ImportDeclaration* declaration) { | |
8967 UNREACHABLE(); | 8913 UNREACHABLE(); |
8968 } | 8914 } |
8969 | 8915 |
8970 | 8916 |
8971 void HOptimizedGraphBuilder::VisitExportDeclaration( | 8917 void HGraphBuilder::VisitExportDeclaration(ExportDeclaration* declaration) { |
8972 ExportDeclaration* declaration) { | |
8973 UNREACHABLE(); | 8918 UNREACHABLE(); |
8974 } | 8919 } |
8975 | 8920 |
8976 | 8921 |
8977 void HOptimizedGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) { | 8922 void HGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) { |
8978 UNREACHABLE(); | 8923 UNREACHABLE(); |
8979 } | 8924 } |
8980 | 8925 |
8981 | 8926 |
8982 void HOptimizedGraphBuilder::VisitModuleVariable(ModuleVariable* module) { | 8927 void HGraphBuilder::VisitModuleVariable(ModuleVariable* module) { |
8983 UNREACHABLE(); | 8928 UNREACHABLE(); |
8984 } | 8929 } |
8985 | 8930 |
8986 | 8931 |
8987 void HOptimizedGraphBuilder::VisitModulePath(ModulePath* module) { | 8932 void HGraphBuilder::VisitModulePath(ModulePath* module) { |
8988 UNREACHABLE(); | 8933 UNREACHABLE(); |
8989 } | 8934 } |
8990 | 8935 |
8991 | 8936 |
8992 void HOptimizedGraphBuilder::VisitModuleUrl(ModuleUrl* module) { | 8937 void HGraphBuilder::VisitModuleUrl(ModuleUrl* module) { |
8993 UNREACHABLE(); | 8938 UNREACHABLE(); |
8994 } | 8939 } |
8995 | 8940 |
8996 | 8941 |
8997 void HOptimizedGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { | 8942 void HGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { |
8998 UNREACHABLE(); | 8943 UNREACHABLE(); |
8999 } | 8944 } |
9000 | 8945 |
9001 | 8946 |
9002 // Generators for inline runtime functions. | 8947 // Generators for inline runtime functions. |
9003 // Support for types. | 8948 // Support for types. |
9004 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) { | 8949 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { |
9005 ASSERT(call->arguments()->length() == 1); | 8950 ASSERT(call->arguments()->length() == 1); |
9006 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8951 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9007 HValue* value = Pop(); | 8952 HValue* value = Pop(); |
9008 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); | 8953 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); |
9009 return ast_context()->ReturnControl(result, call->id()); | 8954 return ast_context()->ReturnControl(result, call->id()); |
9010 } | 8955 } |
9011 | 8956 |
9012 | 8957 |
9013 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { | 8958 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { |
9014 ASSERT(call->arguments()->length() == 1); | 8959 ASSERT(call->arguments()->length() == 1); |
9015 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8960 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9016 HValue* value = Pop(); | 8961 HValue* value = Pop(); |
9017 HHasInstanceTypeAndBranch* result = | 8962 HHasInstanceTypeAndBranch* result = |
9018 new(zone()) HHasInstanceTypeAndBranch(value, | 8963 new(zone()) HHasInstanceTypeAndBranch(value, |
9019 FIRST_SPEC_OBJECT_TYPE, | 8964 FIRST_SPEC_OBJECT_TYPE, |
9020 LAST_SPEC_OBJECT_TYPE); | 8965 LAST_SPEC_OBJECT_TYPE); |
9021 return ast_context()->ReturnControl(result, call->id()); | 8966 return ast_context()->ReturnControl(result, call->id()); |
9022 } | 8967 } |
9023 | 8968 |
9024 | 8969 |
9025 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) { | 8970 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { |
9026 ASSERT(call->arguments()->length() == 1); | 8971 ASSERT(call->arguments()->length() == 1); |
9027 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8972 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9028 HValue* value = Pop(); | 8973 HValue* value = Pop(); |
9029 HHasInstanceTypeAndBranch* result = | 8974 HHasInstanceTypeAndBranch* result = |
9030 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); | 8975 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_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::GenerateHasCachedArrayIndex(CallRuntime* call) { | 8980 void HGraphBuilder::GenerateHasCachedArrayIndex(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 HHasCachedArrayIndexAndBranch* result = | 8984 HHasCachedArrayIndexAndBranch* result = |
9040 new(zone()) HHasCachedArrayIndexAndBranch(value); | 8985 new(zone()) HHasCachedArrayIndexAndBranch(value); |
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::GenerateIsArray(CallRuntime* call) { | 8990 void HGraphBuilder::GenerateIsArray(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 HHasInstanceTypeAndBranch* result = | 8994 HHasInstanceTypeAndBranch* result = |
9050 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); | 8995 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); |
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::GenerateIsRegExp(CallRuntime* call) { | 9000 void HGraphBuilder::GenerateIsRegExp(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_REGEXP_TYPE); | 9005 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_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::GenerateIsObject(CallRuntime* call) { | 9010 void HGraphBuilder::GenerateIsObject(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 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); | 9014 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); |
9070 return ast_context()->ReturnControl(result, call->id()); | 9015 return ast_context()->ReturnControl(result, call->id()); |
9071 } | 9016 } |
9072 | 9017 |
9073 | 9018 |
9074 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { | 9019 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
9075 return Bailout("inlined runtime function: IsNonNegativeSmi"); | 9020 return Bailout("inlined runtime function: IsNonNegativeSmi"); |
9076 } | 9021 } |
9077 | 9022 |
9078 | 9023 |
9079 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { | 9024 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
9080 ASSERT(call->arguments()->length() == 1); | 9025 ASSERT(call->arguments()->length() == 1); |
9081 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9026 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9082 HValue* value = Pop(); | 9027 HValue* value = Pop(); |
9083 HIsUndetectableAndBranch* result = | 9028 HIsUndetectableAndBranch* result = |
9084 new(zone()) HIsUndetectableAndBranch(value); | 9029 new(zone()) HIsUndetectableAndBranch(value); |
9085 return ast_context()->ReturnControl(result, call->id()); | 9030 return ast_context()->ReturnControl(result, call->id()); |
9086 } | 9031 } |
9087 | 9032 |
9088 | 9033 |
9089 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 9034 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
9090 CallRuntime* call) { | 9035 CallRuntime* call) { |
9091 return Bailout( | 9036 return Bailout( |
9092 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | 9037 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
9093 } | 9038 } |
9094 | 9039 |
9095 | 9040 |
9096 // Support for construct call checks. | 9041 // Support for construct call checks. |
9097 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { | 9042 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { |
9098 ASSERT(call->arguments()->length() == 0); | 9043 ASSERT(call->arguments()->length() == 0); |
9099 if (function_state()->outer() != NULL) { | 9044 if (function_state()->outer() != NULL) { |
9100 // We are generating graph for inlined function. | 9045 // We are generating graph for inlined function. |
9101 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN | 9046 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN |
9102 ? graph()->GetConstantTrue() | 9047 ? graph()->GetConstantTrue() |
9103 : graph()->GetConstantFalse(); | 9048 : graph()->GetConstantFalse(); |
9104 return ast_context()->ReturnValue(value); | 9049 return ast_context()->ReturnValue(value); |
9105 } else { | 9050 } else { |
9106 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, | 9051 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, |
9107 call->id()); | 9052 call->id()); |
9108 } | 9053 } |
9109 } | 9054 } |
9110 | 9055 |
9111 | 9056 |
9112 // Support for arguments.length and arguments[?]. | 9057 // Support for arguments.length and arguments[?]. |
9113 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 9058 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
9114 // Our implementation of arguments (based on this stack frame or an | 9059 // Our implementation of arguments (based on this stack frame or an |
9115 // adapter below it) does not work for inlined functions. This runtime | 9060 // adapter below it) does not work for inlined functions. This runtime |
9116 // function is blacklisted by AstNode::IsInlineable. | 9061 // function is blacklisted by AstNode::IsInlineable. |
9117 ASSERT(function_state()->outer() == NULL); | 9062 ASSERT(function_state()->outer() == NULL); |
9118 ASSERT(call->arguments()->length() == 0); | 9063 ASSERT(call->arguments()->length() == 0); |
9119 HInstruction* elements = AddInstruction( | 9064 HInstruction* elements = AddInstruction( |
9120 new(zone()) HArgumentsElements(false)); | 9065 new(zone()) HArgumentsElements(false)); |
9121 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); | 9066 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); |
9122 return ast_context()->ReturnInstruction(result, call->id()); | 9067 return ast_context()->ReturnInstruction(result, call->id()); |
9123 } | 9068 } |
9124 | 9069 |
9125 | 9070 |
9126 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { | 9071 void HGraphBuilder::GenerateArguments(CallRuntime* call) { |
9127 // Our implementation of arguments (based on this stack frame or an | 9072 // Our implementation of arguments (based on this stack frame or an |
9128 // adapter below it) does not work for inlined functions. This runtime | 9073 // adapter below it) does not work for inlined functions. This runtime |
9129 // function is blacklisted by AstNode::IsInlineable. | 9074 // function is blacklisted by AstNode::IsInlineable. |
9130 ASSERT(function_state()->outer() == NULL); | 9075 ASSERT(function_state()->outer() == NULL); |
9131 ASSERT(call->arguments()->length() == 1); | 9076 ASSERT(call->arguments()->length() == 1); |
9132 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9077 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9133 HValue* index = Pop(); | 9078 HValue* index = Pop(); |
9134 HInstruction* elements = AddInstruction( | 9079 HInstruction* elements = AddInstruction( |
9135 new(zone()) HArgumentsElements(false)); | 9080 new(zone()) HArgumentsElements(false)); |
9136 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); | 9081 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
9137 HInstruction* checked_index = | 9082 HInstruction* checked_index = |
9138 AddInstruction(new(zone()) HBoundsCheck(index, length)); | 9083 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
9139 HAccessArgumentsAt* result = | 9084 HAccessArgumentsAt* result = |
9140 new(zone()) HAccessArgumentsAt(elements, length, checked_index); | 9085 new(zone()) HAccessArgumentsAt(elements, length, checked_index); |
9141 return ast_context()->ReturnInstruction(result, call->id()); | 9086 return ast_context()->ReturnInstruction(result, call->id()); |
9142 } | 9087 } |
9143 | 9088 |
9144 | 9089 |
9145 // Support for accessing the class and value fields of an object. | 9090 // Support for accessing the class and value fields of an object. |
9146 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { | 9091 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { |
9147 // The special form detected by IsClassOfTest is detected before we get here | 9092 // The special form detected by IsClassOfTest is detected before we get here |
9148 // and does not cause a bailout. | 9093 // and does not cause a bailout. |
9149 return Bailout("inlined runtime function: ClassOf"); | 9094 return Bailout("inlined runtime function: ClassOf"); |
9150 } | 9095 } |
9151 | 9096 |
9152 | 9097 |
9153 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { | 9098 void HGraphBuilder::GenerateValueOf(CallRuntime* call) { |
9154 ASSERT(call->arguments()->length() == 1); | 9099 ASSERT(call->arguments()->length() == 1); |
9155 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9100 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9156 HValue* value = Pop(); | 9101 HValue* value = Pop(); |
9157 HValueOf* result = new(zone()) HValueOf(value); | 9102 HValueOf* result = new(zone()) HValueOf(value); |
9158 return ast_context()->ReturnInstruction(result, call->id()); | 9103 return ast_context()->ReturnInstruction(result, call->id()); |
9159 } | 9104 } |
9160 | 9105 |
9161 | 9106 |
9162 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) { | 9107 void HGraphBuilder::GenerateDateField(CallRuntime* call) { |
9163 ASSERT(call->arguments()->length() == 2); | 9108 ASSERT(call->arguments()->length() == 2); |
9164 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); | 9109 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); |
9165 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle())); | 9110 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle())); |
9166 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9111 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9167 HValue* date = Pop(); | 9112 HValue* date = Pop(); |
9168 HDateField* result = new(zone()) HDateField(date, index); | 9113 HDateField* result = new(zone()) HDateField(date, index); |
9169 return ast_context()->ReturnInstruction(result, call->id()); | 9114 return ast_context()->ReturnInstruction(result, call->id()); |
9170 } | 9115 } |
9171 | 9116 |
9172 | 9117 |
9173 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar( | 9118 void HGraphBuilder::GenerateOneByteSeqStringSetChar( |
9174 CallRuntime* call) { | 9119 CallRuntime* call) { |
9175 ASSERT(call->arguments()->length() == 3); | 9120 ASSERT(call->arguments()->length() == 3); |
9176 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9121 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9177 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9122 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9178 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); | 9123 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); |
9179 HValue* value = Pop(); | 9124 HValue* value = Pop(); |
9180 HValue* index = Pop(); | 9125 HValue* index = Pop(); |
9181 HValue* string = Pop(); | 9126 HValue* string = Pop(); |
9182 HSeqStringSetChar* result = new(zone()) HSeqStringSetChar( | 9127 HSeqStringSetChar* result = new(zone()) HSeqStringSetChar( |
9183 String::ONE_BYTE_ENCODING, string, index, value); | 9128 String::ONE_BYTE_ENCODING, string, index, value); |
9184 return ast_context()->ReturnInstruction(result, call->id()); | 9129 return ast_context()->ReturnInstruction(result, call->id()); |
9185 } | 9130 } |
9186 | 9131 |
9187 | 9132 |
9188 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar( | 9133 void HGraphBuilder::GenerateTwoByteSeqStringSetChar( |
9189 CallRuntime* call) { | 9134 CallRuntime* call) { |
9190 ASSERT(call->arguments()->length() == 3); | 9135 ASSERT(call->arguments()->length() == 3); |
9191 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9136 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9192 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9137 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9193 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); | 9138 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); |
9194 HValue* value = Pop(); | 9139 HValue* value = Pop(); |
9195 HValue* index = Pop(); | 9140 HValue* index = Pop(); |
9196 HValue* string = Pop(); | 9141 HValue* string = Pop(); |
9197 HValue* context = environment()->LookupContext(); | 9142 HValue* context = environment()->LookupContext(); |
9198 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); | 9143 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); |
9199 AddInstruction(char_code); | 9144 AddInstruction(char_code); |
9200 HSeqStringSetChar* result = new(zone()) HSeqStringSetChar( | 9145 HSeqStringSetChar* result = new(zone()) HSeqStringSetChar( |
9201 String::TWO_BYTE_ENCODING, string, index, value); | 9146 String::TWO_BYTE_ENCODING, string, index, value); |
9202 return ast_context()->ReturnInstruction(result, call->id()); | 9147 return ast_context()->ReturnInstruction(result, call->id()); |
9203 } | 9148 } |
9204 | 9149 |
9205 | 9150 |
9206 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { | 9151 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { |
9207 ASSERT(call->arguments()->length() == 2); | 9152 ASSERT(call->arguments()->length() == 2); |
9208 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9153 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9209 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9154 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9210 HValue* value = Pop(); | 9155 HValue* value = Pop(); |
9211 HValue* object = Pop(); | 9156 HValue* object = Pop(); |
9212 // Check if object is a not a smi. | 9157 // Check if object is a not a smi. |
9213 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object); | 9158 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object); |
9214 HBasicBlock* if_smi = graph()->CreateBasicBlock(); | 9159 HBasicBlock* if_smi = graph()->CreateBasicBlock(); |
9215 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); | 9160 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); |
9216 HBasicBlock* join = graph()->CreateBasicBlock(); | 9161 HBasicBlock* join = graph()->CreateBasicBlock(); |
(...skipping 22 matching lines...) Expand all Loading... |
9239 true, // in-object store. | 9184 true, // in-object store. |
9240 JSValue::kValueOffset)); | 9185 JSValue::kValueOffset)); |
9241 if_js_value->Goto(join); | 9186 if_js_value->Goto(join); |
9242 join->SetJoinId(call->id()); | 9187 join->SetJoinId(call->id()); |
9243 set_current_block(join); | 9188 set_current_block(join); |
9244 return ast_context()->ReturnValue(value); | 9189 return ast_context()->ReturnValue(value); |
9245 } | 9190 } |
9246 | 9191 |
9247 | 9192 |
9248 // Fast support for charCodeAt(n). | 9193 // Fast support for charCodeAt(n). |
9249 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 9194 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
9250 ASSERT(call->arguments()->length() == 2); | 9195 ASSERT(call->arguments()->length() == 2); |
9251 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9196 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9252 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9197 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9253 HValue* index = Pop(); | 9198 HValue* index = Pop(); |
9254 HValue* string = Pop(); | 9199 HValue* string = Pop(); |
9255 HValue* context = environment()->LookupContext(); | 9200 HValue* context = environment()->LookupContext(); |
9256 HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index); | 9201 HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index); |
9257 return ast_context()->ReturnInstruction(result, call->id()); | 9202 return ast_context()->ReturnInstruction(result, call->id()); |
9258 } | 9203 } |
9259 | 9204 |
9260 | 9205 |
9261 // Fast support for string.charAt(n) and string[n]. | 9206 // Fast support for string.charAt(n) and string[n]. |
9262 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { | 9207 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
9263 ASSERT(call->arguments()->length() == 1); | 9208 ASSERT(call->arguments()->length() == 1); |
9264 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9209 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9265 HValue* char_code = Pop(); | 9210 HValue* char_code = Pop(); |
9266 HValue* context = environment()->LookupContext(); | 9211 HValue* context = environment()->LookupContext(); |
9267 HStringCharFromCode* result = | 9212 HStringCharFromCode* result = |
9268 new(zone()) HStringCharFromCode(context, char_code); | 9213 new(zone()) HStringCharFromCode(context, char_code); |
9269 return ast_context()->ReturnInstruction(result, call->id()); | 9214 return ast_context()->ReturnInstruction(result, call->id()); |
9270 } | 9215 } |
9271 | 9216 |
9272 | 9217 |
9273 // Fast support for string.charAt(n) and string[n]. | 9218 // Fast support for string.charAt(n) and string[n]. |
9274 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { | 9219 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
9275 ASSERT(call->arguments()->length() == 2); | 9220 ASSERT(call->arguments()->length() == 2); |
9276 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9221 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9277 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9222 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9278 HValue* index = Pop(); | 9223 HValue* index = Pop(); |
9279 HValue* string = Pop(); | 9224 HValue* string = Pop(); |
9280 HValue* context = environment()->LookupContext(); | 9225 HValue* context = environment()->LookupContext(); |
9281 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); | 9226 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); |
9282 AddInstruction(char_code); | 9227 AddInstruction(char_code); |
9283 HStringCharFromCode* result = | 9228 HStringCharFromCode* result = |
9284 new(zone()) HStringCharFromCode(context, char_code); | 9229 new(zone()) HStringCharFromCode(context, char_code); |
9285 return ast_context()->ReturnInstruction(result, call->id()); | 9230 return ast_context()->ReturnInstruction(result, call->id()); |
9286 } | 9231 } |
9287 | 9232 |
9288 | 9233 |
9289 // Fast support for object equality testing. | 9234 // Fast support for object equality testing. |
9290 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 9235 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
9291 ASSERT(call->arguments()->length() == 2); | 9236 ASSERT(call->arguments()->length() == 2); |
9292 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9237 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9293 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9238 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9294 HValue* right = Pop(); | 9239 HValue* right = Pop(); |
9295 HValue* left = Pop(); | 9240 HValue* left = Pop(); |
9296 HCompareObjectEqAndBranch* result = | 9241 HCompareObjectEqAndBranch* result = |
9297 new(zone()) HCompareObjectEqAndBranch(left, right); | 9242 new(zone()) HCompareObjectEqAndBranch(left, right); |
9298 return ast_context()->ReturnControl(result, call->id()); | 9243 return ast_context()->ReturnControl(result, call->id()); |
9299 } | 9244 } |
9300 | 9245 |
9301 | 9246 |
9302 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { | 9247 void HGraphBuilder::GenerateLog(CallRuntime* call) { |
9303 // %_Log is ignored in optimized code. | 9248 // %_Log is ignored in optimized code. |
9304 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 9249 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
9305 } | 9250 } |
9306 | 9251 |
9307 | 9252 |
9308 // Fast support for Math.random(). | 9253 // Fast support for Math.random(). |
9309 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | 9254 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
9310 HValue* context = environment()->LookupContext(); | 9255 HValue* context = environment()->LookupContext(); |
9311 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 9256 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
9312 AddInstruction(global_object); | 9257 AddInstruction(global_object); |
9313 HRandom* result = new(zone()) HRandom(global_object); | 9258 HRandom* result = new(zone()) HRandom(global_object); |
9314 return ast_context()->ReturnInstruction(result, call->id()); | 9259 return ast_context()->ReturnInstruction(result, call->id()); |
9315 } | 9260 } |
9316 | 9261 |
9317 | 9262 |
9318 // Fast support for StringAdd. | 9263 // Fast support for StringAdd. |
9319 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 9264 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
9320 ASSERT_EQ(2, call->arguments()->length()); | 9265 ASSERT_EQ(2, call->arguments()->length()); |
9321 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9266 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9322 HValue* context = environment()->LookupContext(); | 9267 HValue* context = environment()->LookupContext(); |
9323 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); | 9268 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 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 // Fast support for SubString. | 9274 // Fast support for SubString. |
9330 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 9275 void HGraphBuilder::GenerateSubString(CallRuntime* call) { |
9331 ASSERT_EQ(3, call->arguments()->length()); | 9276 ASSERT_EQ(3, 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::SubString, 3); | 9279 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
9335 Drop(3); | 9280 Drop(3); |
9336 return ast_context()->ReturnInstruction(result, call->id()); | 9281 return ast_context()->ReturnInstruction(result, call->id()); |
9337 } | 9282 } |
9338 | 9283 |
9339 | 9284 |
9340 // Fast support for StringCompare. | 9285 // Fast support for StringCompare. |
9341 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 9286 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
9342 ASSERT_EQ(2, call->arguments()->length()); | 9287 ASSERT_EQ(2, 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::StringCompare, 2); | 9291 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); |
9347 Drop(2); | 9292 Drop(2); |
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 direct calls from JavaScript to native RegExp code. | 9297 // Support for direct calls from JavaScript to native RegExp code. |
9353 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 9298 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
9354 ASSERT_EQ(4, call->arguments()->length()); | 9299 ASSERT_EQ(4, call->arguments()->length()); |
9355 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9300 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9356 HValue* context = environment()->LookupContext(); | 9301 HValue* context = environment()->LookupContext(); |
9357 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); | 9302 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
9358 Drop(4); | 9303 Drop(4); |
9359 return ast_context()->ReturnInstruction(result, call->id()); | 9304 return ast_context()->ReturnInstruction(result, call->id()); |
9360 } | 9305 } |
9361 | 9306 |
9362 | 9307 |
9363 // Construct a RegExp exec result with two in-object properties. | 9308 // Construct a RegExp exec result with two in-object properties. |
9364 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 9309 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
9365 ASSERT_EQ(3, call->arguments()->length()); | 9310 ASSERT_EQ(3, call->arguments()->length()); |
9366 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9311 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9367 HValue* context = environment()->LookupContext(); | 9312 HValue* context = environment()->LookupContext(); |
9368 HCallStub* result = | 9313 HCallStub* result = |
9369 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | 9314 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
9370 Drop(3); | 9315 Drop(3); |
9371 return ast_context()->ReturnInstruction(result, call->id()); | 9316 return ast_context()->ReturnInstruction(result, call->id()); |
9372 } | 9317 } |
9373 | 9318 |
9374 | 9319 |
9375 // Support for fast native caches. | 9320 // Support for fast native caches. |
9376 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9321 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
9377 return Bailout("inlined runtime function: GetFromCache"); | 9322 return Bailout("inlined runtime function: GetFromCache"); |
9378 } | 9323 } |
9379 | 9324 |
9380 | 9325 |
9381 // Fast support for number to string. | 9326 // Fast support for number to string. |
9382 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 9327 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
9383 ASSERT_EQ(1, call->arguments()->length()); | 9328 ASSERT_EQ(1, call->arguments()->length()); |
9384 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9329 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9385 HValue* context = environment()->LookupContext(); | 9330 HValue* context = environment()->LookupContext(); |
9386 HCallStub* result = | 9331 HCallStub* result = |
9387 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 9332 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
9388 Drop(1); | 9333 Drop(1); |
9389 return ast_context()->ReturnInstruction(result, call->id()); | 9334 return ast_context()->ReturnInstruction(result, call->id()); |
9390 } | 9335 } |
9391 | 9336 |
9392 | 9337 |
9393 // Fast call for custom callbacks. | 9338 // Fast call for custom callbacks. |
9394 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 9339 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
9395 // 1 ~ The function to call is not itself an argument to the call. | 9340 // 1 ~ The function to call is not itself an argument to the call. |
9396 int arg_count = call->arguments()->length() - 1; | 9341 int arg_count = call->arguments()->length() - 1; |
9397 ASSERT(arg_count >= 1); // There's always at least a receiver. | 9342 ASSERT(arg_count >= 1); // There's always at least a receiver. |
9398 | 9343 |
9399 for (int i = 0; i < arg_count; ++i) { | 9344 for (int i = 0; i < arg_count; ++i) { |
9400 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); | 9345 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); |
9401 } | 9346 } |
9402 CHECK_ALIVE(VisitForValue(call->arguments()->last())); | 9347 CHECK_ALIVE(VisitForValue(call->arguments()->last())); |
9403 | 9348 |
9404 HValue* function = Pop(); | 9349 HValue* function = Pop(); |
(...skipping 23 matching lines...) Expand all Loading... |
9428 Push(call_result); | 9373 Push(call_result); |
9429 if_nonfunction->Goto(join); | 9374 if_nonfunction->Goto(join); |
9430 | 9375 |
9431 set_current_block(join); | 9376 set_current_block(join); |
9432 join->SetJoinId(call->id()); | 9377 join->SetJoinId(call->id()); |
9433 return ast_context()->ReturnValue(Pop()); | 9378 return ast_context()->ReturnValue(Pop()); |
9434 } | 9379 } |
9435 | 9380 |
9436 | 9381 |
9437 // Fast call to math functions. | 9382 // Fast call to math functions. |
9438 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { | 9383 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { |
9439 ASSERT_EQ(2, call->arguments()->length()); | 9384 ASSERT_EQ(2, call->arguments()->length()); |
9440 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9385 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9441 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9386 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9442 HValue* right = Pop(); | 9387 HValue* right = Pop(); |
9443 HValue* left = Pop(); | 9388 HValue* left = Pop(); |
9444 HPower* result = new(zone()) HPower(left, right); | 9389 HPower* result = new(zone()) HPower(left, right); |
9445 return ast_context()->ReturnInstruction(result, call->id()); | 9390 return ast_context()->ReturnInstruction(result, call->id()); |
9446 } | 9391 } |
9447 | 9392 |
9448 | 9393 |
9449 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { | 9394 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { |
9450 ASSERT_EQ(1, call->arguments()->length()); | 9395 ASSERT_EQ(1, call->arguments()->length()); |
9451 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9396 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9452 HValue* context = environment()->LookupContext(); | 9397 HValue* context = environment()->LookupContext(); |
9453 HCallStub* result = | 9398 HCallStub* result = |
9454 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9399 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9455 result->set_transcendental_type(TranscendentalCache::SIN); | 9400 result->set_transcendental_type(TranscendentalCache::SIN); |
9456 Drop(1); | 9401 Drop(1); |
9457 return ast_context()->ReturnInstruction(result, call->id()); | 9402 return ast_context()->ReturnInstruction(result, call->id()); |
9458 } | 9403 } |
9459 | 9404 |
9460 | 9405 |
9461 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) { | 9406 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { |
9462 ASSERT_EQ(1, call->arguments()->length()); | 9407 ASSERT_EQ(1, call->arguments()->length()); |
9463 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9408 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9464 HValue* context = environment()->LookupContext(); | 9409 HValue* context = environment()->LookupContext(); |
9465 HCallStub* result = | 9410 HCallStub* result = |
9466 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9411 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9467 result->set_transcendental_type(TranscendentalCache::COS); | 9412 result->set_transcendental_type(TranscendentalCache::COS); |
9468 Drop(1); | 9413 Drop(1); |
9469 return ast_context()->ReturnInstruction(result, call->id()); | 9414 return ast_context()->ReturnInstruction(result, call->id()); |
9470 } | 9415 } |
9471 | 9416 |
9472 | 9417 |
9473 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) { | 9418 void HGraphBuilder::GenerateMathTan(CallRuntime* call) { |
9474 ASSERT_EQ(1, call->arguments()->length()); | 9419 ASSERT_EQ(1, call->arguments()->length()); |
9475 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9420 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9476 HValue* context = environment()->LookupContext(); | 9421 HValue* context = environment()->LookupContext(); |
9477 HCallStub* result = | 9422 HCallStub* result = |
9478 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9423 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9479 result->set_transcendental_type(TranscendentalCache::TAN); | 9424 result->set_transcendental_type(TranscendentalCache::TAN); |
9480 Drop(1); | 9425 Drop(1); |
9481 return ast_context()->ReturnInstruction(result, call->id()); | 9426 return ast_context()->ReturnInstruction(result, call->id()); |
9482 } | 9427 } |
9483 | 9428 |
9484 | 9429 |
9485 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { | 9430 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { |
9486 ASSERT_EQ(1, call->arguments()->length()); | 9431 ASSERT_EQ(1, call->arguments()->length()); |
9487 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9432 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9488 HValue* context = environment()->LookupContext(); | 9433 HValue* context = environment()->LookupContext(); |
9489 HCallStub* result = | 9434 HCallStub* result = |
9490 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9435 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9491 result->set_transcendental_type(TranscendentalCache::LOG); | 9436 result->set_transcendental_type(TranscendentalCache::LOG); |
9492 Drop(1); | 9437 Drop(1); |
9493 return ast_context()->ReturnInstruction(result, call->id()); | 9438 return ast_context()->ReturnInstruction(result, call->id()); |
9494 } | 9439 } |
9495 | 9440 |
9496 | 9441 |
9497 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 9442 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
9498 return Bailout("inlined runtime function: MathSqrt"); | 9443 return Bailout("inlined runtime function: MathSqrt"); |
9499 } | 9444 } |
9500 | 9445 |
9501 | 9446 |
9502 // Check whether two RegExps are equivalent | 9447 // Check whether two RegExps are equivalent |
9503 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 9448 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
9504 return Bailout("inlined runtime function: IsRegExpEquivalent"); | 9449 return Bailout("inlined runtime function: IsRegExpEquivalent"); |
9505 } | 9450 } |
9506 | 9451 |
9507 | 9452 |
9508 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { | 9453 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
9509 ASSERT(call->arguments()->length() == 1); | 9454 ASSERT(call->arguments()->length() == 1); |
9510 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9455 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9511 HValue* value = Pop(); | 9456 HValue* value = Pop(); |
9512 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); | 9457 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); |
9513 return ast_context()->ReturnInstruction(result, call->id()); | 9458 return ast_context()->ReturnInstruction(result, call->id()); |
9514 } | 9459 } |
9515 | 9460 |
9516 | 9461 |
9517 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { | 9462 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { |
9518 return Bailout("inlined runtime function: FastAsciiArrayJoin"); | 9463 return Bailout("inlined runtime function: FastAsciiArrayJoin"); |
9519 } | 9464 } |
9520 | 9465 |
9521 | 9466 |
9522 #undef CHECK_BAILOUT | 9467 #undef CHECK_BAILOUT |
9523 #undef CHECK_ALIVE | 9468 #undef CHECK_ALIVE |
9524 | 9469 |
9525 | 9470 |
9526 HEnvironment::HEnvironment(HEnvironment* outer, | 9471 HEnvironment::HEnvironment(HEnvironment* outer, |
9527 Scope* scope, | 9472 Scope* scope, |
9528 Handle<JSFunction> closure, | 9473 Handle<JSFunction> closure, |
9529 Zone* zone) | 9474 Zone* zone) |
9530 : closure_(closure), | 9475 : closure_(closure), |
9531 values_(0, zone), | 9476 values_(0, zone), |
9532 assigned_variables_(4, zone), | 9477 assigned_variables_(4, zone), |
9533 frame_type_(JS_FUNCTION), | 9478 frame_type_(JS_FUNCTION), |
9534 parameter_count_(0), | 9479 parameter_count_(0), |
9535 specials_count_(1), | 9480 specials_count_(1), |
9536 local_count_(0), | 9481 local_count_(0), |
9537 outer_(outer), | 9482 outer_(outer), |
9538 entry_(NULL), | 9483 entry_(NULL), |
9539 pop_count_(0), | 9484 pop_count_(0), |
9540 push_count_(0), | 9485 push_count_(0), |
9541 ast_id_(BailoutId::None()), | 9486 ast_id_(BailoutId::None()), |
9542 zone_(zone) { | 9487 zone_(zone) { |
9543 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); | 9488 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); |
9544 } | 9489 } |
9545 | 9490 |
9546 | 9491 |
9547 HEnvironment::HEnvironment(Zone* zone) | |
9548 : values_(0, zone), | |
9549 assigned_variables_(0, zone), | |
9550 frame_type_(STUB), | |
9551 parameter_count_(0), | |
9552 specials_count_(0), | |
9553 local_count_(0), | |
9554 outer_(NULL), | |
9555 entry_(NULL), | |
9556 pop_count_(0), | |
9557 push_count_(0), | |
9558 ast_id_(BailoutId::None()), | |
9559 zone_(zone) { | |
9560 Initialize(0, 0, 0); | |
9561 } | |
9562 | |
9563 | |
9564 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone) | 9492 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone) |
9565 : values_(0, zone), | 9493 : values_(0, zone), |
9566 assigned_variables_(0, zone), | 9494 assigned_variables_(0, zone), |
9567 frame_type_(JS_FUNCTION), | 9495 frame_type_(JS_FUNCTION), |
9568 parameter_count_(0), | 9496 parameter_count_(0), |
9569 specials_count_(1), | 9497 specials_count_(1), |
9570 local_count_(0), | 9498 local_count_(0), |
9571 outer_(NULL), | 9499 outer_(NULL), |
9572 entry_(NULL), | 9500 entry_(NULL), |
9573 pop_count_(0), | 9501 pop_count_(0), |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9821 | 9749 |
9822 | 9750 |
9823 void HEnvironment::PrintToStd() { | 9751 void HEnvironment::PrintToStd() { |
9824 HeapStringAllocator string_allocator; | 9752 HeapStringAllocator string_allocator; |
9825 StringStream trace(&string_allocator); | 9753 StringStream trace(&string_allocator); |
9826 PrintTo(&trace); | 9754 PrintTo(&trace); |
9827 PrintF("%s", *trace.ToCString()); | 9755 PrintF("%s", *trace.ToCString()); |
9828 } | 9756 } |
9829 | 9757 |
9830 | 9758 |
9831 void HTracer::TraceCompilation(CompilationInfo* info) { | 9759 void HTracer::TraceCompilation(FunctionLiteral* function) { |
9832 Tag tag(this, "compilation"); | 9760 Tag tag(this, "compilation"); |
9833 if (info->IsOptimizing()) { | 9761 Handle<String> name = function->debug_name(); |
9834 Handle<String> name = info->function()->debug_name(); | 9762 PrintStringProperty("name", *name->ToCString()); |
9835 PrintStringProperty("name", *name->ToCString()); | 9763 PrintStringProperty("method", *name->ToCString()); |
9836 PrintStringProperty("method", *name->ToCString()); | |
9837 } else { | |
9838 CodeStub::Major major_key = info->code_stub()->MajorKey(); | |
9839 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); | |
9840 PrintStringProperty("method", "stub"); | |
9841 } | |
9842 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); | 9764 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); |
9843 } | 9765 } |
9844 | 9766 |
9845 | 9767 |
9846 void HTracer::TraceLithium(const char* name, LChunk* chunk) { | 9768 void HTracer::TraceLithium(const char* name, LChunk* chunk) { |
9847 Trace(name, chunk->graph(), chunk); | 9769 Trace(name, chunk->graph(), chunk); |
9848 } | 9770 } |
9849 | 9771 |
9850 | 9772 |
9851 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { | 9773 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10160 } | 10082 } |
10161 } | 10083 } |
10162 | 10084 |
10163 #ifdef DEBUG | 10085 #ifdef DEBUG |
10164 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10086 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
10165 if (allocator_ != NULL) allocator_->Verify(); | 10087 if (allocator_ != NULL) allocator_->Verify(); |
10166 #endif | 10088 #endif |
10167 } | 10089 } |
10168 | 10090 |
10169 } } // namespace v8::internal | 10091 } } // namespace v8::internal |
OLD | NEW |