Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/hydrogen.cc

Issue 24957003: Add tool to visualize machine code/lithium. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Final polish before review Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698