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

Side by Side Diff: src/hydrogen.cc

Issue 39973003: Merge bleeding_edge. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: again Created 7 years, 1 month 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
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-dce.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 12 matching lines...) Expand all
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "hydrogen.h" 28 #include "hydrogen.h"
29 29
30 #include <algorithm> 30 #include <algorithm>
31 31
32 #include "v8.h" 32 #include "v8.h"
33 #include "allocation-site-scopes.h"
33 #include "codegen.h" 34 #include "codegen.h"
34 #include "full-codegen.h" 35 #include "full-codegen.h"
35 #include "hashmap.h" 36 #include "hashmap.h"
36 #include "hydrogen-bce.h" 37 #include "hydrogen-bce.h"
37 #include "hydrogen-bch.h" 38 #include "hydrogen-bch.h"
38 #include "hydrogen-canonicalize.h" 39 #include "hydrogen-canonicalize.h"
39 #include "hydrogen-check-elimination.h" 40 #include "hydrogen-check-elimination.h"
40 #include "hydrogen-dce.h" 41 #include "hydrogen-dce.h"
41 #include "hydrogen-dehoist.h" 42 #include "hydrogen-dehoist.h"
42 #include "hydrogen-environment-liveness.h" 43 #include "hydrogen-environment-liveness.h"
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 133
133 void HBasicBlock::RemovePhi(HPhi* phi) { 134 void HBasicBlock::RemovePhi(HPhi* phi) {
134 ASSERT(phi->block() == this); 135 ASSERT(phi->block() == this);
135 ASSERT(phis_.Contains(phi)); 136 ASSERT(phis_.Contains(phi));
136 phi->Kill(); 137 phi->Kill();
137 phis_.RemoveElement(phi); 138 phis_.RemoveElement(phi);
138 phi->SetBlock(NULL); 139 phi->SetBlock(NULL);
139 } 140 }
140 141
141 142
142 void HBasicBlock::AddInstruction(HInstruction* instr) { 143 void HBasicBlock::AddInstruction(HInstruction* instr, int position) {
143 ASSERT(!IsStartBlock() || !IsFinished()); 144 ASSERT(!IsStartBlock() || !IsFinished());
144 ASSERT(!instr->IsLinked()); 145 ASSERT(!instr->IsLinked());
145 ASSERT(!IsFinished()); 146 ASSERT(!IsFinished());
146 147
148 if (position != RelocInfo::kNoPosition) {
149 instr->set_position(position);
150 }
147 if (first_ == NULL) { 151 if (first_ == NULL) {
148 ASSERT(last_environment() != NULL); 152 ASSERT(last_environment() != NULL);
149 ASSERT(!last_environment()->ast_id().IsNone()); 153 ASSERT(!last_environment()->ast_id().IsNone());
150 HBlockEntry* entry = new(zone()) HBlockEntry(); 154 HBlockEntry* entry = new(zone()) HBlockEntry();
151 entry->InitializeAsFirst(this); 155 entry->InitializeAsFirst(this);
156 if (position != RelocInfo::kNoPosition) {
157 entry->set_position(position);
158 } else {
159 ASSERT(!FLAG_emit_opt_code_positions ||
160 !graph()->info()->IsOptimizing());
161 }
152 first_ = last_ = entry; 162 first_ = last_ = entry;
153 } 163 }
154 instr->InsertAfter(last_); 164 instr->InsertAfter(last_);
155 } 165 }
156 166
157 167
158 HPhi* HBasicBlock::AddNewPhi(int merged_index) { 168 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
159 if (graph()->IsInsideNoSideEffectsScope()) { 169 if (graph()->IsInsideNoSideEffectsScope()) {
160 merged_index = HPhi::kInvalidMergedIndex; 170 merged_index = HPhi::kInvalidMergedIndex;
161 } 171 }
(...skipping 30 matching lines...) Expand all
192 !it.Done(); 202 !it.Done();
193 it.Advance()) { 203 it.Advance()) {
194 int index = it.Current(); 204 int index = it.Current();
195 instr->AddAssignedValue(index, environment->Lookup(index)); 205 instr->AddAssignedValue(index, environment->Lookup(index));
196 } 206 }
197 environment->ClearHistory(); 207 environment->ClearHistory();
198 return instr; 208 return instr;
199 } 209 }
200 210
201 211
202 void HBasicBlock::Finish(HControlInstruction* end) { 212 void HBasicBlock::Finish(HControlInstruction* end, int position) {
203 ASSERT(!IsFinished()); 213 ASSERT(!IsFinished());
204 AddInstruction(end); 214 AddInstruction(end, position);
205 end_ = end; 215 end_ = end;
206 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 216 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
207 it.Current()->RegisterPredecessor(this); 217 it.Current()->RegisterPredecessor(this);
208 } 218 }
209 } 219 }
210 220
211 221
212 void HBasicBlock::Goto(HBasicBlock* block, 222 void HBasicBlock::Goto(HBasicBlock* block,
223 int position,
213 FunctionState* state, 224 FunctionState* state,
214 bool add_simulate) { 225 bool add_simulate) {
215 bool drop_extra = state != NULL && 226 bool drop_extra = state != NULL &&
216 state->inlining_kind() == DROP_EXTRA_ON_RETURN; 227 state->inlining_kind() == DROP_EXTRA_ON_RETURN;
217 228
218 if (block->IsInlineReturnTarget()) { 229 if (block->IsInlineReturnTarget()) {
219 HEnvironment* env = last_environment(); 230 HEnvironment* env = last_environment();
220 int argument_count = env->arguments_environment()->parameter_count(); 231 int argument_count = env->arguments_environment()->parameter_count();
221 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count)); 232 AddInstruction(new(zone())
233 HLeaveInlined(state->entry(), argument_count),
234 position);
222 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 235 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
223 } 236 }
224 237
225 if (add_simulate) AddNewSimulate(BailoutId::None()); 238 if (add_simulate) AddNewSimulate(BailoutId::None(), position);
226 HGoto* instr = new(zone()) HGoto(block); 239 HGoto* instr = new(zone()) HGoto(block);
227 Finish(instr); 240 Finish(instr, position);
228 } 241 }
229 242
230 243
231 void HBasicBlock::AddLeaveInlined(HValue* return_value, 244 void HBasicBlock::AddLeaveInlined(HValue* return_value,
232 FunctionState* state) { 245 FunctionState* state,
246 int position) {
233 HBasicBlock* target = state->function_return(); 247 HBasicBlock* target = state->function_return();
234 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; 248 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN;
235 249
236 ASSERT(target->IsInlineReturnTarget()); 250 ASSERT(target->IsInlineReturnTarget());
237 ASSERT(return_value != NULL); 251 ASSERT(return_value != NULL);
238 HEnvironment* env = last_environment(); 252 HEnvironment* env = last_environment();
239 int argument_count = env->arguments_environment()->parameter_count(); 253 int argument_count = env->arguments_environment()->parameter_count();
240 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count)); 254 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
255 position);
241 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 256 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
242 last_environment()->Push(return_value); 257 last_environment()->Push(return_value);
243 AddNewSimulate(BailoutId::None()); 258 AddNewSimulate(BailoutId::None(), position);
244 HGoto* instr = new(zone()) HGoto(target); 259 HGoto* instr = new(zone()) HGoto(target);
245 Finish(instr); 260 Finish(instr, position);
246 } 261 }
247 262
248 263
249 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 264 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
250 ASSERT(!HasEnvironment()); 265 ASSERT(!HasEnvironment());
251 ASSERT(first() == NULL); 266 ASSERT(first() == NULL);
252 UpdateEnvironment(env); 267 UpdateEnvironment(env);
253 } 268 }
254 269
255 270
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 641
627 #endif 642 #endif
628 643
629 644
630 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, 645 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
631 int32_t value) { 646 int32_t value) {
632 if (!pointer->is_set()) { 647 if (!pointer->is_set()) {
633 // Can't pass GetInvalidContext() to HConstant::New, because that will 648 // Can't pass GetInvalidContext() to HConstant::New, because that will
634 // recursively call GetConstant 649 // recursively call GetConstant
635 HConstant* constant = HConstant::New(zone(), NULL, value); 650 HConstant* constant = HConstant::New(zone(), NULL, value);
636 constant->InsertAfter(GetConstantUndefined()); 651 constant->InsertAfter(entry_block()->first());
637 pointer->set(constant); 652 pointer->set(constant);
653 return constant;
638 } 654 }
639 return pointer->get(); 655 return ReinsertConstantIfNecessary(pointer->get());
640 } 656 }
641 657
642 658
659 HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
660 if (!constant->IsLinked()) {
661 // The constant was removed from the graph. Reinsert.
662 constant->ClearFlag(HValue::kIsDead);
663 constant->InsertAfter(entry_block()->first());
664 }
665 return constant;
666 }
667
668
643 HConstant* HGraph::GetConstant0() { 669 HConstant* HGraph::GetConstant0() {
644 return GetConstant(&constant_0_, 0); 670 return GetConstant(&constant_0_, 0);
645 } 671 }
646 672
647 673
648 HConstant* HGraph::GetConstant1() { 674 HConstant* HGraph::GetConstant1() {
649 return GetConstant(&constant_1_, 1); 675 return GetConstant(&constant_1_, 1);
650 } 676 }
651 677
652 678
653 HConstant* HGraph::GetConstantMinus1() { 679 HConstant* HGraph::GetConstantMinus1() {
654 return GetConstant(&constant_minus1_, -1); 680 return GetConstant(&constant_minus1_, -1);
655 } 681 }
656 682
657 683
658 #define DEFINE_GET_CONSTANT(Name, name, htype, boolean_value) \ 684 #define DEFINE_GET_CONSTANT(Name, name, htype, boolean_value) \
659 HConstant* HGraph::GetConstant##Name() { \ 685 HConstant* HGraph::GetConstant##Name() { \
660 if (!constant_##name##_.is_set()) { \ 686 if (!constant_##name##_.is_set()) { \
661 HConstant* constant = new(zone()) HConstant( \ 687 HConstant* constant = new(zone()) HConstant( \
662 Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \ 688 Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \
663 Representation::Tagged(), \ 689 Representation::Tagged(), \
664 htype, \ 690 htype, \
665 false, \ 691 false, \
666 true, \ 692 true, \
667 false, \ 693 false, \
668 boolean_value); \ 694 boolean_value); \
669 constant->InsertAfter(GetConstantUndefined()); \ 695 constant->InsertAfter(entry_block()->first()); \
670 constant_##name##_.set(constant); \ 696 constant_##name##_.set(constant); \
671 } \ 697 } \
672 return constant_##name##_.get(); \ 698 return ReinsertConstantIfNecessary(constant_##name##_.get()); \
673 } 699 }
674 700
675 701
702 DEFINE_GET_CONSTANT(Undefined, undefined, HType::Tagged(), false)
676 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) 703 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true)
677 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) 704 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false)
678 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) 705 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false)
679 DEFINE_GET_CONSTANT(Null, null, HType::Tagged(), false) 706 DEFINE_GET_CONSTANT(Null, null, HType::Tagged(), false)
680 707
681 708
682 #undef DEFINE_GET_CONSTANT 709 #undef DEFINE_GET_CONSTANT
683 710
684 711
685 HConstant* HGraph::GetInvalidContext() { 712 HConstant* HGraph::GetInvalidContext() {
686 return GetConstant(&constant_invalid_context_, 0xFFFFC0C7); 713 return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
687 } 714 }
688 715
689 716
690 bool HGraph::IsStandardConstant(HConstant* constant) { 717 bool HGraph::IsStandardConstant(HConstant* constant) {
691 if (constant == GetConstantUndefined()) return true; 718 if (constant == GetConstantUndefined()) return true;
692 if (constant == GetConstant0()) return true; 719 if (constant == GetConstant0()) return true;
693 if (constant == GetConstant1()) return true; 720 if (constant == GetConstant1()) return true;
694 if (constant == GetConstantMinus1()) return true; 721 if (constant == GetConstantMinus1()) return true;
695 if (constant == GetConstantTrue()) return true; 722 if (constant == GetConstantTrue()) return true;
696 if (constant == GetConstantFalse()) return true; 723 if (constant == GetConstantFalse()) return true;
697 if (constant == GetConstantHole()) return true; 724 if (constant == GetConstantHole()) return true;
698 if (constant == GetConstantNull()) return true; 725 if (constant == GetConstantNull()) return true;
699 return false; 726 return false;
700 } 727 }
701 728
702 729
703 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) 730 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
704 : builder_(builder), 731 : builder_(builder),
705 position_(position),
706 finished_(false), 732 finished_(false),
707 deopt_then_(false), 733 deopt_then_(false),
708 deopt_else_(false), 734 deopt_else_(false),
709 did_then_(false), 735 did_then_(false),
710 did_else_(false), 736 did_else_(false),
711 did_and_(false), 737 did_and_(false),
712 did_or_(false), 738 did_or_(false),
713 captured_(false), 739 captured_(false),
714 needs_compare_(true), 740 needs_compare_(true),
715 split_edge_merge_block_(NULL), 741 split_edge_merge_block_(NULL),
716 merge_block_(NULL) { 742 merge_block_(NULL) {
717 HEnvironment* env = builder->environment(); 743 HEnvironment* env = builder->environment();
718 first_true_block_ = builder->CreateBasicBlock(env->Copy()); 744 first_true_block_ = builder->CreateBasicBlock(env->Copy());
719 last_true_block_ = NULL; 745 last_true_block_ = NULL;
720 first_false_block_ = builder->CreateBasicBlock(env->Copy()); 746 first_false_block_ = builder->CreateBasicBlock(env->Copy());
721 } 747 }
722 748
723 749
724 HGraphBuilder::IfBuilder::IfBuilder( 750 HGraphBuilder::IfBuilder::IfBuilder(
725 HGraphBuilder* builder, 751 HGraphBuilder* builder,
726 HIfContinuation* continuation) 752 HIfContinuation* continuation)
727 : builder_(builder), 753 : builder_(builder),
728 position_(RelocInfo::kNoPosition),
729 finished_(false), 754 finished_(false),
730 deopt_then_(false), 755 deopt_then_(false),
731 deopt_else_(false), 756 deopt_else_(false),
732 did_then_(false), 757 did_then_(false),
733 did_else_(false), 758 did_else_(false),
734 did_and_(false), 759 did_and_(false),
735 did_or_(false), 760 did_or_(false),
736 captured_(false), 761 captured_(false),
737 needs_compare_(false), 762 needs_compare_(false),
738 first_true_block_(NULL), 763 first_true_block_(NULL),
739 last_true_block_(NULL), 764 last_true_block_(NULL),
740 first_false_block_(NULL), 765 first_false_block_(NULL),
741 split_edge_merge_block_(NULL), 766 split_edge_merge_block_(NULL),
742 merge_block_(NULL) { 767 merge_block_(NULL) {
743 continuation->Continue(&first_true_block_, 768 continuation->Continue(&first_true_block_,
744 &first_false_block_, 769 &first_false_block_);
745 &position_);
746 } 770 }
747 771
748 772
749 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( 773 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
750 HControlInstruction* compare) { 774 HControlInstruction* compare) {
751 if (split_edge_merge_block_ != NULL) { 775 if (split_edge_merge_block_ != NULL) {
752 HEnvironment* env = first_false_block_->last_environment(); 776 HEnvironment* env = first_false_block_->last_environment();
753 HBasicBlock* split_edge = 777 HBasicBlock* split_edge =
754 builder_->CreateBasicBlock(env->Copy()); 778 builder_->CreateBasicBlock(env->Copy());
755 if (did_or_) { 779 if (did_or_) {
756 compare->SetSuccessorAt(0, split_edge); 780 compare->SetSuccessorAt(0, split_edge);
757 compare->SetSuccessorAt(1, first_false_block_); 781 compare->SetSuccessorAt(1, first_false_block_);
758 } else { 782 } else {
759 compare->SetSuccessorAt(0, first_true_block_); 783 compare->SetSuccessorAt(0, first_true_block_);
760 compare->SetSuccessorAt(1, split_edge); 784 compare->SetSuccessorAt(1, split_edge);
761 } 785 }
762 split_edge->GotoNoSimulate(split_edge_merge_block_); 786 builder_->GotoNoSimulate(split_edge, split_edge_merge_block_);
763 } else { 787 } else {
764 compare->SetSuccessorAt(0, first_true_block_); 788 compare->SetSuccessorAt(0, first_true_block_);
765 compare->SetSuccessorAt(1, first_false_block_); 789 compare->SetSuccessorAt(1, first_false_block_);
766 } 790 }
767 builder_->current_block()->Finish(compare); 791 builder_->FinishCurrentBlock(compare);
768 needs_compare_ = false; 792 needs_compare_ = false;
769 return compare; 793 return compare;
770 } 794 }
771 795
772 796
773 void HGraphBuilder::IfBuilder::Or() { 797 void HGraphBuilder::IfBuilder::Or() {
798 ASSERT(!needs_compare_);
774 ASSERT(!did_and_); 799 ASSERT(!did_and_);
775 did_or_ = true; 800 did_or_ = true;
776 HEnvironment* env = first_false_block_->last_environment(); 801 HEnvironment* env = first_false_block_->last_environment();
777 if (split_edge_merge_block_ == NULL) { 802 if (split_edge_merge_block_ == NULL) {
778 split_edge_merge_block_ = 803 split_edge_merge_block_ =
779 builder_->CreateBasicBlock(env->Copy()); 804 builder_->CreateBasicBlock(env->Copy());
780 first_true_block_->GotoNoSimulate(split_edge_merge_block_); 805 builder_->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
781 first_true_block_ = split_edge_merge_block_; 806 first_true_block_ = split_edge_merge_block_;
782 } 807 }
783 builder_->set_current_block(first_false_block_); 808 builder_->set_current_block(first_false_block_);
784 first_false_block_ = builder_->CreateBasicBlock(env->Copy()); 809 first_false_block_ = builder_->CreateBasicBlock(env->Copy());
785 } 810 }
786 811
787 812
788 void HGraphBuilder::IfBuilder::And() { 813 void HGraphBuilder::IfBuilder::And() {
814 ASSERT(!needs_compare_);
789 ASSERT(!did_or_); 815 ASSERT(!did_or_);
790 did_and_ = true; 816 did_and_ = true;
791 HEnvironment* env = first_false_block_->last_environment(); 817 HEnvironment* env = first_false_block_->last_environment();
792 if (split_edge_merge_block_ == NULL) { 818 if (split_edge_merge_block_ == NULL) {
793 split_edge_merge_block_ = builder_->CreateBasicBlock(env->Copy()); 819 split_edge_merge_block_ = builder_->CreateBasicBlock(env->Copy());
794 first_false_block_->GotoNoSimulate(split_edge_merge_block_); 820 builder_->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
795 first_false_block_ = split_edge_merge_block_; 821 first_false_block_ = split_edge_merge_block_;
796 } 822 }
797 builder_->set_current_block(first_true_block_); 823 builder_->set_current_block(first_true_block_);
798 first_true_block_ = builder_->CreateBasicBlock(env->Copy()); 824 first_true_block_ = builder_->CreateBasicBlock(env->Copy());
799 } 825 }
800 826
801 827
802 void HGraphBuilder::IfBuilder::CaptureContinuation( 828 void HGraphBuilder::IfBuilder::CaptureContinuation(
803 HIfContinuation* continuation) { 829 HIfContinuation* continuation) {
804 ASSERT(!finished_); 830 ASSERT(!finished_);
805 ASSERT(!captured_); 831 ASSERT(!captured_);
806 HBasicBlock* true_block = last_true_block_ == NULL 832 HBasicBlock* true_block = last_true_block_ == NULL
807 ? first_true_block_ 833 ? first_true_block_
808 : last_true_block_; 834 : last_true_block_;
809 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) 835 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL)
810 ? builder_->current_block() 836 ? builder_->current_block()
811 : first_false_block_; 837 : first_false_block_;
812 continuation->Capture(true_block, false_block, position_); 838 continuation->Capture(true_block, false_block);
813 captured_ = true; 839 captured_ = true;
814 End(); 840 End();
815 } 841 }
816 842
817 843
818 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { 844 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
819 ASSERT(!finished_); 845 ASSERT(!finished_);
820 ASSERT(!captured_); 846 ASSERT(!captured_);
821 HBasicBlock* true_block = last_true_block_ == NULL 847 HBasicBlock* true_block = last_true_block_ == NULL
822 ? first_true_block_ 848 ? first_true_block_
823 : last_true_block_; 849 : last_true_block_;
824 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) 850 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL)
825 ? builder_->current_block() 851 ? builder_->current_block()
826 : first_false_block_; 852 : first_false_block_;
827 if (true_block != NULL && !true_block->IsFinished()) { 853 if (true_block != NULL && !true_block->IsFinished()) {
828 ASSERT(continuation->IsTrueReachable()); 854 ASSERT(continuation->IsTrueReachable());
829 true_block->GotoNoSimulate(continuation->true_branch()); 855 builder_->GotoNoSimulate(true_block, continuation->true_branch());
830 } 856 }
831 if (false_block != NULL && !false_block->IsFinished()) { 857 if (false_block != NULL && !false_block->IsFinished()) {
832 ASSERT(continuation->IsFalseReachable()); 858 ASSERT(continuation->IsFalseReachable());
833 false_block->GotoNoSimulate(continuation->false_branch()); 859 builder_->GotoNoSimulate(false_block, continuation->false_branch());
834 } 860 }
835 captured_ = true; 861 captured_ = true;
836 End(); 862 End();
837 } 863 }
838 864
839 865
840 void HGraphBuilder::IfBuilder::Then() { 866 void HGraphBuilder::IfBuilder::Then() {
841 ASSERT(!captured_); 867 ASSERT(!captured_);
842 ASSERT(!finished_); 868 ASSERT(!finished_);
843 did_then_ = true; 869 did_then_ = true;
844 if (needs_compare_) { 870 if (needs_compare_) {
845 // Handle if's without any expressions, they jump directly to the "else" 871 // Handle if's without any expressions, they jump directly to the "else"
846 // branch. However, we must pretend that the "then" branch is reachable, 872 // 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 873 // so that the graph builder visits it and sees any live range extending
848 // constructs within it. 874 // constructs within it.
849 HConstant* constant_false = builder_->graph()->GetConstantFalse(); 875 HConstant* constant_false = builder_->graph()->GetConstantFalse();
850 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); 876 ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
851 boolean_type.Add(ToBooleanStub::BOOLEAN); 877 boolean_type.Add(ToBooleanStub::BOOLEAN);
852 HBranch* branch = builder()->New<HBranch>( 878 HBranch* branch = builder()->New<HBranch>(
853 constant_false, boolean_type, first_true_block_, first_false_block_); 879 constant_false, boolean_type, first_true_block_, first_false_block_);
854 builder_->current_block()->Finish(branch); 880 builder_->FinishCurrentBlock(branch);
855 } 881 }
856 builder_->set_current_block(first_true_block_); 882 builder_->set_current_block(first_true_block_);
857 } 883 }
858 884
859 885
860 void HGraphBuilder::IfBuilder::Else() { 886 void HGraphBuilder::IfBuilder::Else() {
861 ASSERT(did_then_); 887 ASSERT(did_then_);
862 ASSERT(!captured_); 888 ASSERT(!captured_);
863 ASSERT(!finished_); 889 ASSERT(!finished_);
864 last_true_block_ = builder_->current_block(); 890 last_true_block_ = builder_->current_block();
865 builder_->set_current_block(first_false_block_); 891 builder_->set_current_block(first_false_block_);
866 did_else_ = true; 892 did_else_ = true;
867 } 893 }
868 894
869 895
870 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { 896 void HGraphBuilder::IfBuilder::Deopt(const char* reason) {
871 ASSERT(did_then_); 897 ASSERT(did_then_);
872 if (did_else_) { 898 if (did_else_) {
873 deopt_else_ = true; 899 deopt_else_ = true;
874 } else { 900 } else {
875 deopt_then_ = true; 901 deopt_then_ = true;
876 } 902 }
877 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER); 903 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
878 } 904 }
879 905
880 906
881 void HGraphBuilder::IfBuilder::Return(HValue* value) { 907 void HGraphBuilder::IfBuilder::Return(HValue* value) {
882 HBasicBlock* block = builder_->current_block();
883 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); 908 HValue* parameter_count = builder_->graph()->GetConstantMinus1();
884 block->FinishExit(builder_->New<HReturn>(value, parameter_count)); 909 builder_->FinishExitCurrentBlock(
885 builder_->set_current_block(NULL); 910 builder_->New<HReturn>(value, parameter_count));
886 if (did_else_) { 911 if (did_else_) {
887 first_false_block_ = NULL; 912 first_false_block_ = NULL;
888 } else { 913 } else {
889 first_true_block_ = NULL; 914 first_true_block_ = NULL;
890 } 915 }
891 } 916 }
892 917
893 918
894 void HGraphBuilder::IfBuilder::End() { 919 void HGraphBuilder::IfBuilder::End() {
895 if (!captured_) { 920 if (!captured_) {
896 ASSERT(did_then_); 921 ASSERT(did_then_);
897 if (!did_else_) { 922 if (!did_else_) {
898 last_true_block_ = builder_->current_block(); 923 last_true_block_ = builder_->current_block();
899 } 924 }
900 if (last_true_block_ == NULL || last_true_block_->IsFinished()) { 925 if (last_true_block_ == NULL || last_true_block_->IsFinished()) {
901 ASSERT(did_else_); 926 ASSERT(did_else_);
902 // Return on true. Nothing to do, just continue the false block. 927 // Return on true. Nothing to do, just continue the false block.
903 } else if (first_false_block_ == NULL || 928 } else if (first_false_block_ == NULL ||
904 (did_else_ && builder_->current_block()->IsFinished())) { 929 (did_else_ && builder_->current_block()->IsFinished())) {
905 // Deopt on false. Nothing to do except switching to the true block. 930 // Deopt on false. Nothing to do except switching to the true block.
906 builder_->set_current_block(last_true_block_); 931 builder_->set_current_block(last_true_block_);
907 } else { 932 } else {
908 merge_block_ = builder_->graph()->CreateBasicBlock(); 933 merge_block_ = builder_->graph()->CreateBasicBlock();
909 ASSERT(!finished_); 934 ASSERT(!finished_);
910 if (!did_else_) Else(); 935 if (!did_else_) Else();
911 ASSERT(!last_true_block_->IsFinished()); 936 ASSERT(!last_true_block_->IsFinished());
912 HBasicBlock* last_false_block = builder_->current_block(); 937 HBasicBlock* last_false_block = builder_->current_block();
913 ASSERT(!last_false_block->IsFinished()); 938 ASSERT(!last_false_block->IsFinished());
914 if (deopt_then_) { 939 if (deopt_then_) {
915 last_false_block->GotoNoSimulate(merge_block_); 940 builder_->GotoNoSimulate(last_false_block, merge_block_);
916 builder_->PadEnvironmentForContinuation(last_true_block_, 941 builder_->PadEnvironmentForContinuation(last_true_block_,
917 merge_block_); 942 merge_block_);
918 last_true_block_->GotoNoSimulate(merge_block_); 943 builder_->GotoNoSimulate(last_true_block_, merge_block_);
919 } else { 944 } else {
920 last_true_block_->GotoNoSimulate(merge_block_); 945 builder_->GotoNoSimulate(last_true_block_, merge_block_);
921 if (deopt_else_) { 946 if (deopt_else_) {
922 builder_->PadEnvironmentForContinuation(last_false_block, 947 builder_->PadEnvironmentForContinuation(last_false_block,
923 merge_block_); 948 merge_block_);
924 } 949 }
925 last_false_block->GotoNoSimulate(merge_block_); 950 builder_->GotoNoSimulate(last_false_block, merge_block_);
926 } 951 }
927 builder_->set_current_block(merge_block_); 952 builder_->set_current_block(merge_block_);
928 } 953 }
929 } 954 }
930 finished_ = true; 955 finished_ = true;
931 } 956 }
932 957
933 958
934 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, 959 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
935 HValue* context, 960 HValue* context,
(...skipping 27 matching lines...) Expand all
963 988
964 989
965 HValue* HGraphBuilder::LoopBuilder::BeginBody( 990 HValue* HGraphBuilder::LoopBuilder::BeginBody(
966 HValue* initial, 991 HValue* initial,
967 HValue* terminating, 992 HValue* terminating,
968 Token::Value token) { 993 Token::Value token) {
969 HEnvironment* env = builder_->environment(); 994 HEnvironment* env = builder_->environment();
970 phi_ = header_block_->AddNewPhi(env->values()->length()); 995 phi_ = header_block_->AddNewPhi(env->values()->length());
971 phi_->AddInput(initial); 996 phi_->AddInput(initial);
972 env->Push(initial); 997 env->Push(initial);
973 builder_->current_block()->GotoNoSimulate(header_block_); 998 builder_->GotoNoSimulate(header_block_);
974 999
975 HEnvironment* body_env = env->Copy(); 1000 HEnvironment* body_env = env->Copy();
976 HEnvironment* exit_env = env->Copy(); 1001 HEnvironment* exit_env = env->Copy();
977 // Remove the phi from the expression stack 1002 // Remove the phi from the expression stack
978 body_env->Pop(); 1003 body_env->Pop();
979 exit_env->Pop(); 1004 exit_env->Pop();
980 body_block_ = builder_->CreateBasicBlock(body_env); 1005 body_block_ = builder_->CreateBasicBlock(body_env);
981 exit_block_ = builder_->CreateBasicBlock(exit_env); 1006 exit_block_ = builder_->CreateBasicBlock(exit_env);
982 1007
983 builder_->set_current_block(header_block_); 1008 builder_->set_current_block(header_block_);
984 env->Pop(); 1009 env->Pop();
985 builder_->current_block()->Finish(builder_->New<HCompareNumericAndBranch>( 1010 builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
986 phi_, terminating, token, body_block_, exit_block_)); 1011 phi_, terminating, token, body_block_, exit_block_));
987 1012
988 builder_->set_current_block(body_block_); 1013 builder_->set_current_block(body_block_);
989 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { 1014 if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
990 HValue* one = builder_->graph()->GetConstant1(); 1015 HValue* one = builder_->graph()->GetConstant1();
991 if (direction_ == kPreIncrement) { 1016 if (direction_ == kPreIncrement) {
992 increment_ = HAdd::New(zone(), context_, phi_, one); 1017 increment_ = HAdd::New(zone(), context_, phi_, one);
993 } else { 1018 } else {
994 increment_ = HSub::New(zone(), context_, phi_, one); 1019 increment_ = HSub::New(zone(), context_, phi_, one);
995 } 1020 }
996 increment_->ClearFlag(HValue::kCanOverflow); 1021 increment_->ClearFlag(HValue::kCanOverflow);
997 builder_->AddInstruction(increment_); 1022 builder_->AddInstruction(increment_);
998 return increment_; 1023 return increment_;
999 } else { 1024 } else {
1000 return phi_; 1025 return phi_;
1001 } 1026 }
1002 } 1027 }
1003 1028
1004 1029
1005 void HGraphBuilder::LoopBuilder::Break() { 1030 void HGraphBuilder::LoopBuilder::Break() {
1006 if (exit_trampoline_block_ == NULL) { 1031 if (exit_trampoline_block_ == NULL) {
1007 // Its the first time we saw a break. 1032 // Its the first time we saw a break.
1008 HEnvironment* env = exit_block_->last_environment()->Copy(); 1033 HEnvironment* env = exit_block_->last_environment()->Copy();
1009 exit_trampoline_block_ = builder_->CreateBasicBlock(env); 1034 exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1010 exit_block_->GotoNoSimulate(exit_trampoline_block_); 1035 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
1011 } 1036 }
1012 1037
1013 builder_->current_block()->GotoNoSimulate(exit_trampoline_block_); 1038 builder_->GotoNoSimulate(exit_trampoline_block_);
1014 } 1039 }
1015 1040
1016 1041
1017 void HGraphBuilder::LoopBuilder::EndBody() { 1042 void HGraphBuilder::LoopBuilder::EndBody() {
1018 ASSERT(!finished_); 1043 ASSERT(!finished_);
1019 1044
1020 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { 1045 if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
1021 if (direction_ == kPostIncrement) { 1046 if (direction_ == kPostIncrement) {
1022 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); 1047 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_);
1023 } else { 1048 } else {
1024 increment_ = HSub::New(zone(), context_, phi_, increment_amount_); 1049 increment_ = HSub::New(zone(), context_, phi_, increment_amount_);
1025 } 1050 }
1026 increment_->ClearFlag(HValue::kCanOverflow); 1051 increment_->ClearFlag(HValue::kCanOverflow);
1027 builder_->AddInstruction(increment_); 1052 builder_->AddInstruction(increment_);
1028 } 1053 }
1029 1054
1030 // Push the new increment value on the expression stack to merge into the phi. 1055 // Push the new increment value on the expression stack to merge into the phi.
1031 builder_->environment()->Push(increment_); 1056 builder_->environment()->Push(increment_);
1032 HBasicBlock* last_block = builder_->current_block(); 1057 HBasicBlock* last_block = builder_->current_block();
1033 last_block->GotoNoSimulate(header_block_); 1058 builder_->GotoNoSimulate(last_block, header_block_);
1034 header_block_->loop_information()->RegisterBackEdge(last_block); 1059 header_block_->loop_information()->RegisterBackEdge(last_block);
1035 1060
1036 if (exit_trampoline_block_ != NULL) { 1061 if (exit_trampoline_block_ != NULL) {
1037 builder_->set_current_block(exit_trampoline_block_); 1062 builder_->set_current_block(exit_trampoline_block_);
1038 } else { 1063 } else {
1039 builder_->set_current_block(exit_block_); 1064 builder_->set_current_block(exit_block_);
1040 } 1065 }
1041 finished_ = true; 1066 finished_ = true;
1042 } 1067 }
1043 1068
1044 1069
1045 HGraph* HGraphBuilder::CreateGraph() { 1070 HGraph* HGraphBuilder::CreateGraph() {
1046 graph_ = new(zone()) HGraph(info_); 1071 graph_ = new(zone()) HGraph(info_);
1047 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); 1072 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
1048 CompilationPhase phase("H_Block building", info_); 1073 CompilationPhase phase("H_Block building", info_);
1049 set_current_block(graph()->entry_block()); 1074 set_current_block(graph()->entry_block());
1050 if (!BuildGraph()) return NULL; 1075 if (!BuildGraph()) return NULL;
1051 graph()->FinalizeUniqueness(); 1076 graph()->FinalizeUniqueness();
1052 return graph_; 1077 return graph_;
1053 } 1078 }
1054 1079
1055 1080
1056 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 1081 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
1057 ASSERT(current_block() != NULL); 1082 ASSERT(current_block() != NULL);
1058 current_block()->AddInstruction(instr); 1083 ASSERT(!FLAG_emit_opt_code_positions ||
1084 position_ != RelocInfo::kNoPosition || !info_->IsOptimizing());
1085 current_block()->AddInstruction(instr, position_);
1059 if (graph()->IsInsideNoSideEffectsScope()) { 1086 if (graph()->IsInsideNoSideEffectsScope()) {
1060 instr->SetFlag(HValue::kHasNoObservableSideEffects); 1087 instr->SetFlag(HValue::kHasNoObservableSideEffects);
1061 } 1088 }
1062 return instr; 1089 return instr;
1063 } 1090 }
1064 1091
1065 1092
1093 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
1094 ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() ||
1095 position_ != RelocInfo::kNoPosition);
1096 current_block()->Finish(last, position_);
1097 if (last->IsReturn() || last->IsAbnormalExit()) {
1098 set_current_block(NULL);
1099 }
1100 }
1101
1102
1103 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
1104 ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() ||
1105 position_ != RelocInfo::kNoPosition);
1106 current_block()->FinishExit(instruction, position_);
1107 if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
1108 set_current_block(NULL);
1109 }
1110 }
1111
1112
1066 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { 1113 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
1067 if (FLAG_native_code_counters && counter->Enabled()) { 1114 if (FLAG_native_code_counters && counter->Enabled()) {
1068 HValue* reference = Add<HConstant>(ExternalReference(counter)); 1115 HValue* reference = Add<HConstant>(ExternalReference(counter));
1069 HValue* old_value = Add<HLoadNamedField>(reference, 1116 HValue* old_value = Add<HLoadNamedField>(reference,
1070 HObjectAccess::ForCounter()); 1117 HObjectAccess::ForCounter());
1071 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); 1118 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1());
1072 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow 1119 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow
1073 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), 1120 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
1074 new_value); 1121 new_value);
1075 } 1122 }
(...skipping 28 matching lines...) Expand all
1104 if (obj->type().IsHeapObject()) return obj; 1151 if (obj->type().IsHeapObject()) return obj;
1105 return Add<HCheckHeapObject>(obj); 1152 return Add<HCheckHeapObject>(obj);
1106 } 1153 }
1107 1154
1108 1155
1109 void HGraphBuilder::FinishExitWithHardDeoptimization( 1156 void HGraphBuilder::FinishExitWithHardDeoptimization(
1110 const char* reason, HBasicBlock* continuation) { 1157 const char* reason, HBasicBlock* continuation) {
1111 PadEnvironmentForContinuation(current_block(), continuation); 1158 PadEnvironmentForContinuation(current_block(), continuation);
1112 Add<HDeoptimize>(reason, Deoptimizer::EAGER); 1159 Add<HDeoptimize>(reason, Deoptimizer::EAGER);
1113 if (graph()->IsInsideNoSideEffectsScope()) { 1160 if (graph()->IsInsideNoSideEffectsScope()) {
1114 current_block()->GotoNoSimulate(continuation); 1161 GotoNoSimulate(continuation);
1115 } else { 1162 } else {
1116 current_block()->Goto(continuation); 1163 Goto(continuation);
1117 } 1164 }
1118 } 1165 }
1119 1166
1120 1167
1121 void HGraphBuilder::PadEnvironmentForContinuation( 1168 void HGraphBuilder::PadEnvironmentForContinuation(
1122 HBasicBlock* from, 1169 HBasicBlock* from,
1123 HBasicBlock* continuation) { 1170 HBasicBlock* continuation) {
1124 if (continuation->last_environment() != NULL) { 1171 if (continuation->last_environment() != NULL) {
1125 // When merging from a deopt block to a continuation, resolve differences in 1172 // 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 1173 // environment by pushing constant 0 and popping extra values so that the
(...skipping 24 matching lines...) Expand all
1151 return Add<HWrapReceiver>(object, function); 1198 return Add<HWrapReceiver>(object, function);
1152 } 1199 }
1153 1200
1154 1201
1155 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, 1202 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
1156 HValue* elements, 1203 HValue* elements,
1157 ElementsKind kind, 1204 ElementsKind kind,
1158 HValue* length, 1205 HValue* length,
1159 HValue* key, 1206 HValue* key,
1160 bool is_js_array) { 1207 bool is_js_array) {
1161 Zone* zone = this->zone();
1162 IfBuilder length_checker(this); 1208 IfBuilder length_checker(this);
1163 1209
1164 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; 1210 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
1165 length_checker.If<HCompareNumericAndBranch>(key, length, token); 1211 length_checker.If<HCompareNumericAndBranch>(key, length, token);
1166 1212
1167 length_checker.Then(); 1213 length_checker.Then();
1168 1214
1169 HValue* current_capacity = AddLoadFixedArrayLength(elements); 1215 HValue* current_capacity = AddLoadFixedArrayLength(elements);
1170 1216
1171 IfBuilder capacity_checker(this); 1217 IfBuilder capacity_checker(this);
1172 1218
1173 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, 1219 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
1174 Token::GTE); 1220 Token::GTE);
1175 capacity_checker.Then(); 1221 capacity_checker.Then();
1176 1222
1177 HValue* context = environment()->context();
1178
1179 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); 1223 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
1180 HValue* max_capacity = Add<HAdd>(current_capacity, max_gap); 1224 HValue* max_capacity = Add<HAdd>(current_capacity, max_gap);
1181 IfBuilder key_checker(this); 1225 IfBuilder key_checker(this);
1182 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); 1226 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT);
1183 key_checker.Then(); 1227 key_checker.Then();
1184 key_checker.ElseDeopt("Key out of capacity range"); 1228 key_checker.ElseDeopt("Key out of capacity range");
1185 key_checker.End(); 1229 key_checker.End();
1186 1230
1187 HValue* new_capacity = BuildNewElementsCapacity(key); 1231 HValue* new_capacity = BuildNewElementsCapacity(key);
1188 HValue* new_elements = BuildGrowElementsCapacity(object, elements, 1232 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1189 kind, kind, length, 1233 kind, kind, length,
1190 new_capacity); 1234 new_capacity);
1191 1235
1192 environment()->Push(new_elements); 1236 environment()->Push(new_elements);
1193 capacity_checker.Else(); 1237 capacity_checker.Else();
1194 1238
1195 environment()->Push(elements); 1239 environment()->Push(elements);
1196 capacity_checker.End(); 1240 capacity_checker.End();
1197 1241
1198 if (is_js_array) { 1242 if (is_js_array) {
1199 HValue* new_length = AddInstruction( 1243 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
1200 HAdd::New(zone, context, key, graph_->GetConstant1()));
1201 new_length->ClearFlag(HValue::kCanOverflow); 1244 new_length->ClearFlag(HValue::kCanOverflow);
1202 1245
1203 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), 1246 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
1204 new_length); 1247 new_length);
1205 } 1248 }
1206 1249
1207 length_checker.Else(); 1250 length_checker.Else();
1208 Add<HBoundsCheck>(key, length); 1251 Add<HBoundsCheck>(key, length);
1209 1252
1210 environment()->Push(elements); 1253 environment()->Push(elements);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1275 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, 1318 BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
1276 array_length, elements_length); 1319 array_length, elements_length);
1277 1320
1278 if_builder.End(); 1321 if_builder.End();
1279 } 1322 }
1280 1323
1281 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); 1324 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
1282 } 1325 }
1283 1326
1284 1327
1285 HValue* HGraphBuilder::BuildLookupNumberStringCache( 1328 HValue* HGraphBuilder::BuildNumberToString(HValue* object,
1286 HValue* object, 1329 Handle<Type> type) {
1287 HIfContinuation* continuation) { 1330 NoObservableSideEffectsScope scope(this);
1331
1288 // Create a joinable continuation. 1332 // Create a joinable continuation.
1289 HIfContinuation found(graph()->CreateBasicBlock(), 1333 HIfContinuation found(graph()->CreateBasicBlock(),
1290 graph()->CreateBasicBlock()); 1334 graph()->CreateBasicBlock());
1291 1335
1292 // Load the number string cache. 1336 // Load the number string cache.
1293 HValue* number_string_cache = 1337 HValue* number_string_cache =
1294 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex); 1338 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
1295 1339
1296 // Make the hash maks from the length of the number string cache. It 1340 // Make the hash mask from the length of the number string cache. It
1297 // contains two elements (number and string) for each cache entry. 1341 // contains two elements (number and string) for each cache entry.
1298 HValue* mask = AddLoadFixedArrayLength(number_string_cache); 1342 HValue* mask = AddLoadFixedArrayLength(number_string_cache);
1299 mask->set_type(HType::Smi()); 1343 mask->set_type(HType::Smi());
1300 mask = Add<HSar>(mask, graph()->GetConstant1()); 1344 mask = Add<HSar>(mask, graph()->GetConstant1());
1301 mask = Add<HSub>(mask, graph()->GetConstant1()); 1345 mask = Add<HSub>(mask, graph()->GetConstant1());
1302 1346
1303 // Check whether object is a smi. 1347 // Check whether object is a smi.
1304 IfBuilder if_objectissmi(this); 1348 IfBuilder if_objectissmi(this);
1305 if_objectissmi.If<HIsSmiAndBranch>(object); 1349 if_objectissmi.If<HIsSmiAndBranch>(object);
1306 if_objectissmi.Then(); 1350 if_objectissmi.Then();
1307 { 1351 {
1308 // Compute hash for smi similar to smi_get_hash(). 1352 // Compute hash for smi similar to smi_get_hash().
1309 HValue* hash = Add<HBitwise>(Token::BIT_AND, object, mask); 1353 HValue* hash = Add<HBitwise>(Token::BIT_AND, object, mask);
1310 1354
1311 // Load the key. 1355 // Load the key.
1312 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); 1356 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1());
1313 HValue* key = AddFastElementAccess(number_string_cache, key_index, 1357 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
1314 NULL, NULL, FAST_ELEMENTS, false, 1358 static_cast<HValue*>(NULL),
1315 ALLOW_RETURN_HOLE, STANDARD_STORE); 1359 FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1316 1360
1317 // Check if object == key. 1361 // Check if object == key.
1318 IfBuilder if_objectiskey(this); 1362 IfBuilder if_objectiskey(this);
1319 if_objectiskey.If<HCompareObjectEqAndBranch>(key, object); 1363 if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
1320 if_objectiskey.Then(); 1364 if_objectiskey.Then();
1321 { 1365 {
1322 // Make the key_index available. 1366 // Make the key_index available.
1323 Push(key_index); 1367 Push(key_index);
1324 } 1368 }
1325 if_objectiskey.JoinContinuation(&found); 1369 if_objectiskey.JoinContinuation(&found);
1326 } 1370 }
1327 if_objectissmi.Else(); 1371 if_objectissmi.Else();
1328 { 1372 {
1329 // Check if object is a heap number. 1373 if (type->Is(Type::Smi())) {
1330 IfBuilder if_objectisnumber(this); 1374 if_objectissmi.Deopt("Excepted smi");
1331 if_objectisnumber.If<HCompareMap>( 1375 } else {
1332 object, isolate()->factory()->heap_number_map()); 1376 // Check if the object is a heap number.
1333 if_objectisnumber.Then(); 1377 IfBuilder if_objectisnumber(this);
1334 { 1378 if_objectisnumber.If<HCompareMap>(
1335 // Compute hash for heap number similar to double_get_hash(). 1379 object, isolate()->factory()->heap_number_map());
1336 HValue* low = Add<HLoadNamedField>( 1380 if_objectisnumber.Then();
1337 object, HObjectAccess::ForHeapNumberValueLowestBits()); 1381 {
1338 HValue* high = Add<HLoadNamedField>( 1382 // Compute hash for heap number similar to double_get_hash().
1339 object, HObjectAccess::ForHeapNumberValueHighestBits()); 1383 HValue* low = Add<HLoadNamedField>(
1340 HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high); 1384 object, HObjectAccess::ForHeapNumberValueLowestBits());
1341 hash = Add<HBitwise>(Token::BIT_AND, hash, mask); 1385 HValue* high = Add<HLoadNamedField>(
1386 object, HObjectAccess::ForHeapNumberValueHighestBits());
1387 HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high);
1388 hash = Add<HBitwise>(Token::BIT_AND, hash, mask);
1342 1389
1343 // Load the key. 1390 // Load the key.
1344 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); 1391 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1());
1345 HValue* key = AddFastElementAccess(number_string_cache, key_index, 1392 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
1346 NULL, NULL, FAST_ELEMENTS, false, 1393 static_cast<HValue*>(NULL),
1347 ALLOW_RETURN_HOLE, STANDARD_STORE); 1394 FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1348 1395
1349 // Check if key is a heap number. 1396 // Check if key is a heap number (the number string cache contains only
1350 IfBuilder if_keyisnumber(this); 1397 // SMIs and heap number, so it is sufficient to do a SMI check here).
1351 if_keyisnumber.IfNot<HIsSmiAndBranch>(key); 1398 IfBuilder if_keyisnotsmi(this);
1352 if_keyisnumber.AndIf<HCompareMap>( 1399 if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
1353 key, isolate()->factory()->heap_number_map()); 1400 if_keyisnotsmi.Then();
1354 if_keyisnumber.Then(); 1401 {
1402 // Check if values of key and object match.
1403 IfBuilder if_keyeqobject(this);
1404 if_keyeqobject.If<HCompareNumericAndBranch>(
1405 Add<HLoadNamedField>(key, HObjectAccess::ForHeapNumberValue()),
1406 Add<HLoadNamedField>(object, HObjectAccess::ForHeapNumberValue()),
1407 Token::EQ);
1408 if_keyeqobject.Then();
1409 {
1410 // Make the key_index available.
1411 Push(key_index);
1412 }
1413 if_keyeqobject.JoinContinuation(&found);
1414 }
1415 if_keyisnotsmi.JoinContinuation(&found);
1416 }
1417 if_objectisnumber.Else();
1355 { 1418 {
1356 // Check if values of key and object match. 1419 if (type->Is(Type::Number())) {
1357 IfBuilder if_keyeqobject(this); 1420 if_objectisnumber.Deopt("Expected heap number");
1358 if_keyeqobject.If<HCompareNumericAndBranch>(
1359 Add<HLoadNamedField>(key, HObjectAccess::ForHeapNumberValue()),
1360 Add<HLoadNamedField>(object, HObjectAccess::ForHeapNumberValue()),
1361 Token::EQ);
1362 if_keyeqobject.Then();
1363 {
1364 // Make the key_index available.
1365 Push(key_index);
1366 } 1421 }
1367 if_keyeqobject.JoinContinuation(&found);
1368 } 1422 }
1369 if_keyisnumber.JoinContinuation(&found); 1423 if_objectisnumber.JoinContinuation(&found);
1370 } 1424 }
1371 if_objectisnumber.JoinContinuation(&found);
1372 } 1425 }
1373 if_objectissmi.End(); 1426 if_objectissmi.JoinContinuation(&found);
1374 1427
1375 // Check for cache hit. 1428 // Check for cache hit.
1376 IfBuilder if_found(this, &found); 1429 IfBuilder if_found(this, &found);
1377 if_found.Then(); 1430 if_found.Then();
1431 {
1432 // Count number to string operation in native code.
1433 AddIncrementCounter(isolate()->counters()->number_to_string_native());
1378 1434
1379 // Load the value in case of cache hit. 1435 // Load the value in case of cache hit.
1380 HValue* key_index = Pop(); 1436 HValue* key_index = Pop();
1381 HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1()); 1437 HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1());
1382 HValue* value = AddFastElementAccess(number_string_cache, value_index, 1438 Push(Add<HLoadKeyed>(number_string_cache, value_index,
1383 NULL, NULL, FAST_ELEMENTS, false, 1439 static_cast<HValue*>(NULL),
1384 ALLOW_RETURN_HOLE, STANDARD_STORE); 1440 FAST_ELEMENTS, ALLOW_RETURN_HOLE));
1385 AddIncrementCounter(isolate()->counters()->number_to_string_native()); 1441 }
1386
1387 if_found.CaptureContinuation(continuation);
1388
1389 // The value is only available in true branch of continuation.
1390 return value;
1391 }
1392
1393
1394 HValue* HGraphBuilder::BuildNumberToString(HValue* number) {
1395 NoObservableSideEffectsScope scope(this);
1396
1397 // Lookup the number in the number string cache.
1398 HIfContinuation continuation;
1399 HValue* value = BuildLookupNumberStringCache(number, &continuation);
1400 IfBuilder if_found(this, &continuation);
1401 if_found.Then();
1402
1403 // Cache hit.
1404 Push(value);
1405
1406 if_found.Else(); 1442 if_found.Else();
1407 1443 {
1408 // Cache miss, fallback to runtime. 1444 // Cache miss, fallback to runtime.
1409 Add<HPushArgument>(number); 1445 Add<HPushArgument>(object);
1410 Push(Add<HCallRuntime>( 1446 Push(Add<HCallRuntime>(
1411 isolate()->factory()->empty_string(), 1447 isolate()->factory()->empty_string(),
1412 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), 1448 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
1413 1)); 1449 1));
1414 1450 }
1415 if_found.End(); 1451 if_found.End();
1416 1452
1417 return Pop(); 1453 return Pop();
1418 } 1454 }
1419 1455
1420 1456
1421 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 1457 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
1422 HValue* checked_object, 1458 HValue* checked_object,
1423 HValue* key, 1459 HValue* key,
1424 HValue* val, 1460 HValue* val,
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1462 NoObservableSideEffectsScope no_effects(this); 1498 NoObservableSideEffectsScope no_effects(this);
1463 HLoadExternalArrayPointer* external_elements = 1499 HLoadExternalArrayPointer* external_elements =
1464 Add<HLoadExternalArrayPointer>(elements); 1500 Add<HLoadExternalArrayPointer>(elements);
1465 IfBuilder length_checker(this); 1501 IfBuilder length_checker(this);
1466 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); 1502 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
1467 length_checker.Then(); 1503 length_checker.Then();
1468 IfBuilder negative_checker(this); 1504 IfBuilder negative_checker(this);
1469 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( 1505 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
1470 key, graph()->GetConstant0(), Token::GTE); 1506 key, graph()->GetConstant0(), Token::GTE);
1471 negative_checker.Then(); 1507 negative_checker.Then();
1472 HInstruction* result = AddExternalArrayElementAccess( 1508 HInstruction* result = AddElementAccess(
1473 external_elements, key, val, bounds_check, elements_kind, is_store); 1509 external_elements, key, val, bounds_check, elements_kind, is_store);
1474 negative_checker.ElseDeopt("Negative key encountered"); 1510 negative_checker.ElseDeopt("Negative key encountered");
1475 length_checker.End(); 1511 length_checker.End();
1476 return result; 1512 return result;
1477 } else { 1513 } else {
1478 ASSERT(store_mode == STANDARD_STORE); 1514 ASSERT(store_mode == STANDARD_STORE);
1479 checked_key = Add<HBoundsCheck>(key, length); 1515 checked_key = Add<HBoundsCheck>(key, length);
1480 HLoadExternalArrayPointer* external_elements = 1516 HLoadExternalArrayPointer* external_elements =
1481 Add<HLoadExternalArrayPointer>(elements); 1517 Add<HLoadExternalArrayPointer>(elements);
1482 return AddExternalArrayElementAccess( 1518 return AddElementAccess(
1483 external_elements, checked_key, val, 1519 external_elements, checked_key, val,
1484 checked_object, elements_kind, is_store); 1520 checked_object, elements_kind, is_store);
1485 } 1521 }
1486 } 1522 }
1487 ASSERT(fast_smi_only_elements || 1523 ASSERT(fast_smi_only_elements ||
1488 fast_elements || 1524 fast_elements ||
1489 IsFastDoubleElementsKind(elements_kind)); 1525 IsFastDoubleElementsKind(elements_kind));
1490 1526
1491 // In case val is stored into a fast smi array, assure that the value is a smi 1527 // In case val is stored into a fast smi array, assure that the value is a smi
1492 // before manipulating the backing store. Otherwise the actual store may 1528 // before manipulating the backing store. Otherwise the actual store may
(...skipping 12 matching lines...) Expand all
1505 } else { 1541 } else {
1506 checked_key = Add<HBoundsCheck>(key, length); 1542 checked_key = Add<HBoundsCheck>(key, length);
1507 1543
1508 if (is_store && (fast_elements || fast_smi_only_elements)) { 1544 if (is_store && (fast_elements || fast_smi_only_elements)) {
1509 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { 1545 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
1510 NoObservableSideEffectsScope no_effects(this); 1546 NoObservableSideEffectsScope no_effects(this);
1511 elements = BuildCopyElementsOnWrite(checked_object, elements, 1547 elements = BuildCopyElementsOnWrite(checked_object, elements,
1512 elements_kind, length); 1548 elements_kind, length);
1513 } else { 1549 } else {
1514 HCheckMaps* check_cow_map = Add<HCheckMaps>( 1550 HCheckMaps* check_cow_map = Add<HCheckMaps>(
1515 elements, isolate()->factory()->fixed_array_map(), 1551 elements, isolate()->factory()->fixed_array_map(), top_info());
1516 top_info());
1517 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 1552 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1518 } 1553 }
1519 } 1554 }
1520 } 1555 }
1521 return AddFastElementAccess(elements, checked_key, val, checked_object, 1556 return AddElementAccess(elements, checked_key, val, checked_object,
1522 elements_kind, is_store, load_mode, store_mode); 1557 elements_kind, is_store, load_mode);
1523 } 1558 }
1524 1559
1525 1560
1526 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, 1561 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
1527 HValue* capacity) { 1562 HValue* capacity) {
1528 int elements_size; 1563 int elements_size;
1529 InstanceType instance_type; 1564 InstanceType instance_type;
1530 1565
1531 if (IsFastDoubleElementsKind(kind)) { 1566 if (IsFastDoubleElementsKind(kind)) {
1532 elements_size = kDoubleSize; 1567 elements_size = kDoubleSize;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 if (mode == TRACK_ALLOCATION_SITE) { 1637 if (mode == TRACK_ALLOCATION_SITE) {
1603 elements_location += AllocationMemento::kSize; 1638 elements_location += AllocationMemento::kSize;
1604 } 1639 }
1605 1640
1606 HValue* elements = Add<HInnerAllocatedObject>(array, elements_location); 1641 HValue* elements = Add<HInnerAllocatedObject>(array, elements_location);
1607 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements); 1642 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements);
1608 return static_cast<HInnerAllocatedObject*>(elements); 1643 return static_cast<HInnerAllocatedObject*>(elements);
1609 } 1644 }
1610 1645
1611 1646
1612 HInstruction* HGraphBuilder::AddExternalArrayElementAccess( 1647 HInstruction* HGraphBuilder::AddElementAccess(
1613 HValue* external_elements, 1648 HValue* elements,
1614 HValue* checked_key, 1649 HValue* checked_key,
1615 HValue* val, 1650 HValue* val,
1616 HValue* dependency, 1651 HValue* dependency,
1617 ElementsKind elements_kind, 1652 ElementsKind elements_kind,
1618 bool is_store) { 1653 bool is_store,
1654 LoadKeyedHoleMode load_mode) {
1619 if (is_store) { 1655 if (is_store) {
1620 ASSERT(val != NULL); 1656 ASSERT(val != NULL);
1621 switch (elements_kind) { 1657 if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
1622 case EXTERNAL_PIXEL_ELEMENTS: { 1658 val = Add<HClampToUint8>(val);
1623 val = Add<HClampToUint8>(val);
1624 break;
1625 }
1626 case EXTERNAL_BYTE_ELEMENTS:
1627 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
1628 case EXTERNAL_SHORT_ELEMENTS:
1629 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
1630 case EXTERNAL_INT_ELEMENTS:
1631 case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
1632 break;
1633 }
1634 case EXTERNAL_FLOAT_ELEMENTS:
1635 case EXTERNAL_DOUBLE_ELEMENTS:
1636 break;
1637 case FAST_SMI_ELEMENTS:
1638 case FAST_ELEMENTS:
1639 case FAST_DOUBLE_ELEMENTS:
1640 case FAST_HOLEY_SMI_ELEMENTS:
1641 case FAST_HOLEY_ELEMENTS:
1642 case FAST_HOLEY_DOUBLE_ELEMENTS:
1643 case DICTIONARY_ELEMENTS:
1644 case NON_STRICT_ARGUMENTS_ELEMENTS:
1645 UNREACHABLE();
1646 break;
1647 } 1659 }
1648 return Add<HStoreKeyed>(external_elements, checked_key, val, elements_kind); 1660 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind);
1649 } else {
1650 ASSERT(val == NULL);
1651 HLoadKeyed* load = Add<HLoadKeyed>(external_elements,
1652 checked_key,
1653 dependency,
1654 elements_kind);
1655 if (FLAG_opt_safe_uint32_operations &&
1656 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
1657 graph()->RecordUint32Instruction(load);
1658 }
1659 return load;
1660 } 1661 }
1662
1663 ASSERT(!is_store);
1664 ASSERT(val == NULL);
1665 HLoadKeyed* load = Add<HLoadKeyed>(
1666 elements, checked_key, dependency, elements_kind, load_mode);
1667 if (FLAG_opt_safe_uint32_operations &&
1668 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
1669 graph()->RecordUint32Instruction(load);
1670 }
1671 return load;
1661 } 1672 }
1662 1673
1663 1674
1664 HInstruction* HGraphBuilder::AddFastElementAccess(
1665 HValue* elements,
1666 HValue* checked_key,
1667 HValue* val,
1668 HValue* load_dependency,
1669 ElementsKind elements_kind,
1670 bool is_store,
1671 LoadKeyedHoleMode load_mode,
1672 KeyedAccessStoreMode store_mode) {
1673 if (is_store) {
1674 ASSERT(val != NULL);
1675 switch (elements_kind) {
1676 case FAST_SMI_ELEMENTS:
1677 case FAST_HOLEY_SMI_ELEMENTS:
1678 case FAST_ELEMENTS:
1679 case FAST_HOLEY_ELEMENTS:
1680 case FAST_DOUBLE_ELEMENTS:
1681 case FAST_HOLEY_DOUBLE_ELEMENTS:
1682 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind);
1683 default:
1684 UNREACHABLE();
1685 return NULL;
1686 }
1687 }
1688 // It's an element load (!is_store).
1689 return Add<HLoadKeyed>(
1690 elements, checked_key, load_dependency, elements_kind, load_mode);
1691 }
1692
1693
1694 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) { 1675 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) {
1695 return Add<HLoadNamedField>(object, HObjectAccess::ForElementsPointer()); 1676 return Add<HLoadNamedField>(object, HObjectAccess::ForElementsPointer());
1696 } 1677 }
1697 1678
1698 1679
1699 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { 1680 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) {
1700 return Add<HLoadNamedField>(object, 1681 return Add<HLoadNamedField>(object,
1701 HObjectAccess::ForFixedArrayLength()); 1682 HObjectAccess::ForFixedArrayLength());
1702 } 1683 }
1703 1684
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
1930 } 1911 }
1931 } 1912 }
1932 1913
1933 return object; 1914 return object;
1934 } 1915 }
1935 1916
1936 1917
1937 void HGraphBuilder::BuildCompareNil( 1918 void HGraphBuilder::BuildCompareNil(
1938 HValue* value, 1919 HValue* value,
1939 Handle<Type> type, 1920 Handle<Type> type,
1940 int position,
1941 HIfContinuation* continuation) { 1921 HIfContinuation* continuation) {
1942 IfBuilder if_nil(this, position); 1922 IfBuilder if_nil(this);
1943 bool some_case_handled = false; 1923 bool some_case_handled = false;
1944 bool some_case_missing = false; 1924 bool some_case_missing = false;
1945 1925
1946 if (type->Maybe(Type::Null())) { 1926 if (type->Maybe(Type::Null())) {
1947 if (some_case_handled) if_nil.Or(); 1927 if (some_case_handled) if_nil.Or();
1948 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); 1928 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
1949 some_case_handled = true; 1929 some_case_handled = true;
1950 } else { 1930 } else {
1951 some_case_missing = true; 1931 some_case_missing = true;
1952 } 1932 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
2044 allocation_site_payload_(NULL), 2024 allocation_site_payload_(NULL),
2045 constructor_function_(constructor_function) { 2025 constructor_function_(constructor_function) {
2046 } 2026 }
2047 2027
2048 2028
2049 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { 2029 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
2050 if (kind_ == GetInitialFastElementsKind()) { 2030 if (kind_ == GetInitialFastElementsKind()) {
2051 // No need for a context lookup if the kind_ matches the initial 2031 // No need for a context lookup if the kind_ matches the initial
2052 // map, because we can just load the map in that case. 2032 // map, because we can just load the map in that case.
2053 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 2033 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
2054 return builder()->AddInstruction( 2034 return builder()->AddLoadNamedField(constructor_function_, access);
2055 builder()->BuildLoadNamedField(constructor_function_, access));
2056 } 2035 }
2057 2036
2058 HInstruction* native_context = builder()->BuildGetNativeContext(); 2037 HInstruction* native_context = builder()->BuildGetNativeContext();
2059 HInstruction* index = builder()->Add<HConstant>( 2038 HInstruction* index = builder()->Add<HConstant>(
2060 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); 2039 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
2061 2040
2062 HInstruction* map_array = builder()->Add<HLoadKeyed>( 2041 HInstruction* map_array = builder()->Add<HLoadKeyed>(
2063 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 2042 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
2064 2043
2065 HInstruction* kind_index = builder()->Add<HConstant>(kind_); 2044 HInstruction* kind_index = builder()->Add<HConstant>(kind_);
2066 2045
2067 return builder()->Add<HLoadKeyed>( 2046 return builder()->Add<HLoadKeyed>(
2068 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 2047 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
2069 } 2048 }
2070 2049
2071 2050
2072 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { 2051 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
2073 // Find the map near the constructor function 2052 // Find the map near the constructor function
2074 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 2053 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
2075 return builder()->AddInstruction( 2054 return builder()->AddLoadNamedField(constructor_function_, access);
2076 builder()->BuildLoadNamedField(constructor_function_, access));
2077 } 2055 }
2078 2056
2079 2057
2080 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( 2058 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize(
2081 HValue* length_node) { 2059 HValue* length_node) {
2082 ASSERT(length_node != NULL); 2060 ASSERT(length_node != NULL);
2083 2061
2084 int base_size = JSArray::kSize; 2062 int base_size = JSArray::kSize;
2085 if (mode_ == TRACK_ALLOCATION_SITE) { 2063 if (mode_ == TRACK_ALLOCATION_SITE) {
2086 base_size += AllocationMemento::kSize; 2064 base_size += AllocationMemento::kSize;
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
2200 break_scope_(NULL), 2178 break_scope_(NULL),
2201 inlined_count_(0), 2179 inlined_count_(0),
2202 globals_(10, info->zone()), 2180 globals_(10, info->zone()),
2203 inline_bailout_(false), 2181 inline_bailout_(false),
2204 osr_(new(info->zone()) HOsrBuilder(this)) { 2182 osr_(new(info->zone()) HOsrBuilder(this)) {
2205 // This is not initialized in the initializer list because the 2183 // This is not initialized in the initializer list because the
2206 // constructor for the initial state relies on function_state_ == NULL 2184 // constructor for the initial state relies on function_state_ == NULL
2207 // to know it's the initial state. 2185 // to know it's the initial state.
2208 function_state_= &initial_function_state_; 2186 function_state_= &initial_function_state_;
2209 InitializeAstVisitor(info->isolate()); 2187 InitializeAstVisitor(info->isolate());
2188 if (FLAG_emit_opt_code_positions) {
2189 SetSourcePosition(info->shared_info()->start_position());
2190 }
2210 } 2191 }
2211 2192
2212 2193
2213 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, 2194 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
2214 HBasicBlock* second, 2195 HBasicBlock* second,
2215 BailoutId join_id) { 2196 BailoutId join_id) {
2216 if (first == NULL) { 2197 if (first == NULL) {
2217 return second; 2198 return second;
2218 } else if (second == NULL) { 2199 } else if (second == NULL) {
2219 return first; 2200 return first;
2220 } else { 2201 } else {
2221 HBasicBlock* join_block = graph()->CreateBasicBlock(); 2202 HBasicBlock* join_block = graph()->CreateBasicBlock();
2222 first->Goto(join_block); 2203 Goto(first, join_block);
2223 second->Goto(join_block); 2204 Goto(second, join_block);
2224 join_block->SetJoinId(join_id); 2205 join_block->SetJoinId(join_id);
2225 return join_block; 2206 return join_block;
2226 } 2207 }
2227 } 2208 }
2228 2209
2229 2210
2230 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement, 2211 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
2231 HBasicBlock* exit_block, 2212 HBasicBlock* exit_block,
2232 HBasicBlock* continue_block) { 2213 HBasicBlock* continue_block) {
2233 if (continue_block != NULL) { 2214 if (continue_block != NULL) {
2234 if (exit_block != NULL) exit_block->Goto(continue_block); 2215 if (exit_block != NULL) Goto(exit_block, continue_block);
2235 continue_block->SetJoinId(statement->ContinueId()); 2216 continue_block->SetJoinId(statement->ContinueId());
2236 return continue_block; 2217 return continue_block;
2237 } 2218 }
2238 return exit_block; 2219 return exit_block;
2239 } 2220 }
2240 2221
2241 2222
2242 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement, 2223 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
2243 HBasicBlock* loop_entry, 2224 HBasicBlock* loop_entry,
2244 HBasicBlock* body_exit, 2225 HBasicBlock* body_exit,
2245 HBasicBlock* loop_successor, 2226 HBasicBlock* loop_successor,
2246 HBasicBlock* break_block) { 2227 HBasicBlock* break_block) {
2247 if (body_exit != NULL) body_exit->Goto(loop_entry); 2228 if (body_exit != NULL) Goto(body_exit, loop_entry);
2248 loop_entry->PostProcessLoopHeader(statement); 2229 loop_entry->PostProcessLoopHeader(statement);
2249 if (break_block != NULL) { 2230 if (break_block != NULL) {
2250 if (loop_successor != NULL) loop_successor->Goto(break_block); 2231 if (loop_successor != NULL) Goto(loop_successor, break_block);
2251 break_block->SetJoinId(statement->ExitId()); 2232 break_block->SetJoinId(statement->ExitId());
2252 return break_block; 2233 return break_block;
2253 } 2234 }
2254 return loop_successor; 2235 return loop_successor;
2255 } 2236 }
2256 2237
2257 2238
2258 // Build a new loop header block and set it as the current block. 2239 // Build a new loop header block and set it as the current block.
2259 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() { 2240 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
2260 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 2241 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2261 current_block()->Goto(loop_entry); 2242 Goto(loop_entry);
2262 set_current_block(loop_entry); 2243 set_current_block(loop_entry);
2263 return loop_entry; 2244 return loop_entry;
2264 } 2245 }
2265 2246
2266 2247
2267 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry( 2248 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
2268 IterationStatement* statement) { 2249 IterationStatement* statement) {
2269 HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement) 2250 HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
2270 ? osr()->BuildOsrLoopEntry(statement) 2251 ? osr()->BuildOsrLoopEntry(statement)
2271 : BuildLoopEntry(); 2252 : BuildLoopEntry();
2272 return loop_entry; 2253 return loop_entry;
2273 } 2254 }
2274 2255
2275 2256
2276 void HBasicBlock::FinishExit(HControlInstruction* instruction) { 2257 void HBasicBlock::FinishExit(HControlInstruction* instruction, int position) {
2277 Finish(instruction); 2258 Finish(instruction, position);
2278 ClearEnvironment(); 2259 ClearEnvironment();
2279 } 2260 }
2280 2261
2281 2262
2282 HGraph::HGraph(CompilationInfo* info) 2263 HGraph::HGraph(CompilationInfo* info)
2283 : isolate_(info->isolate()), 2264 : isolate_(info->isolate()),
2284 next_block_id_(0), 2265 next_block_id_(0),
2285 entry_block_(NULL), 2266 entry_block_(NULL),
2286 blocks_(8, info->zone()), 2267 blocks_(8, info->zone()),
2287 values_(16, info->zone()), 2268 values_(16, info->zone()),
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after
2815 } 2796 }
2816 2797
2817 2798
2818 void EffectContext::ReturnControl(HControlInstruction* instr, 2799 void EffectContext::ReturnControl(HControlInstruction* instr,
2819 BailoutId ast_id) { 2800 BailoutId ast_id) {
2820 ASSERT(!instr->HasObservableSideEffects()); 2801 ASSERT(!instr->HasObservableSideEffects());
2821 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); 2802 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
2822 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); 2803 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
2823 instr->SetSuccessorAt(0, empty_true); 2804 instr->SetSuccessorAt(0, empty_true);
2824 instr->SetSuccessorAt(1, empty_false); 2805 instr->SetSuccessorAt(1, empty_false);
2825 owner()->current_block()->Finish(instr); 2806 owner()->FinishCurrentBlock(instr);
2826 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); 2807 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
2827 owner()->set_current_block(join); 2808 owner()->set_current_block(join);
2828 } 2809 }
2829 2810
2830 2811
2831 void EffectContext::ReturnContinuation(HIfContinuation* continuation, 2812 void EffectContext::ReturnContinuation(HIfContinuation* continuation,
2832 BailoutId ast_id) { 2813 BailoutId ast_id) {
2833 HBasicBlock* true_branch = NULL; 2814 HBasicBlock* true_branch = NULL;
2834 HBasicBlock* false_branch = NULL; 2815 HBasicBlock* false_branch = NULL;
2835 continuation->Continue(&true_branch, &false_branch, NULL); 2816 continuation->Continue(&true_branch, &false_branch);
2836 if (!continuation->IsTrueReachable()) { 2817 if (!continuation->IsTrueReachable()) {
2837 owner()->set_current_block(false_branch); 2818 owner()->set_current_block(false_branch);
2838 } else if (!continuation->IsFalseReachable()) { 2819 } else if (!continuation->IsFalseReachable()) {
2839 owner()->set_current_block(true_branch); 2820 owner()->set_current_block(true_branch);
2840 } else { 2821 } else {
2841 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); 2822 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
2842 owner()->set_current_block(join); 2823 owner()->set_current_block(join);
2843 } 2824 }
2844 } 2825 }
2845 2826
(...skipping 13 matching lines...) Expand all
2859 2840
2860 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { 2841 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
2861 ASSERT(!instr->HasObservableSideEffects()); 2842 ASSERT(!instr->HasObservableSideEffects());
2862 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { 2843 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
2863 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); 2844 return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
2864 } 2845 }
2865 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); 2846 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
2866 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); 2847 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
2867 instr->SetSuccessorAt(0, materialize_true); 2848 instr->SetSuccessorAt(0, materialize_true);
2868 instr->SetSuccessorAt(1, materialize_false); 2849 instr->SetSuccessorAt(1, materialize_false);
2869 owner()->current_block()->Finish(instr); 2850 owner()->FinishCurrentBlock(instr);
2870 owner()->set_current_block(materialize_true); 2851 owner()->set_current_block(materialize_true);
2871 owner()->Push(owner()->graph()->GetConstantTrue()); 2852 owner()->Push(owner()->graph()->GetConstantTrue());
2872 owner()->set_current_block(materialize_false); 2853 owner()->set_current_block(materialize_false);
2873 owner()->Push(owner()->graph()->GetConstantFalse()); 2854 owner()->Push(owner()->graph()->GetConstantFalse());
2874 HBasicBlock* join = 2855 HBasicBlock* join =
2875 owner()->CreateJoin(materialize_true, materialize_false, ast_id); 2856 owner()->CreateJoin(materialize_true, materialize_false, ast_id);
2876 owner()->set_current_block(join); 2857 owner()->set_current_block(join);
2877 } 2858 }
2878 2859
2879 2860
2880 void ValueContext::ReturnContinuation(HIfContinuation* continuation, 2861 void ValueContext::ReturnContinuation(HIfContinuation* continuation,
2881 BailoutId ast_id) { 2862 BailoutId ast_id) {
2882 HBasicBlock* materialize_true = NULL; 2863 HBasicBlock* materialize_true = NULL;
2883 HBasicBlock* materialize_false = NULL; 2864 HBasicBlock* materialize_false = NULL;
2884 continuation->Continue(&materialize_true, &materialize_false, NULL); 2865 continuation->Continue(&materialize_true, &materialize_false);
2885 if (continuation->IsTrueReachable()) { 2866 if (continuation->IsTrueReachable()) {
2886 owner()->set_current_block(materialize_true); 2867 owner()->set_current_block(materialize_true);
2887 owner()->Push(owner()->graph()->GetConstantTrue()); 2868 owner()->Push(owner()->graph()->GetConstantTrue());
2888 owner()->set_current_block(materialize_true); 2869 owner()->set_current_block(materialize_true);
2889 } 2870 }
2890 if (continuation->IsFalseReachable()) { 2871 if (continuation->IsFalseReachable()) {
2891 owner()->set_current_block(materialize_false); 2872 owner()->set_current_block(materialize_false);
2892 owner()->Push(owner()->graph()->GetConstantFalse()); 2873 owner()->Push(owner()->graph()->GetConstantFalse());
2893 owner()->set_current_block(materialize_false); 2874 owner()->set_current_block(materialize_false);
2894 } 2875 }
(...skipping 19 matching lines...) Expand all
2914 BuildBranch(instr); 2895 BuildBranch(instr);
2915 } 2896 }
2916 2897
2917 2898
2918 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { 2899 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
2919 ASSERT(!instr->HasObservableSideEffects()); 2900 ASSERT(!instr->HasObservableSideEffects());
2920 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); 2901 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
2921 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); 2902 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
2922 instr->SetSuccessorAt(0, empty_true); 2903 instr->SetSuccessorAt(0, empty_true);
2923 instr->SetSuccessorAt(1, empty_false); 2904 instr->SetSuccessorAt(1, empty_false);
2924 owner()->current_block()->Finish(instr); 2905 owner()->FinishCurrentBlock(instr);
2925 empty_true->Goto(if_true(), owner()->function_state()); 2906 owner()->Goto(empty_true, if_true(), owner()->function_state());
2926 empty_false->Goto(if_false(), owner()->function_state()); 2907 owner()->Goto(empty_false, if_false(), owner()->function_state());
2927 owner()->set_current_block(NULL); 2908 owner()->set_current_block(NULL);
2928 } 2909 }
2929 2910
2930 2911
2931 void TestContext::ReturnContinuation(HIfContinuation* continuation, 2912 void TestContext::ReturnContinuation(HIfContinuation* continuation,
2932 BailoutId ast_id) { 2913 BailoutId ast_id) {
2933 HBasicBlock* true_branch = NULL; 2914 HBasicBlock* true_branch = NULL;
2934 HBasicBlock* false_branch = NULL; 2915 HBasicBlock* false_branch = NULL;
2935 continuation->Continue(&true_branch, &false_branch, NULL); 2916 continuation->Continue(&true_branch, &false_branch);
2936 if (continuation->IsTrueReachable()) { 2917 if (continuation->IsTrueReachable()) {
2937 true_branch->Goto(if_true(), owner()->function_state()); 2918 owner()->Goto(true_branch, if_true(), owner()->function_state());
2938 } 2919 }
2939 if (continuation->IsFalseReachable()) { 2920 if (continuation->IsFalseReachable()) {
2940 false_branch->Goto(if_false(), owner()->function_state()); 2921 owner()->Goto(false_branch, if_false(), owner()->function_state());
2941 } 2922 }
2942 owner()->set_current_block(NULL); 2923 owner()->set_current_block(NULL);
2943 } 2924 }
2944 2925
2945 2926
2946 void TestContext::BuildBranch(HValue* value) { 2927 void TestContext::BuildBranch(HValue* value) {
2947 // We expect the graph to be in edge-split form: there is no edge that 2928 // 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 2929 // 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 2930 // property by always adding an empty block on the outgoing edges of this
2950 // branch. 2931 // branch.
2951 HOptimizedGraphBuilder* builder = owner(); 2932 HOptimizedGraphBuilder* builder = owner();
2952 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { 2933 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
2953 builder->Bailout(kArgumentsObjectValueInATestContext); 2934 builder->Bailout(kArgumentsObjectValueInATestContext);
2954 } 2935 }
2955 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2936 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2956 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2937 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2957 ToBooleanStub::Types expected(condition()->to_boolean_types()); 2938 ToBooleanStub::Types expected(condition()->to_boolean_types());
2958 builder->current_block()->Finish(builder->New<HBranch>( 2939 builder->FinishCurrentBlock(builder->New<HBranch>(
2959 value, expected, empty_true, empty_false)); 2940 value, expected, empty_true, empty_false));
2960 2941
2961 empty_true->Goto(if_true(), builder->function_state()); 2942 owner()->Goto(empty_true, if_true(), builder->function_state());
2962 empty_false->Goto(if_false(), builder->function_state()); 2943 owner()->Goto(empty_false , if_false(), builder->function_state());
2963 builder->set_current_block(NULL); 2944 builder->set_current_block(NULL);
2964 } 2945 }
2965 2946
2966 2947
2967 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. 2948 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
2968 #define CHECK_BAILOUT(call) \ 2949 #define CHECK_BAILOUT(call) \
2969 do { \ 2950 do { \
2970 call; \ 2951 call; \
2971 if (HasStackOverflow()) return; \ 2952 if (HasStackOverflow()) return; \
2972 } while (false) 2953 } 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 3050 // the body's entry block (along with some special logic for the start
3070 // block in HInstruction::InsertAfter) seals the start block from 3051 // block in HInstruction::InsertAfter) seals the start block from
3071 // getting unwanted instructions inserted. 3052 // getting unwanted instructions inserted.
3072 // 3053 //
3073 // TODO(kmillikin): Fix this. Stop mutating the initial environment. 3054 // TODO(kmillikin): Fix this. Stop mutating the initial environment.
3074 // Make the Hydrogen instructions in the initial block into Hydrogen 3055 // Make the Hydrogen instructions in the initial block into Hydrogen
3075 // values (but not instructions), present in the initial environment and 3056 // values (but not instructions), present in the initial environment and
3076 // not replayed by the Lithium translation. 3057 // not replayed by the Lithium translation.
3077 HEnvironment* initial_env = environment()->CopyWithoutHistory(); 3058 HEnvironment* initial_env = environment()->CopyWithoutHistory();
3078 HBasicBlock* body_entry = CreateBasicBlock(initial_env); 3059 HBasicBlock* body_entry = CreateBasicBlock(initial_env);
3079 current_block()->Goto(body_entry); 3060 Goto(body_entry);
3080 body_entry->SetJoinId(BailoutId::FunctionEntry()); 3061 body_entry->SetJoinId(BailoutId::FunctionEntry());
3081 set_current_block(body_entry); 3062 set_current_block(body_entry);
3082 3063
3083 // Handle implicit declaration of the function name in named function 3064 // Handle implicit declaration of the function name in named function
3084 // expressions before other declarations. 3065 // expressions before other declarations.
3085 if (scope->is_function_scope() && scope->function() != NULL) { 3066 if (scope->is_function_scope() && scope->function() != NULL) {
3086 VisitVariableDeclaration(scope->function()); 3067 VisitVariableDeclaration(scope->function());
3087 } 3068 }
3088 VisitDeclarations(scope->declarations()); 3069 VisitDeclarations(scope->declarations());
3089 Add<HSimulate>(BailoutId::Declarations()); 3070 Add<HSimulate>(BailoutId::Declarations());
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
3227 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); 3208 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
3228 } else { 3209 } else {
3229 instruction->ReplaceAllUsesWith(instruction->ActualValue()); 3210 instruction->ReplaceAllUsesWith(instruction->ActualValue());
3230 } 3211 }
3231 } 3212 }
3232 } 3213 }
3233 } 3214 }
3234 } 3215 }
3235 3216
3236 3217
3237 void HGraphBuilder::PushAndAdd(HInstruction* instr) {
3238 Push(instr);
3239 AddInstruction(instr);
3240 }
3241
3242
3243 template <class Instruction> 3218 template <class Instruction>
3244 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { 3219 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
3245 int count = call->argument_count(); 3220 int count = call->argument_count();
3246 ZoneList<HValue*> arguments(count, zone()); 3221 ZoneList<HValue*> arguments(count, zone());
3247 for (int i = 0; i < count; ++i) { 3222 for (int i = 0; i < count; ++i) {
3248 arguments.Add(Pop(), zone()); 3223 arguments.Add(Pop(), zone());
3249 } 3224 }
3250 3225
3251 while (!arguments.is_empty()) { 3226 while (!arguments.is_empty()) {
3252 Add<HPushArgument>(arguments.RemoveLast()); 3227 Add<HPushArgument>(arguments.RemoveLast());
3253 } 3228 }
3254 return call; 3229 return call;
3255 } 3230 }
3256 3231
3257 3232
3258 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { 3233 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
3259 // First special is HContext. 3234 // First special is HContext.
3260 HInstruction* context = Add<HContext>(); 3235 HInstruction* context = Add<HContext>();
3261 environment()->BindContext(context); 3236 environment()->BindContext(context);
3262 3237
3263 HConstant* undefined_constant = HConstant::cast(Add<HConstant>(
3264 isolate()->factory()->undefined_value()));
3265 graph()->set_undefined_constant(undefined_constant);
3266
3267 // Create an arguments object containing the initial parameters. Set the 3238 // Create an arguments object containing the initial parameters. Set the
3268 // initial values of parameters including "this" having parameter index 0. 3239 // initial values of parameters including "this" having parameter index 0.
3269 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); 3240 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
3270 HArgumentsObject* arguments_object = 3241 HArgumentsObject* arguments_object =
3271 New<HArgumentsObject>(environment()->parameter_count()); 3242 New<HArgumentsObject>(environment()->parameter_count());
3272 for (int i = 0; i < environment()->parameter_count(); ++i) { 3243 for (int i = 0; i < environment()->parameter_count(); ++i) {
3273 HInstruction* parameter = Add<HParameter>(i); 3244 HInstruction* parameter = Add<HParameter>(i);
3274 arguments_object->AddArgument(parameter, zone()); 3245 arguments_object->AddArgument(parameter, zone());
3275 environment()->Bind(i, parameter); 3246 environment()->Bind(i, parameter);
3276 } 3247 }
3277 AddInstruction(arguments_object); 3248 AddInstruction(arguments_object);
3278 graph()->SetArgumentsObject(arguments_object); 3249 graph()->SetArgumentsObject(arguments_object);
3279 3250
3251 HConstant* undefined_constant = graph()->GetConstantUndefined();
3280 // Initialize specials and locals to undefined. 3252 // Initialize specials and locals to undefined.
3281 for (int i = environment()->parameter_count() + 1; 3253 for (int i = environment()->parameter_count() + 1;
3282 i < environment()->length(); 3254 i < environment()->length();
3283 ++i) { 3255 ++i) {
3284 environment()->Bind(i, undefined_constant); 3256 environment()->Bind(i, undefined_constant);
3285 } 3257 }
3286 3258
3287 // Handle the arguments and arguments shadow variables specially (they do 3259 // Handle the arguments and arguments shadow variables specially (they do
3288 // not have declarations). 3260 // not have declarations).
3289 if (scope->arguments() != NULL) { 3261 if (scope->arguments() != NULL) {
(...skipping 22 matching lines...) Expand all
3312 ASSERT(current_block()->HasPredecessor()); 3284 ASSERT(current_block()->HasPredecessor());
3313 if (stmt->scope() != NULL) { 3285 if (stmt->scope() != NULL) {
3314 return Bailout(kScopedBlock); 3286 return Bailout(kScopedBlock);
3315 } 3287 }
3316 BreakAndContinueInfo break_info(stmt); 3288 BreakAndContinueInfo break_info(stmt);
3317 { BreakAndContinueScope push(&break_info, this); 3289 { BreakAndContinueScope push(&break_info, this);
3318 CHECK_BAILOUT(VisitStatements(stmt->statements())); 3290 CHECK_BAILOUT(VisitStatements(stmt->statements()));
3319 } 3291 }
3320 HBasicBlock* break_block = break_info.break_block(); 3292 HBasicBlock* break_block = break_info.break_block();
3321 if (break_block != NULL) { 3293 if (break_block != NULL) {
3322 if (current_block() != NULL) current_block()->Goto(break_block); 3294 if (current_block() != NULL) Goto(break_block);
3323 break_block->SetJoinId(stmt->ExitId()); 3295 break_block->SetJoinId(stmt->ExitId());
3324 set_current_block(break_block); 3296 set_current_block(break_block);
3325 } 3297 }
3326 } 3298 }
3327 3299
3328 3300
3329 void HOptimizedGraphBuilder::VisitExpressionStatement( 3301 void HOptimizedGraphBuilder::VisitExpressionStatement(
3330 ExpressionStatement* stmt) { 3302 ExpressionStatement* stmt) {
3331 ASSERT(!HasStackOverflow()); 3303 ASSERT(!HasStackOverflow());
3332 ASSERT(current_block() != NULL); 3304 ASSERT(current_block() != NULL);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
3422 3394
3423 void HOptimizedGraphBuilder::VisitContinueStatement( 3395 void HOptimizedGraphBuilder::VisitContinueStatement(
3424 ContinueStatement* stmt) { 3396 ContinueStatement* stmt) {
3425 ASSERT(!HasStackOverflow()); 3397 ASSERT(!HasStackOverflow());
3426 ASSERT(current_block() != NULL); 3398 ASSERT(current_block() != NULL);
3427 ASSERT(current_block()->HasPredecessor()); 3399 ASSERT(current_block()->HasPredecessor());
3428 int drop_extra = 0; 3400 int drop_extra = 0;
3429 HBasicBlock* continue_block = break_scope()->Get( 3401 HBasicBlock* continue_block = break_scope()->Get(
3430 stmt->target(), BreakAndContinueScope::CONTINUE, &drop_extra); 3402 stmt->target(), BreakAndContinueScope::CONTINUE, &drop_extra);
3431 Drop(drop_extra); 3403 Drop(drop_extra);
3432 current_block()->Goto(continue_block); 3404 Goto(continue_block);
3433 set_current_block(NULL); 3405 set_current_block(NULL);
3434 } 3406 }
3435 3407
3436 3408
3437 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { 3409 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
3438 ASSERT(!HasStackOverflow()); 3410 ASSERT(!HasStackOverflow());
3439 ASSERT(current_block() != NULL); 3411 ASSERT(current_block() != NULL);
3440 ASSERT(current_block()->HasPredecessor()); 3412 ASSERT(current_block()->HasPredecessor());
3441 int drop_extra = 0; 3413 int drop_extra = 0;
3442 HBasicBlock* break_block = break_scope()->Get( 3414 HBasicBlock* break_block = break_scope()->Get(
3443 stmt->target(), BreakAndContinueScope::BREAK, &drop_extra); 3415 stmt->target(), BreakAndContinueScope::BREAK, &drop_extra);
3444 Drop(drop_extra); 3416 Drop(drop_extra);
3445 current_block()->Goto(break_block); 3417 Goto(break_block);
3446 set_current_block(NULL); 3418 set_current_block(NULL);
3447 } 3419 }
3448 3420
3449 3421
3450 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { 3422 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
3451 ASSERT(!HasStackOverflow()); 3423 ASSERT(!HasStackOverflow());
3452 ASSERT(current_block() != NULL); 3424 ASSERT(current_block() != NULL);
3453 ASSERT(current_block()->HasPredecessor()); 3425 ASSERT(current_block()->HasPredecessor());
3454 FunctionState* state = function_state(); 3426 FunctionState* state = function_state();
3455 AstContext* context = call_context(); 3427 AstContext* context = call_context();
3456 if (context == NULL) { 3428 if (context == NULL) {
3457 // Not an inlined return, so an actual one. 3429 // Not an inlined return, so an actual one.
3458 CHECK_ALIVE(VisitForValue(stmt->expression())); 3430 CHECK_ALIVE(VisitForValue(stmt->expression()));
3459 HValue* result = environment()->Pop(); 3431 HValue* result = environment()->Pop();
3460 Add<HReturn>(result); 3432 Add<HReturn>(result);
3461 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { 3433 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
3462 // Return from an inlined construct call. In a test context the return value 3434 // 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 3435 // will always evaluate to true, in a value context the return value needs
3464 // to be a JSObject. 3436 // to be a JSObject.
3465 if (context->IsTest()) { 3437 if (context->IsTest()) {
3466 TestContext* test = TestContext::cast(context); 3438 TestContext* test = TestContext::cast(context);
3467 CHECK_ALIVE(VisitForEffect(stmt->expression())); 3439 CHECK_ALIVE(VisitForEffect(stmt->expression()));
3468 current_block()->Goto(test->if_true(), state); 3440 Goto(test->if_true(), state);
3469 } else if (context->IsEffect()) { 3441 } else if (context->IsEffect()) {
3470 CHECK_ALIVE(VisitForEffect(stmt->expression())); 3442 CHECK_ALIVE(VisitForEffect(stmt->expression()));
3471 current_block()->Goto(function_return(), state); 3443 Goto(function_return(), state);
3472 } else { 3444 } else {
3473 ASSERT(context->IsValue()); 3445 ASSERT(context->IsValue());
3474 CHECK_ALIVE(VisitForValue(stmt->expression())); 3446 CHECK_ALIVE(VisitForValue(stmt->expression()));
3475 HValue* return_value = Pop(); 3447 HValue* return_value = Pop();
3476 HValue* receiver = environment()->arguments_environment()->Lookup(0); 3448 HValue* receiver = environment()->arguments_environment()->Lookup(0);
3477 HHasInstanceTypeAndBranch* typecheck = 3449 HHasInstanceTypeAndBranch* typecheck =
3478 new(zone()) HHasInstanceTypeAndBranch(return_value, 3450 New<HHasInstanceTypeAndBranch>(return_value,
3479 FIRST_SPEC_OBJECT_TYPE, 3451 FIRST_SPEC_OBJECT_TYPE,
3480 LAST_SPEC_OBJECT_TYPE); 3452 LAST_SPEC_OBJECT_TYPE);
3481 HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); 3453 HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
3482 HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); 3454 HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
3483 typecheck->SetSuccessorAt(0, if_spec_object); 3455 typecheck->SetSuccessorAt(0, if_spec_object);
3484 typecheck->SetSuccessorAt(1, not_spec_object); 3456 typecheck->SetSuccessorAt(1, not_spec_object);
3485 current_block()->Finish(typecheck); 3457 FinishCurrentBlock(typecheck);
3486 if_spec_object->AddLeaveInlined(return_value, state); 3458 AddLeaveInlined(if_spec_object, return_value, state);
3487 not_spec_object->AddLeaveInlined(receiver, state); 3459 AddLeaveInlined(not_spec_object, receiver, state);
3488 } 3460 }
3489 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { 3461 } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
3490 // Return from an inlined setter call. The returned value is never used, the 3462 // 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. 3463 // value of an assignment is always the value of the RHS of the assignment.
3492 CHECK_ALIVE(VisitForEffect(stmt->expression())); 3464 CHECK_ALIVE(VisitForEffect(stmt->expression()));
3493 if (context->IsTest()) { 3465 if (context->IsTest()) {
3494 HValue* rhs = environment()->arguments_environment()->Lookup(1); 3466 HValue* rhs = environment()->arguments_environment()->Lookup(1);
3495 context->ReturnValue(rhs); 3467 context->ReturnValue(rhs);
3496 } else if (context->IsEffect()) { 3468 } else if (context->IsEffect()) {
3497 current_block()->Goto(function_return(), state); 3469 Goto(function_return(), state);
3498 } else { 3470 } else {
3499 ASSERT(context->IsValue()); 3471 ASSERT(context->IsValue());
3500 HValue* rhs = environment()->arguments_environment()->Lookup(1); 3472 HValue* rhs = environment()->arguments_environment()->Lookup(1);
3501 current_block()->AddLeaveInlined(rhs, state); 3473 AddLeaveInlined(rhs, state);
3502 } 3474 }
3503 } else { 3475 } else {
3504 // Return from a normal inlined function. Visit the subexpression in the 3476 // Return from a normal inlined function. Visit the subexpression in the
3505 // expression context of the call. 3477 // expression context of the call.
3506 if (context->IsTest()) { 3478 if (context->IsTest()) {
3507 TestContext* test = TestContext::cast(context); 3479 TestContext* test = TestContext::cast(context);
3508 VisitForControl(stmt->expression(), test->if_true(), test->if_false()); 3480 VisitForControl(stmt->expression(), test->if_true(), test->if_false());
3509 } else if (context->IsEffect()) { 3481 } else if (context->IsEffect()) {
3510 CHECK_ALIVE(VisitForEffect(stmt->expression())); 3482 CHECK_ALIVE(VisitForEffect(stmt->expression()));
3511 current_block()->Goto(function_return(), state); 3483 Goto(function_return(), state);
3512 } else { 3484 } else {
3513 ASSERT(context->IsValue()); 3485 ASSERT(context->IsValue());
3514 CHECK_ALIVE(VisitForValue(stmt->expression())); 3486 CHECK_ALIVE(VisitForValue(stmt->expression()));
3515 current_block()->AddLeaveInlined(Pop(), state); 3487 AddLeaveInlined(Pop(), state);
3516 } 3488 }
3517 } 3489 }
3518 set_current_block(NULL); 3490 set_current_block(NULL);
3519 } 3491 }
3520 3492
3521 3493
3522 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { 3494 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
3523 ASSERT(!HasStackOverflow()); 3495 ASSERT(!HasStackOverflow());
3524 ASSERT(current_block() != NULL); 3496 ASSERT(current_block() != NULL);
3525 ASSERT(current_block()->HasPredecessor()); 3497 ASSERT(current_block()->HasPredecessor());
(...skipping 27 matching lines...) Expand all
3553 3525
3554 HUnaryControlInstruction* string_check = NULL; 3526 HUnaryControlInstruction* string_check = NULL;
3555 HBasicBlock* not_string_block = NULL; 3527 HBasicBlock* not_string_block = NULL;
3556 3528
3557 // Test switch's tag value if all clauses are string literals 3529 // Test switch's tag value if all clauses are string literals
3558 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { 3530 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) {
3559 first_test_block = graph()->CreateBasicBlock(); 3531 first_test_block = graph()->CreateBasicBlock();
3560 not_string_block = graph()->CreateBasicBlock(); 3532 not_string_block = graph()->CreateBasicBlock();
3561 string_check = New<HIsStringAndBranch>( 3533 string_check = New<HIsStringAndBranch>(
3562 tag_value, first_test_block, not_string_block); 3534 tag_value, first_test_block, not_string_block);
3563 current_block()->Finish(string_check); 3535 FinishCurrentBlock(string_check);
3564 3536
3565 set_current_block(first_test_block); 3537 set_current_block(first_test_block);
3566 } 3538 }
3567 3539
3568 // 1. Build all the tests, with dangling true branches 3540 // 1. Build all the tests, with dangling true branches
3569 BailoutId default_id = BailoutId::None(); 3541 BailoutId default_id = BailoutId::None();
3570 for (int i = 0; i < clause_count; ++i) { 3542 for (int i = 0; i < clause_count; ++i) {
3571 CaseClause* clause = clauses->at(i); 3543 CaseClause* clause = clauses->at(i);
3572 if (clause->is_default()) { 3544 if (clause->is_default()) {
3573 default_id = clause->EntryId(); 3545 default_id = clause->EntryId();
(...skipping 22 matching lines...) Expand all
3596 Representation::Smi(), Representation::Smi()); 3568 Representation::Smi(), Representation::Smi());
3597 compare = compare_; 3569 compare = compare_;
3598 } else { 3570 } else {
3599 compare = New<HStringCompareAndBranch>(tag_value, 3571 compare = New<HStringCompareAndBranch>(tag_value,
3600 label_value, 3572 label_value,
3601 Token::EQ_STRICT); 3573 Token::EQ_STRICT);
3602 } 3574 }
3603 3575
3604 compare->SetSuccessorAt(0, body_block); 3576 compare->SetSuccessorAt(0, body_block);
3605 compare->SetSuccessorAt(1, next_test_block); 3577 compare->SetSuccessorAt(1, next_test_block);
3606 current_block()->Finish(compare); 3578 FinishCurrentBlock(compare);
3607 3579
3608 set_current_block(next_test_block); 3580 set_current_block(next_test_block);
3609 } 3581 }
3610 3582
3611 // Save the current block to use for the default or to join with the 3583 // Save the current block to use for the default or to join with the
3612 // exit. 3584 // exit.
3613 HBasicBlock* last_block = current_block(); 3585 HBasicBlock* last_block = current_block();
3614 3586
3615 if (not_string_block != NULL) { 3587 if (not_string_block != NULL) {
3616 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId(); 3588 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
3677 } 3649 }
3678 3650
3679 // Create an up-to-3-way join. Use the break block if it exists since 3651 // Create an up-to-3-way join. Use the break block if it exists since
3680 // it's already a join block. 3652 // it's already a join block.
3681 HBasicBlock* break_block = break_info.break_block(); 3653 HBasicBlock* break_block = break_info.break_block();
3682 if (break_block == NULL) { 3654 if (break_block == NULL) {
3683 set_current_block(CreateJoin(fall_through_block, 3655 set_current_block(CreateJoin(fall_through_block,
3684 last_block, 3656 last_block,
3685 stmt->ExitId())); 3657 stmt->ExitId()));
3686 } else { 3658 } else {
3687 if (fall_through_block != NULL) fall_through_block->Goto(break_block); 3659 if (fall_through_block != NULL) Goto(fall_through_block, break_block);
3688 if (last_block != NULL) last_block->Goto(break_block); 3660 if (last_block != NULL) Goto(last_block, break_block);
3689 break_block->SetJoinId(stmt->ExitId()); 3661 break_block->SetJoinId(stmt->ExitId());
3690 set_current_block(break_block); 3662 set_current_block(break_block);
3691 } 3663 }
3692 } 3664 }
3693 3665
3694 3666
3695 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, 3667 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
3696 HBasicBlock* loop_entry, 3668 HBasicBlock* loop_entry,
3697 BreakAndContinueInfo* break_info) { 3669 BreakAndContinueInfo* break_info) {
3698 BreakAndContinueScope push(break_info, this); 3670 BreakAndContinueScope push(break_info, this);
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
3883 HCompareNumericAndBranch* compare_index = 3855 HCompareNumericAndBranch* compare_index =
3884 New<HCompareNumericAndBranch>(index, limit, Token::LT); 3856 New<HCompareNumericAndBranch>(index, limit, Token::LT);
3885 compare_index->set_observed_input_representation( 3857 compare_index->set_observed_input_representation(
3886 Representation::Smi(), Representation::Smi()); 3858 Representation::Smi(), Representation::Smi());
3887 3859
3888 HBasicBlock* loop_body = graph()->CreateBasicBlock(); 3860 HBasicBlock* loop_body = graph()->CreateBasicBlock();
3889 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); 3861 HBasicBlock* loop_successor = graph()->CreateBasicBlock();
3890 3862
3891 compare_index->SetSuccessorAt(0, loop_body); 3863 compare_index->SetSuccessorAt(0, loop_body);
3892 compare_index->SetSuccessorAt(1, loop_successor); 3864 compare_index->SetSuccessorAt(1, loop_successor);
3893 current_block()->Finish(compare_index); 3865 FinishCurrentBlock(compare_index);
3894 3866
3895 set_current_block(loop_successor); 3867 set_current_block(loop_successor);
3896 Drop(5); 3868 Drop(5);
3897 3869
3898 set_current_block(loop_body); 3870 set_current_block(loop_body);
3899 3871
3900 HValue* key = Add<HLoadKeyed>( 3872 HValue* key = Add<HLoadKeyed>(
3901 environment()->ExpressionStackAt(2), // Enum cache. 3873 environment()->ExpressionStackAt(2), // Enum cache.
3902 environment()->ExpressionStackAt(0), // Iteration index. 3874 environment()->ExpressionStackAt(0), // Iteration index.
3903 environment()->ExpressionStackAt(0), 3875 environment()->ExpressionStackAt(0),
3904 FAST_ELEMENTS); 3876 FAST_ELEMENTS);
3905 3877
3906 // Check if the expected map still matches that of the enumerable. 3878 // Check if the expected map still matches that of the enumerable.
3907 // If not just deoptimize. 3879 // If not just deoptimize.
3908 Add<HCheckMapValue>(environment()->ExpressionStackAt(4), 3880 Add<HCheckMapValue>(environment()->ExpressionStackAt(4),
3909 environment()->ExpressionStackAt(3)); 3881 environment()->ExpressionStackAt(3));
3910 3882
3911 Bind(each_var, key); 3883 Bind(each_var, key);
3912 3884
3913 BreakAndContinueInfo break_info(stmt, 5); 3885 BreakAndContinueInfo break_info(stmt, 5);
3914 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); 3886 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
3915 3887
3916 HBasicBlock* body_exit = 3888 HBasicBlock* body_exit =
3917 JoinContinue(stmt, current_block(), break_info.continue_block()); 3889 JoinContinue(stmt, current_block(), break_info.continue_block());
3918 3890
3919 if (body_exit != NULL) { 3891 if (body_exit != NULL) {
3920 set_current_block(body_exit); 3892 set_current_block(body_exit);
3921 3893
3922 HValue* current_index = Pop(); 3894 HValue* current_index = Pop();
3923 HInstruction* new_index = New<HAdd>(current_index, 3895 Push(Add<HAdd>(current_index, graph()->GetConstant1()));
3924 graph()->GetConstant1());
3925 PushAndAdd(new_index);
3926 body_exit = current_block(); 3896 body_exit = current_block();
3927 } 3897 }
3928 3898
3929 HBasicBlock* loop_exit = CreateLoop(stmt, 3899 HBasicBlock* loop_exit = CreateLoop(stmt,
3930 loop_entry, 3900 loop_entry,
3931 body_exit, 3901 body_exit,
3932 loop_successor, 3902 loop_successor,
3933 break_info.break_block()); 3903 break_info.break_block());
3934 3904
3935 set_current_block(loop_exit); 3905 set_current_block(loop_exit);
(...skipping 26 matching lines...) Expand all
3962 3932
3963 3933
3964 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 3934 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
3965 ASSERT(!HasStackOverflow()); 3935 ASSERT(!HasStackOverflow());
3966 ASSERT(current_block() != NULL); 3936 ASSERT(current_block() != NULL);
3967 ASSERT(current_block()->HasPredecessor()); 3937 ASSERT(current_block()->HasPredecessor());
3968 return Bailout(kDebuggerStatement); 3938 return Bailout(kDebuggerStatement);
3969 } 3939 }
3970 3940
3971 3941
3942 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
3943 UNREACHABLE();
3944 }
3945
3946
3972 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( 3947 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
3973 Code* unoptimized_code, FunctionLiteral* expr) { 3948 Code* unoptimized_code, FunctionLiteral* expr) {
3974 int start_position = expr->start_position(); 3949 int start_position = expr->start_position();
3975 for (RelocIterator it(unoptimized_code); !it.done(); it.next()) { 3950 for (RelocIterator it(unoptimized_code); !it.done(); it.next()) {
3976 RelocInfo* rinfo = it.rinfo(); 3951 RelocInfo* rinfo = it.rinfo();
3977 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; 3952 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
3978 Object* obj = rinfo->target_object(); 3953 Object* obj = rinfo->target_object();
3979 if (obj->IsSharedFunctionInfo()) { 3954 if (obj->IsSharedFunctionInfo()) {
3980 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); 3955 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
3981 if (shared->start_position() == start_position) { 3956 if (shared->start_position() == start_position) {
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
4117 cell->AddDependentCompilationInfo(top_info()); 4092 cell->AddDependentCompilationInfo(top_info());
4118 Handle<Object> constant_object = cell->type()->AsConstant(); 4093 Handle<Object> constant_object = cell->type()->AsConstant();
4119 if (constant_object->IsConsString()) { 4094 if (constant_object->IsConsString()) {
4120 constant_object = 4095 constant_object =
4121 FlattenGetString(Handle<String>::cast(constant_object)); 4096 FlattenGetString(Handle<String>::cast(constant_object));
4122 } 4097 }
4123 HConstant* constant = New<HConstant>(constant_object); 4098 HConstant* constant = New<HConstant>(constant_object);
4124 return ast_context()->ReturnInstruction(constant, expr->id()); 4099 return ast_context()->ReturnInstruction(constant, expr->id());
4125 } else { 4100 } else {
4126 HLoadGlobalCell* instr = 4101 HLoadGlobalCell* instr =
4127 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); 4102 New<HLoadGlobalCell>(cell, lookup.GetPropertyDetails());
4128 return ast_context()->ReturnInstruction(instr, expr->id()); 4103 return ast_context()->ReturnInstruction(instr, expr->id());
4129 } 4104 }
4130 } else { 4105 } else {
4131 HValue* context = environment()->context(); 4106 HGlobalObject* global_object = Add<HGlobalObject>();
4132 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
4133 AddInstruction(global_object);
4134 HLoadGlobalGeneric* instr = 4107 HLoadGlobalGeneric* instr =
4135 new(zone()) HLoadGlobalGeneric(context, 4108 New<HLoadGlobalGeneric>(global_object,
4136 global_object, 4109 variable->name(),
4137 variable->name(), 4110 ast_context()->is_for_typeof());
4138 ast_context()->is_for_typeof());
4139 instr->set_position(expr->position());
4140 return ast_context()->ReturnInstruction(instr, expr->id()); 4111 return ast_context()->ReturnInstruction(instr, expr->id());
4141 } 4112 }
4142 } 4113 }
4143 4114
4144 case Variable::PARAMETER: 4115 case Variable::PARAMETER:
4145 case Variable::LOCAL: { 4116 case Variable::LOCAL: {
4146 HValue* value = LookupAndMakeLive(variable); 4117 HValue* value = LookupAndMakeLive(variable);
4147 if (value == graph()->GetConstantHole()) { 4118 if (value == graph()->GetConstantHole()) {
4148 ASSERT(IsDeclaredVariableMode(variable->mode()) && 4119 ASSERT(IsDeclaredVariableMode(variable->mode()) &&
4149 variable->mode() != VAR); 4120 variable->mode() != VAR);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
4247 } 4218 }
4248 4219
4249 4220
4250 static bool LookupSetter(Handle<Map> map, 4221 static bool LookupSetter(Handle<Map> map,
4251 Handle<String> name, 4222 Handle<String> name,
4252 Handle<JSFunction>* setter, 4223 Handle<JSFunction>* setter,
4253 Handle<JSObject>* holder) { 4224 Handle<JSObject>* holder) {
4254 Handle<AccessorPair> accessors; 4225 Handle<AccessorPair> accessors;
4255 if (LookupAccessorPair(map, name, &accessors, holder) && 4226 if (LookupAccessorPair(map, name, &accessors, holder) &&
4256 accessors->setter()->IsJSFunction()) { 4227 accessors->setter()->IsJSFunction()) {
4257 *setter = Handle<JSFunction>(JSFunction::cast(accessors->setter())); 4228 Handle<JSFunction> func(JSFunction::cast(accessors->setter()));
4229 CallOptimization call_optimization(func);
4230 // TODO(dcarney): temporary hack unless crankshaft can handle api calls.
4231 if (call_optimization.is_simple_api_call()) return false;
4232 *setter = func;
4258 return true; 4233 return true;
4259 } 4234 }
4260 return false; 4235 return false;
4261 } 4236 }
4262 4237
4263 4238
4264 // Determines whether the given array or object literal boilerplate satisfies 4239 // Determines whether the given array or object literal boilerplate satisfies
4265 // all limits to be considered for fast deep-copying and computes the total 4240 // all limits to be considered for fast deep-copying and computes the total
4266 // size of all objects that are part of the graph. 4241 // size of all objects that are part of the graph.
4267 static bool IsFastLiteral(Handle<JSObject> boilerplate, 4242 static bool IsFastLiteral(Handle<JSObject> boilerplate,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
4328 4303
4329 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 4304 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
4330 ASSERT(!HasStackOverflow()); 4305 ASSERT(!HasStackOverflow());
4331 ASSERT(current_block() != NULL); 4306 ASSERT(current_block() != NULL);
4332 ASSERT(current_block()->HasPredecessor()); 4307 ASSERT(current_block()->HasPredecessor());
4333 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); 4308 Handle<JSFunction> closure = function_state()->compilation_info()->closure();
4334 HInstruction* literal; 4309 HInstruction* literal;
4335 4310
4336 // Check whether to use fast or slow deep-copying for boilerplate. 4311 // Check whether to use fast or slow deep-copying for boilerplate.
4337 int max_properties = kMaxFastLiteralProperties; 4312 int max_properties = kMaxFastLiteralProperties;
4338 Handle<Object> boilerplate(closure->literals()->get( 4313 Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()),
4339 expr->literal_index()), isolate()); 4314 isolate());
4340 if (boilerplate->IsJSObject() && 4315 Handle<AllocationSite> site;
4341 IsFastLiteral(Handle<JSObject>::cast(boilerplate), 4316 Handle<JSObject> boilerplate;
4342 kMaxFastLiteralDepth, 4317 if (!literals_cell->IsUndefined()) {
4343 &max_properties)) { 4318 // Retrieve the boilerplate
4344 Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate); 4319 site = Handle<AllocationSite>::cast(literals_cell);
4320 boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
4321 isolate());
4322 }
4345 4323
4346 literal = BuildFastLiteral(boilerplate_object); 4324 if (!boilerplate.is_null() &&
4325 IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
4326 AllocationSiteUsageContext usage_context(isolate(), site, false);
4327 usage_context.EnterNewScope();
4328 literal = BuildFastLiteral(boilerplate, &usage_context);
4329 usage_context.ExitScope(site, boilerplate);
4347 } else { 4330 } else {
4348 NoObservableSideEffectsScope no_effects(this); 4331 NoObservableSideEffectsScope no_effects(this);
4349 Handle<FixedArray> closure_literals(closure->literals(), isolate()); 4332 Handle<FixedArray> closure_literals(closure->literals(), isolate());
4350 Handle<FixedArray> constant_properties = expr->constant_properties(); 4333 Handle<FixedArray> constant_properties = expr->constant_properties();
4351 int literal_index = expr->literal_index(); 4334 int literal_index = expr->literal_index();
4352 int flags = expr->fast_elements() 4335 int flags = expr->fast_elements()
4353 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; 4336 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags;
4354 flags |= expr->has_function() 4337 flags |= expr->has_function()
4355 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; 4338 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags;
4356 4339
4357 Add<HPushArgument>(Add<HConstant>(closure_literals)); 4340 Add<HPushArgument>(Add<HConstant>(closure_literals));
4358 Add<HPushArgument>(Add<HConstant>(literal_index)); 4341 Add<HPushArgument>(Add<HConstant>(literal_index));
4359 Add<HPushArgument>(Add<HConstant>(constant_properties)); 4342 Add<HPushArgument>(Add<HConstant>(constant_properties));
4360 Add<HPushArgument>(Add<HConstant>(flags)); 4343 Add<HPushArgument>(Add<HConstant>(flags));
4361 4344
4345 // TODO(mvstanton): Add a flag to turn off creation of any
4346 // AllocationMementos for this call: we are in crankshaft and should have
4347 // learned enough about transition behavior to stop emitting mementos.
4362 Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral; 4348 Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
4363 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), 4349 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
4364 Runtime::FunctionForId(function_id), 4350 Runtime::FunctionForId(function_id),
4365 4); 4351 4);
4366 } 4352 }
4367 4353
4368 // The object is expected in the bailout environment during computation 4354 // The object is expected in the bailout environment during computation
4369 // of the property values and is the value of the entire expression. 4355 // of the property values and is the value of the entire expression.
4370 Push(literal); 4356 Push(literal);
4371 4357
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
4442 ASSERT(current_block()->HasPredecessor()); 4428 ASSERT(current_block()->HasPredecessor());
4443 ZoneList<Expression*>* subexprs = expr->values(); 4429 ZoneList<Expression*>* subexprs = expr->values();
4444 int length = subexprs->length(); 4430 int length = subexprs->length();
4445 HInstruction* literal; 4431 HInstruction* literal;
4446 4432
4447 Handle<AllocationSite> site; 4433 Handle<AllocationSite> site;
4448 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); 4434 Handle<FixedArray> literals(environment()->closure()->literals(), isolate());
4449 bool uninitialized = false; 4435 bool uninitialized = false;
4450 Handle<Object> literals_cell(literals->get(expr->literal_index()), 4436 Handle<Object> literals_cell(literals->get(expr->literal_index()),
4451 isolate()); 4437 isolate());
4452 Handle<Object> raw_boilerplate; 4438 Handle<JSObject> boilerplate_object;
4453 if (literals_cell->IsUndefined()) { 4439 if (literals_cell->IsUndefined()) {
4454 uninitialized = true; 4440 uninitialized = true;
4455 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( 4441 Handle<Object> raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate(
4456 isolate(), literals, expr->constant_elements()); 4442 isolate(), literals, expr->constant_elements());
4457 if (raw_boilerplate.is_null()) { 4443 if (raw_boilerplate.is_null()) {
4458 return Bailout(kArrayBoilerplateCreationFailed); 4444 return Bailout(kArrayBoilerplateCreationFailed);
4459 } 4445 }
4460 4446
4461 site = isolate()->factory()->NewAllocationSite(); 4447 boilerplate_object = Handle<JSObject>::cast(raw_boilerplate);
4462 site->set_transition_info(*raw_boilerplate); 4448 AllocationSiteCreationContext creation_context(isolate());
4449 site = creation_context.EnterNewScope();
4450 if (JSObject::DeepWalk(boilerplate_object, &creation_context).is_null()) {
4451 return Bailout(kArrayBoilerplateCreationFailed);
4452 }
4453 creation_context.ExitScope(site, boilerplate_object);
4463 literals->set(expr->literal_index(), *site); 4454 literals->set(expr->literal_index(), *site);
4464 4455
4465 if (JSObject::cast(*raw_boilerplate)->elements()->map() == 4456 if (boilerplate_object->elements()->map() ==
4466 isolate()->heap()->fixed_cow_array_map()) { 4457 isolate()->heap()->fixed_cow_array_map()) {
4467 isolate()->counters()->cow_arrays_created_runtime()->Increment(); 4458 isolate()->counters()->cow_arrays_created_runtime()->Increment();
4468 } 4459 }
4469 } else { 4460 } else {
4470 ASSERT(literals_cell->IsAllocationSite()); 4461 ASSERT(literals_cell->IsAllocationSite());
4471 site = Handle<AllocationSite>::cast(literals_cell); 4462 site = Handle<AllocationSite>::cast(literals_cell);
4472 raw_boilerplate = Handle<Object>(site->transition_info(), isolate()); 4463 boilerplate_object = Handle<JSObject>(
4464 JSObject::cast(site->transition_info()), isolate());
4473 } 4465 }
4474 4466
4475 ASSERT(!raw_boilerplate.is_null()); 4467 ASSERT(!boilerplate_object.is_null());
4476 ASSERT(site->IsLiteralSite()); 4468 ASSERT(site->SitePointsToLiteral());
4477 4469
4478 Handle<JSObject> boilerplate_object =
4479 Handle<JSObject>::cast(raw_boilerplate);
4480 ElementsKind boilerplate_elements_kind = 4470 ElementsKind boilerplate_elements_kind =
4481 Handle<JSObject>::cast(boilerplate_object)->GetElementsKind(); 4471 boilerplate_object->GetElementsKind();
4482
4483 ASSERT(AllocationSite::CanTrack(boilerplate_object->map()->instance_type()));
4484 4472
4485 // Check whether to use fast or slow deep-copying for boilerplate. 4473 // Check whether to use fast or slow deep-copying for boilerplate.
4486 int max_properties = kMaxFastLiteralProperties; 4474 int max_properties = kMaxFastLiteralProperties;
4487 if (IsFastLiteral(boilerplate_object, 4475 if (IsFastLiteral(boilerplate_object,
4488 kMaxFastLiteralDepth, 4476 kMaxFastLiteralDepth,
4489 &max_properties)) { 4477 &max_properties)) {
4490 literal = BuildFastLiteral(boilerplate_object); 4478 AllocationSiteUsageContext usage_context(isolate(), site, false);
4479 usage_context.EnterNewScope();
4480 literal = BuildFastLiteral(boilerplate_object, &usage_context);
4481 usage_context.ExitScope(site, boilerplate_object);
4491 } else { 4482 } else {
4492 NoObservableSideEffectsScope no_effects(this); 4483 NoObservableSideEffectsScope no_effects(this);
4493 // Boilerplate already exists and constant elements are never accessed, 4484 // Boilerplate already exists and constant elements are never accessed,
4494 // pass an empty fixed array to the runtime function instead. 4485 // pass an empty fixed array to the runtime function instead.
4495 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); 4486 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
4496 int literal_index = expr->literal_index(); 4487 int literal_index = expr->literal_index();
4497 4488
4498 Add<HPushArgument>(Add<HConstant>(literals)); 4489 Add<HPushArgument>(Add<HConstant>(literals));
4499 Add<HPushArgument>(Add<HConstant>(literal_index)); 4490 Add<HPushArgument>(Add<HConstant>(literal_index));
4500 Add<HPushArgument>(Add<HConstant>(constants)); 4491 Add<HPushArgument>(Add<HConstant>(constants));
4501 4492
4493 // TODO(mvstanton): Consider a flag to turn off creation of any
4494 // AllocationMementos for this call: we are in crankshaft and should have
4495 // learned enough about transition behavior to stop emitting mementos.
4502 Runtime::FunctionId function_id = (expr->depth() > 1) 4496 Runtime::FunctionId function_id = (expr->depth() > 1)
4503 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; 4497 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow;
4504 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), 4498 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
4505 Runtime::FunctionForId(function_id), 4499 Runtime::FunctionForId(function_id),
4506 3); 4500 3);
4507 4501
4508 // De-opt if elements kind changed from boilerplate_elements_kind. 4502 // De-opt if elements kind changed from boilerplate_elements_kind.
4509 Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate()); 4503 Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate());
4510 literal = Add<HCheckMaps>(literal, map, top_info()); 4504 literal = Add<HCheckMaps>(literal, map, top_info());
4511 } 4505 }
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
4645 instr->SetGVNFlag(kChangesMaps); 4639 instr->SetGVNFlag(kChangesMaps);
4646 } 4640 }
4647 return instr; 4641 return instr;
4648 } 4642 }
4649 4643
4650 4644
4651 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( 4645 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric(
4652 HValue* object, 4646 HValue* object,
4653 Handle<String> name, 4647 Handle<String> name,
4654 HValue* value) { 4648 HValue* value) {
4655 HValue* context = environment()->context(); 4649 return New<HStoreNamedGeneric>(
4656 return new(zone()) HStoreNamedGeneric(
4657 context,
4658 object, 4650 object,
4659 name, 4651 name,
4660 value, 4652 value,
4661 function_strict_mode_flag()); 4653 function_strict_mode_flag());
4662 } 4654 }
4663 4655
4664 4656
4665 // Sets the lookup result and returns true if the load/store can be inlined. 4657 // Sets the lookup result and returns true if the load/store can be inlined.
4666 static bool ComputeStoreField(Handle<Map> type, 4658 static bool ComputeStoreField(Handle<Map> type,
4667 Handle<String> name, 4659 Handle<String> name,
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
4743 4735
4744 4736
4745 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { 4737 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
4746 if (lookup_.IsField()) { 4738 if (lookup_.IsField()) {
4747 access_ = HObjectAccess::ForField(map, &lookup_, name_); 4739 access_ = HObjectAccess::ForField(map, &lookup_, name_);
4748 } else if (lookup_.IsPropertyCallbacks()) { 4740 } else if (lookup_.IsPropertyCallbacks()) {
4749 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); 4741 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate());
4750 if (!callback->IsAccessorPair()) return false; 4742 if (!callback->IsAccessorPair()) return false;
4751 Object* getter = Handle<AccessorPair>::cast(callback)->getter(); 4743 Object* getter = Handle<AccessorPair>::cast(callback)->getter();
4752 if (!getter->IsJSFunction()) return false; 4744 if (!getter->IsJSFunction()) return false;
4753 accessor_ = handle(JSFunction::cast(getter)); 4745 Handle<JSFunction> accessor = handle(JSFunction::cast(getter));
4746 CallOptimization call_optimization(accessor);
4747 // TODO(dcarney): temporary hack unless crankshaft can handle api calls.
4748 if (call_optimization.is_simple_api_call()) return false;
4749 accessor_ = accessor;
4754 } else if (lookup_.IsConstant()) { 4750 } else if (lookup_.IsConstant()) {
4755 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); 4751 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate());
4756 } 4752 }
4757 4753
4758 return true; 4754 return true;
4759 } 4755 }
4760 4756
4761 4757
4762 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { 4758 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
4763 Handle<Map> map = map_; 4759 Handle<Map> map = map_;
4764 while (map->prototype()->IsJSObject()) { 4760 while (map->prototype()->IsJSObject()) {
4765 holder_ = handle(JSObject::cast(map->prototype())); 4761 holder_ = handle(JSObject::cast(map->prototype()));
4762 if (holder_->map()->is_deprecated()) {
4763 JSObject::TryMigrateInstance(holder_);
4764 }
4766 map = Handle<Map>(holder_->map()); 4765 map = Handle<Map>(holder_->map());
4767 if (!CanInlinePropertyAccess(*map)) { 4766 if (!CanInlinePropertyAccess(*map)) {
4768 lookup_.NotFound(); 4767 lookup_.NotFound();
4769 return false; 4768 return false;
4770 } 4769 }
4771 map->LookupDescriptor(*holder_, *name_, &lookup_); 4770 map->LookupDescriptor(*holder_, *name_, &lookup_);
4772 if (lookup_.IsFound()) return LoadResult(map); 4771 if (lookup_.IsFound()) return LoadResult(map);
4773 } 4772 }
4774 lookup_.NotFound(); 4773 lookup_.NotFound();
4775 return true; 4774 return true;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
4862 Add<HPushArgument>(Pop()); 4861 Add<HPushArgument>(Pop());
4863 return New<HCallConstantFunction>(info->accessor(), 1); 4862 return New<HCallConstantFunction>(info->accessor(), 1);
4864 } 4863 }
4865 4864
4866 ASSERT(info->lookup()->IsConstant()); 4865 ASSERT(info->lookup()->IsConstant());
4867 return New<HConstant>(info->constant()); 4866 return New<HConstant>(info->constant());
4868 } 4867 }
4869 4868
4870 4869
4871 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 4870 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
4872 int position,
4873 BailoutId ast_id, 4871 BailoutId ast_id,
4874 BailoutId return_id, 4872 BailoutId return_id,
4875 HValue* object, 4873 HValue* object,
4876 SmallMapList* types, 4874 SmallMapList* types,
4877 Handle<String> name) { 4875 Handle<String> name) {
4878 // Something did not match; must use a polymorphic load. 4876 // Something did not match; must use a polymorphic load.
4879 int count = 0; 4877 int count = 0;
4880 HBasicBlock* join = NULL; 4878 HBasicBlock* join = NULL;
4881 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { 4879 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
4882 PropertyAccessInfo info(isolate(), types->at(i), name); 4880 PropertyAccessInfo info(isolate(), types->at(i), name);
4883 if (info.CanLoadMonomorphic()) { 4881 if (info.CanLoadMonomorphic()) {
4884 if (count == 0) { 4882 if (count == 0) {
4885 BuildCheckHeapObject(object); 4883 BuildCheckHeapObject(object);
4886 join = graph()->CreateBasicBlock(); 4884 join = graph()->CreateBasicBlock();
4887 } 4885 }
4888 ++count; 4886 ++count;
4889 HBasicBlock* if_true = graph()->CreateBasicBlock(); 4887 HBasicBlock* if_true = graph()->CreateBasicBlock();
4890 HBasicBlock* if_false = graph()->CreateBasicBlock(); 4888 HBasicBlock* if_false = graph()->CreateBasicBlock();
4891 HCompareMap* compare = New<HCompareMap>( 4889 HCompareMap* compare = New<HCompareMap>(
4892 object, info.map(), if_true, if_false); 4890 object, info.map(), if_true, if_false);
4893 current_block()->Finish(compare); 4891 FinishCurrentBlock(compare);
4894 4892
4895 set_current_block(if_true); 4893 set_current_block(if_true);
4896 4894
4897 HInstruction* load = BuildLoadMonomorphic( 4895 HInstruction* load = BuildLoadMonomorphic(
4898 &info, object, compare, ast_id, return_id, FLAG_polymorphic_inlining); 4896 &info, object, compare, ast_id, return_id, FLAG_polymorphic_inlining);
4899 if (load == NULL) { 4897 if (load == NULL) {
4900 if (HasStackOverflow()) return; 4898 if (HasStackOverflow()) return;
4901 } else { 4899 } else {
4902 if (!load->IsLinked()) { 4900 if (!load->IsLinked()) {
4903 load->set_position(position);
4904 AddInstruction(load); 4901 AddInstruction(load);
4905 } 4902 }
4906 if (!ast_context()->IsEffect()) Push(load); 4903 if (!ast_context()->IsEffect()) Push(load);
4907 } 4904 }
4908 4905
4909 if (current_block() != NULL) current_block()->Goto(join); 4906 if (current_block() != NULL) Goto(join);
4910 set_current_block(if_false); 4907 set_current_block(if_false);
4911 } 4908 }
4912 } 4909 }
4913 4910
4914 // Finish up. Unconditionally deoptimize if we've handled all the maps we 4911 // Finish up. Unconditionally deoptimize if we've handled all the maps we
4915 // know about and do not want to handle ones we've never seen. Otherwise 4912 // know about and do not want to handle ones we've never seen. Otherwise
4916 // use a generic IC. 4913 // use a generic IC.
4917 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 4914 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
4918 // Because the deopt may be the only path in the polymorphic load, make sure 4915 // Because the deopt may be the only path in the polymorphic load, make sure
4919 // that the environment stack matches the depth on deopt that it otherwise 4916 // that the environment stack matches the depth on deopt that it otherwise
4920 // would have had after a successful load. 4917 // would have had after a successful load.
4921 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); 4918 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
4922 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); 4919 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
4923 } else { 4920 } else {
4924 HValue* context = environment()->context(); 4921 HInstruction* load = Add<HLoadNamedGeneric>(object, name);
4925 HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name);
4926 load->set_position(position);
4927 AddInstruction(load);
4928 if (!ast_context()->IsEffect()) Push(load); 4922 if (!ast_context()->IsEffect()) Push(load);
4929 4923
4930 if (join != NULL) { 4924 if (join != NULL) {
4931 current_block()->Goto(join); 4925 Goto(join);
4932 } else { 4926 } else {
4933 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 4927 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4934 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 4928 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
4935 return; 4929 return;
4936 } 4930 }
4937 } 4931 }
4938 4932
4939 ASSERT(join != NULL); 4933 ASSERT(join != NULL);
4940 join->SetJoinId(ast_id); 4934 join->SetJoinId(ast_id);
4941 set_current_block(join); 4935 set_current_block(join);
4942 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 4936 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
4943 } 4937 }
4944 4938
4945 4939
4946 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( 4940 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
4947 int position,
4948 BailoutId assignment_id, 4941 BailoutId assignment_id,
4949 HValue* object, 4942 HValue* object,
4950 HValue* value, 4943 HValue* value,
4951 SmallMapList* types, 4944 SmallMapList* types,
4952 Handle<String> name) { 4945 Handle<String> name) {
4953 // Use monomorphic store if property lookup results in the same field index 4946 // Use monomorphic store if property lookup results in the same field index
4954 // for all maps. Requires special map check on the set of all handled maps. 4947 // for all maps. Requires special map check on the set of all handled maps.
4955 if (types->length() > kMaxStorePolymorphism) return false; 4948 if (types->length() > kMaxStorePolymorphism) return false;
4956 4949
4957 LookupResult lookup(isolate()); 4950 LookupResult lookup(isolate());
(...skipping 29 matching lines...) Expand all
4987 4980
4988 // Everything matched; can use monomorphic store. 4981 // Everything matched; can use monomorphic store.
4989 BuildCheckHeapObject(object); 4982 BuildCheckHeapObject(object);
4990 HCheckMaps* checked_object = Add<HCheckMaps>(object, types); 4983 HCheckMaps* checked_object = Add<HCheckMaps>(object, types);
4991 HInstruction* store; 4984 HInstruction* store;
4992 CHECK_ALIVE_OR_RETURN( 4985 CHECK_ALIVE_OR_RETURN(
4993 store = BuildStoreNamedField( 4986 store = BuildStoreNamedField(
4994 checked_object, name, value, types->at(count - 1), &lookup), 4987 checked_object, name, value, types->at(count - 1), &lookup),
4995 true); 4988 true);
4996 if (!ast_context()->IsEffect()) Push(value); 4989 if (!ast_context()->IsEffect()) Push(value);
4997 store->set_position(position);
4998 AddInstruction(store); 4990 AddInstruction(store);
4999 Add<HSimulate>(assignment_id); 4991 Add<HSimulate>(assignment_id);
5000 if (!ast_context()->IsEffect()) Drop(1); 4992 if (!ast_context()->IsEffect()) Drop(1);
5001 ast_context()->ReturnValue(value); 4993 ast_context()->ReturnValue(value);
5002 return true; 4994 return true;
5003 } 4995 }
5004 4996
5005 4997
5006 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( 4998 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
5007 int position,
5008 BailoutId assignment_id, 4999 BailoutId assignment_id,
5009 HValue* object, 5000 HValue* object,
5010 HValue* value, 5001 HValue* value,
5011 SmallMapList* types, 5002 SmallMapList* types,
5012 Handle<String> name) { 5003 Handle<String> name) {
5013 if (TryStorePolymorphicAsMonomorphic( 5004 if (TryStorePolymorphicAsMonomorphic(
5014 position, assignment_id, object, value, types, name)) { 5005 assignment_id, object, value, types, name)) {
5015 return; 5006 return;
5016 } 5007 }
5017 5008
5018 // TODO(ager): We should recognize when the prototype chains for different 5009 // TODO(ager): We should recognize when the prototype chains for different
5019 // maps are identical. In that case we can avoid repeatedly generating the 5010 // maps are identical. In that case we can avoid repeatedly generating the
5020 // same prototype map checks. 5011 // same prototype map checks.
5021 int count = 0; 5012 int count = 0;
5022 HBasicBlock* join = NULL; 5013 HBasicBlock* join = NULL;
5023 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { 5014 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
5024 Handle<Map> map = types->at(i); 5015 Handle<Map> map = types->at(i);
5025 LookupResult lookup(isolate()); 5016 LookupResult lookup(isolate());
5026 if (ComputeStoreField(map, name, &lookup)) { 5017 if (ComputeStoreField(map, name, &lookup)) {
5027 if (count == 0) { 5018 if (count == 0) {
5028 BuildCheckHeapObject(object); 5019 BuildCheckHeapObject(object);
5029 join = graph()->CreateBasicBlock(); 5020 join = graph()->CreateBasicBlock();
5030 } 5021 }
5031 ++count; 5022 ++count;
5032 HBasicBlock* if_true = graph()->CreateBasicBlock(); 5023 HBasicBlock* if_true = graph()->CreateBasicBlock();
5033 HBasicBlock* if_false = graph()->CreateBasicBlock(); 5024 HBasicBlock* if_false = graph()->CreateBasicBlock();
5034 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false); 5025 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false);
5035 current_block()->Finish(compare); 5026 FinishCurrentBlock(compare);
5036 5027
5037 set_current_block(if_true); 5028 set_current_block(if_true);
5038 HInstruction* instr; 5029 HInstruction* instr;
5039 CHECK_ALIVE(instr = BuildStoreNamedField( 5030 CHECK_ALIVE(instr = BuildStoreNamedField(
5040 compare, name, value, map, &lookup)); 5031 compare, name, value, map, &lookup));
5041 instr->set_position(position);
5042 // Goto will add the HSimulate for the store. 5032 // Goto will add the HSimulate for the store.
5043 AddInstruction(instr); 5033 AddInstruction(instr);
5044 if (!ast_context()->IsEffect()) Push(value); 5034 if (!ast_context()->IsEffect()) Push(value);
5045 current_block()->Goto(join); 5035 Goto(join);
5046 5036
5047 set_current_block(if_false); 5037 set_current_block(if_false);
5048 } 5038 }
5049 } 5039 }
5050 5040
5051 // Finish up. Unconditionally deoptimize if we've handled all the maps we 5041 // Finish up. Unconditionally deoptimize if we've handled all the maps we
5052 // know about and do not want to handle ones we've never seen. Otherwise 5042 // know about and do not want to handle ones we've never seen. Otherwise
5053 // use a generic IC. 5043 // use a generic IC.
5054 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 5044 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
5055 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join); 5045 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join);
5056 } else { 5046 } else {
5057 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); 5047 HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
5058 instr->set_position(position);
5059 AddInstruction(instr); 5048 AddInstruction(instr);
5060 5049
5061 if (join != NULL) { 5050 if (join != NULL) {
5062 if (!ast_context()->IsEffect()) { 5051 if (!ast_context()->IsEffect()) {
5063 Push(value); 5052 Push(value);
5064 } 5053 }
5065 current_block()->Goto(join); 5054 Goto(join);
5066 } else { 5055 } else {
5067 // The HSimulate for the store should not see the stored value in 5056 // The HSimulate for the store should not see the stored value in
5068 // effect contexts (it is not materialized at expr->id() in the 5057 // effect contexts (it is not materialized at expr->id() in the
5069 // unoptimized code). 5058 // unoptimized code).
5070 if (instr->HasObservableSideEffects()) { 5059 if (instr->HasObservableSideEffects()) {
5071 if (ast_context()->IsEffect()) { 5060 if (ast_context()->IsEffect()) {
5072 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); 5061 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
5073 } else { 5062 } else {
5074 Push(value); 5063 Push(value);
5075 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); 5064 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
5109 BailoutId ast_id, 5098 BailoutId ast_id,
5110 BailoutId return_id, 5099 BailoutId return_id,
5111 bool is_uninitialized) { 5100 bool is_uninitialized) {
5112 HValue* value = environment()->ExpressionStackAt(0); 5101 HValue* value = environment()->ExpressionStackAt(0);
5113 5102
5114 if (!prop->key()->IsPropertyName()) { 5103 if (!prop->key()->IsPropertyName()) {
5115 // Keyed store. 5104 // Keyed store.
5116 HValue* key = environment()->ExpressionStackAt(1); 5105 HValue* key = environment()->ExpressionStackAt(1);
5117 HValue* object = environment()->ExpressionStackAt(2); 5106 HValue* object = environment()->ExpressionStackAt(2);
5118 bool has_side_effects = false; 5107 bool has_side_effects = false;
5119 HandleKeyedElementAccess(object, key, value, expr, return_id, 5108 HandleKeyedElementAccess(object, key, value, expr,
5120 expr->position(),
5121 true, // is_store 5109 true, // is_store
5122 &has_side_effects); 5110 &has_side_effects);
5123 Drop(3); 5111 Drop(3);
5124 Push(value); 5112 Push(value);
5125 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); 5113 Add<HSimulate>(return_id, REMOVABLE_SIMULATE);
5126 return ast_context()->ReturnValue(Pop()); 5114 return ast_context()->ReturnValue(Pop());
5127 } 5115 }
5128 5116
5129 // Named store. 5117 // Named store.
5130 HValue* object = environment()->ExpressionStackAt(1); 5118 HValue* object = environment()->ExpressionStackAt(1);
(...skipping 28 matching lines...) Expand all
5159 instr = New<HCallConstantFunction>(setter, 2); 5147 instr = New<HCallConstantFunction>(setter, 2);
5160 } else { 5148 } else {
5161 Drop(2); 5149 Drop(2);
5162 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, 5150 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
5163 name, 5151 name,
5164 value, 5152 value,
5165 map)); 5153 map));
5166 } 5154 }
5167 } else if (types != NULL && types->length() > 1) { 5155 } else if (types != NULL && types->length() > 1) {
5168 Drop(2); 5156 Drop(2);
5169 return HandlePolymorphicStoreNamedField( 5157 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name);
5170 expr->position(), ast_id, object, value, types, name);
5171 } else { 5158 } else {
5172 Drop(2); 5159 Drop(2);
5173 instr = BuildStoreNamedGeneric(object, name, value); 5160 instr = BuildStoreNamedGeneric(object, name, value);
5174 } 5161 }
5175 5162
5176 if (!ast_context()->IsEffect()) Push(value); 5163 if (!ast_context()->IsEffect()) Push(value);
5177 instr->set_position(expr->position());
5178 AddInstruction(instr); 5164 AddInstruction(instr);
5179 if (instr->HasObservableSideEffects()) { 5165 if (instr->HasObservableSideEffects()) {
5180 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5166 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
5181 } 5167 }
5182 if (!ast_context()->IsEffect()) Drop(1); 5168 if (!ast_context()->IsEffect()) Drop(1);
5183 return ast_context()->ReturnValue(value); 5169 return ast_context()->ReturnValue(value);
5184 } 5170 }
5185 5171
5186 5172
5187 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 5173 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
5188 Property* prop = expr->target()->AsProperty(); 5174 Property* prop = expr->target()->AsProperty();
5189 ASSERT(prop != NULL); 5175 ASSERT(prop != NULL);
5190 CHECK_ALIVE(VisitForValue(prop->obj())); 5176 CHECK_ALIVE(VisitForValue(prop->obj()));
5191 if (!prop->key()->IsPropertyName()) { 5177 if (!prop->key()->IsPropertyName()) {
5192 CHECK_ALIVE(VisitForValue(prop->key())); 5178 CHECK_ALIVE(VisitForValue(prop->key()));
5193 } 5179 }
5194 CHECK_ALIVE(VisitForValue(expr->value())); 5180 CHECK_ALIVE(VisitForValue(expr->value()));
5195 BuildStore(expr, prop, expr->id(), 5181 BuildStore(expr, prop, expr->id(),
5196 expr->AssignmentId(), expr->IsUninitialized()); 5182 expr->AssignmentId(), expr->IsUninitialized());
5197 } 5183 }
5198 5184
5199 5185
5200 // Because not every expression has a position and there is not common 5186 // Because not every expression has a position and there is not common
5201 // superclass of Assignment and CountOperation, we cannot just pass the 5187 // superclass of Assignment and CountOperation, we cannot just pass the
5202 // owning expression instead of position and ast_id separately. 5188 // owning expression instead of position and ast_id separately.
5203 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( 5189 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
5204 Variable* var, 5190 Variable* var,
5205 HValue* value, 5191 HValue* value,
5206 int position,
5207 BailoutId ast_id) { 5192 BailoutId ast_id) {
5208 LookupResult lookup(isolate()); 5193 LookupResult lookup(isolate());
5209 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); 5194 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
5210 if (type == kUseCell) { 5195 if (type == kUseCell) {
5211 Handle<GlobalObject> global(current_info()->global_object()); 5196 Handle<GlobalObject> global(current_info()->global_object());
5212 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); 5197 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
5213 if (cell->type()->IsConstant()) { 5198 if (cell->type()->IsConstant()) {
5214 IfBuilder builder(this); 5199 IfBuilder builder(this);
5215 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); 5200 HValue* constant = Add<HConstant>(cell->type()->AsConstant());
5216 if (cell->type()->AsConstant()->IsNumber()) { 5201 if (cell->type()->AsConstant()->IsNumber()) {
5217 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); 5202 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ);
5218 } else { 5203 } else {
5219 builder.If<HCompareObjectEqAndBranch>(value, constant); 5204 builder.If<HCompareObjectEqAndBranch>(value, constant);
5220 } 5205 }
5221 builder.Then(); 5206 builder.Then();
5222 builder.Else(); 5207 builder.Else();
5223 Add<HDeoptimize>("Constant global variable assignment", 5208 Add<HDeoptimize>("Constant global variable assignment",
5224 Deoptimizer::EAGER); 5209 Deoptimizer::EAGER);
5225 builder.End(); 5210 builder.End();
5226 } 5211 }
5227 HInstruction* instr = 5212 HInstruction* instr =
5228 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); 5213 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
5229 instr->set_position(position);
5230 if (instr->HasObservableSideEffects()) { 5214 if (instr->HasObservableSideEffects()) {
5231 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5215 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
5232 } 5216 }
5233 } else { 5217 } else {
5234 HGlobalObject* global_object = Add<HGlobalObject>(); 5218 HGlobalObject* global_object = Add<HGlobalObject>();
5235 HStoreGlobalGeneric* instr = 5219 HStoreGlobalGeneric* instr =
5236 Add<HStoreGlobalGeneric>(global_object, var->name(), 5220 Add<HStoreGlobalGeneric>(global_object, var->name(),
5237 value, function_strict_mode_flag()); 5221 value, function_strict_mode_flag());
5238 instr->set_position(position); 5222 USE(instr);
5239 ASSERT(instr->HasObservableSideEffects()); 5223 ASSERT(instr->HasObservableSideEffects());
5240 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5224 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
5241 } 5225 }
5242 } 5226 }
5243 5227
5244 5228
5245 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 5229 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
5246 Expression* target = expr->target(); 5230 Expression* target = expr->target();
5247 VariableProxy* proxy = target->AsVariableProxy(); 5231 VariableProxy* proxy = target->AsVariableProxy();
5248 Property* prop = target->AsProperty(); 5232 Property* prop = target->AsProperty();
5249 ASSERT(proxy == NULL || prop == NULL); 5233 ASSERT(proxy == NULL || prop == NULL);
5250 5234
5251 // We have a second position recorded in the FullCodeGenerator to have 5235 // We have a second position recorded in the FullCodeGenerator to have
5252 // type feedback for the binary operation. 5236 // type feedback for the binary operation.
5253 BinaryOperation* operation = expr->binary_operation(); 5237 BinaryOperation* operation = expr->binary_operation();
5254 5238
5255 if (proxy != NULL) { 5239 if (proxy != NULL) {
5256 Variable* var = proxy->var(); 5240 Variable* var = proxy->var();
5257 if (var->mode() == LET) { 5241 if (var->mode() == LET) {
5258 return Bailout(kUnsupportedLetCompoundAssignment); 5242 return Bailout(kUnsupportedLetCompoundAssignment);
5259 } 5243 }
5260 5244
5261 CHECK_ALIVE(VisitForValue(operation)); 5245 CHECK_ALIVE(VisitForValue(operation));
5262 5246
5263 switch (var->location()) { 5247 switch (var->location()) {
5264 case Variable::UNALLOCATED: 5248 case Variable::UNALLOCATED:
5265 HandleGlobalVariableAssignment(var, 5249 HandleGlobalVariableAssignment(var,
5266 Top(), 5250 Top(),
5267 expr->position(),
5268 expr->AssignmentId()); 5251 expr->AssignmentId());
5269 break; 5252 break;
5270 5253
5271 case Variable::PARAMETER: 5254 case Variable::PARAMETER:
5272 case Variable::LOCAL: 5255 case Variable::LOCAL:
5273 if (var->mode() == CONST) { 5256 if (var->mode() == CONST) {
5274 return Bailout(kUnsupportedConstCompoundAssignment); 5257 return Bailout(kUnsupportedConstCompoundAssignment);
5275 } 5258 }
5276 BindIfLive(var, Top()); 5259 BindIfLive(var, Top());
5277 break; 5260 break;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
5325 } else if (prop != NULL) { 5308 } else if (prop != NULL) {
5326 CHECK_ALIVE(VisitForValue(prop->obj())); 5309 CHECK_ALIVE(VisitForValue(prop->obj()));
5327 HValue* object = Top(); 5310 HValue* object = Top();
5328 HValue* key = NULL; 5311 HValue* key = NULL;
5329 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || 5312 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) ||
5330 prop->IsStringAccess()) { 5313 prop->IsStringAccess()) {
5331 CHECK_ALIVE(VisitForValue(prop->key())); 5314 CHECK_ALIVE(VisitForValue(prop->key()));
5332 key = Top(); 5315 key = Top();
5333 } 5316 }
5334 5317
5335 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); 5318 CHECK_ALIVE(PushLoad(prop, object, key));
5336 5319
5337 CHECK_ALIVE(VisitForValue(expr->value())); 5320 CHECK_ALIVE(VisitForValue(expr->value()));
5338 HValue* right = Pop(); 5321 HValue* right = Pop();
5339 HValue* left = Pop(); 5322 HValue* left = Pop();
5340 5323
5341 HInstruction* instr = BuildBinaryOperation(operation, left, right); 5324 HInstruction* instr = BuildBinaryOperation(operation, left, right);
5342 PushAndAdd(instr); 5325 AddInstruction(instr);
5326 Push(instr);
5343 if (instr->HasObservableSideEffects()) { 5327 if (instr->HasObservableSideEffects()) {
5344 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); 5328 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
5345 } 5329 }
5346 BuildStore(expr, prop, expr->id(), 5330 BuildStore(expr, prop, expr->id(),
5347 expr->AssignmentId(), expr->IsUninitialized()); 5331 expr->AssignmentId(), expr->IsUninitialized());
5348 } else { 5332 } else {
5349 return Bailout(kInvalidLhsInCompoundAssignment); 5333 return Bailout(kInvalidLhsInCompoundAssignment);
5350 } 5334 }
5351 } 5335 }
5352 5336
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
5388 } 5372 }
5389 5373
5390 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments); 5374 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
5391 5375
5392 // Handle the assignment. 5376 // Handle the assignment.
5393 switch (var->location()) { 5377 switch (var->location()) {
5394 case Variable::UNALLOCATED: 5378 case Variable::UNALLOCATED:
5395 CHECK_ALIVE(VisitForValue(expr->value())); 5379 CHECK_ALIVE(VisitForValue(expr->value()));
5396 HandleGlobalVariableAssignment(var, 5380 HandleGlobalVariableAssignment(var,
5397 Top(), 5381 Top(),
5398 expr->position(),
5399 expr->AssignmentId()); 5382 expr->AssignmentId());
5400 return ast_context()->ReturnValue(Pop()); 5383 return ast_context()->ReturnValue(Pop());
5401 5384
5402 case Variable::PARAMETER: 5385 case Variable::PARAMETER:
5403 case Variable::LOCAL: { 5386 case Variable::LOCAL: {
5404 // Perform an initialization check for let declared variables 5387 // Perform an initialization check for let declared variables
5405 // or parameters. 5388 // or parameters.
5406 if (var->mode() == LET && expr->op() == Token::ASSIGN) { 5389 if (var->mode() == LET && expr->op() == Token::ASSIGN) {
5407 HValue* env_value = environment()->Lookup(var); 5390 HValue* env_value = environment()->Lookup(var);
5408 if (env_value == graph()->GetConstantHole()) { 5391 if (env_value == graph()->GetConstantHole()) {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
5487 ASSERT(!HasStackOverflow()); 5470 ASSERT(!HasStackOverflow());
5488 ASSERT(current_block() != NULL); 5471 ASSERT(current_block() != NULL);
5489 ASSERT(current_block()->HasPredecessor()); 5472 ASSERT(current_block()->HasPredecessor());
5490 // We don't optimize functions with invalid left-hand sides in 5473 // We don't optimize functions with invalid left-hand sides in
5491 // assignments, count operations, or for-in. Consequently throw can 5474 // assignments, count operations, or for-in. Consequently throw can
5492 // currently only occur in an effect context. 5475 // currently only occur in an effect context.
5493 ASSERT(ast_context()->IsEffect()); 5476 ASSERT(ast_context()->IsEffect());
5494 CHECK_ALIVE(VisitForValue(expr->exception())); 5477 CHECK_ALIVE(VisitForValue(expr->exception()));
5495 5478
5496 HValue* value = environment()->Pop(); 5479 HValue* value = environment()->Pop();
5497 HThrow* instr = Add<HThrow>(value); 5480 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
5498 instr->set_position(expr->position()); 5481 Add<HThrow>(value);
5499 Add<HSimulate>(expr->id()); 5482 Add<HSimulate>(expr->id());
5500 5483
5501 // If the throw definitely exits the function, we can finish with a dummy 5484 // If the throw definitely exits the function, we can finish with a dummy
5502 // control flow at this point. This is not the case if the throw is inside 5485 // control flow at this point. This is not the case if the throw is inside
5503 // an inlined function which may be replaced. 5486 // an inlined function which may be replaced.
5504 if (call_context() == NULL) { 5487 if (call_context() == NULL) {
5505 current_block()->FinishExit(new(zone()) HAbnormalExit); 5488 FinishExitCurrentBlock(New<HAbnormalExit>());
5506 set_current_block(NULL);
5507 } 5489 }
5508 } 5490 }
5509 5491
5510 5492
5511 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, 5493 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
5512 HObjectAccess access) { 5494 HObjectAccess access) {
5513 if (FLAG_track_double_fields && access.representation().IsDouble()) { 5495 if (FLAG_track_double_fields && access.representation().IsDouble()) {
5514 // load the heap number 5496 // load the heap number
5515 HLoadNamedField* heap_number = Add<HLoadNamedField>( 5497 HLoadNamedField* heap_number = Add<HLoadNamedField>(
5516 object, access.WithRepresentation(Representation::Tagged())); 5498 object, access.WithRepresentation(Representation::Tagged()));
5517 heap_number->set_type(HType::HeapNumber()); 5499 heap_number->set_type(HType::HeapNumber());
5518 // load the double value from it 5500 // load the double value from it
5519 return New<HLoadNamedField>( 5501 return New<HLoadNamedField>(
5520 heap_number, HObjectAccess::ForHeapNumberValue()); 5502 heap_number, HObjectAccess::ForHeapNumberValue());
5521 } 5503 }
5522 return New<HLoadNamedField>(object, access); 5504 return New<HLoadNamedField>(object, access);
5523 } 5505 }
5524 5506
5525 5507
5508 HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object,
5509 HObjectAccess access) {
5510 return AddInstruction(BuildLoadNamedField(object, access));
5511 }
5512
5513
5526 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object, 5514 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object,
5527 HValue* checked_string) { 5515 HValue* checked_string) {
5528 if (FLAG_fold_constants && object->IsConstant()) { 5516 if (FLAG_fold_constants && object->IsConstant()) {
5529 HConstant* constant = HConstant::cast(object); 5517 HConstant* constant = HConstant::cast(object);
5530 if (constant->HasStringValue()) { 5518 if (constant->HasStringValue()) {
5531 return New<HConstant>(constant->StringValue()->length()); 5519 return New<HConstant>(constant->StringValue()->length());
5532 } 5520 }
5533 } 5521 }
5534 return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength()); 5522 return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength());
5535 } 5523 }
5536 5524
5537 5525
5538 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( 5526 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
5539 HValue* object, 5527 HValue* object,
5540 Handle<String> name, 5528 Handle<String> name,
5541 Property* expr) { 5529 Property* expr) {
5542 if (expr->IsUninitialized()) { 5530 if (expr->IsUninitialized()) {
5543 Add<HDeoptimize>("Insufficient type feedback for generic named load", 5531 Add<HDeoptimize>("Insufficient type feedback for generic named load",
5544 Deoptimizer::SOFT); 5532 Deoptimizer::SOFT);
5545 } 5533 }
5546 HValue* context = environment()->context(); 5534 return New<HLoadNamedGeneric>(object, name);
5547 return new(zone()) HLoadNamedGeneric(context, object, name);
5548 } 5535 }
5549 5536
5550 5537
5551 5538
5552 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 5539 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
5553 HValue* key) { 5540 HValue* key) {
5554 HValue* context = environment()->context(); 5541 return New<HLoadKeyedGeneric>(object, key);
5555 return new(zone()) HLoadKeyedGeneric(context, object, key);
5556 } 5542 }
5557 5543
5558 5544
5559 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { 5545 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
5560 // Loads from a "stock" fast holey double arrays can elide the hole check. 5546 // Loads from a "stock" fast holey double arrays can elide the hole check.
5561 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; 5547 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
5562 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && 5548 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
5563 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { 5549 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
5564 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); 5550 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
5565 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); 5551 Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
5659 false, NEVER_RETURN_HOLE, STANDARD_STORE); 5645 false, NEVER_RETURN_HOLE, STANDARD_STORE);
5660 return instr; 5646 return instr;
5661 } 5647 }
5662 5648
5663 5649
5664 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( 5650 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
5665 HValue* object, 5651 HValue* object,
5666 HValue* key, 5652 HValue* key,
5667 HValue* val, 5653 HValue* val,
5668 SmallMapList* maps, 5654 SmallMapList* maps,
5669 BailoutId ast_id,
5670 int position,
5671 bool is_store, 5655 bool is_store,
5672 KeyedAccessStoreMode store_mode, 5656 KeyedAccessStoreMode store_mode,
5673 bool* has_side_effects) { 5657 bool* has_side_effects) {
5674 *has_side_effects = false; 5658 *has_side_effects = false;
5675 BuildCheckHeapObject(object); 5659 BuildCheckHeapObject(object);
5676 5660
5677 if (!is_store) { 5661 if (!is_store) {
5678 HInstruction* consolidated_load = 5662 HInstruction* consolidated_load =
5679 TryBuildConsolidatedElementLoad(object, key, val, maps); 5663 TryBuildConsolidatedElementLoad(object, key, val, maps);
5680 if (consolidated_load != NULL) { 5664 if (consolidated_load != NULL) {
5681 *has_side_effects |= consolidated_load->HasObservableSideEffects(); 5665 *has_side_effects |= consolidated_load->HasObservableSideEffects();
5682 if (position != RelocInfo::kNoPosition) {
5683 consolidated_load->set_position(position);
5684 }
5685 return consolidated_load; 5666 return consolidated_load;
5686 } 5667 }
5687 } 5668 }
5688 5669
5689 // Elements_kind transition support. 5670 // Elements_kind transition support.
5690 MapHandleList transition_target(maps->length()); 5671 MapHandleList transition_target(maps->length());
5691 // Collect possible transition targets. 5672 // Collect possible transition targets.
5692 MapHandleList possible_transitioned_maps(maps->length()); 5673 MapHandleList possible_transitioned_maps(maps->length());
5693 for (int i = 0; i < maps->length(); ++i) { 5674 for (int i = 0; i < maps->length(); ++i) {
5694 Handle<Map> map = maps->at(i); 5675 Handle<Map> map = maps->at(i);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
5731 if (untransitionable_map->has_slow_elements_kind() || 5712 if (untransitionable_map->has_slow_elements_kind() ||
5732 !untransitionable_map->IsJSObjectMap()) { 5713 !untransitionable_map->IsJSObjectMap()) {
5733 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 5714 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
5734 : BuildLoadKeyedGeneric(object, key)); 5715 : BuildLoadKeyedGeneric(object, key));
5735 } else { 5716 } else {
5736 instr = BuildMonomorphicElementAccess( 5717 instr = BuildMonomorphicElementAccess(
5737 object, key, val, transition, untransitionable_map, is_store, 5718 object, key, val, transition, untransitionable_map, is_store,
5738 store_mode); 5719 store_mode);
5739 } 5720 }
5740 *has_side_effects |= instr->HasObservableSideEffects(); 5721 *has_side_effects |= instr->HasObservableSideEffects();
5741 if (position != RelocInfo::kNoPosition) instr->set_position(position);
5742 return is_store ? NULL : instr; 5722 return is_store ? NULL : instr;
5743 } 5723 }
5744 5724
5745 HBasicBlock* join = graph()->CreateBasicBlock(); 5725 HBasicBlock* join = graph()->CreateBasicBlock();
5746 5726
5747 for (int i = 0; i < untransitionable_maps.length(); ++i) { 5727 for (int i = 0; i < untransitionable_maps.length(); ++i) {
5748 Handle<Map> map = untransitionable_maps[i]; 5728 Handle<Map> map = untransitionable_maps[i];
5749 if (!map->IsJSObjectMap()) continue; 5729 if (!map->IsJSObjectMap()) continue;
5750 ElementsKind elements_kind = map->elements_kind(); 5730 ElementsKind elements_kind = map->elements_kind();
5751 HBasicBlock* this_map = graph()->CreateBasicBlock(); 5731 HBasicBlock* this_map = graph()->CreateBasicBlock();
5752 HBasicBlock* other_map = graph()->CreateBasicBlock(); 5732 HBasicBlock* other_map = graph()->CreateBasicBlock();
5753 HCompareMap* mapcompare = 5733 HCompareMap* mapcompare =
5754 New<HCompareMap>(object, map, this_map, other_map); 5734 New<HCompareMap>(object, map, this_map, other_map);
5755 current_block()->Finish(mapcompare); 5735 FinishCurrentBlock(mapcompare);
5756 5736
5757 set_current_block(this_map); 5737 set_current_block(this_map);
5758 HInstruction* access = NULL; 5738 HInstruction* access = NULL;
5759 if (IsDictionaryElementsKind(elements_kind)) { 5739 if (IsDictionaryElementsKind(elements_kind)) {
5760 access = is_store 5740 access = is_store
5761 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val)) 5741 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val))
5762 : AddInstruction(BuildLoadKeyedGeneric(object, key)); 5742 : AddInstruction(BuildLoadKeyedGeneric(object, key));
5763 } else { 5743 } else {
5764 ASSERT(IsFastElementsKind(elements_kind) || 5744 ASSERT(IsFastElementsKind(elements_kind) ||
5765 IsExternalArrayElementsKind(elements_kind)); 5745 IsExternalArrayElementsKind(elements_kind));
5766 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); 5746 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
5767 // Happily, mapcompare is a checked object. 5747 // Happily, mapcompare is a checked object.
5768 access = BuildUncheckedMonomorphicElementAccess( 5748 access = BuildUncheckedMonomorphicElementAccess(
5769 mapcompare, key, val, 5749 mapcompare, key, val,
5770 map->instance_type() == JS_ARRAY_TYPE, 5750 map->instance_type() == JS_ARRAY_TYPE,
5771 elements_kind, is_store, 5751 elements_kind, is_store,
5772 load_mode, 5752 load_mode,
5773 store_mode); 5753 store_mode);
5774 } 5754 }
5775 *has_side_effects |= access->HasObservableSideEffects(); 5755 *has_side_effects |= access->HasObservableSideEffects();
5776 // The caller will use has_side_effects and add a correct Simulate. 5756 // The caller will use has_side_effects and add a correct Simulate.
5777 access->SetFlag(HValue::kHasNoObservableSideEffects); 5757 access->SetFlag(HValue::kHasNoObservableSideEffects);
5778 if (position != RelocInfo::kNoPosition) access->set_position(position);
5779 if (!is_store) { 5758 if (!is_store) {
5780 Push(access); 5759 Push(access);
5781 } 5760 }
5782 NoObservableSideEffectsScope scope(this); 5761 NoObservableSideEffectsScope scope(this);
5783 current_block()->GotoNoSimulate(join); 5762 GotoNoSimulate(join);
5784 set_current_block(other_map); 5763 set_current_block(other_map);
5785 } 5764 }
5786 5765
5787 // Deopt if none of the cases matched. 5766 // Deopt if none of the cases matched.
5788 NoObservableSideEffectsScope scope(this); 5767 NoObservableSideEffectsScope scope(this);
5789 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access", 5768 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access",
5790 join); 5769 join);
5791 set_current_block(join); 5770 set_current_block(join);
5792 return is_store ? NULL : Pop(); 5771 return is_store ? NULL : Pop();
5793 } 5772 }
5794 5773
5795 5774
5796 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( 5775 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
5797 HValue* obj, 5776 HValue* obj,
5798 HValue* key, 5777 HValue* key,
5799 HValue* val, 5778 HValue* val,
5800 Expression* expr, 5779 Expression* expr,
5801 BailoutId ast_id,
5802 int position,
5803 bool is_store, 5780 bool is_store,
5804 bool* has_side_effects) { 5781 bool* has_side_effects) {
5805 ASSERT(!expr->IsPropertyName()); 5782 ASSERT(!expr->IsPropertyName());
5806 HInstruction* instr = NULL; 5783 HInstruction* instr = NULL;
5807 5784
5808 SmallMapList* types; 5785 SmallMapList* types;
5809 bool monomorphic = ComputeReceiverTypes(expr, obj, &types); 5786 bool monomorphic = ComputeReceiverTypes(expr, obj, &types);
5810 5787
5811 if (monomorphic) { 5788 if (monomorphic) {
5812 Handle<Map> map = types->first(); 5789 Handle<Map> map = types->first();
5813 if (map->has_slow_elements_kind()) { 5790 if (map->has_slow_elements_kind()) {
5814 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 5791 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
5815 : BuildLoadKeyedGeneric(obj, key); 5792 : BuildLoadKeyedGeneric(obj, key);
5816 AddInstruction(instr); 5793 AddInstruction(instr);
5817 } else { 5794 } else {
5818 BuildCheckHeapObject(obj); 5795 BuildCheckHeapObject(obj);
5819 instr = BuildMonomorphicElementAccess( 5796 instr = BuildMonomorphicElementAccess(
5820 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); 5797 obj, key, val, NULL, map, is_store, expr->GetStoreMode());
5821 } 5798 }
5822 } else if (types != NULL && !types->is_empty()) { 5799 } else if (types != NULL && !types->is_empty()) {
5823 return HandlePolymorphicElementAccess( 5800 return HandlePolymorphicElementAccess(
5824 obj, key, val, types, ast_id, position, is_store, 5801 obj, key, val, types, is_store,
5825 expr->GetStoreMode(), has_side_effects); 5802 expr->GetStoreMode(), has_side_effects);
5826 } else { 5803 } else {
5827 if (is_store) { 5804 if (is_store) {
5828 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { 5805 if (expr->IsAssignment() &&
5806 expr->AsAssignment()->HasNoTypeInformation()) {
5829 Add<HDeoptimize>("Insufficient type feedback for keyed store", 5807 Add<HDeoptimize>("Insufficient type feedback for keyed store",
5830 Deoptimizer::SOFT); 5808 Deoptimizer::SOFT);
5831 } 5809 }
5832 instr = BuildStoreKeyedGeneric(obj, key, val); 5810 instr = BuildStoreKeyedGeneric(obj, key, val);
5833 } else { 5811 } else {
5834 if (expr->AsProperty()->IsUninitialized()) { 5812 if (expr->AsProperty()->HasNoTypeInformation()) {
5835 Add<HDeoptimize>("Insufficient type feedback for keyed load", 5813 Add<HDeoptimize>("Insufficient type feedback for keyed load",
5836 Deoptimizer::SOFT); 5814 Deoptimizer::SOFT);
5837 } 5815 }
5838 instr = BuildLoadKeyedGeneric(obj, key); 5816 instr = BuildLoadKeyedGeneric(obj, key);
5839 } 5817 }
5840 AddInstruction(instr); 5818 AddInstruction(instr);
5841 } 5819 }
5842 if (position != RelocInfo::kNoPosition) instr->set_position(position);
5843 *has_side_effects = instr->HasObservableSideEffects(); 5820 *has_side_effects = instr->HasObservableSideEffects();
5844 return instr; 5821 return instr;
5845 } 5822 }
5846 5823
5847 5824
5848 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( 5825 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric(
5849 HValue* object, 5826 HValue* object,
5850 HValue* key, 5827 HValue* key,
5851 HValue* value) { 5828 HValue* value) {
5852 HValue* context = environment()->context(); 5829 return New<HStoreKeyedGeneric>(
5853 return new(zone()) HStoreKeyedGeneric(
5854 context,
5855 object, 5830 object,
5856 key, 5831 key,
5857 value, 5832 value,
5858 function_strict_mode_flag()); 5833 function_strict_mode_flag());
5859 } 5834 }
5860 5835
5861 5836
5862 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { 5837 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
5863 // Outermost function already has arguments on the stack. 5838 // Outermost function already has arguments on the stack.
5864 if (function_state()->outer() == NULL) return; 5839 if (function_state()->outer() == NULL) return;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
5911 } 5886 }
5912 } else { 5887 } else {
5913 Push(graph()->GetArgumentsObject()); 5888 Push(graph()->GetArgumentsObject());
5914 CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true); 5889 CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
5915 HValue* key = Pop(); 5890 HValue* key = Pop();
5916 Drop(1); // Arguments object. 5891 Drop(1); // Arguments object.
5917 if (function_state()->outer() == NULL) { 5892 if (function_state()->outer() == NULL) {
5918 HInstruction* elements = Add<HArgumentsElements>(false); 5893 HInstruction* elements = Add<HArgumentsElements>(false);
5919 HInstruction* length = Add<HArgumentsLength>(elements); 5894 HInstruction* length = Add<HArgumentsLength>(elements);
5920 HInstruction* checked_key = Add<HBoundsCheck>(key, length); 5895 HInstruction* checked_key = Add<HBoundsCheck>(key, length);
5921 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); 5896 result = New<HAccessArgumentsAt>(elements, length, checked_key);
5922 } else { 5897 } else {
5923 EnsureArgumentsArePushedForAccess(); 5898 EnsureArgumentsArePushedForAccess();
5924 5899
5925 // Number of arguments without receiver. 5900 // Number of arguments without receiver.
5926 HInstruction* elements = function_state()->arguments_elements(); 5901 HInstruction* elements = function_state()->arguments_elements();
5927 int argument_count = environment()-> 5902 int argument_count = environment()->
5928 arguments_environment()->parameter_count() - 1; 5903 arguments_environment()->parameter_count() - 1;
5929 HInstruction* length = Add<HConstant>(argument_count); 5904 HInstruction* length = Add<HConstant>(argument_count);
5930 HInstruction* checked_key = Add<HBoundsCheck>(key, length); 5905 HInstruction* checked_key = Add<HBoundsCheck>(key, length);
5931 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); 5906 result = New<HAccessArgumentsAt>(elements, length, checked_key);
5932 } 5907 }
5933 } 5908 }
5934 ast_context()->ReturnInstruction(result, expr->id()); 5909 ast_context()->ReturnInstruction(result, expr->id());
5935 return true; 5910 return true;
5936 } 5911 }
5937 5912
5938 5913
5939 void HOptimizedGraphBuilder::PushLoad(Property* expr, 5914 void HOptimizedGraphBuilder::PushLoad(Property* expr,
5940 HValue* object, 5915 HValue* object,
5941 HValue* key, 5916 HValue* key) {
5942 int position) {
5943 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); 5917 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
5944 Push(object); 5918 Push(object);
5945 if (key != NULL) Push(key); 5919 if (key != NULL) Push(key);
5946 BuildLoad(expr, position, expr->LoadId()); 5920 BuildLoad(expr, expr->LoadId());
5947 } 5921 }
5948 5922
5949 5923
5950 static bool AreStringTypes(SmallMapList* types) { 5924 static bool AreStringTypes(SmallMapList* types) {
5951 for (int i = 0; i < types->length(); i++) { 5925 for (int i = 0; i < types->length(); i++) {
5952 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; 5926 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
5953 } 5927 }
5954 return true; 5928 return true;
5955 } 5929 }
5956 5930
5957 5931
5958 void HOptimizedGraphBuilder::BuildLoad(Property* expr, 5932 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
5959 int position,
5960 BailoutId ast_id) { 5933 BailoutId ast_id) {
5961 HInstruction* instr = NULL; 5934 HInstruction* instr = NULL;
5962 if (expr->IsStringAccess()) { 5935 if (expr->IsStringAccess()) {
5963 HValue* index = Pop(); 5936 HValue* index = Pop();
5964 HValue* string = Pop(); 5937 HValue* string = Pop();
5965 HValue* context = environment()->context(); 5938 HInstruction* char_code = BuildStringCharCodeAt(string, index);
5966 HInstruction* char_code =
5967 BuildStringCharCodeAt(string, index);
5968 AddInstruction(char_code); 5939 AddInstruction(char_code);
5969 instr = HStringCharFromCode::New(zone(), context, char_code); 5940 instr = NewUncasted<HStringCharFromCode>(char_code);
5970 5941
5971 } else if (expr->IsFunctionPrototype()) { 5942 } else if (expr->IsFunctionPrototype()) {
5972 HValue* function = Pop(); 5943 HValue* function = Pop();
5973 BuildCheckHeapObject(function); 5944 BuildCheckHeapObject(function);
5974 instr = new(zone()) HLoadFunctionPrototype(function); 5945 instr = New<HLoadFunctionPrototype>(function);
5975 5946
5976 } else if (expr->key()->IsPropertyName()) { 5947 } else if (expr->key()->IsPropertyName()) {
5977 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 5948 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
5978 HValue* object = Pop(); 5949 HValue* object = Pop();
5979 5950
5980 SmallMapList* types; 5951 SmallMapList* types;
5981 ComputeReceiverTypes(expr, object, &types); 5952 ComputeReceiverTypes(expr, object, &types);
5982 ASSERT(types != NULL); 5953 ASSERT(types != NULL);
5983 5954
5984 if (types->length() > 0) { 5955 if (types->length() > 0) {
5985 PropertyAccessInfo info(isolate(), types->first(), name); 5956 PropertyAccessInfo info(isolate(), types->first(), name);
5986 if (!info.CanLoadAsMonomorphic(types)) { 5957 if (!info.CanLoadAsMonomorphic(types)) {
5987 return HandlePolymorphicLoadNamedField( 5958 return HandlePolymorphicLoadNamedField(
5988 position, ast_id, expr->LoadId(), object, types, name); 5959 ast_id, expr->LoadId(), object, types, name);
5989 } 5960 }
5990 5961
5991 BuildCheckHeapObject(object); 5962 BuildCheckHeapObject(object);
5992 HInstruction* checked_object; 5963 HInstruction* checked_object;
5993 if (AreStringTypes(types)) { 5964 if (AreStringTypes(types)) {
5994 checked_object = 5965 checked_object =
5995 AddInstruction(HCheckInstanceType::NewIsString(object, zone())); 5966 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
5996 } else { 5967 } else {
5997 checked_object = Add<HCheckMaps>(object, types); 5968 checked_object = Add<HCheckMaps>(object, types);
5998 } 5969 }
5999 instr = BuildLoadMonomorphic( 5970 instr = BuildLoadMonomorphic(
6000 &info, object, checked_object, ast_id, expr->LoadId()); 5971 &info, object, checked_object, ast_id, expr->LoadId());
6001 if (instr == NULL) return; 5972 if (instr == NULL) return;
6002 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); 5973 if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
6003 } else { 5974 } else {
6004 instr = BuildLoadNamedGeneric(object, name, expr); 5975 instr = BuildLoadNamedGeneric(object, name, expr);
6005 } 5976 }
6006 5977
6007 } else { 5978 } else {
6008 HValue* key = Pop(); 5979 HValue* key = Pop();
6009 HValue* obj = Pop(); 5980 HValue* obj = Pop();
6010 5981
6011 bool has_side_effects = false; 5982 bool has_side_effects = false;
6012 HValue* load = HandleKeyedElementAccess( 5983 HValue* load = HandleKeyedElementAccess(
6013 obj, key, NULL, expr, ast_id, position, 5984 obj, key, NULL, expr,
6014 false, // is_store 5985 false, // is_store
6015 &has_side_effects); 5986 &has_side_effects);
6016 if (has_side_effects) { 5987 if (has_side_effects) {
6017 if (ast_context()->IsEffect()) { 5988 if (ast_context()->IsEffect()) {
6018 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5989 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6019 } else { 5990 } else {
6020 Push(load); 5991 Push(load);
6021 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5992 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6022 Drop(1); 5993 Drop(1);
6023 } 5994 }
6024 } 5995 }
6025 return ast_context()->ReturnValue(load); 5996 return ast_context()->ReturnValue(load);
6026 } 5997 }
6027 instr->set_position(position);
6028 return ast_context()->ReturnInstruction(instr, ast_id); 5998 return ast_context()->ReturnInstruction(instr, ast_id);
6029 } 5999 }
6030 6000
6031 6001
6032 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { 6002 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
6033 ASSERT(!HasStackOverflow()); 6003 ASSERT(!HasStackOverflow());
6034 ASSERT(current_block() != NULL); 6004 ASSERT(current_block() != NULL);
6035 ASSERT(current_block()->HasPredecessor()); 6005 ASSERT(current_block()->HasPredecessor());
6036 6006
6037 if (TryArgumentsAccess(expr)) return; 6007 if (TryArgumentsAccess(expr)) return;
6038 6008
6039 CHECK_ALIVE(VisitForValue(expr->obj())); 6009 CHECK_ALIVE(VisitForValue(expr->obj()));
6040 if ((!expr->IsFunctionPrototype() && !expr->key()->IsPropertyName()) || 6010 if ((!expr->IsFunctionPrototype() && !expr->key()->IsPropertyName()) ||
6041 expr->IsStringAccess()) { 6011 expr->IsStringAccess()) {
6042 CHECK_ALIVE(VisitForValue(expr->key())); 6012 CHECK_ALIVE(VisitForValue(expr->key()));
6043 } 6013 }
6044 6014
6045 BuildLoad(expr, expr->position(), expr->id()); 6015 BuildLoad(expr, expr->id());
6046 } 6016 }
6047 6017
6048 6018
6049 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, 6019 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
6050 CompilationInfo* info) { 6020 CompilationInfo* info) {
6051 HConstant* constant_value = New<HConstant>(constant); 6021 HConstant* constant_value = New<HConstant>(constant);
6052 6022
6053 if (constant->map()->CanOmitMapChecks()) { 6023 if (constant->map()->CanOmitMapChecks()) {
6054 constant->map()->AddDependentCompilationInfo( 6024 constant->map()->AddDependentCompilationInfo(
6055 DependentCode::kPrototypeCheckGroup, info); 6025 DependentCode::kPrototypeCheckGroup, info);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
6148 SmartArrayPointer<char> caller_name = 6118 SmartArrayPointer<char> caller_name =
6149 caller->shared()->DebugName()->ToCString(); 6119 caller->shared()->DebugName()->ToCString();
6150 PrintF("Trying to inline the polymorphic call to %s from %s\n", 6120 PrintF("Trying to inline the polymorphic call to %s from %s\n",
6151 *name->ToCString(), *caller_name); 6121 *name->ToCString(), *caller_name);
6152 } 6122 }
6153 6123
6154 if (!TryInlineCall(expr)) { 6124 if (!TryInlineCall(expr)) {
6155 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 6125 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
6156 HCallConstantFunction* call = 6126 HCallConstantFunction* call =
6157 New<HCallConstantFunction>(expr->target(), argument_count); 6127 New<HCallConstantFunction>(expr->target(), argument_count);
6158 call->set_position(expr->position());
6159 PreProcessCall(call); 6128 PreProcessCall(call);
6160 AddInstruction(call); 6129 AddInstruction(call);
6161 if (!ast_context()->IsEffect()) Push(call); 6130 if (!ast_context()->IsEffect()) Push(call);
6162 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 6131 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
6163 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 6132 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6164 } 6133 }
6165 6134
6166 return true; 6135 return true;
6167 } 6136 }
6168 6137
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
6212 for (int fn = 0; fn < ordered_functions; ++fn) { 6181 for (int fn = 0; fn < ordered_functions; ++fn) {
6213 int i = order[fn].index(); 6182 int i = order[fn].index();
6214 Handle<Map> map = types->at(i); 6183 Handle<Map> map = types->at(i);
6215 if (fn == 0) { 6184 if (fn == 0) {
6216 // Only needed once. 6185 // Only needed once.
6217 join = graph()->CreateBasicBlock(); 6186 join = graph()->CreateBasicBlock();
6218 if (handle_smi) { 6187 if (handle_smi) {
6219 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); 6188 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
6220 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); 6189 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
6221 number_block = graph()->CreateBasicBlock(); 6190 number_block = graph()->CreateBasicBlock();
6222 current_block()->Finish(New<HIsSmiAndBranch>( 6191 FinishCurrentBlock(New<HIsSmiAndBranch>(
6223 receiver, empty_smi_block, not_smi_block)); 6192 receiver, empty_smi_block, not_smi_block));
6224 empty_smi_block->Goto(number_block); 6193 Goto(empty_smi_block, number_block);
6225 set_current_block(not_smi_block); 6194 set_current_block(not_smi_block);
6226 } else { 6195 } else {
6227 BuildCheckHeapObject(receiver); 6196 BuildCheckHeapObject(receiver);
6228 } 6197 }
6229 } 6198 }
6230 HBasicBlock* if_true = graph()->CreateBasicBlock(); 6199 HBasicBlock* if_true = graph()->CreateBasicBlock();
6231 HBasicBlock* if_false = graph()->CreateBasicBlock(); 6200 HBasicBlock* if_false = graph()->CreateBasicBlock();
6232 HUnaryControlInstruction* compare; 6201 HUnaryControlInstruction* compare;
6233 6202
6234 if (handle_smi && map.is_identical_to(number_marker_map)) { 6203 if (handle_smi && map.is_identical_to(number_marker_map)) {
6235 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); 6204 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
6236 map = initial_number_map; 6205 map = initial_number_map;
6237 expr->set_number_check( 6206 expr->set_number_check(
6238 Handle<JSObject>(JSObject::cast(map->prototype()))); 6207 Handle<JSObject>(JSObject::cast(map->prototype())));
6239 } else if (map.is_identical_to(string_marker_map)) { 6208 } else if (map.is_identical_to(string_marker_map)) {
6240 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); 6209 compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
6241 map = initial_string_map; 6210 map = initial_string_map;
6242 expr->set_string_check( 6211 expr->set_string_check(
6243 Handle<JSObject>(JSObject::cast(map->prototype()))); 6212 Handle<JSObject>(JSObject::cast(map->prototype())));
6244 } else { 6213 } else {
6245 compare = New<HCompareMap>(receiver, map, if_true, if_false); 6214 compare = New<HCompareMap>(receiver, map, if_true, if_false);
6246 expr->set_map_check(); 6215 expr->set_map_check();
6247 } 6216 }
6248 6217
6249 current_block()->Finish(compare); 6218 FinishCurrentBlock(compare);
6250 6219
6251 if (expr->check_type() == NUMBER_CHECK) { 6220 if (expr->check_type() == NUMBER_CHECK) {
6252 if_true->Goto(number_block); 6221 Goto(if_true, number_block);
6253 if_true = number_block; 6222 if_true = number_block;
6254 number_block->SetJoinId(expr->id()); 6223 number_block->SetJoinId(expr->id());
6255 } 6224 }
6256 set_current_block(if_true); 6225 set_current_block(if_true);
6257 6226
6258 expr->ComputeTarget(map, name); 6227 expr->ComputeTarget(map, name);
6259 AddCheckPrototypeMaps(expr->holder(), map); 6228 AddCheckPrototypeMaps(expr->holder(), map);
6260 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 6229 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
6261 Handle<JSFunction> caller = current_info()->closure(); 6230 Handle<JSFunction> caller = current_info()->closure();
6262 SmartArrayPointer<char> caller_name = 6231 SmartArrayPointer<char> caller_name =
6263 caller->shared()->DebugName()->ToCString(); 6232 caller->shared()->DebugName()->ToCString();
6264 PrintF("Trying to inline the polymorphic call to %s from %s\n", 6233 PrintF("Trying to inline the polymorphic call to %s from %s\n",
6265 *name->ToCString(), 6234 *name->ToCString(),
6266 *caller_name); 6235 *caller_name);
6267 } 6236 }
6268 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { 6237 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
6269 // Trying to inline will signal that we should bailout from the 6238 // Trying to inline will signal that we should bailout from the
6270 // entire compilation by setting stack overflow on the visitor. 6239 // entire compilation by setting stack overflow on the visitor.
6271 if (HasStackOverflow()) return; 6240 if (HasStackOverflow()) return;
6272 } else { 6241 } else {
6273 HCallConstantFunction* call = 6242 HCallConstantFunction* call =
6274 New<HCallConstantFunction>(expr->target(), argument_count); 6243 New<HCallConstantFunction>(expr->target(), argument_count);
6275 call->set_position(expr->position());
6276 PreProcessCall(call); 6244 PreProcessCall(call);
6277 AddInstruction(call); 6245 AddInstruction(call);
6278 if (!ast_context()->IsEffect()) Push(call); 6246 if (!ast_context()->IsEffect()) Push(call);
6279 } 6247 }
6280 6248
6281 if (current_block() != NULL) current_block()->Goto(join); 6249 if (current_block() != NULL) Goto(join);
6282 set_current_block(if_false); 6250 set_current_block(if_false);
6283 } 6251 }
6284 6252
6285 // Finish up. Unconditionally deoptimize if we've handled all the maps we 6253 // Finish up. Unconditionally deoptimize if we've handled all the maps we
6286 // know about and do not want to handle ones we've never seen. Otherwise 6254 // know about and do not want to handle ones we've never seen. Otherwise
6287 // use a generic IC. 6255 // use a generic IC.
6288 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { 6256 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
6289 // Because the deopt may be the only path in the polymorphic call, make sure 6257 // Because the deopt may be the only path in the polymorphic call, make sure
6290 // that the environment stack matches the depth on deopt that it otherwise 6258 // that the environment stack matches the depth on deopt that it otherwise
6291 // would have had after a successful call. 6259 // would have had after a successful call.
6292 Drop(argument_count); 6260 Drop(argument_count);
6293 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); 6261 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
6294 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); 6262 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
6295 } else { 6263 } else {
6296 HCallNamed* call = New<HCallNamed>(name, argument_count); 6264 HCallNamed* call = New<HCallNamed>(name, argument_count);
6297 call->set_position(expr->position());
6298 PreProcessCall(call); 6265 PreProcessCall(call);
6299 6266
6300 if (join != NULL) { 6267 if (join != NULL) {
6301 AddInstruction(call); 6268 AddInstruction(call);
6302 if (!ast_context()->IsEffect()) Push(call); 6269 if (!ast_context()->IsEffect()) Push(call);
6303 current_block()->Goto(join); 6270 Goto(join);
6304 } else { 6271 } else {
6305 return ast_context()->ReturnInstruction(call, expr->id()); 6272 return ast_context()->ReturnInstruction(call, expr->id());
6306 } 6273 }
6307 } 6274 }
6308 6275
6309 // We assume that control flow is always live after an expression. So 6276 // We assume that control flow is always live after an expression. So
6310 // even without predecessors to the join block, we set it as the exit 6277 // even without predecessors to the join block, we set it as the exit
6311 // block and continue by adding instructions there. 6278 // block and continue by adding instructions there.
6312 ASSERT(join != NULL); 6279 ASSERT(join != NULL);
6313 if (join->HasPredecessor()) { 6280 if (join->HasPredecessor()) {
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
6595 6562
6596 TraceInline(target, caller, NULL); 6563 TraceInline(target, caller, NULL);
6597 6564
6598 if (current_block() != NULL) { 6565 if (current_block() != NULL) {
6599 FunctionState* state = function_state(); 6566 FunctionState* state = function_state();
6600 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { 6567 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
6601 // Falling off the end of an inlined construct call. In a test context the 6568 // Falling off the end of an inlined construct call. In a test context the
6602 // return value will always evaluate to true, in a value context the 6569 // return value will always evaluate to true, in a value context the
6603 // return value is the newly allocated receiver. 6570 // return value is the newly allocated receiver.
6604 if (call_context()->IsTest()) { 6571 if (call_context()->IsTest()) {
6605 current_block()->Goto(inlined_test_context()->if_true(), state); 6572 Goto(inlined_test_context()->if_true(), state);
6606 } else if (call_context()->IsEffect()) { 6573 } else if (call_context()->IsEffect()) {
6607 current_block()->Goto(function_return(), state); 6574 Goto(function_return(), state);
6608 } else { 6575 } else {
6609 ASSERT(call_context()->IsValue()); 6576 ASSERT(call_context()->IsValue());
6610 current_block()->AddLeaveInlined(implicit_return_value, state); 6577 AddLeaveInlined(implicit_return_value, state);
6611 } 6578 }
6612 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { 6579 } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
6613 // Falling off the end of an inlined setter call. The returned value is 6580 // Falling off the end of an inlined setter call. The returned value is
6614 // never used, the value of an assignment is always the value of the RHS 6581 // never used, the value of an assignment is always the value of the RHS
6615 // of the assignment. 6582 // of the assignment.
6616 if (call_context()->IsTest()) { 6583 if (call_context()->IsTest()) {
6617 inlined_test_context()->ReturnValue(implicit_return_value); 6584 inlined_test_context()->ReturnValue(implicit_return_value);
6618 } else if (call_context()->IsEffect()) { 6585 } else if (call_context()->IsEffect()) {
6619 current_block()->Goto(function_return(), state); 6586 Goto(function_return(), state);
6620 } else { 6587 } else {
6621 ASSERT(call_context()->IsValue()); 6588 ASSERT(call_context()->IsValue());
6622 current_block()->AddLeaveInlined(implicit_return_value, state); 6589 AddLeaveInlined(implicit_return_value, state);
6623 } 6590 }
6624 } else { 6591 } else {
6625 // Falling off the end of a normal inlined function. This basically means 6592 // Falling off the end of a normal inlined function. This basically means
6626 // returning undefined. 6593 // returning undefined.
6627 if (call_context()->IsTest()) { 6594 if (call_context()->IsTest()) {
6628 current_block()->Goto(inlined_test_context()->if_false(), state); 6595 Goto(inlined_test_context()->if_false(), state);
6629 } else if (call_context()->IsEffect()) { 6596 } else if (call_context()->IsEffect()) {
6630 current_block()->Goto(function_return(), state); 6597 Goto(function_return(), state);
6631 } else { 6598 } else {
6632 ASSERT(call_context()->IsValue()); 6599 ASSERT(call_context()->IsValue());
6633 current_block()->AddLeaveInlined(undefined, state); 6600 AddLeaveInlined(undefined, state);
6634 } 6601 }
6635 } 6602 }
6636 } 6603 }
6637 6604
6638 // Fix up the function exits. 6605 // Fix up the function exits.
6639 if (inlined_test_context() != NULL) { 6606 if (inlined_test_context() != NULL) {
6640 HBasicBlock* if_true = inlined_test_context()->if_true(); 6607 HBasicBlock* if_true = inlined_test_context()->if_true();
6641 HBasicBlock* if_false = inlined_test_context()->if_false(); 6608 HBasicBlock* if_false = inlined_test_context()->if_false();
6642 6609
6643 HEnterInlined* entry = function_state()->entry(); 6610 HEnterInlined* entry = function_state()->entry();
6644 6611
6645 // Pop the return test context from the expression context stack. 6612 // Pop the return test context from the expression context stack.
6646 ASSERT(ast_context() == inlined_test_context()); 6613 ASSERT(ast_context() == inlined_test_context());
6647 ClearInlinedTestContext(); 6614 ClearInlinedTestContext();
6648 delete target_state; 6615 delete target_state;
6649 6616
6650 // Forward to the real test context. 6617 // Forward to the real test context.
6651 if (if_true->HasPredecessor()) { 6618 if (if_true->HasPredecessor()) {
6652 entry->RegisterReturnTarget(if_true, zone()); 6619 entry->RegisterReturnTarget(if_true, zone());
6653 if_true->SetJoinId(ast_id); 6620 if_true->SetJoinId(ast_id);
6654 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 6621 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
6655 if_true->Goto(true_target, function_state()); 6622 Goto(if_true, true_target, function_state());
6656 } 6623 }
6657 if (if_false->HasPredecessor()) { 6624 if (if_false->HasPredecessor()) {
6658 entry->RegisterReturnTarget(if_false, zone()); 6625 entry->RegisterReturnTarget(if_false, zone());
6659 if_false->SetJoinId(ast_id); 6626 if_false->SetJoinId(ast_id);
6660 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 6627 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
6661 if_false->Goto(false_target, function_state()); 6628 Goto(if_false, false_target, function_state());
6662 } 6629 }
6663 set_current_block(NULL); 6630 set_current_block(NULL);
6664 return true; 6631 return true;
6665 6632
6666 } else if (function_return()->HasPredecessor()) { 6633 } else if (function_return()->HasPredecessor()) {
6667 function_state()->entry()->RegisterReturnTarget(function_return(), zone()); 6634 function_state()->entry()->RegisterReturnTarget(function_return(), zone());
6668 function_return()->SetJoinId(ast_id); 6635 function_return()->SetJoinId(ast_id);
6669 set_current_block(function_return()); 6636 set_current_block(function_return());
6670 } else { 6637 } else {
6671 set_current_block(NULL); 6638 set_current_block(NULL);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
6754 case kMathRound: 6721 case kMathRound:
6755 case kMathFloor: 6722 case kMathFloor:
6756 case kMathAbs: 6723 case kMathAbs:
6757 case kMathSqrt: 6724 case kMathSqrt:
6758 case kMathLog: 6725 case kMathLog:
6759 case kMathSin: 6726 case kMathSin:
6760 case kMathCos: 6727 case kMathCos:
6761 case kMathTan: 6728 case kMathTan:
6762 if (expr->arguments()->length() == 1) { 6729 if (expr->arguments()->length() == 1) {
6763 HValue* argument = Pop(); 6730 HValue* argument = Pop();
6764 HValue* context = environment()->context();
6765 Drop(1); // Receiver. 6731 Drop(1); // Receiver.
6766 HInstruction* op = 6732 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
6767 HUnaryMathOperation::New(zone(), context, argument, id);
6768 op->set_position(expr->position());
6769 if (drop_extra) Drop(1); // Optionally drop the function. 6733 if (drop_extra) Drop(1); // Optionally drop the function.
6770 ast_context()->ReturnInstruction(op, expr->id()); 6734 ast_context()->ReturnInstruction(op, expr->id());
6771 return true; 6735 return true;
6772 } 6736 }
6773 break; 6737 break;
6774 case kMathImul: 6738 case kMathImul:
6775 if (expr->arguments()->length() == 2) { 6739 if (expr->arguments()->length() == 2) {
6776 HValue* right = Pop(); 6740 HValue* right = Pop();
6777 HValue* left = Pop(); 6741 HValue* left = Pop();
6778 Drop(1); // Receiver. 6742 Drop(1); // Receiver.
6779 HValue* context = environment()->context(); 6743 HInstruction* op = HMul::NewImul(zone(), context(), left, right);
6780 HInstruction* op = HMul::NewImul(zone(), context, left, right);
6781 if (drop_extra) Drop(1); // Optionally drop the function. 6744 if (drop_extra) Drop(1); // Optionally drop the function.
6782 ast_context()->ReturnInstruction(op, expr->id()); 6745 ast_context()->ReturnInstruction(op, expr->id());
6783 return true; 6746 return true;
6784 } 6747 }
6785 break; 6748 break;
6786 default: 6749 default:
6787 // Not supported for inlining yet. 6750 // Not supported for inlining yet.
6788 break; 6751 break;
6789 } 6752 }
6790 return false; 6753 return false;
6791 } 6754 }
6792 6755
6793 6756
6794 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( 6757 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
6795 Call* expr, 6758 Call* expr,
6796 HValue* receiver, 6759 HValue* receiver,
6797 Handle<Map> receiver_map, 6760 Handle<Map> receiver_map,
6798 CheckType check_type) { 6761 CheckType check_type) {
6799 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); 6762 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
6800 // Try to inline calls like Math.* as operations in the calling function. 6763 // Try to inline calls like Math.* as operations in the calling function.
6801 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 6764 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
6802 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 6765 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
6803 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 6766 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
6804 switch (id) { 6767 switch (id) {
6805 case kStringCharCodeAt: 6768 case kStringCharCodeAt:
6806 case kStringCharAt: 6769 case kStringCharAt:
6807 if (argument_count == 2 && check_type == STRING_CHECK) { 6770 if (argument_count == 2 && check_type == STRING_CHECK) {
6808 HValue* index = Pop(); 6771 HValue* index = Pop();
6809 HValue* string = Pop(); 6772 HValue* string = Pop();
6810 HValue* context = environment()->context();
6811 ASSERT(!expr->holder().is_null()); 6773 ASSERT(!expr->holder().is_null());
6812 BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck( 6774 BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck(
6813 STRING_CHECK, expr->holder()->GetIsolate()), 6775 STRING_CHECK, expr->holder()->GetIsolate()),
6814 expr->holder()); 6776 expr->holder());
6815 HInstruction* char_code = 6777 HInstruction* char_code =
6816 BuildStringCharCodeAt(string, index); 6778 BuildStringCharCodeAt(string, index);
6817 if (id == kStringCharCodeAt) { 6779 if (id == kStringCharCodeAt) {
6818 ast_context()->ReturnInstruction(char_code, expr->id()); 6780 ast_context()->ReturnInstruction(char_code, expr->id());
6819 return true; 6781 return true;
6820 } 6782 }
6821 AddInstruction(char_code); 6783 AddInstruction(char_code);
6822 HInstruction* result = 6784 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
6823 HStringCharFromCode::New(zone(), context, char_code);
6824 ast_context()->ReturnInstruction(result, expr->id()); 6785 ast_context()->ReturnInstruction(result, expr->id());
6825 return true; 6786 return true;
6826 } 6787 }
6827 break; 6788 break;
6828 case kStringFromCharCode: 6789 case kStringFromCharCode:
6829 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 6790 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
6830 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6791 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6831 HValue* argument = Pop(); 6792 HValue* argument = Pop();
6832 HValue* context = environment()->context();
6833 Drop(1); // Receiver. 6793 Drop(1); // Receiver.
6834 HInstruction* result = 6794 HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
6835 HStringCharFromCode::New(zone(), context, argument);
6836 ast_context()->ReturnInstruction(result, expr->id()); 6795 ast_context()->ReturnInstruction(result, expr->id());
6837 return true; 6796 return true;
6838 } 6797 }
6839 break; 6798 break;
6840 case kMathExp: 6799 case kMathExp:
6841 if (!FLAG_fast_math) break; 6800 if (!FLAG_fast_math) break;
6842 // Fall through if FLAG_fast_math. 6801 // Fall through if FLAG_fast_math.
6843 case kMathRound: 6802 case kMathRound:
6844 case kMathFloor: 6803 case kMathFloor:
6845 case kMathAbs: 6804 case kMathAbs:
6846 case kMathSqrt: 6805 case kMathSqrt:
6847 case kMathLog: 6806 case kMathLog:
6848 case kMathSin: 6807 case kMathSin:
6849 case kMathCos: 6808 case kMathCos:
6850 case kMathTan: 6809 case kMathTan:
6851 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 6810 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
6852 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6811 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6853 HValue* argument = Pop(); 6812 HValue* argument = Pop();
6854 HValue* context = environment()->context();
6855 Drop(1); // Receiver. 6813 Drop(1); // Receiver.
6856 HInstruction* op = 6814 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
6857 HUnaryMathOperation::New(zone(), context, argument, id);
6858 op->set_position(expr->position());
6859 ast_context()->ReturnInstruction(op, expr->id()); 6815 ast_context()->ReturnInstruction(op, expr->id());
6860 return true; 6816 return true;
6861 } 6817 }
6862 break; 6818 break;
6863 case kMathPow: 6819 case kMathPow:
6864 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 6820 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
6865 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6821 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6866 HValue* right = Pop(); 6822 HValue* right = Pop();
6867 HValue* left = Pop(); 6823 HValue* left = Pop();
6868 Pop(); // Pop receiver. 6824 Pop(); // Pop receiver.
6869 HValue* context = environment()->context();
6870 HInstruction* result = NULL; 6825 HInstruction* result = NULL;
6871 // Use sqrt() if exponent is 0.5 or -0.5. 6826 // Use sqrt() if exponent is 0.5 or -0.5.
6872 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 6827 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
6873 double exponent = HConstant::cast(right)->DoubleValue(); 6828 double exponent = HConstant::cast(right)->DoubleValue();
6874 if (exponent == 0.5) { 6829 if (exponent == 0.5) {
6875 result = 6830 result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
6876 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf);
6877 } else if (exponent == -0.5) { 6831 } else if (exponent == -0.5) {
6878 HValue* one = graph()->GetConstant1(); 6832 HValue* one = graph()->GetConstant1();
6879 HInstruction* sqrt = 6833 HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
6880 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); 6834 left, kMathPowHalf);
6881 AddInstruction(sqrt);
6882 // MathPowHalf doesn't have side effects so there's no need for 6835 // MathPowHalf doesn't have side effects so there's no need for
6883 // an environment simulation here. 6836 // an environment simulation here.
6884 ASSERT(!sqrt->HasObservableSideEffects()); 6837 ASSERT(!sqrt->HasObservableSideEffects());
6885 result = HDiv::New(zone(), context, one, sqrt); 6838 result = NewUncasted<HDiv>(one, sqrt);
6886 } else if (exponent == 2.0) { 6839 } else if (exponent == 2.0) {
6887 result = HMul::New(zone(), context, left, left); 6840 result = NewUncasted<HMul>(left, left);
6888 } 6841 }
6889 } 6842 }
6890 6843
6891 if (result == NULL) { 6844 if (result == NULL) {
6892 result = HPower::New(zone(), context, left, right); 6845 result = NewUncasted<HPower>(left, right);
6893 } 6846 }
6894 ast_context()->ReturnInstruction(result, expr->id()); 6847 ast_context()->ReturnInstruction(result, expr->id());
6895 return true; 6848 return true;
6896 } 6849 }
6897 break; 6850 break;
6898 case kMathRandom: 6851 case kMathRandom:
6899 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { 6852 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) {
6900 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6853 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6901 Drop(1); // Receiver. 6854 Drop(1); // Receiver.
6902 HGlobalObject* global_object = Add<HGlobalObject>(); 6855 HGlobalObject* global_object = Add<HGlobalObject>();
6903 HRandom* result = new(zone()) HRandom(global_object); 6856 HRandom* result = New<HRandom>(global_object);
6904 ast_context()->ReturnInstruction(result, expr->id()); 6857 ast_context()->ReturnInstruction(result, expr->id());
6905 return true; 6858 return true;
6906 } 6859 }
6907 break; 6860 break;
6908 case kMathMax: 6861 case kMathMax:
6909 case kMathMin: 6862 case kMathMin:
6910 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 6863 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
6911 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6864 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6912 HValue* right = Pop(); 6865 HValue* right = Pop();
6913 HValue* left = Pop(); 6866 HValue* left = Pop();
6914 Drop(1); // Receiver. 6867 Drop(1); // Receiver.
6915 HValue* context = environment()->context();
6916 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin 6868 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
6917 : HMathMinMax::kMathMax; 6869 : HMathMinMax::kMathMax;
6918 HInstruction* result = 6870 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
6919 HMathMinMax::New(zone(), context, left, right, op);
6920 ast_context()->ReturnInstruction(result, expr->id()); 6871 ast_context()->ReturnInstruction(result, expr->id());
6921 return true; 6872 return true;
6922 } 6873 }
6923 break; 6874 break;
6924 case kMathImul: 6875 case kMathImul:
6925 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 6876 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
6926 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6877 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6927 HValue* right = Pop(); 6878 HValue* right = Pop();
6928 HValue* left = Pop(); 6879 HValue* left = Pop();
6929 Drop(1); // Receiver. 6880 Drop(1); // Receiver.
6930 HValue* context = environment()->context(); 6881 HInstruction* result = HMul::NewImul(zone(), context(), left, right);
6931 HInstruction* result = HMul::NewImul(zone(), context, left, right);
6932 ast_context()->ReturnInstruction(result, expr->id()); 6882 ast_context()->ReturnInstruction(result, expr->id());
6933 return true; 6883 return true;
6934 } 6884 }
6935 break; 6885 break;
6936 default: 6886 default:
6937 // Not yet supported for inlining. 6887 // Not yet supported for inlining.
6938 break; 6888 break;
6939 } 6889 }
6940 return false; 6890 return false;
6941 } 6891 }
(...skipping 30 matching lines...) Expand all
6972 AddCheckConstantFunction(expr->holder(), function, function_map); 6922 AddCheckConstantFunction(expr->holder(), function, function_map);
6973 Drop(1); 6923 Drop(1);
6974 6924
6975 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true); 6925 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
6976 HValue* receiver = Pop(); 6926 HValue* receiver = Pop();
6977 6927
6978 if (function_state()->outer() == NULL) { 6928 if (function_state()->outer() == NULL) {
6979 HInstruction* elements = Add<HArgumentsElements>(false); 6929 HInstruction* elements = Add<HArgumentsElements>(false);
6980 HInstruction* length = Add<HArgumentsLength>(elements); 6930 HInstruction* length = Add<HArgumentsLength>(elements);
6981 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); 6931 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function);
6982 HInstruction* result = 6932 HInstruction* result = New<HApplyArguments>(function,
6983 new(zone()) HApplyArguments(function, 6933 wrapped_receiver,
6984 wrapped_receiver, 6934 length,
6985 length, 6935 elements);
6986 elements);
6987 result->set_position(expr->position());
6988 ast_context()->ReturnInstruction(result, expr->id()); 6936 ast_context()->ReturnInstruction(result, expr->id());
6989 return true; 6937 return true;
6990 } else { 6938 } else {
6991 // We are inside inlined function and we know exactly what is inside 6939 // We are inside inlined function and we know exactly what is inside
6992 // arguments object. But we need to be able to materialize at deopt. 6940 // arguments object. But we need to be able to materialize at deopt.
6993 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), 6941 ASSERT_EQ(environment()->arguments_environment()->parameter_count(),
6994 function_state()->entry()->arguments_object()->arguments_count()); 6942 function_state()->entry()->arguments_object()->arguments_count());
6995 HArgumentsObject* args = function_state()->entry()->arguments_object(); 6943 HArgumentsObject* args = function_state()->entry()->arguments_object();
6996 const ZoneList<HValue*>* arguments_values = args->arguments_values(); 6944 const ZoneList<HValue*>* arguments_values = args->arguments_values();
6997 int arguments_count = arguments_values->length(); 6945 int arguments_count = arguments_values->length();
6998 Push(BuildWrapReceiver(receiver, function)); 6946 Push(BuildWrapReceiver(receiver, function));
6999 for (int i = 1; i < arguments_count; i++) { 6947 for (int i = 1; i < arguments_count; i++) {
7000 Push(arguments_values->at(i)); 6948 Push(arguments_values->at(i));
7001 } 6949 }
7002 6950
7003 Handle<JSFunction> known_function; 6951 Handle<JSFunction> known_function;
7004 if (function->IsConstant()) { 6952 if (function->IsConstant()) {
7005 HConstant* constant_function = HConstant::cast(function); 6953 HConstant* constant_function = HConstant::cast(function);
7006 known_function = Handle<JSFunction>::cast( 6954 known_function = Handle<JSFunction>::cast(
7007 constant_function->handle(isolate())); 6955 constant_function->handle(isolate()));
7008 int args_count = arguments_count - 1; // Excluding receiver. 6956 int args_count = arguments_count - 1; // Excluding receiver.
7009 if (TryInlineApply(known_function, expr, args_count)) return true; 6957 if (TryInlineApply(known_function, expr, args_count)) return true;
7010 } 6958 }
7011 6959
7012 Drop(arguments_count - 1); 6960 Drop(arguments_count - 1);
7013 PushAndAdd(New<HPushArgument>(Pop())); 6961 Push(Add<HPushArgument>(Pop()));
7014 for (int i = 1; i < arguments_count; i++) { 6962 for (int i = 1; i < arguments_count; i++) {
7015 PushAndAdd(New<HPushArgument>(arguments_values->at(i))); 6963 Push(Add<HPushArgument>(arguments_values->at(i)));
7016 } 6964 }
7017 6965
7018 HValue* context = environment()->context(); 6966 HInvokeFunction* call = New<HInvokeFunction>(function,
7019 HInvokeFunction* call = new(zone()) HInvokeFunction( 6967 known_function,
7020 context, 6968 arguments_count);
7021 function,
7022 known_function,
7023 arguments_count);
7024 Drop(arguments_count); 6969 Drop(arguments_count);
7025 call->set_position(expr->position());
7026 ast_context()->ReturnInstruction(call, expr->id()); 6970 ast_context()->ReturnInstruction(call, expr->id());
7027 return true; 6971 return true;
7028 } 6972 }
7029 } 6973 }
7030 6974
7031 6975
7032 void HOptimizedGraphBuilder::VisitCall(Call* expr) { 6976 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
7033 ASSERT(!HasStackOverflow()); 6977 ASSERT(!HasStackOverflow());
7034 ASSERT(current_block() != NULL); 6978 ASSERT(current_block() != NULL);
7035 ASSERT(current_block()->HasPredecessor()); 6979 ASSERT(current_block()->HasPredecessor());
(...skipping 10 matching lines...) Expand all
7046 CHECK_ALIVE(VisitForValue(prop->key())); 6990 CHECK_ALIVE(VisitForValue(prop->key()));
7047 // Push receiver and key like the non-optimized code generator expects it. 6991 // Push receiver and key like the non-optimized code generator expects it.
7048 HValue* key = Pop(); 6992 HValue* key = Pop();
7049 HValue* receiver = Pop(); 6993 HValue* receiver = Pop();
7050 Push(key); 6994 Push(key);
7051 Push(receiver); 6995 Push(receiver);
7052 6996
7053 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 6997 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7054 6998
7055 call = New<HCallKeyed>(key, argument_count); 6999 call = New<HCallKeyed>(key, argument_count);
7056 call->set_position(expr->position());
7057 Drop(argument_count + 1); // 1 is the key. 7000 Drop(argument_count + 1); // 1 is the key.
7058 return ast_context()->ReturnInstruction(call, expr->id()); 7001 return ast_context()->ReturnInstruction(call, expr->id());
7059 } 7002 }
7060 7003
7061 // Named function call. 7004 // Named function call.
7062 if (TryCallApply(expr)) return; 7005 if (TryCallApply(expr)) return;
7063 7006
7064 CHECK_ALIVE(VisitForValue(prop->obj())); 7007 CHECK_ALIVE(VisitForValue(prop->obj()));
7065 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7008 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7066 7009
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
7100 New<HCallConstantFunction>(expr->target(), argument_count)); 7043 New<HCallConstantFunction>(expr->target(), argument_count));
7101 } 7044 }
7102 } else if (types != NULL && types->length() > 1) { 7045 } else if (types != NULL && types->length() > 1) {
7103 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 7046 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
7104 HandlePolymorphicCallNamed(expr, receiver, types, name); 7047 HandlePolymorphicCallNamed(expr, receiver, types, name);
7105 return; 7048 return;
7106 7049
7107 } else { 7050 } else {
7108 call = PreProcessCall(New<HCallNamed>(name, argument_count)); 7051 call = PreProcessCall(New<HCallNamed>(name, argument_count));
7109 } 7052 }
7110
7111 } else { 7053 } else {
7112 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 7054 VariableProxy* proxy = expr->expression()->AsVariableProxy();
7113 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { 7055 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
7114 return Bailout(kPossibleDirectCallToEval); 7056 return Bailout(kPossibleDirectCallToEval);
7115 } 7057 }
7116 7058
7117 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); 7059 bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
7118 if (global_call) { 7060 if (global_call) {
7119 Variable* var = proxy->var(); 7061 Variable* var = proxy->var();
7120 bool known_global_function = false; 7062 bool known_global_function = false;
7121 // If there is a global property cell for the name at compile time and 7063 // If there is a global property cell for the name at compile time and
7122 // access check is not enabled we assume that the function will not change 7064 // access check is not enabled we assume that the function will not change
7123 // and generate optimized code for calling the function. 7065 // and generate optimized code for calling the function.
7124 LookupResult lookup(isolate()); 7066 LookupResult lookup(isolate());
7125 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 7067 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
7126 if (type == kUseCell && 7068 if (type == kUseCell &&
7127 !current_info()->global_object()->IsAccessCheckNeeded()) { 7069 !current_info()->global_object()->IsAccessCheckNeeded()) {
7128 Handle<GlobalObject> global(current_info()->global_object()); 7070 Handle<GlobalObject> global(current_info()->global_object());
7129 known_global_function = expr->ComputeGlobalTarget(global, &lookup); 7071 known_global_function = expr->ComputeGlobalTarget(global, &lookup);
7130 } 7072 }
7131 if (known_global_function) { 7073 if (known_global_function) {
7132 // Push the global object instead of the global receiver because 7074 // Push the global object instead of the global receiver because
7133 // code generated by the full code generator expects it. 7075 // code generated by the full code generator expects it.
7134 HValue* context = environment()->context(); 7076 HGlobalObject* global_object = Add<HGlobalObject>();
7135 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 7077 Push(global_object);
7136 PushAndAdd(global_object);
7137 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7078 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7138 7079
7139 CHECK_ALIVE(VisitForValue(expr->expression())); 7080 CHECK_ALIVE(VisitForValue(expr->expression()));
7140 HValue* function = Pop(); 7081 HValue* function = Pop();
7141 Add<HCheckValue>(function, expr->target()); 7082 Add<HCheckValue>(function, expr->target());
7142 7083
7143 // Replace the global object with the global receiver. 7084 // Replace the global object with the global receiver.
7144 HGlobalReceiver* global_receiver = Add<HGlobalReceiver>(global_object); 7085 HGlobalReceiver* global_receiver = Add<HGlobalReceiver>(global_object);
7145 // Index of the receiver from the top of the expression stack. 7086 // Index of the receiver from the top of the expression stack.
7146 const int receiver_index = argument_count - 1; 7087 const int receiver_index = argument_count - 1;
(...skipping 13 matching lines...) Expand all
7160 7101
7161 if (expr->target().is_identical_to(current_info()->closure())) { 7102 if (expr->target().is_identical_to(current_info()->closure())) {
7162 graph()->MarkRecursive(); 7103 graph()->MarkRecursive();
7163 } 7104 }
7164 7105
7165 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { 7106 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) {
7166 // When the target has a custom call IC generator, use the IC, 7107 // When the target has a custom call IC generator, use the IC,
7167 // because it is likely to generate better code. 7108 // because it is likely to generate better code.
7168 call = PreProcessCall(New<HCallNamed>(var->name(), argument_count)); 7109 call = PreProcessCall(New<HCallNamed>(var->name(), argument_count));
7169 } else { 7110 } else {
7170 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), 7111 call = PreProcessCall(New<HCallKnownGlobal>(
7171 argument_count)); 7112 expr->target(), argument_count));
7172 } 7113 }
7173 } else { 7114 } else {
7174 HGlobalObject* receiver = Add<HGlobalObject>(); 7115 HGlobalObject* receiver = Add<HGlobalObject>();
7175 PushAndAdd(New<HPushArgument>(receiver)); 7116 Push(Add<HPushArgument>(receiver));
7176 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7117 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7177 7118
7178 call = New<HCallGlobal>(var->name(), argument_count); 7119 call = New<HCallGlobal>(var->name(), argument_count);
7179 Drop(argument_count); 7120 Drop(argument_count);
7180 } 7121 }
7181 7122
7182 } else if (expr->IsMonomorphic()) { 7123 } else if (expr->IsMonomorphic()) {
7183 // The function is on the stack in the unoptimized code during 7124 // The function is on the stack in the unoptimized code during
7184 // evaluation of the arguments. 7125 // evaluation of the arguments.
7185 CHECK_ALIVE(VisitForValue(expr->expression())); 7126 CHECK_ALIVE(VisitForValue(expr->expression()));
7186 HValue* function = Top(); 7127 HValue* function = Top();
7187 HGlobalObject* global = Add<HGlobalObject>(); 7128 HGlobalObject* global = Add<HGlobalObject>();
7188 HGlobalReceiver* receiver = New<HGlobalReceiver>(global); 7129 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global);
7189 PushAndAdd(receiver); 7130 Push(receiver);
7190 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7131 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7191 Add<HCheckValue>(function, expr->target()); 7132 Add<HCheckValue>(function, expr->target());
7192 7133
7193 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. 7134 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function.
7194 if (FLAG_trace_inlining) { 7135 if (FLAG_trace_inlining) {
7195 PrintF("Inlining builtin "); 7136 PrintF("Inlining builtin ");
7196 expr->target()->ShortPrint(); 7137 expr->target()->ShortPrint();
7197 PrintF("\n"); 7138 PrintF("\n");
7198 } 7139 }
7199 return; 7140 return;
7200 } 7141 }
7201 7142
7202 if (TryInlineCall(expr, true)) { // Drop function from environment. 7143 if (TryInlineCall(expr, true)) { // Drop function from environment.
7203 return; 7144 return;
7204 } else { 7145 } else {
7205 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(), 7146 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(),
7206 argument_count)); 7147 argument_count));
7207 Drop(1); // The function. 7148 Drop(1); // The function.
7208 } 7149 }
7209 7150
7210 } else { 7151 } else {
7211 CHECK_ALIVE(VisitForValue(expr->expression())); 7152 CHECK_ALIVE(VisitForValue(expr->expression()));
7212 HValue* function = Top(); 7153 HValue* function = Top();
7213 HGlobalObject* global_object = Add<HGlobalObject>(); 7154 HGlobalObject* global_object = Add<HGlobalObject>();
7214 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object); 7155 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object);
7215 PushAndAdd(New<HPushArgument>(receiver)); 7156 Push(Add<HPushArgument>(receiver));
7216 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7157 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7217 7158
7218 call = New<HCallFunction>(function, argument_count); 7159 call = New<HCallFunction>(function, argument_count);
7219 Drop(argument_count + 1); 7160 Drop(argument_count + 1);
7220 } 7161 }
7221 } 7162 }
7222 7163
7223 call->set_position(expr->position());
7224 return ast_context()->ReturnInstruction(call, expr->id()); 7164 return ast_context()->ReturnInstruction(call, expr->id());
7225 } 7165 }
7226 7166
7227 7167
7228 // Checks whether allocation using the given constructor can be inlined. 7168 // Checks whether allocation using the given constructor can be inlined.
7229 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { 7169 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
7230 return constructor->has_initial_map() && 7170 return constructor->has_initial_map() &&
7231 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && 7171 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
7232 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && 7172 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
7233 constructor->initial_map()->InitialPropertiesLength() == 0; 7173 constructor->initial_map()->InitialPropertiesLength() == 0;
7234 } 7174 }
7235 7175
7236 7176
7237 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { 7177 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
7238 ASSERT(!HasStackOverflow()); 7178 ASSERT(!HasStackOverflow());
7239 ASSERT(current_block() != NULL); 7179 ASSERT(current_block() != NULL);
7240 ASSERT(current_block()->HasPredecessor()); 7180 ASSERT(current_block()->HasPredecessor());
7181 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
7241 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 7182 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
7242 Factory* factory = isolate()->factory(); 7183 Factory* factory = isolate()->factory();
7243 7184
7244 if (FLAG_inline_construct && 7185 if (FLAG_inline_construct &&
7245 expr->IsMonomorphic() && 7186 expr->IsMonomorphic() &&
7246 IsAllocationInlineable(expr->target())) { 7187 IsAllocationInlineable(expr->target())) {
7247 // The constructor function is on the stack in the unoptimized code 7188 // The constructor function is on the stack in the unoptimized code
7248 // during evaluation of the arguments. 7189 // during evaluation of the arguments.
7249 CHECK_ALIVE(VisitForValue(expr->expression())); 7190 CHECK_ALIVE(VisitForValue(expr->expression()));
7250 HValue* function = Top(); 7191 HValue* function = Top();
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
7322 HInstruction* prev_instr = instr->previous(); 7263 HInstruction* prev_instr = instr->previous();
7323 instr->DeleteAndReplaceWith(NULL); 7264 instr->DeleteAndReplaceWith(NULL);
7324 instr = prev_instr; 7265 instr = prev_instr;
7325 } 7266 }
7326 initial_map_value->DeleteAndReplaceWith(NULL); 7267 initial_map_value->DeleteAndReplaceWith(NULL);
7327 receiver->DeleteAndReplaceWith(NULL); 7268 receiver->DeleteAndReplaceWith(NULL);
7328 check->DeleteAndReplaceWith(NULL); 7269 check->DeleteAndReplaceWith(NULL);
7329 environment()->SetExpressionStackAt(receiver_index, function); 7270 environment()->SetExpressionStackAt(receiver_index, function);
7330 HInstruction* call = 7271 HInstruction* call =
7331 PreProcessCall(New<HCallNew>(function, argument_count)); 7272 PreProcessCall(New<HCallNew>(function, argument_count));
7332 call->set_position(expr->position());
7333 return ast_context()->ReturnInstruction(call, expr->id()); 7273 return ast_context()->ReturnInstruction(call, expr->id());
7334 } else { 7274 } else {
7335 // The constructor function is both an operand to the instruction and an 7275 // The constructor function is both an operand to the instruction and an
7336 // argument to the construct call. 7276 // argument to the construct call.
7337 Handle<JSFunction> array_function( 7277 Handle<JSFunction> array_function(
7338 isolate()->global_context()->array_function(), isolate()); 7278 isolate()->global_context()->array_function(), isolate());
7339 CHECK_ALIVE(VisitArgument(expr->expression())); 7279 CHECK_ALIVE(VisitArgument(expr->expression()));
7340 HValue* constructor = HPushArgument::cast(Top())->argument(); 7280 HValue* constructor = HPushArgument::cast(Top())->argument();
7341 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7281 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7342 HBinaryCall* call; 7282 HBinaryCall* call;
7343 if (expr->target().is_identical_to(array_function)) { 7283 if (expr->target().is_identical_to(array_function)) {
7344 Handle<Cell> cell = expr->allocation_info_cell(); 7284 Handle<Cell> cell = expr->allocation_info_cell();
7345 Add<HCheckValue>(constructor, array_function); 7285 Add<HCheckValue>(constructor, array_function);
7346 call = New<HCallNewArray>(constructor, argument_count, 7286 call = New<HCallNewArray>(constructor, argument_count,
7347 cell, expr->elements_kind()); 7287 cell, expr->elements_kind());
7348 } else { 7288 } else {
7349 call = New<HCallNew>(constructor, argument_count); 7289 call = New<HCallNew>(constructor, argument_count);
7350 } 7290 }
7351 Drop(argument_count); 7291 Drop(argument_count);
7352 call->set_position(expr->position());
7353 return ast_context()->ReturnInstruction(call, expr->id()); 7292 return ast_context()->ReturnInstruction(call, expr->id());
7354 } 7293 }
7355 } 7294 }
7356 7295
7357 7296
7358 // Support for generating inlined runtime functions. 7297 // Support for generating inlined runtime functions.
7359 7298
7360 // Lookup table for generators for runtime calls that are generated inline. 7299 // Lookup table for generators for runtime calls that are generated inline.
7361 // Elements of the table are member pointers to functions of 7300 // Elements of the table are member pointers to functions of
7362 // HOptimizedGraphBuilder. 7301 // HOptimizedGraphBuilder.
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
7573 if (key != NULL) Push(key); 7512 if (key != NULL) Push(key);
7574 Push(value); 7513 Push(value);
7575 BuildStore(expr, prop, ast_id, return_id); 7514 BuildStore(expr, prop, ast_id, return_id);
7576 } 7515 }
7577 7516
7578 7517
7579 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { 7518 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
7580 ASSERT(!HasStackOverflow()); 7519 ASSERT(!HasStackOverflow());
7581 ASSERT(current_block() != NULL); 7520 ASSERT(current_block() != NULL);
7582 ASSERT(current_block()->HasPredecessor()); 7521 ASSERT(current_block()->HasPredecessor());
7522 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
7583 Expression* target = expr->expression(); 7523 Expression* target = expr->expression();
7584 VariableProxy* proxy = target->AsVariableProxy(); 7524 VariableProxy* proxy = target->AsVariableProxy();
7585 Property* prop = target->AsProperty(); 7525 Property* prop = target->AsProperty();
7586 if (proxy == NULL && prop == NULL) { 7526 if (proxy == NULL && prop == NULL) {
7587 return Bailout(kInvalidLhsInCountOperation); 7527 return Bailout(kInvalidLhsInCountOperation);
7588 } 7528 }
7589 7529
7590 // Match the full code generator stack by simulating an extra stack 7530 // Match the full code generator stack by simulating an extra stack
7591 // element for postfix operations in a non-effect context. The return 7531 // element for postfix operations in a non-effect context. The return
7592 // value is ToNumber(input). 7532 // value is ToNumber(input).
(...skipping 12 matching lines...) Expand all
7605 CHECK_ALIVE(VisitForValue(target)); 7545 CHECK_ALIVE(VisitForValue(target));
7606 7546
7607 after = BuildIncrement(returns_original_input, expr); 7547 after = BuildIncrement(returns_original_input, expr);
7608 input = returns_original_input ? Top() : Pop(); 7548 input = returns_original_input ? Top() : Pop();
7609 Push(after); 7549 Push(after);
7610 7550
7611 switch (var->location()) { 7551 switch (var->location()) {
7612 case Variable::UNALLOCATED: 7552 case Variable::UNALLOCATED:
7613 HandleGlobalVariableAssignment(var, 7553 HandleGlobalVariableAssignment(var,
7614 after, 7554 after,
7615 expr->position(),
7616 expr->AssignmentId()); 7555 expr->AssignmentId());
7617 break; 7556 break;
7618 7557
7619 case Variable::PARAMETER: 7558 case Variable::PARAMETER:
7620 case Variable::LOCAL: 7559 case Variable::LOCAL:
7621 BindIfLive(var, after); 7560 BindIfLive(var, after);
7622 break; 7561 break;
7623 7562
7624 case Variable::CONTEXT: { 7563 case Variable::CONTEXT: {
7625 // Bail out if we try to mutate a parameter value in a function 7564 // 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
7663 CHECK_ALIVE(VisitForValue(prop->obj())); 7602 CHECK_ALIVE(VisitForValue(prop->obj()));
7664 HValue* object = Top(); 7603 HValue* object = Top();
7665 7604
7666 HValue* key = NULL; 7605 HValue* key = NULL;
7667 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || 7606 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) ||
7668 prop->IsStringAccess()) { 7607 prop->IsStringAccess()) {
7669 CHECK_ALIVE(VisitForValue(prop->key())); 7608 CHECK_ALIVE(VisitForValue(prop->key()));
7670 key = Top(); 7609 key = Top();
7671 } 7610 }
7672 7611
7673 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); 7612 CHECK_ALIVE(PushLoad(prop, object, key));
7674 7613
7675 after = BuildIncrement(returns_original_input, expr); 7614 after = BuildIncrement(returns_original_input, expr);
7676 7615
7677 if (returns_original_input) { 7616 if (returns_original_input) {
7678 input = Pop(); 7617 input = Pop();
7679 // Drop object and key to push it again in the effect context below. 7618 // Drop object and key to push it again in the effect context below.
7680 Drop(key == NULL ? 1 : 2); 7619 Drop(key == NULL ? 1 : 2);
7681 environment()->SetExpressionStackAt(0, input); 7620 environment()->SetExpressionStackAt(0, input);
7682 CHECK_ALIVE(BuildStoreForEffect( 7621 CHECK_ALIVE(BuildStoreForEffect(
7683 expr, prop, expr->id(), expr->AssignmentId(), object, key, after)); 7622 expr, prop, expr->id(), expr->AssignmentId(), object, key, after));
(...skipping 15 matching lines...) Expand all
7699 int32_t i = c_index->NumberValueAsInteger32(); 7638 int32_t i = c_index->NumberValueAsInteger32();
7700 Handle<String> s = c_string->StringValue(); 7639 Handle<String> s = c_string->StringValue();
7701 if (i < 0 || i >= s->length()) { 7640 if (i < 0 || i >= s->length()) {
7702 return New<HConstant>(OS::nan_value()); 7641 return New<HConstant>(OS::nan_value());
7703 } 7642 }
7704 return New<HConstant>(s->Get(i)); 7643 return New<HConstant>(s->Get(i));
7705 } 7644 }
7706 } 7645 }
7707 BuildCheckHeapObject(string); 7646 BuildCheckHeapObject(string);
7708 HValue* checkstring = 7647 HValue* checkstring =
7709 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); 7648 Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
7710 HInstruction* length = BuildLoadStringLength(string, checkstring); 7649 HInstruction* length = BuildLoadStringLength(string, checkstring);
7711 AddInstruction(length); 7650 AddInstruction(length);
7712 HInstruction* checked_index = Add<HBoundsCheck>(index, length); 7651 HInstruction* checked_index = Add<HBoundsCheck>(index, length);
7713 return New<HStringCharCodeAt>(string, checked_index); 7652 return New<HStringCharCodeAt>(string, checked_index);
7714 } 7653 }
7715 7654
7716 7655
7717 // Checks if the given shift amounts have following forms: 7656 // Checks if the given shift amounts have following forms:
7718 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa). 7657 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
7719 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, 7658 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
7876 7815
7877 if (right_type->Is(Type::None())) { 7816 if (right_type->Is(Type::None())) {
7878 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", 7817 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
7879 Deoptimizer::SOFT); 7818 Deoptimizer::SOFT);
7880 right_type = handle(Type::Any(), isolate()); 7819 right_type = handle(Type::Any(), isolate());
7881 } else { 7820 } else {
7882 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); 7821 if (!maybe_string_add) right = TruncateToNumber(right, &right_type);
7883 right_rep = Representation::FromType(right_type); 7822 right_rep = Representation::FromType(right_type);
7884 } 7823 }
7885 7824
7825 // Special case for string addition here.
7826 if (op == Token::ADD &&
7827 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
7828 if (left_type->Is(Type::String())) {
7829 IfBuilder if_isstring(this);
7830 if_isstring.If<HIsStringAndBranch>(left);
7831 if_isstring.Then();
7832 if_isstring.ElseDeopt("Expected string for LHS of binary operation");
7833 } else if (left_type->Is(Type::Number())) {
7834 left = BuildNumberToString(left, left_type);
7835 } else {
7836 ASSERT(right_type->Is(Type::String()));
7837 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT);
7838 Add<HPushArgument>(left);
7839 Add<HPushArgument>(right);
7840 return NewUncasted<HInvokeFunction>(function, 2);
7841 }
7842
7843 if (right_type->Is(Type::String())) {
7844 IfBuilder if_isstring(this);
7845 if_isstring.If<HIsStringAndBranch>(right);
7846 if_isstring.Then();
7847 if_isstring.ElseDeopt("Expected string for RHS of binary operation");
7848 } else if (right_type->Is(Type::Number())) {
7849 right = BuildNumberToString(right, right_type);
7850 } else {
7851 ASSERT(left_type->Is(Type::String()));
7852 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
7853 Add<HPushArgument>(left);
7854 Add<HPushArgument>(right);
7855 return NewUncasted<HInvokeFunction>(function, 2);
7856 }
7857
7858 return NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE);
7859 }
7860
7886 if (binop_stub) { 7861 if (binop_stub) {
7887 left = EnforceNumberType(left, left_type); 7862 left = EnforceNumberType(left, left_type);
7888 right = EnforceNumberType(right, right_type); 7863 right = EnforceNumberType(right, right_type);
7889 } 7864 }
7890 7865
7891 Representation result_rep = Representation::FromType(result_type); 7866 Representation result_rep = Representation::FromType(result_type);
7892 7867
7893 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || 7868 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
7894 (right_rep.IsTagged() && !right_rep.IsSmi()); 7869 (right_rep.IsTagged() && !right_rep.IsSmi());
7895 bool is_string_add = op == Token::ADD &&
7896 (left_type->Is(Type::String()) ||
7897 right_type->Is(Type::String()));
7898 7870
7899 HInstruction* instr = NULL; 7871 HInstruction* instr = NULL;
7900 // Only the stub is allowed to call into the runtime, since otherwise we would 7872 // Only the stub is allowed to call into the runtime, since otherwise we would
7901 // inline several instructions (including the two pushes) for every tagged 7873 // inline several instructions (including the two pushes) for every tagged
7902 // operation in optimized code, which is more expensive, than a stub call. 7874 // operation in optimized code, which is more expensive, than a stub call.
7903 if (binop_stub && is_non_primitive && !is_string_add) { 7875 if (binop_stub && is_non_primitive) {
7904 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op)); 7876 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op));
7905 Add<HPushArgument>(left); 7877 Add<HPushArgument>(left);
7906 Add<HPushArgument>(right); 7878 Add<HPushArgument>(right);
7907 instr = NewUncasted<HInvokeFunction>(function, 2); 7879 instr = NewUncasted<HInvokeFunction>(function, 2);
7908 } else { 7880 } else {
7909 switch (op) { 7881 switch (op) {
7910 case Token::ADD: 7882 case Token::ADD:
7911 if (is_string_add) { 7883 instr = NewUncasted<HAdd>(left, right);
7912 StringAddFlags flags = STRING_ADD_CHECK_BOTH;
7913 if (left_type->Is(Type::String())) {
7914 BuildCheckHeapObject(left);
7915 AddInstruction(HCheckInstanceType::NewIsString(left, zone()));
7916 flags = STRING_ADD_CHECK_RIGHT;
7917 }
7918 if (right_type->Is(Type::String())) {
7919 BuildCheckHeapObject(right);
7920 AddInstruction(HCheckInstanceType::NewIsString(right, zone()));
7921 flags = (flags == STRING_ADD_CHECK_BOTH)
7922 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE;
7923 }
7924 instr = NewUncasted<HStringAdd>(left, right, flags);
7925 } else {
7926 instr = NewUncasted<HAdd>(left, right);
7927 }
7928 break; 7884 break;
7929 case Token::SUB: 7885 case Token::SUB:
7930 instr = NewUncasted<HSub>(left, right); 7886 instr = NewUncasted<HSub>(left, right);
7931 break; 7887 break;
7932 case Token::MUL: 7888 case Token::MUL:
7933 instr = NewUncasted<HMul>(left, right); 7889 instr = NewUncasted<HMul>(left, right);
7934 break; 7890 break;
7935 case Token::MOD: 7891 case Token::MOD:
7936 instr = NewUncasted<HMod>(left, right, fixed_right_arg); 7892 instr = NewUncasted<HMod>(left, right, fixed_right_arg);
7937 break; 7893 break;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
8073 return ast_context()->ReturnValue(Pop()); 8029 return ast_context()->ReturnValue(Pop());
8074 } 8030 }
8075 8031
8076 // We need an extra block to maintain edge-split form. 8032 // We need an extra block to maintain edge-split form.
8077 HBasicBlock* empty_block = graph()->CreateBasicBlock(); 8033 HBasicBlock* empty_block = graph()->CreateBasicBlock();
8078 HBasicBlock* eval_right = graph()->CreateBasicBlock(); 8034 HBasicBlock* eval_right = graph()->CreateBasicBlock();
8079 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); 8035 ToBooleanStub::Types expected(expr->left()->to_boolean_types());
8080 HBranch* test = is_logical_and 8036 HBranch* test = is_logical_and
8081 ? New<HBranch>(left_value, expected, eval_right, empty_block) 8037 ? New<HBranch>(left_value, expected, eval_right, empty_block)
8082 : New<HBranch>(left_value, expected, empty_block, eval_right); 8038 : New<HBranch>(left_value, expected, empty_block, eval_right);
8083 current_block()->Finish(test); 8039 FinishCurrentBlock(test);
8084 8040
8085 set_current_block(eval_right); 8041 set_current_block(eval_right);
8086 Drop(1); // Value of the left subexpression. 8042 Drop(1); // Value of the left subexpression.
8087 CHECK_BAILOUT(VisitForValue(expr->right())); 8043 CHECK_BAILOUT(VisitForValue(expr->right()));
8088 8044
8089 HBasicBlock* join_block = 8045 HBasicBlock* join_block =
8090 CreateJoin(empty_block, current_block(), expr->id()); 8046 CreateJoin(empty_block, current_block(), expr->id());
8091 set_current_block(join_block); 8047 set_current_block(join_block);
8092 return ast_context()->ReturnValue(Pop()); 8048 return ast_context()->ReturnValue(Pop());
8093 8049
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
8130 set_current_block(join_block); 8086 set_current_block(join_block);
8131 // We did not materialize any value in the predecessor environments, 8087 // We did not materialize any value in the predecessor environments,
8132 // so there is no need to handle it here. 8088 // so there is no need to handle it here.
8133 } 8089 }
8134 } 8090 }
8135 8091
8136 8092
8137 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { 8093 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
8138 CHECK_ALIVE(VisitForValue(expr->left())); 8094 CHECK_ALIVE(VisitForValue(expr->left()));
8139 CHECK_ALIVE(VisitForValue(expr->right())); 8095 CHECK_ALIVE(VisitForValue(expr->right()));
8096 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
8140 HValue* right = Pop(); 8097 HValue* right = Pop();
8141 HValue* left = Pop(); 8098 HValue* left = Pop();
8142 HInstruction* instr = BuildBinaryOperation(expr, left, right); 8099 HInstruction* instr = BuildBinaryOperation(expr, left, right);
8143 instr->set_position(expr->position());
8144 return ast_context()->ReturnInstruction(instr, expr->id()); 8100 return ast_context()->ReturnInstruction(instr, expr->id());
8145 } 8101 }
8146 8102
8147 8103
8148 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, 8104 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
8149 Expression* sub_expr, 8105 Expression* sub_expr,
8150 Handle<String> check) { 8106 Handle<String> check) {
8151 CHECK_ALIVE(VisitForTypeOf(sub_expr)); 8107 CHECK_ALIVE(VisitForTypeOf(sub_expr));
8108 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
8152 HValue* value = Pop(); 8109 HValue* value = Pop();
8153 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); 8110 HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
8154 instr->set_position(expr->position());
8155 return ast_context()->ReturnControl(instr, expr->id()); 8111 return ast_context()->ReturnControl(instr, expr->id());
8156 } 8112 }
8157 8113
8158 8114
8159 static bool IsLiteralCompareBool(Isolate* isolate, 8115 static bool IsLiteralCompareBool(Isolate* isolate,
8160 HValue* left, 8116 HValue* left,
8161 Token::Value op, 8117 Token::Value op,
8162 HValue* right) { 8118 HValue* right) {
8163 return op == Token::EQ_STRICT && 8119 return op == Token::EQ_STRICT &&
8164 ((left->IsConstant() && 8120 ((left->IsConstant() &&
8165 HConstant::cast(left)->handle(isolate)->IsBoolean()) || 8121 HConstant::cast(left)->handle(isolate)->IsBoolean()) ||
8166 (right->IsConstant() && 8122 (right->IsConstant() &&
8167 HConstant::cast(right)->handle(isolate)->IsBoolean())); 8123 HConstant::cast(right)->handle(isolate)->IsBoolean()));
8168 } 8124 }
8169 8125
8170 8126
8171 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 8127 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
8172 ASSERT(!HasStackOverflow()); 8128 ASSERT(!HasStackOverflow());
8173 ASSERT(current_block() != NULL); 8129 ASSERT(current_block() != NULL);
8174 ASSERT(current_block()->HasPredecessor()); 8130 ASSERT(current_block()->HasPredecessor());
8175 8131
8132 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
8133
8176 // Check for a few fast cases. The AST visiting behavior must be in sync 8134 // Check for a few fast cases. The AST visiting behavior must be in sync
8177 // with the full codegen: We don't push both left and right values onto 8135 // with the full codegen: We don't push both left and right values onto
8178 // the expression stack when one side is a special-case literal. 8136 // the expression stack when one side is a special-case literal.
8179 Expression* sub_expr = NULL; 8137 Expression* sub_expr = NULL;
8180 Handle<String> check; 8138 Handle<String> check;
8181 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { 8139 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
8182 return HandleLiteralCompareTypeof(expr, sub_expr, check); 8140 return HandleLiteralCompareTypeof(expr, sub_expr, check);
8183 } 8141 }
8184 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { 8142 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
8185 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); 8143 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
8186 } 8144 }
8187 if (expr->IsLiteralCompareNull(&sub_expr)) { 8145 if (expr->IsLiteralCompareNull(&sub_expr)) {
8188 return HandleLiteralCompareNil(expr, sub_expr, kNullValue); 8146 return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
8189 } 8147 }
8190 8148
8191 if (IsClassOfTest(expr)) { 8149 if (IsClassOfTest(expr)) {
8192 CallRuntime* call = expr->left()->AsCallRuntime(); 8150 CallRuntime* call = expr->left()->AsCallRuntime();
8193 ASSERT(call->arguments()->length() == 1); 8151 ASSERT(call->arguments()->length() == 1);
8194 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8152 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8195 HValue* value = Pop(); 8153 HValue* value = Pop();
8196 Literal* literal = expr->right()->AsLiteral(); 8154 Literal* literal = expr->right()->AsLiteral();
8197 Handle<String> rhs = Handle<String>::cast(literal->value()); 8155 Handle<String> rhs = Handle<String>::cast(literal->value());
8198 HClassOfTestAndBranch* instr = 8156 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
8199 new(zone()) HClassOfTestAndBranch(value, rhs);
8200 instr->set_position(expr->position());
8201 return ast_context()->ReturnControl(instr, expr->id()); 8157 return ast_context()->ReturnControl(instr, expr->id());
8202 } 8158 }
8203 8159
8204 Handle<Type> left_type = expr->left()->bounds().lower; 8160 Handle<Type> left_type = expr->left()->bounds().lower;
8205 Handle<Type> right_type = expr->right()->bounds().lower; 8161 Handle<Type> right_type = expr->right()->bounds().lower;
8206 Handle<Type> combined_type = expr->combined_type(); 8162 Handle<Type> combined_type = expr->combined_type();
8207 Representation combined_rep = Representation::FromType(combined_type); 8163 Representation combined_rep = Representation::FromType(combined_type);
8208 Representation left_rep = Representation::FromType(left_type); 8164 Representation left_rep = Representation::FromType(left_type);
8209 Representation right_rep = Representation::FromType(right_type); 8165 Representation right_rep = Representation::FromType(right_type);
8210 8166
8211 CHECK_ALIVE(VisitForValue(expr->left())); 8167 CHECK_ALIVE(VisitForValue(expr->left()));
8212 CHECK_ALIVE(VisitForValue(expr->right())); 8168 CHECK_ALIVE(VisitForValue(expr->right()));
8213 8169
8214 HValue* context = environment()->context();
8215 HValue* right = Pop(); 8170 HValue* right = Pop();
8216 HValue* left = Pop(); 8171 HValue* left = Pop();
8217 Token::Value op = expr->op(); 8172 Token::Value op = expr->op();
8218 8173
8219 if (IsLiteralCompareBool(isolate(), left, op, right)) { 8174 if (IsLiteralCompareBool(isolate(), left, op, right)) {
8220 HCompareObjectEqAndBranch* result = 8175 HCompareObjectEqAndBranch* result =
8221 New<HCompareObjectEqAndBranch>(left, right); 8176 New<HCompareObjectEqAndBranch>(left, right);
8222 result->set_position(expr->position());
8223 return ast_context()->ReturnControl(result, expr->id()); 8177 return ast_context()->ReturnControl(result, expr->id());
8224 } 8178 }
8225 8179
8226 if (op == Token::INSTANCEOF) { 8180 if (op == Token::INSTANCEOF) {
8227 // Check to see if the rhs of the instanceof is a global function not 8181 // Check to see if the rhs of the instanceof is a global function not
8228 // residing in new space. If it is we assume that the function will stay the 8182 // residing in new space. If it is we assume that the function will stay the
8229 // same. 8183 // same.
8230 Handle<JSFunction> target = Handle<JSFunction>::null(); 8184 Handle<JSFunction> target = Handle<JSFunction>::null();
8231 VariableProxy* proxy = expr->right()->AsVariableProxy(); 8185 VariableProxy* proxy = expr->right()->AsVariableProxy();
8232 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); 8186 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
(...skipping 10 matching lines...) Expand all
8243 // change and thus prefer the general IC code. 8197 // change and thus prefer the general IC code.
8244 if (!isolate()->heap()->InNewSpace(*candidate)) { 8198 if (!isolate()->heap()->InNewSpace(*candidate)) {
8245 target = candidate; 8199 target = candidate;
8246 } 8200 }
8247 } 8201 }
8248 } 8202 }
8249 8203
8250 // If the target is not null we have found a known global function that is 8204 // If the target is not null we have found a known global function that is
8251 // assumed to stay the same for this instanceof. 8205 // assumed to stay the same for this instanceof.
8252 if (target.is_null()) { 8206 if (target.is_null()) {
8253 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); 8207 HInstanceOf* result = New<HInstanceOf>(left, right);
8254 result->set_position(expr->position());
8255 return ast_context()->ReturnInstruction(result, expr->id()); 8208 return ast_context()->ReturnInstruction(result, expr->id());
8256 } else { 8209 } else {
8257 Add<HCheckValue>(right, target); 8210 Add<HCheckValue>(right, target);
8258 HInstanceOfKnownGlobal* result = 8211 HInstanceOfKnownGlobal* result =
8259 New<HInstanceOfKnownGlobal>(left, target); 8212 New<HInstanceOfKnownGlobal>(left, target);
8260 result->set_position(expr->position());
8261 return ast_context()->ReturnInstruction(result, expr->id()); 8213 return ast_context()->ReturnInstruction(result, expr->id());
8262 } 8214 }
8263 8215
8264 // Code below assumes that we don't fall through. 8216 // Code below assumes that we don't fall through.
8265 UNREACHABLE(); 8217 UNREACHABLE();
8266 } else if (op == Token::IN) { 8218 } else if (op == Token::IN) {
8267 HValue* function = AddLoadJSBuiltin(Builtins::IN); 8219 HValue* function = AddLoadJSBuiltin(Builtins::IN);
8268 Add<HPushArgument>(left); 8220 Add<HPushArgument>(left);
8269 Add<HPushArgument>(right); 8221 Add<HPushArgument>(right);
8270 // TODO(olivf) InvokeFunction produces a check for the parameter count, 8222 // TODO(olivf) InvokeFunction produces a check for the parameter count,
8271 // even though we are certain to pass the correct number of arguments here. 8223 // even though we are certain to pass the correct number of arguments here.
8272 HInstruction* result = New<HInvokeFunction>(function, 2); 8224 HInstruction* result = New<HInvokeFunction>(function, 2);
8273 result->set_position(expr->position());
8274 return ast_context()->ReturnInstruction(result, expr->id()); 8225 return ast_context()->ReturnInstruction(result, expr->id());
8275 } 8226 }
8276 8227
8277 // Cases handled below depend on collected type feedback. They should 8228 // Cases handled below depend on collected type feedback. They should
8278 // soft deoptimize when there is no type feedback. 8229 // soft deoptimize when there is no type feedback.
8279 if (combined_type->Is(Type::None())) { 8230 if (combined_type->Is(Type::None())) {
8280 Add<HDeoptimize>("Insufficient type feedback for combined type " 8231 Add<HDeoptimize>("Insufficient type feedback for combined type "
8281 "of binary operation", 8232 "of binary operation",
8282 Deoptimizer::SOFT); 8233 Deoptimizer::SOFT);
8283 combined_type = left_type = right_type = handle(Type::Any(), isolate()); 8234 combined_type = left_type = right_type = handle(Type::Any(), isolate());
8284 } 8235 }
8285 8236
8286 if (combined_type->Is(Type::Receiver())) { 8237 if (combined_type->Is(Type::Receiver())) {
8287 switch (op) { 8238 switch (op) {
8288 case Token::EQ: 8239 case Token::EQ:
8289 case Token::EQ_STRICT: { 8240 case Token::EQ_STRICT: {
8290 // Can we get away with map check and not instance type check? 8241 // Can we get away with map check and not instance type check?
8291 if (combined_type->IsClass()) { 8242 if (combined_type->IsClass()) {
8292 Handle<Map> map = combined_type->AsClass(); 8243 Handle<Map> map = combined_type->AsClass();
8293 AddCheckMap(left, map); 8244 AddCheckMap(left, map);
8294 AddCheckMap(right, map); 8245 AddCheckMap(right, map);
8295 HCompareObjectEqAndBranch* result = 8246 HCompareObjectEqAndBranch* result =
8296 New<HCompareObjectEqAndBranch>(left, right); 8247 New<HCompareObjectEqAndBranch>(left, right);
8297 result->set_position(expr->position());
8298 return ast_context()->ReturnControl(result, expr->id()); 8248 return ast_context()->ReturnControl(result, expr->id());
8299 } else { 8249 } else {
8300 BuildCheckHeapObject(left); 8250 BuildCheckHeapObject(left);
8301 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); 8251 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_SPEC_OBJECT);
8302 BuildCheckHeapObject(right); 8252 BuildCheckHeapObject(right);
8303 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); 8253 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_SPEC_OBJECT);
8304 HCompareObjectEqAndBranch* result = 8254 HCompareObjectEqAndBranch* result =
8305 New<HCompareObjectEqAndBranch>(left, right); 8255 New<HCompareObjectEqAndBranch>(left, right);
8306 result->set_position(expr->position());
8307 return ast_context()->ReturnControl(result, expr->id()); 8256 return ast_context()->ReturnControl(result, expr->id());
8308 } 8257 }
8309 } 8258 }
8310 default: 8259 default:
8311 return Bailout(kUnsupportedNonPrimitiveCompare); 8260 return Bailout(kUnsupportedNonPrimitiveCompare);
8312 } 8261 }
8313 } else if (combined_type->Is(Type::InternalizedString()) && 8262 } else if (combined_type->Is(Type::InternalizedString()) &&
8314 Token::IsEqualityOp(op)) { 8263 Token::IsEqualityOp(op)) {
8315 BuildCheckHeapObject(left); 8264 BuildCheckHeapObject(left);
8316 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); 8265 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
8317 BuildCheckHeapObject(right); 8266 BuildCheckHeapObject(right);
8318 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); 8267 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
8319 HCompareObjectEqAndBranch* result = 8268 HCompareObjectEqAndBranch* result =
8320 New<HCompareObjectEqAndBranch>(left, right); 8269 New<HCompareObjectEqAndBranch>(left, right);
8321 result->set_position(expr->position());
8322 return ast_context()->ReturnControl(result, expr->id()); 8270 return ast_context()->ReturnControl(result, expr->id());
8323 } else if (combined_type->Is(Type::String())) { 8271 } else if (combined_type->Is(Type::String())) {
8324 BuildCheckHeapObject(left); 8272 BuildCheckHeapObject(left);
8325 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); 8273 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
8326 BuildCheckHeapObject(right); 8274 BuildCheckHeapObject(right);
8327 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); 8275 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
8328 HStringCompareAndBranch* result = 8276 HStringCompareAndBranch* result =
8329 New<HStringCompareAndBranch>(left, right, op); 8277 New<HStringCompareAndBranch>(left, right, op);
8330 result->set_position(expr->position());
8331 return ast_context()->ReturnControl(result, expr->id()); 8278 return ast_context()->ReturnControl(result, expr->id());
8332 } else if (combined_type->NumClasses() == 1 && Token::IsEqualityOp(op)) {
8333 BuildCheckHeapObject(left);
8334 BuildCheckMap(left, combined_type->Classes().Current());
8335 BuildCheckHeapObject(right);
8336 BuildCheckMap(right, combined_type->Classes().Current());
8337 HCompareObjectEqAndBranch* result =
8338 New<HCompareObjectEqAndBranch>(left, right);
8339 result->set_position(expr->position());
8340 return ast_context()->ReturnInstruction(result, expr->id());
8341 } else if (combined_type->Is(Type::Receiver()) && Token::IsEqualityOp(op)) {
8342 BuildCheckHeapObject(left);
8343 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone()));
8344 BuildCheckHeapObject(right);
8345 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone()));
8346 HCompareObjectEqAndBranch* result =
8347 New<HCompareObjectEqAndBranch>(left, right);
8348 result->set_position(expr->position());
8349 return ast_context()->ReturnInstruction(result, expr->id());
8350 } else { 8279 } else {
8351 if (combined_rep.IsTagged() || combined_rep.IsNone()) { 8280 if (combined_rep.IsTagged() || combined_rep.IsNone()) {
8352 HCompareGeneric* result = 8281 HCompareGeneric* result = New<HCompareGeneric>(left, right, op);
8353 new(zone()) HCompareGeneric(context, left, right, op);
8354 result->set_observed_input_representation(1, left_rep); 8282 result->set_observed_input_representation(1, left_rep);
8355 result->set_observed_input_representation(2, right_rep); 8283 result->set_observed_input_representation(2, right_rep);
8356 result->set_position(expr->position());
8357 return ast_context()->ReturnInstruction(result, expr->id()); 8284 return ast_context()->ReturnInstruction(result, expr->id());
8358 } else { 8285 } else {
8359 HCompareNumericAndBranch* result = 8286 HCompareNumericAndBranch* result =
8360 New<HCompareNumericAndBranch>(left, right, op); 8287 New<HCompareNumericAndBranch>(left, right, op);
8361 result->set_observed_input_representation(left_rep, right_rep); 8288 result->set_observed_input_representation(left_rep, right_rep);
8362 result->set_position(expr->position());
8363 return ast_context()->ReturnControl(result, expr->id()); 8289 return ast_context()->ReturnControl(result, expr->id());
8364 } 8290 }
8365 } 8291 }
8366 } 8292 }
8367 8293
8368 8294
8369 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 8295 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
8370 Expression* sub_expr, 8296 Expression* sub_expr,
8371 NilValue nil) { 8297 NilValue nil) {
8372 ASSERT(!HasStackOverflow()); 8298 ASSERT(!HasStackOverflow());
8373 ASSERT(current_block() != NULL); 8299 ASSERT(current_block() != NULL);
8374 ASSERT(current_block()->HasPredecessor()); 8300 ASSERT(current_block()->HasPredecessor());
8375 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); 8301 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
8302 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
8376 CHECK_ALIVE(VisitForValue(sub_expr)); 8303 CHECK_ALIVE(VisitForValue(sub_expr));
8377 HValue* value = Pop(); 8304 HValue* value = Pop();
8378 if (expr->op() == Token::EQ_STRICT) { 8305 if (expr->op() == Token::EQ_STRICT) {
8379 HConstant* nil_constant = nil == kNullValue 8306 HConstant* nil_constant = nil == kNullValue
8380 ? graph()->GetConstantNull() 8307 ? graph()->GetConstantNull()
8381 : graph()->GetConstantUndefined(); 8308 : graph()->GetConstantUndefined();
8382 HCompareObjectEqAndBranch* instr = 8309 HCompareObjectEqAndBranch* instr =
8383 New<HCompareObjectEqAndBranch>(value, nil_constant); 8310 New<HCompareObjectEqAndBranch>(value, nil_constant);
8384 instr->set_position(expr->position());
8385 return ast_context()->ReturnControl(instr, expr->id()); 8311 return ast_context()->ReturnControl(instr, expr->id());
8386 } else { 8312 } else {
8387 ASSERT_EQ(Token::EQ, expr->op()); 8313 ASSERT_EQ(Token::EQ, expr->op());
8388 Handle<Type> type = expr->combined_type()->Is(Type::None()) 8314 Handle<Type> type = expr->combined_type()->Is(Type::None())
8389 ? handle(Type::Any(), isolate_) 8315 ? handle(Type::Any(), isolate_)
8390 : expr->combined_type(); 8316 : expr->combined_type();
8391 HIfContinuation continuation; 8317 HIfContinuation continuation;
8392 BuildCompareNil(value, type, expr->position(), &continuation); 8318 BuildCompareNil(value, type, &continuation);
8393 return ast_context()->ReturnContinuation(&continuation, expr->id()); 8319 return ast_context()->ReturnContinuation(&continuation, expr->id());
8394 } 8320 }
8395 } 8321 }
8396 8322
8397 8323
8398 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { 8324 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
8399 // If we share optimized code between different closures, the 8325 // If we share optimized code between different closures, the
8400 // this-function is not a constant, except inside an inlined body. 8326 // this-function is not a constant, except inside an inlined body.
8401 if (function_state()->outer() != NULL) { 8327 if (function_state()->outer() != NULL) {
8402 return New<HConstant>( 8328 return New<HConstant>(
8403 function_state()->compilation_info()->closure()); 8329 function_state()->compilation_info()->closure());
8404 } else { 8330 } else {
8405 return new(zone()) HThisFunction; 8331 return New<HThisFunction>();
8406 } 8332 }
8407 } 8333 }
8408 8334
8409 8335
8410 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( 8336 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
8411 Handle<JSObject> boilerplate_object) { 8337 Handle<JSObject> boilerplate_object,
8338 AllocationSiteContext* site_context) {
8412 NoObservableSideEffectsScope no_effects(this); 8339 NoObservableSideEffectsScope no_effects(this);
8413 InstanceType instance_type = boilerplate_object->map()->instance_type(); 8340 InstanceType instance_type = boilerplate_object->map()->instance_type();
8414 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); 8341 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
8415 8342
8416 HType type = instance_type == JS_ARRAY_TYPE 8343 HType type = instance_type == JS_ARRAY_TYPE
8417 ? HType::JSArray() : HType::JSObject(); 8344 ? HType::JSArray() : HType::JSObject();
8418 HValue* object_size_constant = Add<HConstant>( 8345 HValue* object_size_constant = Add<HConstant>(
8419 boilerplate_object->map()->instance_size()); 8346 boilerplate_object->map()->instance_size());
8420 HInstruction* object = Add<HAllocate>(object_size_constant, type, 8347 HInstruction* object = Add<HAllocate>(object_size_constant, type,
8421 isolate()->heap()->GetPretenureMode(), instance_type); 8348 isolate()->heap()->GetPretenureMode(), instance_type);
(...skipping 11 matching lines...) Expand all
8433 if (boilerplate_object->HasFastDoubleElements()) { 8360 if (boilerplate_object->HasFastDoubleElements()) {
8434 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), 8361 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(),
8435 isolate()->heap()->GetPretenureMode(), FIXED_DOUBLE_ARRAY_TYPE); 8362 isolate()->heap()->GetPretenureMode(), FIXED_DOUBLE_ARRAY_TYPE);
8436 } else { 8363 } else {
8437 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), 8364 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(),
8438 isolate()->heap()->GetPretenureMode(), FIXED_ARRAY_TYPE); 8365 isolate()->heap()->GetPretenureMode(), FIXED_ARRAY_TYPE);
8439 } 8366 }
8440 } 8367 }
8441 BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements); 8368 BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements);
8442 8369
8443
8444 // Copy object elements if non-COW. 8370 // Copy object elements if non-COW.
8445 if (object_elements != NULL) { 8371 if (object_elements != NULL) {
8446 BuildEmitElements(boilerplate_object, elements, object_elements); 8372 BuildEmitElements(boilerplate_object, elements, object_elements,
8373 site_context);
8447 } 8374 }
8448 8375
8449 // Copy in-object properties. 8376 // Copy in-object properties.
8450 if (boilerplate_object->map()->NumberOfFields() != 0) { 8377 if (boilerplate_object->map()->NumberOfFields() != 0) {
8451 BuildEmitInObjectProperties(boilerplate_object, object); 8378 BuildEmitInObjectProperties(boilerplate_object, object, site_context);
8452 } 8379 }
8453 return object; 8380 return object;
8454 } 8381 }
8455 8382
8456 8383
8457 void HOptimizedGraphBuilder::BuildEmitObjectHeader( 8384 void HOptimizedGraphBuilder::BuildEmitObjectHeader(
8458 Handle<JSObject> boilerplate_object, 8385 Handle<JSObject> boilerplate_object,
8459 HInstruction* object) { 8386 HInstruction* object) {
8460 ASSERT(boilerplate_object->properties()->length() == 0); 8387 ASSERT(boilerplate_object->properties()->length() == 0);
8461 8388
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
8493 Handle<Object>(boilerplate_object->elements(), isolate()); 8420 Handle<Object>(boilerplate_object->elements(), isolate());
8494 object_elements = Add<HConstant>(elements_field); 8421 object_elements = Add<HConstant>(elements_field);
8495 } 8422 }
8496 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), 8423 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
8497 object_elements); 8424 object_elements);
8498 } 8425 }
8499 8426
8500 8427
8501 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( 8428 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
8502 Handle<JSObject> boilerplate_object, 8429 Handle<JSObject> boilerplate_object,
8503 HInstruction* object) { 8430 HInstruction* object,
8431 AllocationSiteContext* site_context) {
8504 Handle<DescriptorArray> descriptors( 8432 Handle<DescriptorArray> descriptors(
8505 boilerplate_object->map()->instance_descriptors()); 8433 boilerplate_object->map()->instance_descriptors());
8506 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); 8434 int limit = boilerplate_object->map()->NumberOfOwnDescriptors();
8507 8435
8508 int copied_fields = 0; 8436 int copied_fields = 0;
8509 for (int i = 0; i < limit; i++) { 8437 for (int i = 0; i < limit; i++) {
8510 PropertyDetails details = descriptors->GetDetails(i); 8438 PropertyDetails details = descriptors->GetDetails(i);
8511 if (details.type() != FIELD) continue; 8439 if (details.type() != FIELD) continue;
8512 copied_fields++; 8440 copied_fields++;
8513 int index = descriptors->GetFieldIndex(i); 8441 int index = descriptors->GetFieldIndex(i);
8514 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); 8442 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index);
8515 Handle<Name> name(descriptors->GetKey(i)); 8443 Handle<Name> name(descriptors->GetKey(i));
8516 Handle<Object> value = 8444 Handle<Object> value =
8517 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), 8445 Handle<Object>(boilerplate_object->InObjectPropertyAt(index),
8518 isolate()); 8446 isolate());
8519 8447
8520 // The access for the store depends on the type of the boilerplate. 8448 // The access for the store depends on the type of the boilerplate.
8521 HObjectAccess access = boilerplate_object->IsJSArray() ? 8449 HObjectAccess access = boilerplate_object->IsJSArray() ?
8522 HObjectAccess::ForJSArrayOffset(property_offset) : 8450 HObjectAccess::ForJSArrayOffset(property_offset) :
8523 HObjectAccess::ForJSObjectOffset(property_offset); 8451 HObjectAccess::ForJSObjectOffset(property_offset);
8524 8452
8525 if (value->IsJSObject()) { 8453 if (value->IsJSObject()) {
8526 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 8454 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
8527 HInstruction* result = BuildFastLiteral(value_object); 8455 Handle<AllocationSite> current_site = site_context->EnterNewScope();
8456 HInstruction* result =
8457 BuildFastLiteral(value_object, site_context);
8458 site_context->ExitScope(current_site, value_object);
8528 Add<HStoreNamedField>(object, access, result); 8459 Add<HStoreNamedField>(object, access, result);
8529 } else { 8460 } else {
8530 Representation representation = details.representation(); 8461 Representation representation = details.representation();
8531 HInstruction* value_instruction = Add<HConstant>(value); 8462 HInstruction* value_instruction = Add<HConstant>(value);
8532 8463
8533 if (representation.IsDouble()) { 8464 if (representation.IsDouble()) {
8534 // Allocate a HeapNumber box and store the value into it. 8465 // Allocate a HeapNumber box and store the value into it.
8535 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize); 8466 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
8467 // TODO(mvstanton): This heap number alloc does not have a corresponding
8468 // AllocationSite. That is okay because
8469 // 1) it's a child object of another object with a valid allocation site
8470 // 2) we can just use the mode of the parent object for pretenuring
8471 // The todo is replace GetPretenureMode() with
8472 // site_context->top()->GetPretenureMode().
8536 HInstruction* double_box = 8473 HInstruction* double_box =
8537 Add<HAllocate>(heap_number_constant, HType::HeapNumber(), 8474 Add<HAllocate>(heap_number_constant, HType::HeapNumber(),
8538 isolate()->heap()->GetPretenureMode(), HEAP_NUMBER_TYPE); 8475 isolate()->heap()->GetPretenureMode(), HEAP_NUMBER_TYPE);
8539 AddStoreMapConstant(double_box, 8476 AddStoreMapConstant(double_box,
8540 isolate()->factory()->heap_number_map()); 8477 isolate()->factory()->heap_number_map());
8541 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), 8478 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(),
8542 value_instruction); 8479 value_instruction);
8543 value_instruction = double_box; 8480 value_instruction = double_box;
8544 } 8481 }
8545 8482
8546 Add<HStoreNamedField>(object, access, value_instruction); 8483 Add<HStoreNamedField>(object, access, value_instruction);
8547 } 8484 }
8548 } 8485 }
8549 8486
8550 int inobject_properties = boilerplate_object->map()->inobject_properties(); 8487 int inobject_properties = boilerplate_object->map()->inobject_properties();
8551 HInstruction* value_instruction = 8488 HInstruction* value_instruction =
8552 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); 8489 Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
8553 for (int i = copied_fields; i < inobject_properties; i++) { 8490 for (int i = copied_fields; i < inobject_properties; i++) {
8554 ASSERT(boilerplate_object->IsJSObject()); 8491 ASSERT(boilerplate_object->IsJSObject());
8555 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); 8492 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
8556 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); 8493 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset);
8557 Add<HStoreNamedField>(object, access, value_instruction); 8494 Add<HStoreNamedField>(object, access, value_instruction);
8558 } 8495 }
8559 } 8496 }
8560 8497
8561 8498
8562 void HOptimizedGraphBuilder::BuildEmitElements( 8499 void HOptimizedGraphBuilder::BuildEmitElements(
8563 Handle<JSObject> boilerplate_object, 8500 Handle<JSObject> boilerplate_object,
8564 Handle<FixedArrayBase> elements, 8501 Handle<FixedArrayBase> elements,
8565 HValue* object_elements) { 8502 HValue* object_elements,
8503 AllocationSiteContext* site_context) {
8566 ElementsKind kind = boilerplate_object->map()->elements_kind(); 8504 ElementsKind kind = boilerplate_object->map()->elements_kind();
8567 int elements_length = elements->length(); 8505 int elements_length = elements->length();
8568 HValue* object_elements_length = Add<HConstant>(elements_length); 8506 HValue* object_elements_length = Add<HConstant>(elements_length);
8569 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); 8507 BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
8570 8508
8571 // Copy elements backing store content. 8509 // Copy elements backing store content.
8572 if (elements->IsFixedDoubleArray()) { 8510 if (elements->IsFixedDoubleArray()) {
8573 BuildEmitFixedDoubleArray(elements, kind, object_elements); 8511 BuildEmitFixedDoubleArray(elements, kind, object_elements);
8574 } else if (elements->IsFixedArray()) { 8512 } else if (elements->IsFixedArray()) {
8575 BuildEmitFixedArray(elements, kind, object_elements); 8513 BuildEmitFixedArray(elements, kind, object_elements,
8514 site_context);
8576 } else { 8515 } else {
8577 UNREACHABLE(); 8516 UNREACHABLE();
8578 } 8517 }
8579 } 8518 }
8580 8519
8581 8520
8582 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( 8521 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
8583 Handle<FixedArrayBase> elements, 8522 Handle<FixedArrayBase> elements,
8584 ElementsKind kind, 8523 ElementsKind kind,
8585 HValue* object_elements) { 8524 HValue* object_elements) {
8586 HInstruction* boilerplate_elements = Add<HConstant>(elements); 8525 HInstruction* boilerplate_elements = Add<HConstant>(elements);
8587 int elements_length = elements->length(); 8526 int elements_length = elements->length();
8588 for (int i = 0; i < elements_length; i++) { 8527 for (int i = 0; i < elements_length; i++) {
8589 HValue* key_constant = Add<HConstant>(i); 8528 HValue* key_constant = Add<HConstant>(i);
8590 HInstruction* value_instruction = 8529 HInstruction* value_instruction =
8591 Add<HLoadKeyed>(boilerplate_elements, key_constant, 8530 Add<HLoadKeyed>(boilerplate_elements, key_constant,
8592 static_cast<HValue*>(NULL), kind, 8531 static_cast<HValue*>(NULL), kind,
8593 ALLOW_RETURN_HOLE); 8532 ALLOW_RETURN_HOLE);
8594 HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant, 8533 HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
8595 value_instruction, kind); 8534 value_instruction, kind);
8596 store->SetFlag(HValue::kAllowUndefinedAsNaN); 8535 store->SetFlag(HValue::kAllowUndefinedAsNaN);
8597 } 8536 }
8598 } 8537 }
8599 8538
8600 8539
8601 void HOptimizedGraphBuilder::BuildEmitFixedArray( 8540 void HOptimizedGraphBuilder::BuildEmitFixedArray(
8602 Handle<FixedArrayBase> elements, 8541 Handle<FixedArrayBase> elements,
8603 ElementsKind kind, 8542 ElementsKind kind,
8604 HValue* object_elements) { 8543 HValue* object_elements,
8544 AllocationSiteContext* site_context) {
8605 HInstruction* boilerplate_elements = Add<HConstant>(elements); 8545 HInstruction* boilerplate_elements = Add<HConstant>(elements);
8606 int elements_length = elements->length(); 8546 int elements_length = elements->length();
8607 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); 8547 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
8608 for (int i = 0; i < elements_length; i++) { 8548 for (int i = 0; i < elements_length; i++) {
8609 Handle<Object> value(fast_elements->get(i), isolate()); 8549 Handle<Object> value(fast_elements->get(i), isolate());
8610 HValue* key_constant = Add<HConstant>(i); 8550 HValue* key_constant = Add<HConstant>(i);
8611 if (value->IsJSObject()) { 8551 if (value->IsJSObject()) {
8612 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 8552 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
8613 HInstruction* result = BuildFastLiteral(value_object); 8553 Handle<AllocationSite> current_site = site_context->EnterNewScope();
8554 HInstruction* result =
8555 BuildFastLiteral(value_object, site_context);
8556 site_context->ExitScope(current_site, value_object);
8614 Add<HStoreKeyed>(object_elements, key_constant, result, kind); 8557 Add<HStoreKeyed>(object_elements, key_constant, result, kind);
8615 } else { 8558 } else {
8616 HInstruction* value_instruction = 8559 HInstruction* value_instruction =
8617 Add<HLoadKeyed>(boilerplate_elements, key_constant, 8560 Add<HLoadKeyed>(boilerplate_elements, key_constant,
8618 static_cast<HValue*>(NULL), kind, 8561 static_cast<HValue*>(NULL), kind,
8619 ALLOW_RETURN_HOLE); 8562 ALLOW_RETURN_HOLE);
8620 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); 8563 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind);
8621 } 8564 }
8622 } 8565 }
8623 } 8566 }
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
8776 HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value); 8719 HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
8777 return ast_context()->ReturnControl(result, call->id()); 8720 return ast_context()->ReturnControl(result, call->id());
8778 } 8721 }
8779 8722
8780 8723
8781 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { 8724 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
8782 ASSERT(call->arguments()->length() == 1); 8725 ASSERT(call->arguments()->length() == 1);
8783 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8726 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8784 HValue* value = Pop(); 8727 HValue* value = Pop();
8785 HHasInstanceTypeAndBranch* result = 8728 HHasInstanceTypeAndBranch* result =
8786 new(zone()) HHasInstanceTypeAndBranch(value, 8729 New<HHasInstanceTypeAndBranch>(value,
8787 FIRST_SPEC_OBJECT_TYPE, 8730 FIRST_SPEC_OBJECT_TYPE,
8788 LAST_SPEC_OBJECT_TYPE); 8731 LAST_SPEC_OBJECT_TYPE);
8789 return ast_context()->ReturnControl(result, call->id()); 8732 return ast_context()->ReturnControl(result, call->id());
8790 } 8733 }
8791 8734
8792 8735
8793 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) { 8736 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
8794 ASSERT(call->arguments()->length() == 1); 8737 ASSERT(call->arguments()->length() == 1);
8795 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8738 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8796 HValue* value = Pop(); 8739 HValue* value = Pop();
8797 HHasInstanceTypeAndBranch* result = 8740 HHasInstanceTypeAndBranch* result =
8798 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); 8741 New<HHasInstanceTypeAndBranch>(value, JS_FUNCTION_TYPE);
8799 return ast_context()->ReturnControl(result, call->id()); 8742 return ast_context()->ReturnControl(result, call->id());
8800 } 8743 }
8801 8744
8802 8745
8803 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { 8746 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
8804 ASSERT(call->arguments()->length() == 1); 8747 ASSERT(call->arguments()->length() == 1);
8805 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8748 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8806 HValue* value = Pop(); 8749 HValue* value = Pop();
8807 HHasCachedArrayIndexAndBranch* result = 8750 HHasCachedArrayIndexAndBranch* result =
8808 new(zone()) HHasCachedArrayIndexAndBranch(value); 8751 New<HHasCachedArrayIndexAndBranch>(value);
8809 return ast_context()->ReturnControl(result, call->id()); 8752 return ast_context()->ReturnControl(result, call->id());
8810 } 8753 }
8811 8754
8812 8755
8813 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) { 8756 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
8814 ASSERT(call->arguments()->length() == 1); 8757 ASSERT(call->arguments()->length() == 1);
8815 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8758 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8816 HValue* value = Pop(); 8759 HValue* value = Pop();
8817 HHasInstanceTypeAndBranch* result = 8760 HHasInstanceTypeAndBranch* result =
8818 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); 8761 New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
8819 return ast_context()->ReturnControl(result, call->id()); 8762 return ast_context()->ReturnControl(result, call->id());
8820 } 8763 }
8821 8764
8822 8765
8823 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) { 8766 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
8824 ASSERT(call->arguments()->length() == 1); 8767 ASSERT(call->arguments()->length() == 1);
8825 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8768 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8826 HValue* value = Pop(); 8769 HValue* value = Pop();
8827 HHasInstanceTypeAndBranch* result = 8770 HHasInstanceTypeAndBranch* result =
8828 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE); 8771 New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE);
8829 return ast_context()->ReturnControl(result, call->id()); 8772 return ast_context()->ReturnControl(result, call->id());
8830 } 8773 }
8831 8774
8832 8775
8833 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) { 8776 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
8834 ASSERT(call->arguments()->length() == 1); 8777 ASSERT(call->arguments()->length() == 1);
8835 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8778 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8836 HValue* value = Pop(); 8779 HValue* value = Pop();
8837 HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value); 8780 HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value);
8838 return ast_context()->ReturnControl(result, call->id()); 8781 return ast_context()->ReturnControl(result, call->id());
(...skipping 23 matching lines...) Expand all
8862 // Support for construct call checks. 8805 // Support for construct call checks.
8863 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { 8806 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
8864 ASSERT(call->arguments()->length() == 0); 8807 ASSERT(call->arguments()->length() == 0);
8865 if (function_state()->outer() != NULL) { 8808 if (function_state()->outer() != NULL) {
8866 // We are generating graph for inlined function. 8809 // We are generating graph for inlined function.
8867 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN 8810 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN
8868 ? graph()->GetConstantTrue() 8811 ? graph()->GetConstantTrue()
8869 : graph()->GetConstantFalse(); 8812 : graph()->GetConstantFalse();
8870 return ast_context()->ReturnValue(value); 8813 return ast_context()->ReturnValue(value);
8871 } else { 8814 } else {
8872 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, 8815 return ast_context()->ReturnControl(New<HIsConstructCallAndBranch>(),
8873 call->id()); 8816 call->id());
8874 } 8817 }
8875 } 8818 }
8876 8819
8877 8820
8878 // Support for arguments.length and arguments[?]. 8821 // Support for arguments.length and arguments[?].
8879 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { 8822 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
8880 // Our implementation of arguments (based on this stack frame or an 8823 // Our implementation of arguments (based on this stack frame or an
8881 // adapter below it) does not work for inlined functions. This runtime 8824 // adapter below it) does not work for inlined functions. This runtime
8882 // function is blacklisted by AstNode::IsInlineable. 8825 // function is blacklisted by AstNode::IsInlineable.
8883 ASSERT(function_state()->outer() == NULL); 8826 ASSERT(function_state()->outer() == NULL);
8884 ASSERT(call->arguments()->length() == 0); 8827 ASSERT(call->arguments()->length() == 0);
8885 HInstruction* elements = Add<HArgumentsElements>(false); 8828 HInstruction* elements = Add<HArgumentsElements>(false);
8886 HArgumentsLength* result = New<HArgumentsLength>(elements); 8829 HArgumentsLength* result = New<HArgumentsLength>(elements);
8887 return ast_context()->ReturnInstruction(result, call->id()); 8830 return ast_context()->ReturnInstruction(result, call->id());
8888 } 8831 }
8889 8832
8890 8833
8891 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { 8834 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
8892 // Our implementation of arguments (based on this stack frame or an 8835 // Our implementation of arguments (based on this stack frame or an
8893 // adapter below it) does not work for inlined functions. This runtime 8836 // adapter below it) does not work for inlined functions. This runtime
8894 // function is blacklisted by AstNode::IsInlineable. 8837 // function is blacklisted by AstNode::IsInlineable.
8895 ASSERT(function_state()->outer() == NULL); 8838 ASSERT(function_state()->outer() == NULL);
8896 ASSERT(call->arguments()->length() == 1); 8839 ASSERT(call->arguments()->length() == 1);
8897 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8840 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8898 HValue* index = Pop(); 8841 HValue* index = Pop();
8899 HInstruction* elements = Add<HArgumentsElements>(false); 8842 HInstruction* elements = Add<HArgumentsElements>(false);
8900 HInstruction* length = Add<HArgumentsLength>(elements); 8843 HInstruction* length = Add<HArgumentsLength>(elements);
8901 HInstruction* checked_index = Add<HBoundsCheck>(index, length); 8844 HInstruction* checked_index = Add<HBoundsCheck>(index, length);
8902 HAccessArgumentsAt* result = 8845 HAccessArgumentsAt* result = New<HAccessArgumentsAt>(
8903 new(zone()) HAccessArgumentsAt(elements, length, checked_index); 8846 elements, length, checked_index);
8904 return ast_context()->ReturnInstruction(result, call->id()); 8847 return ast_context()->ReturnInstruction(result, call->id());
8905 } 8848 }
8906 8849
8907 8850
8908 // Support for accessing the class and value fields of an object. 8851 // Support for accessing the class and value fields of an object.
8909 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { 8852 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) {
8910 // The special form detected by IsClassOfTest is detected before we get here 8853 // The special form detected by IsClassOfTest is detected before we get here
8911 // and does not cause a bailout. 8854 // and does not cause a bailout.
8912 return Bailout(kInlinedRuntimeFunctionClassOf); 8855 return Bailout(kInlinedRuntimeFunctionClassOf);
8913 } 8856 }
8914 8857
8915 8858
8916 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { 8859 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
8917 ASSERT(call->arguments()->length() == 1); 8860 ASSERT(call->arguments()->length() == 1);
8918 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8861 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8919 HValue* value = Pop(); 8862 HValue* value = Pop();
8920 HValueOf* result = new(zone()) HValueOf(value); 8863 HValueOf* result = New<HValueOf>(value);
8921 return ast_context()->ReturnInstruction(result, call->id()); 8864 return ast_context()->ReturnInstruction(result, call->id());
8922 } 8865 }
8923 8866
8924 8867
8925 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) { 8868 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
8926 ASSERT(call->arguments()->length() == 2); 8869 ASSERT(call->arguments()->length() == 2);
8927 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); 8870 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral());
8928 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value())); 8871 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value()));
8929 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8872 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8930 HValue* date = Pop(); 8873 HValue* date = Pop();
8931 HDateField* result = new(zone()) HDateField(date, index); 8874 HDateField* result = New<HDateField>(date, index);
8932 return ast_context()->ReturnInstruction(result, call->id()); 8875 return ast_context()->ReturnInstruction(result, call->id());
8933 } 8876 }
8934 8877
8935 8878
8936 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar( 8879 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
8937 CallRuntime* call) { 8880 CallRuntime* call) {
8938 ASSERT(call->arguments()->length() == 3); 8881 ASSERT(call->arguments()->length() == 3);
8939 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8882 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8940 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 8883 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
8941 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); 8884 CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
8942 HValue* value = Pop(); 8885 HValue* value = Pop();
8943 HValue* index = Pop(); 8886 HValue* index = Pop();
8944 HValue* string = Pop(); 8887 HValue* string = Pop();
8945 HSeqStringSetChar* result = new(zone()) HSeqStringSetChar( 8888 HSeqStringSetChar* result = New<HSeqStringSetChar>(
8946 String::ONE_BYTE_ENCODING, string, index, value); 8889 String::ONE_BYTE_ENCODING, string, index, value);
8947 return ast_context()->ReturnInstruction(result, call->id()); 8890 return ast_context()->ReturnInstruction(result, call->id());
8948 } 8891 }
8949 8892
8950 8893
8951 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar( 8894 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
8952 CallRuntime* call) { 8895 CallRuntime* call) {
8953 ASSERT(call->arguments()->length() == 3); 8896 ASSERT(call->arguments()->length() == 3);
8954 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8897 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8955 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 8898 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
8956 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); 8899 CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
8957 HValue* value = Pop(); 8900 HValue* value = Pop();
8958 HValue* index = Pop(); 8901 HValue* index = Pop();
8959 HValue* string = Pop(); 8902 HValue* string = Pop();
8960 HSeqStringSetChar* result = new(zone()) HSeqStringSetChar( 8903 HSeqStringSetChar* result = New<HSeqStringSetChar>(
8961 String::TWO_BYTE_ENCODING, string, index, value); 8904 String::TWO_BYTE_ENCODING, string, index, value);
8962 return ast_context()->ReturnInstruction(result, call->id()); 8905 return ast_context()->ReturnInstruction(result, call->id());
8963 } 8906 }
8964 8907
8965 8908
8966 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { 8909 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
8967 ASSERT(call->arguments()->length() == 2); 8910 ASSERT(call->arguments()->length() == 2);
8968 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8911 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8969 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 8912 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
8970 HValue* value = Pop(); 8913 HValue* value = Pop();
8971 HValue* object = Pop(); 8914 HValue* object = Pop();
8972 // Check if object is a not a smi. 8915 // Check if object is a not a smi.
8973 HBasicBlock* if_smi = graph()->CreateBasicBlock(); 8916 HBasicBlock* if_smi = graph()->CreateBasicBlock();
8974 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); 8917 HBasicBlock* if_heap_object = graph()->CreateBasicBlock();
8975 HBasicBlock* join = graph()->CreateBasicBlock(); 8918 HBasicBlock* join = graph()->CreateBasicBlock();
8976 current_block()->Finish(New<HIsSmiAndBranch>(object, if_smi, if_heap_object)); 8919 FinishCurrentBlock(New<HIsSmiAndBranch>(object, if_smi, if_heap_object));
8977 if_smi->Goto(join); 8920 Goto(if_smi, join);
8978 8921
8979 // Check if object is a JSValue. 8922 // Check if object is a JSValue.
8980 set_current_block(if_heap_object); 8923 set_current_block(if_heap_object);
8981 HHasInstanceTypeAndBranch* typecheck = 8924 HHasInstanceTypeAndBranch* typecheck =
8982 new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE); 8925 New<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
8983 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); 8926 HBasicBlock* if_js_value = graph()->CreateBasicBlock();
8984 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); 8927 HBasicBlock* not_js_value = graph()->CreateBasicBlock();
8985 typecheck->SetSuccessorAt(0, if_js_value); 8928 typecheck->SetSuccessorAt(0, if_js_value);
8986 typecheck->SetSuccessorAt(1, not_js_value); 8929 typecheck->SetSuccessorAt(1, not_js_value);
8987 current_block()->Finish(typecheck); 8930 FinishCurrentBlock(typecheck);
8988 not_js_value->Goto(join); 8931 Goto(not_js_value, join);
8989 8932
8990 // Create in-object property store to kValueOffset. 8933 // Create in-object property store to kValueOffset.
8991 set_current_block(if_js_value); 8934 set_current_block(if_js_value);
8992 Add<HStoreNamedField>(object, 8935 Add<HStoreNamedField>(object,
8993 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); 8936 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value);
8994 if_js_value->Goto(join); 8937 Goto(if_js_value, join);
8995 join->SetJoinId(call->id()); 8938 join->SetJoinId(call->id());
8996 set_current_block(join); 8939 set_current_block(join);
8997 return ast_context()->ReturnValue(value); 8940 return ast_context()->ReturnValue(value);
8998 } 8941 }
8999 8942
9000 8943
9001 // Fast support for charCodeAt(n). 8944 // Fast support for charCodeAt(n).
9002 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { 8945 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
9003 ASSERT(call->arguments()->length() == 2); 8946 ASSERT(call->arguments()->length() == 2);
9004 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8947 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9005 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 8948 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9006 HValue* index = Pop(); 8949 HValue* index = Pop();
9007 HValue* string = Pop(); 8950 HValue* string = Pop();
9008 HInstruction* result = BuildStringCharCodeAt(string, index); 8951 HInstruction* result = BuildStringCharCodeAt(string, index);
9009 return ast_context()->ReturnInstruction(result, call->id()); 8952 return ast_context()->ReturnInstruction(result, call->id());
9010 } 8953 }
9011 8954
9012 8955
9013 // Fast support for string.charAt(n) and string[n]. 8956 // Fast support for string.charAt(n) and string[n].
9014 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { 8957 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
9015 ASSERT(call->arguments()->length() == 1); 8958 ASSERT(call->arguments()->length() == 1);
9016 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8959 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9017 HValue* char_code = Pop(); 8960 HValue* char_code = Pop();
9018 HInstruction* result = New<HStringCharFromCode>(char_code); 8961 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
9019 return ast_context()->ReturnInstruction(result, call->id()); 8962 return ast_context()->ReturnInstruction(result, call->id());
9020 } 8963 }
9021 8964
9022 8965
9023 // Fast support for string.charAt(n) and string[n]. 8966 // Fast support for string.charAt(n) and string[n].
9024 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { 8967 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
9025 ASSERT(call->arguments()->length() == 2); 8968 ASSERT(call->arguments()->length() == 2);
9026 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8969 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9027 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 8970 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9028 HValue* index = Pop(); 8971 HValue* index = Pop();
9029 HValue* string = Pop(); 8972 HValue* string = Pop();
9030 HInstruction* char_code = BuildStringCharCodeAt(string, index); 8973 HInstruction* char_code = BuildStringCharCodeAt(string, index);
9031 AddInstruction(char_code); 8974 AddInstruction(char_code);
9032 HInstruction* result = New<HStringCharFromCode>(char_code); 8975 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
9033 return ast_context()->ReturnInstruction(result, call->id()); 8976 return ast_context()->ReturnInstruction(result, call->id());
9034 } 8977 }
9035 8978
9036 8979
9037 // Fast support for object equality testing. 8980 // Fast support for object equality testing.
9038 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { 8981 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
9039 ASSERT(call->arguments()->length() == 2); 8982 ASSERT(call->arguments()->length() == 2);
9040 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8983 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9041 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 8984 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9042 HValue* right = Pop(); 8985 HValue* right = Pop();
9043 HValue* left = Pop(); 8986 HValue* left = Pop();
9044 HCompareObjectEqAndBranch* result = 8987 HCompareObjectEqAndBranch* result =
9045 New<HCompareObjectEqAndBranch>(left, right); 8988 New<HCompareObjectEqAndBranch>(left, right);
9046 return ast_context()->ReturnControl(result, call->id()); 8989 return ast_context()->ReturnControl(result, call->id());
9047 } 8990 }
9048 8991
9049 8992
9050 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { 8993 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) {
9051 // %_Log is ignored in optimized code. 8994 // %_Log is ignored in optimized code.
9052 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 8995 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
9053 } 8996 }
9054 8997
9055 8998
9056 // Fast support for Math.random(). 8999 // Fast support for Math.random().
9057 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { 9000 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
9058 HGlobalObject* global_object = Add<HGlobalObject>(); 9001 HGlobalObject* global_object = Add<HGlobalObject>();
9059 HRandom* result = new(zone()) HRandom(global_object); 9002 HRandom* result = New<HRandom>(global_object);
9060 return ast_context()->ReturnInstruction(result, call->id()); 9003 return ast_context()->ReturnInstruction(result, call->id());
9061 } 9004 }
9062 9005
9063 9006
9064 // Fast support for StringAdd. 9007 // Fast support for StringAdd.
9065 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { 9008 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
9066 ASSERT_EQ(2, call->arguments()->length()); 9009 ASSERT_EQ(2, call->arguments()->length());
9067 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9010 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9068 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 9011 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9069 HValue* right = Pop(); 9012 HValue* right = Pop();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
9117 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { 9060 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
9118 return Bailout(kInlinedRuntimeFunctionGetFromCache); 9061 return Bailout(kInlinedRuntimeFunctionGetFromCache);
9119 } 9062 }
9120 9063
9121 9064
9122 // Fast support for number to string. 9065 // Fast support for number to string.
9123 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { 9066 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
9124 ASSERT_EQ(1, call->arguments()->length()); 9067 ASSERT_EQ(1, call->arguments()->length());
9125 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9068 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9126 HValue* number = Pop(); 9069 HValue* number = Pop();
9127 HValue* result = BuildNumberToString(number); 9070 HValue* result = BuildNumberToString(
9071 number, handle(Type::Number(), isolate()));
9128 return ast_context()->ReturnValue(result); 9072 return ast_context()->ReturnValue(result);
9129 } 9073 }
9130 9074
9131 9075
9132 // Fast call for custom callbacks. 9076 // Fast call for custom callbacks.
9133 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { 9077 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
9134 // 1 ~ The function to call is not itself an argument to the call. 9078 // 1 ~ The function to call is not itself an argument to the call.
9135 int arg_count = call->arguments()->length() - 1; 9079 int arg_count = call->arguments()->length() - 1;
9136 ASSERT(arg_count >= 1); // There's always at least a receiver. 9080 ASSERT(arg_count >= 1); // There's always at least a receiver.
9137 9081
9138 for (int i = 0; i < arg_count; ++i) { 9082 for (int i = 0; i < arg_count; ++i) {
9139 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); 9083 CHECK_ALIVE(VisitArgument(call->arguments()->at(i)));
9140 } 9084 }
9141 CHECK_ALIVE(VisitForValue(call->arguments()->last())); 9085 CHECK_ALIVE(VisitForValue(call->arguments()->last()));
9142 9086
9143 HValue* function = Pop(); 9087 HValue* function = Pop();
9144 9088
9145 // Branch for function proxies, or other non-functions. 9089 // Branch for function proxies, or other non-functions.
9146 HHasInstanceTypeAndBranch* typecheck = 9090 HHasInstanceTypeAndBranch* typecheck =
9147 new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE); 9091 New<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE);
9148 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); 9092 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock();
9149 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); 9093 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock();
9150 HBasicBlock* join = graph()->CreateBasicBlock(); 9094 HBasicBlock* join = graph()->CreateBasicBlock();
9151 typecheck->SetSuccessorAt(0, if_jsfunction); 9095 typecheck->SetSuccessorAt(0, if_jsfunction);
9152 typecheck->SetSuccessorAt(1, if_nonfunction); 9096 typecheck->SetSuccessorAt(1, if_nonfunction);
9153 current_block()->Finish(typecheck); 9097 FinishCurrentBlock(typecheck);
9154 9098
9155 set_current_block(if_jsfunction); 9099 set_current_block(if_jsfunction);
9156 HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count); 9100 HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count);
9157 Drop(arg_count); 9101 Drop(arg_count);
9158 Push(invoke_result); 9102 Push(invoke_result);
9159 if_jsfunction->Goto(join); 9103 Goto(if_jsfunction, join);
9160 9104
9161 set_current_block(if_nonfunction); 9105 set_current_block(if_nonfunction);
9162 HInstruction* call_result = Add<HCallFunction>(function, arg_count); 9106 HInstruction* call_result = Add<HCallFunction>(function, arg_count);
9163 Drop(arg_count); 9107 Drop(arg_count);
9164 Push(call_result); 9108 Push(call_result);
9165 if_nonfunction->Goto(join); 9109 Goto(if_nonfunction, join);
9166 9110
9167 set_current_block(join); 9111 set_current_block(join);
9168 join->SetJoinId(call->id()); 9112 join->SetJoinId(call->id());
9169 return ast_context()->ReturnValue(Pop()); 9113 return ast_context()->ReturnValue(Pop());
9170 } 9114 }
9171 9115
9172 9116
9173 // Fast call to math functions. 9117 // Fast call to math functions.
9174 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { 9118 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
9175 ASSERT_EQ(2, call->arguments()->length()); 9119 ASSERT_EQ(2, call->arguments()->length());
9176 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9120 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9177 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 9121 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9178 HValue* right = Pop(); 9122 HValue* right = Pop();
9179 HValue* left = Pop(); 9123 HValue* left = Pop();
9180 HInstruction* result = HPower::New(zone(), context(), left, right); 9124 HInstruction* result = NewUncasted<HPower>(left, right);
9181 return ast_context()->ReturnInstruction(result, call->id()); 9125 return ast_context()->ReturnInstruction(result, call->id());
9182 } 9126 }
9183 9127
9184 9128
9185 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { 9129 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) {
9186 ASSERT_EQ(1, call->arguments()->length()); 9130 ASSERT_EQ(1, call->arguments()->length());
9187 CHECK_ALIVE(VisitArgumentList(call->arguments())); 9131 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9188 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1); 9132 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1);
9189 result->set_transcendental_type(TranscendentalCache::SIN); 9133 result->set_transcendental_type(TranscendentalCache::SIN);
9190 Drop(1); 9134 Drop(1);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
9234 // Check whether two RegExps are equivalent 9178 // Check whether two RegExps are equivalent
9235 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { 9179 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
9236 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent); 9180 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent);
9237 } 9181 }
9238 9182
9239 9183
9240 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { 9184 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
9241 ASSERT(call->arguments()->length() == 1); 9185 ASSERT(call->arguments()->length() == 1);
9242 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9186 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9243 HValue* value = Pop(); 9187 HValue* value = Pop();
9244 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); 9188 HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
9245 return ast_context()->ReturnInstruction(result, call->id()); 9189 return ast_context()->ReturnInstruction(result, call->id());
9246 } 9190 }
9247 9191
9248 9192
9249 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { 9193 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
9250 return Bailout(kInlinedRuntimeFunctionFastAsciiArrayJoin); 9194 return Bailout(kInlinedRuntimeFunctionFastAsciiArrayJoin);
9251 } 9195 }
9252 9196
9253 9197
9254 // Support for generators. 9198 // Support for generators.
9255 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) { 9199 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) {
9256 return Bailout(kInlinedRuntimeFunctionGeneratorNext); 9200 return Bailout(kInlinedRuntimeFunctionGeneratorNext);
9257 } 9201 }
9258 9202
9259 9203
9260 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) { 9204 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) {
9261 return Bailout(kInlinedRuntimeFunctionGeneratorThrow); 9205 return Bailout(kInlinedRuntimeFunctionGeneratorThrow);
9262 } 9206 }
9263 9207
9264 9208
9265 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode( 9209 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
9266 CallRuntime* call) { 9210 CallRuntime* call) {
9267 AddInstruction(new(zone()) HDebugBreak()); 9211 Add<HDebugBreak>();
9268 return ast_context()->ReturnValue(graph()->GetConstant0()); 9212 return ast_context()->ReturnValue(graph()->GetConstant0());
9269 } 9213 }
9270 9214
9271 9215
9272 #undef CHECK_BAILOUT 9216 #undef CHECK_BAILOUT
9273 #undef CHECK_ALIVE 9217 #undef CHECK_ALIVE
9274 9218
9275 9219
9276 HEnvironment::HEnvironment(HEnvironment* outer, 9220 HEnvironment::HEnvironment(HEnvironment* outer,
9277 Scope* scope, 9221 Scope* scope,
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after
9875 if (ShouldProduceTraceOutput()) { 9819 if (ShouldProduceTraceOutput()) {
9876 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9820 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9877 } 9821 }
9878 9822
9879 #ifdef DEBUG 9823 #ifdef DEBUG
9880 graph_->Verify(false); // No full verify. 9824 graph_->Verify(false); // No full verify.
9881 #endif 9825 #endif
9882 } 9826 }
9883 9827
9884 } } // namespace v8::internal 9828 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-dce.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698