| 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 void HBasicBlock::SetJoinId(BailoutId ast_id) { | 239 void HBasicBlock::SetJoinId(BailoutId ast_id) { |
| 260 int length = predecessors_.length(); | 240 int length = predecessors_.length(); |
| 261 ASSERT(length > 0); | 241 ASSERT(length > 0); |
| 262 for (int i = 0; i < length; i++) { | 242 for (int i = 0; i < length; i++) { |
| 263 HBasicBlock* predecessor = predecessors_[i]; | 243 HBasicBlock* predecessor = predecessors_[i]; |
| 264 ASSERT(predecessor->end()->IsGoto()); | 244 ASSERT(predecessor->end()->IsGoto()); |
| 265 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); | 245 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); |
| 266 ASSERT(i != 0 || | 246 ASSERT(i != 0 || |
| 267 (predecessor->last_environment()->closure().is_null() || | 247 (predecessor->last_environment()->closure().is_null() || |
| 268 predecessor->last_environment()->closure()->shared() | 248 predecessor->last_environment()->closure()->shared() |
| 269 ->VerifyBailoutId(ast_id))); | 249 ->VerifyBailoutId(ast_id))); |
| 270 simulate->set_ast_id(ast_id); | 250 simulate->set_ast_id(ast_id); |
| 271 predecessor->last_environment()->set_ast_id(ast_id); | 251 predecessor->last_environment()->set_ast_id(ast_id); |
| 272 } | 252 } |
| 273 } | 253 } |
| 274 | 254 |
| 275 | 255 |
| 276 bool HBasicBlock::Dominates(HBasicBlock* other) const { | 256 bool HBasicBlock::Dominates(HBasicBlock* other) const { |
| 277 HBasicBlock* current = other->dominator(); | 257 HBasicBlock* current = other->dominator(); |
| 278 while (current != NULL) { | 258 while (current != NULL) { |
| 279 if (current == this) return true; | 259 if (current == this) return true; |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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), |
| 703 did_then_(false), | 683 did_then_(false), |
| 704 did_else_(false), | 684 did_else_(false), |
| 705 did_and_(false), | 685 did_and_(false), |
| 706 did_or_(false), | 686 did_or_(false), |
| 707 captured_(false), | 687 captured_(false), |
| 708 needs_compare_(true), | 688 needs_compare_(true), |
| 709 split_edge_merge_block_(NULL) { | 689 split_edge_merge_block_(NULL), |
| 690 merge_block_(NULL) { |
| 710 HEnvironment* env = builder->environment(); | 691 HEnvironment* env = builder->environment(); |
| 711 first_true_block_ = builder->CreateBasicBlock(env->Copy()); | 692 first_true_block_ = builder->CreateBasicBlock(env->Copy()); |
| 712 last_true_block_ = NULL; | 693 last_true_block_ = NULL; |
| 713 first_false_block_ = builder->CreateBasicBlock(env->Copy()); | 694 first_false_block_ = builder->CreateBasicBlock(env->Copy()); |
| 714 } | 695 } |
| 715 | 696 |
| 716 | 697 |
| 717 HGraphBuilder::IfBuilder::IfBuilder( | 698 HGraphBuilder::IfBuilder::IfBuilder( |
| 718 HGraphBuilder* builder, | 699 HGraphBuilder* builder, |
| 719 HIfContinuation* continuation) | 700 HIfContinuation* continuation) |
| 720 : builder_(builder), | 701 : builder_(builder), |
| 721 position_(RelocInfo::kNoPosition), | 702 position_(RelocInfo::kNoPosition), |
| 722 finished_(false), | 703 finished_(false), |
| 723 did_then_(false), | 704 did_then_(false), |
| 724 did_else_(false), | 705 did_else_(false), |
| 725 did_and_(false), | 706 did_and_(false), |
| 726 did_or_(false), | 707 did_or_(false), |
| 727 captured_(false), | 708 captured_(false), |
| 728 needs_compare_(false), | 709 needs_compare_(false), |
| 729 first_true_block_(NULL), | 710 first_true_block_(NULL), |
| 730 first_false_block_(NULL), | 711 first_false_block_(NULL), |
| 731 split_edge_merge_block_(NULL), | 712 split_edge_merge_block_(NULL), |
| 732 merge_block_(NULL) { | 713 merge_block_(NULL) { |
| 733 continuation->Continue(&first_true_block_, | 714 continuation->Continue(&first_true_block_, |
| 734 &first_false_block_, | 715 &first_false_block_, |
| 735 &position_); | 716 &position_); |
| 736 } | 717 } |
| 737 | 718 |
| 738 | 719 |
| 739 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { | 720 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { |
| 740 if (split_edge_merge_block_ != NULL) { | 721 if (split_edge_merge_block_ != NULL) { |
| 741 HEnvironment* env = first_false_block_->last_environment(); | 722 HEnvironment* env = first_false_block_->last_environment(); |
| 742 HBasicBlock* split_edge = | 723 HBasicBlock* split_edge = |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 ASSERT(!captured_); | 810 ASSERT(!captured_); |
| 830 ASSERT(!finished_); | 811 ASSERT(!finished_); |
| 831 last_true_block_ = builder_->current_block(); | 812 last_true_block_ = builder_->current_block(); |
| 832 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); | 813 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); |
| 833 builder_->set_current_block(first_false_block_); | 814 builder_->set_current_block(first_false_block_); |
| 834 did_else_ = true; | 815 did_else_ = true; |
| 835 } | 816 } |
| 836 | 817 |
| 837 | 818 |
| 838 void HGraphBuilder::IfBuilder::Deopt() { | 819 void HGraphBuilder::IfBuilder::Deopt() { |
| 839 HBasicBlock* block = builder_->current_block(); | 820 builder_->Add<HDeoptimize>(Deoptimizer::EAGER); |
| 840 block->FinishExitWithDeoptimization(HDeoptimize::kUseAll); | |
| 841 builder_->set_current_block(NULL); | |
| 842 if (did_else_) { | |
| 843 first_false_block_ = NULL; | |
| 844 } else { | |
| 845 first_true_block_ = NULL; | |
| 846 } | |
| 847 } | 821 } |
| 848 | 822 |
| 849 | 823 |
| 850 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 824 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
| 851 HBasicBlock* block = builder_->current_block(); | 825 HBasicBlock* block = builder_->current_block(); |
| 852 HValue* context = builder_->environment()->LookupContext(); | 826 HValue* context = builder_->environment()->LookupContext(); |
| 853 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); | 827 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); |
| 854 block->FinishExit(new(zone()) HReturn(value, context, parameter_count)); | 828 block->FinishExit(new(zone()) HReturn(value, context, parameter_count)); |
| 855 builder_->set_current_block(NULL); | 829 builder_->set_current_block(NULL); |
| 856 if (did_else_) { | 830 if (did_else_) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 984 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 958 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 985 ASSERT(current_block() != NULL); | 959 ASSERT(current_block() != NULL); |
| 986 current_block()->AddInstruction(instr); | 960 current_block()->AddInstruction(instr); |
| 987 if (no_side_effects_scope_count_ > 0) { | 961 if (no_side_effects_scope_count_ > 0) { |
| 988 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 962 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
| 989 } | 963 } |
| 990 return instr; | 964 return instr; |
| 991 } | 965 } |
| 992 | 966 |
| 993 | 967 |
| 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) { | 968 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
| 1025 HBasicBlock* b = graph()->CreateBasicBlock(); | 969 HBasicBlock* b = graph()->CreateBasicBlock(); |
| 1026 b->SetInitialEnvironment(env); | 970 b->SetInitialEnvironment(env); |
| 1027 return b; | 971 return b; |
| 1028 } | 972 } |
| 1029 | 973 |
| 1030 | 974 |
| 1031 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 975 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
| 1032 HBasicBlock* header = graph()->CreateBasicBlock(); | 976 HBasicBlock* header = graph()->CreateBasicBlock(); |
| 1033 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 977 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
| 1034 header->SetInitialEnvironment(entry_env); | 978 header->SetInitialEnvironment(entry_env); |
| 1035 header->AttachLoopInformation(); | 979 header->AttachLoopInformation(); |
| 1036 return header; | 980 return header; |
| 1037 } | 981 } |
| 1038 | 982 |
| 1039 | 983 |
| 1040 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { | 984 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { |
| 1041 if (obj->type().IsHeapObject()) return obj; | 985 if (obj->type().IsHeapObject()) return obj; |
| 1042 return Add<HCheckHeapObject>(obj); | 986 return Add<HCheckHeapObject>(obj); |
| 1043 } | 987 } |
| 1044 | 988 |
| 1045 | 989 |
| 990 void HGraphBuilder::Deoptimize(HBasicBlock* continuation) { |
| 991 while (true) { |
| 992 if (continuation->last_environment()->length() > |
| 993 environment()->length()) { |
| 994 environment()->Push(graph()->GetConstantUndefined()); |
| 995 } else if (continuation->last_environment()->length() < |
| 996 environment()->length()) { |
| 997 environment()->Pop(); |
| 998 } else { |
| 999 break; |
| 1000 } |
| 1001 } |
| 1002 Add<HDeoptimize>(Deoptimizer::EAGER); |
| 1003 current_block()->Goto(continuation); |
| 1004 } |
| 1005 |
| 1006 |
| 1046 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, | 1007 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, |
| 1047 Handle<Map> map) { | 1008 Handle<Map> map) { |
| 1048 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); | 1009 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); |
| 1049 AddInstruction(check); | 1010 AddInstruction(check); |
| 1050 return check; | 1011 return check; |
| 1051 } | 1012 } |
| 1052 | 1013 |
| 1053 | |
| 1054 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( | 1014 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( |
| 1055 HValue* external_elements, | 1015 HValue* external_elements, |
| 1056 HValue* checked_key, | 1016 HValue* checked_key, |
| 1057 HValue* val, | 1017 HValue* val, |
| 1058 HValue* dependency, | 1018 HValue* dependency, |
| 1059 ElementsKind elements_kind, | 1019 ElementsKind elements_kind, |
| 1060 bool is_store) { | 1020 bool is_store) { |
| 1061 Zone* zone = this->zone(); | 1021 Zone* zone = this->zone(); |
| 1062 if (is_store) { | 1022 if (is_store) { |
| 1063 ASSERT(val != NULL); | 1023 ASSERT(val != NULL); |
| (...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1722 | 1682 |
| 1723 switch (operation) { | 1683 switch (operation) { |
| 1724 default: | 1684 default: |
| 1725 UNREACHABLE(); | 1685 UNREACHABLE(); |
| 1726 case Token::SUB: { | 1686 case Token::SUB: { |
| 1727 HInstruction* instr = | 1687 HInstruction* instr = |
| 1728 HMul::New(zone(), environment()->LookupContext(), | 1688 HMul::New(zone(), environment()->LookupContext(), |
| 1729 input, graph()->GetConstantMinus1()); | 1689 input, graph()->GetConstantMinus1()); |
| 1730 Representation rep = Representation::FromType(type); | 1690 Representation rep = Representation::FromType(type); |
| 1731 if (type->Is(Type::None())) { | 1691 if (type->Is(Type::None())) { |
| 1732 AddSoftDeoptimize(); | 1692 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 1733 } | 1693 } |
| 1734 if (instr->IsBinaryOperation()) { | 1694 if (instr->IsBinaryOperation()) { |
| 1735 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 1695 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
| 1736 binop->set_observed_input_representation(1, rep); | 1696 binop->set_observed_input_representation(1, rep); |
| 1737 binop->set_observed_input_representation(2, rep); | 1697 binop->set_observed_input_representation(2, rep); |
| 1738 } | 1698 } |
| 1739 return instr; | 1699 return instr; |
| 1740 } | 1700 } |
| 1741 case Token::BIT_NOT: | 1701 case Token::BIT_NOT: |
| 1742 if (type->Is(Type::None())) { | 1702 if (type->Is(Type::None())) { |
| 1743 AddSoftDeoptimize(); | 1703 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 1744 } | 1704 } |
| 1745 return new(zone()) HBitNot(input); | 1705 return new(zone()) HBitNot(input); |
| 1746 } | 1706 } |
| 1747 } | 1707 } |
| 1748 | 1708 |
| 1749 | 1709 |
| 1750 void HGraphBuilder::BuildCompareNil( | 1710 void HGraphBuilder::BuildCompareNil( |
| 1751 HValue* value, | 1711 HValue* value, |
| 1752 Handle<Type> type, | 1712 Handle<Type> type, |
| 1753 int position, | 1713 int position, |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2074 if (loop_successor != NULL) loop_successor->Goto(break_block); | 2034 if (loop_successor != NULL) loop_successor->Goto(break_block); |
| 2075 break_block->SetJoinId(statement->ExitId()); | 2035 break_block->SetJoinId(statement->ExitId()); |
| 2076 return break_block; | 2036 return break_block; |
| 2077 } | 2037 } |
| 2078 return loop_successor; | 2038 return loop_successor; |
| 2079 } | 2039 } |
| 2080 | 2040 |
| 2081 | 2041 |
| 2082 void HBasicBlock::FinishExit(HControlInstruction* instruction) { | 2042 void HBasicBlock::FinishExit(HControlInstruction* instruction) { |
| 2083 Finish(instruction); | 2043 Finish(instruction); |
| 2084 ClearEnvironment(); | |
| 2085 } | 2044 } |
| 2086 | 2045 |
| 2087 | 2046 |
| 2088 HGraph::HGraph(CompilationInfo* info) | 2047 HGraph::HGraph(CompilationInfo* info) |
| 2089 : isolate_(info->isolate()), | 2048 : isolate_(info->isolate()), |
| 2090 next_block_id_(0), | 2049 next_block_id_(0), |
| 2091 entry_block_(NULL), | 2050 entry_block_(NULL), |
| 2092 blocks_(8, info->zone()), | 2051 blocks_(8, info->zone()), |
| 2093 values_(16, info->zone()), | 2052 values_(16, info->zone()), |
| 2094 phi_list_(NULL), | 2053 phi_list_(NULL), |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2641 | 2600 |
| 2642 void TestContext::ReturnValue(HValue* value) { | 2601 void TestContext::ReturnValue(HValue* value) { |
| 2643 BuildBranch(value); | 2602 BuildBranch(value); |
| 2644 } | 2603 } |
| 2645 | 2604 |
| 2646 | 2605 |
| 2647 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2606 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
| 2648 ASSERT(!instr->IsControlInstruction()); | 2607 ASSERT(!instr->IsControlInstruction()); |
| 2649 owner()->AddInstruction(instr); | 2608 owner()->AddInstruction(instr); |
| 2650 if (instr->HasObservableSideEffects()) { | 2609 if (instr->HasObservableSideEffects()) { |
| 2651 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2610 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 2652 } | 2611 } |
| 2653 } | 2612 } |
| 2654 | 2613 |
| 2655 | 2614 |
| 2656 void EffectContext::ReturnControl(HControlInstruction* instr, | 2615 void EffectContext::ReturnControl(HControlInstruction* instr, |
| 2657 BailoutId ast_id) { | 2616 BailoutId ast_id) { |
| 2658 ASSERT(!instr->HasObservableSideEffects()); | 2617 ASSERT(!instr->HasObservableSideEffects()); |
| 2659 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2618 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
| 2660 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2619 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
| 2661 instr->SetSuccessorAt(0, empty_true); | 2620 instr->SetSuccessorAt(0, empty_true); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2683 | 2642 |
| 2684 | 2643 |
| 2685 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2644 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
| 2686 ASSERT(!instr->IsControlInstruction()); | 2645 ASSERT(!instr->IsControlInstruction()); |
| 2687 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2646 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
| 2688 return owner()->Bailout("bad value context for arguments object value"); | 2647 return owner()->Bailout("bad value context for arguments object value"); |
| 2689 } | 2648 } |
| 2690 owner()->AddInstruction(instr); | 2649 owner()->AddInstruction(instr); |
| 2691 owner()->Push(instr); | 2650 owner()->Push(instr); |
| 2692 if (instr->HasObservableSideEffects()) { | 2651 if (instr->HasObservableSideEffects()) { |
| 2693 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2652 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 2694 } | 2653 } |
| 2695 } | 2654 } |
| 2696 | 2655 |
| 2697 | 2656 |
| 2698 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2657 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
| 2699 ASSERT(!instr->HasObservableSideEffects()); | 2658 ASSERT(!instr->HasObservableSideEffects()); |
| 2700 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2659 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
| 2701 return owner()->Bailout("bad value context for arguments object value"); | 2660 return owner()->Bailout("bad value context for arguments object value"); |
| 2702 } | 2661 } |
| 2703 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | 2662 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2739 | 2698 |
| 2740 | 2699 |
| 2741 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2700 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
| 2742 ASSERT(!instr->IsControlInstruction()); | 2701 ASSERT(!instr->IsControlInstruction()); |
| 2743 HOptimizedGraphBuilder* builder = owner(); | 2702 HOptimizedGraphBuilder* builder = owner(); |
| 2744 builder->AddInstruction(instr); | 2703 builder->AddInstruction(instr); |
| 2745 // We expect a simulate after every expression with side effects, though | 2704 // We expect a simulate after every expression with side effects, though |
| 2746 // this one isn't actually needed (and wouldn't work if it were targeted). | 2705 // this one isn't actually needed (and wouldn't work if it were targeted). |
| 2747 if (instr->HasObservableSideEffects()) { | 2706 if (instr->HasObservableSideEffects()) { |
| 2748 builder->Push(instr); | 2707 builder->Push(instr); |
| 2749 builder->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2708 builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 2750 builder->Pop(); | 2709 builder->Pop(); |
| 2751 } | 2710 } |
| 2752 BuildBranch(instr); | 2711 BuildBranch(instr); |
| 2753 } | 2712 } |
| 2754 | 2713 |
| 2755 | 2714 |
| 2756 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2715 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
| 2757 ASSERT(!instr->HasObservableSideEffects()); | 2716 ASSERT(!instr->HasObservableSideEffects()); |
| 2758 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2717 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
| 2759 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2718 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2927 current_block()->Goto(body_entry); | 2886 current_block()->Goto(body_entry); |
| 2928 body_entry->SetJoinId(BailoutId::FunctionEntry()); | 2887 body_entry->SetJoinId(BailoutId::FunctionEntry()); |
| 2929 set_current_block(body_entry); | 2888 set_current_block(body_entry); |
| 2930 | 2889 |
| 2931 // Handle implicit declaration of the function name in named function | 2890 // Handle implicit declaration of the function name in named function |
| 2932 // expressions before other declarations. | 2891 // expressions before other declarations. |
| 2933 if (scope->is_function_scope() && scope->function() != NULL) { | 2892 if (scope->is_function_scope() && scope->function() != NULL) { |
| 2934 VisitVariableDeclaration(scope->function()); | 2893 VisitVariableDeclaration(scope->function()); |
| 2935 } | 2894 } |
| 2936 VisitDeclarations(scope->declarations()); | 2895 VisitDeclarations(scope->declarations()); |
| 2937 AddSimulate(BailoutId::Declarations()); | 2896 Add<HSimulate>(BailoutId::Declarations()); |
| 2938 | 2897 |
| 2939 HValue* context = environment()->LookupContext(); | 2898 HValue* context = environment()->LookupContext(); |
| 2940 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); | 2899 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); |
| 2941 | 2900 |
| 2942 VisitStatements(current_info()->function()->body()); | 2901 VisitStatements(current_info()->function()->body()); |
| 2943 if (HasStackOverflow()) return false; | 2902 if (HasStackOverflow()) return false; |
| 2944 | 2903 |
| 2945 if (current_block() != NULL) { | 2904 if (current_block() != NULL) { |
| 2946 AddReturn(graph()->GetConstantUndefined()); | 2905 Add<HReturn>(graph()->GetConstantUndefined()); |
| 2947 set_current_block(NULL); | 2906 set_current_block(NULL); |
| 2948 } | 2907 } |
| 2949 | 2908 |
| 2950 // If the checksum of the number of type info changes is the same as the | 2909 // If the checksum of the number of type info changes is the same as the |
| 2951 // last time this function was compiled, then this recompile is likely not | 2910 // last time this function was compiled, then this recompile is likely not |
| 2952 // due to missing/inadequate type feedback, but rather too aggressive | 2911 // due to missing/inadequate type feedback, but rather too aggressive |
| 2953 // optimization. Disable optimistic LICM in that case. | 2912 // optimization. Disable optimistic LICM in that case. |
| 2954 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); | 2913 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); |
| 2955 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 2914 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 2956 Handle<TypeFeedbackInfo> type_info( | 2915 Handle<TypeFeedbackInfo> type_info( |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3226 ASSERT(current_block() != NULL); | 3185 ASSERT(current_block() != NULL); |
| 3227 ASSERT(current_block()->HasPredecessor()); | 3186 ASSERT(current_block()->HasPredecessor()); |
| 3228 } | 3187 } |
| 3229 | 3188 |
| 3230 | 3189 |
| 3231 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 3190 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
| 3232 ASSERT(!HasStackOverflow()); | 3191 ASSERT(!HasStackOverflow()); |
| 3233 ASSERT(current_block() != NULL); | 3192 ASSERT(current_block() != NULL); |
| 3234 ASSERT(current_block()->HasPredecessor()); | 3193 ASSERT(current_block()->HasPredecessor()); |
| 3235 if (stmt->condition()->ToBooleanIsTrue()) { | 3194 if (stmt->condition()->ToBooleanIsTrue()) { |
| 3236 AddSimulate(stmt->ThenId()); | 3195 Add<HSimulate>(stmt->ThenId()); |
| 3237 Visit(stmt->then_statement()); | 3196 Visit(stmt->then_statement()); |
| 3238 } else if (stmt->condition()->ToBooleanIsFalse()) { | 3197 } else if (stmt->condition()->ToBooleanIsFalse()) { |
| 3239 AddSimulate(stmt->ElseId()); | 3198 Add<HSimulate>(stmt->ElseId()); |
| 3240 Visit(stmt->else_statement()); | 3199 Visit(stmt->else_statement()); |
| 3241 } else { | 3200 } else { |
| 3242 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 3201 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
| 3243 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 3202 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
| 3244 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); | 3203 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); |
| 3245 | 3204 |
| 3246 if (cond_true->HasPredecessor()) { | 3205 if (cond_true->HasPredecessor()) { |
| 3247 cond_true->SetJoinId(stmt->ThenId()); | 3206 cond_true->SetJoinId(stmt->ThenId()); |
| 3248 set_current_block(cond_true); | 3207 set_current_block(cond_true); |
| 3249 CHECK_BAILOUT(Visit(stmt->then_statement())); | 3208 CHECK_BAILOUT(Visit(stmt->then_statement())); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3336 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 3295 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| 3337 ASSERT(!HasStackOverflow()); | 3296 ASSERT(!HasStackOverflow()); |
| 3338 ASSERT(current_block() != NULL); | 3297 ASSERT(current_block() != NULL); |
| 3339 ASSERT(current_block()->HasPredecessor()); | 3298 ASSERT(current_block()->HasPredecessor()); |
| 3340 FunctionState* state = function_state(); | 3299 FunctionState* state = function_state(); |
| 3341 AstContext* context = call_context(); | 3300 AstContext* context = call_context(); |
| 3342 if (context == NULL) { | 3301 if (context == NULL) { |
| 3343 // Not an inlined return, so an actual one. | 3302 // Not an inlined return, so an actual one. |
| 3344 CHECK_ALIVE(VisitForValue(stmt->expression())); | 3303 CHECK_ALIVE(VisitForValue(stmt->expression())); |
| 3345 HValue* result = environment()->Pop(); | 3304 HValue* result = environment()->Pop(); |
| 3346 AddReturn(result); | 3305 Add<HReturn>(result); |
| 3347 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 3306 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
| 3348 // Return from an inlined construct call. In a test context the return value | 3307 // Return from an inlined construct call. In a test context the return value |
| 3349 // will always evaluate to true, in a value context the return value needs | 3308 // will always evaluate to true, in a value context the return value needs |
| 3350 // to be a JSObject. | 3309 // to be a JSObject. |
| 3351 if (context->IsTest()) { | 3310 if (context->IsTest()) { |
| 3352 TestContext* test = TestContext::cast(context); | 3311 TestContext* test = TestContext::cast(context); |
| 3353 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3312 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
| 3354 current_block()->Goto(test->if_true(), state); | 3313 current_block()->Goto(test->if_true(), state); |
| 3355 } else if (context->IsEffect()) { | 3314 } else if (context->IsEffect()) { |
| 3356 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3315 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3428 } | 3387 } |
| 3429 | 3388 |
| 3430 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); | 3389 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); |
| 3431 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { | 3390 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { |
| 3432 return Bailout("SwitchStatement: mixed or non-literal switch labels"); | 3391 return Bailout("SwitchStatement: mixed or non-literal switch labels"); |
| 3433 } | 3392 } |
| 3434 | 3393 |
| 3435 HValue* context = environment()->LookupContext(); | 3394 HValue* context = environment()->LookupContext(); |
| 3436 | 3395 |
| 3437 CHECK_ALIVE(VisitForValue(stmt->tag())); | 3396 CHECK_ALIVE(VisitForValue(stmt->tag())); |
| 3438 AddSimulate(stmt->EntryId()); | 3397 Add<HSimulate>(stmt->EntryId()); |
| 3439 HValue* tag_value = Pop(); | 3398 HValue* tag_value = Pop(); |
| 3440 HBasicBlock* first_test_block = current_block(); | 3399 HBasicBlock* first_test_block = current_block(); |
| 3441 | 3400 |
| 3442 HUnaryControlInstruction* string_check = NULL; | 3401 HUnaryControlInstruction* string_check = NULL; |
| 3443 HBasicBlock* not_string_block = NULL; | 3402 HBasicBlock* not_string_block = NULL; |
| 3444 | 3403 |
| 3445 // Test switch's tag value if all clauses are string literals | 3404 // Test switch's tag value if all clauses are string literals |
| 3446 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { | 3405 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { |
| 3447 string_check = new(zone()) HIsStringAndBranch(tag_value); | 3406 string_check = new(zone()) HIsStringAndBranch(tag_value); |
| 3448 first_test_block = graph()->CreateBasicBlock(); | 3407 first_test_block = graph()->CreateBasicBlock(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3468 CHECK_ALIVE(VisitForValue(clause->label())); | 3427 CHECK_ALIVE(VisitForValue(clause->label())); |
| 3469 HValue* label_value = Pop(); | 3428 HValue* label_value = Pop(); |
| 3470 | 3429 |
| 3471 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 3430 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
| 3472 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 3431 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
| 3473 | 3432 |
| 3474 HControlInstruction* compare; | 3433 HControlInstruction* compare; |
| 3475 | 3434 |
| 3476 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { | 3435 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { |
| 3477 if (!clause->compare_type()->Is(Type::Smi())) { | 3436 if (!clause->compare_type()->Is(Type::Smi())) { |
| 3478 AddSoftDeoptimize(); | 3437 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 3479 } | 3438 } |
| 3480 | 3439 |
| 3481 HCompareNumericAndBranch* compare_ = | 3440 HCompareNumericAndBranch* compare_ = |
| 3482 new(zone()) HCompareNumericAndBranch(tag_value, | 3441 new(zone()) HCompareNumericAndBranch(tag_value, |
| 3483 label_value, | 3442 label_value, |
| 3484 Token::EQ_STRICT); | 3443 Token::EQ_STRICT); |
| 3485 compare_->set_observed_input_representation( | 3444 compare_->set_observed_input_representation( |
| 3486 Representation::Smi(), Representation::Smi()); | 3445 Representation::Smi(), Representation::Smi()); |
| 3487 compare = compare_; | 3446 compare = compare_; |
| 3488 } else { | 3447 } else { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3518 CaseClause* clause = clauses->at(i); | 3477 CaseClause* clause = clauses->at(i); |
| 3519 | 3478 |
| 3520 // Identify the block where normal (non-fall-through) control flow | 3479 // Identify the block where normal (non-fall-through) control flow |
| 3521 // goes to. | 3480 // goes to. |
| 3522 HBasicBlock* normal_block = NULL; | 3481 HBasicBlock* normal_block = NULL; |
| 3523 if (clause->is_default()) { | 3482 if (clause->is_default()) { |
| 3524 if (last_block != NULL) { | 3483 if (last_block != NULL) { |
| 3525 normal_block = last_block; | 3484 normal_block = last_block; |
| 3526 last_block = NULL; // Cleared to indicate we've handled it. | 3485 last_block = NULL; // Cleared to indicate we've handled it. |
| 3527 } | 3486 } |
| 3528 } else if (!curr_test_block->end()->IsDeoptimize()) { | 3487 } else { |
| 3529 normal_block = curr_test_block->end()->FirstSuccessor(); | 3488 normal_block = curr_test_block->end()->FirstSuccessor(); |
| 3530 curr_test_block = curr_test_block->end()->SecondSuccessor(); | 3489 curr_test_block = curr_test_block->end()->SecondSuccessor(); |
| 3531 } | 3490 } |
| 3532 | 3491 |
| 3533 // Identify a block to emit the body into. | 3492 // Identify a block to emit the body into. |
| 3534 if (normal_block == NULL) { | 3493 if (normal_block == NULL) { |
| 3535 if (fall_through_block == NULL) { | 3494 if (fall_through_block == NULL) { |
| 3536 // (a) Unreachable. | 3495 // (a) Unreachable. |
| 3537 if (clause->is_default()) { | 3496 if (clause->is_default()) { |
| 3538 continue; // Might still be reachable clause bodies. | 3497 continue; // Might still be reachable clause bodies. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3572 break_block->SetJoinId(stmt->ExitId()); | 3531 break_block->SetJoinId(stmt->ExitId()); |
| 3573 set_current_block(break_block); | 3532 set_current_block(break_block); |
| 3574 } | 3533 } |
| 3575 } | 3534 } |
| 3576 | 3535 |
| 3577 | 3536 |
| 3578 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 3537 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
| 3579 HBasicBlock* loop_entry, | 3538 HBasicBlock* loop_entry, |
| 3580 BreakAndContinueInfo* break_info) { | 3539 BreakAndContinueInfo* break_info) { |
| 3581 BreakAndContinueScope push(break_info, this); | 3540 BreakAndContinueScope push(break_info, this); |
| 3582 AddSimulate(stmt->StackCheckId()); | 3541 Add<HSimulate>(stmt->StackCheckId()); |
| 3583 HValue* context = environment()->LookupContext(); | 3542 HValue* context = environment()->LookupContext(); |
| 3584 HStackCheck* stack_check = Add<HStackCheck>( | 3543 HStackCheck* stack_check = Add<HStackCheck>( |
| 3585 context, HStackCheck::kBackwardsBranch); | 3544 context, HStackCheck::kBackwardsBranch); |
| 3586 ASSERT(loop_entry->IsLoopHeader()); | 3545 ASSERT(loop_entry->IsLoopHeader()); |
| 3587 loop_entry->loop_information()->set_stack_check(stack_check); | 3546 loop_entry->loop_information()->set_stack_check(stack_check); |
| 3588 CHECK_BAILOUT(Visit(stmt->body())); | 3547 CHECK_BAILOUT(Visit(stmt->body())); |
| 3589 } | 3548 } |
| 3590 | 3549 |
| 3591 | 3550 |
| 3592 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 3551 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3733 return Bailout("ForInStatement with non-local each variable"); | 3692 return Bailout("ForInStatement with non-local each variable"); |
| 3734 } | 3693 } |
| 3735 | 3694 |
| 3736 Variable* each_var = stmt->each()->AsVariableProxy()->var(); | 3695 Variable* each_var = stmt->each()->AsVariableProxy()->var(); |
| 3737 | 3696 |
| 3738 CHECK_ALIVE(VisitForValue(stmt->enumerable())); | 3697 CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
| 3739 HValue* enumerable = Top(); // Leave enumerable at the top. | 3698 HValue* enumerable = Top(); // Leave enumerable at the top. |
| 3740 | 3699 |
| 3741 HInstruction* map = Add<HForInPrepareMap>( | 3700 HInstruction* map = Add<HForInPrepareMap>( |
| 3742 environment()->LookupContext(), enumerable); | 3701 environment()->LookupContext(), enumerable); |
| 3743 AddSimulate(stmt->PrepareId()); | 3702 Add<HSimulate>(stmt->PrepareId()); |
| 3744 | 3703 |
| 3745 HInstruction* array = Add<HForInCacheArray>( | 3704 HInstruction* array = Add<HForInCacheArray>( |
| 3746 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); | 3705 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); |
| 3747 | 3706 |
| 3748 HInstruction* enum_length = Add<HMapEnumLength>(map); | 3707 HInstruction* enum_length = Add<HMapEnumLength>(map); |
| 3749 | 3708 |
| 3750 HInstruction* start_index = Add<HConstant>(0); | 3709 HInstruction* start_index = Add<HConstant>(0); |
| 3751 | 3710 |
| 3752 Push(map); | 3711 Push(map); |
| 3753 Push(array); | 3712 Push(array); |
| (...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4330 Handle<JSObject> holder; | 4289 Handle<JSObject> holder; |
| 4331 ASSERT(!LookupSetter(map, name, &setter, &holder)); | 4290 ASSERT(!LookupSetter(map, name, &setter, &holder)); |
| 4332 #endif | 4291 #endif |
| 4333 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, | 4292 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, |
| 4334 name, | 4293 name, |
| 4335 value, | 4294 value, |
| 4336 map)); | 4295 map)); |
| 4337 } | 4296 } |
| 4338 AddInstruction(store); | 4297 AddInstruction(store); |
| 4339 if (store->HasObservableSideEffects()) { | 4298 if (store->HasObservableSideEffects()) { |
| 4340 AddSimulate(key->id(), REMOVABLE_SIMULATE); | 4299 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
| 4341 } | 4300 } |
| 4342 } else { | 4301 } else { |
| 4343 CHECK_ALIVE(VisitForEffect(value)); | 4302 CHECK_ALIVE(VisitForEffect(value)); |
| 4344 } | 4303 } |
| 4345 break; | 4304 break; |
| 4346 } | 4305 } |
| 4347 // Fall through. | 4306 // Fall through. |
| 4348 case ObjectLiteral::Property::PROTOTYPE: | 4307 case ObjectLiteral::Property::PROTOTYPE: |
| 4349 case ObjectLiteral::Property::SETTER: | 4308 case ObjectLiteral::Property::SETTER: |
| 4350 case ObjectLiteral::Property::GETTER: | 4309 case ObjectLiteral::Property::GETTER: |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4495 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, | 4454 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, |
| 4496 boilerplate_elements_kind); | 4455 boilerplate_elements_kind); |
| 4497 instr->SetUninitialized(uninitialized); | 4456 instr->SetUninitialized(uninitialized); |
| 4498 break; | 4457 break; |
| 4499 } | 4458 } |
| 4500 default: | 4459 default: |
| 4501 UNREACHABLE(); | 4460 UNREACHABLE(); |
| 4502 break; | 4461 break; |
| 4503 } | 4462 } |
| 4504 | 4463 |
| 4505 AddSimulate(expr->GetIdForElement(i)); | 4464 Add<HSimulate>(expr->GetIdForElement(i)); |
| 4506 } | 4465 } |
| 4507 | 4466 |
| 4508 Drop(1); // array literal index | 4467 Drop(1); // array literal index |
| 4509 return ast_context()->ReturnValue(Pop()); | 4468 return ast_context()->ReturnValue(Pop()); |
| 4510 } | 4469 } |
| 4511 | 4470 |
| 4512 | 4471 |
| 4513 // Sets the lookup result and returns true if the load/store can be inlined. | 4472 // Sets the lookup result and returns true if the load/store can be inlined. |
| 4514 static bool ComputeLoadStoreField(Handle<Map> type, | 4473 static bool ComputeLoadStoreField(Handle<Map> type, |
| 4515 Handle<String> name, | 4474 Handle<String> name, |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4826 AddInstruction(HCheckMaps::New(object, types, zone())); | 4785 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 4827 HInstruction* store; | 4786 HInstruction* store; |
| 4828 CHECK_ALIVE_OR_RETURN( | 4787 CHECK_ALIVE_OR_RETURN( |
| 4829 store = BuildStoreNamedField( | 4788 store = BuildStoreNamedField( |
| 4830 object, name, store_value, types->at(count - 1), &lookup), | 4789 object, name, store_value, types->at(count - 1), &lookup), |
| 4831 true); | 4790 true); |
| 4832 if (result_value != NULL) Push(result_value); | 4791 if (result_value != NULL) Push(result_value); |
| 4833 Push(store_value); | 4792 Push(store_value); |
| 4834 store->set_position(position); | 4793 store->set_position(position); |
| 4835 AddInstruction(store); | 4794 AddInstruction(store); |
| 4836 AddSimulate(assignment_id); | 4795 Add<HSimulate>(assignment_id); |
| 4837 if (result_value != NULL) Drop(1); | 4796 if (result_value != NULL) Drop(1); |
| 4838 ast_context()->ReturnValue(Pop()); | 4797 ast_context()->ReturnValue(Pop()); |
| 4839 return true; | 4798 return true; |
| 4840 } | 4799 } |
| 4841 | 4800 |
| 4842 | 4801 |
| 4802 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedFieldHelper( |
| 4803 HValue* object, |
| 4804 Handle<String> name, |
| 4805 HValue* value, |
| 4806 SmallMapList* types, |
| 4807 int current_type, |
| 4808 int stored_count, |
| 4809 int position) { |
| 4810 HInstruction* instr = NULL; |
| 4811 if (stored_count == kMaxStorePolymorphism || |
| 4812 (current_type == types->length() - 1)) { |
| 4813 if (FLAG_deoptimize_uncommon_cases) { |
| 4814 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 4815 } else { |
| 4816 instr = BuildStoreNamedGeneric(object, name, value); |
| 4817 instr->set_position(position); |
| 4818 AddInstruction(instr); |
| 4819 } |
| 4820 return; |
| 4821 } |
| 4822 |
| 4823 Handle<Map> map = types->at(current_type); |
| 4824 LookupResult lookup(isolate()); |
| 4825 if (!ComputeLoadStoreField(map, name, &lookup, true)) { |
| 4826 HandlePolymorphicStoreNamedFieldHelper(object, name, value, types, |
| 4827 current_type + 1, stored_count, |
| 4828 position); |
| 4829 return; |
| 4830 } |
| 4831 |
| 4832 IfBuilder builder(this); |
| 4833 builder.If<HCompareMap>(object, map); |
| 4834 |
| 4835 builder.Then(); |
| 4836 CHECK_ALIVE(instr = BuildStoreNamedField(object, name, value, map, &lookup)); |
| 4837 instr->set_position(position); |
| 4838 AddInstruction(instr); |
| 4839 |
| 4840 builder.Else(); |
| 4841 HandlePolymorphicStoreNamedFieldHelper(object, name, value, types, |
| 4842 current_type + 1, stored_count + 1, |
| 4843 position); |
| 4844 builder.End(); |
| 4845 } |
| 4846 |
| 4847 |
| 4843 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 4848 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| 4844 BailoutId id, | 4849 BailoutId id, |
| 4845 int position, | 4850 int position, |
| 4846 BailoutId assignment_id, | 4851 BailoutId assignment_id, |
| 4847 HValue* object, | 4852 HValue* object, |
| 4848 HValue* store_value, | 4853 HValue* store_value, |
| 4849 HValue* result_value, | 4854 HValue* result_value, |
| 4850 SmallMapList* types, | 4855 SmallMapList* types, |
| 4851 Handle<String> name) { | 4856 Handle<String> name) { |
| 4852 if (TryStorePolymorphicAsMonomorphic( | 4857 if (TryStorePolymorphicAsMonomorphic( |
| 4853 position, assignment_id, object, | 4858 position, assignment_id, object, |
| 4854 store_value, result_value, types, name)) { | 4859 store_value, result_value, types, name)) { |
| 4855 return; | 4860 return; |
| 4856 } | 4861 } |
| 4857 | 4862 |
| 4858 // TODO(ager): We should recognize when the prototype chains for different | 4863 { |
| 4859 // maps are identical. In that case we can avoid repeatedly generating the | 4864 Add<HCheckHeapObject>(object); |
| 4860 // same prototype map checks. | 4865 NoObservableSideEffectsScope no_effects(this); |
| 4861 int count = 0; | 4866 HandlePolymorphicStoreNamedFieldHelper(object, name, store_value, types, |
| 4862 HBasicBlock* join = NULL; | 4867 0, 0, position); |
| 4863 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | |
| 4864 Handle<Map> map = types->at(i); | |
| 4865 LookupResult lookup(isolate()); | |
| 4866 if (ComputeLoadStoreField(map, name, &lookup, true)) { | |
| 4867 if (count == 0) { | |
| 4868 BuildCheckHeapObject(object); | |
| 4869 join = graph()->CreateBasicBlock(); | |
| 4870 } | |
| 4871 ++count; | |
| 4872 HBasicBlock* if_true = graph()->CreateBasicBlock(); | |
| 4873 HBasicBlock* if_false = graph()->CreateBasicBlock(); | |
| 4874 HCompareMap* compare = | |
| 4875 new(zone()) HCompareMap(object, map, if_true, if_false); | |
| 4876 current_block()->Finish(compare); | |
| 4877 | |
| 4878 set_current_block(if_true); | |
| 4879 HInstruction* instr; | |
| 4880 CHECK_ALIVE(instr = BuildStoreNamedField( | |
| 4881 object, name, store_value, map, &lookup)); | |
| 4882 instr->set_position(position); | |
| 4883 // Goto will add the HSimulate for the store. | |
| 4884 AddInstruction(instr); | |
| 4885 if (!ast_context()->IsEffect()) { | |
| 4886 if (result_value != NULL) Push(result_value); | |
| 4887 Push(store_value); | |
| 4888 } | |
| 4889 current_block()->Goto(join); | |
| 4890 | |
| 4891 set_current_block(if_false); | |
| 4892 } | |
| 4893 } | 4868 } |
| 4894 | 4869 |
| 4895 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 4870 if (ast_context()->IsEffect()) { |
| 4896 // know about and do not want to handle ones we've never seen. Otherwise | 4871 Add<HSimulate>(id, REMOVABLE_SIMULATE); |
| 4897 // use a generic IC. | |
| 4898 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | |
| 4899 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | |
| 4900 } else { | 4872 } else { |
| 4901 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); | 4873 if (result_value != NULL) Push(result_value); |
| 4902 instr->set_position(position); | 4874 Push(store_value); |
| 4903 AddInstruction(instr); | 4875 Add<HSimulate>(id, REMOVABLE_SIMULATE); |
| 4904 | |
| 4905 if (join != NULL) { | |
| 4906 if (!ast_context()->IsEffect()) { | |
| 4907 if (result_value != NULL) Push(result_value); | |
| 4908 Push(store_value); | |
| 4909 } | |
| 4910 current_block()->Goto(join); | |
| 4911 } else { | |
| 4912 // The HSimulate for the store should not see the stored value in | |
| 4913 // effect contexts (it is not materialized at expr->id() in the | |
| 4914 // unoptimized code). | |
| 4915 if (instr->HasObservableSideEffects()) { | |
| 4916 if (ast_context()->IsEffect()) { | |
| 4917 AddSimulate(id, REMOVABLE_SIMULATE); | |
| 4918 } else { | |
| 4919 if (result_value != NULL) Push(result_value); | |
| 4920 Push(store_value); | |
| 4921 AddSimulate(id, REMOVABLE_SIMULATE); | |
| 4922 Drop(result_value != NULL ? 2 : 1); | |
| 4923 } | |
| 4924 } | |
| 4925 return ast_context()->ReturnValue( | |
| 4926 result_value != NULL ? result_value : store_value); | |
| 4927 } | |
| 4928 } | |
| 4929 | |
| 4930 ASSERT(join != NULL); | |
| 4931 join->SetJoinId(id); | |
| 4932 set_current_block(join); | |
| 4933 if (!ast_context()->IsEffect()) { | |
| 4934 if (result_value != NULL) Drop(1); | 4876 if (result_value != NULL) Drop(1); |
| 4935 ast_context()->ReturnValue(Pop()); | 4877 ast_context()->ReturnValue(Pop()); |
| 4936 } | 4878 } |
| 4937 } | 4879 } |
| 4938 | 4880 |
| 4939 | 4881 |
| 4940 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 4882 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 4941 Property* prop = expr->target()->AsProperty(); | 4883 Property* prop = expr->target()->AsProperty(); |
| 4942 ASSERT(prop != NULL); | 4884 ASSERT(prop != NULL); |
| 4943 CHECK_ALIVE(VisitForValue(prop->obj())); | 4885 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 4944 | 4886 |
| 4945 if (prop->key()->IsPropertyName()) { | 4887 if (prop->key()->IsPropertyName()) { |
| 4946 // Named store. | 4888 // Named store. |
| 4947 CHECK_ALIVE(VisitForValue(expr->value())); | 4889 CHECK_ALIVE(VisitForValue(expr->value())); |
| 4948 HValue* value = environment()->ExpressionStackAt(0); | 4890 HValue* value = environment()->ExpressionStackAt(0); |
| 4949 HValue* object = environment()->ExpressionStackAt(1); | 4891 HValue* object = environment()->ExpressionStackAt(1); |
| 4950 | 4892 |
| 4951 if (expr->IsUninitialized()) AddSoftDeoptimize(); | 4893 if (expr->IsUninitialized()) Add<HDeoptimize>(Deoptimizer::SOFT); |
| 4952 return BuildStoreNamed(expr, expr->id(), expr->position(), | 4894 return BuildStoreNamed(expr, expr->id(), expr->position(), |
| 4953 expr->AssignmentId(), prop, object, value); | 4895 expr->AssignmentId(), prop, object, value); |
| 4954 } else { | 4896 } else { |
| 4955 // Keyed store. | 4897 // Keyed store. |
| 4956 CHECK_ALIVE(VisitForValue(prop->key())); | 4898 CHECK_ALIVE(VisitForValue(prop->key())); |
| 4957 CHECK_ALIVE(VisitForValue(expr->value())); | 4899 CHECK_ALIVE(VisitForValue(expr->value())); |
| 4958 HValue* value = environment()->ExpressionStackAt(0); | 4900 HValue* value = environment()->ExpressionStackAt(0); |
| 4959 HValue* key = environment()->ExpressionStackAt(1); | 4901 HValue* key = environment()->ExpressionStackAt(1); |
| 4960 HValue* object = environment()->ExpressionStackAt(2); | 4902 HValue* object = environment()->ExpressionStackAt(2); |
| 4961 bool has_side_effects = false; | 4903 bool has_side_effects = false; |
| 4962 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 4904 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
| 4963 expr->position(), | 4905 expr->position(), |
| 4964 true, // is_store | 4906 true, // is_store |
| 4965 &has_side_effects); | 4907 &has_side_effects); |
| 4966 Drop(3); | 4908 Drop(3); |
| 4967 Push(value); | 4909 Push(value); |
| 4968 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 4910 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 4969 return ast_context()->ReturnValue(Pop()); | 4911 return ast_context()->ReturnValue(Pop()); |
| 4970 } | 4912 } |
| 4971 } | 4913 } |
| 4972 | 4914 |
| 4973 | 4915 |
| 4974 // Because not every expression has a position and there is not common | 4916 // Because not every expression has a position and there is not common |
| 4975 // superclass of Assignment and CountOperation, we cannot just pass the | 4917 // superclass of Assignment and CountOperation, we cannot just pass the |
| 4976 // owning expression instead of position and ast_id separately. | 4918 // owning expression instead of position and ast_id separately. |
| 4977 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 4919 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 4978 Variable* var, | 4920 Variable* var, |
| 4979 HValue* value, | 4921 HValue* value, |
| 4980 int position, | 4922 int position, |
| 4981 BailoutId ast_id) { | 4923 BailoutId ast_id) { |
| 4982 LookupResult lookup(isolate()); | 4924 LookupResult lookup(isolate()); |
| 4983 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 4925 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 4984 if (type == kUseCell) { | 4926 if (type == kUseCell) { |
| 4985 Handle<GlobalObject> global(current_info()->global_object()); | 4927 Handle<GlobalObject> global(current_info()->global_object()); |
| 4986 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 4928 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 4987 if (cell->type()->IsConstant()) { | 4929 if (cell->type()->IsConstant()) { |
| 4988 IfBuilder builder(this); | 4930 IfBuilder builder(this); |
| 4989 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); | 4931 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); |
| 4990 if (cell->type()->AsConstant()->IsNumber()) { | 4932 if (cell->type()->AsConstant()->IsNumber()) { |
| 4991 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); | 4933 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); |
| 4992 } else { | 4934 } else { |
| 4993 builder.If<HCompareObjectEqAndBranch>(value, constant); | 4935 builder.If<HCompareObjectEqAndBranch>(value, constant); |
| 4994 } | 4936 } |
| 4995 builder.Then(); | 4937 builder.Then(); |
| 4996 builder.Else(); | 4938 builder.Else(); |
| 4997 AddSoftDeoptimize(MUST_EMIT_SOFT_DEOPT); | 4939 Add<HDeoptimize>(Deoptimizer::EAGER); |
| 4998 builder.End(); | 4940 builder.End(); |
| 4999 } | 4941 } |
| 5000 HInstruction* instr = | 4942 HInstruction* instr = |
| 5001 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | 4943 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
| 5002 instr->set_position(position); | 4944 instr->set_position(position); |
| 5003 if (instr->HasObservableSideEffects()) { | 4945 if (instr->HasObservableSideEffects()) { |
| 5004 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 4946 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5005 } | 4947 } |
| 5006 } else { | 4948 } else { |
| 5007 HValue* context = environment()->LookupContext(); | 4949 HValue* context = environment()->LookupContext(); |
| 5008 HGlobalObject* global_object = Add<HGlobalObject>(context); | 4950 HGlobalObject* global_object = Add<HGlobalObject>(context); |
| 5009 HStoreGlobalGeneric* instr = | 4951 HStoreGlobalGeneric* instr = |
| 5010 Add<HStoreGlobalGeneric>(context, global_object, var->name(), | 4952 Add<HStoreGlobalGeneric>(context, global_object, var->name(), |
| 5011 value, function_strict_mode_flag()); | 4953 value, function_strict_mode_flag()); |
| 5012 instr->set_position(position); | 4954 instr->set_position(position); |
| 5013 ASSERT(instr->HasObservableSideEffects()); | 4955 ASSERT(instr->HasObservableSideEffects()); |
| 5014 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 4956 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5015 } | 4957 } |
| 5016 } | 4958 } |
| 5017 | 4959 |
| 5018 | 4960 |
| 5019 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, | 4961 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, |
| 5020 BailoutId id, | 4962 BailoutId id, |
| 5021 int position, | 4963 int position, |
| 5022 BailoutId assignment_id, | 4964 BailoutId assignment_id, |
| 5023 Property* prop, | 4965 Property* prop, |
| 5024 HValue* object, | 4966 HValue* object, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5067 } else { | 5009 } else { |
| 5068 Drop(2); | 5010 Drop(2); |
| 5069 instr = BuildStoreNamedGeneric(object, name, store_value); | 5011 instr = BuildStoreNamedGeneric(object, name, store_value); |
| 5070 } | 5012 } |
| 5071 | 5013 |
| 5072 if (result_value != NULL) Push(result_value); | 5014 if (result_value != NULL) Push(result_value); |
| 5073 Push(store_value); | 5015 Push(store_value); |
| 5074 instr->set_position(position); | 5016 instr->set_position(position); |
| 5075 AddInstruction(instr); | 5017 AddInstruction(instr); |
| 5076 if (instr->HasObservableSideEffects()) { | 5018 if (instr->HasObservableSideEffects()) { |
| 5077 AddSimulate(assignment_id, REMOVABLE_SIMULATE); | 5019 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
| 5078 } | 5020 } |
| 5079 if (result_value != NULL) Drop(1); | 5021 if (result_value != NULL) Drop(1); |
| 5080 return ast_context()->ReturnValue(Pop()); | 5022 return ast_context()->ReturnValue(Pop()); |
| 5081 } | 5023 } |
| 5082 | 5024 |
| 5083 | 5025 |
| 5084 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5026 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 5085 Expression* target = expr->target(); | 5027 Expression* target = expr->target(); |
| 5086 VariableProxy* proxy = target->AsVariableProxy(); | 5028 VariableProxy* proxy = target->AsVariableProxy(); |
| 5087 Property* prop = target->AsProperty(); | 5029 Property* prop = target->AsProperty(); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5145 // perform checks here | 5087 // perform checks here |
| 5146 UNREACHABLE(); | 5088 UNREACHABLE(); |
| 5147 default: | 5089 default: |
| 5148 mode = HStoreContextSlot::kNoCheck; | 5090 mode = HStoreContextSlot::kNoCheck; |
| 5149 } | 5091 } |
| 5150 | 5092 |
| 5151 HValue* context = BuildContextChainWalk(var); | 5093 HValue* context = BuildContextChainWalk(var); |
| 5152 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5094 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
| 5153 mode, Top()); | 5095 mode, Top()); |
| 5154 if (instr->HasObservableSideEffects()) { | 5096 if (instr->HasObservableSideEffects()) { |
| 5155 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5097 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5156 } | 5098 } |
| 5157 break; | 5099 break; |
| 5158 } | 5100 } |
| 5159 | 5101 |
| 5160 case Variable::LOOKUP: | 5102 case Variable::LOOKUP: |
| 5161 return Bailout("compound assignment to lookup slot"); | 5103 return Bailout("compound assignment to lookup slot"); |
| 5162 } | 5104 } |
| 5163 return ast_context()->ReturnValue(Pop()); | 5105 return ast_context()->ReturnValue(Pop()); |
| 5164 | 5106 |
| 5165 } else if (prop != NULL) { | 5107 } else if (prop != NULL) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 5186 load = BuildCallGetter(object, map, getter, holder); | 5128 load = BuildCallGetter(object, map, getter, holder); |
| 5187 } else { | 5129 } else { |
| 5188 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 5130 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
| 5189 } | 5131 } |
| 5190 } else if (types != NULL && types->length() > 1) { | 5132 } else if (types != NULL && types->length() > 1) { |
| 5191 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); | 5133 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
| 5192 } | 5134 } |
| 5193 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); | 5135 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
| 5194 PushAndAdd(load); | 5136 PushAndAdd(load); |
| 5195 if (load->HasObservableSideEffects()) { | 5137 if (load->HasObservableSideEffects()) { |
| 5196 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 5138 Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
| 5197 } | 5139 } |
| 5198 | 5140 |
| 5199 CHECK_ALIVE(VisitForValue(expr->value())); | 5141 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5200 HValue* right = Pop(); | 5142 HValue* right = Pop(); |
| 5201 HValue* left = Pop(); | 5143 HValue* left = Pop(); |
| 5202 | 5144 |
| 5203 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5145 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5204 PushAndAdd(instr); | 5146 PushAndAdd(instr); |
| 5205 if (instr->HasObservableSideEffects()) { | 5147 if (instr->HasObservableSideEffects()) { |
| 5206 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 5148 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
| 5207 } | 5149 } |
| 5208 | 5150 |
| 5209 return BuildStoreNamed(prop, expr->id(), expr->position(), | 5151 return BuildStoreNamed(prop, expr->id(), expr->position(), |
| 5210 expr->AssignmentId(), prop, object, instr); | 5152 expr->AssignmentId(), prop, object, instr); |
| 5211 } else { | 5153 } else { |
| 5212 // Keyed property. | 5154 // Keyed property. |
| 5213 CHECK_ALIVE(VisitForValue(prop->obj())); | 5155 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5214 CHECK_ALIVE(VisitForValue(prop->key())); | 5156 CHECK_ALIVE(VisitForValue(prop->key())); |
| 5215 HValue* obj = environment()->ExpressionStackAt(1); | 5157 HValue* obj = environment()->ExpressionStackAt(1); |
| 5216 HValue* key = environment()->ExpressionStackAt(0); | 5158 HValue* key = environment()->ExpressionStackAt(0); |
| 5217 | 5159 |
| 5218 bool has_side_effects = false; | 5160 bool has_side_effects = false; |
| 5219 HValue* load = HandleKeyedElementAccess( | 5161 HValue* load = HandleKeyedElementAccess( |
| 5220 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 5162 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
| 5221 false, // is_store | 5163 false, // is_store |
| 5222 &has_side_effects); | 5164 &has_side_effects); |
| 5223 Push(load); | 5165 Push(load); |
| 5224 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 5166 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
| 5225 | 5167 |
| 5226 CHECK_ALIVE(VisitForValue(expr->value())); | 5168 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5227 HValue* right = Pop(); | 5169 HValue* right = Pop(); |
| 5228 HValue* left = Pop(); | 5170 HValue* left = Pop(); |
| 5229 | 5171 |
| 5230 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5172 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5231 PushAndAdd(instr); | 5173 PushAndAdd(instr); |
| 5232 if (instr->HasObservableSideEffects()) { | 5174 if (instr->HasObservableSideEffects()) { |
| 5233 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 5175 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
| 5234 } | 5176 } |
| 5235 | 5177 |
| 5236 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), | 5178 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), |
| 5237 RelocInfo::kNoPosition, | 5179 RelocInfo::kNoPosition, |
| 5238 true, // is_store | 5180 true, // is_store |
| 5239 &has_side_effects); | 5181 &has_side_effects); |
| 5240 | 5182 |
| 5241 // Drop the simulated receiver, key, and value. Return the value. | 5183 // Drop the simulated receiver, key, and value. Return the value. |
| 5242 Drop(3); | 5184 Drop(3); |
| 5243 Push(instr); | 5185 Push(instr); |
| 5244 ASSERT(has_side_effects); // Stores always have side effects. | 5186 ASSERT(has_side_effects); // Stores always have side effects. |
| 5245 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5187 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5246 return ast_context()->ReturnValue(Pop()); | 5188 return ast_context()->ReturnValue(Pop()); |
| 5247 } | 5189 } |
| 5248 | 5190 |
| 5249 } else { | 5191 } else { |
| 5250 return Bailout("invalid lhs in compound assignment"); | 5192 return Bailout("invalid lhs in compound assignment"); |
| 5251 } | 5193 } |
| 5252 } | 5194 } |
| 5253 | 5195 |
| 5254 | 5196 |
| 5255 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 5197 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5357 } else { | 5299 } else { |
| 5358 ASSERT(expr->op() == Token::INIT_CONST); | 5300 ASSERT(expr->op() == Token::INIT_CONST); |
| 5359 | 5301 |
| 5360 mode = HStoreContextSlot::kCheckIgnoreAssignment; | 5302 mode = HStoreContextSlot::kCheckIgnoreAssignment; |
| 5361 } | 5303 } |
| 5362 | 5304 |
| 5363 HValue* context = BuildContextChainWalk(var); | 5305 HValue* context = BuildContextChainWalk(var); |
| 5364 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5306 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
| 5365 mode, Top()); | 5307 mode, Top()); |
| 5366 if (instr->HasObservableSideEffects()) { | 5308 if (instr->HasObservableSideEffects()) { |
| 5367 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5309 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5368 } | 5310 } |
| 5369 return ast_context()->ReturnValue(Pop()); | 5311 return ast_context()->ReturnValue(Pop()); |
| 5370 } | 5312 } |
| 5371 | 5313 |
| 5372 case Variable::LOOKUP: | 5314 case Variable::LOOKUP: |
| 5373 return Bailout("assignment to LOOKUP variable"); | 5315 return Bailout("assignment to LOOKUP variable"); |
| 5374 } | 5316 } |
| 5375 } else { | 5317 } else { |
| 5376 return Bailout("invalid left-hand side in assignment"); | 5318 return Bailout("invalid left-hand side in assignment"); |
| 5377 } | 5319 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5391 // We don't optimize functions with invalid left-hand sides in | 5333 // We don't optimize functions with invalid left-hand sides in |
| 5392 // assignments, count operations, or for-in. Consequently throw can | 5334 // assignments, count operations, or for-in. Consequently throw can |
| 5393 // currently only occur in an effect context. | 5335 // currently only occur in an effect context. |
| 5394 ASSERT(ast_context()->IsEffect()); | 5336 ASSERT(ast_context()->IsEffect()); |
| 5395 CHECK_ALIVE(VisitForValue(expr->exception())); | 5337 CHECK_ALIVE(VisitForValue(expr->exception())); |
| 5396 | 5338 |
| 5397 HValue* context = environment()->LookupContext(); | 5339 HValue* context = environment()->LookupContext(); |
| 5398 HValue* value = environment()->Pop(); | 5340 HValue* value = environment()->Pop(); |
| 5399 HThrow* instr = Add<HThrow>(context, value); | 5341 HThrow* instr = Add<HThrow>(context, value); |
| 5400 instr->set_position(expr->position()); | 5342 instr->set_position(expr->position()); |
| 5401 AddSimulate(expr->id()); | 5343 Add<HSimulate>(expr->id()); |
| 5402 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5344 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 5403 set_current_block(NULL); | 5345 set_current_block(NULL); |
| 5404 } | 5346 } |
| 5405 | 5347 |
| 5406 | 5348 |
| 5407 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( | 5349 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( |
| 5408 HValue* object, | 5350 HValue* object, |
| 5409 HObjectAccess access, | 5351 HObjectAccess access, |
| 5410 Representation representation) { | 5352 Representation representation) { |
| 5411 bool load_double = false; | 5353 bool load_double = false; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5423 } | 5365 } |
| 5424 return field; | 5366 return field; |
| 5425 } | 5367 } |
| 5426 | 5368 |
| 5427 | 5369 |
| 5428 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5370 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
| 5429 HValue* object, | 5371 HValue* object, |
| 5430 Handle<String> name, | 5372 Handle<String> name, |
| 5431 Property* expr) { | 5373 Property* expr) { |
| 5432 if (expr->IsUninitialized()) { | 5374 if (expr->IsUninitialized()) { |
| 5433 AddSoftDeoptimize(); | 5375 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 5434 } | 5376 } |
| 5435 HValue* context = environment()->LookupContext(); | 5377 HValue* context = environment()->LookupContext(); |
| 5436 return new(zone()) HLoadNamedGeneric(context, object, name); | 5378 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 5437 } | 5379 } |
| 5438 | 5380 |
| 5439 | 5381 |
| 5440 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 5382 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
| 5441 HValue* object, | 5383 HValue* object, |
| 5442 Handle<Map> map, | 5384 Handle<Map> map, |
| 5443 Handle<JSFunction> getter, | 5385 Handle<JSFunction> getter, |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5807 if (position != RelocInfo::kNoPosition) access->set_position(position); | 5749 if (position != RelocInfo::kNoPosition) access->set_position(position); |
| 5808 if (!is_store) { | 5750 if (!is_store) { |
| 5809 Push(access); | 5751 Push(access); |
| 5810 } | 5752 } |
| 5811 current_block()->GotoNoSimulate(join); | 5753 current_block()->GotoNoSimulate(join); |
| 5812 set_current_block(if_false); | 5754 set_current_block(if_false); |
| 5813 } | 5755 } |
| 5814 } | 5756 } |
| 5815 | 5757 |
| 5816 // Deopt if none of the cases matched. | 5758 // Deopt if none of the cases matched. |
| 5817 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 5759 Deoptimize(join); |
| 5818 set_current_block(join); | 5760 set_current_block(join); |
| 5819 return is_store ? NULL : Pop(); | 5761 return is_store ? NULL : Pop(); |
| 5820 } | 5762 } |
| 5821 | 5763 |
| 5822 | 5764 |
| 5823 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 5765 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
| 5824 HValue* obj, | 5766 HValue* obj, |
| 5825 HValue* key, | 5767 HValue* key, |
| 5826 HValue* val, | 5768 HValue* val, |
| 5827 Expression* expr, | 5769 Expression* expr, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5843 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | 5785 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); |
| 5844 } | 5786 } |
| 5845 } else if (expr->GetReceiverTypes() != NULL && | 5787 } else if (expr->GetReceiverTypes() != NULL && |
| 5846 !expr->GetReceiverTypes()->is_empty()) { | 5788 !expr->GetReceiverTypes()->is_empty()) { |
| 5847 return HandlePolymorphicElementAccess( | 5789 return HandlePolymorphicElementAccess( |
| 5848 obj, key, val, expr, ast_id, position, is_store, | 5790 obj, key, val, expr, ast_id, position, is_store, |
| 5849 expr->GetStoreMode(), has_side_effects); | 5791 expr->GetStoreMode(), has_side_effects); |
| 5850 } else { | 5792 } else { |
| 5851 if (is_store) { | 5793 if (is_store) { |
| 5852 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { | 5794 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { |
| 5853 AddSoftDeoptimize(); | 5795 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 5854 } | 5796 } |
| 5855 instr = BuildStoreKeyedGeneric(obj, key, val); | 5797 instr = BuildStoreKeyedGeneric(obj, key, val); |
| 5856 } else { | 5798 } else { |
| 5857 if (expr->AsProperty()->IsUninitialized()) { | 5799 if (expr->AsProperty()->IsUninitialized()) { |
| 5858 AddSoftDeoptimize(); | 5800 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 5859 } | 5801 } |
| 5860 instr = BuildLoadKeyedGeneric(obj, key); | 5802 instr = BuildLoadKeyedGeneric(obj, key); |
| 5861 } | 5803 } |
| 5862 AddInstruction(instr); | 5804 AddInstruction(instr); |
| 5863 } | 5805 } |
| 5864 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5806 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
| 5865 *has_side_effects = instr->HasObservableSideEffects(); | 5807 *has_side_effects = instr->HasObservableSideEffects(); |
| 5866 return instr; | 5808 return instr; |
| 5867 } | 5809 } |
| 5868 | 5810 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6027 HValue* key = Pop(); | 5969 HValue* key = Pop(); |
| 6028 HValue* obj = Pop(); | 5970 HValue* obj = Pop(); |
| 6029 | 5971 |
| 6030 bool has_side_effects = false; | 5972 bool has_side_effects = false; |
| 6031 HValue* load = HandleKeyedElementAccess( | 5973 HValue* load = HandleKeyedElementAccess( |
| 6032 obj, key, NULL, expr, expr->id(), expr->position(), | 5974 obj, key, NULL, expr, expr->id(), expr->position(), |
| 6033 false, // is_store | 5975 false, // is_store |
| 6034 &has_side_effects); | 5976 &has_side_effects); |
| 6035 if (has_side_effects) { | 5977 if (has_side_effects) { |
| 6036 if (ast_context()->IsEffect()) { | 5978 if (ast_context()->IsEffect()) { |
| 6037 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 5979 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 6038 } else { | 5980 } else { |
| 6039 Push(load); | 5981 Push(load); |
| 6040 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 5982 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 6041 Drop(1); | 5983 Drop(1); |
| 6042 } | 5984 } |
| 6043 } | 5985 } |
| 6044 return ast_context()->ReturnValue(load); | 5986 return ast_context()->ReturnValue(load); |
| 6045 } | 5987 } |
| 6046 instr->set_position(expr->position()); | 5988 instr->set_position(expr->position()); |
| 6047 return ast_context()->ReturnInstruction(instr, expr->id()); | 5989 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 6048 } | 5990 } |
| 6049 | 5991 |
| 6050 | 5992 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6132 } | 6074 } |
| 6133 | 6075 |
| 6134 if (!TryInlineCall(expr)) { | 6076 if (!TryInlineCall(expr)) { |
| 6135 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6077 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 6136 HCallConstantFunction* call = | 6078 HCallConstantFunction* call = |
| 6137 new(zone()) HCallConstantFunction(expr->target(), argument_count); | 6079 new(zone()) HCallConstantFunction(expr->target(), argument_count); |
| 6138 call->set_position(expr->position()); | 6080 call->set_position(expr->position()); |
| 6139 PreProcessCall(call); | 6081 PreProcessCall(call); |
| 6140 AddInstruction(call); | 6082 AddInstruction(call); |
| 6141 if (!ast_context()->IsEffect()) Push(call); | 6083 if (!ast_context()->IsEffect()) Push(call); |
| 6142 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 6084 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 6143 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6085 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 6144 } | 6086 } |
| 6145 | 6087 |
| 6146 return true; | 6088 return true; |
| 6147 } | 6089 } |
| 6148 | 6090 |
| 6149 | 6091 |
| 6150 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( | 6092 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( |
| 6151 Call* expr, | 6093 Call* expr, |
| 6152 HValue* receiver, | 6094 HValue* receiver, |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6264 } | 6206 } |
| 6265 | 6207 |
| 6266 if (current_block() != NULL) current_block()->Goto(join); | 6208 if (current_block() != NULL) current_block()->Goto(join); |
| 6267 set_current_block(if_false); | 6209 set_current_block(if_false); |
| 6268 } | 6210 } |
| 6269 | 6211 |
| 6270 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6212 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 6271 // know about and do not want to handle ones we've never seen. Otherwise | 6213 // know about and do not want to handle ones we've never seen. Otherwise |
| 6272 // use a generic IC. | 6214 // use a generic IC. |
| 6273 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6215 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 6274 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 6216 Deoptimize(join); |
| 6275 } else { | 6217 } else { |
| 6276 HValue* context = environment()->LookupContext(); | 6218 HValue* context = environment()->LookupContext(); |
| 6277 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); | 6219 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); |
| 6278 call->set_position(expr->position()); | 6220 call->set_position(expr->position()); |
| 6279 PreProcessCall(call); | 6221 PreProcessCall(call); |
| 6280 | 6222 |
| 6281 if (join != NULL) { | 6223 if (join != NULL) { |
| 6282 AddInstruction(call); | 6224 AddInstruction(call); |
| 6283 if (!ast_context()->IsEffect()) Push(call); | 6225 if (!ast_context()->IsEffect()) Push(call); |
| 6284 current_block()->Goto(join); | 6226 current_block()->Goto(join); |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6522 #if V8_TARGET_ARCH_IA32 | 6464 #if V8_TARGET_ARCH_IA32 |
| 6523 // IA32 only, overwrite the caller's context in the deoptimization | 6465 // IA32 only, overwrite the caller's context in the deoptimization |
| 6524 // environment with the correct one. | 6466 // environment with the correct one. |
| 6525 // | 6467 // |
| 6526 // TODO(kmillikin): implement the same inlining on other platforms so we | 6468 // TODO(kmillikin): implement the same inlining on other platforms so we |
| 6527 // can remove the unsightly ifdefs in this function. | 6469 // can remove the unsightly ifdefs in this function. |
| 6528 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); | 6470 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); |
| 6529 inner_env->BindContext(context); | 6471 inner_env->BindContext(context); |
| 6530 #endif | 6472 #endif |
| 6531 | 6473 |
| 6532 AddSimulate(return_id); | 6474 Add<HSimulate>(return_id); |
| 6533 current_block()->UpdateEnvironment(inner_env); | 6475 current_block()->UpdateEnvironment(inner_env); |
| 6534 HArgumentsObject* arguments_object = NULL; | 6476 HArgumentsObject* arguments_object = NULL; |
| 6535 | 6477 |
| 6536 // If the function uses arguments object create and bind one, also copy | 6478 // If the function uses arguments object create and bind one, also copy |
| 6537 // current arguments values to use them for materialization. | 6479 // current arguments values to use them for materialization. |
| 6538 if (function->scope()->arguments() != NULL) { | 6480 if (function->scope()->arguments() != NULL) { |
| 6539 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 6481 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
| 6540 HEnvironment* arguments_env = inner_env->arguments_environment(); | 6482 HEnvironment* arguments_env = inner_env->arguments_environment(); |
| 6541 int arguments_count = arguments_env->parameter_count(); | 6483 int arguments_count = arguments_env->parameter_count(); |
| 6542 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); | 6484 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); |
| (...skipping 1165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7708 } | 7650 } |
| 7709 } | 7651 } |
| 7710 } | 7652 } |
| 7711 | 7653 |
| 7712 HValue* context = BuildContextChainWalk(var); | 7654 HValue* context = BuildContextChainWalk(var); |
| 7713 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 7655 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
| 7714 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 7656 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
| 7715 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 7657 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
| 7716 mode, after); | 7658 mode, after); |
| 7717 if (instr->HasObservableSideEffects()) { | 7659 if (instr->HasObservableSideEffects()) { |
| 7718 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7660 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 7719 } | 7661 } |
| 7720 break; | 7662 break; |
| 7721 } | 7663 } |
| 7722 | 7664 |
| 7723 case Variable::LOOKUP: | 7665 case Variable::LOOKUP: |
| 7724 return Bailout("lookup variable in count operation"); | 7666 return Bailout("lookup variable in count operation"); |
| 7725 } | 7667 } |
| 7726 | 7668 |
| 7727 } else { | 7669 } else { |
| 7728 // Argument of the count operation is a property. | 7670 // Argument of the count operation is a property. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 7751 load = BuildCallGetter(object, map, getter, holder); | 7693 load = BuildCallGetter(object, map, getter, holder); |
| 7752 } else { | 7694 } else { |
| 7753 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 7695 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
| 7754 } | 7696 } |
| 7755 } else if (types != NULL && types->length() > 1) { | 7697 } else if (types != NULL && types->length() > 1) { |
| 7756 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); | 7698 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
| 7757 } | 7699 } |
| 7758 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); | 7700 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
| 7759 PushAndAdd(load); | 7701 PushAndAdd(load); |
| 7760 if (load->HasObservableSideEffects()) { | 7702 if (load->HasObservableSideEffects()) { |
| 7761 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7703 Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
| 7762 } | 7704 } |
| 7763 | 7705 |
| 7764 after = BuildIncrement(returns_original_input, expr); | 7706 after = BuildIncrement(returns_original_input, expr); |
| 7765 | 7707 |
| 7766 HValue* result = returns_original_input ? Pop() : NULL; | 7708 HValue* result = returns_original_input ? Pop() : NULL; |
| 7767 | 7709 |
| 7768 return BuildStoreNamed(prop, expr->id(), expr->position(), | 7710 return BuildStoreNamed(prop, expr->id(), expr->position(), |
| 7769 expr->AssignmentId(), prop, object, after, result); | 7711 expr->AssignmentId(), prop, object, after, result); |
| 7770 } else { | 7712 } else { |
| 7771 // Keyed property. | 7713 // Keyed property. |
| 7772 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7714 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
| 7773 | 7715 |
| 7774 CHECK_ALIVE(VisitForValue(prop->obj())); | 7716 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7775 CHECK_ALIVE(VisitForValue(prop->key())); | 7717 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7776 HValue* obj = environment()->ExpressionStackAt(1); | 7718 HValue* obj = environment()->ExpressionStackAt(1); |
| 7777 HValue* key = environment()->ExpressionStackAt(0); | 7719 HValue* key = environment()->ExpressionStackAt(0); |
| 7778 | 7720 |
| 7779 bool has_side_effects = false; | 7721 bool has_side_effects = false; |
| 7780 HValue* load = HandleKeyedElementAccess( | 7722 HValue* load = HandleKeyedElementAccess( |
| 7781 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 7723 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
| 7782 false, // is_store | 7724 false, // is_store |
| 7783 &has_side_effects); | 7725 &has_side_effects); |
| 7784 Push(load); | 7726 Push(load); |
| 7785 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7727 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
| 7786 | 7728 |
| 7787 after = BuildIncrement(returns_original_input, expr); | 7729 after = BuildIncrement(returns_original_input, expr); |
| 7788 input = environment()->ExpressionStackAt(0); | 7730 input = environment()->ExpressionStackAt(0); |
| 7789 | 7731 |
| 7790 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), | 7732 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), |
| 7791 RelocInfo::kNoPosition, | 7733 RelocInfo::kNoPosition, |
| 7792 true, // is_store | 7734 true, // is_store |
| 7793 &has_side_effects); | 7735 &has_side_effects); |
| 7794 | 7736 |
| 7795 // Drop the key and the original value from the bailout environment. | 7737 // Drop the key and the original value from the bailout environment. |
| 7796 // Overwrite the receiver with the result of the operation, and the | 7738 // Overwrite the receiver with the result of the operation, and the |
| 7797 // placeholder with the original value if necessary. | 7739 // placeholder with the original value if necessary. |
| 7798 Drop(2); | 7740 Drop(2); |
| 7799 environment()->SetExpressionStackAt(0, after); | 7741 environment()->SetExpressionStackAt(0, after); |
| 7800 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 7742 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
| 7801 ASSERT(has_side_effects); // Stores always have side effects. | 7743 ASSERT(has_side_effects); // Stores always have side effects. |
| 7802 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7744 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 7803 } | 7745 } |
| 7804 } | 7746 } |
| 7805 | 7747 |
| 7806 Drop(returns_original_input ? 2 : 1); | 7748 Drop(returns_original_input ? 2 : 1); |
| 7807 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 7749 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
| 7808 } | 7750 } |
| 7809 | 7751 |
| 7810 | 7752 |
| 7811 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( | 7753 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( |
| 7812 HValue* context, | 7754 HValue* context, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7898 HValue* context = environment()->LookupContext(); | 7840 HValue* context = environment()->LookupContext(); |
| 7899 Handle<Type> left_type = expr->left()->bounds().lower; | 7841 Handle<Type> left_type = expr->left()->bounds().lower; |
| 7900 Handle<Type> right_type = expr->right()->bounds().lower; | 7842 Handle<Type> right_type = expr->right()->bounds().lower; |
| 7901 Handle<Type> result_type = expr->bounds().lower; | 7843 Handle<Type> result_type = expr->bounds().lower; |
| 7902 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7844 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 7903 Representation left_rep = Representation::FromType(left_type); | 7845 Representation left_rep = Representation::FromType(left_type); |
| 7904 Representation right_rep = Representation::FromType(right_type); | 7846 Representation right_rep = Representation::FromType(right_type); |
| 7905 Representation result_rep = Representation::FromType(result_type); | 7847 Representation result_rep = Representation::FromType(result_type); |
| 7906 | 7848 |
| 7907 if (left_type->Is(Type::None())) { | 7849 if (left_type->Is(Type::None())) { |
| 7908 AddSoftDeoptimize(); | 7850 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 7909 // TODO(rossberg): we should be able to get rid of non-continuous defaults. | 7851 // TODO(rossberg): we should be able to get rid of non-continuous defaults. |
| 7910 left_type = handle(Type::Any(), isolate()); | 7852 left_type = handle(Type::Any(), isolate()); |
| 7911 } | 7853 } |
| 7912 if (right_type->Is(Type::None())) { | 7854 if (right_type->Is(Type::None())) { |
| 7913 AddSoftDeoptimize(); | 7855 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 7914 right_type = handle(Type::Any(), isolate()); | 7856 right_type = handle(Type::Any(), isolate()); |
| 7915 } | 7857 } |
| 7916 HInstruction* instr = NULL; | 7858 HInstruction* instr = NULL; |
| 7917 switch (expr->op()) { | 7859 switch (expr->op()) { |
| 7918 case Token::ADD: | 7860 case Token::ADD: |
| 7919 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { | 7861 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { |
| 7920 BuildCheckHeapObject(left); | 7862 BuildCheckHeapObject(left); |
| 7921 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 7863 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 7922 BuildCheckHeapObject(right); | 7864 BuildCheckHeapObject(right); |
| 7923 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 7865 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8253 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 8195 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
| 8254 // even though we are certain to pass the correct number of arguments here. | 8196 // even though we are certain to pass the correct number of arguments here. |
| 8255 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); | 8197 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); |
| 8256 result->set_position(expr->position()); | 8198 result->set_position(expr->position()); |
| 8257 return ast_context()->ReturnInstruction(result, expr->id()); | 8199 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8258 } | 8200 } |
| 8259 | 8201 |
| 8260 // Cases handled below depend on collected type feedback. They should | 8202 // Cases handled below depend on collected type feedback. They should |
| 8261 // soft deoptimize when there is no type feedback. | 8203 // soft deoptimize when there is no type feedback. |
| 8262 if (combined_type->Is(Type::None())) { | 8204 if (combined_type->Is(Type::None())) { |
| 8263 AddSoftDeoptimize(); | 8205 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 8264 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 8206 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
| 8265 } | 8207 } |
| 8266 | 8208 |
| 8267 if (combined_type->Is(Type::Receiver())) { | 8209 if (combined_type->Is(Type::Receiver())) { |
| 8268 switch (op) { | 8210 switch (op) { |
| 8269 case Token::EQ: | 8211 case Token::EQ: |
| 8270 case Token::EQ_STRICT: { | 8212 case Token::EQ_STRICT: { |
| 8271 // Can we get away with map check and not instance type check? | 8213 // Can we get away with map check and not instance type check? |
| 8272 if (combined_type->IsClass()) { | 8214 if (combined_type->IsClass()) { |
| 8273 Handle<Map> map = combined_type->AsClass(); | 8215 Handle<Map> map = combined_type->AsClass(); |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8753 environment()->Bind(variable, value); | 8695 environment()->Bind(variable, value); |
| 8754 } | 8696 } |
| 8755 break; | 8697 break; |
| 8756 case Variable::CONTEXT: | 8698 case Variable::CONTEXT: |
| 8757 if (hole_init) { | 8699 if (hole_init) { |
| 8758 HValue* value = graph()->GetConstantHole(); | 8700 HValue* value = graph()->GetConstantHole(); |
| 8759 HValue* context = environment()->LookupContext(); | 8701 HValue* context = environment()->LookupContext(); |
| 8760 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8702 HStoreContextSlot* store = Add<HStoreContextSlot>( |
| 8761 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8703 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
| 8762 if (store->HasObservableSideEffects()) { | 8704 if (store->HasObservableSideEffects()) { |
| 8763 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8705 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
| 8764 } | 8706 } |
| 8765 } | 8707 } |
| 8766 break; | 8708 break; |
| 8767 case Variable::LOOKUP: | 8709 case Variable::LOOKUP: |
| 8768 return Bailout("unsupported lookup slot in declaration"); | 8710 return Bailout("unsupported lookup slot in declaration"); |
| 8769 } | 8711 } |
| 8770 } | 8712 } |
| 8771 | 8713 |
| 8772 | 8714 |
| 8773 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 8715 void HOptimizedGraphBuilder::VisitFunctionDeclaration( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 8791 BindIfLive(variable, value); | 8733 BindIfLive(variable, value); |
| 8792 break; | 8734 break; |
| 8793 } | 8735 } |
| 8794 case Variable::CONTEXT: { | 8736 case Variable::CONTEXT: { |
| 8795 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8737 CHECK_ALIVE(VisitForValue(declaration->fun())); |
| 8796 HValue* value = Pop(); | 8738 HValue* value = Pop(); |
| 8797 HValue* context = environment()->LookupContext(); | 8739 HValue* context = environment()->LookupContext(); |
| 8798 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8740 HStoreContextSlot* store = Add<HStoreContextSlot>( |
| 8799 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8741 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
| 8800 if (store->HasObservableSideEffects()) { | 8742 if (store->HasObservableSideEffects()) { |
| 8801 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8743 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
| 8802 } | 8744 } |
| 8803 break; | 8745 break; |
| 8804 } | 8746 } |
| 8805 case Variable::LOOKUP: | 8747 case Variable::LOOKUP: |
| 8806 return Bailout("unsupported lookup slot in declaration"); | 8748 return Bailout("unsupported lookup slot in declaration"); |
| 8807 } | 8749 } |
| 8808 } | 8750 } |
| 8809 | 8751 |
| 8810 | 8752 |
| 8811 void HOptimizedGraphBuilder::VisitModuleDeclaration( | 8753 void HOptimizedGraphBuilder::VisitModuleDeclaration( |
| (...skipping 1177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9989 if (ShouldProduceTraceOutput()) { | 9931 if (ShouldProduceTraceOutput()) { |
| 9990 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9932 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9991 } | 9933 } |
| 9992 | 9934 |
| 9993 #ifdef DEBUG | 9935 #ifdef DEBUG |
| 9994 graph_->Verify(false); // No full verify. | 9936 graph_->Verify(false); // No full verify. |
| 9995 #endif | 9937 #endif |
| 9996 } | 9938 } |
| 9997 | 9939 |
| 9998 } } // namespace v8::internal | 9940 } } // namespace v8::internal |
| OLD | NEW |