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

Side by Side Diff: src/hydrogen.cc

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

Powered by Google App Engine
This is Rietveld 408576698