| 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) { |
| (...skipping 96 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 // Return on true. Nothing to do, just continue the false block. |
| 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 merge_block_ = builder_->graph()->CreateBasicBlock(); |
| 877 merge_block_ = builder_->CreateBasicBlock(merge_env); | |
| 878 ASSERT(!finished_); | 861 ASSERT(!finished_); |
| 879 if (!did_else_) Else(); | 862 if (!did_else_) Else(); |
| 880 ASSERT(!last_true_block_->IsFinished()); | 863 ASSERT(!last_true_block_->IsFinished()); |
| 881 HBasicBlock* last_false_block = builder_->current_block(); | 864 HBasicBlock* last_false_block = builder_->current_block(); |
| 882 ASSERT(!last_false_block->IsFinished()); | 865 ASSERT(!last_false_block->IsFinished()); |
| 883 last_true_block_->GotoNoSimulate(merge_block_); | 866 if (deopt_then_) { |
| 884 last_false_block->GotoNoSimulate(merge_block_); | 867 last_false_block->GotoNoSimulate(merge_block_); |
| 868 builder_->PadEnvironmentForContinuation(last_true_block_, |
| 869 merge_block_); |
| 870 last_true_block_->GotoNoSimulate(merge_block_); |
| 871 } else { |
| 872 last_true_block_->GotoNoSimulate(merge_block_); |
| 873 if (deopt_else_) { |
| 874 builder_->PadEnvironmentForContinuation(last_false_block, |
| 875 merge_block_); |
| 876 } |
| 877 last_false_block->GotoNoSimulate(merge_block_); |
| 878 } |
| 885 builder_->set_current_block(merge_block_); | 879 builder_->set_current_block(merge_block_); |
| 886 } | 880 } |
| 887 } | 881 } |
| 888 finished_ = true; | 882 finished_ = true; |
| 889 } | 883 } |
| 890 | 884 |
| 891 | 885 |
| 892 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, | 886 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
| 893 HValue* context, | 887 HValue* context, |
| 894 LoopBuilder::Direction direction) | 888 LoopBuilder::Direction direction) |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 984 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 978 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 985 ASSERT(current_block() != NULL); | 979 ASSERT(current_block() != NULL); |
| 986 current_block()->AddInstruction(instr); | 980 current_block()->AddInstruction(instr); |
| 987 if (no_side_effects_scope_count_ > 0) { | 981 if (no_side_effects_scope_count_ > 0) { |
| 988 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 982 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
| 989 } | 983 } |
| 990 return instr; | 984 return instr; |
| 991 } | 985 } |
| 992 | 986 |
| 993 | 987 |
| 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) { | 988 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
| 1025 HBasicBlock* b = graph()->CreateBasicBlock(); | 989 HBasicBlock* b = graph()->CreateBasicBlock(); |
| 1026 b->SetInitialEnvironment(env); | 990 b->SetInitialEnvironment(env); |
| 1027 return b; | 991 return b; |
| 1028 } | 992 } |
| 1029 | 993 |
| 1030 | 994 |
| 1031 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 995 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
| 1032 HBasicBlock* header = graph()->CreateBasicBlock(); | 996 HBasicBlock* header = graph()->CreateBasicBlock(); |
| 1033 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 997 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
| 1034 header->SetInitialEnvironment(entry_env); | 998 header->SetInitialEnvironment(entry_env); |
| 1035 header->AttachLoopInformation(); | 999 header->AttachLoopInformation(); |
| 1036 return header; | 1000 return header; |
| 1037 } | 1001 } |
| 1038 | 1002 |
| 1039 | 1003 |
| 1040 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { | 1004 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { |
| 1041 if (obj->type().IsHeapObject()) return obj; | 1005 if (obj->type().IsHeapObject()) return obj; |
| 1042 return Add<HCheckHeapObject>(obj); | 1006 return Add<HCheckHeapObject>(obj); |
| 1043 } | 1007 } |
| 1044 | 1008 |
| 1045 | 1009 |
| 1046 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, | 1010 void HGraphBuilder::FinishExitWithHardDeoptimization( |
| 1047 Handle<Map> map) { | 1011 HBasicBlock* continuation) { |
| 1012 PadEnvironmentForContinuation(current_block(), continuation); |
| 1013 Add<HDeoptimize>(Deoptimizer::EAGER); |
| 1014 if (no_side_effects_scope_count_ > 0) { |
| 1015 current_block()->GotoNoSimulate(continuation); |
| 1016 } else { |
| 1017 current_block()->Goto(continuation); |
| 1018 } |
| 1019 } |
| 1020 |
| 1021 |
| 1022 void HGraphBuilder::PadEnvironmentForContinuation( |
| 1023 HBasicBlock* from, |
| 1024 HBasicBlock* continuation) { |
| 1025 if (continuation->last_environment() != NULL) { |
| 1026 // When merging from a deopt block to a continuation, resolve differences in |
| 1027 // environment by pushing undefined and popping extra values so that the |
| 1028 // environments match during the join. |
| 1029 int continuation_env_length = continuation->last_environment()->length(); |
| 1030 while (continuation_env_length != from->last_environment()->length()) { |
| 1031 if (continuation_env_length > from->last_environment()->length()) { |
| 1032 from->last_environment()->Push(graph()->GetConstantUndefined()); |
| 1033 } else { |
| 1034 from->last_environment()->Pop(); |
| 1035 } |
| 1036 } |
| 1037 } else { |
| 1038 ASSERT(continuation->predecessors()->length() == 0); |
| 1039 } |
| 1040 } |
| 1041 |
| 1042 |
| 1043 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { |
| 1048 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); | 1044 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); |
| 1049 AddInstruction(check); | 1045 AddInstruction(check); |
| 1050 return check; | 1046 return check; |
| 1051 } | 1047 } |
| 1052 | 1048 |
| 1053 | 1049 |
| 1054 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, | 1050 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, |
| 1055 HValue* elements, | 1051 HValue* elements, |
| 1056 ElementsKind kind, | 1052 ElementsKind kind, |
| 1057 HValue* length, | 1053 HValue* length, |
| (...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1712 | 1708 |
| 1713 switch (operation) { | 1709 switch (operation) { |
| 1714 default: | 1710 default: |
| 1715 UNREACHABLE(); | 1711 UNREACHABLE(); |
| 1716 case Token::SUB: { | 1712 case Token::SUB: { |
| 1717 HInstruction* instr = | 1713 HInstruction* instr = |
| 1718 HMul::New(zone(), environment()->LookupContext(), | 1714 HMul::New(zone(), environment()->LookupContext(), |
| 1719 input, graph()->GetConstantMinus1()); | 1715 input, graph()->GetConstantMinus1()); |
| 1720 Representation rep = Representation::FromType(type); | 1716 Representation rep = Representation::FromType(type); |
| 1721 if (type->Is(Type::None())) { | 1717 if (type->Is(Type::None())) { |
| 1722 AddSoftDeoptimize(); | 1718 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 1723 } | 1719 } |
| 1724 if (instr->IsBinaryOperation()) { | 1720 if (instr->IsBinaryOperation()) { |
| 1725 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 1721 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
| 1726 binop->set_observed_input_representation(1, rep); | 1722 binop->set_observed_input_representation(1, rep); |
| 1727 binop->set_observed_input_representation(2, rep); | 1723 binop->set_observed_input_representation(2, rep); |
| 1728 } | 1724 } |
| 1729 return instr; | 1725 return instr; |
| 1730 } | 1726 } |
| 1731 case Token::BIT_NOT: | 1727 case Token::BIT_NOT: |
| 1732 if (type->Is(Type::None())) { | 1728 if (type->Is(Type::None())) { |
| 1733 AddSoftDeoptimize(); | 1729 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 1734 } | 1730 } |
| 1735 return new(zone()) HBitNot(input); | 1731 return new(zone()) HBitNot(input); |
| 1736 } | 1732 } |
| 1737 } | 1733 } |
| 1738 | 1734 |
| 1739 | 1735 |
| 1740 void HGraphBuilder::BuildCompareNil( | 1736 void HGraphBuilder::BuildCompareNil( |
| 1741 HValue* value, | 1737 HValue* value, |
| 1742 Handle<Type> type, | 1738 Handle<Type> type, |
| 1743 int position, | 1739 int position, |
| (...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2631 | 2627 |
| 2632 void TestContext::ReturnValue(HValue* value) { | 2628 void TestContext::ReturnValue(HValue* value) { |
| 2633 BuildBranch(value); | 2629 BuildBranch(value); |
| 2634 } | 2630 } |
| 2635 | 2631 |
| 2636 | 2632 |
| 2637 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2633 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
| 2638 ASSERT(!instr->IsControlInstruction()); | 2634 ASSERT(!instr->IsControlInstruction()); |
| 2639 owner()->AddInstruction(instr); | 2635 owner()->AddInstruction(instr); |
| 2640 if (instr->HasObservableSideEffects()) { | 2636 if (instr->HasObservableSideEffects()) { |
| 2641 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2637 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 2642 } | 2638 } |
| 2643 } | 2639 } |
| 2644 | 2640 |
| 2645 | 2641 |
| 2646 void EffectContext::ReturnControl(HControlInstruction* instr, | 2642 void EffectContext::ReturnControl(HControlInstruction* instr, |
| 2647 BailoutId ast_id) { | 2643 BailoutId ast_id) { |
| 2648 ASSERT(!instr->HasObservableSideEffects()); | 2644 ASSERT(!instr->HasObservableSideEffects()); |
| 2649 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2645 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
| 2650 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2646 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
| 2651 instr->SetSuccessorAt(0, empty_true); | 2647 instr->SetSuccessorAt(0, empty_true); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2673 | 2669 |
| 2674 | 2670 |
| 2675 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2671 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
| 2676 ASSERT(!instr->IsControlInstruction()); | 2672 ASSERT(!instr->IsControlInstruction()); |
| 2677 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2673 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
| 2678 return owner()->Bailout("bad value context for arguments object value"); | 2674 return owner()->Bailout("bad value context for arguments object value"); |
| 2679 } | 2675 } |
| 2680 owner()->AddInstruction(instr); | 2676 owner()->AddInstruction(instr); |
| 2681 owner()->Push(instr); | 2677 owner()->Push(instr); |
| 2682 if (instr->HasObservableSideEffects()) { | 2678 if (instr->HasObservableSideEffects()) { |
| 2683 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2679 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 2684 } | 2680 } |
| 2685 } | 2681 } |
| 2686 | 2682 |
| 2687 | 2683 |
| 2688 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2684 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
| 2689 ASSERT(!instr->HasObservableSideEffects()); | 2685 ASSERT(!instr->HasObservableSideEffects()); |
| 2690 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2686 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
| 2691 return owner()->Bailout("bad value context for arguments object value"); | 2687 return owner()->Bailout("bad value context for arguments object value"); |
| 2692 } | 2688 } |
| 2693 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | 2689 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2729 | 2725 |
| 2730 | 2726 |
| 2731 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2727 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
| 2732 ASSERT(!instr->IsControlInstruction()); | 2728 ASSERT(!instr->IsControlInstruction()); |
| 2733 HOptimizedGraphBuilder* builder = owner(); | 2729 HOptimizedGraphBuilder* builder = owner(); |
| 2734 builder->AddInstruction(instr); | 2730 builder->AddInstruction(instr); |
| 2735 // We expect a simulate after every expression with side effects, though | 2731 // We expect a simulate after every expression with side effects, though |
| 2736 // this one isn't actually needed (and wouldn't work if it were targeted). | 2732 // this one isn't actually needed (and wouldn't work if it were targeted). |
| 2737 if (instr->HasObservableSideEffects()) { | 2733 if (instr->HasObservableSideEffects()) { |
| 2738 builder->Push(instr); | 2734 builder->Push(instr); |
| 2739 builder->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2735 builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 2740 builder->Pop(); | 2736 builder->Pop(); |
| 2741 } | 2737 } |
| 2742 BuildBranch(instr); | 2738 BuildBranch(instr); |
| 2743 } | 2739 } |
| 2744 | 2740 |
| 2745 | 2741 |
| 2746 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2742 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
| 2747 ASSERT(!instr->HasObservableSideEffects()); | 2743 ASSERT(!instr->HasObservableSideEffects()); |
| 2748 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2744 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
| 2749 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2745 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2917 current_block()->Goto(body_entry); | 2913 current_block()->Goto(body_entry); |
| 2918 body_entry->SetJoinId(BailoutId::FunctionEntry()); | 2914 body_entry->SetJoinId(BailoutId::FunctionEntry()); |
| 2919 set_current_block(body_entry); | 2915 set_current_block(body_entry); |
| 2920 | 2916 |
| 2921 // Handle implicit declaration of the function name in named function | 2917 // Handle implicit declaration of the function name in named function |
| 2922 // expressions before other declarations. | 2918 // expressions before other declarations. |
| 2923 if (scope->is_function_scope() && scope->function() != NULL) { | 2919 if (scope->is_function_scope() && scope->function() != NULL) { |
| 2924 VisitVariableDeclaration(scope->function()); | 2920 VisitVariableDeclaration(scope->function()); |
| 2925 } | 2921 } |
| 2926 VisitDeclarations(scope->declarations()); | 2922 VisitDeclarations(scope->declarations()); |
| 2927 AddSimulate(BailoutId::Declarations()); | 2923 Add<HSimulate>(BailoutId::Declarations()); |
| 2928 | 2924 |
| 2929 HValue* context = environment()->LookupContext(); | 2925 HValue* context = environment()->LookupContext(); |
| 2930 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); | 2926 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); |
| 2931 | 2927 |
| 2932 VisitStatements(current_info()->function()->body()); | 2928 VisitStatements(current_info()->function()->body()); |
| 2933 if (HasStackOverflow()) return false; | 2929 if (HasStackOverflow()) return false; |
| 2934 | 2930 |
| 2935 if (current_block() != NULL) { | 2931 if (current_block() != NULL) { |
| 2936 AddReturn(graph()->GetConstantUndefined()); | 2932 Add<HReturn>(graph()->GetConstantUndefined()); |
| 2937 set_current_block(NULL); | 2933 set_current_block(NULL); |
| 2938 } | 2934 } |
| 2939 | 2935 |
| 2940 // If the checksum of the number of type info changes is the same as the | 2936 // If the checksum of the number of type info changes is the same as the |
| 2941 // last time this function was compiled, then this recompile is likely not | 2937 // last time this function was compiled, then this recompile is likely not |
| 2942 // due to missing/inadequate type feedback, but rather too aggressive | 2938 // due to missing/inadequate type feedback, but rather too aggressive |
| 2943 // optimization. Disable optimistic LICM in that case. | 2939 // optimization. Disable optimistic LICM in that case. |
| 2944 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); | 2940 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); |
| 2945 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 2941 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 2946 Handle<TypeFeedbackInfo> type_info( | 2942 Handle<TypeFeedbackInfo> type_info( |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3216 ASSERT(current_block() != NULL); | 3212 ASSERT(current_block() != NULL); |
| 3217 ASSERT(current_block()->HasPredecessor()); | 3213 ASSERT(current_block()->HasPredecessor()); |
| 3218 } | 3214 } |
| 3219 | 3215 |
| 3220 | 3216 |
| 3221 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 3217 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
| 3222 ASSERT(!HasStackOverflow()); | 3218 ASSERT(!HasStackOverflow()); |
| 3223 ASSERT(current_block() != NULL); | 3219 ASSERT(current_block() != NULL); |
| 3224 ASSERT(current_block()->HasPredecessor()); | 3220 ASSERT(current_block()->HasPredecessor()); |
| 3225 if (stmt->condition()->ToBooleanIsTrue()) { | 3221 if (stmt->condition()->ToBooleanIsTrue()) { |
| 3226 AddSimulate(stmt->ThenId()); | 3222 Add<HSimulate>(stmt->ThenId()); |
| 3227 Visit(stmt->then_statement()); | 3223 Visit(stmt->then_statement()); |
| 3228 } else if (stmt->condition()->ToBooleanIsFalse()) { | 3224 } else if (stmt->condition()->ToBooleanIsFalse()) { |
| 3229 AddSimulate(stmt->ElseId()); | 3225 Add<HSimulate>(stmt->ElseId()); |
| 3230 Visit(stmt->else_statement()); | 3226 Visit(stmt->else_statement()); |
| 3231 } else { | 3227 } else { |
| 3232 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 3228 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
| 3233 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 3229 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
| 3234 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); | 3230 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); |
| 3235 | 3231 |
| 3236 if (cond_true->HasPredecessor()) { | 3232 if (cond_true->HasPredecessor()) { |
| 3237 cond_true->SetJoinId(stmt->ThenId()); | 3233 cond_true->SetJoinId(stmt->ThenId()); |
| 3238 set_current_block(cond_true); | 3234 set_current_block(cond_true); |
| 3239 CHECK_BAILOUT(Visit(stmt->then_statement())); | 3235 CHECK_BAILOUT(Visit(stmt->then_statement())); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3326 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 3322 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| 3327 ASSERT(!HasStackOverflow()); | 3323 ASSERT(!HasStackOverflow()); |
| 3328 ASSERT(current_block() != NULL); | 3324 ASSERT(current_block() != NULL); |
| 3329 ASSERT(current_block()->HasPredecessor()); | 3325 ASSERT(current_block()->HasPredecessor()); |
| 3330 FunctionState* state = function_state(); | 3326 FunctionState* state = function_state(); |
| 3331 AstContext* context = call_context(); | 3327 AstContext* context = call_context(); |
| 3332 if (context == NULL) { | 3328 if (context == NULL) { |
| 3333 // Not an inlined return, so an actual one. | 3329 // Not an inlined return, so an actual one. |
| 3334 CHECK_ALIVE(VisitForValue(stmt->expression())); | 3330 CHECK_ALIVE(VisitForValue(stmt->expression())); |
| 3335 HValue* result = environment()->Pop(); | 3331 HValue* result = environment()->Pop(); |
| 3336 AddReturn(result); | 3332 Add<HReturn>(result); |
| 3337 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 3333 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
| 3338 // Return from an inlined construct call. In a test context the return value | 3334 // Return from an inlined construct call. In a test context the return value |
| 3339 // will always evaluate to true, in a value context the return value needs | 3335 // will always evaluate to true, in a value context the return value needs |
| 3340 // to be a JSObject. | 3336 // to be a JSObject. |
| 3341 if (context->IsTest()) { | 3337 if (context->IsTest()) { |
| 3342 TestContext* test = TestContext::cast(context); | 3338 TestContext* test = TestContext::cast(context); |
| 3343 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3339 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
| 3344 current_block()->Goto(test->if_true(), state); | 3340 current_block()->Goto(test->if_true(), state); |
| 3345 } else if (context->IsEffect()) { | 3341 } else if (context->IsEffect()) { |
| 3346 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3342 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3418 } | 3414 } |
| 3419 | 3415 |
| 3420 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); | 3416 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); |
| 3421 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { | 3417 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { |
| 3422 return Bailout("SwitchStatement: mixed or non-literal switch labels"); | 3418 return Bailout("SwitchStatement: mixed or non-literal switch labels"); |
| 3423 } | 3419 } |
| 3424 | 3420 |
| 3425 HValue* context = environment()->LookupContext(); | 3421 HValue* context = environment()->LookupContext(); |
| 3426 | 3422 |
| 3427 CHECK_ALIVE(VisitForValue(stmt->tag())); | 3423 CHECK_ALIVE(VisitForValue(stmt->tag())); |
| 3428 AddSimulate(stmt->EntryId()); | 3424 Add<HSimulate>(stmt->EntryId()); |
| 3429 HValue* tag_value = Pop(); | 3425 HValue* tag_value = Pop(); |
| 3430 HBasicBlock* first_test_block = current_block(); | 3426 HBasicBlock* first_test_block = current_block(); |
| 3431 | 3427 |
| 3432 HUnaryControlInstruction* string_check = NULL; | 3428 HUnaryControlInstruction* string_check = NULL; |
| 3433 HBasicBlock* not_string_block = NULL; | 3429 HBasicBlock* not_string_block = NULL; |
| 3434 | 3430 |
| 3435 // Test switch's tag value if all clauses are string literals | 3431 // Test switch's tag value if all clauses are string literals |
| 3436 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { | 3432 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { |
| 3437 string_check = new(zone()) HIsStringAndBranch(tag_value); | 3433 string_check = new(zone()) HIsStringAndBranch(tag_value); |
| 3438 first_test_block = graph()->CreateBasicBlock(); | 3434 first_test_block = graph()->CreateBasicBlock(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3458 CHECK_ALIVE(VisitForValue(clause->label())); | 3454 CHECK_ALIVE(VisitForValue(clause->label())); |
| 3459 HValue* label_value = Pop(); | 3455 HValue* label_value = Pop(); |
| 3460 | 3456 |
| 3461 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 3457 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
| 3462 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 3458 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
| 3463 | 3459 |
| 3464 HControlInstruction* compare; | 3460 HControlInstruction* compare; |
| 3465 | 3461 |
| 3466 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { | 3462 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { |
| 3467 if (!clause->compare_type()->Is(Type::Smi())) { | 3463 if (!clause->compare_type()->Is(Type::Smi())) { |
| 3468 AddSoftDeoptimize(); | 3464 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 3469 } | 3465 } |
| 3470 | 3466 |
| 3471 HCompareNumericAndBranch* compare_ = | 3467 HCompareNumericAndBranch* compare_ = |
| 3472 new(zone()) HCompareNumericAndBranch(tag_value, | 3468 new(zone()) HCompareNumericAndBranch(tag_value, |
| 3473 label_value, | 3469 label_value, |
| 3474 Token::EQ_STRICT); | 3470 Token::EQ_STRICT); |
| 3475 compare_->set_observed_input_representation( | 3471 compare_->set_observed_input_representation( |
| 3476 Representation::Smi(), Representation::Smi()); | 3472 Representation::Smi(), Representation::Smi()); |
| 3477 compare = compare_; | 3473 compare = compare_; |
| 3478 } else { | 3474 } else { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3508 CaseClause* clause = clauses->at(i); | 3504 CaseClause* clause = clauses->at(i); |
| 3509 | 3505 |
| 3510 // Identify the block where normal (non-fall-through) control flow | 3506 // Identify the block where normal (non-fall-through) control flow |
| 3511 // goes to. | 3507 // goes to. |
| 3512 HBasicBlock* normal_block = NULL; | 3508 HBasicBlock* normal_block = NULL; |
| 3513 if (clause->is_default()) { | 3509 if (clause->is_default()) { |
| 3514 if (last_block != NULL) { | 3510 if (last_block != NULL) { |
| 3515 normal_block = last_block; | 3511 normal_block = last_block; |
| 3516 last_block = NULL; // Cleared to indicate we've handled it. | 3512 last_block = NULL; // Cleared to indicate we've handled it. |
| 3517 } | 3513 } |
| 3518 } else if (!curr_test_block->end()->IsDeoptimize()) { | 3514 } else { |
| 3519 normal_block = curr_test_block->end()->FirstSuccessor(); | 3515 normal_block = curr_test_block->end()->FirstSuccessor(); |
| 3520 curr_test_block = curr_test_block->end()->SecondSuccessor(); | 3516 curr_test_block = curr_test_block->end()->SecondSuccessor(); |
| 3521 } | 3517 } |
| 3522 | 3518 |
| 3523 // Identify a block to emit the body into. | 3519 // Identify a block to emit the body into. |
| 3524 if (normal_block == NULL) { | 3520 if (normal_block == NULL) { |
| 3525 if (fall_through_block == NULL) { | 3521 if (fall_through_block == NULL) { |
| 3526 // (a) Unreachable. | 3522 // (a) Unreachable. |
| 3527 if (clause->is_default()) { | 3523 if (clause->is_default()) { |
| 3528 continue; // Might still be reachable clause bodies. | 3524 continue; // Might still be reachable clause bodies. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3562 break_block->SetJoinId(stmt->ExitId()); | 3558 break_block->SetJoinId(stmt->ExitId()); |
| 3563 set_current_block(break_block); | 3559 set_current_block(break_block); |
| 3564 } | 3560 } |
| 3565 } | 3561 } |
| 3566 | 3562 |
| 3567 | 3563 |
| 3568 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 3564 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
| 3569 HBasicBlock* loop_entry, | 3565 HBasicBlock* loop_entry, |
| 3570 BreakAndContinueInfo* break_info) { | 3566 BreakAndContinueInfo* break_info) { |
| 3571 BreakAndContinueScope push(break_info, this); | 3567 BreakAndContinueScope push(break_info, this); |
| 3572 AddSimulate(stmt->StackCheckId()); | 3568 Add<HSimulate>(stmt->StackCheckId()); |
| 3573 HValue* context = environment()->LookupContext(); | 3569 HValue* context = environment()->LookupContext(); |
| 3574 HStackCheck* stack_check = Add<HStackCheck>( | 3570 HStackCheck* stack_check = Add<HStackCheck>( |
| 3575 context, HStackCheck::kBackwardsBranch); | 3571 context, HStackCheck::kBackwardsBranch); |
| 3576 ASSERT(loop_entry->IsLoopHeader()); | 3572 ASSERT(loop_entry->IsLoopHeader()); |
| 3577 loop_entry->loop_information()->set_stack_check(stack_check); | 3573 loop_entry->loop_information()->set_stack_check(stack_check); |
| 3578 CHECK_BAILOUT(Visit(stmt->body())); | 3574 CHECK_BAILOUT(Visit(stmt->body())); |
| 3579 } | 3575 } |
| 3580 | 3576 |
| 3581 | 3577 |
| 3582 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 3578 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3723 return Bailout("ForInStatement with non-local each variable"); | 3719 return Bailout("ForInStatement with non-local each variable"); |
| 3724 } | 3720 } |
| 3725 | 3721 |
| 3726 Variable* each_var = stmt->each()->AsVariableProxy()->var(); | 3722 Variable* each_var = stmt->each()->AsVariableProxy()->var(); |
| 3727 | 3723 |
| 3728 CHECK_ALIVE(VisitForValue(stmt->enumerable())); | 3724 CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
| 3729 HValue* enumerable = Top(); // Leave enumerable at the top. | 3725 HValue* enumerable = Top(); // Leave enumerable at the top. |
| 3730 | 3726 |
| 3731 HInstruction* map = Add<HForInPrepareMap>( | 3727 HInstruction* map = Add<HForInPrepareMap>( |
| 3732 environment()->LookupContext(), enumerable); | 3728 environment()->LookupContext(), enumerable); |
| 3733 AddSimulate(stmt->PrepareId()); | 3729 Add<HSimulate>(stmt->PrepareId()); |
| 3734 | 3730 |
| 3735 HInstruction* array = Add<HForInCacheArray>( | 3731 HInstruction* array = Add<HForInCacheArray>( |
| 3736 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); | 3732 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); |
| 3737 | 3733 |
| 3738 HInstruction* enum_length = Add<HMapEnumLength>(map); | 3734 HInstruction* enum_length = Add<HMapEnumLength>(map); |
| 3739 | 3735 |
| 3740 HInstruction* start_index = Add<HConstant>(0); | 3736 HInstruction* start_index = Add<HConstant>(0); |
| 3741 | 3737 |
| 3742 Push(map); | 3738 Push(map); |
| 3743 Push(array); | 3739 Push(array); |
| (...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4320 Handle<JSObject> holder; | 4316 Handle<JSObject> holder; |
| 4321 ASSERT(!LookupSetter(map, name, &setter, &holder)); | 4317 ASSERT(!LookupSetter(map, name, &setter, &holder)); |
| 4322 #endif | 4318 #endif |
| 4323 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, | 4319 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, |
| 4324 name, | 4320 name, |
| 4325 value, | 4321 value, |
| 4326 map)); | 4322 map)); |
| 4327 } | 4323 } |
| 4328 AddInstruction(store); | 4324 AddInstruction(store); |
| 4329 if (store->HasObservableSideEffects()) { | 4325 if (store->HasObservableSideEffects()) { |
| 4330 AddSimulate(key->id(), REMOVABLE_SIMULATE); | 4326 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
| 4331 } | 4327 } |
| 4332 } else { | 4328 } else { |
| 4333 CHECK_ALIVE(VisitForEffect(value)); | 4329 CHECK_ALIVE(VisitForEffect(value)); |
| 4334 } | 4330 } |
| 4335 break; | 4331 break; |
| 4336 } | 4332 } |
| 4337 // Fall through. | 4333 // Fall through. |
| 4338 case ObjectLiteral::Property::PROTOTYPE: | 4334 case ObjectLiteral::Property::PROTOTYPE: |
| 4339 case ObjectLiteral::Property::SETTER: | 4335 case ObjectLiteral::Property::SETTER: |
| 4340 case ObjectLiteral::Property::GETTER: | 4336 case ObjectLiteral::Property::GETTER: |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4485 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, | 4481 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, |
| 4486 boilerplate_elements_kind); | 4482 boilerplate_elements_kind); |
| 4487 instr->SetUninitialized(uninitialized); | 4483 instr->SetUninitialized(uninitialized); |
| 4488 break; | 4484 break; |
| 4489 } | 4485 } |
| 4490 default: | 4486 default: |
| 4491 UNREACHABLE(); | 4487 UNREACHABLE(); |
| 4492 break; | 4488 break; |
| 4493 } | 4489 } |
| 4494 | 4490 |
| 4495 AddSimulate(expr->GetIdForElement(i)); | 4491 Add<HSimulate>(expr->GetIdForElement(i)); |
| 4496 } | 4492 } |
| 4497 | 4493 |
| 4498 Drop(1); // array literal index | 4494 Drop(1); // array literal index |
| 4499 return ast_context()->ReturnValue(Pop()); | 4495 return ast_context()->ReturnValue(Pop()); |
| 4500 } | 4496 } |
| 4501 | 4497 |
| 4502 | 4498 |
| 4503 // Sets the lookup result and returns true if the load/store can be inlined. | 4499 // Sets the lookup result and returns true if the load/store can be inlined. |
| 4504 static bool ComputeLoadStoreField(Handle<Map> type, | 4500 static bool ComputeLoadStoreField(Handle<Map> type, |
| 4505 Handle<String> name, | 4501 Handle<String> name, |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4815 BuildCheckHeapObject(object); | 4811 BuildCheckHeapObject(object); |
| 4816 AddInstruction(HCheckMaps::New(object, types, zone())); | 4812 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 4817 HInstruction* store; | 4813 HInstruction* store; |
| 4818 CHECK_ALIVE_OR_RETURN( | 4814 CHECK_ALIVE_OR_RETURN( |
| 4819 store = BuildStoreNamedField( | 4815 store = BuildStoreNamedField( |
| 4820 object, name, store_value, types->at(count - 1), &lookup), | 4816 object, name, store_value, types->at(count - 1), &lookup), |
| 4821 true); | 4817 true); |
| 4822 if (!ast_context()->IsEffect()) Push(result_value); | 4818 if (!ast_context()->IsEffect()) Push(result_value); |
| 4823 store->set_position(position); | 4819 store->set_position(position); |
| 4824 AddInstruction(store); | 4820 AddInstruction(store); |
| 4825 AddSimulate(assignment_id); | 4821 Add<HSimulate>(assignment_id); |
| 4826 if (!ast_context()->IsEffect()) Drop(1); | 4822 if (!ast_context()->IsEffect()) Drop(1); |
| 4827 ast_context()->ReturnValue(result_value); | 4823 ast_context()->ReturnValue(result_value); |
| 4828 return true; | 4824 return true; |
| 4829 } | 4825 } |
| 4830 | 4826 |
| 4831 | 4827 |
| 4832 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 4828 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| 4833 int position, | 4829 int position, |
| 4834 BailoutId assignment_id, | 4830 BailoutId assignment_id, |
| 4835 HValue* object, | 4831 HValue* object, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4874 current_block()->Goto(join); | 4870 current_block()->Goto(join); |
| 4875 | 4871 |
| 4876 set_current_block(if_false); | 4872 set_current_block(if_false); |
| 4877 } | 4873 } |
| 4878 } | 4874 } |
| 4879 | 4875 |
| 4880 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 4876 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 4881 // know about and do not want to handle ones we've never seen. Otherwise | 4877 // know about and do not want to handle ones we've never seen. Otherwise |
| 4882 // use a generic IC. | 4878 // use a generic IC. |
| 4883 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 4879 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 4884 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 4880 FinishExitWithHardDeoptimization(join); |
| 4885 } else { | 4881 } else { |
| 4886 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); | 4882 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); |
| 4887 instr->set_position(position); | 4883 instr->set_position(position); |
| 4888 AddInstruction(instr); | 4884 AddInstruction(instr); |
| 4889 | 4885 |
| 4890 if (join != NULL) { | 4886 if (join != NULL) { |
| 4891 if (!ast_context()->IsEffect()) { | 4887 if (!ast_context()->IsEffect()) { |
| 4892 Push(result_value); | 4888 Push(result_value); |
| 4893 } | 4889 } |
| 4894 current_block()->Goto(join); | 4890 current_block()->Goto(join); |
| 4895 } else { | 4891 } else { |
| 4896 // The HSimulate for the store should not see the stored value in | 4892 // The HSimulate for the store should not see the stored value in |
| 4897 // effect contexts (it is not materialized at expr->id() in the | 4893 // effect contexts (it is not materialized at expr->id() in the |
| 4898 // unoptimized code). | 4894 // unoptimized code). |
| 4899 if (instr->HasObservableSideEffects()) { | 4895 if (instr->HasObservableSideEffects()) { |
| 4900 if (ast_context()->IsEffect()) { | 4896 if (ast_context()->IsEffect()) { |
| 4901 AddSimulate(assignment_id, REMOVABLE_SIMULATE); | 4897 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
| 4902 } else { | 4898 } else { |
| 4903 Push(result_value); | 4899 Push(result_value); |
| 4904 AddSimulate(assignment_id, REMOVABLE_SIMULATE); | 4900 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
| 4905 Drop(1); | 4901 Drop(1); |
| 4906 } | 4902 } |
| 4907 } | 4903 } |
| 4908 return ast_context()->ReturnValue(result_value); | 4904 return ast_context()->ReturnValue(result_value); |
| 4909 } | 4905 } |
| 4910 } | 4906 } |
| 4911 | 4907 |
| 4912 ASSERT(join != NULL); | 4908 ASSERT(join != NULL); |
| 4913 join->SetJoinId(assignment_id); | 4909 join->SetJoinId(assignment_id); |
| 4914 set_current_block(join); | 4910 set_current_block(join); |
| 4915 if (!ast_context()->IsEffect()) { | 4911 if (!ast_context()->IsEffect()) { |
| 4916 ast_context()->ReturnValue(Pop()); | 4912 ast_context()->ReturnValue(Pop()); |
| 4917 } | 4913 } |
| 4918 } | 4914 } |
| 4919 | 4915 |
| 4920 | 4916 |
| 4921 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 4917 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 4922 Property* prop = expr->target()->AsProperty(); | 4918 Property* prop = expr->target()->AsProperty(); |
| 4923 ASSERT(prop != NULL); | 4919 ASSERT(prop != NULL); |
| 4924 CHECK_ALIVE(VisitForValue(prop->obj())); | 4920 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 4925 | 4921 |
| 4926 if (prop->key()->IsPropertyName()) { | 4922 if (prop->key()->IsPropertyName()) { |
| 4927 // Named store. | 4923 // Named store. |
| 4928 CHECK_ALIVE(VisitForValue(expr->value())); | 4924 CHECK_ALIVE(VisitForValue(expr->value())); |
| 4929 HValue* value = environment()->ExpressionStackAt(0); | 4925 HValue* value = environment()->ExpressionStackAt(0); |
| 4930 HValue* object = environment()->ExpressionStackAt(1); | 4926 HValue* object = environment()->ExpressionStackAt(1); |
| 4931 | 4927 |
| 4932 if (expr->IsUninitialized()) AddSoftDeoptimize(); | 4928 if (expr->IsUninitialized()) Add<HDeoptimize>(Deoptimizer::SOFT); |
| 4933 return BuildStoreNamed(expr, expr->id(), expr->position(), | 4929 return BuildStoreNamed(expr, expr->id(), expr->position(), |
| 4934 expr->AssignmentId(), prop, object, value, value); | 4930 expr->AssignmentId(), prop, object, value, value); |
| 4935 } else { | 4931 } else { |
| 4936 // Keyed store. | 4932 // Keyed store. |
| 4937 CHECK_ALIVE(VisitForValue(prop->key())); | 4933 CHECK_ALIVE(VisitForValue(prop->key())); |
| 4938 CHECK_ALIVE(VisitForValue(expr->value())); | 4934 CHECK_ALIVE(VisitForValue(expr->value())); |
| 4939 HValue* value = environment()->ExpressionStackAt(0); | 4935 HValue* value = environment()->ExpressionStackAt(0); |
| 4940 HValue* key = environment()->ExpressionStackAt(1); | 4936 HValue* key = environment()->ExpressionStackAt(1); |
| 4941 HValue* object = environment()->ExpressionStackAt(2); | 4937 HValue* object = environment()->ExpressionStackAt(2); |
| 4942 bool has_side_effects = false; | 4938 bool has_side_effects = false; |
| 4943 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 4939 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
| 4944 expr->position(), | 4940 expr->position(), |
| 4945 true, // is_store | 4941 true, // is_store |
| 4946 &has_side_effects); | 4942 &has_side_effects); |
| 4947 Drop(3); | 4943 Drop(3); |
| 4948 Push(value); | 4944 Push(value); |
| 4949 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 4945 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 4950 return ast_context()->ReturnValue(Pop()); | 4946 return ast_context()->ReturnValue(Pop()); |
| 4951 } | 4947 } |
| 4952 } | 4948 } |
| 4953 | 4949 |
| 4954 | 4950 |
| 4955 // Because not every expression has a position and there is not common | 4951 // Because not every expression has a position and there is not common |
| 4956 // superclass of Assignment and CountOperation, we cannot just pass the | 4952 // superclass of Assignment and CountOperation, we cannot just pass the |
| 4957 // owning expression instead of position and ast_id separately. | 4953 // owning expression instead of position and ast_id separately. |
| 4958 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 4954 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 4959 Variable* var, | 4955 Variable* var, |
| 4960 HValue* value, | 4956 HValue* value, |
| 4961 int position, | 4957 int position, |
| 4962 BailoutId ast_id) { | 4958 BailoutId ast_id) { |
| 4963 LookupResult lookup(isolate()); | 4959 LookupResult lookup(isolate()); |
| 4964 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 4960 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 4965 if (type == kUseCell) { | 4961 if (type == kUseCell) { |
| 4966 Handle<GlobalObject> global(current_info()->global_object()); | 4962 Handle<GlobalObject> global(current_info()->global_object()); |
| 4967 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 4963 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 4968 if (cell->type()->IsConstant()) { | 4964 if (cell->type()->IsConstant()) { |
| 4969 IfBuilder builder(this); | 4965 IfBuilder builder(this); |
| 4970 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); | 4966 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); |
| 4971 if (cell->type()->AsConstant()->IsNumber()) { | 4967 if (cell->type()->AsConstant()->IsNumber()) { |
| 4972 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); | 4968 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); |
| 4973 } else { | 4969 } else { |
| 4974 builder.If<HCompareObjectEqAndBranch>(value, constant); | 4970 builder.If<HCompareObjectEqAndBranch>(value, constant); |
| 4975 } | 4971 } |
| 4976 builder.Then(); | 4972 builder.Then(); |
| 4977 builder.Else(); | 4973 builder.Else(); |
| 4978 AddSoftDeoptimize(MUST_EMIT_SOFT_DEOPT); | 4974 Add<HDeoptimize>(Deoptimizer::EAGER); |
| 4979 builder.End(); | 4975 builder.End(); |
| 4980 } | 4976 } |
| 4981 HInstruction* instr = | 4977 HInstruction* instr = |
| 4982 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | 4978 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
| 4983 instr->set_position(position); | 4979 instr->set_position(position); |
| 4984 if (instr->HasObservableSideEffects()) { | 4980 if (instr->HasObservableSideEffects()) { |
| 4985 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 4981 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 4986 } | 4982 } |
| 4987 } else { | 4983 } else { |
| 4988 HValue* context = environment()->LookupContext(); | 4984 HValue* context = environment()->LookupContext(); |
| 4989 HGlobalObject* global_object = Add<HGlobalObject>(context); | 4985 HGlobalObject* global_object = Add<HGlobalObject>(context); |
| 4990 HStoreGlobalGeneric* instr = | 4986 HStoreGlobalGeneric* instr = |
| 4991 Add<HStoreGlobalGeneric>(context, global_object, var->name(), | 4987 Add<HStoreGlobalGeneric>(context, global_object, var->name(), |
| 4992 value, function_strict_mode_flag()); | 4988 value, function_strict_mode_flag()); |
| 4993 instr->set_position(position); | 4989 instr->set_position(position); |
| 4994 ASSERT(instr->HasObservableSideEffects()); | 4990 ASSERT(instr->HasObservableSideEffects()); |
| 4995 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 4991 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 4996 } | 4992 } |
| 4997 } | 4993 } |
| 4998 | 4994 |
| 4999 | 4995 |
| 5000 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, | 4996 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, |
| 5001 BailoutId id, | 4997 BailoutId id, |
| 5002 int position, | 4998 int position, |
| 5003 BailoutId assignment_id, | 4999 BailoutId assignment_id, |
| 5004 Property* prop, | 5000 Property* prop, |
| 5005 HValue* object, | 5001 HValue* object, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5047 store_value, result_value, types, name); | 5043 store_value, result_value, types, name); |
| 5048 } else { | 5044 } else { |
| 5049 Drop(2); | 5045 Drop(2); |
| 5050 instr = BuildStoreNamedGeneric(object, name, store_value); | 5046 instr = BuildStoreNamedGeneric(object, name, store_value); |
| 5051 } | 5047 } |
| 5052 | 5048 |
| 5053 if (!ast_context()->IsEffect()) Push(result_value); | 5049 if (!ast_context()->IsEffect()) Push(result_value); |
| 5054 instr->set_position(position); | 5050 instr->set_position(position); |
| 5055 AddInstruction(instr); | 5051 AddInstruction(instr); |
| 5056 if (instr->HasObservableSideEffects()) { | 5052 if (instr->HasObservableSideEffects()) { |
| 5057 AddSimulate(id, REMOVABLE_SIMULATE); | 5053 Add<HSimulate>(id, REMOVABLE_SIMULATE); |
| 5058 } | 5054 } |
| 5059 if (!ast_context()->IsEffect()) Drop(1); | 5055 if (!ast_context()->IsEffect()) Drop(1); |
| 5060 return ast_context()->ReturnValue(result_value); | 5056 return ast_context()->ReturnValue(result_value); |
| 5061 } | 5057 } |
| 5062 | 5058 |
| 5063 | 5059 |
| 5064 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5060 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 5065 Expression* target = expr->target(); | 5061 Expression* target = expr->target(); |
| 5066 VariableProxy* proxy = target->AsVariableProxy(); | 5062 VariableProxy* proxy = target->AsVariableProxy(); |
| 5067 Property* prop = target->AsProperty(); | 5063 Property* prop = target->AsProperty(); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5125 // perform checks here | 5121 // perform checks here |
| 5126 UNREACHABLE(); | 5122 UNREACHABLE(); |
| 5127 default: | 5123 default: |
| 5128 mode = HStoreContextSlot::kNoCheck; | 5124 mode = HStoreContextSlot::kNoCheck; |
| 5129 } | 5125 } |
| 5130 | 5126 |
| 5131 HValue* context = BuildContextChainWalk(var); | 5127 HValue* context = BuildContextChainWalk(var); |
| 5132 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5128 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
| 5133 mode, Top()); | 5129 mode, Top()); |
| 5134 if (instr->HasObservableSideEffects()) { | 5130 if (instr->HasObservableSideEffects()) { |
| 5135 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5131 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5136 } | 5132 } |
| 5137 break; | 5133 break; |
| 5138 } | 5134 } |
| 5139 | 5135 |
| 5140 case Variable::LOOKUP: | 5136 case Variable::LOOKUP: |
| 5141 return Bailout("compound assignment to lookup slot"); | 5137 return Bailout("compound assignment to lookup slot"); |
| 5142 } | 5138 } |
| 5143 return ast_context()->ReturnValue(Pop()); | 5139 return ast_context()->ReturnValue(Pop()); |
| 5144 | 5140 |
| 5145 } else if (prop != NULL) { | 5141 } else if (prop != NULL) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 5166 load = BuildCallGetter(object, map, getter, holder); | 5162 load = BuildCallGetter(object, map, getter, holder); |
| 5167 } else { | 5163 } else { |
| 5168 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 5164 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
| 5169 } | 5165 } |
| 5170 } else if (types != NULL && types->length() > 1) { | 5166 } else if (types != NULL && types->length() > 1) { |
| 5171 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); | 5167 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
| 5172 } | 5168 } |
| 5173 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); | 5169 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
| 5174 PushAndAdd(load); | 5170 PushAndAdd(load); |
| 5175 if (load->HasObservableSideEffects()) { | 5171 if (load->HasObservableSideEffects()) { |
| 5176 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 5172 Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
| 5177 } | 5173 } |
| 5178 | 5174 |
| 5179 CHECK_ALIVE(VisitForValue(expr->value())); | 5175 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5180 HValue* right = Pop(); | 5176 HValue* right = Pop(); |
| 5181 HValue* left = Pop(); | 5177 HValue* left = Pop(); |
| 5182 | 5178 |
| 5183 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5179 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5184 PushAndAdd(instr); | 5180 PushAndAdd(instr); |
| 5185 if (instr->HasObservableSideEffects()) { | 5181 if (instr->HasObservableSideEffects()) { |
| 5186 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 5182 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
| 5187 } | 5183 } |
| 5188 | 5184 |
| 5189 return BuildStoreNamed(prop, expr->id(), expr->position(), | 5185 return BuildStoreNamed(prop, expr->id(), expr->position(), |
| 5190 expr->AssignmentId(), prop, object, instr, instr); | 5186 expr->AssignmentId(), prop, object, instr, instr); |
| 5191 } else { | 5187 } else { |
| 5192 // Keyed property. | 5188 // Keyed property. |
| 5193 CHECK_ALIVE(VisitForValue(prop->obj())); | 5189 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5194 CHECK_ALIVE(VisitForValue(prop->key())); | 5190 CHECK_ALIVE(VisitForValue(prop->key())); |
| 5195 HValue* obj = environment()->ExpressionStackAt(1); | 5191 HValue* obj = environment()->ExpressionStackAt(1); |
| 5196 HValue* key = environment()->ExpressionStackAt(0); | 5192 HValue* key = environment()->ExpressionStackAt(0); |
| 5197 | 5193 |
| 5198 bool has_side_effects = false; | 5194 bool has_side_effects = false; |
| 5199 HValue* load = HandleKeyedElementAccess( | 5195 HValue* load = HandleKeyedElementAccess( |
| 5200 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 5196 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
| 5201 false, // is_store | 5197 false, // is_store |
| 5202 &has_side_effects); | 5198 &has_side_effects); |
| 5203 Push(load); | 5199 Push(load); |
| 5204 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 5200 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
| 5205 | 5201 |
| 5206 CHECK_ALIVE(VisitForValue(expr->value())); | 5202 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5207 HValue* right = Pop(); | 5203 HValue* right = Pop(); |
| 5208 HValue* left = Pop(); | 5204 HValue* left = Pop(); |
| 5209 | 5205 |
| 5210 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5206 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5211 PushAndAdd(instr); | 5207 PushAndAdd(instr); |
| 5212 if (instr->HasObservableSideEffects()) { | 5208 if (instr->HasObservableSideEffects()) { |
| 5213 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 5209 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
| 5214 } | 5210 } |
| 5215 | 5211 |
| 5216 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), | 5212 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), |
| 5217 RelocInfo::kNoPosition, | 5213 RelocInfo::kNoPosition, |
| 5218 true, // is_store | 5214 true, // is_store |
| 5219 &has_side_effects); | 5215 &has_side_effects); |
| 5220 | 5216 |
| 5221 // Drop the simulated receiver, key, and value. Return the value. | 5217 // Drop the simulated receiver, key, and value. Return the value. |
| 5222 Drop(3); | 5218 Drop(3); |
| 5223 Push(instr); | 5219 Push(instr); |
| 5224 ASSERT(has_side_effects); // Stores always have side effects. | 5220 ASSERT(has_side_effects); // Stores always have side effects. |
| 5225 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5221 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5226 return ast_context()->ReturnValue(Pop()); | 5222 return ast_context()->ReturnValue(Pop()); |
| 5227 } | 5223 } |
| 5228 | 5224 |
| 5229 } else { | 5225 } else { |
| 5230 return Bailout("invalid lhs in compound assignment"); | 5226 return Bailout("invalid lhs in compound assignment"); |
| 5231 } | 5227 } |
| 5232 } | 5228 } |
| 5233 | 5229 |
| 5234 | 5230 |
| 5235 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 5231 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5337 } else { | 5333 } else { |
| 5338 ASSERT(expr->op() == Token::INIT_CONST); | 5334 ASSERT(expr->op() == Token::INIT_CONST); |
| 5339 | 5335 |
| 5340 mode = HStoreContextSlot::kCheckIgnoreAssignment; | 5336 mode = HStoreContextSlot::kCheckIgnoreAssignment; |
| 5341 } | 5337 } |
| 5342 | 5338 |
| 5343 HValue* context = BuildContextChainWalk(var); | 5339 HValue* context = BuildContextChainWalk(var); |
| 5344 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5340 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
| 5345 mode, Top()); | 5341 mode, Top()); |
| 5346 if (instr->HasObservableSideEffects()) { | 5342 if (instr->HasObservableSideEffects()) { |
| 5347 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5343 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5348 } | 5344 } |
| 5349 return ast_context()->ReturnValue(Pop()); | 5345 return ast_context()->ReturnValue(Pop()); |
| 5350 } | 5346 } |
| 5351 | 5347 |
| 5352 case Variable::LOOKUP: | 5348 case Variable::LOOKUP: |
| 5353 return Bailout("assignment to LOOKUP variable"); | 5349 return Bailout("assignment to LOOKUP variable"); |
| 5354 } | 5350 } |
| 5355 } else { | 5351 } else { |
| 5356 return Bailout("invalid left-hand side in assignment"); | 5352 return Bailout("invalid left-hand side in assignment"); |
| 5357 } | 5353 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5371 // We don't optimize functions with invalid left-hand sides in | 5367 // We don't optimize functions with invalid left-hand sides in |
| 5372 // assignments, count operations, or for-in. Consequently throw can | 5368 // assignments, count operations, or for-in. Consequently throw can |
| 5373 // currently only occur in an effect context. | 5369 // currently only occur in an effect context. |
| 5374 ASSERT(ast_context()->IsEffect()); | 5370 ASSERT(ast_context()->IsEffect()); |
| 5375 CHECK_ALIVE(VisitForValue(expr->exception())); | 5371 CHECK_ALIVE(VisitForValue(expr->exception())); |
| 5376 | 5372 |
| 5377 HValue* context = environment()->LookupContext(); | 5373 HValue* context = environment()->LookupContext(); |
| 5378 HValue* value = environment()->Pop(); | 5374 HValue* value = environment()->Pop(); |
| 5379 HThrow* instr = Add<HThrow>(context, value); | 5375 HThrow* instr = Add<HThrow>(context, value); |
| 5380 instr->set_position(expr->position()); | 5376 instr->set_position(expr->position()); |
| 5381 AddSimulate(expr->id()); | 5377 Add<HSimulate>(expr->id()); |
| 5382 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5378 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 5383 set_current_block(NULL); | 5379 set_current_block(NULL); |
| 5384 } | 5380 } |
| 5385 | 5381 |
| 5386 | 5382 |
| 5387 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( | 5383 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( |
| 5388 HValue* object, | 5384 HValue* object, |
| 5389 HObjectAccess access, | 5385 HObjectAccess access, |
| 5390 Representation representation) { | 5386 Representation representation) { |
| 5391 bool load_double = false; | 5387 bool load_double = false; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5403 } | 5399 } |
| 5404 return field; | 5400 return field; |
| 5405 } | 5401 } |
| 5406 | 5402 |
| 5407 | 5403 |
| 5408 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5404 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
| 5409 HValue* object, | 5405 HValue* object, |
| 5410 Handle<String> name, | 5406 Handle<String> name, |
| 5411 Property* expr) { | 5407 Property* expr) { |
| 5412 if (expr->IsUninitialized()) { | 5408 if (expr->IsUninitialized()) { |
| 5413 AddSoftDeoptimize(); | 5409 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 5414 } | 5410 } |
| 5415 HValue* context = environment()->LookupContext(); | 5411 HValue* context = environment()->LookupContext(); |
| 5416 return new(zone()) HLoadNamedGeneric(context, object, name); | 5412 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 5417 } | 5413 } |
| 5418 | 5414 |
| 5419 | 5415 |
| 5420 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 5416 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
| 5421 HValue* object, | 5417 HValue* object, |
| 5422 Handle<Map> map, | 5418 Handle<Map> map, |
| 5423 Handle<JSFunction> getter, | 5419 Handle<JSFunction> getter, |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5725 access->SetFlag(HValue::kHasNoObservableSideEffects); | 5721 access->SetFlag(HValue::kHasNoObservableSideEffects); |
| 5726 if (position != RelocInfo::kNoPosition) access->set_position(position); | 5722 if (position != RelocInfo::kNoPosition) access->set_position(position); |
| 5727 if (!is_store) { | 5723 if (!is_store) { |
| 5728 Push(access); | 5724 Push(access); |
| 5729 } | 5725 } |
| 5730 current_block()->GotoNoSimulate(join); | 5726 current_block()->GotoNoSimulate(join); |
| 5731 set_current_block(other_map); | 5727 set_current_block(other_map); |
| 5732 } | 5728 } |
| 5733 | 5729 |
| 5734 // Deopt if none of the cases matched. | 5730 // Deopt if none of the cases matched. |
| 5735 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 5731 NoObservableSideEffectsScope scope(this); |
| 5732 FinishExitWithHardDeoptimization(join); |
| 5736 set_current_block(join); | 5733 set_current_block(join); |
| 5737 return is_store ? NULL : Pop(); | 5734 return is_store ? NULL : Pop(); |
| 5738 } | 5735 } |
| 5739 | 5736 |
| 5740 | 5737 |
| 5741 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 5738 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
| 5742 HValue* obj, | 5739 HValue* obj, |
| 5743 HValue* key, | 5740 HValue* key, |
| 5744 HValue* val, | 5741 HValue* val, |
| 5745 Expression* expr, | 5742 Expression* expr, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5761 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | 5758 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); |
| 5762 } | 5759 } |
| 5763 } else if (expr->GetReceiverTypes() != NULL && | 5760 } else if (expr->GetReceiverTypes() != NULL && |
| 5764 !expr->GetReceiverTypes()->is_empty()) { | 5761 !expr->GetReceiverTypes()->is_empty()) { |
| 5765 return HandlePolymorphicElementAccess( | 5762 return HandlePolymorphicElementAccess( |
| 5766 obj, key, val, expr, ast_id, position, is_store, | 5763 obj, key, val, expr, ast_id, position, is_store, |
| 5767 expr->GetStoreMode(), has_side_effects); | 5764 expr->GetStoreMode(), has_side_effects); |
| 5768 } else { | 5765 } else { |
| 5769 if (is_store) { | 5766 if (is_store) { |
| 5770 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { | 5767 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { |
| 5771 AddSoftDeoptimize(); | 5768 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 5772 } | 5769 } |
| 5773 instr = BuildStoreKeyedGeneric(obj, key, val); | 5770 instr = BuildStoreKeyedGeneric(obj, key, val); |
| 5774 } else { | 5771 } else { |
| 5775 if (expr->AsProperty()->IsUninitialized()) { | 5772 if (expr->AsProperty()->IsUninitialized()) { |
| 5776 AddSoftDeoptimize(); | 5773 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 5777 } | 5774 } |
| 5778 instr = BuildLoadKeyedGeneric(obj, key); | 5775 instr = BuildLoadKeyedGeneric(obj, key); |
| 5779 } | 5776 } |
| 5780 AddInstruction(instr); | 5777 AddInstruction(instr); |
| 5781 } | 5778 } |
| 5782 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5779 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
| 5783 *has_side_effects = instr->HasObservableSideEffects(); | 5780 *has_side_effects = instr->HasObservableSideEffects(); |
| 5784 return instr; | 5781 return instr; |
| 5785 } | 5782 } |
| 5786 | 5783 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5945 HValue* key = Pop(); | 5942 HValue* key = Pop(); |
| 5946 HValue* obj = Pop(); | 5943 HValue* obj = Pop(); |
| 5947 | 5944 |
| 5948 bool has_side_effects = false; | 5945 bool has_side_effects = false; |
| 5949 HValue* load = HandleKeyedElementAccess( | 5946 HValue* load = HandleKeyedElementAccess( |
| 5950 obj, key, NULL, expr, expr->id(), expr->position(), | 5947 obj, key, NULL, expr, expr->id(), expr->position(), |
| 5951 false, // is_store | 5948 false, // is_store |
| 5952 &has_side_effects); | 5949 &has_side_effects); |
| 5953 if (has_side_effects) { | 5950 if (has_side_effects) { |
| 5954 if (ast_context()->IsEffect()) { | 5951 if (ast_context()->IsEffect()) { |
| 5955 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 5952 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 5956 } else { | 5953 } else { |
| 5957 Push(load); | 5954 Push(load); |
| 5958 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 5955 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 5959 Drop(1); | 5956 Drop(1); |
| 5960 } | 5957 } |
| 5961 } | 5958 } |
| 5962 return ast_context()->ReturnValue(load); | 5959 return ast_context()->ReturnValue(load); |
| 5963 } | 5960 } |
| 5964 instr->set_position(expr->position()); | 5961 instr->set_position(expr->position()); |
| 5965 return ast_context()->ReturnInstruction(instr, expr->id()); | 5962 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5966 } | 5963 } |
| 5967 | 5964 |
| 5968 | 5965 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6050 } | 6047 } |
| 6051 | 6048 |
| 6052 if (!TryInlineCall(expr)) { | 6049 if (!TryInlineCall(expr)) { |
| 6053 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6050 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 6054 HCallConstantFunction* call = | 6051 HCallConstantFunction* call = |
| 6055 new(zone()) HCallConstantFunction(expr->target(), argument_count); | 6052 new(zone()) HCallConstantFunction(expr->target(), argument_count); |
| 6056 call->set_position(expr->position()); | 6053 call->set_position(expr->position()); |
| 6057 PreProcessCall(call); | 6054 PreProcessCall(call); |
| 6058 AddInstruction(call); | 6055 AddInstruction(call); |
| 6059 if (!ast_context()->IsEffect()) Push(call); | 6056 if (!ast_context()->IsEffect()) Push(call); |
| 6060 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 6057 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 6061 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6058 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 6062 } | 6059 } |
| 6063 | 6060 |
| 6064 return true; | 6061 return true; |
| 6065 } | 6062 } |
| 6066 | 6063 |
| 6067 | 6064 |
| 6068 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( | 6065 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( |
| 6069 Call* expr, | 6066 Call* expr, |
| 6070 HValue* receiver, | 6067 HValue* receiver, |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6182 } | 6179 } |
| 6183 | 6180 |
| 6184 if (current_block() != NULL) current_block()->Goto(join); | 6181 if (current_block() != NULL) current_block()->Goto(join); |
| 6185 set_current_block(if_false); | 6182 set_current_block(if_false); |
| 6186 } | 6183 } |
| 6187 | 6184 |
| 6188 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6185 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 6189 // know about and do not want to handle ones we've never seen. Otherwise | 6186 // know about and do not want to handle ones we've never seen. Otherwise |
| 6190 // use a generic IC. | 6187 // use a generic IC. |
| 6191 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6188 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 6192 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 6189 FinishExitWithHardDeoptimization(join); |
| 6193 } else { | 6190 } else { |
| 6194 HValue* context = environment()->LookupContext(); | 6191 HValue* context = environment()->LookupContext(); |
| 6195 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); | 6192 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); |
| 6196 call->set_position(expr->position()); | 6193 call->set_position(expr->position()); |
| 6197 PreProcessCall(call); | 6194 PreProcessCall(call); |
| 6198 | 6195 |
| 6199 if (join != NULL) { | 6196 if (join != NULL) { |
| 6200 AddInstruction(call); | 6197 AddInstruction(call); |
| 6201 if (!ast_context()->IsEffect()) Push(call); | 6198 if (!ast_context()->IsEffect()) Push(call); |
| 6202 current_block()->Goto(join); | 6199 current_block()->Goto(join); |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6440 #if V8_TARGET_ARCH_IA32 | 6437 #if V8_TARGET_ARCH_IA32 |
| 6441 // IA32 only, overwrite the caller's context in the deoptimization | 6438 // IA32 only, overwrite the caller's context in the deoptimization |
| 6442 // environment with the correct one. | 6439 // environment with the correct one. |
| 6443 // | 6440 // |
| 6444 // TODO(kmillikin): implement the same inlining on other platforms so we | 6441 // TODO(kmillikin): implement the same inlining on other platforms so we |
| 6445 // can remove the unsightly ifdefs in this function. | 6442 // can remove the unsightly ifdefs in this function. |
| 6446 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); | 6443 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); |
| 6447 inner_env->BindContext(context); | 6444 inner_env->BindContext(context); |
| 6448 #endif | 6445 #endif |
| 6449 | 6446 |
| 6450 AddSimulate(return_id); | 6447 Add<HSimulate>(return_id); |
| 6451 current_block()->UpdateEnvironment(inner_env); | 6448 current_block()->UpdateEnvironment(inner_env); |
| 6452 HArgumentsObject* arguments_object = NULL; | 6449 HArgumentsObject* arguments_object = NULL; |
| 6453 | 6450 |
| 6454 // If the function uses arguments object create and bind one, also copy | 6451 // If the function uses arguments object create and bind one, also copy |
| 6455 // current arguments values to use them for materialization. | 6452 // current arguments values to use them for materialization. |
| 6456 if (function->scope()->arguments() != NULL) { | 6453 if (function->scope()->arguments() != NULL) { |
| 6457 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 6454 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
| 6458 HEnvironment* arguments_env = inner_env->arguments_environment(); | 6455 HEnvironment* arguments_env = inner_env->arguments_environment(); |
| 6459 int arguments_count = arguments_env->parameter_count(); | 6456 int arguments_count = arguments_env->parameter_count(); |
| 6460 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); | 6457 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); |
| (...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7618 } | 7615 } |
| 7619 } | 7616 } |
| 7620 } | 7617 } |
| 7621 | 7618 |
| 7622 HValue* context = BuildContextChainWalk(var); | 7619 HValue* context = BuildContextChainWalk(var); |
| 7623 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 7620 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
| 7624 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 7621 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
| 7625 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 7622 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
| 7626 mode, after); | 7623 mode, after); |
| 7627 if (instr->HasObservableSideEffects()) { | 7624 if (instr->HasObservableSideEffects()) { |
| 7628 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7625 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 7629 } | 7626 } |
| 7630 break; | 7627 break; |
| 7631 } | 7628 } |
| 7632 | 7629 |
| 7633 case Variable::LOOKUP: | 7630 case Variable::LOOKUP: |
| 7634 return Bailout("lookup variable in count operation"); | 7631 return Bailout("lookup variable in count operation"); |
| 7635 } | 7632 } |
| 7636 | 7633 |
| 7637 } else { | 7634 } else { |
| 7638 // Argument of the count operation is a property. | 7635 // Argument of the count operation is a property. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 7661 load = BuildCallGetter(object, map, getter, holder); | 7658 load = BuildCallGetter(object, map, getter, holder); |
| 7662 } else { | 7659 } else { |
| 7663 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 7660 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
| 7664 } | 7661 } |
| 7665 } else if (types != NULL && types->length() > 1) { | 7662 } else if (types != NULL && types->length() > 1) { |
| 7666 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); | 7663 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
| 7667 } | 7664 } |
| 7668 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); | 7665 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
| 7669 PushAndAdd(load); | 7666 PushAndAdd(load); |
| 7670 if (load->HasObservableSideEffects()) { | 7667 if (load->HasObservableSideEffects()) { |
| 7671 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7668 Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
| 7672 } | 7669 } |
| 7673 | 7670 |
| 7674 after = BuildIncrement(returns_original_input, expr); | 7671 after = BuildIncrement(returns_original_input, expr); |
| 7675 HValue* result = returns_original_input ? Pop() : after; | 7672 HValue* result = returns_original_input ? Pop() : after; |
| 7676 | 7673 |
| 7677 return BuildStoreNamed(prop, expr->id(), expr->position(), | 7674 return BuildStoreNamed(prop, expr->id(), expr->position(), |
| 7678 expr->AssignmentId(), prop, object, after, result); | 7675 expr->AssignmentId(), prop, object, after, result); |
| 7679 } else { | 7676 } else { |
| 7680 // Keyed property. | 7677 // Keyed property. |
| 7681 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7678 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
| 7682 | 7679 |
| 7683 CHECK_ALIVE(VisitForValue(prop->obj())); | 7680 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7684 CHECK_ALIVE(VisitForValue(prop->key())); | 7681 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7685 HValue* obj = environment()->ExpressionStackAt(1); | 7682 HValue* obj = environment()->ExpressionStackAt(1); |
| 7686 HValue* key = environment()->ExpressionStackAt(0); | 7683 HValue* key = environment()->ExpressionStackAt(0); |
| 7687 | 7684 |
| 7688 bool has_side_effects = false; | 7685 bool has_side_effects = false; |
| 7689 HValue* load = HandleKeyedElementAccess( | 7686 HValue* load = HandleKeyedElementAccess( |
| 7690 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 7687 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
| 7691 false, // is_store | 7688 false, // is_store |
| 7692 &has_side_effects); | 7689 &has_side_effects); |
| 7693 Push(load); | 7690 Push(load); |
| 7694 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7691 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
| 7695 | 7692 |
| 7696 after = BuildIncrement(returns_original_input, expr); | 7693 after = BuildIncrement(returns_original_input, expr); |
| 7697 input = environment()->ExpressionStackAt(0); | 7694 input = environment()->ExpressionStackAt(0); |
| 7698 | 7695 |
| 7699 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), | 7696 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), |
| 7700 RelocInfo::kNoPosition, | 7697 RelocInfo::kNoPosition, |
| 7701 true, // is_store | 7698 true, // is_store |
| 7702 &has_side_effects); | 7699 &has_side_effects); |
| 7703 | 7700 |
| 7704 // Drop the key and the original value from the bailout environment. | 7701 // Drop the key and the original value from the bailout environment. |
| 7705 // Overwrite the receiver with the result of the operation, and the | 7702 // Overwrite the receiver with the result of the operation, and the |
| 7706 // placeholder with the original value if necessary. | 7703 // placeholder with the original value if necessary. |
| 7707 Drop(2); | 7704 Drop(2); |
| 7708 environment()->SetExpressionStackAt(0, after); | 7705 environment()->SetExpressionStackAt(0, after); |
| 7709 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 7706 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
| 7710 ASSERT(has_side_effects); // Stores always have side effects. | 7707 ASSERT(has_side_effects); // Stores always have side effects. |
| 7711 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7708 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 7712 } | 7709 } |
| 7713 } | 7710 } |
| 7714 | 7711 |
| 7715 Drop(returns_original_input ? 2 : 1); | 7712 Drop(returns_original_input ? 2 : 1); |
| 7716 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 7713 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
| 7717 } | 7714 } |
| 7718 | 7715 |
| 7719 | 7716 |
| 7720 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( | 7717 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( |
| 7721 HValue* context, | 7718 HValue* context, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7807 HValue* context = environment()->LookupContext(); | 7804 HValue* context = environment()->LookupContext(); |
| 7808 Handle<Type> left_type = expr->left()->bounds().lower; | 7805 Handle<Type> left_type = expr->left()->bounds().lower; |
| 7809 Handle<Type> right_type = expr->right()->bounds().lower; | 7806 Handle<Type> right_type = expr->right()->bounds().lower; |
| 7810 Handle<Type> result_type = expr->bounds().lower; | 7807 Handle<Type> result_type = expr->bounds().lower; |
| 7811 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7808 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 7812 Representation left_rep = Representation::FromType(left_type); | 7809 Representation left_rep = Representation::FromType(left_type); |
| 7813 Representation right_rep = Representation::FromType(right_type); | 7810 Representation right_rep = Representation::FromType(right_type); |
| 7814 Representation result_rep = Representation::FromType(result_type); | 7811 Representation result_rep = Representation::FromType(result_type); |
| 7815 | 7812 |
| 7816 if (left_type->Is(Type::None())) { | 7813 if (left_type->Is(Type::None())) { |
| 7817 AddSoftDeoptimize(); | 7814 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 7818 // TODO(rossberg): we should be able to get rid of non-continuous defaults. | 7815 // TODO(rossberg): we should be able to get rid of non-continuous defaults. |
| 7819 left_type = handle(Type::Any(), isolate()); | 7816 left_type = handle(Type::Any(), isolate()); |
| 7820 } | 7817 } |
| 7821 if (right_type->Is(Type::None())) { | 7818 if (right_type->Is(Type::None())) { |
| 7822 AddSoftDeoptimize(); | 7819 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 7823 right_type = handle(Type::Any(), isolate()); | 7820 right_type = handle(Type::Any(), isolate()); |
| 7824 } | 7821 } |
| 7825 HInstruction* instr = NULL; | 7822 HInstruction* instr = NULL; |
| 7826 switch (expr->op()) { | 7823 switch (expr->op()) { |
| 7827 case Token::ADD: | 7824 case Token::ADD: |
| 7828 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { | 7825 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { |
| 7829 BuildCheckHeapObject(left); | 7826 BuildCheckHeapObject(left); |
| 7830 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 7827 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 7831 BuildCheckHeapObject(right); | 7828 BuildCheckHeapObject(right); |
| 7832 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 7829 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8162 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 8159 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
| 8163 // even though we are certain to pass the correct number of arguments here. | 8160 // even though we are certain to pass the correct number of arguments here. |
| 8164 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); | 8161 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); |
| 8165 result->set_position(expr->position()); | 8162 result->set_position(expr->position()); |
| 8166 return ast_context()->ReturnInstruction(result, expr->id()); | 8163 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8167 } | 8164 } |
| 8168 | 8165 |
| 8169 // Cases handled below depend on collected type feedback. They should | 8166 // Cases handled below depend on collected type feedback. They should |
| 8170 // soft deoptimize when there is no type feedback. | 8167 // soft deoptimize when there is no type feedback. |
| 8171 if (combined_type->Is(Type::None())) { | 8168 if (combined_type->Is(Type::None())) { |
| 8172 AddSoftDeoptimize(); | 8169 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 8173 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 8170 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
| 8174 } | 8171 } |
| 8175 | 8172 |
| 8176 if (combined_type->Is(Type::Receiver())) { | 8173 if (combined_type->Is(Type::Receiver())) { |
| 8177 switch (op) { | 8174 switch (op) { |
| 8178 case Token::EQ: | 8175 case Token::EQ: |
| 8179 case Token::EQ_STRICT: { | 8176 case Token::EQ_STRICT: { |
| 8180 // Can we get away with map check and not instance type check? | 8177 // Can we get away with map check and not instance type check? |
| 8181 if (combined_type->IsClass()) { | 8178 if (combined_type->IsClass()) { |
| 8182 Handle<Map> map = combined_type->AsClass(); | 8179 Handle<Map> map = combined_type->AsClass(); |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8665 environment()->Bind(variable, value); | 8662 environment()->Bind(variable, value); |
| 8666 } | 8663 } |
| 8667 break; | 8664 break; |
| 8668 case Variable::CONTEXT: | 8665 case Variable::CONTEXT: |
| 8669 if (hole_init) { | 8666 if (hole_init) { |
| 8670 HValue* value = graph()->GetConstantHole(); | 8667 HValue* value = graph()->GetConstantHole(); |
| 8671 HValue* context = environment()->LookupContext(); | 8668 HValue* context = environment()->LookupContext(); |
| 8672 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8669 HStoreContextSlot* store = Add<HStoreContextSlot>( |
| 8673 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8670 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
| 8674 if (store->HasObservableSideEffects()) { | 8671 if (store->HasObservableSideEffects()) { |
| 8675 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8672 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
| 8676 } | 8673 } |
| 8677 } | 8674 } |
| 8678 break; | 8675 break; |
| 8679 case Variable::LOOKUP: | 8676 case Variable::LOOKUP: |
| 8680 return Bailout("unsupported lookup slot in declaration"); | 8677 return Bailout("unsupported lookup slot in declaration"); |
| 8681 } | 8678 } |
| 8682 } | 8679 } |
| 8683 | 8680 |
| 8684 | 8681 |
| 8685 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 8682 void HOptimizedGraphBuilder::VisitFunctionDeclaration( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 8703 BindIfLive(variable, value); | 8700 BindIfLive(variable, value); |
| 8704 break; | 8701 break; |
| 8705 } | 8702 } |
| 8706 case Variable::CONTEXT: { | 8703 case Variable::CONTEXT: { |
| 8707 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8704 CHECK_ALIVE(VisitForValue(declaration->fun())); |
| 8708 HValue* value = Pop(); | 8705 HValue* value = Pop(); |
| 8709 HValue* context = environment()->LookupContext(); | 8706 HValue* context = environment()->LookupContext(); |
| 8710 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8707 HStoreContextSlot* store = Add<HStoreContextSlot>( |
| 8711 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8708 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
| 8712 if (store->HasObservableSideEffects()) { | 8709 if (store->HasObservableSideEffects()) { |
| 8713 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8710 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
| 8714 } | 8711 } |
| 8715 break; | 8712 break; |
| 8716 } | 8713 } |
| 8717 case Variable::LOOKUP: | 8714 case Variable::LOOKUP: |
| 8718 return Bailout("unsupported lookup slot in declaration"); | 8715 return Bailout("unsupported lookup slot in declaration"); |
| 8719 } | 8716 } |
| 8720 } | 8717 } |
| 8721 | 8718 |
| 8722 | 8719 |
| 8723 void HOptimizedGraphBuilder::VisitModuleDeclaration( | 8720 void HOptimizedGraphBuilder::VisitModuleDeclaration( |
| (...skipping 1180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9904 if (ShouldProduceTraceOutput()) { | 9901 if (ShouldProduceTraceOutput()) { |
| 9905 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9902 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9906 } | 9903 } |
| 9907 | 9904 |
| 9908 #ifdef DEBUG | 9905 #ifdef DEBUG |
| 9909 graph_->Verify(false); // No full verify. | 9906 graph_->Verify(false); // No full verify. |
| 9910 #endif | 9907 #endif |
| 9911 } | 9908 } |
| 9912 | 9909 |
| 9913 } } // namespace v8::internal | 9910 } } // namespace v8::internal |
| OLD | NEW |