OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 | 132 |
133 void HBasicBlock::RemovePhi(HPhi* phi) { | 133 void HBasicBlock::RemovePhi(HPhi* phi) { |
134 ASSERT(phi->block() == this); | 134 ASSERT(phi->block() == this); |
135 ASSERT(phis_.Contains(phi)); | 135 ASSERT(phis_.Contains(phi)); |
136 phi->Kill(); | 136 phi->Kill(); |
137 phis_.RemoveElement(phi); | 137 phis_.RemoveElement(phi); |
138 phi->SetBlock(NULL); | 138 phi->SetBlock(NULL); |
139 } | 139 } |
140 | 140 |
141 | 141 |
142 void HBasicBlock::AddInstruction(HInstruction* instr) { | 142 void HBasicBlock::AddInstruction(HInstruction* instr, int position) { |
143 ASSERT(!IsStartBlock() || !IsFinished()); | 143 ASSERT(!IsStartBlock() || !IsFinished()); |
144 ASSERT(!instr->IsLinked()); | 144 ASSERT(!instr->IsLinked()); |
145 ASSERT(!IsFinished()); | 145 ASSERT(!IsFinished()); |
146 | 146 |
| 147 if (position != RelocInfo::kNoPosition) { |
| 148 instr->set_position(position); |
| 149 } |
147 if (first_ == NULL) { | 150 if (first_ == NULL) { |
148 ASSERT(last_environment() != NULL); | 151 ASSERT(last_environment() != NULL); |
149 ASSERT(!last_environment()->ast_id().IsNone()); | 152 ASSERT(!last_environment()->ast_id().IsNone()); |
150 HBlockEntry* entry = new(zone()) HBlockEntry(); | 153 HBlockEntry* entry = new(zone()) HBlockEntry(); |
151 entry->InitializeAsFirst(this); | 154 entry->InitializeAsFirst(this); |
| 155 if (position != RelocInfo::kNoPosition) { |
| 156 entry->set_position(position); |
| 157 } else { |
| 158 ASSERT(!FLAG_opt_code_positions || |
| 159 !graph()->info()->IsOptimizing()); |
| 160 } |
152 first_ = last_ = entry; | 161 first_ = last_ = entry; |
153 } | 162 } |
154 instr->InsertAfter(last_); | 163 instr->InsertAfter(last_); |
155 } | 164 } |
156 | 165 |
157 | 166 |
158 HPhi* HBasicBlock::AddNewPhi(int merged_index) { | 167 HPhi* HBasicBlock::AddNewPhi(int merged_index) { |
159 if (graph()->IsInsideNoSideEffectsScope()) { | 168 if (graph()->IsInsideNoSideEffectsScope()) { |
160 merged_index = HPhi::kInvalidMergedIndex; | 169 merged_index = HPhi::kInvalidMergedIndex; |
161 } | 170 } |
(...skipping 30 matching lines...) Expand all Loading... |
192 !it.Done(); | 201 !it.Done(); |
193 it.Advance()) { | 202 it.Advance()) { |
194 int index = it.Current(); | 203 int index = it.Current(); |
195 instr->AddAssignedValue(index, environment->Lookup(index)); | 204 instr->AddAssignedValue(index, environment->Lookup(index)); |
196 } | 205 } |
197 environment->ClearHistory(); | 206 environment->ClearHistory(); |
198 return instr; | 207 return instr; |
199 } | 208 } |
200 | 209 |
201 | 210 |
202 void HBasicBlock::Finish(HControlInstruction* end) { | 211 void HBasicBlock::Finish(HControlInstruction* end, int position) { |
203 ASSERT(!IsFinished()); | 212 ASSERT(!IsFinished()); |
204 AddInstruction(end); | 213 AddInstruction(end, position); |
205 end_ = end; | 214 end_ = end; |
206 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { | 215 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { |
207 it.Current()->RegisterPredecessor(this); | 216 it.Current()->RegisterPredecessor(this); |
208 } | 217 } |
209 } | 218 } |
210 | 219 |
211 | 220 |
212 void HBasicBlock::Goto(HBasicBlock* block, | 221 void HBasicBlock::Goto(HBasicBlock* block, |
| 222 int position, |
213 FunctionState* state, | 223 FunctionState* state, |
214 bool add_simulate) { | 224 bool add_simulate) { |
215 bool drop_extra = state != NULL && | 225 bool drop_extra = state != NULL && |
216 state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 226 state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
217 | 227 |
218 if (block->IsInlineReturnTarget()) { | 228 if (block->IsInlineReturnTarget()) { |
219 HEnvironment* env = last_environment(); | 229 HEnvironment* env = last_environment(); |
220 int argument_count = env->arguments_environment()->parameter_count(); | 230 int argument_count = env->arguments_environment()->parameter_count(); |
221 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count)); | 231 AddInstruction(new(zone()) |
| 232 HLeaveInlined(state->entry(), argument_count), |
| 233 position); |
222 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); | 234 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
223 } | 235 } |
224 | 236 |
225 if (add_simulate) AddNewSimulate(BailoutId::None()); | 237 if (add_simulate) AddNewSimulate(BailoutId::None(), position); |
226 HGoto* instr = new(zone()) HGoto(block); | 238 HGoto* instr = new(zone()) HGoto(block); |
227 Finish(instr); | 239 Finish(instr, position); |
228 } | 240 } |
229 | 241 |
230 | 242 |
231 void HBasicBlock::AddLeaveInlined(HValue* return_value, | 243 void HBasicBlock::AddLeaveInlined(HValue* return_value, |
232 FunctionState* state) { | 244 FunctionState* state, |
| 245 int position) { |
233 HBasicBlock* target = state->function_return(); | 246 HBasicBlock* target = state->function_return(); |
234 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 247 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
235 | 248 |
236 ASSERT(target->IsInlineReturnTarget()); | 249 ASSERT(target->IsInlineReturnTarget()); |
237 ASSERT(return_value != NULL); | 250 ASSERT(return_value != NULL); |
238 HEnvironment* env = last_environment(); | 251 HEnvironment* env = last_environment(); |
239 int argument_count = env->arguments_environment()->parameter_count(); | 252 int argument_count = env->arguments_environment()->parameter_count(); |
240 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count)); | 253 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count), |
| 254 position); |
241 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); | 255 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
242 last_environment()->Push(return_value); | 256 last_environment()->Push(return_value); |
243 AddNewSimulate(BailoutId::None()); | 257 AddNewSimulate(BailoutId::None(), position); |
244 HGoto* instr = new(zone()) HGoto(target); | 258 HGoto* instr = new(zone()) HGoto(target); |
245 Finish(instr); | 259 Finish(instr, position); |
246 } | 260 } |
247 | 261 |
248 | 262 |
249 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { | 263 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { |
250 ASSERT(!HasEnvironment()); | 264 ASSERT(!HasEnvironment()); |
251 ASSERT(first() == NULL); | 265 ASSERT(first() == NULL); |
252 UpdateEnvironment(env); | 266 UpdateEnvironment(env); |
253 } | 267 } |
254 | 268 |
255 | 269 |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 if (constant == GetConstant1()) return true; | 707 if (constant == GetConstant1()) return true; |
694 if (constant == GetConstantMinus1()) return true; | 708 if (constant == GetConstantMinus1()) return true; |
695 if (constant == GetConstantTrue()) return true; | 709 if (constant == GetConstantTrue()) return true; |
696 if (constant == GetConstantFalse()) return true; | 710 if (constant == GetConstantFalse()) return true; |
697 if (constant == GetConstantHole()) return true; | 711 if (constant == GetConstantHole()) return true; |
698 if (constant == GetConstantNull()) return true; | 712 if (constant == GetConstantNull()) return true; |
699 return false; | 713 return false; |
700 } | 714 } |
701 | 715 |
702 | 716 |
703 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) | 717 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder) |
704 : builder_(builder), | 718 : builder_(builder), |
705 position_(position), | |
706 finished_(false), | 719 finished_(false), |
707 deopt_then_(false), | 720 deopt_then_(false), |
708 deopt_else_(false), | 721 deopt_else_(false), |
709 did_then_(false), | 722 did_then_(false), |
710 did_else_(false), | 723 did_else_(false), |
711 did_and_(false), | 724 did_and_(false), |
712 did_or_(false), | 725 did_or_(false), |
713 captured_(false), | 726 captured_(false), |
714 needs_compare_(true), | 727 needs_compare_(true), |
715 split_edge_merge_block_(NULL), | 728 split_edge_merge_block_(NULL), |
716 merge_block_(NULL) { | 729 merge_block_(NULL) { |
717 HEnvironment* env = builder->environment(); | 730 HEnvironment* env = builder->environment(); |
718 first_true_block_ = builder->CreateBasicBlock(env->Copy()); | 731 first_true_block_ = builder->CreateBasicBlock(env->Copy()); |
719 last_true_block_ = NULL; | 732 last_true_block_ = NULL; |
720 first_false_block_ = builder->CreateBasicBlock(env->Copy()); | 733 first_false_block_ = builder->CreateBasicBlock(env->Copy()); |
721 } | 734 } |
722 | 735 |
723 | 736 |
724 HGraphBuilder::IfBuilder::IfBuilder( | 737 HGraphBuilder::IfBuilder::IfBuilder( |
725 HGraphBuilder* builder, | 738 HGraphBuilder* builder, |
726 HIfContinuation* continuation) | 739 HIfContinuation* continuation) |
727 : builder_(builder), | 740 : builder_(builder), |
728 position_(RelocInfo::kNoPosition), | |
729 finished_(false), | 741 finished_(false), |
730 deopt_then_(false), | 742 deopt_then_(false), |
731 deopt_else_(false), | 743 deopt_else_(false), |
732 did_then_(false), | 744 did_then_(false), |
733 did_else_(false), | 745 did_else_(false), |
734 did_and_(false), | 746 did_and_(false), |
735 did_or_(false), | 747 did_or_(false), |
736 captured_(false), | 748 captured_(false), |
737 needs_compare_(false), | 749 needs_compare_(false), |
738 first_true_block_(NULL), | 750 first_true_block_(NULL), |
739 last_true_block_(NULL), | 751 last_true_block_(NULL), |
740 first_false_block_(NULL), | 752 first_false_block_(NULL), |
741 split_edge_merge_block_(NULL), | 753 split_edge_merge_block_(NULL), |
742 merge_block_(NULL) { | 754 merge_block_(NULL) { |
743 continuation->Continue(&first_true_block_, | 755 continuation->Continue(&first_true_block_, |
744 &first_false_block_, | 756 &first_false_block_); |
745 &position_); | |
746 } | 757 } |
747 | 758 |
748 | 759 |
749 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( | 760 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( |
750 HControlInstruction* compare) { | 761 HControlInstruction* compare) { |
751 if (split_edge_merge_block_ != NULL) { | 762 if (split_edge_merge_block_ != NULL) { |
752 HEnvironment* env = first_false_block_->last_environment(); | 763 HEnvironment* env = first_false_block_->last_environment(); |
753 HBasicBlock* split_edge = | 764 HBasicBlock* split_edge = |
754 builder_->CreateBasicBlock(env->Copy()); | 765 builder_->CreateBasicBlock(env->Copy()); |
755 if (did_or_) { | 766 if (did_or_) { |
756 compare->SetSuccessorAt(0, split_edge); | 767 compare->SetSuccessorAt(0, split_edge); |
757 compare->SetSuccessorAt(1, first_false_block_); | 768 compare->SetSuccessorAt(1, first_false_block_); |
758 } else { | 769 } else { |
759 compare->SetSuccessorAt(0, first_true_block_); | 770 compare->SetSuccessorAt(0, first_true_block_); |
760 compare->SetSuccessorAt(1, split_edge); | 771 compare->SetSuccessorAt(1, split_edge); |
761 } | 772 } |
762 split_edge->GotoNoSimulate(split_edge_merge_block_); | 773 builder_->GotoNoSimulate(split_edge, split_edge_merge_block_); |
763 } else { | 774 } else { |
764 compare->SetSuccessorAt(0, first_true_block_); | 775 compare->SetSuccessorAt(0, first_true_block_); |
765 compare->SetSuccessorAt(1, first_false_block_); | 776 compare->SetSuccessorAt(1, first_false_block_); |
766 } | 777 } |
767 builder_->current_block()->Finish(compare); | 778 builder_->FinishCurrentBlock(compare); |
768 needs_compare_ = false; | 779 needs_compare_ = false; |
769 return compare; | 780 return compare; |
770 } | 781 } |
771 | 782 |
772 | 783 |
773 void HGraphBuilder::IfBuilder::Or() { | 784 void HGraphBuilder::IfBuilder::Or() { |
774 ASSERT(!did_and_); | 785 ASSERT(!did_and_); |
775 did_or_ = true; | 786 did_or_ = true; |
776 HEnvironment* env = first_false_block_->last_environment(); | 787 HEnvironment* env = first_false_block_->last_environment(); |
777 if (split_edge_merge_block_ == NULL) { | 788 if (split_edge_merge_block_ == NULL) { |
778 split_edge_merge_block_ = | 789 split_edge_merge_block_ = |
779 builder_->CreateBasicBlock(env->Copy()); | 790 builder_->CreateBasicBlock(env->Copy()); |
780 first_true_block_->GotoNoSimulate(split_edge_merge_block_); | 791 builder_->GotoNoSimulate(first_true_block_, split_edge_merge_block_); |
781 first_true_block_ = split_edge_merge_block_; | 792 first_true_block_ = split_edge_merge_block_; |
782 } | 793 } |
783 builder_->set_current_block(first_false_block_); | 794 builder_->set_current_block(first_false_block_); |
784 first_false_block_ = builder_->CreateBasicBlock(env->Copy()); | 795 first_false_block_ = builder_->CreateBasicBlock(env->Copy()); |
785 } | 796 } |
786 | 797 |
787 | 798 |
788 void HGraphBuilder::IfBuilder::And() { | 799 void HGraphBuilder::IfBuilder::And() { |
789 ASSERT(!did_or_); | 800 ASSERT(!did_or_); |
790 did_and_ = true; | 801 did_and_ = true; |
791 HEnvironment* env = first_false_block_->last_environment(); | 802 HEnvironment* env = first_false_block_->last_environment(); |
792 if (split_edge_merge_block_ == NULL) { | 803 if (split_edge_merge_block_ == NULL) { |
793 split_edge_merge_block_ = builder_->CreateBasicBlock(env->Copy()); | 804 split_edge_merge_block_ = builder_->CreateBasicBlock(env->Copy()); |
794 first_false_block_->GotoNoSimulate(split_edge_merge_block_); | 805 builder_->GotoNoSimulate(first_false_block_, split_edge_merge_block_); |
795 first_false_block_ = split_edge_merge_block_; | 806 first_false_block_ = split_edge_merge_block_; |
796 } | 807 } |
797 builder_->set_current_block(first_true_block_); | 808 builder_->set_current_block(first_true_block_); |
798 first_true_block_ = builder_->CreateBasicBlock(env->Copy()); | 809 first_true_block_ = builder_->CreateBasicBlock(env->Copy()); |
799 } | 810 } |
800 | 811 |
801 | 812 |
802 void HGraphBuilder::IfBuilder::CaptureContinuation( | 813 void HGraphBuilder::IfBuilder::CaptureContinuation( |
803 HIfContinuation* continuation) { | 814 HIfContinuation* continuation) { |
804 ASSERT(!finished_); | 815 ASSERT(!finished_); |
805 ASSERT(!captured_); | 816 ASSERT(!captured_); |
806 HBasicBlock* true_block = last_true_block_ == NULL | 817 HBasicBlock* true_block = last_true_block_ == NULL |
807 ? first_true_block_ | 818 ? first_true_block_ |
808 : last_true_block_; | 819 : last_true_block_; |
809 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) | 820 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) |
810 ? builder_->current_block() | 821 ? builder_->current_block() |
811 : first_false_block_; | 822 : first_false_block_; |
812 continuation->Capture(true_block, false_block, position_); | 823 continuation->Capture(true_block, false_block); |
813 captured_ = true; | 824 captured_ = true; |
814 End(); | 825 End(); |
815 } | 826 } |
816 | 827 |
817 | 828 |
818 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { | 829 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { |
819 ASSERT(!finished_); | 830 ASSERT(!finished_); |
820 ASSERT(!captured_); | 831 ASSERT(!captured_); |
821 HBasicBlock* true_block = last_true_block_ == NULL | 832 HBasicBlock* true_block = last_true_block_ == NULL |
822 ? first_true_block_ | 833 ? first_true_block_ |
823 : last_true_block_; | 834 : last_true_block_; |
824 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) | 835 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) |
825 ? builder_->current_block() | 836 ? builder_->current_block() |
826 : first_false_block_; | 837 : first_false_block_; |
827 if (true_block != NULL && !true_block->IsFinished()) { | 838 if (true_block != NULL && !true_block->IsFinished()) { |
828 ASSERT(continuation->IsTrueReachable()); | 839 ASSERT(continuation->IsTrueReachable()); |
829 true_block->GotoNoSimulate(continuation->true_branch()); | 840 builder_->GotoNoSimulate(true_block, continuation->true_branch()); |
830 } | 841 } |
831 if (false_block != NULL && !false_block->IsFinished()) { | 842 if (false_block != NULL && !false_block->IsFinished()) { |
832 ASSERT(continuation->IsFalseReachable()); | 843 ASSERT(continuation->IsFalseReachable()); |
833 false_block->GotoNoSimulate(continuation->false_branch()); | 844 builder_->GotoNoSimulate(false_block, continuation->false_branch()); |
834 } | 845 } |
835 captured_ = true; | 846 captured_ = true; |
836 End(); | 847 End(); |
837 } | 848 } |
838 | 849 |
839 | 850 |
840 void HGraphBuilder::IfBuilder::Then() { | 851 void HGraphBuilder::IfBuilder::Then() { |
841 ASSERT(!captured_); | 852 ASSERT(!captured_); |
842 ASSERT(!finished_); | 853 ASSERT(!finished_); |
843 did_then_ = true; | 854 did_then_ = true; |
844 if (needs_compare_) { | 855 if (needs_compare_) { |
845 // Handle if's without any expressions, they jump directly to the "else" | 856 // Handle if's without any expressions, they jump directly to the "else" |
846 // branch. However, we must pretend that the "then" branch is reachable, | 857 // branch. However, we must pretend that the "then" branch is reachable, |
847 // so that the graph builder visits it and sees any live range extending | 858 // so that the graph builder visits it and sees any live range extending |
848 // constructs within it. | 859 // constructs within it. |
849 HConstant* constant_false = builder_->graph()->GetConstantFalse(); | 860 HConstant* constant_false = builder_->graph()->GetConstantFalse(); |
850 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); | 861 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); |
851 boolean_type.Add(ToBooleanStub::BOOLEAN); | 862 boolean_type.Add(ToBooleanStub::BOOLEAN); |
852 HBranch* branch = builder()->New<HBranch>( | 863 HBranch* branch = builder()->New<HBranch>( |
853 constant_false, boolean_type, first_true_block_, first_false_block_); | 864 constant_false, boolean_type, first_true_block_, first_false_block_); |
854 builder_->current_block()->Finish(branch); | 865 builder_->FinishCurrentBlock(branch); |
855 } | 866 } |
856 builder_->set_current_block(first_true_block_); | 867 builder_->set_current_block(first_true_block_); |
857 } | 868 } |
858 | 869 |
859 | 870 |
860 void HGraphBuilder::IfBuilder::Else() { | 871 void HGraphBuilder::IfBuilder::Else() { |
861 ASSERT(did_then_); | 872 ASSERT(did_then_); |
862 ASSERT(!captured_); | 873 ASSERT(!captured_); |
863 ASSERT(!finished_); | 874 ASSERT(!finished_); |
864 last_true_block_ = builder_->current_block(); | 875 last_true_block_ = builder_->current_block(); |
865 builder_->set_current_block(first_false_block_); | 876 builder_->set_current_block(first_false_block_); |
866 did_else_ = true; | 877 did_else_ = true; |
867 } | 878 } |
868 | 879 |
869 | 880 |
870 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { | 881 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { |
871 ASSERT(did_then_); | 882 ASSERT(did_then_); |
872 if (did_else_) { | 883 if (did_else_) { |
873 deopt_else_ = true; | 884 deopt_else_ = true; |
874 } else { | 885 } else { |
875 deopt_then_ = true; | 886 deopt_then_ = true; |
876 } | 887 } |
877 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 888 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
878 } | 889 } |
879 | 890 |
880 | 891 |
881 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 892 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
882 HBasicBlock* block = builder_->current_block(); | |
883 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); | 893 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); |
884 block->FinishExit(builder_->New<HReturn>(value, parameter_count)); | 894 builder_->FinishExitCurrentBlock( |
885 builder_->set_current_block(NULL); | 895 builder_->New<HReturn>(value, parameter_count)); |
886 if (did_else_) { | 896 if (did_else_) { |
887 first_false_block_ = NULL; | 897 first_false_block_ = NULL; |
888 } else { | 898 } else { |
889 first_true_block_ = NULL; | 899 first_true_block_ = NULL; |
890 } | 900 } |
891 } | 901 } |
892 | 902 |
893 | 903 |
894 void HGraphBuilder::IfBuilder::End() { | 904 void HGraphBuilder::IfBuilder::End() { |
895 if (!captured_) { | 905 if (!captured_) { |
896 ASSERT(did_then_); | 906 ASSERT(did_then_); |
897 if (!did_else_) { | 907 if (!did_else_) { |
898 last_true_block_ = builder_->current_block(); | 908 last_true_block_ = builder_->current_block(); |
899 } | 909 } |
900 if (last_true_block_ == NULL || last_true_block_->IsFinished()) { | 910 if (last_true_block_ == NULL || last_true_block_->IsFinished()) { |
901 ASSERT(did_else_); | 911 ASSERT(did_else_); |
902 // Return on true. Nothing to do, just continue the false block. | 912 // Return on true. Nothing to do, just continue the false block. |
903 } else if (first_false_block_ == NULL || | 913 } else if (first_false_block_ == NULL || |
904 (did_else_ && builder_->current_block()->IsFinished())) { | 914 (did_else_ && builder_->current_block()->IsFinished())) { |
905 // Deopt on false. Nothing to do except switching to the true block. | 915 // Deopt on false. Nothing to do except switching to the true block. |
906 builder_->set_current_block(last_true_block_); | 916 builder_->set_current_block(last_true_block_); |
907 } else { | 917 } else { |
908 merge_block_ = builder_->graph()->CreateBasicBlock(); | 918 merge_block_ = builder_->graph()->CreateBasicBlock(); |
909 ASSERT(!finished_); | 919 ASSERT(!finished_); |
910 if (!did_else_) Else(); | 920 if (!did_else_) Else(); |
911 ASSERT(!last_true_block_->IsFinished()); | 921 ASSERT(!last_true_block_->IsFinished()); |
912 HBasicBlock* last_false_block = builder_->current_block(); | 922 HBasicBlock* last_false_block = builder_->current_block(); |
913 ASSERT(!last_false_block->IsFinished()); | 923 ASSERT(!last_false_block->IsFinished()); |
914 if (deopt_then_) { | 924 if (deopt_then_) { |
915 last_false_block->GotoNoSimulate(merge_block_); | 925 builder_->GotoNoSimulate(last_false_block, merge_block_); |
916 builder_->PadEnvironmentForContinuation(last_true_block_, | 926 builder_->PadEnvironmentForContinuation(last_true_block_, |
917 merge_block_); | 927 merge_block_); |
918 last_true_block_->GotoNoSimulate(merge_block_); | 928 builder_->GotoNoSimulate(last_true_block_, merge_block_); |
919 } else { | 929 } else { |
920 last_true_block_->GotoNoSimulate(merge_block_); | 930 builder_->GotoNoSimulate(last_true_block_, merge_block_); |
921 if (deopt_else_) { | 931 if (deopt_else_) { |
922 builder_->PadEnvironmentForContinuation(last_false_block, | 932 builder_->PadEnvironmentForContinuation(last_false_block, |
923 merge_block_); | 933 merge_block_); |
924 } | 934 } |
925 last_false_block->GotoNoSimulate(merge_block_); | 935 builder_->GotoNoSimulate(last_false_block, merge_block_); |
926 } | 936 } |
927 builder_->set_current_block(merge_block_); | 937 builder_->set_current_block(merge_block_); |
928 } | 938 } |
929 } | 939 } |
930 finished_ = true; | 940 finished_ = true; |
931 } | 941 } |
932 | 942 |
933 | 943 |
934 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, | 944 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
935 HValue* context, | 945 HValue* context, |
(...skipping 27 matching lines...) Expand all Loading... |
963 | 973 |
964 | 974 |
965 HValue* HGraphBuilder::LoopBuilder::BeginBody( | 975 HValue* HGraphBuilder::LoopBuilder::BeginBody( |
966 HValue* initial, | 976 HValue* initial, |
967 HValue* terminating, | 977 HValue* terminating, |
968 Token::Value token) { | 978 Token::Value token) { |
969 HEnvironment* env = builder_->environment(); | 979 HEnvironment* env = builder_->environment(); |
970 phi_ = header_block_->AddNewPhi(env->values()->length()); | 980 phi_ = header_block_->AddNewPhi(env->values()->length()); |
971 phi_->AddInput(initial); | 981 phi_->AddInput(initial); |
972 env->Push(initial); | 982 env->Push(initial); |
973 builder_->current_block()->GotoNoSimulate(header_block_); | 983 builder_->GotoNoSimulate(header_block_); |
974 | 984 |
975 HEnvironment* body_env = env->Copy(); | 985 HEnvironment* body_env = env->Copy(); |
976 HEnvironment* exit_env = env->Copy(); | 986 HEnvironment* exit_env = env->Copy(); |
977 // Remove the phi from the expression stack | 987 // Remove the phi from the expression stack |
978 body_env->Pop(); | 988 body_env->Pop(); |
979 exit_env->Pop(); | 989 exit_env->Pop(); |
980 body_block_ = builder_->CreateBasicBlock(body_env); | 990 body_block_ = builder_->CreateBasicBlock(body_env); |
981 exit_block_ = builder_->CreateBasicBlock(exit_env); | 991 exit_block_ = builder_->CreateBasicBlock(exit_env); |
982 | 992 |
983 builder_->set_current_block(header_block_); | 993 builder_->set_current_block(header_block_); |
984 env->Pop(); | 994 env->Pop(); |
985 builder_->current_block()->Finish(builder_->New<HCompareNumericAndBranch>( | 995 builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>( |
986 phi_, terminating, token, body_block_, exit_block_)); | 996 phi_, terminating, token, body_block_, exit_block_)); |
987 | 997 |
988 builder_->set_current_block(body_block_); | 998 builder_->set_current_block(body_block_); |
989 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { | 999 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { |
990 HValue* one = builder_->graph()->GetConstant1(); | 1000 HValue* one = builder_->graph()->GetConstant1(); |
991 if (direction_ == kPreIncrement) { | 1001 if (direction_ == kPreIncrement) { |
992 increment_ = HAdd::New(zone(), context_, phi_, one); | 1002 increment_ = HAdd::New(zone(), context_, phi_, one); |
993 } else { | 1003 } else { |
994 increment_ = HSub::New(zone(), context_, phi_, one); | 1004 increment_ = HSub::New(zone(), context_, phi_, one); |
995 } | 1005 } |
996 increment_->ClearFlag(HValue::kCanOverflow); | 1006 increment_->ClearFlag(HValue::kCanOverflow); |
997 builder_->AddInstruction(increment_); | 1007 builder_->AddInstruction(increment_); |
998 return increment_; | 1008 return increment_; |
999 } else { | 1009 } else { |
1000 return phi_; | 1010 return phi_; |
1001 } | 1011 } |
1002 } | 1012 } |
1003 | 1013 |
1004 | 1014 |
1005 void HGraphBuilder::LoopBuilder::Break() { | 1015 void HGraphBuilder::LoopBuilder::Break() { |
1006 if (exit_trampoline_block_ == NULL) { | 1016 if (exit_trampoline_block_ == NULL) { |
1007 // Its the first time we saw a break. | 1017 // Its the first time we saw a break. |
1008 HEnvironment* env = exit_block_->last_environment()->Copy(); | 1018 HEnvironment* env = exit_block_->last_environment()->Copy(); |
1009 exit_trampoline_block_ = builder_->CreateBasicBlock(env); | 1019 exit_trampoline_block_ = builder_->CreateBasicBlock(env); |
1010 exit_block_->GotoNoSimulate(exit_trampoline_block_); | 1020 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_); |
1011 } | 1021 } |
1012 | 1022 |
1013 builder_->current_block()->GotoNoSimulate(exit_trampoline_block_); | 1023 builder_->GotoNoSimulate(exit_trampoline_block_); |
1014 } | 1024 } |
1015 | 1025 |
1016 | 1026 |
1017 void HGraphBuilder::LoopBuilder::EndBody() { | 1027 void HGraphBuilder::LoopBuilder::EndBody() { |
1018 ASSERT(!finished_); | 1028 ASSERT(!finished_); |
1019 | 1029 |
1020 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { | 1030 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { |
1021 if (direction_ == kPostIncrement) { | 1031 if (direction_ == kPostIncrement) { |
1022 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); | 1032 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); |
1023 } else { | 1033 } else { |
1024 increment_ = HSub::New(zone(), context_, phi_, increment_amount_); | 1034 increment_ = HSub::New(zone(), context_, phi_, increment_amount_); |
1025 } | 1035 } |
1026 increment_->ClearFlag(HValue::kCanOverflow); | 1036 increment_->ClearFlag(HValue::kCanOverflow); |
1027 builder_->AddInstruction(increment_); | 1037 builder_->AddInstruction(increment_); |
1028 } | 1038 } |
1029 | 1039 |
1030 // Push the new increment value on the expression stack to merge into the phi. | 1040 // Push the new increment value on the expression stack to merge into the phi. |
1031 builder_->environment()->Push(increment_); | 1041 builder_->environment()->Push(increment_); |
1032 HBasicBlock* last_block = builder_->current_block(); | 1042 HBasicBlock* last_block = builder_->current_block(); |
1033 last_block->GotoNoSimulate(header_block_); | 1043 builder_->GotoNoSimulate(last_block, header_block_); |
1034 header_block_->loop_information()->RegisterBackEdge(last_block); | 1044 header_block_->loop_information()->RegisterBackEdge(last_block); |
1035 | 1045 |
1036 if (exit_trampoline_block_ != NULL) { | 1046 if (exit_trampoline_block_ != NULL) { |
1037 builder_->set_current_block(exit_trampoline_block_); | 1047 builder_->set_current_block(exit_trampoline_block_); |
1038 } else { | 1048 } else { |
1039 builder_->set_current_block(exit_block_); | 1049 builder_->set_current_block(exit_block_); |
1040 } | 1050 } |
1041 finished_ = true; | 1051 finished_ = true; |
1042 } | 1052 } |
1043 | 1053 |
1044 | 1054 |
1045 HGraph* HGraphBuilder::CreateGraph() { | 1055 HGraph* HGraphBuilder::CreateGraph() { |
1046 graph_ = new(zone()) HGraph(info_); | 1056 graph_ = new(zone()) HGraph(info_); |
1047 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); | 1057 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); |
1048 CompilationPhase phase("H_Block building", info_); | 1058 CompilationPhase phase("H_Block building", info_); |
1049 set_current_block(graph()->entry_block()); | 1059 set_current_block(graph()->entry_block()); |
1050 if (!BuildGraph()) return NULL; | 1060 if (!BuildGraph()) return NULL; |
1051 graph()->FinalizeUniqueness(); | 1061 graph()->FinalizeUniqueness(); |
1052 return graph_; | 1062 return graph_; |
1053 } | 1063 } |
1054 | 1064 |
1055 | 1065 |
1056 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 1066 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
1057 ASSERT(current_block() != NULL); | 1067 ASSERT(current_block() != NULL); |
1058 current_block()->AddInstruction(instr); | 1068 ASSERT(!FLAG_opt_code_positions || |
| 1069 position_ != RelocInfo::kNoPosition || !info_->IsOptimizing()); |
| 1070 current_block()->AddInstruction(instr, position_); |
1059 if (graph()->IsInsideNoSideEffectsScope()) { | 1071 if (graph()->IsInsideNoSideEffectsScope()) { |
1060 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 1072 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
1061 } | 1073 } |
1062 return instr; | 1074 return instr; |
1063 } | 1075 } |
1064 | 1076 |
1065 | 1077 |
| 1078 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) { |
| 1079 ASSERT(!FLAG_opt_code_positions || !info_->IsOptimizing() || |
| 1080 position_ != RelocInfo::kNoPosition); |
| 1081 current_block()->Finish(last, position_); |
| 1082 if (last->IsReturn() || last->IsAbnormalExit()) { |
| 1083 set_current_block(NULL); |
| 1084 } |
| 1085 } |
| 1086 |
| 1087 |
| 1088 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) { |
| 1089 ASSERT(!FLAG_opt_code_positions || !info_->IsOptimizing() || |
| 1090 position_ != RelocInfo::kNoPosition); |
| 1091 current_block()->FinishExit(instruction, position_); |
| 1092 if (instruction->IsReturn() || instruction->IsAbnormalExit()) { |
| 1093 set_current_block(NULL); |
| 1094 } |
| 1095 } |
| 1096 |
| 1097 |
1066 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { | 1098 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { |
1067 if (FLAG_native_code_counters && counter->Enabled()) { | 1099 if (FLAG_native_code_counters && counter->Enabled()) { |
1068 HValue* reference = Add<HConstant>(ExternalReference(counter)); | 1100 HValue* reference = Add<HConstant>(ExternalReference(counter)); |
1069 HValue* old_value = Add<HLoadNamedField>(reference, | 1101 HValue* old_value = Add<HLoadNamedField>(reference, |
1070 HObjectAccess::ForCounter()); | 1102 HObjectAccess::ForCounter()); |
1071 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); | 1103 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); |
1072 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow | 1104 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow |
1073 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), | 1105 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), |
1074 new_value); | 1106 new_value); |
1075 } | 1107 } |
(...skipping 28 matching lines...) Expand all Loading... |
1104 if (obj->type().IsHeapObject()) return obj; | 1136 if (obj->type().IsHeapObject()) return obj; |
1105 return Add<HCheckHeapObject>(obj); | 1137 return Add<HCheckHeapObject>(obj); |
1106 } | 1138 } |
1107 | 1139 |
1108 | 1140 |
1109 void HGraphBuilder::FinishExitWithHardDeoptimization( | 1141 void HGraphBuilder::FinishExitWithHardDeoptimization( |
1110 const char* reason, HBasicBlock* continuation) { | 1142 const char* reason, HBasicBlock* continuation) { |
1111 PadEnvironmentForContinuation(current_block(), continuation); | 1143 PadEnvironmentForContinuation(current_block(), continuation); |
1112 Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 1144 Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
1113 if (graph()->IsInsideNoSideEffectsScope()) { | 1145 if (graph()->IsInsideNoSideEffectsScope()) { |
1114 current_block()->GotoNoSimulate(continuation); | 1146 GotoNoSimulate(continuation); |
1115 } else { | 1147 } else { |
1116 current_block()->Goto(continuation); | 1148 Goto(continuation); |
1117 } | 1149 } |
1118 } | 1150 } |
1119 | 1151 |
1120 | 1152 |
1121 void HGraphBuilder::PadEnvironmentForContinuation( | 1153 void HGraphBuilder::PadEnvironmentForContinuation( |
1122 HBasicBlock* from, | 1154 HBasicBlock* from, |
1123 HBasicBlock* continuation) { | 1155 HBasicBlock* continuation) { |
1124 if (continuation->last_environment() != NULL) { | 1156 if (continuation->last_environment() != NULL) { |
1125 // When merging from a deopt block to a continuation, resolve differences in | 1157 // When merging from a deopt block to a continuation, resolve differences in |
1126 // environment by pushing constant 0 and popping extra values so that the | 1158 // environment by pushing constant 0 and popping extra values so that the |
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1930 } | 1962 } |
1931 } | 1963 } |
1932 | 1964 |
1933 return object; | 1965 return object; |
1934 } | 1966 } |
1935 | 1967 |
1936 | 1968 |
1937 void HGraphBuilder::BuildCompareNil( | 1969 void HGraphBuilder::BuildCompareNil( |
1938 HValue* value, | 1970 HValue* value, |
1939 Handle<Type> type, | 1971 Handle<Type> type, |
1940 int position, | |
1941 HIfContinuation* continuation) { | 1972 HIfContinuation* continuation) { |
1942 IfBuilder if_nil(this, position); | 1973 IfBuilder if_nil(this); |
1943 bool some_case_handled = false; | 1974 bool some_case_handled = false; |
1944 bool some_case_missing = false; | 1975 bool some_case_missing = false; |
1945 | 1976 |
1946 if (type->Maybe(Type::Null())) { | 1977 if (type->Maybe(Type::Null())) { |
1947 if (some_case_handled) if_nil.Or(); | 1978 if (some_case_handled) if_nil.Or(); |
1948 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); | 1979 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); |
1949 some_case_handled = true; | 1980 some_case_handled = true; |
1950 } else { | 1981 } else { |
1951 some_case_missing = true; | 1982 some_case_missing = true; |
1952 } | 1983 } |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2200 break_scope_(NULL), | 2231 break_scope_(NULL), |
2201 inlined_count_(0), | 2232 inlined_count_(0), |
2202 globals_(10, info->zone()), | 2233 globals_(10, info->zone()), |
2203 inline_bailout_(false), | 2234 inline_bailout_(false), |
2204 osr_(new(info->zone()) HOsrBuilder(this)) { | 2235 osr_(new(info->zone()) HOsrBuilder(this)) { |
2205 // This is not initialized in the initializer list because the | 2236 // This is not initialized in the initializer list because the |
2206 // constructor for the initial state relies on function_state_ == NULL | 2237 // constructor for the initial state relies on function_state_ == NULL |
2207 // to know it's the initial state. | 2238 // to know it's the initial state. |
2208 function_state_= &initial_function_state_; | 2239 function_state_= &initial_function_state_; |
2209 InitializeAstVisitor(info->isolate()); | 2240 InitializeAstVisitor(info->isolate()); |
| 2241 if (FLAG_opt_code_positions) { |
| 2242 SetSourcePosition(info->shared_info()->start_position()); |
| 2243 } |
2210 } | 2244 } |
2211 | 2245 |
2212 | 2246 |
2213 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, | 2247 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, |
2214 HBasicBlock* second, | 2248 HBasicBlock* second, |
2215 BailoutId join_id) { | 2249 BailoutId join_id) { |
2216 if (first == NULL) { | 2250 if (first == NULL) { |
2217 return second; | 2251 return second; |
2218 } else if (second == NULL) { | 2252 } else if (second == NULL) { |
2219 return first; | 2253 return first; |
2220 } else { | 2254 } else { |
2221 HBasicBlock* join_block = graph()->CreateBasicBlock(); | 2255 HBasicBlock* join_block = graph()->CreateBasicBlock(); |
2222 first->Goto(join_block); | 2256 Goto(first, join_block); |
2223 second->Goto(join_block); | 2257 Goto(second, join_block); |
2224 join_block->SetJoinId(join_id); | 2258 join_block->SetJoinId(join_id); |
2225 return join_block; | 2259 return join_block; |
2226 } | 2260 } |
2227 } | 2261 } |
2228 | 2262 |
2229 | 2263 |
2230 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement, | 2264 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement, |
2231 HBasicBlock* exit_block, | 2265 HBasicBlock* exit_block, |
2232 HBasicBlock* continue_block) { | 2266 HBasicBlock* continue_block) { |
2233 if (continue_block != NULL) { | 2267 if (continue_block != NULL) { |
2234 if (exit_block != NULL) exit_block->Goto(continue_block); | 2268 if (exit_block != NULL) Goto(exit_block, continue_block); |
2235 continue_block->SetJoinId(statement->ContinueId()); | 2269 continue_block->SetJoinId(statement->ContinueId()); |
2236 return continue_block; | 2270 return continue_block; |
2237 } | 2271 } |
2238 return exit_block; | 2272 return exit_block; |
2239 } | 2273 } |
2240 | 2274 |
2241 | 2275 |
2242 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement, | 2276 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement, |
2243 HBasicBlock* loop_entry, | 2277 HBasicBlock* loop_entry, |
2244 HBasicBlock* body_exit, | 2278 HBasicBlock* body_exit, |
2245 HBasicBlock* loop_successor, | 2279 HBasicBlock* loop_successor, |
2246 HBasicBlock* break_block) { | 2280 HBasicBlock* break_block) { |
2247 if (body_exit != NULL) body_exit->Goto(loop_entry); | 2281 if (body_exit != NULL) Goto(body_exit, loop_entry); |
2248 loop_entry->PostProcessLoopHeader(statement); | 2282 loop_entry->PostProcessLoopHeader(statement); |
2249 if (break_block != NULL) { | 2283 if (break_block != NULL) { |
2250 if (loop_successor != NULL) loop_successor->Goto(break_block); | 2284 if (loop_successor != NULL) Goto(loop_successor, break_block); |
2251 break_block->SetJoinId(statement->ExitId()); | 2285 break_block->SetJoinId(statement->ExitId()); |
2252 return break_block; | 2286 return break_block; |
2253 } | 2287 } |
2254 return loop_successor; | 2288 return loop_successor; |
2255 } | 2289 } |
2256 | 2290 |
2257 | 2291 |
2258 // Build a new loop header block and set it as the current block. | 2292 // Build a new loop header block and set it as the current block. |
2259 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() { | 2293 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() { |
2260 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 2294 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
2261 current_block()->Goto(loop_entry); | 2295 Goto(loop_entry); |
2262 set_current_block(loop_entry); | 2296 set_current_block(loop_entry); |
2263 return loop_entry; | 2297 return loop_entry; |
2264 } | 2298 } |
2265 | 2299 |
2266 | 2300 |
2267 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry( | 2301 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry( |
2268 IterationStatement* statement) { | 2302 IterationStatement* statement) { |
2269 HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement) | 2303 HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement) |
2270 ? osr()->BuildOsrLoopEntry(statement) | 2304 ? osr()->BuildOsrLoopEntry(statement) |
2271 : BuildLoopEntry(); | 2305 : BuildLoopEntry(); |
2272 return loop_entry; | 2306 return loop_entry; |
2273 } | 2307 } |
2274 | 2308 |
2275 | 2309 |
2276 void HBasicBlock::FinishExit(HControlInstruction* instruction) { | 2310 void HBasicBlock::FinishExit(HControlInstruction* instruction, int position) { |
2277 Finish(instruction); | 2311 Finish(instruction, position); |
2278 ClearEnvironment(); | 2312 ClearEnvironment(); |
2279 } | 2313 } |
2280 | 2314 |
2281 | 2315 |
2282 HGraph::HGraph(CompilationInfo* info) | 2316 HGraph::HGraph(CompilationInfo* info) |
2283 : isolate_(info->isolate()), | 2317 : isolate_(info->isolate()), |
2284 next_block_id_(0), | 2318 next_block_id_(0), |
2285 entry_block_(NULL), | 2319 entry_block_(NULL), |
2286 blocks_(8, info->zone()), | 2320 blocks_(8, info->zone()), |
2287 values_(16, info->zone()), | 2321 values_(16, info->zone()), |
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2815 } | 2849 } |
2816 | 2850 |
2817 | 2851 |
2818 void EffectContext::ReturnControl(HControlInstruction* instr, | 2852 void EffectContext::ReturnControl(HControlInstruction* instr, |
2819 BailoutId ast_id) { | 2853 BailoutId ast_id) { |
2820 ASSERT(!instr->HasObservableSideEffects()); | 2854 ASSERT(!instr->HasObservableSideEffects()); |
2821 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2855 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
2822 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2856 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
2823 instr->SetSuccessorAt(0, empty_true); | 2857 instr->SetSuccessorAt(0, empty_true); |
2824 instr->SetSuccessorAt(1, empty_false); | 2858 instr->SetSuccessorAt(1, empty_false); |
2825 owner()->current_block()->Finish(instr); | 2859 owner()->FinishCurrentBlock(instr); |
2826 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); | 2860 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); |
2827 owner()->set_current_block(join); | 2861 owner()->set_current_block(join); |
2828 } | 2862 } |
2829 | 2863 |
2830 | 2864 |
2831 void EffectContext::ReturnContinuation(HIfContinuation* continuation, | 2865 void EffectContext::ReturnContinuation(HIfContinuation* continuation, |
2832 BailoutId ast_id) { | 2866 BailoutId ast_id) { |
2833 HBasicBlock* true_branch = NULL; | 2867 HBasicBlock* true_branch = NULL; |
2834 HBasicBlock* false_branch = NULL; | 2868 HBasicBlock* false_branch = NULL; |
2835 continuation->Continue(&true_branch, &false_branch, NULL); | 2869 continuation->Continue(&true_branch, &false_branch); |
2836 if (!continuation->IsTrueReachable()) { | 2870 if (!continuation->IsTrueReachable()) { |
2837 owner()->set_current_block(false_branch); | 2871 owner()->set_current_block(false_branch); |
2838 } else if (!continuation->IsFalseReachable()) { | 2872 } else if (!continuation->IsFalseReachable()) { |
2839 owner()->set_current_block(true_branch); | 2873 owner()->set_current_block(true_branch); |
2840 } else { | 2874 } else { |
2841 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); | 2875 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); |
2842 owner()->set_current_block(join); | 2876 owner()->set_current_block(join); |
2843 } | 2877 } |
2844 } | 2878 } |
2845 | 2879 |
(...skipping 13 matching lines...) Expand all Loading... |
2859 | 2893 |
2860 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2894 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
2861 ASSERT(!instr->HasObservableSideEffects()); | 2895 ASSERT(!instr->HasObservableSideEffects()); |
2862 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2896 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
2863 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); | 2897 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); |
2864 } | 2898 } |
2865 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | 2899 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
2866 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); | 2900 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); |
2867 instr->SetSuccessorAt(0, materialize_true); | 2901 instr->SetSuccessorAt(0, materialize_true); |
2868 instr->SetSuccessorAt(1, materialize_false); | 2902 instr->SetSuccessorAt(1, materialize_false); |
2869 owner()->current_block()->Finish(instr); | 2903 owner()->FinishCurrentBlock(instr); |
2870 owner()->set_current_block(materialize_true); | 2904 owner()->set_current_block(materialize_true); |
2871 owner()->Push(owner()->graph()->GetConstantTrue()); | 2905 owner()->Push(owner()->graph()->GetConstantTrue()); |
2872 owner()->set_current_block(materialize_false); | 2906 owner()->set_current_block(materialize_false); |
2873 owner()->Push(owner()->graph()->GetConstantFalse()); | 2907 owner()->Push(owner()->graph()->GetConstantFalse()); |
2874 HBasicBlock* join = | 2908 HBasicBlock* join = |
2875 owner()->CreateJoin(materialize_true, materialize_false, ast_id); | 2909 owner()->CreateJoin(materialize_true, materialize_false, ast_id); |
2876 owner()->set_current_block(join); | 2910 owner()->set_current_block(join); |
2877 } | 2911 } |
2878 | 2912 |
2879 | 2913 |
2880 void ValueContext::ReturnContinuation(HIfContinuation* continuation, | 2914 void ValueContext::ReturnContinuation(HIfContinuation* continuation, |
2881 BailoutId ast_id) { | 2915 BailoutId ast_id) { |
2882 HBasicBlock* materialize_true = NULL; | 2916 HBasicBlock* materialize_true = NULL; |
2883 HBasicBlock* materialize_false = NULL; | 2917 HBasicBlock* materialize_false = NULL; |
2884 continuation->Continue(&materialize_true, &materialize_false, NULL); | 2918 continuation->Continue(&materialize_true, &materialize_false); |
2885 if (continuation->IsTrueReachable()) { | 2919 if (continuation->IsTrueReachable()) { |
2886 owner()->set_current_block(materialize_true); | 2920 owner()->set_current_block(materialize_true); |
2887 owner()->Push(owner()->graph()->GetConstantTrue()); | 2921 owner()->Push(owner()->graph()->GetConstantTrue()); |
2888 owner()->set_current_block(materialize_true); | 2922 owner()->set_current_block(materialize_true); |
2889 } | 2923 } |
2890 if (continuation->IsFalseReachable()) { | 2924 if (continuation->IsFalseReachable()) { |
2891 owner()->set_current_block(materialize_false); | 2925 owner()->set_current_block(materialize_false); |
2892 owner()->Push(owner()->graph()->GetConstantFalse()); | 2926 owner()->Push(owner()->graph()->GetConstantFalse()); |
2893 owner()->set_current_block(materialize_false); | 2927 owner()->set_current_block(materialize_false); |
2894 } | 2928 } |
(...skipping 19 matching lines...) Expand all Loading... |
2914 BuildBranch(instr); | 2948 BuildBranch(instr); |
2915 } | 2949 } |
2916 | 2950 |
2917 | 2951 |
2918 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2952 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
2919 ASSERT(!instr->HasObservableSideEffects()); | 2953 ASSERT(!instr->HasObservableSideEffects()); |
2920 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2954 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
2921 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2955 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
2922 instr->SetSuccessorAt(0, empty_true); | 2956 instr->SetSuccessorAt(0, empty_true); |
2923 instr->SetSuccessorAt(1, empty_false); | 2957 instr->SetSuccessorAt(1, empty_false); |
2924 owner()->current_block()->Finish(instr); | 2958 owner()->FinishCurrentBlock(instr); |
2925 empty_true->Goto(if_true(), owner()->function_state()); | 2959 owner()->Goto(empty_true, if_true(), owner()->function_state()); |
2926 empty_false->Goto(if_false(), owner()->function_state()); | 2960 owner()->Goto(empty_false, if_false(), owner()->function_state()); |
2927 owner()->set_current_block(NULL); | 2961 owner()->set_current_block(NULL); |
2928 } | 2962 } |
2929 | 2963 |
2930 | 2964 |
2931 void TestContext::ReturnContinuation(HIfContinuation* continuation, | 2965 void TestContext::ReturnContinuation(HIfContinuation* continuation, |
2932 BailoutId ast_id) { | 2966 BailoutId ast_id) { |
2933 HBasicBlock* true_branch = NULL; | 2967 HBasicBlock* true_branch = NULL; |
2934 HBasicBlock* false_branch = NULL; | 2968 HBasicBlock* false_branch = NULL; |
2935 continuation->Continue(&true_branch, &false_branch, NULL); | 2969 continuation->Continue(&true_branch, &false_branch); |
2936 if (continuation->IsTrueReachable()) { | 2970 if (continuation->IsTrueReachable()) { |
2937 true_branch->Goto(if_true(), owner()->function_state()); | 2971 owner()->Goto(true_branch, if_true(), owner()->function_state()); |
2938 } | 2972 } |
2939 if (continuation->IsFalseReachable()) { | 2973 if (continuation->IsFalseReachable()) { |
2940 false_branch->Goto(if_false(), owner()->function_state()); | 2974 owner()->Goto(false_branch, if_false(), owner()->function_state()); |
2941 } | 2975 } |
2942 owner()->set_current_block(NULL); | 2976 owner()->set_current_block(NULL); |
2943 } | 2977 } |
2944 | 2978 |
2945 | 2979 |
2946 void TestContext::BuildBranch(HValue* value) { | 2980 void TestContext::BuildBranch(HValue* value) { |
2947 // We expect the graph to be in edge-split form: there is no edge that | 2981 // We expect the graph to be in edge-split form: there is no edge that |
2948 // connects a branch node to a join node. We conservatively ensure that | 2982 // connects a branch node to a join node. We conservatively ensure that |
2949 // property by always adding an empty block on the outgoing edges of this | 2983 // property by always adding an empty block on the outgoing edges of this |
2950 // branch. | 2984 // branch. |
2951 HOptimizedGraphBuilder* builder = owner(); | 2985 HOptimizedGraphBuilder* builder = owner(); |
2952 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { | 2986 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { |
2953 builder->Bailout(kArgumentsObjectValueInATestContext); | 2987 builder->Bailout(kArgumentsObjectValueInATestContext); |
2954 } | 2988 } |
2955 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | 2989 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
2956 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | 2990 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
2957 ToBooleanStub::Types expected(condition()->to_boolean_types()); | 2991 ToBooleanStub::Types expected(condition()->to_boolean_types()); |
2958 builder->current_block()->Finish(builder->New<HBranch>( | 2992 builder->FinishCurrentBlock(builder->New<HBranch>( |
2959 value, expected, empty_true, empty_false)); | 2993 value, expected, empty_true, empty_false)); |
2960 | 2994 |
2961 empty_true->Goto(if_true(), builder->function_state()); | 2995 owner()->Goto(empty_true, if_true(), builder->function_state()); |
2962 empty_false->Goto(if_false(), builder->function_state()); | 2996 owner()->Goto(empty_false , if_false(), builder->function_state()); |
2963 builder->set_current_block(NULL); | 2997 builder->set_current_block(NULL); |
2964 } | 2998 } |
2965 | 2999 |
2966 | 3000 |
2967 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. | 3001 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. |
2968 #define CHECK_BAILOUT(call) \ | 3002 #define CHECK_BAILOUT(call) \ |
2969 do { \ | 3003 do { \ |
2970 call; \ | 3004 call; \ |
2971 if (HasStackOverflow()) return; \ | 3005 if (HasStackOverflow()) return; \ |
2972 } while (false) | 3006 } while (false) |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3069 // the body's entry block (along with some special logic for the start | 3103 // the body's entry block (along with some special logic for the start |
3070 // block in HInstruction::InsertAfter) seals the start block from | 3104 // block in HInstruction::InsertAfter) seals the start block from |
3071 // getting unwanted instructions inserted. | 3105 // getting unwanted instructions inserted. |
3072 // | 3106 // |
3073 // TODO(kmillikin): Fix this. Stop mutating the initial environment. | 3107 // TODO(kmillikin): Fix this. Stop mutating the initial environment. |
3074 // Make the Hydrogen instructions in the initial block into Hydrogen | 3108 // Make the Hydrogen instructions in the initial block into Hydrogen |
3075 // values (but not instructions), present in the initial environment and | 3109 // values (but not instructions), present in the initial environment and |
3076 // not replayed by the Lithium translation. | 3110 // not replayed by the Lithium translation. |
3077 HEnvironment* initial_env = environment()->CopyWithoutHistory(); | 3111 HEnvironment* initial_env = environment()->CopyWithoutHistory(); |
3078 HBasicBlock* body_entry = CreateBasicBlock(initial_env); | 3112 HBasicBlock* body_entry = CreateBasicBlock(initial_env); |
3079 current_block()->Goto(body_entry); | 3113 Goto(body_entry); |
3080 body_entry->SetJoinId(BailoutId::FunctionEntry()); | 3114 body_entry->SetJoinId(BailoutId::FunctionEntry()); |
3081 set_current_block(body_entry); | 3115 set_current_block(body_entry); |
3082 | 3116 |
3083 // Handle implicit declaration of the function name in named function | 3117 // Handle implicit declaration of the function name in named function |
3084 // expressions before other declarations. | 3118 // expressions before other declarations. |
3085 if (scope->is_function_scope() && scope->function() != NULL) { | 3119 if (scope->is_function_scope() && scope->function() != NULL) { |
3086 VisitVariableDeclaration(scope->function()); | 3120 VisitVariableDeclaration(scope->function()); |
3087 } | 3121 } |
3088 VisitDeclarations(scope->declarations()); | 3122 VisitDeclarations(scope->declarations()); |
3089 Add<HSimulate>(BailoutId::Declarations()); | 3123 Add<HSimulate>(BailoutId::Declarations()); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3312 ASSERT(current_block()->HasPredecessor()); | 3346 ASSERT(current_block()->HasPredecessor()); |
3313 if (stmt->scope() != NULL) { | 3347 if (stmt->scope() != NULL) { |
3314 return Bailout(kScopedBlock); | 3348 return Bailout(kScopedBlock); |
3315 } | 3349 } |
3316 BreakAndContinueInfo break_info(stmt); | 3350 BreakAndContinueInfo break_info(stmt); |
3317 { BreakAndContinueScope push(&break_info, this); | 3351 { BreakAndContinueScope push(&break_info, this); |
3318 CHECK_BAILOUT(VisitStatements(stmt->statements())); | 3352 CHECK_BAILOUT(VisitStatements(stmt->statements())); |
3319 } | 3353 } |
3320 HBasicBlock* break_block = break_info.break_block(); | 3354 HBasicBlock* break_block = break_info.break_block(); |
3321 if (break_block != NULL) { | 3355 if (break_block != NULL) { |
3322 if (current_block() != NULL) current_block()->Goto(break_block); | 3356 if (current_block() != NULL) Goto(break_block); |
3323 break_block->SetJoinId(stmt->ExitId()); | 3357 break_block->SetJoinId(stmt->ExitId()); |
3324 set_current_block(break_block); | 3358 set_current_block(break_block); |
3325 } | 3359 } |
3326 } | 3360 } |
3327 | 3361 |
3328 | 3362 |
3329 void HOptimizedGraphBuilder::VisitExpressionStatement( | 3363 void HOptimizedGraphBuilder::VisitExpressionStatement( |
3330 ExpressionStatement* stmt) { | 3364 ExpressionStatement* stmt) { |
3331 ASSERT(!HasStackOverflow()); | 3365 ASSERT(!HasStackOverflow()); |
3332 ASSERT(current_block() != NULL); | 3366 ASSERT(current_block() != NULL); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3422 | 3456 |
3423 void HOptimizedGraphBuilder::VisitContinueStatement( | 3457 void HOptimizedGraphBuilder::VisitContinueStatement( |
3424 ContinueStatement* stmt) { | 3458 ContinueStatement* stmt) { |
3425 ASSERT(!HasStackOverflow()); | 3459 ASSERT(!HasStackOverflow()); |
3426 ASSERT(current_block() != NULL); | 3460 ASSERT(current_block() != NULL); |
3427 ASSERT(current_block()->HasPredecessor()); | 3461 ASSERT(current_block()->HasPredecessor()); |
3428 int drop_extra = 0; | 3462 int drop_extra = 0; |
3429 HBasicBlock* continue_block = break_scope()->Get( | 3463 HBasicBlock* continue_block = break_scope()->Get( |
3430 stmt->target(), BreakAndContinueScope::CONTINUE, &drop_extra); | 3464 stmt->target(), BreakAndContinueScope::CONTINUE, &drop_extra); |
3431 Drop(drop_extra); | 3465 Drop(drop_extra); |
3432 current_block()->Goto(continue_block); | 3466 Goto(continue_block); |
3433 set_current_block(NULL); | 3467 set_current_block(NULL); |
3434 } | 3468 } |
3435 | 3469 |
3436 | 3470 |
3437 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 3471 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
3438 ASSERT(!HasStackOverflow()); | 3472 ASSERT(!HasStackOverflow()); |
3439 ASSERT(current_block() != NULL); | 3473 ASSERT(current_block() != NULL); |
3440 ASSERT(current_block()->HasPredecessor()); | 3474 ASSERT(current_block()->HasPredecessor()); |
3441 int drop_extra = 0; | 3475 int drop_extra = 0; |
3442 HBasicBlock* break_block = break_scope()->Get( | 3476 HBasicBlock* break_block = break_scope()->Get( |
3443 stmt->target(), BreakAndContinueScope::BREAK, &drop_extra); | 3477 stmt->target(), BreakAndContinueScope::BREAK, &drop_extra); |
3444 Drop(drop_extra); | 3478 Drop(drop_extra); |
3445 current_block()->Goto(break_block); | 3479 Goto(break_block); |
3446 set_current_block(NULL); | 3480 set_current_block(NULL); |
3447 } | 3481 } |
3448 | 3482 |
3449 | 3483 |
3450 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 3484 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
3451 ASSERT(!HasStackOverflow()); | 3485 ASSERT(!HasStackOverflow()); |
3452 ASSERT(current_block() != NULL); | 3486 ASSERT(current_block() != NULL); |
3453 ASSERT(current_block()->HasPredecessor()); | 3487 ASSERT(current_block()->HasPredecessor()); |
3454 FunctionState* state = function_state(); | 3488 FunctionState* state = function_state(); |
3455 AstContext* context = call_context(); | 3489 AstContext* context = call_context(); |
3456 if (context == NULL) { | 3490 if (context == NULL) { |
3457 // Not an inlined return, so an actual one. | 3491 // Not an inlined return, so an actual one. |
3458 CHECK_ALIVE(VisitForValue(stmt->expression())); | 3492 CHECK_ALIVE(VisitForValue(stmt->expression())); |
3459 HValue* result = environment()->Pop(); | 3493 HValue* result = environment()->Pop(); |
3460 Add<HReturn>(result); | 3494 Add<HReturn>(result); |
3461 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 3495 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
3462 // Return from an inlined construct call. In a test context the return value | 3496 // Return from an inlined construct call. In a test context the return value |
3463 // will always evaluate to true, in a value context the return value needs | 3497 // will always evaluate to true, in a value context the return value needs |
3464 // to be a JSObject. | 3498 // to be a JSObject. |
3465 if (context->IsTest()) { | 3499 if (context->IsTest()) { |
3466 TestContext* test = TestContext::cast(context); | 3500 TestContext* test = TestContext::cast(context); |
3467 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3501 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
3468 current_block()->Goto(test->if_true(), state); | 3502 Goto(test->if_true(), state); |
3469 } else if (context->IsEffect()) { | 3503 } else if (context->IsEffect()) { |
3470 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3504 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
3471 current_block()->Goto(function_return(), state); | 3505 Goto(function_return(), state); |
3472 } else { | 3506 } else { |
3473 ASSERT(context->IsValue()); | 3507 ASSERT(context->IsValue()); |
3474 CHECK_ALIVE(VisitForValue(stmt->expression())); | 3508 CHECK_ALIVE(VisitForValue(stmt->expression())); |
3475 HValue* return_value = Pop(); | 3509 HValue* return_value = Pop(); |
3476 HValue* receiver = environment()->arguments_environment()->Lookup(0); | 3510 HValue* receiver = environment()->arguments_environment()->Lookup(0); |
3477 HHasInstanceTypeAndBranch* typecheck = | 3511 HHasInstanceTypeAndBranch* typecheck = |
3478 New<HHasInstanceTypeAndBranch>(return_value, | 3512 New<HHasInstanceTypeAndBranch>(return_value, |
3479 FIRST_SPEC_OBJECT_TYPE, | 3513 FIRST_SPEC_OBJECT_TYPE, |
3480 LAST_SPEC_OBJECT_TYPE); | 3514 LAST_SPEC_OBJECT_TYPE); |
3481 HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); | 3515 HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); |
3482 HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); | 3516 HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); |
3483 typecheck->SetSuccessorAt(0, if_spec_object); | 3517 typecheck->SetSuccessorAt(0, if_spec_object); |
3484 typecheck->SetSuccessorAt(1, not_spec_object); | 3518 typecheck->SetSuccessorAt(1, not_spec_object); |
3485 current_block()->Finish(typecheck); | 3519 FinishCurrentBlock(typecheck); |
3486 if_spec_object->AddLeaveInlined(return_value, state); | 3520 AddLeaveInlined(if_spec_object, return_value, state); |
3487 not_spec_object->AddLeaveInlined(receiver, state); | 3521 AddLeaveInlined(not_spec_object, receiver, state); |
3488 } | 3522 } |
3489 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { | 3523 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { |
3490 // Return from an inlined setter call. The returned value is never used, the | 3524 // Return from an inlined setter call. The returned value is never used, the |
3491 // value of an assignment is always the value of the RHS of the assignment. | 3525 // value of an assignment is always the value of the RHS of the assignment. |
3492 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3526 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
3493 if (context->IsTest()) { | 3527 if (context->IsTest()) { |
3494 HValue* rhs = environment()->arguments_environment()->Lookup(1); | 3528 HValue* rhs = environment()->arguments_environment()->Lookup(1); |
3495 context->ReturnValue(rhs); | 3529 context->ReturnValue(rhs); |
3496 } else if (context->IsEffect()) { | 3530 } else if (context->IsEffect()) { |
3497 current_block()->Goto(function_return(), state); | 3531 Goto(function_return(), state); |
3498 } else { | 3532 } else { |
3499 ASSERT(context->IsValue()); | 3533 ASSERT(context->IsValue()); |
3500 HValue* rhs = environment()->arguments_environment()->Lookup(1); | 3534 HValue* rhs = environment()->arguments_environment()->Lookup(1); |
3501 current_block()->AddLeaveInlined(rhs, state); | 3535 AddLeaveInlined(rhs, state); |
3502 } | 3536 } |
3503 } else { | 3537 } else { |
3504 // Return from a normal inlined function. Visit the subexpression in the | 3538 // Return from a normal inlined function. Visit the subexpression in the |
3505 // expression context of the call. | 3539 // expression context of the call. |
3506 if (context->IsTest()) { | 3540 if (context->IsTest()) { |
3507 TestContext* test = TestContext::cast(context); | 3541 TestContext* test = TestContext::cast(context); |
3508 VisitForControl(stmt->expression(), test->if_true(), test->if_false()); | 3542 VisitForControl(stmt->expression(), test->if_true(), test->if_false()); |
3509 } else if (context->IsEffect()) { | 3543 } else if (context->IsEffect()) { |
3510 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3544 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
3511 current_block()->Goto(function_return(), state); | 3545 Goto(function_return(), state); |
3512 } else { | 3546 } else { |
3513 ASSERT(context->IsValue()); | 3547 ASSERT(context->IsValue()); |
3514 CHECK_ALIVE(VisitForValue(stmt->expression())); | 3548 CHECK_ALIVE(VisitForValue(stmt->expression())); |
3515 current_block()->AddLeaveInlined(Pop(), state); | 3549 AddLeaveInlined(Pop(), state); |
3516 } | 3550 } |
3517 } | 3551 } |
3518 set_current_block(NULL); | 3552 set_current_block(NULL); |
3519 } | 3553 } |
3520 | 3554 |
3521 | 3555 |
3522 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 3556 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
3523 ASSERT(!HasStackOverflow()); | 3557 ASSERT(!HasStackOverflow()); |
3524 ASSERT(current_block() != NULL); | 3558 ASSERT(current_block() != NULL); |
3525 ASSERT(current_block()->HasPredecessor()); | 3559 ASSERT(current_block()->HasPredecessor()); |
(...skipping 27 matching lines...) Expand all Loading... |
3553 | 3587 |
3554 HUnaryControlInstruction* string_check = NULL; | 3588 HUnaryControlInstruction* string_check = NULL; |
3555 HBasicBlock* not_string_block = NULL; | 3589 HBasicBlock* not_string_block = NULL; |
3556 | 3590 |
3557 // Test switch's tag value if all clauses are string literals | 3591 // Test switch's tag value if all clauses are string literals |
3558 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { | 3592 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { |
3559 first_test_block = graph()->CreateBasicBlock(); | 3593 first_test_block = graph()->CreateBasicBlock(); |
3560 not_string_block = graph()->CreateBasicBlock(); | 3594 not_string_block = graph()->CreateBasicBlock(); |
3561 string_check = New<HIsStringAndBranch>( | 3595 string_check = New<HIsStringAndBranch>( |
3562 tag_value, first_test_block, not_string_block); | 3596 tag_value, first_test_block, not_string_block); |
3563 current_block()->Finish(string_check); | 3597 FinishCurrentBlock(string_check); |
3564 | 3598 |
3565 set_current_block(first_test_block); | 3599 set_current_block(first_test_block); |
3566 } | 3600 } |
3567 | 3601 |
3568 // 1. Build all the tests, with dangling true branches | 3602 // 1. Build all the tests, with dangling true branches |
3569 BailoutId default_id = BailoutId::None(); | 3603 BailoutId default_id = BailoutId::None(); |
3570 for (int i = 0; i < clause_count; ++i) { | 3604 for (int i = 0; i < clause_count; ++i) { |
3571 CaseClause* clause = clauses->at(i); | 3605 CaseClause* clause = clauses->at(i); |
3572 if (clause->is_default()) { | 3606 if (clause->is_default()) { |
3573 default_id = clause->EntryId(); | 3607 default_id = clause->EntryId(); |
(...skipping 22 matching lines...) Expand all Loading... |
3596 Representation::Smi(), Representation::Smi()); | 3630 Representation::Smi(), Representation::Smi()); |
3597 compare = compare_; | 3631 compare = compare_; |
3598 } else { | 3632 } else { |
3599 compare = New<HStringCompareAndBranch>(tag_value, | 3633 compare = New<HStringCompareAndBranch>(tag_value, |
3600 label_value, | 3634 label_value, |
3601 Token::EQ_STRICT); | 3635 Token::EQ_STRICT); |
3602 } | 3636 } |
3603 | 3637 |
3604 compare->SetSuccessorAt(0, body_block); | 3638 compare->SetSuccessorAt(0, body_block); |
3605 compare->SetSuccessorAt(1, next_test_block); | 3639 compare->SetSuccessorAt(1, next_test_block); |
3606 current_block()->Finish(compare); | 3640 FinishCurrentBlock(compare); |
3607 | 3641 |
3608 set_current_block(next_test_block); | 3642 set_current_block(next_test_block); |
3609 } | 3643 } |
3610 | 3644 |
3611 // Save the current block to use for the default or to join with the | 3645 // Save the current block to use for the default or to join with the |
3612 // exit. | 3646 // exit. |
3613 HBasicBlock* last_block = current_block(); | 3647 HBasicBlock* last_block = current_block(); |
3614 | 3648 |
3615 if (not_string_block != NULL) { | 3649 if (not_string_block != NULL) { |
3616 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId(); | 3650 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3677 } | 3711 } |
3678 | 3712 |
3679 // Create an up-to-3-way join. Use the break block if it exists since | 3713 // Create an up-to-3-way join. Use the break block if it exists since |
3680 // it's already a join block. | 3714 // it's already a join block. |
3681 HBasicBlock* break_block = break_info.break_block(); | 3715 HBasicBlock* break_block = break_info.break_block(); |
3682 if (break_block == NULL) { | 3716 if (break_block == NULL) { |
3683 set_current_block(CreateJoin(fall_through_block, | 3717 set_current_block(CreateJoin(fall_through_block, |
3684 last_block, | 3718 last_block, |
3685 stmt->ExitId())); | 3719 stmt->ExitId())); |
3686 } else { | 3720 } else { |
3687 if (fall_through_block != NULL) fall_through_block->Goto(break_block); | 3721 if (fall_through_block != NULL) Goto(fall_through_block, break_block); |
3688 if (last_block != NULL) last_block->Goto(break_block); | 3722 if (last_block != NULL) Goto(last_block, break_block); |
3689 break_block->SetJoinId(stmt->ExitId()); | 3723 break_block->SetJoinId(stmt->ExitId()); |
3690 set_current_block(break_block); | 3724 set_current_block(break_block); |
3691 } | 3725 } |
3692 } | 3726 } |
3693 | 3727 |
3694 | 3728 |
3695 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 3729 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
3696 HBasicBlock* loop_entry, | 3730 HBasicBlock* loop_entry, |
3697 BreakAndContinueInfo* break_info) { | 3731 BreakAndContinueInfo* break_info) { |
3698 BreakAndContinueScope push(break_info, this); | 3732 BreakAndContinueScope push(break_info, this); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3883 HCompareNumericAndBranch* compare_index = | 3917 HCompareNumericAndBranch* compare_index = |
3884 New<HCompareNumericAndBranch>(index, limit, Token::LT); | 3918 New<HCompareNumericAndBranch>(index, limit, Token::LT); |
3885 compare_index->set_observed_input_representation( | 3919 compare_index->set_observed_input_representation( |
3886 Representation::Smi(), Representation::Smi()); | 3920 Representation::Smi(), Representation::Smi()); |
3887 | 3921 |
3888 HBasicBlock* loop_body = graph()->CreateBasicBlock(); | 3922 HBasicBlock* loop_body = graph()->CreateBasicBlock(); |
3889 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); | 3923 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); |
3890 | 3924 |
3891 compare_index->SetSuccessorAt(0, loop_body); | 3925 compare_index->SetSuccessorAt(0, loop_body); |
3892 compare_index->SetSuccessorAt(1, loop_successor); | 3926 compare_index->SetSuccessorAt(1, loop_successor); |
3893 current_block()->Finish(compare_index); | 3927 FinishCurrentBlock(compare_index); |
3894 | 3928 |
3895 set_current_block(loop_successor); | 3929 set_current_block(loop_successor); |
3896 Drop(5); | 3930 Drop(5); |
3897 | 3931 |
3898 set_current_block(loop_body); | 3932 set_current_block(loop_body); |
3899 | 3933 |
3900 HValue* key = Add<HLoadKeyed>( | 3934 HValue* key = Add<HLoadKeyed>( |
3901 environment()->ExpressionStackAt(2), // Enum cache. | 3935 environment()->ExpressionStackAt(2), // Enum cache. |
3902 environment()->ExpressionStackAt(0), // Iteration index. | 3936 environment()->ExpressionStackAt(0), // Iteration index. |
3903 environment()->ExpressionStackAt(0), | 3937 environment()->ExpressionStackAt(0), |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4134 } | 4168 } |
4135 } else { | 4169 } else { |
4136 HValue* context = environment()->context(); | 4170 HValue* context = environment()->context(); |
4137 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 4171 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
4138 AddInstruction(global_object); | 4172 AddInstruction(global_object); |
4139 HLoadGlobalGeneric* instr = | 4173 HLoadGlobalGeneric* instr = |
4140 new(zone()) HLoadGlobalGeneric(context, | 4174 new(zone()) HLoadGlobalGeneric(context, |
4141 global_object, | 4175 global_object, |
4142 variable->name(), | 4176 variable->name(), |
4143 ast_context()->is_for_typeof()); | 4177 ast_context()->is_for_typeof()); |
4144 instr->set_position(expr->position()); | |
4145 return ast_context()->ReturnInstruction(instr, expr->id()); | 4178 return ast_context()->ReturnInstruction(instr, expr->id()); |
4146 } | 4179 } |
4147 } | 4180 } |
4148 | 4181 |
4149 case Variable::PARAMETER: | 4182 case Variable::PARAMETER: |
4150 case Variable::LOCAL: { | 4183 case Variable::LOCAL: { |
4151 HValue* value = LookupAndMakeLive(variable); | 4184 HValue* value = LookupAndMakeLive(variable); |
4152 if (value == graph()->GetConstantHole()) { | 4185 if (value == graph()->GetConstantHole()) { |
4153 ASSERT(IsDeclaredVariableMode(variable->mode()) && | 4186 ASSERT(IsDeclaredVariableMode(variable->mode()) && |
4154 variable->mode() != VAR); | 4187 variable->mode() != VAR); |
(...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4872 Add<HPushArgument>(Pop()); | 4905 Add<HPushArgument>(Pop()); |
4873 return New<HCallConstantFunction>(info->accessor(), 1); | 4906 return New<HCallConstantFunction>(info->accessor(), 1); |
4874 } | 4907 } |
4875 | 4908 |
4876 ASSERT(info->lookup()->IsConstant()); | 4909 ASSERT(info->lookup()->IsConstant()); |
4877 return New<HConstant>(info->constant()); | 4910 return New<HConstant>(info->constant()); |
4878 } | 4911 } |
4879 | 4912 |
4880 | 4913 |
4881 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 4914 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
4882 int position, | |
4883 BailoutId ast_id, | 4915 BailoutId ast_id, |
4884 BailoutId return_id, | 4916 BailoutId return_id, |
4885 HValue* object, | 4917 HValue* object, |
4886 SmallMapList* types, | 4918 SmallMapList* types, |
4887 Handle<String> name) { | 4919 Handle<String> name) { |
4888 // Something did not match; must use a polymorphic load. | 4920 // Something did not match; must use a polymorphic load. |
4889 int count = 0; | 4921 int count = 0; |
4890 HBasicBlock* join = NULL; | 4922 HBasicBlock* join = NULL; |
4891 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 4923 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
4892 PropertyAccessInfo info(isolate(), types->at(i), name); | 4924 PropertyAccessInfo info(isolate(), types->at(i), name); |
4893 if (info.CanLoadMonomorphic()) { | 4925 if (info.CanLoadMonomorphic()) { |
4894 if (count == 0) { | 4926 if (count == 0) { |
4895 BuildCheckHeapObject(object); | 4927 BuildCheckHeapObject(object); |
4896 join = graph()->CreateBasicBlock(); | 4928 join = graph()->CreateBasicBlock(); |
4897 } | 4929 } |
4898 ++count; | 4930 ++count; |
4899 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 4931 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
4900 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 4932 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
4901 HCompareMap* compare = New<HCompareMap>( | 4933 HCompareMap* compare = New<HCompareMap>( |
4902 object, info.map(), if_true, if_false); | 4934 object, info.map(), if_true, if_false); |
4903 current_block()->Finish(compare); | 4935 FinishCurrentBlock(compare); |
4904 | 4936 |
4905 set_current_block(if_true); | 4937 set_current_block(if_true); |
4906 | 4938 |
4907 HInstruction* load = BuildLoadMonomorphic( | 4939 HInstruction* load = BuildLoadMonomorphic( |
4908 &info, object, compare, ast_id, return_id, FLAG_polymorphic_inlining); | 4940 &info, object, compare, ast_id, return_id, FLAG_polymorphic_inlining); |
4909 if (load == NULL) { | 4941 if (load == NULL) { |
4910 if (HasStackOverflow()) return; | 4942 if (HasStackOverflow()) return; |
4911 } else { | 4943 } else { |
4912 if (!load->IsLinked()) { | 4944 if (!load->IsLinked()) { |
4913 load->set_position(position); | |
4914 AddInstruction(load); | 4945 AddInstruction(load); |
4915 } | 4946 } |
4916 if (!ast_context()->IsEffect()) Push(load); | 4947 if (!ast_context()->IsEffect()) Push(load); |
4917 } | 4948 } |
4918 | 4949 |
4919 if (current_block() != NULL) current_block()->Goto(join); | 4950 if (current_block() != NULL) Goto(join); |
4920 set_current_block(if_false); | 4951 set_current_block(if_false); |
4921 } | 4952 } |
4922 } | 4953 } |
4923 | 4954 |
4924 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 4955 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
4925 // know about and do not want to handle ones we've never seen. Otherwise | 4956 // know about and do not want to handle ones we've never seen. Otherwise |
4926 // use a generic IC. | 4957 // use a generic IC. |
4927 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 4958 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
4928 // Because the deopt may be the only path in the polymorphic load, make sure | 4959 // Because the deopt may be the only path in the polymorphic load, make sure |
4929 // that the environment stack matches the depth on deopt that it otherwise | 4960 // that the environment stack matches the depth on deopt that it otherwise |
4930 // would have had after a successful load. | 4961 // would have had after a successful load. |
4931 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 4962 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
4932 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); | 4963 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); |
4933 } else { | 4964 } else { |
4934 HValue* context = environment()->context(); | 4965 HValue* context = environment()->context(); |
4935 HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name); | 4966 HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name); |
4936 load->set_position(position); | |
4937 AddInstruction(load); | 4967 AddInstruction(load); |
4938 if (!ast_context()->IsEffect()) Push(load); | 4968 if (!ast_context()->IsEffect()) Push(load); |
4939 | 4969 |
4940 if (join != NULL) { | 4970 if (join != NULL) { |
4941 current_block()->Goto(join); | 4971 Goto(join); |
4942 } else { | 4972 } else { |
4943 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 4973 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
4944 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 4974 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
4945 return; | 4975 return; |
4946 } | 4976 } |
4947 } | 4977 } |
4948 | 4978 |
4949 ASSERT(join != NULL); | 4979 ASSERT(join != NULL); |
4950 join->SetJoinId(ast_id); | 4980 join->SetJoinId(ast_id); |
4951 set_current_block(join); | 4981 set_current_block(join); |
4952 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 4982 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
4953 } | 4983 } |
4954 | 4984 |
4955 | 4985 |
4956 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( | 4986 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
4957 int position, | |
4958 BailoutId assignment_id, | 4987 BailoutId assignment_id, |
4959 HValue* object, | 4988 HValue* object, |
4960 HValue* value, | 4989 HValue* value, |
4961 SmallMapList* types, | 4990 SmallMapList* types, |
4962 Handle<String> name) { | 4991 Handle<String> name) { |
4963 // Use monomorphic store if property lookup results in the same field index | 4992 // Use monomorphic store if property lookup results in the same field index |
4964 // for all maps. Requires special map check on the set of all handled maps. | 4993 // for all maps. Requires special map check on the set of all handled maps. |
4965 if (types->length() > kMaxStorePolymorphism) return false; | 4994 if (types->length() > kMaxStorePolymorphism) return false; |
4966 | 4995 |
4967 LookupResult lookup(isolate()); | 4996 LookupResult lookup(isolate()); |
(...skipping 29 matching lines...) Expand all Loading... |
4997 | 5026 |
4998 // Everything matched; can use monomorphic store. | 5027 // Everything matched; can use monomorphic store. |
4999 BuildCheckHeapObject(object); | 5028 BuildCheckHeapObject(object); |
5000 HCheckMaps* checked_object = Add<HCheckMaps>(object, types); | 5029 HCheckMaps* checked_object = Add<HCheckMaps>(object, types); |
5001 HInstruction* store; | 5030 HInstruction* store; |
5002 CHECK_ALIVE_OR_RETURN( | 5031 CHECK_ALIVE_OR_RETURN( |
5003 store = BuildStoreNamedField( | 5032 store = BuildStoreNamedField( |
5004 checked_object, name, value, types->at(count - 1), &lookup), | 5033 checked_object, name, value, types->at(count - 1), &lookup), |
5005 true); | 5034 true); |
5006 if (!ast_context()->IsEffect()) Push(value); | 5035 if (!ast_context()->IsEffect()) Push(value); |
5007 store->set_position(position); | |
5008 AddInstruction(store); | 5036 AddInstruction(store); |
5009 Add<HSimulate>(assignment_id); | 5037 Add<HSimulate>(assignment_id); |
5010 if (!ast_context()->IsEffect()) Drop(1); | 5038 if (!ast_context()->IsEffect()) Drop(1); |
5011 ast_context()->ReturnValue(value); | 5039 ast_context()->ReturnValue(value); |
5012 return true; | 5040 return true; |
5013 } | 5041 } |
5014 | 5042 |
5015 | 5043 |
5016 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 5044 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
5017 int position, | |
5018 BailoutId assignment_id, | 5045 BailoutId assignment_id, |
5019 HValue* object, | 5046 HValue* object, |
5020 HValue* value, | 5047 HValue* value, |
5021 SmallMapList* types, | 5048 SmallMapList* types, |
5022 Handle<String> name) { | 5049 Handle<String> name) { |
5023 if (TryStorePolymorphicAsMonomorphic( | 5050 if (TryStorePolymorphicAsMonomorphic( |
5024 position, assignment_id, object, value, types, name)) { | 5051 assignment_id, object, value, types, name)) { |
5025 return; | 5052 return; |
5026 } | 5053 } |
5027 | 5054 |
5028 // TODO(ager): We should recognize when the prototype chains for different | 5055 // TODO(ager): We should recognize when the prototype chains for different |
5029 // maps are identical. In that case we can avoid repeatedly generating the | 5056 // maps are identical. In that case we can avoid repeatedly generating the |
5030 // same prototype map checks. | 5057 // same prototype map checks. |
5031 int count = 0; | 5058 int count = 0; |
5032 HBasicBlock* join = NULL; | 5059 HBasicBlock* join = NULL; |
5033 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 5060 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
5034 Handle<Map> map = types->at(i); | 5061 Handle<Map> map = types->at(i); |
5035 LookupResult lookup(isolate()); | 5062 LookupResult lookup(isolate()); |
5036 if (ComputeStoreField(map, name, &lookup)) { | 5063 if (ComputeStoreField(map, name, &lookup)) { |
5037 if (count == 0) { | 5064 if (count == 0) { |
5038 BuildCheckHeapObject(object); | 5065 BuildCheckHeapObject(object); |
5039 join = graph()->CreateBasicBlock(); | 5066 join = graph()->CreateBasicBlock(); |
5040 } | 5067 } |
5041 ++count; | 5068 ++count; |
5042 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5069 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
5043 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5070 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
5044 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false); | 5071 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false); |
5045 current_block()->Finish(compare); | 5072 FinishCurrentBlock(compare); |
5046 | 5073 |
5047 set_current_block(if_true); | 5074 set_current_block(if_true); |
5048 HInstruction* instr; | 5075 HInstruction* instr; |
5049 CHECK_ALIVE(instr = BuildStoreNamedField( | 5076 CHECK_ALIVE(instr = BuildStoreNamedField( |
5050 compare, name, value, map, &lookup)); | 5077 compare, name, value, map, &lookup)); |
5051 instr->set_position(position); | |
5052 // Goto will add the HSimulate for the store. | 5078 // Goto will add the HSimulate for the store. |
5053 AddInstruction(instr); | 5079 AddInstruction(instr); |
5054 if (!ast_context()->IsEffect()) Push(value); | 5080 if (!ast_context()->IsEffect()) Push(value); |
5055 current_block()->Goto(join); | 5081 Goto(join); |
5056 | 5082 |
5057 set_current_block(if_false); | 5083 set_current_block(if_false); |
5058 } | 5084 } |
5059 } | 5085 } |
5060 | 5086 |
5061 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 5087 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
5062 // know about and do not want to handle ones we've never seen. Otherwise | 5088 // know about and do not want to handle ones we've never seen. Otherwise |
5063 // use a generic IC. | 5089 // use a generic IC. |
5064 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 5090 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
5065 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join); | 5091 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join); |
5066 } else { | 5092 } else { |
5067 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); | 5093 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); |
5068 instr->set_position(position); | |
5069 AddInstruction(instr); | 5094 AddInstruction(instr); |
5070 | 5095 |
5071 if (join != NULL) { | 5096 if (join != NULL) { |
5072 if (!ast_context()->IsEffect()) { | 5097 if (!ast_context()->IsEffect()) { |
5073 Push(value); | 5098 Push(value); |
5074 } | 5099 } |
5075 current_block()->Goto(join); | 5100 Goto(join); |
5076 } else { | 5101 } else { |
5077 // The HSimulate for the store should not see the stored value in | 5102 // The HSimulate for the store should not see the stored value in |
5078 // effect contexts (it is not materialized at expr->id() in the | 5103 // effect contexts (it is not materialized at expr->id() in the |
5079 // unoptimized code). | 5104 // unoptimized code). |
5080 if (instr->HasObservableSideEffects()) { | 5105 if (instr->HasObservableSideEffects()) { |
5081 if (ast_context()->IsEffect()) { | 5106 if (ast_context()->IsEffect()) { |
5082 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); | 5107 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
5083 } else { | 5108 } else { |
5084 Push(value); | 5109 Push(value); |
5085 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); | 5110 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5120 BailoutId return_id, | 5145 BailoutId return_id, |
5121 bool is_uninitialized) { | 5146 bool is_uninitialized) { |
5122 HValue* value = environment()->ExpressionStackAt(0); | 5147 HValue* value = environment()->ExpressionStackAt(0); |
5123 | 5148 |
5124 if (!prop->key()->IsPropertyName()) { | 5149 if (!prop->key()->IsPropertyName()) { |
5125 // Keyed store. | 5150 // Keyed store. |
5126 HValue* key = environment()->ExpressionStackAt(1); | 5151 HValue* key = environment()->ExpressionStackAt(1); |
5127 HValue* object = environment()->ExpressionStackAt(2); | 5152 HValue* object = environment()->ExpressionStackAt(2); |
5128 bool has_side_effects = false; | 5153 bool has_side_effects = false; |
5129 HandleKeyedElementAccess(object, key, value, expr, return_id, | 5154 HandleKeyedElementAccess(object, key, value, expr, return_id, |
5130 expr->position(), | |
5131 true, // is_store | 5155 true, // is_store |
5132 &has_side_effects); | 5156 &has_side_effects); |
5133 Drop(3); | 5157 Drop(3); |
5134 Push(value); | 5158 Push(value); |
5135 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); | 5159 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); |
5136 return ast_context()->ReturnValue(Pop()); | 5160 return ast_context()->ReturnValue(Pop()); |
5137 } | 5161 } |
5138 | 5162 |
5139 // Named store. | 5163 // Named store. |
5140 HValue* object = environment()->ExpressionStackAt(1); | 5164 HValue* object = environment()->ExpressionStackAt(1); |
(...skipping 28 matching lines...) Expand all Loading... |
5169 instr = New<HCallConstantFunction>(setter, 2); | 5193 instr = New<HCallConstantFunction>(setter, 2); |
5170 } else { | 5194 } else { |
5171 Drop(2); | 5195 Drop(2); |
5172 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | 5196 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
5173 name, | 5197 name, |
5174 value, | 5198 value, |
5175 map)); | 5199 map)); |
5176 } | 5200 } |
5177 } else if (types != NULL && types->length() > 1) { | 5201 } else if (types != NULL && types->length() > 1) { |
5178 Drop(2); | 5202 Drop(2); |
5179 return HandlePolymorphicStoreNamedField( | 5203 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name); |
5180 expr->position(), ast_id, object, value, types, name); | |
5181 } else { | 5204 } else { |
5182 Drop(2); | 5205 Drop(2); |
5183 instr = BuildStoreNamedGeneric(object, name, value); | 5206 instr = BuildStoreNamedGeneric(object, name, value); |
5184 } | 5207 } |
5185 | 5208 |
5186 if (!ast_context()->IsEffect()) Push(value); | 5209 if (!ast_context()->IsEffect()) Push(value); |
5187 instr->set_position(expr->position()); | |
5188 AddInstruction(instr); | 5210 AddInstruction(instr); |
5189 if (instr->HasObservableSideEffects()) { | 5211 if (instr->HasObservableSideEffects()) { |
5190 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5212 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
5191 } | 5213 } |
5192 if (!ast_context()->IsEffect()) Drop(1); | 5214 if (!ast_context()->IsEffect()) Drop(1); |
5193 return ast_context()->ReturnValue(value); | 5215 return ast_context()->ReturnValue(value); |
5194 } | 5216 } |
5195 | 5217 |
5196 | 5218 |
5197 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 5219 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
5198 Property* prop = expr->target()->AsProperty(); | 5220 Property* prop = expr->target()->AsProperty(); |
5199 ASSERT(prop != NULL); | 5221 ASSERT(prop != NULL); |
5200 CHECK_ALIVE(VisitForValue(prop->obj())); | 5222 CHECK_ALIVE(VisitForValue(prop->obj())); |
5201 if (!prop->key()->IsPropertyName()) { | 5223 if (!prop->key()->IsPropertyName()) { |
5202 CHECK_ALIVE(VisitForValue(prop->key())); | 5224 CHECK_ALIVE(VisitForValue(prop->key())); |
5203 } | 5225 } |
5204 CHECK_ALIVE(VisitForValue(expr->value())); | 5226 CHECK_ALIVE(VisitForValue(expr->value())); |
5205 BuildStore(expr, prop, expr->id(), | 5227 BuildStore(expr, prop, expr->id(), |
5206 expr->AssignmentId(), expr->IsUninitialized()); | 5228 expr->AssignmentId(), expr->IsUninitialized()); |
5207 } | 5229 } |
5208 | 5230 |
5209 | 5231 |
5210 // Because not every expression has a position and there is not common | 5232 // Because not every expression has a position and there is not common |
5211 // superclass of Assignment and CountOperation, we cannot just pass the | 5233 // superclass of Assignment and CountOperation, we cannot just pass the |
5212 // owning expression instead of position and ast_id separately. | 5234 // owning expression instead of position and ast_id separately. |
5213 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 5235 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
5214 Variable* var, | 5236 Variable* var, |
5215 HValue* value, | 5237 HValue* value, |
5216 int position, | |
5217 BailoutId ast_id) { | 5238 BailoutId ast_id) { |
5218 LookupResult lookup(isolate()); | 5239 LookupResult lookup(isolate()); |
5219 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 5240 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
5220 if (type == kUseCell) { | 5241 if (type == kUseCell) { |
5221 Handle<GlobalObject> global(current_info()->global_object()); | 5242 Handle<GlobalObject> global(current_info()->global_object()); |
5222 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 5243 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
5223 if (cell->type()->IsConstant()) { | 5244 if (cell->type()->IsConstant()) { |
5224 IfBuilder builder(this); | 5245 IfBuilder builder(this); |
5225 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); | 5246 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); |
5226 if (cell->type()->AsConstant()->IsNumber()) { | 5247 if (cell->type()->AsConstant()->IsNumber()) { |
5227 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); | 5248 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); |
5228 } else { | 5249 } else { |
5229 builder.If<HCompareObjectEqAndBranch>(value, constant); | 5250 builder.If<HCompareObjectEqAndBranch>(value, constant); |
5230 } | 5251 } |
5231 builder.Then(); | 5252 builder.Then(); |
5232 builder.Else(); | 5253 builder.Else(); |
5233 Add<HDeoptimize>("Constant global variable assignment", | 5254 Add<HDeoptimize>("Constant global variable assignment", |
5234 Deoptimizer::EAGER); | 5255 Deoptimizer::EAGER); |
5235 builder.End(); | 5256 builder.End(); |
5236 } | 5257 } |
5237 HInstruction* instr = | 5258 HInstruction* instr = |
5238 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | 5259 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
5239 instr->set_position(position); | |
5240 if (instr->HasObservableSideEffects()) { | 5260 if (instr->HasObservableSideEffects()) { |
5241 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5261 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
5242 } | 5262 } |
5243 } else { | 5263 } else { |
5244 HGlobalObject* global_object = Add<HGlobalObject>(); | 5264 HGlobalObject* global_object = Add<HGlobalObject>(); |
5245 HStoreGlobalGeneric* instr = | 5265 HStoreGlobalGeneric* instr = |
5246 Add<HStoreGlobalGeneric>(global_object, var->name(), | 5266 Add<HStoreGlobalGeneric>(global_object, var->name(), |
5247 value, function_strict_mode_flag()); | 5267 value, function_strict_mode_flag()); |
5248 instr->set_position(position); | 5268 USE(instr); |
5249 ASSERT(instr->HasObservableSideEffects()); | 5269 ASSERT(instr->HasObservableSideEffects()); |
5250 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5270 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
5251 } | 5271 } |
5252 } | 5272 } |
5253 | 5273 |
5254 | 5274 |
5255 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5275 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
5256 Expression* target = expr->target(); | 5276 Expression* target = expr->target(); |
5257 VariableProxy* proxy = target->AsVariableProxy(); | 5277 VariableProxy* proxy = target->AsVariableProxy(); |
5258 Property* prop = target->AsProperty(); | 5278 Property* prop = target->AsProperty(); |
5259 ASSERT(proxy == NULL || prop == NULL); | 5279 ASSERT(proxy == NULL || prop == NULL); |
5260 | 5280 |
5261 // We have a second position recorded in the FullCodeGenerator to have | 5281 // We have a second position recorded in the FullCodeGenerator to have |
5262 // type feedback for the binary operation. | 5282 // type feedback for the binary operation. |
5263 BinaryOperation* operation = expr->binary_operation(); | 5283 BinaryOperation* operation = expr->binary_operation(); |
5264 | 5284 |
5265 if (proxy != NULL) { | 5285 if (proxy != NULL) { |
5266 Variable* var = proxy->var(); | 5286 Variable* var = proxy->var(); |
5267 if (var->mode() == LET) { | 5287 if (var->mode() == LET) { |
5268 return Bailout(kUnsupportedLetCompoundAssignment); | 5288 return Bailout(kUnsupportedLetCompoundAssignment); |
5269 } | 5289 } |
5270 | 5290 |
5271 CHECK_ALIVE(VisitForValue(operation)); | 5291 CHECK_ALIVE(VisitForValue(operation)); |
5272 | 5292 |
5273 switch (var->location()) { | 5293 switch (var->location()) { |
5274 case Variable::UNALLOCATED: | 5294 case Variable::UNALLOCATED: |
5275 HandleGlobalVariableAssignment(var, | 5295 HandleGlobalVariableAssignment(var, |
5276 Top(), | 5296 Top(), |
5277 expr->position(), | |
5278 expr->AssignmentId()); | 5297 expr->AssignmentId()); |
5279 break; | 5298 break; |
5280 | 5299 |
5281 case Variable::PARAMETER: | 5300 case Variable::PARAMETER: |
5282 case Variable::LOCAL: | 5301 case Variable::LOCAL: |
5283 if (var->mode() == CONST) { | 5302 if (var->mode() == CONST) { |
5284 return Bailout(kUnsupportedConstCompoundAssignment); | 5303 return Bailout(kUnsupportedConstCompoundAssignment); |
5285 } | 5304 } |
5286 BindIfLive(var, Top()); | 5305 BindIfLive(var, Top()); |
5287 break; | 5306 break; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5335 } else if (prop != NULL) { | 5354 } else if (prop != NULL) { |
5336 CHECK_ALIVE(VisitForValue(prop->obj())); | 5355 CHECK_ALIVE(VisitForValue(prop->obj())); |
5337 HValue* object = Top(); | 5356 HValue* object = Top(); |
5338 HValue* key = NULL; | 5357 HValue* key = NULL; |
5339 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || | 5358 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || |
5340 prop->IsStringAccess()) { | 5359 prop->IsStringAccess()) { |
5341 CHECK_ALIVE(VisitForValue(prop->key())); | 5360 CHECK_ALIVE(VisitForValue(prop->key())); |
5342 key = Top(); | 5361 key = Top(); |
5343 } | 5362 } |
5344 | 5363 |
5345 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); | 5364 CHECK_ALIVE(PushLoad(prop, object, key)); |
5346 | 5365 |
5347 CHECK_ALIVE(VisitForValue(expr->value())); | 5366 CHECK_ALIVE(VisitForValue(expr->value())); |
5348 HValue* right = Pop(); | 5367 HValue* right = Pop(); |
5349 HValue* left = Pop(); | 5368 HValue* left = Pop(); |
5350 | 5369 |
5351 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5370 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
5352 PushAndAdd(instr); | 5371 PushAndAdd(instr); |
5353 if (instr->HasObservableSideEffects()) { | 5372 if (instr->HasObservableSideEffects()) { |
5354 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); | 5373 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
5355 } | 5374 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5398 } | 5417 } |
5399 | 5418 |
5400 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments); | 5419 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments); |
5401 | 5420 |
5402 // Handle the assignment. | 5421 // Handle the assignment. |
5403 switch (var->location()) { | 5422 switch (var->location()) { |
5404 case Variable::UNALLOCATED: | 5423 case Variable::UNALLOCATED: |
5405 CHECK_ALIVE(VisitForValue(expr->value())); | 5424 CHECK_ALIVE(VisitForValue(expr->value())); |
5406 HandleGlobalVariableAssignment(var, | 5425 HandleGlobalVariableAssignment(var, |
5407 Top(), | 5426 Top(), |
5408 expr->position(), | |
5409 expr->AssignmentId()); | 5427 expr->AssignmentId()); |
5410 return ast_context()->ReturnValue(Pop()); | 5428 return ast_context()->ReturnValue(Pop()); |
5411 | 5429 |
5412 case Variable::PARAMETER: | 5430 case Variable::PARAMETER: |
5413 case Variable::LOCAL: { | 5431 case Variable::LOCAL: { |
5414 // Perform an initialization check for let declared variables | 5432 // Perform an initialization check for let declared variables |
5415 // or parameters. | 5433 // or parameters. |
5416 if (var->mode() == LET && expr->op() == Token::ASSIGN) { | 5434 if (var->mode() == LET && expr->op() == Token::ASSIGN) { |
5417 HValue* env_value = environment()->Lookup(var); | 5435 HValue* env_value = environment()->Lookup(var); |
5418 if (env_value == graph()->GetConstantHole()) { | 5436 if (env_value == graph()->GetConstantHole()) { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5497 ASSERT(!HasStackOverflow()); | 5515 ASSERT(!HasStackOverflow()); |
5498 ASSERT(current_block() != NULL); | 5516 ASSERT(current_block() != NULL); |
5499 ASSERT(current_block()->HasPredecessor()); | 5517 ASSERT(current_block()->HasPredecessor()); |
5500 // We don't optimize functions with invalid left-hand sides in | 5518 // We don't optimize functions with invalid left-hand sides in |
5501 // assignments, count operations, or for-in. Consequently throw can | 5519 // assignments, count operations, or for-in. Consequently throw can |
5502 // currently only occur in an effect context. | 5520 // currently only occur in an effect context. |
5503 ASSERT(ast_context()->IsEffect()); | 5521 ASSERT(ast_context()->IsEffect()); |
5504 CHECK_ALIVE(VisitForValue(expr->exception())); | 5522 CHECK_ALIVE(VisitForValue(expr->exception())); |
5505 | 5523 |
5506 HValue* value = environment()->Pop(); | 5524 HValue* value = environment()->Pop(); |
5507 HThrow* instr = Add<HThrow>(value); | 5525 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
5508 instr->set_position(expr->position()); | 5526 Add<HThrow>(value); |
5509 Add<HSimulate>(expr->id()); | 5527 Add<HSimulate>(expr->id()); |
5510 | 5528 |
5511 // If the throw definitely exits the function, we can finish with a dummy | 5529 // If the throw definitely exits the function, we can finish with a dummy |
5512 // control flow at this point. This is not the case if the throw is inside | 5530 // control flow at this point. This is not the case if the throw is inside |
5513 // an inlined function which may be replaced. | 5531 // an inlined function which may be replaced. |
5514 if (call_context() == NULL) { | 5532 if (call_context() == NULL) { |
5515 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5533 FinishExitCurrentBlock(new(zone()) HAbnormalExit); |
5516 set_current_block(NULL); | |
5517 } | 5534 } |
5518 } | 5535 } |
5519 | 5536 |
5520 | 5537 |
5521 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 5538 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
5522 HObjectAccess access) { | 5539 HObjectAccess access) { |
5523 if (FLAG_track_double_fields && access.representation().IsDouble()) { | 5540 if (FLAG_track_double_fields && access.representation().IsDouble()) { |
5524 // load the heap number | 5541 // load the heap number |
5525 HLoadNamedField* heap_number = Add<HLoadNamedField>( | 5542 HLoadNamedField* heap_number = Add<HLoadNamedField>( |
5526 object, access.WithRepresentation(Representation::Tagged())); | 5543 object, access.WithRepresentation(Representation::Tagged())); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5670 return instr; | 5687 return instr; |
5671 } | 5688 } |
5672 | 5689 |
5673 | 5690 |
5674 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 5691 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
5675 HValue* object, | 5692 HValue* object, |
5676 HValue* key, | 5693 HValue* key, |
5677 HValue* val, | 5694 HValue* val, |
5678 SmallMapList* maps, | 5695 SmallMapList* maps, |
5679 BailoutId ast_id, | 5696 BailoutId ast_id, |
5680 int position, | |
5681 bool is_store, | 5697 bool is_store, |
5682 KeyedAccessStoreMode store_mode, | 5698 KeyedAccessStoreMode store_mode, |
5683 bool* has_side_effects) { | 5699 bool* has_side_effects) { |
5684 *has_side_effects = false; | 5700 *has_side_effects = false; |
5685 BuildCheckHeapObject(object); | 5701 BuildCheckHeapObject(object); |
5686 | 5702 |
5687 if (!is_store) { | 5703 if (!is_store) { |
5688 HInstruction* consolidated_load = | 5704 HInstruction* consolidated_load = |
5689 TryBuildConsolidatedElementLoad(object, key, val, maps); | 5705 TryBuildConsolidatedElementLoad(object, key, val, maps); |
5690 if (consolidated_load != NULL) { | 5706 if (consolidated_load != NULL) { |
5691 *has_side_effects |= consolidated_load->HasObservableSideEffects(); | 5707 *has_side_effects |= consolidated_load->HasObservableSideEffects(); |
5692 if (position != RelocInfo::kNoPosition) { | |
5693 consolidated_load->set_position(position); | |
5694 } | |
5695 return consolidated_load; | 5708 return consolidated_load; |
5696 } | 5709 } |
5697 } | 5710 } |
5698 | 5711 |
5699 // Elements_kind transition support. | 5712 // Elements_kind transition support. |
5700 MapHandleList transition_target(maps->length()); | 5713 MapHandleList transition_target(maps->length()); |
5701 // Collect possible transition targets. | 5714 // Collect possible transition targets. |
5702 MapHandleList possible_transitioned_maps(maps->length()); | 5715 MapHandleList possible_transitioned_maps(maps->length()); |
5703 for (int i = 0; i < maps->length(); ++i) { | 5716 for (int i = 0; i < maps->length(); ++i) { |
5704 Handle<Map> map = maps->at(i); | 5717 Handle<Map> map = maps->at(i); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5741 if (untransitionable_map->has_slow_elements_kind() || | 5754 if (untransitionable_map->has_slow_elements_kind() || |
5742 !untransitionable_map->IsJSObjectMap()) { | 5755 !untransitionable_map->IsJSObjectMap()) { |
5743 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) | 5756 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) |
5744 : BuildLoadKeyedGeneric(object, key)); | 5757 : BuildLoadKeyedGeneric(object, key)); |
5745 } else { | 5758 } else { |
5746 instr = BuildMonomorphicElementAccess( | 5759 instr = BuildMonomorphicElementAccess( |
5747 object, key, val, transition, untransitionable_map, is_store, | 5760 object, key, val, transition, untransitionable_map, is_store, |
5748 store_mode); | 5761 store_mode); |
5749 } | 5762 } |
5750 *has_side_effects |= instr->HasObservableSideEffects(); | 5763 *has_side_effects |= instr->HasObservableSideEffects(); |
5751 if (position != RelocInfo::kNoPosition) instr->set_position(position); | |
5752 return is_store ? NULL : instr; | 5764 return is_store ? NULL : instr; |
5753 } | 5765 } |
5754 | 5766 |
5755 HBasicBlock* join = graph()->CreateBasicBlock(); | 5767 HBasicBlock* join = graph()->CreateBasicBlock(); |
5756 | 5768 |
5757 for (int i = 0; i < untransitionable_maps.length(); ++i) { | 5769 for (int i = 0; i < untransitionable_maps.length(); ++i) { |
5758 Handle<Map> map = untransitionable_maps[i]; | 5770 Handle<Map> map = untransitionable_maps[i]; |
5759 if (!map->IsJSObjectMap()) continue; | 5771 if (!map->IsJSObjectMap()) continue; |
5760 ElementsKind elements_kind = map->elements_kind(); | 5772 ElementsKind elements_kind = map->elements_kind(); |
5761 HBasicBlock* this_map = graph()->CreateBasicBlock(); | 5773 HBasicBlock* this_map = graph()->CreateBasicBlock(); |
5762 HBasicBlock* other_map = graph()->CreateBasicBlock(); | 5774 HBasicBlock* other_map = graph()->CreateBasicBlock(); |
5763 HCompareMap* mapcompare = | 5775 HCompareMap* mapcompare = |
5764 New<HCompareMap>(object, map, this_map, other_map); | 5776 New<HCompareMap>(object, map, this_map, other_map); |
5765 current_block()->Finish(mapcompare); | 5777 FinishCurrentBlock(mapcompare); |
5766 | 5778 |
5767 set_current_block(this_map); | 5779 set_current_block(this_map); |
5768 HInstruction* access = NULL; | 5780 HInstruction* access = NULL; |
5769 if (IsDictionaryElementsKind(elements_kind)) { | 5781 if (IsDictionaryElementsKind(elements_kind)) { |
5770 access = is_store | 5782 access = is_store |
5771 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val)) | 5783 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val)) |
5772 : AddInstruction(BuildLoadKeyedGeneric(object, key)); | 5784 : AddInstruction(BuildLoadKeyedGeneric(object, key)); |
5773 } else { | 5785 } else { |
5774 ASSERT(IsFastElementsKind(elements_kind) || | 5786 ASSERT(IsFastElementsKind(elements_kind) || |
5775 IsExternalArrayElementsKind(elements_kind)); | 5787 IsExternalArrayElementsKind(elements_kind)); |
5776 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); | 5788 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
5777 // Happily, mapcompare is a checked object. | 5789 // Happily, mapcompare is a checked object. |
5778 access = BuildUncheckedMonomorphicElementAccess( | 5790 access = BuildUncheckedMonomorphicElementAccess( |
5779 mapcompare, key, val, | 5791 mapcompare, key, val, |
5780 map->instance_type() == JS_ARRAY_TYPE, | 5792 map->instance_type() == JS_ARRAY_TYPE, |
5781 elements_kind, is_store, | 5793 elements_kind, is_store, |
5782 load_mode, | 5794 load_mode, |
5783 store_mode); | 5795 store_mode); |
5784 } | 5796 } |
5785 *has_side_effects |= access->HasObservableSideEffects(); | 5797 *has_side_effects |= access->HasObservableSideEffects(); |
5786 // The caller will use has_side_effects and add a correct Simulate. | 5798 // The caller will use has_side_effects and add a correct Simulate. |
5787 access->SetFlag(HValue::kHasNoObservableSideEffects); | 5799 access->SetFlag(HValue::kHasNoObservableSideEffects); |
5788 if (position != RelocInfo::kNoPosition) access->set_position(position); | |
5789 if (!is_store) { | 5800 if (!is_store) { |
5790 Push(access); | 5801 Push(access); |
5791 } | 5802 } |
5792 NoObservableSideEffectsScope scope(this); | 5803 NoObservableSideEffectsScope scope(this); |
5793 current_block()->GotoNoSimulate(join); | 5804 GotoNoSimulate(join); |
5794 set_current_block(other_map); | 5805 set_current_block(other_map); |
5795 } | 5806 } |
5796 | 5807 |
5797 // Deopt if none of the cases matched. | 5808 // Deopt if none of the cases matched. |
5798 NoObservableSideEffectsScope scope(this); | 5809 NoObservableSideEffectsScope scope(this); |
5799 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access", | 5810 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access", |
5800 join); | 5811 join); |
5801 set_current_block(join); | 5812 set_current_block(join); |
5802 return is_store ? NULL : Pop(); | 5813 return is_store ? NULL : Pop(); |
5803 } | 5814 } |
5804 | 5815 |
5805 | 5816 |
5806 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 5817 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
5807 HValue* obj, | 5818 HValue* obj, |
5808 HValue* key, | 5819 HValue* key, |
5809 HValue* val, | 5820 HValue* val, |
5810 Expression* expr, | 5821 Expression* expr, |
5811 BailoutId ast_id, | 5822 BailoutId ast_id, |
5812 int position, | |
5813 bool is_store, | 5823 bool is_store, |
5814 bool* has_side_effects) { | 5824 bool* has_side_effects) { |
5815 ASSERT(!expr->IsPropertyName()); | 5825 ASSERT(!expr->IsPropertyName()); |
5816 HInstruction* instr = NULL; | 5826 HInstruction* instr = NULL; |
5817 | 5827 |
5818 SmallMapList* types; | 5828 SmallMapList* types; |
5819 bool monomorphic = ComputeReceiverTypes(expr, obj, &types); | 5829 bool monomorphic = ComputeReceiverTypes(expr, obj, &types); |
5820 | 5830 |
5821 if (monomorphic) { | 5831 if (monomorphic) { |
5822 Handle<Map> map = types->first(); | 5832 Handle<Map> map = types->first(); |
5823 if (map->has_slow_elements_kind()) { | 5833 if (map->has_slow_elements_kind()) { |
5824 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 5834 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
5825 : BuildLoadKeyedGeneric(obj, key); | 5835 : BuildLoadKeyedGeneric(obj, key); |
5826 AddInstruction(instr); | 5836 AddInstruction(instr); |
5827 } else { | 5837 } else { |
5828 BuildCheckHeapObject(obj); | 5838 BuildCheckHeapObject(obj); |
5829 instr = BuildMonomorphicElementAccess( | 5839 instr = BuildMonomorphicElementAccess( |
5830 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | 5840 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); |
5831 } | 5841 } |
5832 } else if (types != NULL && !types->is_empty()) { | 5842 } else if (types != NULL && !types->is_empty()) { |
5833 return HandlePolymorphicElementAccess( | 5843 return HandlePolymorphicElementAccess( |
5834 obj, key, val, types, ast_id, position, is_store, | 5844 obj, key, val, types, ast_id, is_store, |
5835 expr->GetStoreMode(), has_side_effects); | 5845 expr->GetStoreMode(), has_side_effects); |
5836 } else { | 5846 } else { |
5837 if (is_store) { | 5847 if (is_store) { |
5838 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { | 5848 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { |
5839 Add<HDeoptimize>("Insufficient type feedback for keyed store", | 5849 Add<HDeoptimize>("Insufficient type feedback for keyed store", |
5840 Deoptimizer::SOFT); | 5850 Deoptimizer::SOFT); |
5841 } | 5851 } |
5842 instr = BuildStoreKeyedGeneric(obj, key, val); | 5852 instr = BuildStoreKeyedGeneric(obj, key, val); |
5843 } else { | 5853 } else { |
5844 if (expr->AsProperty()->IsUninitialized()) { | 5854 if (expr->AsProperty()->IsUninitialized()) { |
5845 Add<HDeoptimize>("Insufficient type feedback for keyed load", | 5855 Add<HDeoptimize>("Insufficient type feedback for keyed load", |
5846 Deoptimizer::SOFT); | 5856 Deoptimizer::SOFT); |
5847 } | 5857 } |
5848 instr = BuildLoadKeyedGeneric(obj, key); | 5858 instr = BuildLoadKeyedGeneric(obj, key); |
5849 } | 5859 } |
5850 AddInstruction(instr); | 5860 AddInstruction(instr); |
5851 } | 5861 } |
5852 if (position != RelocInfo::kNoPosition) instr->set_position(position); | |
5853 *has_side_effects = instr->HasObservableSideEffects(); | 5862 *has_side_effects = instr->HasObservableSideEffects(); |
5854 return instr; | 5863 return instr; |
5855 } | 5864 } |
5856 | 5865 |
5857 | 5866 |
5858 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( | 5867 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( |
5859 HValue* object, | 5868 HValue* object, |
5860 HValue* key, | 5869 HValue* key, |
5861 HValue* value) { | 5870 HValue* value) { |
5862 HValue* context = environment()->context(); | 5871 HValue* context = environment()->context(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5941 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 5950 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
5942 } | 5951 } |
5943 } | 5952 } |
5944 ast_context()->ReturnInstruction(result, expr->id()); | 5953 ast_context()->ReturnInstruction(result, expr->id()); |
5945 return true; | 5954 return true; |
5946 } | 5955 } |
5947 | 5956 |
5948 | 5957 |
5949 void HOptimizedGraphBuilder::PushLoad(Property* expr, | 5958 void HOptimizedGraphBuilder::PushLoad(Property* expr, |
5950 HValue* object, | 5959 HValue* object, |
5951 HValue* key, | 5960 HValue* key) { |
5952 int position) { | |
5953 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 5961 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
5954 Push(object); | 5962 Push(object); |
5955 if (key != NULL) Push(key); | 5963 if (key != NULL) Push(key); |
5956 BuildLoad(expr, position, expr->LoadId()); | 5964 BuildLoad(expr, expr->LoadId()); |
5957 } | 5965 } |
5958 | 5966 |
5959 | 5967 |
5960 static bool AreStringTypes(SmallMapList* types) { | 5968 static bool AreStringTypes(SmallMapList* types) { |
5961 for (int i = 0; i < types->length(); i++) { | 5969 for (int i = 0; i < types->length(); i++) { |
5962 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; | 5970 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; |
5963 } | 5971 } |
5964 return true; | 5972 return true; |
5965 } | 5973 } |
5966 | 5974 |
5967 | 5975 |
5968 void HOptimizedGraphBuilder::BuildLoad(Property* expr, | 5976 void HOptimizedGraphBuilder::BuildLoad(Property* expr, |
5969 int position, | |
5970 BailoutId ast_id) { | 5977 BailoutId ast_id) { |
5971 HInstruction* instr = NULL; | 5978 HInstruction* instr = NULL; |
5972 if (expr->IsStringAccess()) { | 5979 if (expr->IsStringAccess()) { |
5973 HValue* index = Pop(); | 5980 HValue* index = Pop(); |
5974 HValue* string = Pop(); | 5981 HValue* string = Pop(); |
5975 HValue* context = environment()->context(); | 5982 HValue* context = environment()->context(); |
5976 HInstruction* char_code = | 5983 HInstruction* char_code = |
5977 BuildStringCharCodeAt(string, index); | 5984 BuildStringCharCodeAt(string, index); |
5978 AddInstruction(char_code); | 5985 AddInstruction(char_code); |
5979 instr = HStringCharFromCode::New(zone(), context, char_code); | 5986 instr = HStringCharFromCode::New(zone(), context, char_code); |
5980 | 5987 |
5981 } else if (expr->IsFunctionPrototype()) { | 5988 } else if (expr->IsFunctionPrototype()) { |
5982 HValue* function = Pop(); | 5989 HValue* function = Pop(); |
5983 BuildCheckHeapObject(function); | 5990 BuildCheckHeapObject(function); |
5984 instr = new(zone()) HLoadFunctionPrototype(function); | 5991 instr = new(zone()) HLoadFunctionPrototype(function); |
5985 | 5992 |
5986 } else if (expr->key()->IsPropertyName()) { | 5993 } else if (expr->key()->IsPropertyName()) { |
5987 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 5994 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
5988 HValue* object = Pop(); | 5995 HValue* object = Pop(); |
5989 | 5996 |
5990 SmallMapList* types; | 5997 SmallMapList* types; |
5991 ComputeReceiverTypes(expr, object, &types); | 5998 ComputeReceiverTypes(expr, object, &types); |
5992 ASSERT(types != NULL); | 5999 ASSERT(types != NULL); |
5993 | 6000 |
5994 if (types->length() > 0) { | 6001 if (types->length() > 0) { |
5995 PropertyAccessInfo info(isolate(), types->first(), name); | 6002 PropertyAccessInfo info(isolate(), types->first(), name); |
5996 if (!info.CanLoadAsMonomorphic(types)) { | 6003 if (!info.CanLoadAsMonomorphic(types)) { |
5997 return HandlePolymorphicLoadNamedField( | 6004 return HandlePolymorphicLoadNamedField( |
5998 position, ast_id, expr->LoadId(), object, types, name); | 6005 ast_id, expr->LoadId(), object, types, name); |
5999 } | 6006 } |
6000 | 6007 |
6001 BuildCheckHeapObject(object); | 6008 BuildCheckHeapObject(object); |
6002 HInstruction* checked_object; | 6009 HInstruction* checked_object; |
6003 if (AreStringTypes(types)) { | 6010 if (AreStringTypes(types)) { |
6004 checked_object = | 6011 checked_object = |
6005 AddInstruction(HCheckInstanceType::NewIsString(object, zone())); | 6012 AddInstruction(HCheckInstanceType::NewIsString(object, zone())); |
6006 } else { | 6013 } else { |
6007 checked_object = Add<HCheckMaps>(object, types); | 6014 checked_object = Add<HCheckMaps>(object, types); |
6008 } | 6015 } |
6009 instr = BuildLoadMonomorphic( | 6016 instr = BuildLoadMonomorphic( |
6010 &info, object, checked_object, ast_id, expr->LoadId()); | 6017 &info, object, checked_object, ast_id, expr->LoadId()); |
6011 if (instr == NULL) return; | 6018 if (instr == NULL) return; |
6012 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); | 6019 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); |
6013 } else { | 6020 } else { |
6014 instr = BuildLoadNamedGeneric(object, name, expr); | 6021 instr = BuildLoadNamedGeneric(object, name, expr); |
6015 } | 6022 } |
6016 | 6023 |
6017 } else { | 6024 } else { |
6018 HValue* key = Pop(); | 6025 HValue* key = Pop(); |
6019 HValue* obj = Pop(); | 6026 HValue* obj = Pop(); |
6020 | 6027 |
6021 bool has_side_effects = false; | 6028 bool has_side_effects = false; |
6022 HValue* load = HandleKeyedElementAccess( | 6029 HValue* load = HandleKeyedElementAccess( |
6023 obj, key, NULL, expr, ast_id, position, | 6030 obj, key, NULL, expr, ast_id, |
6024 false, // is_store | 6031 false, // is_store |
6025 &has_side_effects); | 6032 &has_side_effects); |
6026 if (has_side_effects) { | 6033 if (has_side_effects) { |
6027 if (ast_context()->IsEffect()) { | 6034 if (ast_context()->IsEffect()) { |
6028 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6035 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6029 } else { | 6036 } else { |
6030 Push(load); | 6037 Push(load); |
6031 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6038 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6032 Drop(1); | 6039 Drop(1); |
6033 } | 6040 } |
6034 } | 6041 } |
6035 return ast_context()->ReturnValue(load); | 6042 return ast_context()->ReturnValue(load); |
6036 } | 6043 } |
6037 instr->set_position(position); | |
6038 return ast_context()->ReturnInstruction(instr, ast_id); | 6044 return ast_context()->ReturnInstruction(instr, ast_id); |
6039 } | 6045 } |
6040 | 6046 |
6041 | 6047 |
6042 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 6048 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
6043 ASSERT(!HasStackOverflow()); | 6049 ASSERT(!HasStackOverflow()); |
6044 ASSERT(current_block() != NULL); | 6050 ASSERT(current_block() != NULL); |
6045 ASSERT(current_block()->HasPredecessor()); | 6051 ASSERT(current_block()->HasPredecessor()); |
6046 | 6052 |
6047 if (TryArgumentsAccess(expr)) return; | 6053 if (TryArgumentsAccess(expr)) return; |
6048 | 6054 |
6049 CHECK_ALIVE(VisitForValue(expr->obj())); | 6055 CHECK_ALIVE(VisitForValue(expr->obj())); |
6050 if ((!expr->IsFunctionPrototype() && !expr->key()->IsPropertyName()) || | 6056 if ((!expr->IsFunctionPrototype() && !expr->key()->IsPropertyName()) || |
6051 expr->IsStringAccess()) { | 6057 expr->IsStringAccess()) { |
6052 CHECK_ALIVE(VisitForValue(expr->key())); | 6058 CHECK_ALIVE(VisitForValue(expr->key())); |
6053 } | 6059 } |
6054 | 6060 |
6055 BuildLoad(expr, expr->position(), expr->id()); | 6061 BuildLoad(expr, expr->id()); |
6056 } | 6062 } |
6057 | 6063 |
6058 | 6064 |
6059 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, | 6065 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, |
6060 CompilationInfo* info) { | 6066 CompilationInfo* info) { |
6061 HConstant* constant_value = New<HConstant>(constant); | 6067 HConstant* constant_value = New<HConstant>(constant); |
6062 | 6068 |
6063 if (constant->map()->CanOmitMapChecks()) { | 6069 if (constant->map()->CanOmitMapChecks()) { |
6064 constant->map()->AddDependentCompilationInfo( | 6070 constant->map()->AddDependentCompilationInfo( |
6065 DependentCode::kPrototypeCheckGroup, info); | 6071 DependentCode::kPrototypeCheckGroup, info); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6158 SmartArrayPointer<char> caller_name = | 6164 SmartArrayPointer<char> caller_name = |
6159 caller->shared()->DebugName()->ToCString(); | 6165 caller->shared()->DebugName()->ToCString(); |
6160 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6166 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
6161 *name->ToCString(), *caller_name); | 6167 *name->ToCString(), *caller_name); |
6162 } | 6168 } |
6163 | 6169 |
6164 if (!TryInlineCall(expr)) { | 6170 if (!TryInlineCall(expr)) { |
6165 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6171 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
6166 HCallConstantFunction* call = | 6172 HCallConstantFunction* call = |
6167 New<HCallConstantFunction>(expr->target(), argument_count); | 6173 New<HCallConstantFunction>(expr->target(), argument_count); |
6168 call->set_position(expr->position()); | |
6169 PreProcessCall(call); | 6174 PreProcessCall(call); |
6170 AddInstruction(call); | 6175 AddInstruction(call); |
6171 if (!ast_context()->IsEffect()) Push(call); | 6176 if (!ast_context()->IsEffect()) Push(call); |
6172 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 6177 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
6173 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6178 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
6174 } | 6179 } |
6175 | 6180 |
6176 return true; | 6181 return true; |
6177 } | 6182 } |
6178 | 6183 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6222 for (int fn = 0; fn < ordered_functions; ++fn) { | 6227 for (int fn = 0; fn < ordered_functions; ++fn) { |
6223 int i = order[fn].index(); | 6228 int i = order[fn].index(); |
6224 Handle<Map> map = types->at(i); | 6229 Handle<Map> map = types->at(i); |
6225 if (fn == 0) { | 6230 if (fn == 0) { |
6226 // Only needed once. | 6231 // Only needed once. |
6227 join = graph()->CreateBasicBlock(); | 6232 join = graph()->CreateBasicBlock(); |
6228 if (handle_smi) { | 6233 if (handle_smi) { |
6229 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); | 6234 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
6230 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); | 6235 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
6231 number_block = graph()->CreateBasicBlock(); | 6236 number_block = graph()->CreateBasicBlock(); |
6232 current_block()->Finish(New<HIsSmiAndBranch>( | 6237 FinishCurrentBlock(New<HIsSmiAndBranch>( |
6233 receiver, empty_smi_block, not_smi_block)); | 6238 receiver, empty_smi_block, not_smi_block)); |
6234 empty_smi_block->Goto(number_block); | 6239 Goto(empty_smi_block, number_block); |
6235 set_current_block(not_smi_block); | 6240 set_current_block(not_smi_block); |
6236 } else { | 6241 } else { |
6237 BuildCheckHeapObject(receiver); | 6242 BuildCheckHeapObject(receiver); |
6238 } | 6243 } |
6239 } | 6244 } |
6240 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 6245 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
6241 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 6246 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
6242 HUnaryControlInstruction* compare; | 6247 HUnaryControlInstruction* compare; |
6243 | 6248 |
6244 if (handle_smi && map.is_identical_to(number_marker_map)) { | 6249 if (handle_smi && map.is_identical_to(number_marker_map)) { |
6245 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); | 6250 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); |
6246 map = initial_number_map; | 6251 map = initial_number_map; |
6247 expr->set_number_check( | 6252 expr->set_number_check( |
6248 Handle<JSObject>(JSObject::cast(map->prototype()))); | 6253 Handle<JSObject>(JSObject::cast(map->prototype()))); |
6249 } else if (map.is_identical_to(string_marker_map)) { | 6254 } else if (map.is_identical_to(string_marker_map)) { |
6250 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); | 6255 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); |
6251 map = initial_string_map; | 6256 map = initial_string_map; |
6252 expr->set_string_check( | 6257 expr->set_string_check( |
6253 Handle<JSObject>(JSObject::cast(map->prototype()))); | 6258 Handle<JSObject>(JSObject::cast(map->prototype()))); |
6254 } else { | 6259 } else { |
6255 compare = New<HCompareMap>(receiver, map, if_true, if_false); | 6260 compare = New<HCompareMap>(receiver, map, if_true, if_false); |
6256 expr->set_map_check(); | 6261 expr->set_map_check(); |
6257 } | 6262 } |
6258 | 6263 |
6259 current_block()->Finish(compare); | 6264 FinishCurrentBlock(compare); |
6260 | 6265 |
6261 if (expr->check_type() == NUMBER_CHECK) { | 6266 if (expr->check_type() == NUMBER_CHECK) { |
6262 if_true->Goto(number_block); | 6267 Goto(if_true, number_block); |
6263 if_true = number_block; | 6268 if_true = number_block; |
6264 number_block->SetJoinId(expr->id()); | 6269 number_block->SetJoinId(expr->id()); |
6265 } | 6270 } |
6266 set_current_block(if_true); | 6271 set_current_block(if_true); |
6267 | 6272 |
6268 expr->ComputeTarget(map, name); | 6273 expr->ComputeTarget(map, name); |
6269 AddCheckPrototypeMaps(expr->holder(), map); | 6274 AddCheckPrototypeMaps(expr->holder(), map); |
6270 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 6275 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
6271 Handle<JSFunction> caller = current_info()->closure(); | 6276 Handle<JSFunction> caller = current_info()->closure(); |
6272 SmartArrayPointer<char> caller_name = | 6277 SmartArrayPointer<char> caller_name = |
6273 caller->shared()->DebugName()->ToCString(); | 6278 caller->shared()->DebugName()->ToCString(); |
6274 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6279 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
6275 *name->ToCString(), | 6280 *name->ToCString(), |
6276 *caller_name); | 6281 *caller_name); |
6277 } | 6282 } |
6278 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 6283 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { |
6279 // Trying to inline will signal that we should bailout from the | 6284 // Trying to inline will signal that we should bailout from the |
6280 // entire compilation by setting stack overflow on the visitor. | 6285 // entire compilation by setting stack overflow on the visitor. |
6281 if (HasStackOverflow()) return; | 6286 if (HasStackOverflow()) return; |
6282 } else { | 6287 } else { |
6283 HCallConstantFunction* call = | 6288 HCallConstantFunction* call = |
6284 New<HCallConstantFunction>(expr->target(), argument_count); | 6289 New<HCallConstantFunction>(expr->target(), argument_count); |
6285 call->set_position(expr->position()); | |
6286 PreProcessCall(call); | 6290 PreProcessCall(call); |
6287 AddInstruction(call); | 6291 AddInstruction(call); |
6288 if (!ast_context()->IsEffect()) Push(call); | 6292 if (!ast_context()->IsEffect()) Push(call); |
6289 } | 6293 } |
6290 | 6294 |
6291 if (current_block() != NULL) current_block()->Goto(join); | 6295 if (current_block() != NULL) Goto(join); |
6292 set_current_block(if_false); | 6296 set_current_block(if_false); |
6293 } | 6297 } |
6294 | 6298 |
6295 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6299 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6296 // know about and do not want to handle ones we've never seen. Otherwise | 6300 // know about and do not want to handle ones we've never seen. Otherwise |
6297 // use a generic IC. | 6301 // use a generic IC. |
6298 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6302 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
6299 // Because the deopt may be the only path in the polymorphic call, make sure | 6303 // Because the deopt may be the only path in the polymorphic call, make sure |
6300 // that the environment stack matches the depth on deopt that it otherwise | 6304 // that the environment stack matches the depth on deopt that it otherwise |
6301 // would have had after a successful call. | 6305 // would have had after a successful call. |
6302 Drop(argument_count); | 6306 Drop(argument_count); |
6303 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 6307 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
6304 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); | 6308 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); |
6305 } else { | 6309 } else { |
6306 HCallNamed* call = New<HCallNamed>(name, argument_count); | 6310 HCallNamed* call = New<HCallNamed>(name, argument_count); |
6307 call->set_position(expr->position()); | |
6308 PreProcessCall(call); | 6311 PreProcessCall(call); |
6309 | 6312 |
6310 if (join != NULL) { | 6313 if (join != NULL) { |
6311 AddInstruction(call); | 6314 AddInstruction(call); |
6312 if (!ast_context()->IsEffect()) Push(call); | 6315 if (!ast_context()->IsEffect()) Push(call); |
6313 current_block()->Goto(join); | 6316 Goto(join); |
6314 } else { | 6317 } else { |
6315 return ast_context()->ReturnInstruction(call, expr->id()); | 6318 return ast_context()->ReturnInstruction(call, expr->id()); |
6316 } | 6319 } |
6317 } | 6320 } |
6318 | 6321 |
6319 // We assume that control flow is always live after an expression. So | 6322 // We assume that control flow is always live after an expression. So |
6320 // even without predecessors to the join block, we set it as the exit | 6323 // even without predecessors to the join block, we set it as the exit |
6321 // block and continue by adding instructions there. | 6324 // block and continue by adding instructions there. |
6322 ASSERT(join != NULL); | 6325 ASSERT(join != NULL); |
6323 if (join->HasPredecessor()) { | 6326 if (join->HasPredecessor()) { |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6605 | 6608 |
6606 TraceInline(target, caller, NULL); | 6609 TraceInline(target, caller, NULL); |
6607 | 6610 |
6608 if (current_block() != NULL) { | 6611 if (current_block() != NULL) { |
6609 FunctionState* state = function_state(); | 6612 FunctionState* state = function_state(); |
6610 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 6613 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
6611 // Falling off the end of an inlined construct call. In a test context the | 6614 // Falling off the end of an inlined construct call. In a test context the |
6612 // return value will always evaluate to true, in a value context the | 6615 // return value will always evaluate to true, in a value context the |
6613 // return value is the newly allocated receiver. | 6616 // return value is the newly allocated receiver. |
6614 if (call_context()->IsTest()) { | 6617 if (call_context()->IsTest()) { |
6615 current_block()->Goto(inlined_test_context()->if_true(), state); | 6618 Goto(inlined_test_context()->if_true(), state); |
6616 } else if (call_context()->IsEffect()) { | 6619 } else if (call_context()->IsEffect()) { |
6617 current_block()->Goto(function_return(), state); | 6620 Goto(function_return(), state); |
6618 } else { | 6621 } else { |
6619 ASSERT(call_context()->IsValue()); | 6622 ASSERT(call_context()->IsValue()); |
6620 current_block()->AddLeaveInlined(implicit_return_value, state); | 6623 AddLeaveInlined(implicit_return_value, state); |
6621 } | 6624 } |
6622 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { | 6625 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { |
6623 // Falling off the end of an inlined setter call. The returned value is | 6626 // Falling off the end of an inlined setter call. The returned value is |
6624 // never used, the value of an assignment is always the value of the RHS | 6627 // never used, the value of an assignment is always the value of the RHS |
6625 // of the assignment. | 6628 // of the assignment. |
6626 if (call_context()->IsTest()) { | 6629 if (call_context()->IsTest()) { |
6627 inlined_test_context()->ReturnValue(implicit_return_value); | 6630 inlined_test_context()->ReturnValue(implicit_return_value); |
6628 } else if (call_context()->IsEffect()) { | 6631 } else if (call_context()->IsEffect()) { |
6629 current_block()->Goto(function_return(), state); | 6632 Goto(function_return(), state); |
6630 } else { | 6633 } else { |
6631 ASSERT(call_context()->IsValue()); | 6634 ASSERT(call_context()->IsValue()); |
6632 current_block()->AddLeaveInlined(implicit_return_value, state); | 6635 AddLeaveInlined(implicit_return_value, state); |
6633 } | 6636 } |
6634 } else { | 6637 } else { |
6635 // Falling off the end of a normal inlined function. This basically means | 6638 // Falling off the end of a normal inlined function. This basically means |
6636 // returning undefined. | 6639 // returning undefined. |
6637 if (call_context()->IsTest()) { | 6640 if (call_context()->IsTest()) { |
6638 current_block()->Goto(inlined_test_context()->if_false(), state); | 6641 Goto(inlined_test_context()->if_false(), state); |
6639 } else if (call_context()->IsEffect()) { | 6642 } else if (call_context()->IsEffect()) { |
6640 current_block()->Goto(function_return(), state); | 6643 Goto(function_return(), state); |
6641 } else { | 6644 } else { |
6642 ASSERT(call_context()->IsValue()); | 6645 ASSERT(call_context()->IsValue()); |
6643 current_block()->AddLeaveInlined(undefined, state); | 6646 AddLeaveInlined(undefined, state); |
6644 } | 6647 } |
6645 } | 6648 } |
6646 } | 6649 } |
6647 | 6650 |
6648 // Fix up the function exits. | 6651 // Fix up the function exits. |
6649 if (inlined_test_context() != NULL) { | 6652 if (inlined_test_context() != NULL) { |
6650 HBasicBlock* if_true = inlined_test_context()->if_true(); | 6653 HBasicBlock* if_true = inlined_test_context()->if_true(); |
6651 HBasicBlock* if_false = inlined_test_context()->if_false(); | 6654 HBasicBlock* if_false = inlined_test_context()->if_false(); |
6652 | 6655 |
6653 HEnterInlined* entry = function_state()->entry(); | 6656 HEnterInlined* entry = function_state()->entry(); |
6654 | 6657 |
6655 // Pop the return test context from the expression context stack. | 6658 // Pop the return test context from the expression context stack. |
6656 ASSERT(ast_context() == inlined_test_context()); | 6659 ASSERT(ast_context() == inlined_test_context()); |
6657 ClearInlinedTestContext(); | 6660 ClearInlinedTestContext(); |
6658 delete target_state; | 6661 delete target_state; |
6659 | 6662 |
6660 // Forward to the real test context. | 6663 // Forward to the real test context. |
6661 if (if_true->HasPredecessor()) { | 6664 if (if_true->HasPredecessor()) { |
6662 entry->RegisterReturnTarget(if_true, zone()); | 6665 entry->RegisterReturnTarget(if_true, zone()); |
6663 if_true->SetJoinId(ast_id); | 6666 if_true->SetJoinId(ast_id); |
6664 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); | 6667 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); |
6665 if_true->Goto(true_target, function_state()); | 6668 Goto(if_true, true_target, function_state()); |
6666 } | 6669 } |
6667 if (if_false->HasPredecessor()) { | 6670 if (if_false->HasPredecessor()) { |
6668 entry->RegisterReturnTarget(if_false, zone()); | 6671 entry->RegisterReturnTarget(if_false, zone()); |
6669 if_false->SetJoinId(ast_id); | 6672 if_false->SetJoinId(ast_id); |
6670 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); | 6673 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); |
6671 if_false->Goto(false_target, function_state()); | 6674 Goto(if_false, false_target, function_state()); |
6672 } | 6675 } |
6673 set_current_block(NULL); | 6676 set_current_block(NULL); |
6674 return true; | 6677 return true; |
6675 | 6678 |
6676 } else if (function_return()->HasPredecessor()) { | 6679 } else if (function_return()->HasPredecessor()) { |
6677 function_state()->entry()->RegisterReturnTarget(function_return(), zone()); | 6680 function_state()->entry()->RegisterReturnTarget(function_return(), zone()); |
6678 function_return()->SetJoinId(ast_id); | 6681 function_return()->SetJoinId(ast_id); |
6679 set_current_block(function_return()); | 6682 set_current_block(function_return()); |
6680 } else { | 6683 } else { |
6681 set_current_block(NULL); | 6684 set_current_block(NULL); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6768 case kMathLog: | 6771 case kMathLog: |
6769 case kMathSin: | 6772 case kMathSin: |
6770 case kMathCos: | 6773 case kMathCos: |
6771 case kMathTan: | 6774 case kMathTan: |
6772 if (expr->arguments()->length() == 1) { | 6775 if (expr->arguments()->length() == 1) { |
6773 HValue* argument = Pop(); | 6776 HValue* argument = Pop(); |
6774 HValue* context = environment()->context(); | 6777 HValue* context = environment()->context(); |
6775 Drop(1); // Receiver. | 6778 Drop(1); // Receiver. |
6776 HInstruction* op = | 6779 HInstruction* op = |
6777 HUnaryMathOperation::New(zone(), context, argument, id); | 6780 HUnaryMathOperation::New(zone(), context, argument, id); |
6778 op->set_position(expr->position()); | |
6779 if (drop_extra) Drop(1); // Optionally drop the function. | 6781 if (drop_extra) Drop(1); // Optionally drop the function. |
6780 ast_context()->ReturnInstruction(op, expr->id()); | 6782 ast_context()->ReturnInstruction(op, expr->id()); |
6781 return true; | 6783 return true; |
6782 } | 6784 } |
6783 break; | 6785 break; |
6784 case kMathImul: | 6786 case kMathImul: |
6785 if (expr->arguments()->length() == 2) { | 6787 if (expr->arguments()->length() == 2) { |
6786 HValue* right = Pop(); | 6788 HValue* right = Pop(); |
6787 HValue* left = Pop(); | 6789 HValue* left = Pop(); |
6788 Drop(1); // Receiver. | 6790 Drop(1); // Receiver. |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6858 case kMathSin: | 6860 case kMathSin: |
6859 case kMathCos: | 6861 case kMathCos: |
6860 case kMathTan: | 6862 case kMathTan: |
6861 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { | 6863 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
6862 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6864 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6863 HValue* argument = Pop(); | 6865 HValue* argument = Pop(); |
6864 HValue* context = environment()->context(); | 6866 HValue* context = environment()->context(); |
6865 Drop(1); // Receiver. | 6867 Drop(1); // Receiver. |
6866 HInstruction* op = | 6868 HInstruction* op = |
6867 HUnaryMathOperation::New(zone(), context, argument, id); | 6869 HUnaryMathOperation::New(zone(), context, argument, id); |
6868 op->set_position(expr->position()); | |
6869 ast_context()->ReturnInstruction(op, expr->id()); | 6870 ast_context()->ReturnInstruction(op, expr->id()); |
6870 return true; | 6871 return true; |
6871 } | 6872 } |
6872 break; | 6873 break; |
6873 case kMathPow: | 6874 case kMathPow: |
6874 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 6875 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
6875 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6876 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6876 HValue* right = Pop(); | 6877 HValue* right = Pop(); |
6877 HValue* left = Pop(); | 6878 HValue* left = Pop(); |
6878 Pop(); // Pop receiver. | 6879 Pop(); // Pop receiver. |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6987 | 6988 |
6988 if (function_state()->outer() == NULL) { | 6989 if (function_state()->outer() == NULL) { |
6989 HInstruction* elements = Add<HArgumentsElements>(false); | 6990 HInstruction* elements = Add<HArgumentsElements>(false); |
6990 HInstruction* length = Add<HArgumentsLength>(elements); | 6991 HInstruction* length = Add<HArgumentsLength>(elements); |
6991 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); | 6992 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); |
6992 HInstruction* result = | 6993 HInstruction* result = |
6993 new(zone()) HApplyArguments(function, | 6994 new(zone()) HApplyArguments(function, |
6994 wrapped_receiver, | 6995 wrapped_receiver, |
6995 length, | 6996 length, |
6996 elements); | 6997 elements); |
6997 result->set_position(expr->position()); | |
6998 ast_context()->ReturnInstruction(result, expr->id()); | 6998 ast_context()->ReturnInstruction(result, expr->id()); |
6999 return true; | 6999 return true; |
7000 } else { | 7000 } else { |
7001 // We are inside inlined function and we know exactly what is inside | 7001 // We are inside inlined function and we know exactly what is inside |
7002 // arguments object. But we need to be able to materialize at deopt. | 7002 // arguments object. But we need to be able to materialize at deopt. |
7003 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), | 7003 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), |
7004 function_state()->entry()->arguments_object()->arguments_count()); | 7004 function_state()->entry()->arguments_object()->arguments_count()); |
7005 HArgumentsObject* args = function_state()->entry()->arguments_object(); | 7005 HArgumentsObject* args = function_state()->entry()->arguments_object(); |
7006 const ZoneList<HValue*>* arguments_values = args->arguments_values(); | 7006 const ZoneList<HValue*>* arguments_values = args->arguments_values(); |
7007 int arguments_count = arguments_values->length(); | 7007 int arguments_count = arguments_values->length(); |
(...skipping 17 matching lines...) Expand all Loading... |
7025 PushAndAdd(New<HPushArgument>(arguments_values->at(i))); | 7025 PushAndAdd(New<HPushArgument>(arguments_values->at(i))); |
7026 } | 7026 } |
7027 | 7027 |
7028 HValue* context = environment()->context(); | 7028 HValue* context = environment()->context(); |
7029 HInvokeFunction* call = new(zone()) HInvokeFunction( | 7029 HInvokeFunction* call = new(zone()) HInvokeFunction( |
7030 context, | 7030 context, |
7031 function, | 7031 function, |
7032 known_function, | 7032 known_function, |
7033 arguments_count); | 7033 arguments_count); |
7034 Drop(arguments_count); | 7034 Drop(arguments_count); |
7035 call->set_position(expr->position()); | |
7036 ast_context()->ReturnInstruction(call, expr->id()); | 7035 ast_context()->ReturnInstruction(call, expr->id()); |
7037 return true; | 7036 return true; |
7038 } | 7037 } |
7039 } | 7038 } |
7040 | 7039 |
7041 | 7040 |
7042 void HOptimizedGraphBuilder::VisitCall(Call* expr) { | 7041 void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
7043 ASSERT(!HasStackOverflow()); | 7042 ASSERT(!HasStackOverflow()); |
7044 ASSERT(current_block() != NULL); | 7043 ASSERT(current_block() != NULL); |
7045 ASSERT(current_block()->HasPredecessor()); | 7044 ASSERT(current_block()->HasPredecessor()); |
(...skipping 10 matching lines...) Expand all Loading... |
7056 CHECK_ALIVE(VisitForValue(prop->key())); | 7055 CHECK_ALIVE(VisitForValue(prop->key())); |
7057 // Push receiver and key like the non-optimized code generator expects it. | 7056 // Push receiver and key like the non-optimized code generator expects it. |
7058 HValue* key = Pop(); | 7057 HValue* key = Pop(); |
7059 HValue* receiver = Pop(); | 7058 HValue* receiver = Pop(); |
7060 Push(key); | 7059 Push(key); |
7061 Push(receiver); | 7060 Push(receiver); |
7062 | 7061 |
7063 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7062 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
7064 | 7063 |
7065 call = New<HCallKeyed>(key, argument_count); | 7064 call = New<HCallKeyed>(key, argument_count); |
7066 call->set_position(expr->position()); | |
7067 Drop(argument_count + 1); // 1 is the key. | 7065 Drop(argument_count + 1); // 1 is the key. |
7068 return ast_context()->ReturnInstruction(call, expr->id()); | 7066 return ast_context()->ReturnInstruction(call, expr->id()); |
7069 } | 7067 } |
7070 | 7068 |
7071 // Named function call. | 7069 // Named function call. |
7072 if (TryCallApply(expr)) return; | 7070 if (TryCallApply(expr)) return; |
7073 | 7071 |
7074 CHECK_ALIVE(VisitForValue(prop->obj())); | 7072 CHECK_ALIVE(VisitForValue(prop->obj())); |
7075 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7073 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
7076 | 7074 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7110 New<HCallConstantFunction>(expr->target(), argument_count)); | 7108 New<HCallConstantFunction>(expr->target(), argument_count)); |
7111 } | 7109 } |
7112 } else if (types != NULL && types->length() > 1) { | 7110 } else if (types != NULL && types->length() > 1) { |
7113 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 7111 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
7114 HandlePolymorphicCallNamed(expr, receiver, types, name); | 7112 HandlePolymorphicCallNamed(expr, receiver, types, name); |
7115 return; | 7113 return; |
7116 | 7114 |
7117 } else { | 7115 } else { |
7118 call = PreProcessCall(New<HCallNamed>(name, argument_count)); | 7116 call = PreProcessCall(New<HCallNamed>(name, argument_count)); |
7119 } | 7117 } |
7120 | |
7121 } else { | 7118 } else { |
7122 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7119 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
7123 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 7120 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
7124 return Bailout(kPossibleDirectCallToEval); | 7121 return Bailout(kPossibleDirectCallToEval); |
7125 } | 7122 } |
7126 | 7123 |
7127 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 7124 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
7128 if (global_call) { | 7125 if (global_call) { |
7129 Variable* var = proxy->var(); | 7126 Variable* var = proxy->var(); |
7130 bool known_global_function = false; | 7127 bool known_global_function = false; |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7223 HGlobalObject* global_object = Add<HGlobalObject>(); | 7220 HGlobalObject* global_object = Add<HGlobalObject>(); |
7224 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object); | 7221 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object); |
7225 PushAndAdd(New<HPushArgument>(receiver)); | 7222 PushAndAdd(New<HPushArgument>(receiver)); |
7226 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7223 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
7227 | 7224 |
7228 call = New<HCallFunction>(function, argument_count); | 7225 call = New<HCallFunction>(function, argument_count); |
7229 Drop(argument_count + 1); | 7226 Drop(argument_count + 1); |
7230 } | 7227 } |
7231 } | 7228 } |
7232 | 7229 |
7233 call->set_position(expr->position()); | |
7234 return ast_context()->ReturnInstruction(call, expr->id()); | 7230 return ast_context()->ReturnInstruction(call, expr->id()); |
7235 } | 7231 } |
7236 | 7232 |
7237 | 7233 |
7238 // Checks whether allocation using the given constructor can be inlined. | 7234 // Checks whether allocation using the given constructor can be inlined. |
7239 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 7235 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
7240 return constructor->has_initial_map() && | 7236 return constructor->has_initial_map() && |
7241 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 7237 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
7242 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && | 7238 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && |
7243 constructor->initial_map()->InitialPropertiesLength() == 0; | 7239 constructor->initial_map()->InitialPropertiesLength() == 0; |
7244 } | 7240 } |
7245 | 7241 |
7246 | 7242 |
7247 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 7243 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
7248 ASSERT(!HasStackOverflow()); | 7244 ASSERT(!HasStackOverflow()); |
7249 ASSERT(current_block() != NULL); | 7245 ASSERT(current_block() != NULL); |
7250 ASSERT(current_block()->HasPredecessor()); | 7246 ASSERT(current_block()->HasPredecessor()); |
| 7247 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
7251 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 7248 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
7252 Factory* factory = isolate()->factory(); | 7249 Factory* factory = isolate()->factory(); |
7253 | 7250 |
7254 if (FLAG_inline_construct && | 7251 if (FLAG_inline_construct && |
7255 expr->IsMonomorphic() && | 7252 expr->IsMonomorphic() && |
7256 IsAllocationInlineable(expr->target())) { | 7253 IsAllocationInlineable(expr->target())) { |
7257 // The constructor function is on the stack in the unoptimized code | 7254 // The constructor function is on the stack in the unoptimized code |
7258 // during evaluation of the arguments. | 7255 // during evaluation of the arguments. |
7259 CHECK_ALIVE(VisitForValue(expr->expression())); | 7256 CHECK_ALIVE(VisitForValue(expr->expression())); |
7260 HValue* function = Top(); | 7257 HValue* function = Top(); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7332 HInstruction* prev_instr = instr->previous(); | 7329 HInstruction* prev_instr = instr->previous(); |
7333 instr->DeleteAndReplaceWith(NULL); | 7330 instr->DeleteAndReplaceWith(NULL); |
7334 instr = prev_instr; | 7331 instr = prev_instr; |
7335 } | 7332 } |
7336 initial_map_value->DeleteAndReplaceWith(NULL); | 7333 initial_map_value->DeleteAndReplaceWith(NULL); |
7337 receiver->DeleteAndReplaceWith(NULL); | 7334 receiver->DeleteAndReplaceWith(NULL); |
7338 check->DeleteAndReplaceWith(NULL); | 7335 check->DeleteAndReplaceWith(NULL); |
7339 environment()->SetExpressionStackAt(receiver_index, function); | 7336 environment()->SetExpressionStackAt(receiver_index, function); |
7340 HInstruction* call = | 7337 HInstruction* call = |
7341 PreProcessCall(New<HCallNew>(function, argument_count)); | 7338 PreProcessCall(New<HCallNew>(function, argument_count)); |
7342 call->set_position(expr->position()); | |
7343 return ast_context()->ReturnInstruction(call, expr->id()); | 7339 return ast_context()->ReturnInstruction(call, expr->id()); |
7344 } else { | 7340 } else { |
7345 // The constructor function is both an operand to the instruction and an | 7341 // The constructor function is both an operand to the instruction and an |
7346 // argument to the construct call. | 7342 // argument to the construct call. |
7347 Handle<JSFunction> array_function( | 7343 Handle<JSFunction> array_function( |
7348 isolate()->global_context()->array_function(), isolate()); | 7344 isolate()->global_context()->array_function(), isolate()); |
7349 CHECK_ALIVE(VisitArgument(expr->expression())); | 7345 CHECK_ALIVE(VisitArgument(expr->expression())); |
7350 HValue* constructor = HPushArgument::cast(Top())->argument(); | 7346 HValue* constructor = HPushArgument::cast(Top())->argument(); |
7351 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7347 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
7352 HBinaryCall* call; | 7348 HBinaryCall* call; |
7353 if (expr->target().is_identical_to(array_function)) { | 7349 if (expr->target().is_identical_to(array_function)) { |
7354 Handle<Cell> cell = expr->allocation_info_cell(); | 7350 Handle<Cell> cell = expr->allocation_info_cell(); |
7355 Add<HCheckValue>(constructor, array_function); | 7351 Add<HCheckValue>(constructor, array_function); |
7356 call = New<HCallNewArray>(constructor, argument_count, | 7352 call = New<HCallNewArray>(constructor, argument_count, |
7357 cell, expr->elements_kind()); | 7353 cell, expr->elements_kind()); |
7358 } else { | 7354 } else { |
7359 call = New<HCallNew>(constructor, argument_count); | 7355 call = New<HCallNew>(constructor, argument_count); |
7360 } | 7356 } |
7361 Drop(argument_count); | 7357 Drop(argument_count); |
7362 call->set_position(expr->position()); | |
7363 return ast_context()->ReturnInstruction(call, expr->id()); | 7358 return ast_context()->ReturnInstruction(call, expr->id()); |
7364 } | 7359 } |
7365 } | 7360 } |
7366 | 7361 |
7367 | 7362 |
7368 // Support for generating inlined runtime functions. | 7363 // Support for generating inlined runtime functions. |
7369 | 7364 |
7370 // Lookup table for generators for runtime calls that are generated inline. | 7365 // Lookup table for generators for runtime calls that are generated inline. |
7371 // Elements of the table are member pointers to functions of | 7366 // Elements of the table are member pointers to functions of |
7372 // HOptimizedGraphBuilder. | 7367 // HOptimizedGraphBuilder. |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7583 if (key != NULL) Push(key); | 7578 if (key != NULL) Push(key); |
7584 Push(value); | 7579 Push(value); |
7585 BuildStore(expr, prop, ast_id, return_id); | 7580 BuildStore(expr, prop, ast_id, return_id); |
7586 } | 7581 } |
7587 | 7582 |
7588 | 7583 |
7589 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 7584 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
7590 ASSERT(!HasStackOverflow()); | 7585 ASSERT(!HasStackOverflow()); |
7591 ASSERT(current_block() != NULL); | 7586 ASSERT(current_block() != NULL); |
7592 ASSERT(current_block()->HasPredecessor()); | 7587 ASSERT(current_block()->HasPredecessor()); |
| 7588 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
7593 Expression* target = expr->expression(); | 7589 Expression* target = expr->expression(); |
7594 VariableProxy* proxy = target->AsVariableProxy(); | 7590 VariableProxy* proxy = target->AsVariableProxy(); |
7595 Property* prop = target->AsProperty(); | 7591 Property* prop = target->AsProperty(); |
7596 if (proxy == NULL && prop == NULL) { | 7592 if (proxy == NULL && prop == NULL) { |
7597 return Bailout(kInvalidLhsInCountOperation); | 7593 return Bailout(kInvalidLhsInCountOperation); |
7598 } | 7594 } |
7599 | 7595 |
7600 // Match the full code generator stack by simulating an extra stack | 7596 // Match the full code generator stack by simulating an extra stack |
7601 // element for postfix operations in a non-effect context. The return | 7597 // element for postfix operations in a non-effect context. The return |
7602 // value is ToNumber(input). | 7598 // value is ToNumber(input). |
(...skipping 12 matching lines...) Expand all Loading... |
7615 CHECK_ALIVE(VisitForValue(target)); | 7611 CHECK_ALIVE(VisitForValue(target)); |
7616 | 7612 |
7617 after = BuildIncrement(returns_original_input, expr); | 7613 after = BuildIncrement(returns_original_input, expr); |
7618 input = returns_original_input ? Top() : Pop(); | 7614 input = returns_original_input ? Top() : Pop(); |
7619 Push(after); | 7615 Push(after); |
7620 | 7616 |
7621 switch (var->location()) { | 7617 switch (var->location()) { |
7622 case Variable::UNALLOCATED: | 7618 case Variable::UNALLOCATED: |
7623 HandleGlobalVariableAssignment(var, | 7619 HandleGlobalVariableAssignment(var, |
7624 after, | 7620 after, |
7625 expr->position(), | |
7626 expr->AssignmentId()); | 7621 expr->AssignmentId()); |
7627 break; | 7622 break; |
7628 | 7623 |
7629 case Variable::PARAMETER: | 7624 case Variable::PARAMETER: |
7630 case Variable::LOCAL: | 7625 case Variable::LOCAL: |
7631 BindIfLive(var, after); | 7626 BindIfLive(var, after); |
7632 break; | 7627 break; |
7633 | 7628 |
7634 case Variable::CONTEXT: { | 7629 case Variable::CONTEXT: { |
7635 // Bail out if we try to mutate a parameter value in a function | 7630 // Bail out if we try to mutate a parameter value in a function |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7673 CHECK_ALIVE(VisitForValue(prop->obj())); | 7668 CHECK_ALIVE(VisitForValue(prop->obj())); |
7674 HValue* object = Top(); | 7669 HValue* object = Top(); |
7675 | 7670 |
7676 HValue* key = NULL; | 7671 HValue* key = NULL; |
7677 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || | 7672 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || |
7678 prop->IsStringAccess()) { | 7673 prop->IsStringAccess()) { |
7679 CHECK_ALIVE(VisitForValue(prop->key())); | 7674 CHECK_ALIVE(VisitForValue(prop->key())); |
7680 key = Top(); | 7675 key = Top(); |
7681 } | 7676 } |
7682 | 7677 |
7683 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); | 7678 CHECK_ALIVE(PushLoad(prop, object, key)); |
7684 | 7679 |
7685 after = BuildIncrement(returns_original_input, expr); | 7680 after = BuildIncrement(returns_original_input, expr); |
7686 | 7681 |
7687 if (returns_original_input) { | 7682 if (returns_original_input) { |
7688 input = Pop(); | 7683 input = Pop(); |
7689 // Drop object and key to push it again in the effect context below. | 7684 // Drop object and key to push it again in the effect context below. |
7690 Drop(key == NULL ? 1 : 2); | 7685 Drop(key == NULL ? 1 : 2); |
7691 environment()->SetExpressionStackAt(0, input); | 7686 environment()->SetExpressionStackAt(0, input); |
7692 CHECK_ALIVE(BuildStoreForEffect( | 7687 CHECK_ALIVE(BuildStoreForEffect( |
7693 expr, prop, expr->id(), expr->AssignmentId(), object, key, after)); | 7688 expr, prop, expr->id(), expr->AssignmentId(), object, key, after)); |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8083 return ast_context()->ReturnValue(Pop()); | 8078 return ast_context()->ReturnValue(Pop()); |
8084 } | 8079 } |
8085 | 8080 |
8086 // We need an extra block to maintain edge-split form. | 8081 // We need an extra block to maintain edge-split form. |
8087 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 8082 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
8088 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 8083 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
8089 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); | 8084 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); |
8090 HBranch* test = is_logical_and | 8085 HBranch* test = is_logical_and |
8091 ? New<HBranch>(left_value, expected, eval_right, empty_block) | 8086 ? New<HBranch>(left_value, expected, eval_right, empty_block) |
8092 : New<HBranch>(left_value, expected, empty_block, eval_right); | 8087 : New<HBranch>(left_value, expected, empty_block, eval_right); |
8093 current_block()->Finish(test); | 8088 FinishCurrentBlock(test); |
8094 | 8089 |
8095 set_current_block(eval_right); | 8090 set_current_block(eval_right); |
8096 Drop(1); // Value of the left subexpression. | 8091 Drop(1); // Value of the left subexpression. |
8097 CHECK_BAILOUT(VisitForValue(expr->right())); | 8092 CHECK_BAILOUT(VisitForValue(expr->right())); |
8098 | 8093 |
8099 HBasicBlock* join_block = | 8094 HBasicBlock* join_block = |
8100 CreateJoin(empty_block, current_block(), expr->id()); | 8095 CreateJoin(empty_block, current_block(), expr->id()); |
8101 set_current_block(join_block); | 8096 set_current_block(join_block); |
8102 return ast_context()->ReturnValue(Pop()); | 8097 return ast_context()->ReturnValue(Pop()); |
8103 | 8098 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8140 set_current_block(join_block); | 8135 set_current_block(join_block); |
8141 // We did not materialize any value in the predecessor environments, | 8136 // We did not materialize any value in the predecessor environments, |
8142 // so there is no need to handle it here. | 8137 // so there is no need to handle it here. |
8143 } | 8138 } |
8144 } | 8139 } |
8145 | 8140 |
8146 | 8141 |
8147 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { | 8142 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { |
8148 CHECK_ALIVE(VisitForValue(expr->left())); | 8143 CHECK_ALIVE(VisitForValue(expr->left())); |
8149 CHECK_ALIVE(VisitForValue(expr->right())); | 8144 CHECK_ALIVE(VisitForValue(expr->right())); |
| 8145 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
8150 HValue* right = Pop(); | 8146 HValue* right = Pop(); |
8151 HValue* left = Pop(); | 8147 HValue* left = Pop(); |
8152 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 8148 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
8153 instr->set_position(expr->position()); | |
8154 return ast_context()->ReturnInstruction(instr, expr->id()); | 8149 return ast_context()->ReturnInstruction(instr, expr->id()); |
8155 } | 8150 } |
8156 | 8151 |
8157 | 8152 |
8158 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 8153 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
8159 Expression* sub_expr, | 8154 Expression* sub_expr, |
8160 Handle<String> check) { | 8155 Handle<String> check) { |
8161 CHECK_ALIVE(VisitForTypeOf(sub_expr)); | 8156 CHECK_ALIVE(VisitForTypeOf(sub_expr)); |
| 8157 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
8162 HValue* value = Pop(); | 8158 HValue* value = Pop(); |
8163 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); | 8159 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); |
8164 instr->set_position(expr->position()); | |
8165 return ast_context()->ReturnControl(instr, expr->id()); | 8160 return ast_context()->ReturnControl(instr, expr->id()); |
8166 } | 8161 } |
8167 | 8162 |
8168 | 8163 |
8169 static bool IsLiteralCompareBool(Isolate* isolate, | 8164 static bool IsLiteralCompareBool(Isolate* isolate, |
8170 HValue* left, | 8165 HValue* left, |
8171 Token::Value op, | 8166 Token::Value op, |
8172 HValue* right) { | 8167 HValue* right) { |
8173 return op == Token::EQ_STRICT && | 8168 return op == Token::EQ_STRICT && |
8174 ((left->IsConstant() && | 8169 ((left->IsConstant() && |
8175 HConstant::cast(left)->handle(isolate)->IsBoolean()) || | 8170 HConstant::cast(left)->handle(isolate)->IsBoolean()) || |
8176 (right->IsConstant() && | 8171 (right->IsConstant() && |
8177 HConstant::cast(right)->handle(isolate)->IsBoolean())); | 8172 HConstant::cast(right)->handle(isolate)->IsBoolean())); |
8178 } | 8173 } |
8179 | 8174 |
8180 | 8175 |
8181 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 8176 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
8182 ASSERT(!HasStackOverflow()); | 8177 ASSERT(!HasStackOverflow()); |
8183 ASSERT(current_block() != NULL); | 8178 ASSERT(current_block() != NULL); |
8184 ASSERT(current_block()->HasPredecessor()); | 8179 ASSERT(current_block()->HasPredecessor()); |
8185 | 8180 |
| 8181 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
| 8182 |
8186 // Check for a few fast cases. The AST visiting behavior must be in sync | 8183 // Check for a few fast cases. The AST visiting behavior must be in sync |
8187 // with the full codegen: We don't push both left and right values onto | 8184 // with the full codegen: We don't push both left and right values onto |
8188 // the expression stack when one side is a special-case literal. | 8185 // the expression stack when one side is a special-case literal. |
8189 Expression* sub_expr = NULL; | 8186 Expression* sub_expr = NULL; |
8190 Handle<String> check; | 8187 Handle<String> check; |
8191 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { | 8188 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { |
8192 return HandleLiteralCompareTypeof(expr, sub_expr, check); | 8189 return HandleLiteralCompareTypeof(expr, sub_expr, check); |
8193 } | 8190 } |
8194 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { | 8191 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { |
8195 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); | 8192 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); |
8196 } | 8193 } |
8197 if (expr->IsLiteralCompareNull(&sub_expr)) { | 8194 if (expr->IsLiteralCompareNull(&sub_expr)) { |
8198 return HandleLiteralCompareNil(expr, sub_expr, kNullValue); | 8195 return HandleLiteralCompareNil(expr, sub_expr, kNullValue); |
8199 } | 8196 } |
8200 | 8197 |
8201 if (IsClassOfTest(expr)) { | 8198 if (IsClassOfTest(expr)) { |
8202 CallRuntime* call = expr->left()->AsCallRuntime(); | 8199 CallRuntime* call = expr->left()->AsCallRuntime(); |
8203 ASSERT(call->arguments()->length() == 1); | 8200 ASSERT(call->arguments()->length() == 1); |
8204 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8201 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8205 HValue* value = Pop(); | 8202 HValue* value = Pop(); |
8206 Literal* literal = expr->right()->AsLiteral(); | 8203 Literal* literal = expr->right()->AsLiteral(); |
8207 Handle<String> rhs = Handle<String>::cast(literal->value()); | 8204 Handle<String> rhs = Handle<String>::cast(literal->value()); |
8208 HClassOfTestAndBranch* instr = | 8205 HClassOfTestAndBranch* instr = |
8209 new(zone()) HClassOfTestAndBranch(value, rhs); | 8206 new(zone()) HClassOfTestAndBranch(value, rhs); |
8210 instr->set_position(expr->position()); | |
8211 return ast_context()->ReturnControl(instr, expr->id()); | 8207 return ast_context()->ReturnControl(instr, expr->id()); |
8212 } | 8208 } |
8213 | 8209 |
8214 Handle<Type> left_type = expr->left()->bounds().lower; | 8210 Handle<Type> left_type = expr->left()->bounds().lower; |
8215 Handle<Type> right_type = expr->right()->bounds().lower; | 8211 Handle<Type> right_type = expr->right()->bounds().lower; |
8216 Handle<Type> combined_type = expr->combined_type(); | 8212 Handle<Type> combined_type = expr->combined_type(); |
8217 Representation combined_rep = Representation::FromType(combined_type); | 8213 Representation combined_rep = Representation::FromType(combined_type); |
8218 Representation left_rep = Representation::FromType(left_type); | 8214 Representation left_rep = Representation::FromType(left_type); |
8219 Representation right_rep = Representation::FromType(right_type); | 8215 Representation right_rep = Representation::FromType(right_type); |
8220 | 8216 |
8221 CHECK_ALIVE(VisitForValue(expr->left())); | 8217 CHECK_ALIVE(VisitForValue(expr->left())); |
8222 CHECK_ALIVE(VisitForValue(expr->right())); | 8218 CHECK_ALIVE(VisitForValue(expr->right())); |
8223 | 8219 |
8224 HValue* context = environment()->context(); | 8220 HValue* context = environment()->context(); |
8225 HValue* right = Pop(); | 8221 HValue* right = Pop(); |
8226 HValue* left = Pop(); | 8222 HValue* left = Pop(); |
8227 Token::Value op = expr->op(); | 8223 Token::Value op = expr->op(); |
8228 | 8224 |
8229 if (IsLiteralCompareBool(isolate(), left, op, right)) { | 8225 if (IsLiteralCompareBool(isolate(), left, op, right)) { |
8230 HCompareObjectEqAndBranch* result = | 8226 HCompareObjectEqAndBranch* result = |
8231 New<HCompareObjectEqAndBranch>(left, right); | 8227 New<HCompareObjectEqAndBranch>(left, right); |
8232 result->set_position(expr->position()); | |
8233 return ast_context()->ReturnControl(result, expr->id()); | 8228 return ast_context()->ReturnControl(result, expr->id()); |
8234 } | 8229 } |
8235 | 8230 |
8236 if (op == Token::INSTANCEOF) { | 8231 if (op == Token::INSTANCEOF) { |
8237 // Check to see if the rhs of the instanceof is a global function not | 8232 // Check to see if the rhs of the instanceof is a global function not |
8238 // residing in new space. If it is we assume that the function will stay the | 8233 // residing in new space. If it is we assume that the function will stay the |
8239 // same. | 8234 // same. |
8240 Handle<JSFunction> target = Handle<JSFunction>::null(); | 8235 Handle<JSFunction> target = Handle<JSFunction>::null(); |
8241 VariableProxy* proxy = expr->right()->AsVariableProxy(); | 8236 VariableProxy* proxy = expr->right()->AsVariableProxy(); |
8242 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); | 8237 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); |
(...skipping 11 matching lines...) Expand all Loading... |
8254 if (!isolate()->heap()->InNewSpace(*candidate)) { | 8249 if (!isolate()->heap()->InNewSpace(*candidate)) { |
8255 target = candidate; | 8250 target = candidate; |
8256 } | 8251 } |
8257 } | 8252 } |
8258 } | 8253 } |
8259 | 8254 |
8260 // If the target is not null we have found a known global function that is | 8255 // If the target is not null we have found a known global function that is |
8261 // assumed to stay the same for this instanceof. | 8256 // assumed to stay the same for this instanceof. |
8262 if (target.is_null()) { | 8257 if (target.is_null()) { |
8263 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); | 8258 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); |
8264 result->set_position(expr->position()); | |
8265 return ast_context()->ReturnInstruction(result, expr->id()); | 8259 return ast_context()->ReturnInstruction(result, expr->id()); |
8266 } else { | 8260 } else { |
8267 Add<HCheckValue>(right, target); | 8261 Add<HCheckValue>(right, target); |
8268 HInstanceOfKnownGlobal* result = | 8262 HInstanceOfKnownGlobal* result = |
8269 New<HInstanceOfKnownGlobal>(left, target); | 8263 New<HInstanceOfKnownGlobal>(left, target); |
8270 result->set_position(expr->position()); | |
8271 return ast_context()->ReturnInstruction(result, expr->id()); | 8264 return ast_context()->ReturnInstruction(result, expr->id()); |
8272 } | 8265 } |
8273 | 8266 |
8274 // Code below assumes that we don't fall through. | 8267 // Code below assumes that we don't fall through. |
8275 UNREACHABLE(); | 8268 UNREACHABLE(); |
8276 } else if (op == Token::IN) { | 8269 } else if (op == Token::IN) { |
8277 HValue* function = AddLoadJSBuiltin(Builtins::IN); | 8270 HValue* function = AddLoadJSBuiltin(Builtins::IN); |
8278 Add<HPushArgument>(left); | 8271 Add<HPushArgument>(left); |
8279 Add<HPushArgument>(right); | 8272 Add<HPushArgument>(right); |
8280 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 8273 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
8281 // even though we are certain to pass the correct number of arguments here. | 8274 // even though we are certain to pass the correct number of arguments here. |
8282 HInstruction* result = New<HInvokeFunction>(function, 2); | 8275 HInstruction* result = New<HInvokeFunction>(function, 2); |
8283 result->set_position(expr->position()); | |
8284 return ast_context()->ReturnInstruction(result, expr->id()); | 8276 return ast_context()->ReturnInstruction(result, expr->id()); |
8285 } | 8277 } |
8286 | 8278 |
8287 // Cases handled below depend on collected type feedback. They should | 8279 // Cases handled below depend on collected type feedback. They should |
8288 // soft deoptimize when there is no type feedback. | 8280 // soft deoptimize when there is no type feedback. |
8289 if (combined_type->Is(Type::None())) { | 8281 if (combined_type->Is(Type::None())) { |
8290 Add<HDeoptimize>("Insufficient type feedback for combined type " | 8282 Add<HDeoptimize>("Insufficient type feedback for combined type " |
8291 "of binary operation", | 8283 "of binary operation", |
8292 Deoptimizer::SOFT); | 8284 Deoptimizer::SOFT); |
8293 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 8285 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
8294 } | 8286 } |
8295 | 8287 |
8296 if (combined_type->Is(Type::Receiver())) { | 8288 if (combined_type->Is(Type::Receiver())) { |
8297 switch (op) { | 8289 switch (op) { |
8298 case Token::EQ: | 8290 case Token::EQ: |
8299 case Token::EQ_STRICT: { | 8291 case Token::EQ_STRICT: { |
8300 // Can we get away with map check and not instance type check? | 8292 // Can we get away with map check and not instance type check? |
8301 if (combined_type->IsClass()) { | 8293 if (combined_type->IsClass()) { |
8302 Handle<Map> map = combined_type->AsClass(); | 8294 Handle<Map> map = combined_type->AsClass(); |
8303 AddCheckMap(left, map); | 8295 AddCheckMap(left, map); |
8304 AddCheckMap(right, map); | 8296 AddCheckMap(right, map); |
8305 HCompareObjectEqAndBranch* result = | 8297 HCompareObjectEqAndBranch* result = |
8306 New<HCompareObjectEqAndBranch>(left, right); | 8298 New<HCompareObjectEqAndBranch>(left, right); |
8307 result->set_position(expr->position()); | |
8308 return ast_context()->ReturnControl(result, expr->id()); | 8299 return ast_context()->ReturnControl(result, expr->id()); |
8309 } else { | 8300 } else { |
8310 BuildCheckHeapObject(left); | 8301 BuildCheckHeapObject(left); |
8311 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 8302 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
8312 BuildCheckHeapObject(right); | 8303 BuildCheckHeapObject(right); |
8313 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 8304 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
8314 HCompareObjectEqAndBranch* result = | 8305 HCompareObjectEqAndBranch* result = |
8315 New<HCompareObjectEqAndBranch>(left, right); | 8306 New<HCompareObjectEqAndBranch>(left, right); |
8316 result->set_position(expr->position()); | |
8317 return ast_context()->ReturnControl(result, expr->id()); | 8307 return ast_context()->ReturnControl(result, expr->id()); |
8318 } | 8308 } |
8319 } | 8309 } |
8320 default: | 8310 default: |
8321 return Bailout(kUnsupportedNonPrimitiveCompare); | 8311 return Bailout(kUnsupportedNonPrimitiveCompare); |
8322 } | 8312 } |
8323 } else if (combined_type->Is(Type::InternalizedString()) && | 8313 } else if (combined_type->Is(Type::InternalizedString()) && |
8324 Token::IsEqualityOp(op)) { | 8314 Token::IsEqualityOp(op)) { |
8325 BuildCheckHeapObject(left); | 8315 BuildCheckHeapObject(left); |
8326 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); | 8316 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); |
8327 BuildCheckHeapObject(right); | 8317 BuildCheckHeapObject(right); |
8328 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); | 8318 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); |
8329 HCompareObjectEqAndBranch* result = | 8319 HCompareObjectEqAndBranch* result = |
8330 New<HCompareObjectEqAndBranch>(left, right); | 8320 New<HCompareObjectEqAndBranch>(left, right); |
8331 result->set_position(expr->position()); | |
8332 return ast_context()->ReturnControl(result, expr->id()); | 8321 return ast_context()->ReturnControl(result, expr->id()); |
8333 } else if (combined_type->Is(Type::String())) { | 8322 } else if (combined_type->Is(Type::String())) { |
8334 BuildCheckHeapObject(left); | 8323 BuildCheckHeapObject(left); |
8335 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 8324 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
8336 BuildCheckHeapObject(right); | 8325 BuildCheckHeapObject(right); |
8337 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 8326 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
8338 HStringCompareAndBranch* result = | 8327 HStringCompareAndBranch* result = |
8339 New<HStringCompareAndBranch>(left, right, op); | 8328 New<HStringCompareAndBranch>(left, right, op); |
8340 result->set_position(expr->position()); | |
8341 return ast_context()->ReturnControl(result, expr->id()); | 8329 return ast_context()->ReturnControl(result, expr->id()); |
8342 } else if (combined_type->NumClasses() == 1 && Token::IsEqualityOp(op)) { | 8330 } else if (combined_type->NumClasses() == 1 && Token::IsEqualityOp(op)) { |
8343 BuildCheckHeapObject(left); | 8331 BuildCheckHeapObject(left); |
8344 BuildCheckMap(left, combined_type->Classes().Current()); | 8332 BuildCheckMap(left, combined_type->Classes().Current()); |
8345 BuildCheckHeapObject(right); | 8333 BuildCheckHeapObject(right); |
8346 BuildCheckMap(right, combined_type->Classes().Current()); | 8334 BuildCheckMap(right, combined_type->Classes().Current()); |
8347 HCompareObjectEqAndBranch* result = | 8335 HCompareObjectEqAndBranch* result = |
8348 New<HCompareObjectEqAndBranch>(left, right); | 8336 New<HCompareObjectEqAndBranch>(left, right); |
8349 result->set_position(expr->position()); | |
8350 return ast_context()->ReturnInstruction(result, expr->id()); | 8337 return ast_context()->ReturnInstruction(result, expr->id()); |
8351 } else if (combined_type->Is(Type::Receiver()) && Token::IsEqualityOp(op)) { | 8338 } else if (combined_type->Is(Type::Receiver()) && Token::IsEqualityOp(op)) { |
8352 BuildCheckHeapObject(left); | 8339 BuildCheckHeapObject(left); |
8353 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 8340 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
8354 BuildCheckHeapObject(right); | 8341 BuildCheckHeapObject(right); |
8355 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 8342 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
8356 HCompareObjectEqAndBranch* result = | 8343 HCompareObjectEqAndBranch* result = |
8357 New<HCompareObjectEqAndBranch>(left, right); | 8344 New<HCompareObjectEqAndBranch>(left, right); |
8358 result->set_position(expr->position()); | |
8359 return ast_context()->ReturnInstruction(result, expr->id()); | 8345 return ast_context()->ReturnInstruction(result, expr->id()); |
8360 } else { | 8346 } else { |
8361 if (combined_rep.IsTagged() || combined_rep.IsNone()) { | 8347 if (combined_rep.IsTagged() || combined_rep.IsNone()) { |
8362 HCompareGeneric* result = | 8348 HCompareGeneric* result = |
8363 new(zone()) HCompareGeneric(context, left, right, op); | 8349 new(zone()) HCompareGeneric(context, left, right, op); |
8364 result->set_observed_input_representation(1, left_rep); | 8350 result->set_observed_input_representation(1, left_rep); |
8365 result->set_observed_input_representation(2, right_rep); | 8351 result->set_observed_input_representation(2, right_rep); |
8366 result->set_position(expr->position()); | |
8367 return ast_context()->ReturnInstruction(result, expr->id()); | 8352 return ast_context()->ReturnInstruction(result, expr->id()); |
8368 } else { | 8353 } else { |
8369 HCompareNumericAndBranch* result = | 8354 HCompareNumericAndBranch* result = |
8370 New<HCompareNumericAndBranch>(left, right, op); | 8355 New<HCompareNumericAndBranch>(left, right, op); |
8371 result->set_observed_input_representation(left_rep, right_rep); | 8356 result->set_observed_input_representation(left_rep, right_rep); |
8372 result->set_position(expr->position()); | |
8373 return ast_context()->ReturnControl(result, expr->id()); | 8357 return ast_context()->ReturnControl(result, expr->id()); |
8374 } | 8358 } |
8375 } | 8359 } |
8376 } | 8360 } |
8377 | 8361 |
8378 | 8362 |
8379 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 8363 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
8380 Expression* sub_expr, | 8364 Expression* sub_expr, |
8381 NilValue nil) { | 8365 NilValue nil) { |
8382 ASSERT(!HasStackOverflow()); | 8366 ASSERT(!HasStackOverflow()); |
8383 ASSERT(current_block() != NULL); | 8367 ASSERT(current_block() != NULL); |
8384 ASSERT(current_block()->HasPredecessor()); | 8368 ASSERT(current_block()->HasPredecessor()); |
8385 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); | 8369 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); |
| 8370 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
8386 CHECK_ALIVE(VisitForValue(sub_expr)); | 8371 CHECK_ALIVE(VisitForValue(sub_expr)); |
8387 HValue* value = Pop(); | 8372 HValue* value = Pop(); |
8388 if (expr->op() == Token::EQ_STRICT) { | 8373 if (expr->op() == Token::EQ_STRICT) { |
8389 HConstant* nil_constant = nil == kNullValue | 8374 HConstant* nil_constant = nil == kNullValue |
8390 ? graph()->GetConstantNull() | 8375 ? graph()->GetConstantNull() |
8391 : graph()->GetConstantUndefined(); | 8376 : graph()->GetConstantUndefined(); |
8392 HCompareObjectEqAndBranch* instr = | 8377 HCompareObjectEqAndBranch* instr = |
8393 New<HCompareObjectEqAndBranch>(value, nil_constant); | 8378 New<HCompareObjectEqAndBranch>(value, nil_constant); |
8394 instr->set_position(expr->position()); | |
8395 return ast_context()->ReturnControl(instr, expr->id()); | 8379 return ast_context()->ReturnControl(instr, expr->id()); |
8396 } else { | 8380 } else { |
8397 ASSERT_EQ(Token::EQ, expr->op()); | 8381 ASSERT_EQ(Token::EQ, expr->op()); |
8398 Handle<Type> type = expr->combined_type()->Is(Type::None()) | 8382 Handle<Type> type = expr->combined_type()->Is(Type::None()) |
8399 ? handle(Type::Any(), isolate_) | 8383 ? handle(Type::Any(), isolate_) |
8400 : expr->combined_type(); | 8384 : expr->combined_type(); |
8401 HIfContinuation continuation; | 8385 HIfContinuation continuation; |
8402 BuildCompareNil(value, type, expr->position(), &continuation); | 8386 BuildCompareNil(value, type, &continuation); |
8403 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 8387 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
8404 } | 8388 } |
8405 } | 8389 } |
8406 | 8390 |
8407 | 8391 |
8408 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 8392 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
8409 // If we share optimized code between different closures, the | 8393 // If we share optimized code between different closures, the |
8410 // this-function is not a constant, except inside an inlined body. | 8394 // this-function is not a constant, except inside an inlined body. |
8411 if (function_state()->outer() != NULL) { | 8395 if (function_state()->outer() != NULL) { |
8412 return New<HConstant>( | 8396 return New<HConstant>( |
(...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8976 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { | 8960 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { |
8977 ASSERT(call->arguments()->length() == 2); | 8961 ASSERT(call->arguments()->length() == 2); |
8978 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8962 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8979 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 8963 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
8980 HValue* value = Pop(); | 8964 HValue* value = Pop(); |
8981 HValue* object = Pop(); | 8965 HValue* object = Pop(); |
8982 // Check if object is a not a smi. | 8966 // Check if object is a not a smi. |
8983 HBasicBlock* if_smi = graph()->CreateBasicBlock(); | 8967 HBasicBlock* if_smi = graph()->CreateBasicBlock(); |
8984 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); | 8968 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); |
8985 HBasicBlock* join = graph()->CreateBasicBlock(); | 8969 HBasicBlock* join = graph()->CreateBasicBlock(); |
8986 current_block()->Finish(New<HIsSmiAndBranch>(object, if_smi, if_heap_object)); | 8970 FinishCurrentBlock(New<HIsSmiAndBranch>(object, if_smi, if_heap_object)); |
8987 if_smi->Goto(join); | 8971 Goto(if_smi, join); |
8988 | 8972 |
8989 // Check if object is a JSValue. | 8973 // Check if object is a JSValue. |
8990 set_current_block(if_heap_object); | 8974 set_current_block(if_heap_object); |
8991 HHasInstanceTypeAndBranch* typecheck = | 8975 HHasInstanceTypeAndBranch* typecheck = |
8992 New<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE); | 8976 New<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE); |
8993 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); | 8977 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); |
8994 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); | 8978 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); |
8995 typecheck->SetSuccessorAt(0, if_js_value); | 8979 typecheck->SetSuccessorAt(0, if_js_value); |
8996 typecheck->SetSuccessorAt(1, not_js_value); | 8980 typecheck->SetSuccessorAt(1, not_js_value); |
8997 current_block()->Finish(typecheck); | 8981 FinishCurrentBlock(typecheck); |
8998 not_js_value->Goto(join); | 8982 Goto(not_js_value, join); |
8999 | 8983 |
9000 // Create in-object property store to kValueOffset. | 8984 // Create in-object property store to kValueOffset. |
9001 set_current_block(if_js_value); | 8985 set_current_block(if_js_value); |
9002 Add<HStoreNamedField>(object, | 8986 Add<HStoreNamedField>(object, |
9003 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); | 8987 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); |
9004 if_js_value->Goto(join); | 8988 Goto(if_js_value, join); |
9005 join->SetJoinId(call->id()); | 8989 join->SetJoinId(call->id()); |
9006 set_current_block(join); | 8990 set_current_block(join); |
9007 return ast_context()->ReturnValue(value); | 8991 return ast_context()->ReturnValue(value); |
9008 } | 8992 } |
9009 | 8993 |
9010 | 8994 |
9011 // Fast support for charCodeAt(n). | 8995 // Fast support for charCodeAt(n). |
9012 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 8996 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
9013 ASSERT(call->arguments()->length() == 2); | 8997 ASSERT(call->arguments()->length() == 2); |
9014 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8998 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9153 HValue* function = Pop(); | 9137 HValue* function = Pop(); |
9154 | 9138 |
9155 // Branch for function proxies, or other non-functions. | 9139 // Branch for function proxies, or other non-functions. |
9156 HHasInstanceTypeAndBranch* typecheck = | 9140 HHasInstanceTypeAndBranch* typecheck = |
9157 New<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE); | 9141 New<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE); |
9158 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); | 9142 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); |
9159 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); | 9143 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); |
9160 HBasicBlock* join = graph()->CreateBasicBlock(); | 9144 HBasicBlock* join = graph()->CreateBasicBlock(); |
9161 typecheck->SetSuccessorAt(0, if_jsfunction); | 9145 typecheck->SetSuccessorAt(0, if_jsfunction); |
9162 typecheck->SetSuccessorAt(1, if_nonfunction); | 9146 typecheck->SetSuccessorAt(1, if_nonfunction); |
9163 current_block()->Finish(typecheck); | 9147 FinishCurrentBlock(typecheck); |
9164 | 9148 |
9165 set_current_block(if_jsfunction); | 9149 set_current_block(if_jsfunction); |
9166 HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count); | 9150 HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count); |
9167 Drop(arg_count); | 9151 Drop(arg_count); |
9168 Push(invoke_result); | 9152 Push(invoke_result); |
9169 if_jsfunction->Goto(join); | 9153 Goto(if_jsfunction, join); |
9170 | 9154 |
9171 set_current_block(if_nonfunction); | 9155 set_current_block(if_nonfunction); |
9172 HInstruction* call_result = Add<HCallFunction>(function, arg_count); | 9156 HInstruction* call_result = Add<HCallFunction>(function, arg_count); |
9173 Drop(arg_count); | 9157 Drop(arg_count); |
9174 Push(call_result); | 9158 Push(call_result); |
9175 if_nonfunction->Goto(join); | 9159 Goto(if_nonfunction, join); |
9176 | 9160 |
9177 set_current_block(join); | 9161 set_current_block(join); |
9178 join->SetJoinId(call->id()); | 9162 join->SetJoinId(call->id()); |
9179 return ast_context()->ReturnValue(Pop()); | 9163 return ast_context()->ReturnValue(Pop()); |
9180 } | 9164 } |
9181 | 9165 |
9182 | 9166 |
9183 // Fast call to math functions. | 9167 // Fast call to math functions. |
9184 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { | 9168 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { |
9185 ASSERT_EQ(2, call->arguments()->length()); | 9169 ASSERT_EQ(2, call->arguments()->length()); |
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9885 if (ShouldProduceTraceOutput()) { | 9869 if (ShouldProduceTraceOutput()) { |
9886 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9870 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9887 } | 9871 } |
9888 | 9872 |
9889 #ifdef DEBUG | 9873 #ifdef DEBUG |
9890 graph_->Verify(false); // No full verify. | 9874 graph_->Verify(false); // No full verify. |
9891 #endif | 9875 #endif |
9892 } | 9876 } |
9893 | 9877 |
9894 } } // namespace v8::internal | 9878 } } // namespace v8::internal |
OLD | NEW |