OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 ASSERT(last_environment() != NULL); | 139 ASSERT(last_environment() != NULL); |
140 ASSERT(!last_environment()->ast_id().IsNone()); | 140 ASSERT(!last_environment()->ast_id().IsNone()); |
141 HBlockEntry* entry = new(zone()) HBlockEntry(); | 141 HBlockEntry* entry = new(zone()) HBlockEntry(); |
142 entry->InitializeAsFirst(this); | 142 entry->InitializeAsFirst(this); |
143 first_ = last_ = entry; | 143 first_ = last_ = entry; |
144 } | 144 } |
145 instr->InsertAfter(last_); | 145 instr->InsertAfter(last_); |
146 } | 146 } |
147 | 147 |
148 | 148 |
149 HDeoptimize* HBasicBlock::CreateDeoptimize( | |
150 HDeoptimize::UseEnvironment has_uses) { | |
151 ASSERT(HasEnvironment()); | |
152 if (has_uses == HDeoptimize::kNoUses) | |
153 return new(zone()) HDeoptimize(0, 0, 0, zone()); | |
154 | |
155 HEnvironment* environment = last_environment(); | |
156 int first_local_index = environment->first_local_index(); | |
157 int first_expression_index = environment->first_expression_index(); | |
158 HDeoptimize* instr = new(zone()) HDeoptimize( | |
159 environment->length(), first_local_index, first_expression_index, zone()); | |
160 for (int i = 0; i < environment->length(); i++) { | |
161 HValue* val = environment->values()->at(i); | |
162 instr->AddEnvironmentValue(val, zone()); | |
163 } | |
164 | |
165 return instr; | |
166 } | |
167 | |
168 | |
169 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, | 149 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, |
170 RemovableSimulate removable) { | 150 RemovableSimulate removable) { |
171 ASSERT(HasEnvironment()); | 151 ASSERT(HasEnvironment()); |
172 HEnvironment* environment = last_environment(); | 152 HEnvironment* environment = last_environment(); |
173 ASSERT(ast_id.IsNone() || | 153 ASSERT(ast_id.IsNone() || |
174 ast_id == BailoutId::StubEntry() || | 154 ast_id == BailoutId::StubEntry() || |
175 environment->closure()->shared()->VerifyBailoutId(ast_id)); | 155 environment->closure()->shared()->VerifyBailoutId(ast_id)); |
176 | 156 |
177 int push_count = environment->push_count(); | 157 int push_count = environment->push_count(); |
178 int pop_count = environment->pop_count(); | 158 int pop_count = environment->pop_count(); |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
693 if (constant == GetConstantHole()) return true; | 673 if (constant == GetConstantHole()) return true; |
694 if (constant == GetConstantNull()) return true; | 674 if (constant == GetConstantNull()) return true; |
695 return false; | 675 return false; |
696 } | 676 } |
697 | 677 |
698 | 678 |
699 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) | 679 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) |
700 : builder_(builder), | 680 : builder_(builder), |
701 position_(position), | 681 position_(position), |
702 finished_(false), | 682 finished_(false), |
683 deopt_then_(false), | |
684 deopt_else_(false), | |
703 did_then_(false), | 685 did_then_(false), |
704 did_else_(false), | 686 did_else_(false), |
705 did_and_(false), | 687 did_and_(false), |
706 did_or_(false), | 688 did_or_(false), |
707 captured_(false), | 689 captured_(false), |
708 needs_compare_(true), | 690 needs_compare_(true), |
709 split_edge_merge_block_(NULL) { | 691 split_edge_merge_block_(NULL), |
692 merge_block_(NULL) { | |
710 HEnvironment* env = builder->environment(); | 693 HEnvironment* env = builder->environment(); |
711 first_true_block_ = builder->CreateBasicBlock(env->Copy()); | 694 first_true_block_ = builder->CreateBasicBlock(env->Copy()); |
712 last_true_block_ = NULL; | 695 last_true_block_ = NULL; |
713 first_false_block_ = builder->CreateBasicBlock(env->Copy()); | 696 first_false_block_ = builder->CreateBasicBlock(env->Copy()); |
714 } | 697 } |
715 | 698 |
716 | 699 |
717 HGraphBuilder::IfBuilder::IfBuilder( | 700 HGraphBuilder::IfBuilder::IfBuilder( |
718 HGraphBuilder* builder, | 701 HGraphBuilder* builder, |
719 HIfContinuation* continuation) | 702 HIfContinuation* continuation) |
720 : builder_(builder), | 703 : builder_(builder), |
721 position_(RelocInfo::kNoPosition), | 704 position_(RelocInfo::kNoPosition), |
722 finished_(false), | 705 finished_(false), |
706 deopt_then_(false), | |
707 deopt_else_(false), | |
723 did_then_(false), | 708 did_then_(false), |
724 did_else_(false), | 709 did_else_(false), |
725 did_and_(false), | 710 did_and_(false), |
726 did_or_(false), | 711 did_or_(false), |
727 captured_(false), | 712 captured_(false), |
728 needs_compare_(false), | 713 needs_compare_(false), |
729 first_true_block_(NULL), | 714 first_true_block_(NULL), |
730 first_false_block_(NULL), | 715 first_false_block_(NULL), |
731 split_edge_merge_block_(NULL), | 716 split_edge_merge_block_(NULL), |
732 merge_block_(NULL) { | 717 merge_block_(NULL) { |
Jakob Kummerow
2013/07/22 16:53:12
nit: unnecessary whitespace change
danno
2013/07/23 12:18:14
Done.
| |
733 continuation->Continue(&first_true_block_, | 718 continuation->Continue(&first_true_block_, |
734 &first_false_block_, | 719 &first_false_block_, |
735 &position_); | 720 &position_); |
736 } | 721 } |
737 | 722 |
738 | 723 |
739 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { | 724 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { |
740 if (split_edge_merge_block_ != NULL) { | 725 if (split_edge_merge_block_ != NULL) { |
741 HEnvironment* env = first_false_block_->last_environment(); | 726 HEnvironment* env = first_false_block_->last_environment(); |
742 HBasicBlock* split_edge = | 727 HBasicBlock* split_edge = |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
829 ASSERT(!captured_); | 814 ASSERT(!captured_); |
830 ASSERT(!finished_); | 815 ASSERT(!finished_); |
831 last_true_block_ = builder_->current_block(); | 816 last_true_block_ = builder_->current_block(); |
832 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); | 817 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); |
833 builder_->set_current_block(first_false_block_); | 818 builder_->set_current_block(first_false_block_); |
834 did_else_ = true; | 819 did_else_ = true; |
835 } | 820 } |
836 | 821 |
837 | 822 |
838 void HGraphBuilder::IfBuilder::Deopt() { | 823 void HGraphBuilder::IfBuilder::Deopt() { |
839 HBasicBlock* block = builder_->current_block(); | 824 ASSERT(did_then_); |
840 block->FinishExitWithDeoptimization(HDeoptimize::kUseAll); | |
841 builder_->set_current_block(NULL); | |
842 if (did_else_) { | 825 if (did_else_) { |
843 first_false_block_ = NULL; | 826 deopt_else_ = true; |
844 } else { | 827 } else { |
845 first_true_block_ = NULL; | 828 deopt_then_ = true; |
846 } | 829 } |
830 builder_->Add<HDeoptimize>(Deoptimizer::EAGER); | |
847 } | 831 } |
848 | 832 |
849 | 833 |
850 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 834 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
851 HBasicBlock* block = builder_->current_block(); | 835 HBasicBlock* block = builder_->current_block(); |
852 HValue* context = builder_->environment()->LookupContext(); | 836 HValue* context = builder_->environment()->LookupContext(); |
853 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); | 837 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); |
854 block->FinishExit(new(zone()) HReturn(value, context, parameter_count)); | 838 block->FinishExit(new(zone()) HReturn(value, context, parameter_count)); |
855 builder_->set_current_block(NULL); | 839 builder_->set_current_block(NULL); |
856 if (did_else_) { | 840 if (did_else_) { |
857 first_false_block_ = NULL; | 841 first_false_block_ = NULL; |
858 } else { | 842 } else { |
859 first_true_block_ = NULL; | 843 first_true_block_ = NULL; |
860 } | 844 } |
861 } | 845 } |
862 | 846 |
863 | 847 |
864 void HGraphBuilder::IfBuilder::End() { | 848 void HGraphBuilder::IfBuilder::End() { |
865 if (!captured_) { | 849 if (!captured_) { |
866 ASSERT(did_then_); | 850 ASSERT(did_then_); |
867 if (!did_else_) { | 851 if (!did_else_) { |
868 last_true_block_ = builder_->current_block(); | 852 last_true_block_ = builder_->current_block(); |
869 } | 853 } |
870 if (first_true_block_ == NULL) { | 854 if (first_true_block_ == NULL) { |
871 // Deopt on true. Nothing to do, just continue the false block. | 855 // Deopt on true. Nothing to do, just continue the false block. |
Jakob Kummerow
2013/07/22 16:53:12
s/Deopt/Return/ ?
danno
2013/07/23 12:18:14
Done.
| |
872 } else if (first_false_block_ == NULL) { | 856 } else if (first_false_block_ == NULL) { |
873 // Deopt on false. Nothing to do except switching to the true block. | 857 // Deopt on false. Nothing to do except switching to the true block. |
874 builder_->set_current_block(last_true_block_); | 858 builder_->set_current_block(last_true_block_); |
875 } else { | 859 } else { |
876 HEnvironment* merge_env = last_true_block_->last_environment()->Copy(); | 860 HEnvironment* merge_env = last_true_block_->last_environment()->Copy(); |
877 merge_block_ = builder_->CreateBasicBlock(merge_env); | 861 merge_block_ = builder_->CreateBasicBlock(merge_env); |
878 ASSERT(!finished_); | 862 ASSERT(!finished_); |
879 if (!did_else_) Else(); | 863 if (!did_else_) Else(); |
880 ASSERT(!last_true_block_->IsFinished()); | 864 ASSERT(!last_true_block_->IsFinished()); |
881 HBasicBlock* last_false_block = builder_->current_block(); | 865 HBasicBlock* last_false_block = builder_->current_block(); |
882 ASSERT(!last_false_block->IsFinished()); | 866 ASSERT(!last_false_block->IsFinished()); |
867 if (deopt_then_) { | |
868 builder_->PadEnvironmentForContinuation(last_true_block_, | |
Jakob Kummerow
2013/07/22 16:53:12
IIUC, this call never does anything, because merge
danno
2013/07/23 12:18:14
Done.
| |
869 merge_block_); | |
870 } | |
883 last_true_block_->GotoNoSimulate(merge_block_); | 871 last_true_block_->GotoNoSimulate(merge_block_); |
872 if (deopt_else_) { | |
873 builder_->PadEnvironmentForContinuation(last_false_block, | |
874 merge_block_); | |
875 } | |
884 last_false_block->GotoNoSimulate(merge_block_); | 876 last_false_block->GotoNoSimulate(merge_block_); |
885 builder_->set_current_block(merge_block_); | 877 builder_->set_current_block(merge_block_); |
886 } | 878 } |
887 } | 879 } |
888 finished_ = true; | 880 finished_ = true; |
889 } | 881 } |
890 | 882 |
891 | 883 |
892 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, | 884 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
893 HValue* context, | 885 HValue* context, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
984 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 976 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
985 ASSERT(current_block() != NULL); | 977 ASSERT(current_block() != NULL); |
986 current_block()->AddInstruction(instr); | 978 current_block()->AddInstruction(instr); |
987 if (no_side_effects_scope_count_ > 0) { | 979 if (no_side_effects_scope_count_ > 0) { |
988 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 980 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
989 } | 981 } |
990 return instr; | 982 return instr; |
991 } | 983 } |
992 | 984 |
993 | 985 |
994 void HGraphBuilder::AddSimulate(BailoutId id, | |
995 RemovableSimulate removable) { | |
996 ASSERT(current_block() != NULL); | |
997 ASSERT(no_side_effects_scope_count_ == 0); | |
998 current_block()->AddSimulate(id, removable); | |
999 } | |
1000 | |
1001 | |
1002 HReturn* HGraphBuilder::AddReturn(HValue* value) { | |
1003 HValue* context = environment()->LookupContext(); | |
1004 int num_parameters = graph()->info()->num_parameters(); | |
1005 HValue* params = Add<HConstant>(num_parameters); | |
1006 HReturn* return_instruction = new(graph()->zone()) | |
1007 HReturn(value, context, params); | |
1008 current_block()->FinishExit(return_instruction); | |
1009 return return_instruction; | |
1010 } | |
1011 | |
1012 | |
1013 void HGraphBuilder::AddSoftDeoptimize(SoftDeoptimizeMode mode) { | |
1014 isolate()->counters()->soft_deopts_requested()->Increment(); | |
1015 if (FLAG_always_opt && mode == CAN_OMIT_SOFT_DEOPT) return; | |
1016 if (current_block()->IsDeoptimizing()) return; | |
1017 Add<HSoftDeoptimize>(); | |
1018 isolate()->counters()->soft_deopts_inserted()->Increment(); | |
1019 current_block()->MarkAsDeoptimizing(); | |
1020 graph()->set_has_soft_deoptimize(true); | |
1021 } | |
1022 | |
1023 | |
1024 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 986 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
1025 HBasicBlock* b = graph()->CreateBasicBlock(); | 987 HBasicBlock* b = graph()->CreateBasicBlock(); |
1026 b->SetInitialEnvironment(env); | 988 b->SetInitialEnvironment(env); |
1027 return b; | 989 return b; |
1028 } | 990 } |
1029 | 991 |
1030 | 992 |
1031 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 993 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
1032 HBasicBlock* header = graph()->CreateBasicBlock(); | 994 HBasicBlock* header = graph()->CreateBasicBlock(); |
1033 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 995 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
1034 header->SetInitialEnvironment(entry_env); | 996 header->SetInitialEnvironment(entry_env); |
1035 header->AttachLoopInformation(); | 997 header->AttachLoopInformation(); |
1036 return header; | 998 return header; |
1037 } | 999 } |
1038 | 1000 |
1039 | 1001 |
1040 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { | 1002 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { |
1041 if (obj->type().IsHeapObject()) return obj; | 1003 if (obj->type().IsHeapObject()) return obj; |
1042 return Add<HCheckHeapObject>(obj); | 1004 return Add<HCheckHeapObject>(obj); |
1043 } | 1005 } |
1044 | 1006 |
1045 | 1007 |
1008 void HGraphBuilder::FinishExitWithHardDeoptimization( | |
1009 HBasicBlock* continuation) { | |
1010 PadEnvironmentForContinuation(current_block(), continuation); | |
1011 Add<HDeoptimize>(Deoptimizer::EAGER); | |
1012 if (no_side_effects_scope_count_ > 0) { | |
1013 current_block()->GotoNoSimulate(continuation); | |
1014 } else { | |
1015 current_block()->Goto(continuation); | |
1016 } | |
1017 } | |
1018 | |
1019 | |
1020 void HGraphBuilder::PadEnvironmentForContinuation( | |
1021 HBasicBlock* from, | |
1022 HBasicBlock* continuation) { | |
1023 if (continuation->last_environment() != NULL) { | |
1024 // When merging from a deopt block to a continuation, resolve differences in | |
1025 // environment by pushing undefined so that the environment match during the | |
Jakob Kummerow
2013/07/22 16:53:12
nit: "the environments match"
danno
2013/07/23 12:18:14
Done.
| |
1026 // join. Popping values isn't allowed, that would kill the live ranges of | |
1027 // values that might be needed after the deopt. | |
1028 int continuation_env_length = continuation->last_environment()->length(); | |
1029 ASSERT(continuation_env_length >= from->last_environment()->length()); | |
1030 while (continuation_env_length > from->last_environment()->length()) { | |
1031 from->last_environment()->Push(graph()->GetConstantUndefined()); | |
1032 } | |
1033 } else { | |
1034 ASSERT(continuation->predecessors()->length() == 0); | |
1035 } | |
1036 } | |
1037 | |
1038 | |
1046 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, | 1039 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, |
1047 Handle<Map> map) { | 1040 Handle<Map> map) { |
Jakob Kummerow
2013/07/22 16:53:12
nit: fits on last line?
danno
2013/07/23 12:18:14
Done.
| |
1048 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); | 1041 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); |
1049 AddInstruction(check); | 1042 AddInstruction(check); |
1050 return check; | 1043 return check; |
1051 } | 1044 } |
1052 | 1045 |
1053 | 1046 |
1054 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( | 1047 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( |
1055 HValue* external_elements, | 1048 HValue* external_elements, |
1056 HValue* checked_key, | 1049 HValue* checked_key, |
1057 HValue* val, | 1050 HValue* val, |
(...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1722 | 1715 |
1723 switch (operation) { | 1716 switch (operation) { |
1724 default: | 1717 default: |
1725 UNREACHABLE(); | 1718 UNREACHABLE(); |
1726 case Token::SUB: { | 1719 case Token::SUB: { |
1727 HInstruction* instr = | 1720 HInstruction* instr = |
1728 HMul::New(zone(), environment()->LookupContext(), | 1721 HMul::New(zone(), environment()->LookupContext(), |
1729 input, graph()->GetConstantMinus1()); | 1722 input, graph()->GetConstantMinus1()); |
1730 Representation rep = Representation::FromType(type); | 1723 Representation rep = Representation::FromType(type); |
1731 if (type->Is(Type::None())) { | 1724 if (type->Is(Type::None())) { |
1732 AddSoftDeoptimize(); | 1725 Add<HDeoptimize>(); |
Jakob Kummerow
2013/07/22 16:53:12
I'm not a fan of this parameterless convenience me
danno
2013/07/23 12:18:14
Done.
| |
1733 } | 1726 } |
1734 if (instr->IsBinaryOperation()) { | 1727 if (instr->IsBinaryOperation()) { |
1735 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 1728 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
1736 binop->set_observed_input_representation(1, rep); | 1729 binop->set_observed_input_representation(1, rep); |
1737 binop->set_observed_input_representation(2, rep); | 1730 binop->set_observed_input_representation(2, rep); |
1738 } | 1731 } |
1739 return instr; | 1732 return instr; |
1740 } | 1733 } |
1741 case Token::BIT_NOT: | 1734 case Token::BIT_NOT: |
1742 if (type->Is(Type::None())) { | 1735 if (type->Is(Type::None())) { |
1743 AddSoftDeoptimize(); | 1736 Add<HDeoptimize>(); |
1744 } | 1737 } |
1745 return new(zone()) HBitNot(input); | 1738 return new(zone()) HBitNot(input); |
1746 } | 1739 } |
1747 } | 1740 } |
1748 | 1741 |
1749 | 1742 |
1750 void HGraphBuilder::BuildCompareNil( | 1743 void HGraphBuilder::BuildCompareNil( |
1751 HValue* value, | 1744 HValue* value, |
1752 Handle<Type> type, | 1745 Handle<Type> type, |
1753 int position, | 1746 int position, |
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2641 | 2634 |
2642 void TestContext::ReturnValue(HValue* value) { | 2635 void TestContext::ReturnValue(HValue* value) { |
2643 BuildBranch(value); | 2636 BuildBranch(value); |
2644 } | 2637 } |
2645 | 2638 |
2646 | 2639 |
2647 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2640 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
2648 ASSERT(!instr->IsControlInstruction()); | 2641 ASSERT(!instr->IsControlInstruction()); |
2649 owner()->AddInstruction(instr); | 2642 owner()->AddInstruction(instr); |
2650 if (instr->HasObservableSideEffects()) { | 2643 if (instr->HasObservableSideEffects()) { |
2651 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2644 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
2652 } | 2645 } |
2653 } | 2646 } |
2654 | 2647 |
2655 | 2648 |
2656 void EffectContext::ReturnControl(HControlInstruction* instr, | 2649 void EffectContext::ReturnControl(HControlInstruction* instr, |
2657 BailoutId ast_id) { | 2650 BailoutId ast_id) { |
2658 ASSERT(!instr->HasObservableSideEffects()); | 2651 ASSERT(!instr->HasObservableSideEffects()); |
2659 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2652 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
2660 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2653 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
2661 instr->SetSuccessorAt(0, empty_true); | 2654 instr->SetSuccessorAt(0, empty_true); |
(...skipping 21 matching lines...) Expand all Loading... | |
2683 | 2676 |
2684 | 2677 |
2685 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2678 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
2686 ASSERT(!instr->IsControlInstruction()); | 2679 ASSERT(!instr->IsControlInstruction()); |
2687 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2680 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
2688 return owner()->Bailout("bad value context for arguments object value"); | 2681 return owner()->Bailout("bad value context for arguments object value"); |
2689 } | 2682 } |
2690 owner()->AddInstruction(instr); | 2683 owner()->AddInstruction(instr); |
2691 owner()->Push(instr); | 2684 owner()->Push(instr); |
2692 if (instr->HasObservableSideEffects()) { | 2685 if (instr->HasObservableSideEffects()) { |
2693 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2686 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
2694 } | 2687 } |
2695 } | 2688 } |
2696 | 2689 |
2697 | 2690 |
2698 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2691 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
2699 ASSERT(!instr->HasObservableSideEffects()); | 2692 ASSERT(!instr->HasObservableSideEffects()); |
2700 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2693 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
2701 return owner()->Bailout("bad value context for arguments object value"); | 2694 return owner()->Bailout("bad value context for arguments object value"); |
2702 } | 2695 } |
2703 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | 2696 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2739 | 2732 |
2740 | 2733 |
2741 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2734 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
2742 ASSERT(!instr->IsControlInstruction()); | 2735 ASSERT(!instr->IsControlInstruction()); |
2743 HOptimizedGraphBuilder* builder = owner(); | 2736 HOptimizedGraphBuilder* builder = owner(); |
2744 builder->AddInstruction(instr); | 2737 builder->AddInstruction(instr); |
2745 // We expect a simulate after every expression with side effects, though | 2738 // We expect a simulate after every expression with side effects, though |
2746 // this one isn't actually needed (and wouldn't work if it were targeted). | 2739 // this one isn't actually needed (and wouldn't work if it were targeted). |
2747 if (instr->HasObservableSideEffects()) { | 2740 if (instr->HasObservableSideEffects()) { |
2748 builder->Push(instr); | 2741 builder->Push(instr); |
2749 builder->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2742 builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
2750 builder->Pop(); | 2743 builder->Pop(); |
2751 } | 2744 } |
2752 BuildBranch(instr); | 2745 BuildBranch(instr); |
2753 } | 2746 } |
2754 | 2747 |
2755 | 2748 |
2756 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2749 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
2757 ASSERT(!instr->HasObservableSideEffects()); | 2750 ASSERT(!instr->HasObservableSideEffects()); |
2758 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2751 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
2759 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2752 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2927 current_block()->Goto(body_entry); | 2920 current_block()->Goto(body_entry); |
2928 body_entry->SetJoinId(BailoutId::FunctionEntry()); | 2921 body_entry->SetJoinId(BailoutId::FunctionEntry()); |
2929 set_current_block(body_entry); | 2922 set_current_block(body_entry); |
2930 | 2923 |
2931 // Handle implicit declaration of the function name in named function | 2924 // Handle implicit declaration of the function name in named function |
2932 // expressions before other declarations. | 2925 // expressions before other declarations. |
2933 if (scope->is_function_scope() && scope->function() != NULL) { | 2926 if (scope->is_function_scope() && scope->function() != NULL) { |
2934 VisitVariableDeclaration(scope->function()); | 2927 VisitVariableDeclaration(scope->function()); |
2935 } | 2928 } |
2936 VisitDeclarations(scope->declarations()); | 2929 VisitDeclarations(scope->declarations()); |
2937 AddSimulate(BailoutId::Declarations()); | 2930 Add<HSimulate>(BailoutId::Declarations()); |
2938 | 2931 |
2939 HValue* context = environment()->LookupContext(); | 2932 HValue* context = environment()->LookupContext(); |
2940 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); | 2933 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); |
2941 | 2934 |
2942 VisitStatements(current_info()->function()->body()); | 2935 VisitStatements(current_info()->function()->body()); |
2943 if (HasStackOverflow()) return false; | 2936 if (HasStackOverflow()) return false; |
2944 | 2937 |
2945 if (current_block() != NULL) { | 2938 if (current_block() != NULL) { |
2946 AddReturn(graph()->GetConstantUndefined()); | 2939 Add<HReturn>(graph()->GetConstantUndefined()); |
2947 set_current_block(NULL); | 2940 set_current_block(NULL); |
2948 } | 2941 } |
2949 | 2942 |
2950 // If the checksum of the number of type info changes is the same as the | 2943 // If the checksum of the number of type info changes is the same as the |
2951 // last time this function was compiled, then this recompile is likely not | 2944 // last time this function was compiled, then this recompile is likely not |
2952 // due to missing/inadequate type feedback, but rather too aggressive | 2945 // due to missing/inadequate type feedback, but rather too aggressive |
2953 // optimization. Disable optimistic LICM in that case. | 2946 // optimization. Disable optimistic LICM in that case. |
2954 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); | 2947 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); |
2955 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 2948 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
2956 Handle<TypeFeedbackInfo> type_info( | 2949 Handle<TypeFeedbackInfo> type_info( |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3226 ASSERT(current_block() != NULL); | 3219 ASSERT(current_block() != NULL); |
3227 ASSERT(current_block()->HasPredecessor()); | 3220 ASSERT(current_block()->HasPredecessor()); |
3228 } | 3221 } |
3229 | 3222 |
3230 | 3223 |
3231 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 3224 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
3232 ASSERT(!HasStackOverflow()); | 3225 ASSERT(!HasStackOverflow()); |
3233 ASSERT(current_block() != NULL); | 3226 ASSERT(current_block() != NULL); |
3234 ASSERT(current_block()->HasPredecessor()); | 3227 ASSERT(current_block()->HasPredecessor()); |
3235 if (stmt->condition()->ToBooleanIsTrue()) { | 3228 if (stmt->condition()->ToBooleanIsTrue()) { |
3236 AddSimulate(stmt->ThenId()); | 3229 Add<HSimulate>(stmt->ThenId()); |
3237 Visit(stmt->then_statement()); | 3230 Visit(stmt->then_statement()); |
3238 } else if (stmt->condition()->ToBooleanIsFalse()) { | 3231 } else if (stmt->condition()->ToBooleanIsFalse()) { |
3239 AddSimulate(stmt->ElseId()); | 3232 Add<HSimulate>(stmt->ElseId()); |
3240 Visit(stmt->else_statement()); | 3233 Visit(stmt->else_statement()); |
3241 } else { | 3234 } else { |
3242 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 3235 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
3243 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 3236 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
3244 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); | 3237 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); |
3245 | 3238 |
3246 if (cond_true->HasPredecessor()) { | 3239 if (cond_true->HasPredecessor()) { |
3247 cond_true->SetJoinId(stmt->ThenId()); | 3240 cond_true->SetJoinId(stmt->ThenId()); |
3248 set_current_block(cond_true); | 3241 set_current_block(cond_true); |
3249 CHECK_BAILOUT(Visit(stmt->then_statement())); | 3242 CHECK_BAILOUT(Visit(stmt->then_statement())); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3336 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 3329 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
3337 ASSERT(!HasStackOverflow()); | 3330 ASSERT(!HasStackOverflow()); |
3338 ASSERT(current_block() != NULL); | 3331 ASSERT(current_block() != NULL); |
3339 ASSERT(current_block()->HasPredecessor()); | 3332 ASSERT(current_block()->HasPredecessor()); |
3340 FunctionState* state = function_state(); | 3333 FunctionState* state = function_state(); |
3341 AstContext* context = call_context(); | 3334 AstContext* context = call_context(); |
3342 if (context == NULL) { | 3335 if (context == NULL) { |
3343 // Not an inlined return, so an actual one. | 3336 // Not an inlined return, so an actual one. |
3344 CHECK_ALIVE(VisitForValue(stmt->expression())); | 3337 CHECK_ALIVE(VisitForValue(stmt->expression())); |
3345 HValue* result = environment()->Pop(); | 3338 HValue* result = environment()->Pop(); |
3346 AddReturn(result); | 3339 Add<HReturn>(result); |
3347 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 3340 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
3348 // Return from an inlined construct call. In a test context the return value | 3341 // Return from an inlined construct call. In a test context the return value |
3349 // will always evaluate to true, in a value context the return value needs | 3342 // will always evaluate to true, in a value context the return value needs |
3350 // to be a JSObject. | 3343 // to be a JSObject. |
3351 if (context->IsTest()) { | 3344 if (context->IsTest()) { |
3352 TestContext* test = TestContext::cast(context); | 3345 TestContext* test = TestContext::cast(context); |
3353 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3346 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
3354 current_block()->Goto(test->if_true(), state); | 3347 current_block()->Goto(test->if_true(), state); |
3355 } else if (context->IsEffect()) { | 3348 } else if (context->IsEffect()) { |
3356 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3349 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3428 } | 3421 } |
3429 | 3422 |
3430 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); | 3423 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); |
3431 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { | 3424 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { |
3432 return Bailout("SwitchStatement: mixed or non-literal switch labels"); | 3425 return Bailout("SwitchStatement: mixed or non-literal switch labels"); |
3433 } | 3426 } |
3434 | 3427 |
3435 HValue* context = environment()->LookupContext(); | 3428 HValue* context = environment()->LookupContext(); |
3436 | 3429 |
3437 CHECK_ALIVE(VisitForValue(stmt->tag())); | 3430 CHECK_ALIVE(VisitForValue(stmt->tag())); |
3438 AddSimulate(stmt->EntryId()); | 3431 Add<HSimulate>(stmt->EntryId()); |
3439 HValue* tag_value = Pop(); | 3432 HValue* tag_value = Pop(); |
3440 HBasicBlock* first_test_block = current_block(); | 3433 HBasicBlock* first_test_block = current_block(); |
3441 | 3434 |
3442 HUnaryControlInstruction* string_check = NULL; | 3435 HUnaryControlInstruction* string_check = NULL; |
3443 HBasicBlock* not_string_block = NULL; | 3436 HBasicBlock* not_string_block = NULL; |
3444 | 3437 |
3445 // Test switch's tag value if all clauses are string literals | 3438 // Test switch's tag value if all clauses are string literals |
3446 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { | 3439 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { |
3447 string_check = new(zone()) HIsStringAndBranch(tag_value); | 3440 string_check = new(zone()) HIsStringAndBranch(tag_value); |
3448 first_test_block = graph()->CreateBasicBlock(); | 3441 first_test_block = graph()->CreateBasicBlock(); |
(...skipping 19 matching lines...) Expand all Loading... | |
3468 CHECK_ALIVE(VisitForValue(clause->label())); | 3461 CHECK_ALIVE(VisitForValue(clause->label())); |
3469 HValue* label_value = Pop(); | 3462 HValue* label_value = Pop(); |
3470 | 3463 |
3471 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 3464 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
3472 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 3465 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
3473 | 3466 |
3474 HControlInstruction* compare; | 3467 HControlInstruction* compare; |
3475 | 3468 |
3476 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { | 3469 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { |
3477 if (!clause->compare_type()->Is(Type::Smi())) { | 3470 if (!clause->compare_type()->Is(Type::Smi())) { |
3478 AddSoftDeoptimize(); | 3471 Add<HDeoptimize>(); |
3479 } | 3472 } |
3480 | 3473 |
3481 HCompareNumericAndBranch* compare_ = | 3474 HCompareNumericAndBranch* compare_ = |
3482 new(zone()) HCompareNumericAndBranch(tag_value, | 3475 new(zone()) HCompareNumericAndBranch(tag_value, |
3483 label_value, | 3476 label_value, |
3484 Token::EQ_STRICT); | 3477 Token::EQ_STRICT); |
3485 compare_->set_observed_input_representation( | 3478 compare_->set_observed_input_representation( |
3486 Representation::Smi(), Representation::Smi()); | 3479 Representation::Smi(), Representation::Smi()); |
3487 compare = compare_; | 3480 compare = compare_; |
3488 } else { | 3481 } else { |
(...skipping 29 matching lines...) Expand all Loading... | |
3518 CaseClause* clause = clauses->at(i); | 3511 CaseClause* clause = clauses->at(i); |
3519 | 3512 |
3520 // Identify the block where normal (non-fall-through) control flow | 3513 // Identify the block where normal (non-fall-through) control flow |
3521 // goes to. | 3514 // goes to. |
3522 HBasicBlock* normal_block = NULL; | 3515 HBasicBlock* normal_block = NULL; |
3523 if (clause->is_default()) { | 3516 if (clause->is_default()) { |
3524 if (last_block != NULL) { | 3517 if (last_block != NULL) { |
3525 normal_block = last_block; | 3518 normal_block = last_block; |
3526 last_block = NULL; // Cleared to indicate we've handled it. | 3519 last_block = NULL; // Cleared to indicate we've handled it. |
3527 } | 3520 } |
3528 } else if (!curr_test_block->end()->IsDeoptimize()) { | 3521 } else { |
3529 normal_block = curr_test_block->end()->FirstSuccessor(); | 3522 normal_block = curr_test_block->end()->FirstSuccessor(); |
3530 curr_test_block = curr_test_block->end()->SecondSuccessor(); | 3523 curr_test_block = curr_test_block->end()->SecondSuccessor(); |
3531 } | 3524 } |
3532 | 3525 |
3533 // Identify a block to emit the body into. | 3526 // Identify a block to emit the body into. |
3534 if (normal_block == NULL) { | 3527 if (normal_block == NULL) { |
3535 if (fall_through_block == NULL) { | 3528 if (fall_through_block == NULL) { |
3536 // (a) Unreachable. | 3529 // (a) Unreachable. |
3537 if (clause->is_default()) { | 3530 if (clause->is_default()) { |
3538 continue; // Might still be reachable clause bodies. | 3531 continue; // Might still be reachable clause bodies. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3572 break_block->SetJoinId(stmt->ExitId()); | 3565 break_block->SetJoinId(stmt->ExitId()); |
3573 set_current_block(break_block); | 3566 set_current_block(break_block); |
3574 } | 3567 } |
3575 } | 3568 } |
3576 | 3569 |
3577 | 3570 |
3578 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 3571 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
3579 HBasicBlock* loop_entry, | 3572 HBasicBlock* loop_entry, |
3580 BreakAndContinueInfo* break_info) { | 3573 BreakAndContinueInfo* break_info) { |
3581 BreakAndContinueScope push(break_info, this); | 3574 BreakAndContinueScope push(break_info, this); |
3582 AddSimulate(stmt->StackCheckId()); | 3575 Add<HSimulate>(stmt->StackCheckId()); |
3583 HValue* context = environment()->LookupContext(); | 3576 HValue* context = environment()->LookupContext(); |
3584 HStackCheck* stack_check = Add<HStackCheck>( | 3577 HStackCheck* stack_check = Add<HStackCheck>( |
3585 context, HStackCheck::kBackwardsBranch); | 3578 context, HStackCheck::kBackwardsBranch); |
3586 ASSERT(loop_entry->IsLoopHeader()); | 3579 ASSERT(loop_entry->IsLoopHeader()); |
3587 loop_entry->loop_information()->set_stack_check(stack_check); | 3580 loop_entry->loop_information()->set_stack_check(stack_check); |
3588 CHECK_BAILOUT(Visit(stmt->body())); | 3581 CHECK_BAILOUT(Visit(stmt->body())); |
3589 } | 3582 } |
3590 | 3583 |
3591 | 3584 |
3592 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 3585 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3733 return Bailout("ForInStatement with non-local each variable"); | 3726 return Bailout("ForInStatement with non-local each variable"); |
3734 } | 3727 } |
3735 | 3728 |
3736 Variable* each_var = stmt->each()->AsVariableProxy()->var(); | 3729 Variable* each_var = stmt->each()->AsVariableProxy()->var(); |
3737 | 3730 |
3738 CHECK_ALIVE(VisitForValue(stmt->enumerable())); | 3731 CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
3739 HValue* enumerable = Top(); // Leave enumerable at the top. | 3732 HValue* enumerable = Top(); // Leave enumerable at the top. |
3740 | 3733 |
3741 HInstruction* map = Add<HForInPrepareMap>( | 3734 HInstruction* map = Add<HForInPrepareMap>( |
3742 environment()->LookupContext(), enumerable); | 3735 environment()->LookupContext(), enumerable); |
3743 AddSimulate(stmt->PrepareId()); | 3736 Add<HSimulate>(stmt->PrepareId()); |
3744 | 3737 |
3745 HInstruction* array = Add<HForInCacheArray>( | 3738 HInstruction* array = Add<HForInCacheArray>( |
3746 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); | 3739 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); |
3747 | 3740 |
3748 HInstruction* enum_length = Add<HMapEnumLength>(map); | 3741 HInstruction* enum_length = Add<HMapEnumLength>(map); |
3749 | 3742 |
3750 HInstruction* start_index = Add<HConstant>(0); | 3743 HInstruction* start_index = Add<HConstant>(0); |
3751 | 3744 |
3752 Push(map); | 3745 Push(map); |
3753 Push(array); | 3746 Push(array); |
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4330 Handle<JSObject> holder; | 4323 Handle<JSObject> holder; |
4331 ASSERT(!LookupSetter(map, name, &setter, &holder)); | 4324 ASSERT(!LookupSetter(map, name, &setter, &holder)); |
4332 #endif | 4325 #endif |
4333 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, | 4326 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, |
4334 name, | 4327 name, |
4335 value, | 4328 value, |
4336 map)); | 4329 map)); |
4337 } | 4330 } |
4338 AddInstruction(store); | 4331 AddInstruction(store); |
4339 if (store->HasObservableSideEffects()) { | 4332 if (store->HasObservableSideEffects()) { |
4340 AddSimulate(key->id(), REMOVABLE_SIMULATE); | 4333 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
4341 } | 4334 } |
4342 } else { | 4335 } else { |
4343 CHECK_ALIVE(VisitForEffect(value)); | 4336 CHECK_ALIVE(VisitForEffect(value)); |
4344 } | 4337 } |
4345 break; | 4338 break; |
4346 } | 4339 } |
4347 // Fall through. | 4340 // Fall through. |
4348 case ObjectLiteral::Property::PROTOTYPE: | 4341 case ObjectLiteral::Property::PROTOTYPE: |
4349 case ObjectLiteral::Property::SETTER: | 4342 case ObjectLiteral::Property::SETTER: |
4350 case ObjectLiteral::Property::GETTER: | 4343 case ObjectLiteral::Property::GETTER: |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4495 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, | 4488 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, |
4496 boilerplate_elements_kind); | 4489 boilerplate_elements_kind); |
4497 instr->SetUninitialized(uninitialized); | 4490 instr->SetUninitialized(uninitialized); |
4498 break; | 4491 break; |
4499 } | 4492 } |
4500 default: | 4493 default: |
4501 UNREACHABLE(); | 4494 UNREACHABLE(); |
4502 break; | 4495 break; |
4503 } | 4496 } |
4504 | 4497 |
4505 AddSimulate(expr->GetIdForElement(i)); | 4498 Add<HSimulate>(expr->GetIdForElement(i)); |
4506 } | 4499 } |
4507 | 4500 |
4508 Drop(1); // array literal index | 4501 Drop(1); // array literal index |
4509 return ast_context()->ReturnValue(Pop()); | 4502 return ast_context()->ReturnValue(Pop()); |
4510 } | 4503 } |
4511 | 4504 |
4512 | 4505 |
4513 // Sets the lookup result and returns true if the load/store can be inlined. | 4506 // Sets the lookup result and returns true if the load/store can be inlined. |
4514 static bool ComputeLoadStoreField(Handle<Map> type, | 4507 static bool ComputeLoadStoreField(Handle<Map> type, |
4515 Handle<String> name, | 4508 Handle<String> name, |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4826 AddInstruction(HCheckMaps::New(object, types, zone())); | 4819 AddInstruction(HCheckMaps::New(object, types, zone())); |
4827 HInstruction* store; | 4820 HInstruction* store; |
4828 CHECK_ALIVE_OR_RETURN( | 4821 CHECK_ALIVE_OR_RETURN( |
4829 store = BuildStoreNamedField( | 4822 store = BuildStoreNamedField( |
4830 object, name, store_value, types->at(count - 1), &lookup), | 4823 object, name, store_value, types->at(count - 1), &lookup), |
4831 true); | 4824 true); |
4832 if (result_value != NULL) Push(result_value); | 4825 if (result_value != NULL) Push(result_value); |
4833 Push(store_value); | 4826 Push(store_value); |
4834 store->set_position(position); | 4827 store->set_position(position); |
4835 AddInstruction(store); | 4828 AddInstruction(store); |
4836 AddSimulate(assignment_id); | 4829 Add<HSimulate>(assignment_id); |
4837 if (result_value != NULL) Drop(1); | 4830 if (result_value != NULL) Drop(1); |
4838 ast_context()->ReturnValue(Pop()); | 4831 ast_context()->ReturnValue(Pop()); |
4839 return true; | 4832 return true; |
4840 } | 4833 } |
4841 | 4834 |
4842 | 4835 |
4843 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 4836 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
4844 BailoutId id, | 4837 BailoutId id, |
4845 int position, | 4838 int position, |
4846 BailoutId assignment_id, | 4839 BailoutId assignment_id, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4889 current_block()->Goto(join); | 4882 current_block()->Goto(join); |
4890 | 4883 |
4891 set_current_block(if_false); | 4884 set_current_block(if_false); |
4892 } | 4885 } |
4893 } | 4886 } |
4894 | 4887 |
4895 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 4888 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
4896 // know about and do not want to handle ones we've never seen. Otherwise | 4889 // know about and do not want to handle ones we've never seen. Otherwise |
4897 // use a generic IC. | 4890 // use a generic IC. |
4898 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 4891 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
4899 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 4892 FinishExitWithHardDeoptimization(join); |
4900 } else { | 4893 } else { |
4901 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); | 4894 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); |
4902 instr->set_position(position); | 4895 instr->set_position(position); |
4903 AddInstruction(instr); | 4896 AddInstruction(instr); |
4904 | 4897 |
4905 if (join != NULL) { | 4898 if (join != NULL) { |
4906 if (!ast_context()->IsEffect()) { | 4899 if (!ast_context()->IsEffect()) { |
4907 if (result_value != NULL) Push(result_value); | 4900 if (result_value != NULL) Push(result_value); |
4908 Push(store_value); | 4901 Push(store_value); |
4909 } | 4902 } |
4910 current_block()->Goto(join); | 4903 current_block()->Goto(join); |
4911 } else { | 4904 } else { |
4912 // The HSimulate for the store should not see the stored value in | 4905 // The HSimulate for the store should not see the stored value in |
4913 // effect contexts (it is not materialized at expr->id() in the | 4906 // effect contexts (it is not materialized at expr->id() in the |
4914 // unoptimized code). | 4907 // unoptimized code). |
4915 if (instr->HasObservableSideEffects()) { | 4908 if (instr->HasObservableSideEffects()) { |
4916 if (ast_context()->IsEffect()) { | 4909 if (ast_context()->IsEffect()) { |
4917 AddSimulate(id, REMOVABLE_SIMULATE); | 4910 Add<HSimulate>(id, REMOVABLE_SIMULATE); |
4918 } else { | 4911 } else { |
4919 if (result_value != NULL) Push(result_value); | 4912 if (result_value != NULL) Push(result_value); |
4920 Push(store_value); | 4913 Push(store_value); |
4921 AddSimulate(id, REMOVABLE_SIMULATE); | 4914 Add<HSimulate>(id, REMOVABLE_SIMULATE); |
4922 Drop(result_value != NULL ? 2 : 1); | 4915 Drop(result_value != NULL ? 2 : 1); |
4923 } | 4916 } |
4924 } | 4917 } |
4925 return ast_context()->ReturnValue( | 4918 return ast_context()->ReturnValue( |
4926 result_value != NULL ? result_value : store_value); | 4919 result_value != NULL ? result_value : store_value); |
4927 } | 4920 } |
4928 } | 4921 } |
4929 | 4922 |
4930 ASSERT(join != NULL); | 4923 ASSERT(join != NULL); |
4931 join->SetJoinId(id); | 4924 join->SetJoinId(id); |
4932 set_current_block(join); | 4925 set_current_block(join); |
4933 if (!ast_context()->IsEffect()) { | 4926 if (!ast_context()->IsEffect()) { |
4934 if (result_value != NULL) Drop(1); | 4927 if (result_value != NULL) Drop(1); |
4935 ast_context()->ReturnValue(Pop()); | 4928 ast_context()->ReturnValue(Pop()); |
4936 } | 4929 } |
4937 } | 4930 } |
4938 | 4931 |
4939 | 4932 |
4940 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 4933 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
4941 Property* prop = expr->target()->AsProperty(); | 4934 Property* prop = expr->target()->AsProperty(); |
4942 ASSERT(prop != NULL); | 4935 ASSERT(prop != NULL); |
4943 CHECK_ALIVE(VisitForValue(prop->obj())); | 4936 CHECK_ALIVE(VisitForValue(prop->obj())); |
4944 | 4937 |
4945 if (prop->key()->IsPropertyName()) { | 4938 if (prop->key()->IsPropertyName()) { |
4946 // Named store. | 4939 // Named store. |
4947 CHECK_ALIVE(VisitForValue(expr->value())); | 4940 CHECK_ALIVE(VisitForValue(expr->value())); |
4948 HValue* value = environment()->ExpressionStackAt(0); | 4941 HValue* value = environment()->ExpressionStackAt(0); |
4949 HValue* object = environment()->ExpressionStackAt(1); | 4942 HValue* object = environment()->ExpressionStackAt(1); |
4950 | 4943 |
4951 if (expr->IsUninitialized()) AddSoftDeoptimize(); | 4944 if (expr->IsUninitialized()) Add<HDeoptimize>(); |
4952 return BuildStoreNamed(expr, expr->id(), expr->position(), | 4945 return BuildStoreNamed(expr, expr->id(), expr->position(), |
4953 expr->AssignmentId(), prop, object, value); | 4946 expr->AssignmentId(), prop, object, value); |
4954 } else { | 4947 } else { |
4955 // Keyed store. | 4948 // Keyed store. |
4956 CHECK_ALIVE(VisitForValue(prop->key())); | 4949 CHECK_ALIVE(VisitForValue(prop->key())); |
4957 CHECK_ALIVE(VisitForValue(expr->value())); | 4950 CHECK_ALIVE(VisitForValue(expr->value())); |
4958 HValue* value = environment()->ExpressionStackAt(0); | 4951 HValue* value = environment()->ExpressionStackAt(0); |
4959 HValue* key = environment()->ExpressionStackAt(1); | 4952 HValue* key = environment()->ExpressionStackAt(1); |
4960 HValue* object = environment()->ExpressionStackAt(2); | 4953 HValue* object = environment()->ExpressionStackAt(2); |
4961 bool has_side_effects = false; | 4954 bool has_side_effects = false; |
4962 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 4955 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
4963 expr->position(), | 4956 expr->position(), |
4964 true, // is_store | 4957 true, // is_store |
4965 &has_side_effects); | 4958 &has_side_effects); |
4966 Drop(3); | 4959 Drop(3); |
4967 Push(value); | 4960 Push(value); |
4968 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 4961 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
4969 return ast_context()->ReturnValue(Pop()); | 4962 return ast_context()->ReturnValue(Pop()); |
4970 } | 4963 } |
4971 } | 4964 } |
4972 | 4965 |
4973 | 4966 |
4974 // Because not every expression has a position and there is not common | 4967 // Because not every expression has a position and there is not common |
4975 // superclass of Assignment and CountOperation, we cannot just pass the | 4968 // superclass of Assignment and CountOperation, we cannot just pass the |
4976 // owning expression instead of position and ast_id separately. | 4969 // owning expression instead of position and ast_id separately. |
4977 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 4970 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
4978 Variable* var, | 4971 Variable* var, |
4979 HValue* value, | 4972 HValue* value, |
4980 int position, | 4973 int position, |
4981 BailoutId ast_id) { | 4974 BailoutId ast_id) { |
4982 LookupResult lookup(isolate()); | 4975 LookupResult lookup(isolate()); |
4983 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 4976 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
4984 if (type == kUseCell) { | 4977 if (type == kUseCell) { |
4985 Handle<GlobalObject> global(current_info()->global_object()); | 4978 Handle<GlobalObject> global(current_info()->global_object()); |
4986 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 4979 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
4987 if (cell->type()->IsConstant()) { | 4980 if (cell->type()->IsConstant()) { |
4988 IfBuilder builder(this); | 4981 IfBuilder builder(this); |
4989 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); | 4982 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); |
4990 if (cell->type()->AsConstant()->IsNumber()) { | 4983 if (cell->type()->AsConstant()->IsNumber()) { |
4991 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); | 4984 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); |
4992 } else { | 4985 } else { |
4993 builder.If<HCompareObjectEqAndBranch>(value, constant); | 4986 builder.If<HCompareObjectEqAndBranch>(value, constant); |
4994 } | 4987 } |
4995 builder.Then(); | 4988 builder.Then(); |
4996 builder.Else(); | 4989 builder.Else(); |
4997 AddSoftDeoptimize(MUST_EMIT_SOFT_DEOPT); | 4990 Add<HDeoptimize>(Deoptimizer::EAGER); |
4998 builder.End(); | 4991 builder.End(); |
4999 } | 4992 } |
5000 HInstruction* instr = | 4993 HInstruction* instr = |
5001 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | 4994 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
5002 instr->set_position(position); | 4995 instr->set_position(position); |
5003 if (instr->HasObservableSideEffects()) { | 4996 if (instr->HasObservableSideEffects()) { |
5004 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 4997 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
5005 } | 4998 } |
5006 } else { | 4999 } else { |
5007 HValue* context = environment()->LookupContext(); | 5000 HValue* context = environment()->LookupContext(); |
5008 HGlobalObject* global_object = Add<HGlobalObject>(context); | 5001 HGlobalObject* global_object = Add<HGlobalObject>(context); |
5009 HStoreGlobalGeneric* instr = | 5002 HStoreGlobalGeneric* instr = |
5010 Add<HStoreGlobalGeneric>(context, global_object, var->name(), | 5003 Add<HStoreGlobalGeneric>(context, global_object, var->name(), |
5011 value, function_strict_mode_flag()); | 5004 value, function_strict_mode_flag()); |
5012 instr->set_position(position); | 5005 instr->set_position(position); |
5013 ASSERT(instr->HasObservableSideEffects()); | 5006 ASSERT(instr->HasObservableSideEffects()); |
5014 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 5007 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
5015 } | 5008 } |
5016 } | 5009 } |
5017 | 5010 |
5018 | 5011 |
5019 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, | 5012 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, |
5020 BailoutId id, | 5013 BailoutId id, |
5021 int position, | 5014 int position, |
5022 BailoutId assignment_id, | 5015 BailoutId assignment_id, |
5023 Property* prop, | 5016 Property* prop, |
5024 HValue* object, | 5017 HValue* object, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5067 } else { | 5060 } else { |
5068 Drop(2); | 5061 Drop(2); |
5069 instr = BuildStoreNamedGeneric(object, name, store_value); | 5062 instr = BuildStoreNamedGeneric(object, name, store_value); |
5070 } | 5063 } |
5071 | 5064 |
5072 if (result_value != NULL) Push(result_value); | 5065 if (result_value != NULL) Push(result_value); |
5073 Push(store_value); | 5066 Push(store_value); |
5074 instr->set_position(position); | 5067 instr->set_position(position); |
5075 AddInstruction(instr); | 5068 AddInstruction(instr); |
5076 if (instr->HasObservableSideEffects()) { | 5069 if (instr->HasObservableSideEffects()) { |
5077 AddSimulate(assignment_id, REMOVABLE_SIMULATE); | 5070 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
5078 } | 5071 } |
5079 if (result_value != NULL) Drop(1); | 5072 if (result_value != NULL) Drop(1); |
5080 return ast_context()->ReturnValue(Pop()); | 5073 return ast_context()->ReturnValue(Pop()); |
5081 } | 5074 } |
5082 | 5075 |
5083 | 5076 |
5084 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5077 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
5085 Expression* target = expr->target(); | 5078 Expression* target = expr->target(); |
5086 VariableProxy* proxy = target->AsVariableProxy(); | 5079 VariableProxy* proxy = target->AsVariableProxy(); |
5087 Property* prop = target->AsProperty(); | 5080 Property* prop = target->AsProperty(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5145 // perform checks here | 5138 // perform checks here |
5146 UNREACHABLE(); | 5139 UNREACHABLE(); |
5147 default: | 5140 default: |
5148 mode = HStoreContextSlot::kNoCheck; | 5141 mode = HStoreContextSlot::kNoCheck; |
5149 } | 5142 } |
5150 | 5143 |
5151 HValue* context = BuildContextChainWalk(var); | 5144 HValue* context = BuildContextChainWalk(var); |
5152 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5145 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
5153 mode, Top()); | 5146 mode, Top()); |
5154 if (instr->HasObservableSideEffects()) { | 5147 if (instr->HasObservableSideEffects()) { |
5155 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5148 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5156 } | 5149 } |
5157 break; | 5150 break; |
5158 } | 5151 } |
5159 | 5152 |
5160 case Variable::LOOKUP: | 5153 case Variable::LOOKUP: |
5161 return Bailout("compound assignment to lookup slot"); | 5154 return Bailout("compound assignment to lookup slot"); |
5162 } | 5155 } |
5163 return ast_context()->ReturnValue(Pop()); | 5156 return ast_context()->ReturnValue(Pop()); |
5164 | 5157 |
5165 } else if (prop != NULL) { | 5158 } else if (prop != NULL) { |
(...skipping 20 matching lines...) Expand all Loading... | |
5186 load = BuildCallGetter(object, map, getter, holder); | 5179 load = BuildCallGetter(object, map, getter, holder); |
5187 } else { | 5180 } else { |
5188 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 5181 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
5189 } | 5182 } |
5190 } else if (types != NULL && types->length() > 1) { | 5183 } else if (types != NULL && types->length() > 1) { |
5191 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); | 5184 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
5192 } | 5185 } |
5193 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); | 5186 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
5194 PushAndAdd(load); | 5187 PushAndAdd(load); |
5195 if (load->HasObservableSideEffects()) { | 5188 if (load->HasObservableSideEffects()) { |
5196 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 5189 Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
5197 } | 5190 } |
5198 | 5191 |
5199 CHECK_ALIVE(VisitForValue(expr->value())); | 5192 CHECK_ALIVE(VisitForValue(expr->value())); |
5200 HValue* right = Pop(); | 5193 HValue* right = Pop(); |
5201 HValue* left = Pop(); | 5194 HValue* left = Pop(); |
5202 | 5195 |
5203 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5196 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
5204 PushAndAdd(instr); | 5197 PushAndAdd(instr); |
5205 if (instr->HasObservableSideEffects()) { | 5198 if (instr->HasObservableSideEffects()) { |
5206 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 5199 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
5207 } | 5200 } |
5208 | 5201 |
5209 return BuildStoreNamed(prop, expr->id(), expr->position(), | 5202 return BuildStoreNamed(prop, expr->id(), expr->position(), |
5210 expr->AssignmentId(), prop, object, instr); | 5203 expr->AssignmentId(), prop, object, instr); |
5211 } else { | 5204 } else { |
5212 // Keyed property. | 5205 // Keyed property. |
5213 CHECK_ALIVE(VisitForValue(prop->obj())); | 5206 CHECK_ALIVE(VisitForValue(prop->obj())); |
5214 CHECK_ALIVE(VisitForValue(prop->key())); | 5207 CHECK_ALIVE(VisitForValue(prop->key())); |
5215 HValue* obj = environment()->ExpressionStackAt(1); | 5208 HValue* obj = environment()->ExpressionStackAt(1); |
5216 HValue* key = environment()->ExpressionStackAt(0); | 5209 HValue* key = environment()->ExpressionStackAt(0); |
5217 | 5210 |
5218 bool has_side_effects = false; | 5211 bool has_side_effects = false; |
5219 HValue* load = HandleKeyedElementAccess( | 5212 HValue* load = HandleKeyedElementAccess( |
5220 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 5213 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
5221 false, // is_store | 5214 false, // is_store |
5222 &has_side_effects); | 5215 &has_side_effects); |
5223 Push(load); | 5216 Push(load); |
5224 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 5217 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
5225 | 5218 |
5226 CHECK_ALIVE(VisitForValue(expr->value())); | 5219 CHECK_ALIVE(VisitForValue(expr->value())); |
5227 HValue* right = Pop(); | 5220 HValue* right = Pop(); |
5228 HValue* left = Pop(); | 5221 HValue* left = Pop(); |
5229 | 5222 |
5230 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5223 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
5231 PushAndAdd(instr); | 5224 PushAndAdd(instr); |
5232 if (instr->HasObservableSideEffects()) { | 5225 if (instr->HasObservableSideEffects()) { |
5233 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 5226 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
5234 } | 5227 } |
5235 | 5228 |
5236 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), | 5229 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), |
5237 RelocInfo::kNoPosition, | 5230 RelocInfo::kNoPosition, |
5238 true, // is_store | 5231 true, // is_store |
5239 &has_side_effects); | 5232 &has_side_effects); |
5240 | 5233 |
5241 // Drop the simulated receiver, key, and value. Return the value. | 5234 // Drop the simulated receiver, key, and value. Return the value. |
5242 Drop(3); | 5235 Drop(3); |
5243 Push(instr); | 5236 Push(instr); |
5244 ASSERT(has_side_effects); // Stores always have side effects. | 5237 ASSERT(has_side_effects); // Stores always have side effects. |
5245 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5238 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5246 return ast_context()->ReturnValue(Pop()); | 5239 return ast_context()->ReturnValue(Pop()); |
5247 } | 5240 } |
5248 | 5241 |
5249 } else { | 5242 } else { |
5250 return Bailout("invalid lhs in compound assignment"); | 5243 return Bailout("invalid lhs in compound assignment"); |
5251 } | 5244 } |
5252 } | 5245 } |
5253 | 5246 |
5254 | 5247 |
5255 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 5248 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5357 } else { | 5350 } else { |
5358 ASSERT(expr->op() == Token::INIT_CONST); | 5351 ASSERT(expr->op() == Token::INIT_CONST); |
5359 | 5352 |
5360 mode = HStoreContextSlot::kCheckIgnoreAssignment; | 5353 mode = HStoreContextSlot::kCheckIgnoreAssignment; |
5361 } | 5354 } |
5362 | 5355 |
5363 HValue* context = BuildContextChainWalk(var); | 5356 HValue* context = BuildContextChainWalk(var); |
5364 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5357 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
5365 mode, Top()); | 5358 mode, Top()); |
5366 if (instr->HasObservableSideEffects()) { | 5359 if (instr->HasObservableSideEffects()) { |
5367 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5360 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5368 } | 5361 } |
5369 return ast_context()->ReturnValue(Pop()); | 5362 return ast_context()->ReturnValue(Pop()); |
5370 } | 5363 } |
5371 | 5364 |
5372 case Variable::LOOKUP: | 5365 case Variable::LOOKUP: |
5373 return Bailout("assignment to LOOKUP variable"); | 5366 return Bailout("assignment to LOOKUP variable"); |
5374 } | 5367 } |
5375 } else { | 5368 } else { |
5376 return Bailout("invalid left-hand side in assignment"); | 5369 return Bailout("invalid left-hand side in assignment"); |
5377 } | 5370 } |
(...skipping 13 matching lines...) Expand all Loading... | |
5391 // We don't optimize functions with invalid left-hand sides in | 5384 // We don't optimize functions with invalid left-hand sides in |
5392 // assignments, count operations, or for-in. Consequently throw can | 5385 // assignments, count operations, or for-in. Consequently throw can |
5393 // currently only occur in an effect context. | 5386 // currently only occur in an effect context. |
5394 ASSERT(ast_context()->IsEffect()); | 5387 ASSERT(ast_context()->IsEffect()); |
5395 CHECK_ALIVE(VisitForValue(expr->exception())); | 5388 CHECK_ALIVE(VisitForValue(expr->exception())); |
5396 | 5389 |
5397 HValue* context = environment()->LookupContext(); | 5390 HValue* context = environment()->LookupContext(); |
5398 HValue* value = environment()->Pop(); | 5391 HValue* value = environment()->Pop(); |
5399 HThrow* instr = Add<HThrow>(context, value); | 5392 HThrow* instr = Add<HThrow>(context, value); |
5400 instr->set_position(expr->position()); | 5393 instr->set_position(expr->position()); |
5401 AddSimulate(expr->id()); | 5394 Add<HSimulate>(expr->id()); |
5402 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5395 current_block()->FinishExit(new(zone()) HAbnormalExit); |
5403 set_current_block(NULL); | 5396 set_current_block(NULL); |
5404 } | 5397 } |
5405 | 5398 |
5406 | 5399 |
5407 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( | 5400 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( |
5408 HValue* object, | 5401 HValue* object, |
5409 HObjectAccess access, | 5402 HObjectAccess access, |
5410 Representation representation) { | 5403 Representation representation) { |
5411 bool load_double = false; | 5404 bool load_double = false; |
(...skipping 11 matching lines...) Expand all Loading... | |
5423 } | 5416 } |
5424 return field; | 5417 return field; |
5425 } | 5418 } |
5426 | 5419 |
5427 | 5420 |
5428 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5421 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
5429 HValue* object, | 5422 HValue* object, |
5430 Handle<String> name, | 5423 Handle<String> name, |
5431 Property* expr) { | 5424 Property* expr) { |
5432 if (expr->IsUninitialized()) { | 5425 if (expr->IsUninitialized()) { |
5433 AddSoftDeoptimize(); | 5426 Add<HDeoptimize>(); |
5434 } | 5427 } |
5435 HValue* context = environment()->LookupContext(); | 5428 HValue* context = environment()->LookupContext(); |
5436 return new(zone()) HLoadNamedGeneric(context, object, name); | 5429 return new(zone()) HLoadNamedGeneric(context, object, name); |
5437 } | 5430 } |
5438 | 5431 |
5439 | 5432 |
5440 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 5433 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
5441 HValue* object, | 5434 HValue* object, |
5442 Handle<Map> map, | 5435 Handle<Map> map, |
5443 Handle<JSFunction> getter, | 5436 Handle<JSFunction> getter, |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5709 HLoadExternalArrayPointer* external_elements = NULL; | 5702 HLoadExternalArrayPointer* external_elements = NULL; |
5710 HInstruction* checked_key = NULL; | 5703 HInstruction* checked_key = NULL; |
5711 | 5704 |
5712 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds | 5705 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds |
5713 // are handled before external arrays. | 5706 // are handled before external arrays. |
5714 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5707 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5715 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5708 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5716 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5709 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5717 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5710 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5718 | 5711 |
5712 NoObservableSideEffectsScope scope(this); | |
5713 | |
5719 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; | 5714 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; |
5720 elements_kind <= LAST_ELEMENTS_KIND; | 5715 elements_kind <= LAST_ELEMENTS_KIND; |
5721 elements_kind = ElementsKind(elements_kind + 1)) { | 5716 elements_kind = ElementsKind(elements_kind + 1)) { |
5722 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some | 5717 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some |
5723 // code that's executed for all external array cases. | 5718 // code that's executed for all external array cases. |
5724 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == | 5719 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == |
5725 LAST_ELEMENTS_KIND); | 5720 LAST_ELEMENTS_KIND); |
5726 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND | 5721 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND |
5727 && todo_external_array) { | 5722 && todo_external_array) { |
5728 HInstruction* length = AddLoadFixedArrayLength(elements); | 5723 HInstruction* length = AddLoadFixedArrayLength(elements); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5807 if (position != RelocInfo::kNoPosition) access->set_position(position); | 5802 if (position != RelocInfo::kNoPosition) access->set_position(position); |
5808 if (!is_store) { | 5803 if (!is_store) { |
5809 Push(access); | 5804 Push(access); |
5810 } | 5805 } |
5811 current_block()->GotoNoSimulate(join); | 5806 current_block()->GotoNoSimulate(join); |
5812 set_current_block(if_false); | 5807 set_current_block(if_false); |
5813 } | 5808 } |
5814 } | 5809 } |
5815 | 5810 |
5816 // Deopt if none of the cases matched. | 5811 // Deopt if none of the cases matched. |
5817 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 5812 FinishExitWithHardDeoptimization(join); |
5818 set_current_block(join); | 5813 set_current_block(join); |
5819 return is_store ? NULL : Pop(); | 5814 return is_store ? NULL : Pop(); |
5820 } | 5815 } |
5821 | 5816 |
5822 | 5817 |
5823 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 5818 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
5824 HValue* obj, | 5819 HValue* obj, |
5825 HValue* key, | 5820 HValue* key, |
5826 HValue* val, | 5821 HValue* val, |
5827 Expression* expr, | 5822 Expression* expr, |
(...skipping 15 matching lines...) Expand all Loading... | |
5843 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | 5838 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); |
5844 } | 5839 } |
5845 } else if (expr->GetReceiverTypes() != NULL && | 5840 } else if (expr->GetReceiverTypes() != NULL && |
5846 !expr->GetReceiverTypes()->is_empty()) { | 5841 !expr->GetReceiverTypes()->is_empty()) { |
5847 return HandlePolymorphicElementAccess( | 5842 return HandlePolymorphicElementAccess( |
5848 obj, key, val, expr, ast_id, position, is_store, | 5843 obj, key, val, expr, ast_id, position, is_store, |
5849 expr->GetStoreMode(), has_side_effects); | 5844 expr->GetStoreMode(), has_side_effects); |
5850 } else { | 5845 } else { |
5851 if (is_store) { | 5846 if (is_store) { |
5852 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { | 5847 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { |
5853 AddSoftDeoptimize(); | 5848 Add<HDeoptimize>(); |
5854 } | 5849 } |
5855 instr = BuildStoreKeyedGeneric(obj, key, val); | 5850 instr = BuildStoreKeyedGeneric(obj, key, val); |
5856 } else { | 5851 } else { |
5857 if (expr->AsProperty()->IsUninitialized()) { | 5852 if (expr->AsProperty()->IsUninitialized()) { |
5858 AddSoftDeoptimize(); | 5853 Add<HDeoptimize>(); |
5859 } | 5854 } |
5860 instr = BuildLoadKeyedGeneric(obj, key); | 5855 instr = BuildLoadKeyedGeneric(obj, key); |
5861 } | 5856 } |
5862 AddInstruction(instr); | 5857 AddInstruction(instr); |
5863 } | 5858 } |
5864 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5859 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
5865 *has_side_effects = instr->HasObservableSideEffects(); | 5860 *has_side_effects = instr->HasObservableSideEffects(); |
5866 return instr; | 5861 return instr; |
5867 } | 5862 } |
5868 | 5863 |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6027 HValue* key = Pop(); | 6022 HValue* key = Pop(); |
6028 HValue* obj = Pop(); | 6023 HValue* obj = Pop(); |
6029 | 6024 |
6030 bool has_side_effects = false; | 6025 bool has_side_effects = false; |
6031 HValue* load = HandleKeyedElementAccess( | 6026 HValue* load = HandleKeyedElementAccess( |
6032 obj, key, NULL, expr, expr->id(), expr->position(), | 6027 obj, key, NULL, expr, expr->id(), expr->position(), |
6033 false, // is_store | 6028 false, // is_store |
6034 &has_side_effects); | 6029 &has_side_effects); |
6035 if (has_side_effects) { | 6030 if (has_side_effects) { |
6036 if (ast_context()->IsEffect()) { | 6031 if (ast_context()->IsEffect()) { |
6037 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 6032 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
6038 } else { | 6033 } else { |
6039 Push(load); | 6034 Push(load); |
6040 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 6035 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
6041 Drop(1); | 6036 Drop(1); |
6042 } | 6037 } |
6043 } | 6038 } |
6044 return ast_context()->ReturnValue(load); | 6039 return ast_context()->ReturnValue(load); |
6045 } | 6040 } |
6046 instr->set_position(expr->position()); | 6041 instr->set_position(expr->position()); |
6047 return ast_context()->ReturnInstruction(instr, expr->id()); | 6042 return ast_context()->ReturnInstruction(instr, expr->id()); |
6048 } | 6043 } |
6049 | 6044 |
6050 | 6045 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6132 } | 6127 } |
6133 | 6128 |
6134 if (!TryInlineCall(expr)) { | 6129 if (!TryInlineCall(expr)) { |
6135 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6130 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
6136 HCallConstantFunction* call = | 6131 HCallConstantFunction* call = |
6137 new(zone()) HCallConstantFunction(expr->target(), argument_count); | 6132 new(zone()) HCallConstantFunction(expr->target(), argument_count); |
6138 call->set_position(expr->position()); | 6133 call->set_position(expr->position()); |
6139 PreProcessCall(call); | 6134 PreProcessCall(call); |
6140 AddInstruction(call); | 6135 AddInstruction(call); |
6141 if (!ast_context()->IsEffect()) Push(call); | 6136 if (!ast_context()->IsEffect()) Push(call); |
6142 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 6137 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
6143 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6138 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
6144 } | 6139 } |
6145 | 6140 |
6146 return true; | 6141 return true; |
6147 } | 6142 } |
6148 | 6143 |
6149 | 6144 |
6150 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( | 6145 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( |
6151 Call* expr, | 6146 Call* expr, |
6152 HValue* receiver, | 6147 HValue* receiver, |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6264 } | 6259 } |
6265 | 6260 |
6266 if (current_block() != NULL) current_block()->Goto(join); | 6261 if (current_block() != NULL) current_block()->Goto(join); |
6267 set_current_block(if_false); | 6262 set_current_block(if_false); |
6268 } | 6263 } |
6269 | 6264 |
6270 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6265 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6271 // know about and do not want to handle ones we've never seen. Otherwise | 6266 // know about and do not want to handle ones we've never seen. Otherwise |
6272 // use a generic IC. | 6267 // use a generic IC. |
6273 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6268 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
6274 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 6269 FinishExitWithHardDeoptimization(join); |
6275 } else { | 6270 } else { |
6276 HValue* context = environment()->LookupContext(); | 6271 HValue* context = environment()->LookupContext(); |
6277 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); | 6272 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); |
6278 call->set_position(expr->position()); | 6273 call->set_position(expr->position()); |
6279 PreProcessCall(call); | 6274 PreProcessCall(call); |
6280 | 6275 |
6281 if (join != NULL) { | 6276 if (join != NULL) { |
6282 AddInstruction(call); | 6277 AddInstruction(call); |
6283 if (!ast_context()->IsEffect()) Push(call); | 6278 if (!ast_context()->IsEffect()) Push(call); |
6284 current_block()->Goto(join); | 6279 current_block()->Goto(join); |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6522 #if V8_TARGET_ARCH_IA32 | 6517 #if V8_TARGET_ARCH_IA32 |
6523 // IA32 only, overwrite the caller's context in the deoptimization | 6518 // IA32 only, overwrite the caller's context in the deoptimization |
6524 // environment with the correct one. | 6519 // environment with the correct one. |
6525 // | 6520 // |
6526 // TODO(kmillikin): implement the same inlining on other platforms so we | 6521 // TODO(kmillikin): implement the same inlining on other platforms so we |
6527 // can remove the unsightly ifdefs in this function. | 6522 // can remove the unsightly ifdefs in this function. |
6528 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); | 6523 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); |
6529 inner_env->BindContext(context); | 6524 inner_env->BindContext(context); |
6530 #endif | 6525 #endif |
6531 | 6526 |
6532 AddSimulate(return_id); | 6527 Add<HSimulate>(return_id); |
6533 current_block()->UpdateEnvironment(inner_env); | 6528 current_block()->UpdateEnvironment(inner_env); |
6534 HArgumentsObject* arguments_object = NULL; | 6529 HArgumentsObject* arguments_object = NULL; |
6535 | 6530 |
6536 // If the function uses arguments object create and bind one, also copy | 6531 // If the function uses arguments object create and bind one, also copy |
6537 // current arguments values to use them for materialization. | 6532 // current arguments values to use them for materialization. |
6538 if (function->scope()->arguments() != NULL) { | 6533 if (function->scope()->arguments() != NULL) { |
6539 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 6534 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
6540 HEnvironment* arguments_env = inner_env->arguments_environment(); | 6535 HEnvironment* arguments_env = inner_env->arguments_environment(); |
6541 int arguments_count = arguments_env->parameter_count(); | 6536 int arguments_count = arguments_env->parameter_count(); |
6542 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); | 6537 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); |
(...skipping 1165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7708 } | 7703 } |
7709 } | 7704 } |
7710 } | 7705 } |
7711 | 7706 |
7712 HValue* context = BuildContextChainWalk(var); | 7707 HValue* context = BuildContextChainWalk(var); |
7713 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 7708 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
7714 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 7709 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
7715 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 7710 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
7716 mode, after); | 7711 mode, after); |
7717 if (instr->HasObservableSideEffects()) { | 7712 if (instr->HasObservableSideEffects()) { |
7718 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7713 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
7719 } | 7714 } |
7720 break; | 7715 break; |
7721 } | 7716 } |
7722 | 7717 |
7723 case Variable::LOOKUP: | 7718 case Variable::LOOKUP: |
7724 return Bailout("lookup variable in count operation"); | 7719 return Bailout("lookup variable in count operation"); |
7725 } | 7720 } |
7726 | 7721 |
7727 } else { | 7722 } else { |
7728 // Argument of the count operation is a property. | 7723 // Argument of the count operation is a property. |
(...skipping 22 matching lines...) Expand all Loading... | |
7751 load = BuildCallGetter(object, map, getter, holder); | 7746 load = BuildCallGetter(object, map, getter, holder); |
7752 } else { | 7747 } else { |
7753 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 7748 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
7754 } | 7749 } |
7755 } else if (types != NULL && types->length() > 1) { | 7750 } else if (types != NULL && types->length() > 1) { |
7756 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); | 7751 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
7757 } | 7752 } |
7758 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); | 7753 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
7759 PushAndAdd(load); | 7754 PushAndAdd(load); |
7760 if (load->HasObservableSideEffects()) { | 7755 if (load->HasObservableSideEffects()) { |
7761 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7756 Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
7762 } | 7757 } |
7763 | 7758 |
7764 after = BuildIncrement(returns_original_input, expr); | 7759 after = BuildIncrement(returns_original_input, expr); |
7765 | 7760 |
7766 HValue* result = returns_original_input ? Pop() : NULL; | 7761 HValue* result = returns_original_input ? Pop() : NULL; |
7767 | 7762 |
7768 return BuildStoreNamed(prop, expr->id(), expr->position(), | 7763 return BuildStoreNamed(prop, expr->id(), expr->position(), |
7769 expr->AssignmentId(), prop, object, after, result); | 7764 expr->AssignmentId(), prop, object, after, result); |
7770 } else { | 7765 } else { |
7771 // Keyed property. | 7766 // Keyed property. |
7772 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7767 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
7773 | 7768 |
7774 CHECK_ALIVE(VisitForValue(prop->obj())); | 7769 CHECK_ALIVE(VisitForValue(prop->obj())); |
7775 CHECK_ALIVE(VisitForValue(prop->key())); | 7770 CHECK_ALIVE(VisitForValue(prop->key())); |
7776 HValue* obj = environment()->ExpressionStackAt(1); | 7771 HValue* obj = environment()->ExpressionStackAt(1); |
7777 HValue* key = environment()->ExpressionStackAt(0); | 7772 HValue* key = environment()->ExpressionStackAt(0); |
7778 | 7773 |
7779 bool has_side_effects = false; | 7774 bool has_side_effects = false; |
7780 HValue* load = HandleKeyedElementAccess( | 7775 HValue* load = HandleKeyedElementAccess( |
7781 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 7776 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
7782 false, // is_store | 7777 false, // is_store |
7783 &has_side_effects); | 7778 &has_side_effects); |
7784 Push(load); | 7779 Push(load); |
7785 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7780 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
7786 | 7781 |
7787 after = BuildIncrement(returns_original_input, expr); | 7782 after = BuildIncrement(returns_original_input, expr); |
7788 input = environment()->ExpressionStackAt(0); | 7783 input = environment()->ExpressionStackAt(0); |
7789 | 7784 |
7790 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), | 7785 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), |
7791 RelocInfo::kNoPosition, | 7786 RelocInfo::kNoPosition, |
7792 true, // is_store | 7787 true, // is_store |
7793 &has_side_effects); | 7788 &has_side_effects); |
7794 | 7789 |
7795 // Drop the key and the original value from the bailout environment. | 7790 // Drop the key and the original value from the bailout environment. |
7796 // Overwrite the receiver with the result of the operation, and the | 7791 // Overwrite the receiver with the result of the operation, and the |
7797 // placeholder with the original value if necessary. | 7792 // placeholder with the original value if necessary. |
7798 Drop(2); | 7793 Drop(2); |
7799 environment()->SetExpressionStackAt(0, after); | 7794 environment()->SetExpressionStackAt(0, after); |
7800 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 7795 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
7801 ASSERT(has_side_effects); // Stores always have side effects. | 7796 ASSERT(has_side_effects); // Stores always have side effects. |
7802 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7797 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
7803 } | 7798 } |
7804 } | 7799 } |
7805 | 7800 |
7806 Drop(returns_original_input ? 2 : 1); | 7801 Drop(returns_original_input ? 2 : 1); |
7807 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 7802 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
7808 } | 7803 } |
7809 | 7804 |
7810 | 7805 |
7811 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( | 7806 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( |
7812 HValue* context, | 7807 HValue* context, |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7898 HValue* context = environment()->LookupContext(); | 7893 HValue* context = environment()->LookupContext(); |
7899 Handle<Type> left_type = expr->left()->bounds().lower; | 7894 Handle<Type> left_type = expr->left()->bounds().lower; |
7900 Handle<Type> right_type = expr->right()->bounds().lower; | 7895 Handle<Type> right_type = expr->right()->bounds().lower; |
7901 Handle<Type> result_type = expr->bounds().lower; | 7896 Handle<Type> result_type = expr->bounds().lower; |
7902 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7897 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
7903 Representation left_rep = Representation::FromType(left_type); | 7898 Representation left_rep = Representation::FromType(left_type); |
7904 Representation right_rep = Representation::FromType(right_type); | 7899 Representation right_rep = Representation::FromType(right_type); |
7905 Representation result_rep = Representation::FromType(result_type); | 7900 Representation result_rep = Representation::FromType(result_type); |
7906 | 7901 |
7907 if (left_type->Is(Type::None())) { | 7902 if (left_type->Is(Type::None())) { |
7908 AddSoftDeoptimize(); | 7903 Add<HDeoptimize>(); |
7909 // TODO(rossberg): we should be able to get rid of non-continuous defaults. | 7904 // TODO(rossberg): we should be able to get rid of non-continuous defaults. |
7910 left_type = handle(Type::Any(), isolate()); | 7905 left_type = handle(Type::Any(), isolate()); |
7911 } | 7906 } |
7912 if (right_type->Is(Type::None())) { | 7907 if (right_type->Is(Type::None())) { |
7913 AddSoftDeoptimize(); | 7908 Add<HDeoptimize>(); |
7914 right_type = handle(Type::Any(), isolate()); | 7909 right_type = handle(Type::Any(), isolate()); |
7915 } | 7910 } |
7916 HInstruction* instr = NULL; | 7911 HInstruction* instr = NULL; |
7917 switch (expr->op()) { | 7912 switch (expr->op()) { |
7918 case Token::ADD: | 7913 case Token::ADD: |
7919 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { | 7914 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { |
7920 BuildCheckHeapObject(left); | 7915 BuildCheckHeapObject(left); |
7921 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 7916 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
7922 BuildCheckHeapObject(right); | 7917 BuildCheckHeapObject(right); |
7923 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 7918 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8253 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 8248 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
8254 // even though we are certain to pass the correct number of arguments here. | 8249 // even though we are certain to pass the correct number of arguments here. |
8255 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); | 8250 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); |
8256 result->set_position(expr->position()); | 8251 result->set_position(expr->position()); |
8257 return ast_context()->ReturnInstruction(result, expr->id()); | 8252 return ast_context()->ReturnInstruction(result, expr->id()); |
8258 } | 8253 } |
8259 | 8254 |
8260 // Cases handled below depend on collected type feedback. They should | 8255 // Cases handled below depend on collected type feedback. They should |
8261 // soft deoptimize when there is no type feedback. | 8256 // soft deoptimize when there is no type feedback. |
8262 if (combined_type->Is(Type::None())) { | 8257 if (combined_type->Is(Type::None())) { |
8263 AddSoftDeoptimize(); | 8258 Add<HDeoptimize>(); |
8264 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 8259 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
8265 } | 8260 } |
8266 | 8261 |
8267 if (combined_type->Is(Type::Receiver())) { | 8262 if (combined_type->Is(Type::Receiver())) { |
8268 switch (op) { | 8263 switch (op) { |
8269 case Token::EQ: | 8264 case Token::EQ: |
8270 case Token::EQ_STRICT: { | 8265 case Token::EQ_STRICT: { |
8271 // Can we get away with map check and not instance type check? | 8266 // Can we get away with map check and not instance type check? |
8272 if (combined_type->IsClass()) { | 8267 if (combined_type->IsClass()) { |
8273 Handle<Map> map = combined_type->AsClass(); | 8268 Handle<Map> map = combined_type->AsClass(); |
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8753 environment()->Bind(variable, value); | 8748 environment()->Bind(variable, value); |
8754 } | 8749 } |
8755 break; | 8750 break; |
8756 case Variable::CONTEXT: | 8751 case Variable::CONTEXT: |
8757 if (hole_init) { | 8752 if (hole_init) { |
8758 HValue* value = graph()->GetConstantHole(); | 8753 HValue* value = graph()->GetConstantHole(); |
8759 HValue* context = environment()->LookupContext(); | 8754 HValue* context = environment()->LookupContext(); |
8760 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8755 HStoreContextSlot* store = Add<HStoreContextSlot>( |
8761 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8756 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8762 if (store->HasObservableSideEffects()) { | 8757 if (store->HasObservableSideEffects()) { |
8763 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8758 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8764 } | 8759 } |
8765 } | 8760 } |
8766 break; | 8761 break; |
8767 case Variable::LOOKUP: | 8762 case Variable::LOOKUP: |
8768 return Bailout("unsupported lookup slot in declaration"); | 8763 return Bailout("unsupported lookup slot in declaration"); |
8769 } | 8764 } |
8770 } | 8765 } |
8771 | 8766 |
8772 | 8767 |
8773 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 8768 void HOptimizedGraphBuilder::VisitFunctionDeclaration( |
(...skipping 17 matching lines...) Expand all Loading... | |
8791 BindIfLive(variable, value); | 8786 BindIfLive(variable, value); |
8792 break; | 8787 break; |
8793 } | 8788 } |
8794 case Variable::CONTEXT: { | 8789 case Variable::CONTEXT: { |
8795 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8790 CHECK_ALIVE(VisitForValue(declaration->fun())); |
8796 HValue* value = Pop(); | 8791 HValue* value = Pop(); |
8797 HValue* context = environment()->LookupContext(); | 8792 HValue* context = environment()->LookupContext(); |
8798 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8793 HStoreContextSlot* store = Add<HStoreContextSlot>( |
8799 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8794 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8800 if (store->HasObservableSideEffects()) { | 8795 if (store->HasObservableSideEffects()) { |
8801 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8796 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8802 } | 8797 } |
8803 break; | 8798 break; |
8804 } | 8799 } |
8805 case Variable::LOOKUP: | 8800 case Variable::LOOKUP: |
8806 return Bailout("unsupported lookup slot in declaration"); | 8801 return Bailout("unsupported lookup slot in declaration"); |
8807 } | 8802 } |
8808 } | 8803 } |
8809 | 8804 |
8810 | 8805 |
8811 void HOptimizedGraphBuilder::VisitModuleDeclaration( | 8806 void HOptimizedGraphBuilder::VisitModuleDeclaration( |
(...skipping 1177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9989 if (ShouldProduceTraceOutput()) { | 9984 if (ShouldProduceTraceOutput()) { |
9990 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9985 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9991 } | 9986 } |
9992 | 9987 |
9993 #ifdef DEBUG | 9988 #ifdef DEBUG |
9994 graph_->Verify(false); // No full verify. | 9989 graph_->Verify(false); // No full verify. |
9995 #endif | 9990 #endif |
9996 } | 9991 } |
9997 | 9992 |
9998 } } // namespace v8::internal | 9993 } } // namespace v8::internal |
OLD | NEW |