| 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 | 132 |
| 133 void HBasicBlock::RemovePhi(HPhi* phi) { | 133 void HBasicBlock::RemovePhi(HPhi* phi) { |
| 134 ASSERT(phi->block() == this); | 134 ASSERT(phi->block() == this); |
| 135 ASSERT(phis_.Contains(phi)); | 135 ASSERT(phis_.Contains(phi)); |
| 136 phi->Kill(); | 136 phi->Kill(); |
| 137 phis_.RemoveElement(phi); | 137 phis_.RemoveElement(phi); |
| 138 phi->SetBlock(NULL); | 138 phi->SetBlock(NULL); |
| 139 } | 139 } |
| 140 | 140 |
| 141 | 141 |
| 142 void HBasicBlock::AddInstruction(HInstruction* instr) { | 142 void HBasicBlock::AddInstruction(HInstruction* instr, int position) { |
| 143 ASSERT(!IsStartBlock() || !IsFinished()); | 143 ASSERT(!IsStartBlock() || !IsFinished()); |
| 144 ASSERT(!instr->IsLinked()); | 144 ASSERT(!instr->IsLinked()); |
| 145 ASSERT(!IsFinished()); | 145 ASSERT(!IsFinished()); |
| 146 | 146 |
| 147 if (position != RelocInfo::kNoPosition) { |
| 148 instr->set_position(position); |
| 149 } |
| 147 if (first_ == NULL) { | 150 if (first_ == NULL) { |
| 148 ASSERT(last_environment() != NULL); | 151 ASSERT(last_environment() != NULL); |
| 149 ASSERT(!last_environment()->ast_id().IsNone()); | 152 ASSERT(!last_environment()->ast_id().IsNone()); |
| 150 HBlockEntry* entry = new(zone()) HBlockEntry(); | 153 HBlockEntry* entry = new(zone()) HBlockEntry(); |
| 151 entry->InitializeAsFirst(this); | 154 entry->InitializeAsFirst(this); |
| 155 if (position != RelocInfo::kNoPosition) { |
| 156 entry->set_position(position); |
| 157 } else { |
| 158 ASSERT(!FLAG_opt_code_positions || |
| 159 !graph()->info()->IsOptimizing()); |
| 160 } |
| 152 first_ = last_ = entry; | 161 first_ = last_ = entry; |
| 153 } | 162 } |
| 154 instr->InsertAfter(last_); | 163 instr->InsertAfter(last_); |
| 155 } | 164 } |
| 156 | 165 |
| 157 | 166 |
| 158 HPhi* HBasicBlock::AddNewPhi(int merged_index) { | 167 HPhi* HBasicBlock::AddNewPhi(int merged_index) { |
| 159 if (graph()->IsInsideNoSideEffectsScope()) { | 168 if (graph()->IsInsideNoSideEffectsScope()) { |
| 160 merged_index = HPhi::kInvalidMergedIndex; | 169 merged_index = HPhi::kInvalidMergedIndex; |
| 161 } | 170 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 192 !it.Done(); | 201 !it.Done(); |
| 193 it.Advance()) { | 202 it.Advance()) { |
| 194 int index = it.Current(); | 203 int index = it.Current(); |
| 195 instr->AddAssignedValue(index, environment->Lookup(index)); | 204 instr->AddAssignedValue(index, environment->Lookup(index)); |
| 196 } | 205 } |
| 197 environment->ClearHistory(); | 206 environment->ClearHistory(); |
| 198 return instr; | 207 return instr; |
| 199 } | 208 } |
| 200 | 209 |
| 201 | 210 |
| 202 void HBasicBlock::Finish(HControlInstruction* end) { | 211 void HBasicBlock::Finish(HControlInstruction* end, int position) { |
| 203 ASSERT(!IsFinished()); | 212 ASSERT(!IsFinished()); |
| 204 AddInstruction(end); | 213 AddInstruction(end, position); |
| 205 end_ = end; | 214 end_ = end; |
| 206 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { | 215 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { |
| 207 it.Current()->RegisterPredecessor(this); | 216 it.Current()->RegisterPredecessor(this); |
| 208 } | 217 } |
| 209 } | 218 } |
| 210 | 219 |
| 211 | 220 |
| 212 void HBasicBlock::Goto(HBasicBlock* block, | 221 void HBasicBlock::Goto(HBasicBlock* block, |
| 222 int position, |
| 213 FunctionState* state, | 223 FunctionState* state, |
| 214 bool add_simulate) { | 224 bool add_simulate) { |
| 215 bool drop_extra = state != NULL && | 225 bool drop_extra = state != NULL && |
| 216 state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 226 state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
| 217 | 227 |
| 218 if (block->IsInlineReturnTarget()) { | 228 if (block->IsInlineReturnTarget()) { |
| 219 HEnvironment* env = last_environment(); | 229 HEnvironment* env = last_environment(); |
| 220 int argument_count = env->arguments_environment()->parameter_count(); | 230 int argument_count = env->arguments_environment()->parameter_count(); |
| 221 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count)); | 231 AddInstruction(new(zone()) |
| 232 HLeaveInlined(state->entry(), argument_count), |
| 233 position); |
| 222 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); | 234 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
| 223 } | 235 } |
| 224 | 236 |
| 225 if (add_simulate) AddNewSimulate(BailoutId::None()); | 237 if (add_simulate) AddNewSimulate(BailoutId::None(), position); |
| 226 HGoto* instr = new(zone()) HGoto(block); | 238 HGoto* instr = new(zone()) HGoto(block); |
| 227 Finish(instr); | 239 Finish(instr, position); |
| 228 } | 240 } |
| 229 | 241 |
| 230 | 242 |
| 231 void HBasicBlock::AddLeaveInlined(HValue* return_value, | 243 void HBasicBlock::AddLeaveInlined(HValue* return_value, |
| 232 FunctionState* state) { | 244 FunctionState* state, |
| 245 int position) { |
| 233 HBasicBlock* target = state->function_return(); | 246 HBasicBlock* target = state->function_return(); |
| 234 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 247 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
| 235 | 248 |
| 236 ASSERT(target->IsInlineReturnTarget()); | 249 ASSERT(target->IsInlineReturnTarget()); |
| 237 ASSERT(return_value != NULL); | 250 ASSERT(return_value != NULL); |
| 238 HEnvironment* env = last_environment(); | 251 HEnvironment* env = last_environment(); |
| 239 int argument_count = env->arguments_environment()->parameter_count(); | 252 int argument_count = env->arguments_environment()->parameter_count(); |
| 240 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count)); | 253 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count), |
| 254 position); |
| 241 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); | 255 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
| 242 last_environment()->Push(return_value); | 256 last_environment()->Push(return_value); |
| 243 AddNewSimulate(BailoutId::None()); | 257 AddNewSimulate(BailoutId::None(), position); |
| 244 HGoto* instr = new(zone()) HGoto(target); | 258 HGoto* instr = new(zone()) HGoto(target); |
| 245 Finish(instr); | 259 Finish(instr, position); |
| 246 } | 260 } |
| 247 | 261 |
| 248 | 262 |
| 249 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { | 263 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { |
| 250 ASSERT(!HasEnvironment()); | 264 ASSERT(!HasEnvironment()); |
| 251 ASSERT(first() == NULL); | 265 ASSERT(first() == NULL); |
| 252 UpdateEnvironment(env); | 266 UpdateEnvironment(env); |
| 253 } | 267 } |
| 254 | 268 |
| 255 | 269 |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 if (constant == GetConstant1()) return true; | 707 if (constant == GetConstant1()) return true; |
| 694 if (constant == GetConstantMinus1()) return true; | 708 if (constant == GetConstantMinus1()) return true; |
| 695 if (constant == GetConstantTrue()) return true; | 709 if (constant == GetConstantTrue()) return true; |
| 696 if (constant == GetConstantFalse()) return true; | 710 if (constant == GetConstantFalse()) return true; |
| 697 if (constant == GetConstantHole()) return true; | 711 if (constant == GetConstantHole()) return true; |
| 698 if (constant == GetConstantNull()) return true; | 712 if (constant == GetConstantNull()) return true; |
| 699 return false; | 713 return false; |
| 700 } | 714 } |
| 701 | 715 |
| 702 | 716 |
| 703 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) | 717 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder) |
| 704 : builder_(builder), | 718 : builder_(builder), |
| 705 position_(position), | |
| 706 finished_(false), | 719 finished_(false), |
| 707 deopt_then_(false), | 720 deopt_then_(false), |
| 708 deopt_else_(false), | 721 deopt_else_(false), |
| 709 did_then_(false), | 722 did_then_(false), |
| 710 did_else_(false), | 723 did_else_(false), |
| 711 did_and_(false), | 724 did_and_(false), |
| 712 did_or_(false), | 725 did_or_(false), |
| 713 captured_(false), | 726 captured_(false), |
| 714 needs_compare_(true), | 727 needs_compare_(true), |
| 715 split_edge_merge_block_(NULL), | 728 split_edge_merge_block_(NULL), |
| 716 merge_block_(NULL) { | 729 merge_block_(NULL) { |
| 717 HEnvironment* env = builder->environment(); | 730 HEnvironment* env = builder->environment(); |
| 718 first_true_block_ = builder->CreateBasicBlock(env->Copy()); | 731 first_true_block_ = builder->CreateBasicBlock(env->Copy()); |
| 719 last_true_block_ = NULL; | 732 last_true_block_ = NULL; |
| 720 first_false_block_ = builder->CreateBasicBlock(env->Copy()); | 733 first_false_block_ = builder->CreateBasicBlock(env->Copy()); |
| 721 } | 734 } |
| 722 | 735 |
| 723 | 736 |
| 724 HGraphBuilder::IfBuilder::IfBuilder( | 737 HGraphBuilder::IfBuilder::IfBuilder( |
| 725 HGraphBuilder* builder, | 738 HGraphBuilder* builder, |
| 726 HIfContinuation* continuation) | 739 HIfContinuation* continuation) |
| 727 : builder_(builder), | 740 : builder_(builder), |
| 728 position_(RelocInfo::kNoPosition), | |
| 729 finished_(false), | 741 finished_(false), |
| 730 deopt_then_(false), | 742 deopt_then_(false), |
| 731 deopt_else_(false), | 743 deopt_else_(false), |
| 732 did_then_(false), | 744 did_then_(false), |
| 733 did_else_(false), | 745 did_else_(false), |
| 734 did_and_(false), | 746 did_and_(false), |
| 735 did_or_(false), | 747 did_or_(false), |
| 736 captured_(false), | 748 captured_(false), |
| 737 needs_compare_(false), | 749 needs_compare_(false), |
| 738 first_true_block_(NULL), | 750 first_true_block_(NULL), |
| 739 last_true_block_(NULL), | 751 last_true_block_(NULL), |
| 740 first_false_block_(NULL), | 752 first_false_block_(NULL), |
| 741 split_edge_merge_block_(NULL), | 753 split_edge_merge_block_(NULL), |
| 742 merge_block_(NULL) { | 754 merge_block_(NULL) { |
| 743 continuation->Continue(&first_true_block_, | 755 continuation->Continue(&first_true_block_, |
| 744 &first_false_block_, | 756 &first_false_block_); |
| 745 &position_); | |
| 746 } | 757 } |
| 747 | 758 |
| 748 | 759 |
| 749 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( | 760 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( |
| 750 HControlInstruction* compare) { | 761 HControlInstruction* compare) { |
| 751 if (split_edge_merge_block_ != NULL) { | 762 if (split_edge_merge_block_ != NULL) { |
| 752 HEnvironment* env = first_false_block_->last_environment(); | 763 HEnvironment* env = first_false_block_->last_environment(); |
| 753 HBasicBlock* split_edge = | 764 HBasicBlock* split_edge = |
| 754 builder_->CreateBasicBlock(env->Copy()); | 765 builder_->CreateBasicBlock(env->Copy()); |
| 755 if (did_or_) { | 766 if (did_or_) { |
| 756 compare->SetSuccessorAt(0, split_edge); | 767 compare->SetSuccessorAt(0, split_edge); |
| 757 compare->SetSuccessorAt(1, first_false_block_); | 768 compare->SetSuccessorAt(1, first_false_block_); |
| 758 } else { | 769 } else { |
| 759 compare->SetSuccessorAt(0, first_true_block_); | 770 compare->SetSuccessorAt(0, first_true_block_); |
| 760 compare->SetSuccessorAt(1, split_edge); | 771 compare->SetSuccessorAt(1, split_edge); |
| 761 } | 772 } |
| 762 split_edge->GotoNoSimulate(split_edge_merge_block_); | 773 builder_->GotoNoSimulate(split_edge, split_edge_merge_block_); |
| 763 } else { | 774 } else { |
| 764 compare->SetSuccessorAt(0, first_true_block_); | 775 compare->SetSuccessorAt(0, first_true_block_); |
| 765 compare->SetSuccessorAt(1, first_false_block_); | 776 compare->SetSuccessorAt(1, first_false_block_); |
| 766 } | 777 } |
| 767 builder_->current_block()->Finish(compare); | 778 builder_->FinishCurrentBlock(compare); |
| 768 needs_compare_ = false; | 779 needs_compare_ = false; |
| 769 return compare; | 780 return compare; |
| 770 } | 781 } |
| 771 | 782 |
| 772 | 783 |
| 773 void HGraphBuilder::IfBuilder::Or() { | 784 void HGraphBuilder::IfBuilder::Or() { |
| 774 ASSERT(!did_and_); | 785 ASSERT(!did_and_); |
| 775 did_or_ = true; | 786 did_or_ = true; |
| 776 HEnvironment* env = first_false_block_->last_environment(); | 787 HEnvironment* env = first_false_block_->last_environment(); |
| 777 if (split_edge_merge_block_ == NULL) { | 788 if (split_edge_merge_block_ == NULL) { |
| 778 split_edge_merge_block_ = | 789 split_edge_merge_block_ = |
| 779 builder_->CreateBasicBlock(env->Copy()); | 790 builder_->CreateBasicBlock(env->Copy()); |
| 780 first_true_block_->GotoNoSimulate(split_edge_merge_block_); | 791 builder_->GotoNoSimulate(first_true_block_, split_edge_merge_block_); |
| 781 first_true_block_ = split_edge_merge_block_; | 792 first_true_block_ = split_edge_merge_block_; |
| 782 } | 793 } |
| 783 builder_->set_current_block(first_false_block_); | 794 builder_->set_current_block(first_false_block_); |
| 784 first_false_block_ = builder_->CreateBasicBlock(env->Copy()); | 795 first_false_block_ = builder_->CreateBasicBlock(env->Copy()); |
| 785 } | 796 } |
| 786 | 797 |
| 787 | 798 |
| 788 void HGraphBuilder::IfBuilder::And() { | 799 void HGraphBuilder::IfBuilder::And() { |
| 789 ASSERT(!did_or_); | 800 ASSERT(!did_or_); |
| 790 did_and_ = true; | 801 did_and_ = true; |
| 791 HEnvironment* env = first_false_block_->last_environment(); | 802 HEnvironment* env = first_false_block_->last_environment(); |
| 792 if (split_edge_merge_block_ == NULL) { | 803 if (split_edge_merge_block_ == NULL) { |
| 793 split_edge_merge_block_ = builder_->CreateBasicBlock(env->Copy()); | 804 split_edge_merge_block_ = builder_->CreateBasicBlock(env->Copy()); |
| 794 first_false_block_->GotoNoSimulate(split_edge_merge_block_); | 805 builder_->GotoNoSimulate(first_false_block_, split_edge_merge_block_); |
| 795 first_false_block_ = split_edge_merge_block_; | 806 first_false_block_ = split_edge_merge_block_; |
| 796 } | 807 } |
| 797 builder_->set_current_block(first_true_block_); | 808 builder_->set_current_block(first_true_block_); |
| 798 first_true_block_ = builder_->CreateBasicBlock(env->Copy()); | 809 first_true_block_ = builder_->CreateBasicBlock(env->Copy()); |
| 799 } | 810 } |
| 800 | 811 |
| 801 | 812 |
| 802 void HGraphBuilder::IfBuilder::CaptureContinuation( | 813 void HGraphBuilder::IfBuilder::CaptureContinuation( |
| 803 HIfContinuation* continuation) { | 814 HIfContinuation* continuation) { |
| 804 ASSERT(!finished_); | 815 ASSERT(!finished_); |
| 805 ASSERT(!captured_); | 816 ASSERT(!captured_); |
| 806 HBasicBlock* true_block = last_true_block_ == NULL | 817 HBasicBlock* true_block = last_true_block_ == NULL |
| 807 ? first_true_block_ | 818 ? first_true_block_ |
| 808 : last_true_block_; | 819 : last_true_block_; |
| 809 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) | 820 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) |
| 810 ? builder_->current_block() | 821 ? builder_->current_block() |
| 811 : first_false_block_; | 822 : first_false_block_; |
| 812 continuation->Capture(true_block, false_block, position_); | 823 continuation->Capture(true_block, false_block); |
| 813 captured_ = true; | 824 captured_ = true; |
| 814 End(); | 825 End(); |
| 815 } | 826 } |
| 816 | 827 |
| 817 | 828 |
| 818 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { | 829 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { |
| 819 ASSERT(!finished_); | 830 ASSERT(!finished_); |
| 820 ASSERT(!captured_); | 831 ASSERT(!captured_); |
| 821 HBasicBlock* true_block = last_true_block_ == NULL | 832 HBasicBlock* true_block = last_true_block_ == NULL |
| 822 ? first_true_block_ | 833 ? first_true_block_ |
| 823 : last_true_block_; | 834 : last_true_block_; |
| 824 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) | 835 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) |
| 825 ? builder_->current_block() | 836 ? builder_->current_block() |
| 826 : first_false_block_; | 837 : first_false_block_; |
| 827 if (true_block != NULL && !true_block->IsFinished()) { | 838 if (true_block != NULL && !true_block->IsFinished()) { |
| 828 ASSERT(continuation->IsTrueReachable()); | 839 ASSERT(continuation->IsTrueReachable()); |
| 829 true_block->GotoNoSimulate(continuation->true_branch()); | 840 builder_->GotoNoSimulate(true_block, continuation->true_branch()); |
| 830 } | 841 } |
| 831 if (false_block != NULL && !false_block->IsFinished()) { | 842 if (false_block != NULL && !false_block->IsFinished()) { |
| 832 ASSERT(continuation->IsFalseReachable()); | 843 ASSERT(continuation->IsFalseReachable()); |
| 833 false_block->GotoNoSimulate(continuation->false_branch()); | 844 builder_->GotoNoSimulate(false_block, continuation->false_branch()); |
| 834 } | 845 } |
| 835 captured_ = true; | 846 captured_ = true; |
| 836 End(); | 847 End(); |
| 837 } | 848 } |
| 838 | 849 |
| 839 | 850 |
| 840 void HGraphBuilder::IfBuilder::Then() { | 851 void HGraphBuilder::IfBuilder::Then() { |
| 841 ASSERT(!captured_); | 852 ASSERT(!captured_); |
| 842 ASSERT(!finished_); | 853 ASSERT(!finished_); |
| 843 did_then_ = true; | 854 did_then_ = true; |
| 844 if (needs_compare_) { | 855 if (needs_compare_) { |
| 845 // Handle if's without any expressions, they jump directly to the "else" | 856 // Handle if's without any expressions, they jump directly to the "else" |
| 846 // branch. However, we must pretend that the "then" branch is reachable, | 857 // branch. However, we must pretend that the "then" branch is reachable, |
| 847 // so that the graph builder visits it and sees any live range extending | 858 // so that the graph builder visits it and sees any live range extending |
| 848 // constructs within it. | 859 // constructs within it. |
| 849 HConstant* constant_false = builder_->graph()->GetConstantFalse(); | 860 HConstant* constant_false = builder_->graph()->GetConstantFalse(); |
| 850 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); | 861 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); |
| 851 boolean_type.Add(ToBooleanStub::BOOLEAN); | 862 boolean_type.Add(ToBooleanStub::BOOLEAN); |
| 852 HBranch* branch = builder()->New<HBranch>( | 863 HBranch* branch = builder()->New<HBranch>( |
| 853 constant_false, boolean_type, first_true_block_, first_false_block_); | 864 constant_false, boolean_type, first_true_block_, first_false_block_); |
| 854 builder_->current_block()->Finish(branch); | 865 builder_->FinishCurrentBlock(branch); |
| 855 } | 866 } |
| 856 builder_->set_current_block(first_true_block_); | 867 builder_->set_current_block(first_true_block_); |
| 857 } | 868 } |
| 858 | 869 |
| 859 | 870 |
| 860 void HGraphBuilder::IfBuilder::Else() { | 871 void HGraphBuilder::IfBuilder::Else() { |
| 861 ASSERT(did_then_); | 872 ASSERT(did_then_); |
| 862 ASSERT(!captured_); | 873 ASSERT(!captured_); |
| 863 ASSERT(!finished_); | 874 ASSERT(!finished_); |
| 864 last_true_block_ = builder_->current_block(); | 875 last_true_block_ = builder_->current_block(); |
| 865 builder_->set_current_block(first_false_block_); | 876 builder_->set_current_block(first_false_block_); |
| 866 did_else_ = true; | 877 did_else_ = true; |
| 867 } | 878 } |
| 868 | 879 |
| 869 | 880 |
| 870 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { | 881 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { |
| 871 ASSERT(did_then_); | 882 ASSERT(did_then_); |
| 872 if (did_else_) { | 883 if (did_else_) { |
| 873 deopt_else_ = true; | 884 deopt_else_ = true; |
| 874 } else { | 885 } else { |
| 875 deopt_then_ = true; | 886 deopt_then_ = true; |
| 876 } | 887 } |
| 877 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 888 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
| 878 } | 889 } |
| 879 | 890 |
| 880 | 891 |
| 881 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 892 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
| 882 HBasicBlock* block = builder_->current_block(); | |
| 883 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); | 893 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); |
| 884 block->FinishExit(builder_->New<HReturn>(value, parameter_count)); | 894 builder_->FinishExitCurrentBlock( |
| 885 builder_->set_current_block(NULL); | 895 builder_->New<HReturn>(value, parameter_count)); |
| 886 if (did_else_) { | 896 if (did_else_) { |
| 887 first_false_block_ = NULL; | 897 first_false_block_ = NULL; |
| 888 } else { | 898 } else { |
| 889 first_true_block_ = NULL; | 899 first_true_block_ = NULL; |
| 890 } | 900 } |
| 891 } | 901 } |
| 892 | 902 |
| 893 | 903 |
| 894 void HGraphBuilder::IfBuilder::End() { | 904 void HGraphBuilder::IfBuilder::End() { |
| 895 if (!captured_) { | 905 if (!captured_) { |
| 896 ASSERT(did_then_); | 906 ASSERT(did_then_); |
| 897 if (!did_else_) { | 907 if (!did_else_) { |
| 898 last_true_block_ = builder_->current_block(); | 908 last_true_block_ = builder_->current_block(); |
| 899 } | 909 } |
| 900 if (last_true_block_ == NULL || last_true_block_->IsFinished()) { | 910 if (last_true_block_ == NULL || last_true_block_->IsFinished()) { |
| 901 ASSERT(did_else_); | 911 ASSERT(did_else_); |
| 902 // Return on true. Nothing to do, just continue the false block. | 912 // Return on true. Nothing to do, just continue the false block. |
| 903 } else if (first_false_block_ == NULL || | 913 } else if (first_false_block_ == NULL || |
| 904 (did_else_ && builder_->current_block()->IsFinished())) { | 914 (did_else_ && builder_->current_block()->IsFinished())) { |
| 905 // Deopt on false. Nothing to do except switching to the true block. | 915 // Deopt on false. Nothing to do except switching to the true block. |
| 906 builder_->set_current_block(last_true_block_); | 916 builder_->set_current_block(last_true_block_); |
| 907 } else { | 917 } else { |
| 908 merge_block_ = builder_->graph()->CreateBasicBlock(); | 918 merge_block_ = builder_->graph()->CreateBasicBlock(); |
| 909 ASSERT(!finished_); | 919 ASSERT(!finished_); |
| 910 if (!did_else_) Else(); | 920 if (!did_else_) Else(); |
| 911 ASSERT(!last_true_block_->IsFinished()); | 921 ASSERT(!last_true_block_->IsFinished()); |
| 912 HBasicBlock* last_false_block = builder_->current_block(); | 922 HBasicBlock* last_false_block = builder_->current_block(); |
| 913 ASSERT(!last_false_block->IsFinished()); | 923 ASSERT(!last_false_block->IsFinished()); |
| 914 if (deopt_then_) { | 924 if (deopt_then_) { |
| 915 last_false_block->GotoNoSimulate(merge_block_); | 925 builder_->GotoNoSimulate(last_false_block, merge_block_); |
| 916 builder_->PadEnvironmentForContinuation(last_true_block_, | 926 builder_->PadEnvironmentForContinuation(last_true_block_, |
| 917 merge_block_); | 927 merge_block_); |
| 918 last_true_block_->GotoNoSimulate(merge_block_); | 928 builder_->GotoNoSimulate(last_true_block_, merge_block_); |
| 919 } else { | 929 } else { |
| 920 last_true_block_->GotoNoSimulate(merge_block_); | 930 builder_->GotoNoSimulate(last_true_block_, merge_block_); |
| 921 if (deopt_else_) { | 931 if (deopt_else_) { |
| 922 builder_->PadEnvironmentForContinuation(last_false_block, | 932 builder_->PadEnvironmentForContinuation(last_false_block, |
| 923 merge_block_); | 933 merge_block_); |
| 924 } | 934 } |
| 925 last_false_block->GotoNoSimulate(merge_block_); | 935 builder_->GotoNoSimulate(last_false_block, merge_block_); |
| 926 } | 936 } |
| 927 builder_->set_current_block(merge_block_); | 937 builder_->set_current_block(merge_block_); |
| 928 } | 938 } |
| 929 } | 939 } |
| 930 finished_ = true; | 940 finished_ = true; |
| 931 } | 941 } |
| 932 | 942 |
| 933 | 943 |
| 934 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, | 944 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
| 935 HValue* context, | 945 HValue* context, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 963 | 973 |
| 964 | 974 |
| 965 HValue* HGraphBuilder::LoopBuilder::BeginBody( | 975 HValue* HGraphBuilder::LoopBuilder::BeginBody( |
| 966 HValue* initial, | 976 HValue* initial, |
| 967 HValue* terminating, | 977 HValue* terminating, |
| 968 Token::Value token) { | 978 Token::Value token) { |
| 969 HEnvironment* env = builder_->environment(); | 979 HEnvironment* env = builder_->environment(); |
| 970 phi_ = header_block_->AddNewPhi(env->values()->length()); | 980 phi_ = header_block_->AddNewPhi(env->values()->length()); |
| 971 phi_->AddInput(initial); | 981 phi_->AddInput(initial); |
| 972 env->Push(initial); | 982 env->Push(initial); |
| 973 builder_->current_block()->GotoNoSimulate(header_block_); | 983 builder_->GotoNoSimulate(header_block_); |
| 974 | 984 |
| 975 HEnvironment* body_env = env->Copy(); | 985 HEnvironment* body_env = env->Copy(); |
| 976 HEnvironment* exit_env = env->Copy(); | 986 HEnvironment* exit_env = env->Copy(); |
| 977 // Remove the phi from the expression stack | 987 // Remove the phi from the expression stack |
| 978 body_env->Pop(); | 988 body_env->Pop(); |
| 979 exit_env->Pop(); | 989 exit_env->Pop(); |
| 980 body_block_ = builder_->CreateBasicBlock(body_env); | 990 body_block_ = builder_->CreateBasicBlock(body_env); |
| 981 exit_block_ = builder_->CreateBasicBlock(exit_env); | 991 exit_block_ = builder_->CreateBasicBlock(exit_env); |
| 982 | 992 |
| 983 builder_->set_current_block(header_block_); | 993 builder_->set_current_block(header_block_); |
| 984 env->Pop(); | 994 env->Pop(); |
| 985 builder_->current_block()->Finish(builder_->New<HCompareNumericAndBranch>( | 995 builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>( |
| 986 phi_, terminating, token, body_block_, exit_block_)); | 996 phi_, terminating, token, body_block_, exit_block_)); |
| 987 | 997 |
| 988 builder_->set_current_block(body_block_); | 998 builder_->set_current_block(body_block_); |
| 989 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { | 999 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { |
| 990 HValue* one = builder_->graph()->GetConstant1(); | 1000 HValue* one = builder_->graph()->GetConstant1(); |
| 991 if (direction_ == kPreIncrement) { | 1001 if (direction_ == kPreIncrement) { |
| 992 increment_ = HAdd::New(zone(), context_, phi_, one); | 1002 increment_ = HAdd::New(zone(), context_, phi_, one); |
| 993 } else { | 1003 } else { |
| 994 increment_ = HSub::New(zone(), context_, phi_, one); | 1004 increment_ = HSub::New(zone(), context_, phi_, one); |
| 995 } | 1005 } |
| 996 increment_->ClearFlag(HValue::kCanOverflow); | 1006 increment_->ClearFlag(HValue::kCanOverflow); |
| 997 builder_->AddInstruction(increment_); | 1007 builder_->AddInstruction(increment_); |
| 998 return increment_; | 1008 return increment_; |
| 999 } else { | 1009 } else { |
| 1000 return phi_; | 1010 return phi_; |
| 1001 } | 1011 } |
| 1002 } | 1012 } |
| 1003 | 1013 |
| 1004 | 1014 |
| 1005 void HGraphBuilder::LoopBuilder::Break() { | 1015 void HGraphBuilder::LoopBuilder::Break() { |
| 1006 if (exit_trampoline_block_ == NULL) { | 1016 if (exit_trampoline_block_ == NULL) { |
| 1007 // Its the first time we saw a break. | 1017 // Its the first time we saw a break. |
| 1008 HEnvironment* env = exit_block_->last_environment()->Copy(); | 1018 HEnvironment* env = exit_block_->last_environment()->Copy(); |
| 1009 exit_trampoline_block_ = builder_->CreateBasicBlock(env); | 1019 exit_trampoline_block_ = builder_->CreateBasicBlock(env); |
| 1010 exit_block_->GotoNoSimulate(exit_trampoline_block_); | 1020 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_); |
| 1011 } | 1021 } |
| 1012 | 1022 |
| 1013 builder_->current_block()->GotoNoSimulate(exit_trampoline_block_); | 1023 builder_->GotoNoSimulate(exit_trampoline_block_); |
| 1014 } | 1024 } |
| 1015 | 1025 |
| 1016 | 1026 |
| 1017 void HGraphBuilder::LoopBuilder::EndBody() { | 1027 void HGraphBuilder::LoopBuilder::EndBody() { |
| 1018 ASSERT(!finished_); | 1028 ASSERT(!finished_); |
| 1019 | 1029 |
| 1020 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { | 1030 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { |
| 1021 if (direction_ == kPostIncrement) { | 1031 if (direction_ == kPostIncrement) { |
| 1022 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); | 1032 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); |
| 1023 } else { | 1033 } else { |
| 1024 increment_ = HSub::New(zone(), context_, phi_, increment_amount_); | 1034 increment_ = HSub::New(zone(), context_, phi_, increment_amount_); |
| 1025 } | 1035 } |
| 1026 increment_->ClearFlag(HValue::kCanOverflow); | 1036 increment_->ClearFlag(HValue::kCanOverflow); |
| 1027 builder_->AddInstruction(increment_); | 1037 builder_->AddInstruction(increment_); |
| 1028 } | 1038 } |
| 1029 | 1039 |
| 1030 // Push the new increment value on the expression stack to merge into the phi. | 1040 // Push the new increment value on the expression stack to merge into the phi. |
| 1031 builder_->environment()->Push(increment_); | 1041 builder_->environment()->Push(increment_); |
| 1032 HBasicBlock* last_block = builder_->current_block(); | 1042 HBasicBlock* last_block = builder_->current_block(); |
| 1033 last_block->GotoNoSimulate(header_block_); | 1043 builder_->GotoNoSimulate(last_block, header_block_); |
| 1034 header_block_->loop_information()->RegisterBackEdge(last_block); | 1044 header_block_->loop_information()->RegisterBackEdge(last_block); |
| 1035 | 1045 |
| 1036 if (exit_trampoline_block_ != NULL) { | 1046 if (exit_trampoline_block_ != NULL) { |
| 1037 builder_->set_current_block(exit_trampoline_block_); | 1047 builder_->set_current_block(exit_trampoline_block_); |
| 1038 } else { | 1048 } else { |
| 1039 builder_->set_current_block(exit_block_); | 1049 builder_->set_current_block(exit_block_); |
| 1040 } | 1050 } |
| 1041 finished_ = true; | 1051 finished_ = true; |
| 1042 } | 1052 } |
| 1043 | 1053 |
| 1044 | 1054 |
| 1045 HGraph* HGraphBuilder::CreateGraph() { | 1055 HGraph* HGraphBuilder::CreateGraph() { |
| 1046 graph_ = new(zone()) HGraph(info_); | 1056 graph_ = new(zone()) HGraph(info_); |
| 1047 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); | 1057 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); |
| 1048 CompilationPhase phase("H_Block building", info_); | 1058 CompilationPhase phase("H_Block building", info_); |
| 1049 set_current_block(graph()->entry_block()); | 1059 set_current_block(graph()->entry_block()); |
| 1050 if (!BuildGraph()) return NULL; | 1060 if (!BuildGraph()) return NULL; |
| 1051 graph()->FinalizeUniqueness(); | 1061 graph()->FinalizeUniqueness(); |
| 1052 return graph_; | 1062 return graph_; |
| 1053 } | 1063 } |
| 1054 | 1064 |
| 1055 | 1065 |
| 1056 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 1066 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 1057 ASSERT(current_block() != NULL); | 1067 ASSERT(current_block() != NULL); |
| 1058 current_block()->AddInstruction(instr); | 1068 ASSERT(!FLAG_opt_code_positions || |
| 1069 position_ != RelocInfo::kNoPosition || !info_->IsOptimizing()); |
| 1070 current_block()->AddInstruction(instr, position_); |
| 1059 if (graph()->IsInsideNoSideEffectsScope()) { | 1071 if (graph()->IsInsideNoSideEffectsScope()) { |
| 1060 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 1072 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
| 1061 } | 1073 } |
| 1062 return instr; | 1074 return instr; |
| 1063 } | 1075 } |
| 1064 | 1076 |
| 1065 | 1077 |
| 1078 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) { |
| 1079 ASSERT(!FLAG_opt_code_positions || !info_->IsOptimizing() || |
| 1080 position_ != RelocInfo::kNoPosition); |
| 1081 current_block()->Finish(last, position_); |
| 1082 if (last->IsReturn() || last->IsAbnormalExit()) { |
| 1083 set_current_block(NULL); |
| 1084 } |
| 1085 } |
| 1086 |
| 1087 |
| 1088 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) { |
| 1089 ASSERT(!FLAG_opt_code_positions || !info_->IsOptimizing() || |
| 1090 position_ != RelocInfo::kNoPosition); |
| 1091 current_block()->FinishExit(instruction, position_); |
| 1092 if (instruction->IsReturn() || instruction->IsAbnormalExit()) { |
| 1093 set_current_block(NULL); |
| 1094 } |
| 1095 } |
| 1096 |
| 1097 |
| 1066 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { | 1098 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { |
| 1067 if (FLAG_native_code_counters && counter->Enabled()) { | 1099 if (FLAG_native_code_counters && counter->Enabled()) { |
| 1068 HValue* reference = Add<HConstant>(ExternalReference(counter)); | 1100 HValue* reference = Add<HConstant>(ExternalReference(counter)); |
| 1069 HValue* old_value = Add<HLoadNamedField>(reference, | 1101 HValue* old_value = Add<HLoadNamedField>(reference, |
| 1070 HObjectAccess::ForCounter()); | 1102 HObjectAccess::ForCounter()); |
| 1071 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); | 1103 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); |
| 1072 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow | 1104 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow |
| 1073 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), | 1105 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), |
| 1074 new_value); | 1106 new_value); |
| 1075 } | 1107 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1104 if (obj->type().IsHeapObject()) return obj; | 1136 if (obj->type().IsHeapObject()) return obj; |
| 1105 return Add<HCheckHeapObject>(obj); | 1137 return Add<HCheckHeapObject>(obj); |
| 1106 } | 1138 } |
| 1107 | 1139 |
| 1108 | 1140 |
| 1109 void HGraphBuilder::FinishExitWithHardDeoptimization( | 1141 void HGraphBuilder::FinishExitWithHardDeoptimization( |
| 1110 const char* reason, HBasicBlock* continuation) { | 1142 const char* reason, HBasicBlock* continuation) { |
| 1111 PadEnvironmentForContinuation(current_block(), continuation); | 1143 PadEnvironmentForContinuation(current_block(), continuation); |
| 1112 Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 1144 Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
| 1113 if (graph()->IsInsideNoSideEffectsScope()) { | 1145 if (graph()->IsInsideNoSideEffectsScope()) { |
| 1114 current_block()->GotoNoSimulate(continuation); | 1146 GotoNoSimulate(continuation); |
| 1115 } else { | 1147 } else { |
| 1116 current_block()->Goto(continuation); | 1148 Goto(continuation); |
| 1117 } | 1149 } |
| 1118 } | 1150 } |
| 1119 | 1151 |
| 1120 | 1152 |
| 1121 void HGraphBuilder::PadEnvironmentForContinuation( | 1153 void HGraphBuilder::PadEnvironmentForContinuation( |
| 1122 HBasicBlock* from, | 1154 HBasicBlock* from, |
| 1123 HBasicBlock* continuation) { | 1155 HBasicBlock* continuation) { |
| 1124 if (continuation->last_environment() != NULL) { | 1156 if (continuation->last_environment() != NULL) { |
| 1125 // When merging from a deopt block to a continuation, resolve differences in | 1157 // When merging from a deopt block to a continuation, resolve differences in |
| 1126 // environment by pushing constant 0 and popping extra values so that the | 1158 // environment by pushing constant 0 and popping extra values so that the |
| (...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1930 } | 1962 } |
| 1931 } | 1963 } |
| 1932 | 1964 |
| 1933 return object; | 1965 return object; |
| 1934 } | 1966 } |
| 1935 | 1967 |
| 1936 | 1968 |
| 1937 void HGraphBuilder::BuildCompareNil( | 1969 void HGraphBuilder::BuildCompareNil( |
| 1938 HValue* value, | 1970 HValue* value, |
| 1939 Handle<Type> type, | 1971 Handle<Type> type, |
| 1940 int position, | |
| 1941 HIfContinuation* continuation) { | 1972 HIfContinuation* continuation) { |
| 1942 IfBuilder if_nil(this, position); | 1973 IfBuilder if_nil(this); |
| 1943 bool some_case_handled = false; | 1974 bool some_case_handled = false; |
| 1944 bool some_case_missing = false; | 1975 bool some_case_missing = false; |
| 1945 | 1976 |
| 1946 if (type->Maybe(Type::Null())) { | 1977 if (type->Maybe(Type::Null())) { |
| 1947 if (some_case_handled) if_nil.Or(); | 1978 if (some_case_handled) if_nil.Or(); |
| 1948 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); | 1979 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); |
| 1949 some_case_handled = true; | 1980 some_case_handled = true; |
| 1950 } else { | 1981 } else { |
| 1951 some_case_missing = true; | 1982 some_case_missing = true; |
| 1952 } | 1983 } |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2200 break_scope_(NULL), | 2231 break_scope_(NULL), |
| 2201 inlined_count_(0), | 2232 inlined_count_(0), |
| 2202 globals_(10, info->zone()), | 2233 globals_(10, info->zone()), |
| 2203 inline_bailout_(false), | 2234 inline_bailout_(false), |
| 2204 osr_(new(info->zone()) HOsrBuilder(this)) { | 2235 osr_(new(info->zone()) HOsrBuilder(this)) { |
| 2205 // This is not initialized in the initializer list because the | 2236 // This is not initialized in the initializer list because the |
| 2206 // constructor for the initial state relies on function_state_ == NULL | 2237 // constructor for the initial state relies on function_state_ == NULL |
| 2207 // to know it's the initial state. | 2238 // to know it's the initial state. |
| 2208 function_state_= &initial_function_state_; | 2239 function_state_= &initial_function_state_; |
| 2209 InitializeAstVisitor(info->isolate()); | 2240 InitializeAstVisitor(info->isolate()); |
| 2241 if (FLAG_opt_code_positions) { |
| 2242 SetSourcePosition(info->shared_info()->start_position()); |
| 2243 } |
| 2210 } | 2244 } |
| 2211 | 2245 |
| 2212 | 2246 |
| 2213 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, | 2247 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, |
| 2214 HBasicBlock* second, | 2248 HBasicBlock* second, |
| 2215 BailoutId join_id) { | 2249 BailoutId join_id) { |
| 2216 if (first == NULL) { | 2250 if (first == NULL) { |
| 2217 return second; | 2251 return second; |
| 2218 } else if (second == NULL) { | 2252 } else if (second == NULL) { |
| 2219 return first; | 2253 return first; |
| 2220 } else { | 2254 } else { |
| 2221 HBasicBlock* join_block = graph()->CreateBasicBlock(); | 2255 HBasicBlock* join_block = graph()->CreateBasicBlock(); |
| 2222 first->Goto(join_block); | 2256 Goto(first, join_block); |
| 2223 second->Goto(join_block); | 2257 Goto(second, join_block); |
| 2224 join_block->SetJoinId(join_id); | 2258 join_block->SetJoinId(join_id); |
| 2225 return join_block; | 2259 return join_block; |
| 2226 } | 2260 } |
| 2227 } | 2261 } |
| 2228 | 2262 |
| 2229 | 2263 |
| 2230 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement, | 2264 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement, |
| 2231 HBasicBlock* exit_block, | 2265 HBasicBlock* exit_block, |
| 2232 HBasicBlock* continue_block) { | 2266 HBasicBlock* continue_block) { |
| 2233 if (continue_block != NULL) { | 2267 if (continue_block != NULL) { |
| 2234 if (exit_block != NULL) exit_block->Goto(continue_block); | 2268 if (exit_block != NULL) Goto(exit_block, continue_block); |
| 2235 continue_block->SetJoinId(statement->ContinueId()); | 2269 continue_block->SetJoinId(statement->ContinueId()); |
| 2236 return continue_block; | 2270 return continue_block; |
| 2237 } | 2271 } |
| 2238 return exit_block; | 2272 return exit_block; |
| 2239 } | 2273 } |
| 2240 | 2274 |
| 2241 | 2275 |
| 2242 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement, | 2276 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement, |
| 2243 HBasicBlock* loop_entry, | 2277 HBasicBlock* loop_entry, |
| 2244 HBasicBlock* body_exit, | 2278 HBasicBlock* body_exit, |
| 2245 HBasicBlock* loop_successor, | 2279 HBasicBlock* loop_successor, |
| 2246 HBasicBlock* break_block) { | 2280 HBasicBlock* break_block) { |
| 2247 if (body_exit != NULL) body_exit->Goto(loop_entry); | 2281 if (body_exit != NULL) Goto(body_exit, loop_entry); |
| 2248 loop_entry->PostProcessLoopHeader(statement); | 2282 loop_entry->PostProcessLoopHeader(statement); |
| 2249 if (break_block != NULL) { | 2283 if (break_block != NULL) { |
| 2250 if (loop_successor != NULL) loop_successor->Goto(break_block); | 2284 if (loop_successor != NULL) Goto(loop_successor, break_block); |
| 2251 break_block->SetJoinId(statement->ExitId()); | 2285 break_block->SetJoinId(statement->ExitId()); |
| 2252 return break_block; | 2286 return break_block; |
| 2253 } | 2287 } |
| 2254 return loop_successor; | 2288 return loop_successor; |
| 2255 } | 2289 } |
| 2256 | 2290 |
| 2257 | 2291 |
| 2258 // Build a new loop header block and set it as the current block. | 2292 // Build a new loop header block and set it as the current block. |
| 2259 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() { | 2293 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() { |
| 2260 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 2294 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
| 2261 current_block()->Goto(loop_entry); | 2295 Goto(loop_entry); |
| 2262 set_current_block(loop_entry); | 2296 set_current_block(loop_entry); |
| 2263 return loop_entry; | 2297 return loop_entry; |
| 2264 } | 2298 } |
| 2265 | 2299 |
| 2266 | 2300 |
| 2267 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry( | 2301 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry( |
| 2268 IterationStatement* statement) { | 2302 IterationStatement* statement) { |
| 2269 HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement) | 2303 HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement) |
| 2270 ? osr()->BuildOsrLoopEntry(statement) | 2304 ? osr()->BuildOsrLoopEntry(statement) |
| 2271 : BuildLoopEntry(); | 2305 : BuildLoopEntry(); |
| 2272 return loop_entry; | 2306 return loop_entry; |
| 2273 } | 2307 } |
| 2274 | 2308 |
| 2275 | 2309 |
| 2276 void HBasicBlock::FinishExit(HControlInstruction* instruction) { | 2310 void HBasicBlock::FinishExit(HControlInstruction* instruction, int position) { |
| 2277 Finish(instruction); | 2311 Finish(instruction, position); |
| 2278 ClearEnvironment(); | 2312 ClearEnvironment(); |
| 2279 } | 2313 } |
| 2280 | 2314 |
| 2281 | 2315 |
| 2282 HGraph::HGraph(CompilationInfo* info) | 2316 HGraph::HGraph(CompilationInfo* info) |
| 2283 : isolate_(info->isolate()), | 2317 : isolate_(info->isolate()), |
| 2284 next_block_id_(0), | 2318 next_block_id_(0), |
| 2285 entry_block_(NULL), | 2319 entry_block_(NULL), |
| 2286 blocks_(8, info->zone()), | 2320 blocks_(8, info->zone()), |
| 2287 values_(16, info->zone()), | 2321 values_(16, info->zone()), |
| (...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2815 } | 2849 } |
| 2816 | 2850 |
| 2817 | 2851 |
| 2818 void EffectContext::ReturnControl(HControlInstruction* instr, | 2852 void EffectContext::ReturnControl(HControlInstruction* instr, |
| 2819 BailoutId ast_id) { | 2853 BailoutId ast_id) { |
| 2820 ASSERT(!instr->HasObservableSideEffects()); | 2854 ASSERT(!instr->HasObservableSideEffects()); |
| 2821 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2855 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
| 2822 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2856 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
| 2823 instr->SetSuccessorAt(0, empty_true); | 2857 instr->SetSuccessorAt(0, empty_true); |
| 2824 instr->SetSuccessorAt(1, empty_false); | 2858 instr->SetSuccessorAt(1, empty_false); |
| 2825 owner()->current_block()->Finish(instr); | 2859 owner()->FinishCurrentBlock(instr); |
| 2826 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); | 2860 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); |
| 2827 owner()->set_current_block(join); | 2861 owner()->set_current_block(join); |
| 2828 } | 2862 } |
| 2829 | 2863 |
| 2830 | 2864 |
| 2831 void EffectContext::ReturnContinuation(HIfContinuation* continuation, | 2865 void EffectContext::ReturnContinuation(HIfContinuation* continuation, |
| 2832 BailoutId ast_id) { | 2866 BailoutId ast_id) { |
| 2833 HBasicBlock* true_branch = NULL; | 2867 HBasicBlock* true_branch = NULL; |
| 2834 HBasicBlock* false_branch = NULL; | 2868 HBasicBlock* false_branch = NULL; |
| 2835 continuation->Continue(&true_branch, &false_branch, NULL); | 2869 continuation->Continue(&true_branch, &false_branch); |
| 2836 if (!continuation->IsTrueReachable()) { | 2870 if (!continuation->IsTrueReachable()) { |
| 2837 owner()->set_current_block(false_branch); | 2871 owner()->set_current_block(false_branch); |
| 2838 } else if (!continuation->IsFalseReachable()) { | 2872 } else if (!continuation->IsFalseReachable()) { |
| 2839 owner()->set_current_block(true_branch); | 2873 owner()->set_current_block(true_branch); |
| 2840 } else { | 2874 } else { |
| 2841 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); | 2875 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); |
| 2842 owner()->set_current_block(join); | 2876 owner()->set_current_block(join); |
| 2843 } | 2877 } |
| 2844 } | 2878 } |
| 2845 | 2879 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2859 | 2893 |
| 2860 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2894 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
| 2861 ASSERT(!instr->HasObservableSideEffects()); | 2895 ASSERT(!instr->HasObservableSideEffects()); |
| 2862 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2896 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
| 2863 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); | 2897 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); |
| 2864 } | 2898 } |
| 2865 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | 2899 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
| 2866 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); | 2900 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); |
| 2867 instr->SetSuccessorAt(0, materialize_true); | 2901 instr->SetSuccessorAt(0, materialize_true); |
| 2868 instr->SetSuccessorAt(1, materialize_false); | 2902 instr->SetSuccessorAt(1, materialize_false); |
| 2869 owner()->current_block()->Finish(instr); | 2903 owner()->FinishCurrentBlock(instr); |
| 2870 owner()->set_current_block(materialize_true); | 2904 owner()->set_current_block(materialize_true); |
| 2871 owner()->Push(owner()->graph()->GetConstantTrue()); | 2905 owner()->Push(owner()->graph()->GetConstantTrue()); |
| 2872 owner()->set_current_block(materialize_false); | 2906 owner()->set_current_block(materialize_false); |
| 2873 owner()->Push(owner()->graph()->GetConstantFalse()); | 2907 owner()->Push(owner()->graph()->GetConstantFalse()); |
| 2874 HBasicBlock* join = | 2908 HBasicBlock* join = |
| 2875 owner()->CreateJoin(materialize_true, materialize_false, ast_id); | 2909 owner()->CreateJoin(materialize_true, materialize_false, ast_id); |
| 2876 owner()->set_current_block(join); | 2910 owner()->set_current_block(join); |
| 2877 } | 2911 } |
| 2878 | 2912 |
| 2879 | 2913 |
| 2880 void ValueContext::ReturnContinuation(HIfContinuation* continuation, | 2914 void ValueContext::ReturnContinuation(HIfContinuation* continuation, |
| 2881 BailoutId ast_id) { | 2915 BailoutId ast_id) { |
| 2882 HBasicBlock* materialize_true = NULL; | 2916 HBasicBlock* materialize_true = NULL; |
| 2883 HBasicBlock* materialize_false = NULL; | 2917 HBasicBlock* materialize_false = NULL; |
| 2884 continuation->Continue(&materialize_true, &materialize_false, NULL); | 2918 continuation->Continue(&materialize_true, &materialize_false); |
| 2885 if (continuation->IsTrueReachable()) { | 2919 if (continuation->IsTrueReachable()) { |
| 2886 owner()->set_current_block(materialize_true); | 2920 owner()->set_current_block(materialize_true); |
| 2887 owner()->Push(owner()->graph()->GetConstantTrue()); | 2921 owner()->Push(owner()->graph()->GetConstantTrue()); |
| 2888 owner()->set_current_block(materialize_true); | 2922 owner()->set_current_block(materialize_true); |
| 2889 } | 2923 } |
| 2890 if (continuation->IsFalseReachable()) { | 2924 if (continuation->IsFalseReachable()) { |
| 2891 owner()->set_current_block(materialize_false); | 2925 owner()->set_current_block(materialize_false); |
| 2892 owner()->Push(owner()->graph()->GetConstantFalse()); | 2926 owner()->Push(owner()->graph()->GetConstantFalse()); |
| 2893 owner()->set_current_block(materialize_false); | 2927 owner()->set_current_block(materialize_false); |
| 2894 } | 2928 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2914 BuildBranch(instr); | 2948 BuildBranch(instr); |
| 2915 } | 2949 } |
| 2916 | 2950 |
| 2917 | 2951 |
| 2918 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2952 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
| 2919 ASSERT(!instr->HasObservableSideEffects()); | 2953 ASSERT(!instr->HasObservableSideEffects()); |
| 2920 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2954 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
| 2921 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2955 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
| 2922 instr->SetSuccessorAt(0, empty_true); | 2956 instr->SetSuccessorAt(0, empty_true); |
| 2923 instr->SetSuccessorAt(1, empty_false); | 2957 instr->SetSuccessorAt(1, empty_false); |
| 2924 owner()->current_block()->Finish(instr); | 2958 owner()->FinishCurrentBlock(instr); |
| 2925 empty_true->Goto(if_true(), owner()->function_state()); | 2959 owner()->Goto(empty_true, if_true(), owner()->function_state()); |
| 2926 empty_false->Goto(if_false(), owner()->function_state()); | 2960 owner()->Goto(empty_false, if_false(), owner()->function_state()); |
| 2927 owner()->set_current_block(NULL); | 2961 owner()->set_current_block(NULL); |
| 2928 } | 2962 } |
| 2929 | 2963 |
| 2930 | 2964 |
| 2931 void TestContext::ReturnContinuation(HIfContinuation* continuation, | 2965 void TestContext::ReturnContinuation(HIfContinuation* continuation, |
| 2932 BailoutId ast_id) { | 2966 BailoutId ast_id) { |
| 2933 HBasicBlock* true_branch = NULL; | 2967 HBasicBlock* true_branch = NULL; |
| 2934 HBasicBlock* false_branch = NULL; | 2968 HBasicBlock* false_branch = NULL; |
| 2935 continuation->Continue(&true_branch, &false_branch, NULL); | 2969 continuation->Continue(&true_branch, &false_branch); |
| 2936 if (continuation->IsTrueReachable()) { | 2970 if (continuation->IsTrueReachable()) { |
| 2937 true_branch->Goto(if_true(), owner()->function_state()); | 2971 owner()->Goto(true_branch, if_true(), owner()->function_state()); |
| 2938 } | 2972 } |
| 2939 if (continuation->IsFalseReachable()) { | 2973 if (continuation->IsFalseReachable()) { |
| 2940 false_branch->Goto(if_false(), owner()->function_state()); | 2974 owner()->Goto(false_branch, if_false(), owner()->function_state()); |
| 2941 } | 2975 } |
| 2942 owner()->set_current_block(NULL); | 2976 owner()->set_current_block(NULL); |
| 2943 } | 2977 } |
| 2944 | 2978 |
| 2945 | 2979 |
| 2946 void TestContext::BuildBranch(HValue* value) { | 2980 void TestContext::BuildBranch(HValue* value) { |
| 2947 // We expect the graph to be in edge-split form: there is no edge that | 2981 // We expect the graph to be in edge-split form: there is no edge that |
| 2948 // connects a branch node to a join node. We conservatively ensure that | 2982 // connects a branch node to a join node. We conservatively ensure that |
| 2949 // property by always adding an empty block on the outgoing edges of this | 2983 // property by always adding an empty block on the outgoing edges of this |
| 2950 // branch. | 2984 // branch. |
| 2951 HOptimizedGraphBuilder* builder = owner(); | 2985 HOptimizedGraphBuilder* builder = owner(); |
| 2952 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { | 2986 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { |
| 2953 builder->Bailout(kArgumentsObjectValueInATestContext); | 2987 builder->Bailout(kArgumentsObjectValueInATestContext); |
| 2954 } | 2988 } |
| 2955 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | 2989 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
| 2956 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | 2990 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
| 2957 ToBooleanStub::Types expected(condition()->to_boolean_types()); | 2991 ToBooleanStub::Types expected(condition()->to_boolean_types()); |
| 2958 builder->current_block()->Finish(builder->New<HBranch>( | 2992 builder->FinishCurrentBlock(builder->New<HBranch>( |
| 2959 value, expected, empty_true, empty_false)); | 2993 value, expected, empty_true, empty_false)); |
| 2960 | 2994 |
| 2961 empty_true->Goto(if_true(), builder->function_state()); | 2995 owner()->Goto(empty_true, if_true(), builder->function_state()); |
| 2962 empty_false->Goto(if_false(), builder->function_state()); | 2996 owner()->Goto(empty_false , if_false(), builder->function_state()); |
| 2963 builder->set_current_block(NULL); | 2997 builder->set_current_block(NULL); |
| 2964 } | 2998 } |
| 2965 | 2999 |
| 2966 | 3000 |
| 2967 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. | 3001 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. |
| 2968 #define CHECK_BAILOUT(call) \ | 3002 #define CHECK_BAILOUT(call) \ |
| 2969 do { \ | 3003 do { \ |
| 2970 call; \ | 3004 call; \ |
| 2971 if (HasStackOverflow()) return; \ | 3005 if (HasStackOverflow()) return; \ |
| 2972 } while (false) | 3006 } while (false) |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3069 // the body's entry block (along with some special logic for the start | 3103 // the body's entry block (along with some special logic for the start |
| 3070 // block in HInstruction::InsertAfter) seals the start block from | 3104 // block in HInstruction::InsertAfter) seals the start block from |
| 3071 // getting unwanted instructions inserted. | 3105 // getting unwanted instructions inserted. |
| 3072 // | 3106 // |
| 3073 // TODO(kmillikin): Fix this. Stop mutating the initial environment. | 3107 // TODO(kmillikin): Fix this. Stop mutating the initial environment. |
| 3074 // Make the Hydrogen instructions in the initial block into Hydrogen | 3108 // Make the Hydrogen instructions in the initial block into Hydrogen |
| 3075 // values (but not instructions), present in the initial environment and | 3109 // values (but not instructions), present in the initial environment and |
| 3076 // not replayed by the Lithium translation. | 3110 // not replayed by the Lithium translation. |
| 3077 HEnvironment* initial_env = environment()->CopyWithoutHistory(); | 3111 HEnvironment* initial_env = environment()->CopyWithoutHistory(); |
| 3078 HBasicBlock* body_entry = CreateBasicBlock(initial_env); | 3112 HBasicBlock* body_entry = CreateBasicBlock(initial_env); |
| 3079 current_block()->Goto(body_entry); | 3113 Goto(body_entry); |
| 3080 body_entry->SetJoinId(BailoutId::FunctionEntry()); | 3114 body_entry->SetJoinId(BailoutId::FunctionEntry()); |
| 3081 set_current_block(body_entry); | 3115 set_current_block(body_entry); |
| 3082 | 3116 |
| 3083 // Handle implicit declaration of the function name in named function | 3117 // Handle implicit declaration of the function name in named function |
| 3084 // expressions before other declarations. | 3118 // expressions before other declarations. |
| 3085 if (scope->is_function_scope() && scope->function() != NULL) { | 3119 if (scope->is_function_scope() && scope->function() != NULL) { |
| 3086 VisitVariableDeclaration(scope->function()); | 3120 VisitVariableDeclaration(scope->function()); |
| 3087 } | 3121 } |
| 3088 VisitDeclarations(scope->declarations()); | 3122 VisitDeclarations(scope->declarations()); |
| 3089 Add<HSimulate>(BailoutId::Declarations()); | 3123 Add<HSimulate>(BailoutId::Declarations()); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3312 ASSERT(current_block()->HasPredecessor()); | 3346 ASSERT(current_block()->HasPredecessor()); |
| 3313 if (stmt->scope() != NULL) { | 3347 if (stmt->scope() != NULL) { |
| 3314 return Bailout(kScopedBlock); | 3348 return Bailout(kScopedBlock); |
| 3315 } | 3349 } |
| 3316 BreakAndContinueInfo break_info(stmt); | 3350 BreakAndContinueInfo break_info(stmt); |
| 3317 { BreakAndContinueScope push(&break_info, this); | 3351 { BreakAndContinueScope push(&break_info, this); |
| 3318 CHECK_BAILOUT(VisitStatements(stmt->statements())); | 3352 CHECK_BAILOUT(VisitStatements(stmt->statements())); |
| 3319 } | 3353 } |
| 3320 HBasicBlock* break_block = break_info.break_block(); | 3354 HBasicBlock* break_block = break_info.break_block(); |
| 3321 if (break_block != NULL) { | 3355 if (break_block != NULL) { |
| 3322 if (current_block() != NULL) current_block()->Goto(break_block); | 3356 if (current_block() != NULL) Goto(break_block); |
| 3323 break_block->SetJoinId(stmt->ExitId()); | 3357 break_block->SetJoinId(stmt->ExitId()); |
| 3324 set_current_block(break_block); | 3358 set_current_block(break_block); |
| 3325 } | 3359 } |
| 3326 } | 3360 } |
| 3327 | 3361 |
| 3328 | 3362 |
| 3329 void HOptimizedGraphBuilder::VisitExpressionStatement( | 3363 void HOptimizedGraphBuilder::VisitExpressionStatement( |
| 3330 ExpressionStatement* stmt) { | 3364 ExpressionStatement* stmt) { |
| 3331 ASSERT(!HasStackOverflow()); | 3365 ASSERT(!HasStackOverflow()); |
| 3332 ASSERT(current_block() != NULL); | 3366 ASSERT(current_block() != NULL); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3422 | 3456 |
| 3423 void HOptimizedGraphBuilder::VisitContinueStatement( | 3457 void HOptimizedGraphBuilder::VisitContinueStatement( |
| 3424 ContinueStatement* stmt) { | 3458 ContinueStatement* stmt) { |
| 3425 ASSERT(!HasStackOverflow()); | 3459 ASSERT(!HasStackOverflow()); |
| 3426 ASSERT(current_block() != NULL); | 3460 ASSERT(current_block() != NULL); |
| 3427 ASSERT(current_block()->HasPredecessor()); | 3461 ASSERT(current_block()->HasPredecessor()); |
| 3428 int drop_extra = 0; | 3462 int drop_extra = 0; |
| 3429 HBasicBlock* continue_block = break_scope()->Get( | 3463 HBasicBlock* continue_block = break_scope()->Get( |
| 3430 stmt->target(), BreakAndContinueScope::CONTINUE, &drop_extra); | 3464 stmt->target(), BreakAndContinueScope::CONTINUE, &drop_extra); |
| 3431 Drop(drop_extra); | 3465 Drop(drop_extra); |
| 3432 current_block()->Goto(continue_block); | 3466 Goto(continue_block); |
| 3433 set_current_block(NULL); | 3467 set_current_block(NULL); |
| 3434 } | 3468 } |
| 3435 | 3469 |
| 3436 | 3470 |
| 3437 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 3471 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
| 3438 ASSERT(!HasStackOverflow()); | 3472 ASSERT(!HasStackOverflow()); |
| 3439 ASSERT(current_block() != NULL); | 3473 ASSERT(current_block() != NULL); |
| 3440 ASSERT(current_block()->HasPredecessor()); | 3474 ASSERT(current_block()->HasPredecessor()); |
| 3441 int drop_extra = 0; | 3475 int drop_extra = 0; |
| 3442 HBasicBlock* break_block = break_scope()->Get( | 3476 HBasicBlock* break_block = break_scope()->Get( |
| 3443 stmt->target(), BreakAndContinueScope::BREAK, &drop_extra); | 3477 stmt->target(), BreakAndContinueScope::BREAK, &drop_extra); |
| 3444 Drop(drop_extra); | 3478 Drop(drop_extra); |
| 3445 current_block()->Goto(break_block); | 3479 Goto(break_block); |
| 3446 set_current_block(NULL); | 3480 set_current_block(NULL); |
| 3447 } | 3481 } |
| 3448 | 3482 |
| 3449 | 3483 |
| 3450 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 3484 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| 3451 ASSERT(!HasStackOverflow()); | 3485 ASSERT(!HasStackOverflow()); |
| 3452 ASSERT(current_block() != NULL); | 3486 ASSERT(current_block() != NULL); |
| 3453 ASSERT(current_block()->HasPredecessor()); | 3487 ASSERT(current_block()->HasPredecessor()); |
| 3454 FunctionState* state = function_state(); | 3488 FunctionState* state = function_state(); |
| 3455 AstContext* context = call_context(); | 3489 AstContext* context = call_context(); |
| 3456 if (context == NULL) { | 3490 if (context == NULL) { |
| 3457 // Not an inlined return, so an actual one. | 3491 // Not an inlined return, so an actual one. |
| 3458 CHECK_ALIVE(VisitForValue(stmt->expression())); | 3492 CHECK_ALIVE(VisitForValue(stmt->expression())); |
| 3459 HValue* result = environment()->Pop(); | 3493 HValue* result = environment()->Pop(); |
| 3460 Add<HReturn>(result); | 3494 Add<HReturn>(result); |
| 3461 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 3495 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
| 3462 // Return from an inlined construct call. In a test context the return value | 3496 // Return from an inlined construct call. In a test context the return value |
| 3463 // will always evaluate to true, in a value context the return value needs | 3497 // will always evaluate to true, in a value context the return value needs |
| 3464 // to be a JSObject. | 3498 // to be a JSObject. |
| 3465 if (context->IsTest()) { | 3499 if (context->IsTest()) { |
| 3466 TestContext* test = TestContext::cast(context); | 3500 TestContext* test = TestContext::cast(context); |
| 3467 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3501 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
| 3468 current_block()->Goto(test->if_true(), state); | 3502 Goto(test->if_true(), state); |
| 3469 } else if (context->IsEffect()) { | 3503 } else if (context->IsEffect()) { |
| 3470 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3504 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
| 3471 current_block()->Goto(function_return(), state); | 3505 Goto(function_return(), state); |
| 3472 } else { | 3506 } else { |
| 3473 ASSERT(context->IsValue()); | 3507 ASSERT(context->IsValue()); |
| 3474 CHECK_ALIVE(VisitForValue(stmt->expression())); | 3508 CHECK_ALIVE(VisitForValue(stmt->expression())); |
| 3475 HValue* return_value = Pop(); | 3509 HValue* return_value = Pop(); |
| 3476 HValue* receiver = environment()->arguments_environment()->Lookup(0); | 3510 HValue* receiver = environment()->arguments_environment()->Lookup(0); |
| 3477 HHasInstanceTypeAndBranch* typecheck = | 3511 HHasInstanceTypeAndBranch* typecheck = |
| 3478 New<HHasInstanceTypeAndBranch>(return_value, | 3512 New<HHasInstanceTypeAndBranch>(return_value, |
| 3479 FIRST_SPEC_OBJECT_TYPE, | 3513 FIRST_SPEC_OBJECT_TYPE, |
| 3480 LAST_SPEC_OBJECT_TYPE); | 3514 LAST_SPEC_OBJECT_TYPE); |
| 3481 HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); | 3515 HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); |
| 3482 HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); | 3516 HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); |
| 3483 typecheck->SetSuccessorAt(0, if_spec_object); | 3517 typecheck->SetSuccessorAt(0, if_spec_object); |
| 3484 typecheck->SetSuccessorAt(1, not_spec_object); | 3518 typecheck->SetSuccessorAt(1, not_spec_object); |
| 3485 current_block()->Finish(typecheck); | 3519 FinishCurrentBlock(typecheck); |
| 3486 if_spec_object->AddLeaveInlined(return_value, state); | 3520 AddLeaveInlined(if_spec_object, return_value, state); |
| 3487 not_spec_object->AddLeaveInlined(receiver, state); | 3521 AddLeaveInlined(not_spec_object, receiver, state); |
| 3488 } | 3522 } |
| 3489 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { | 3523 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { |
| 3490 // Return from an inlined setter call. The returned value is never used, the | 3524 // Return from an inlined setter call. The returned value is never used, the |
| 3491 // value of an assignment is always the value of the RHS of the assignment. | 3525 // value of an assignment is always the value of the RHS of the assignment. |
| 3492 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3526 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
| 3493 if (context->IsTest()) { | 3527 if (context->IsTest()) { |
| 3494 HValue* rhs = environment()->arguments_environment()->Lookup(1); | 3528 HValue* rhs = environment()->arguments_environment()->Lookup(1); |
| 3495 context->ReturnValue(rhs); | 3529 context->ReturnValue(rhs); |
| 3496 } else if (context->IsEffect()) { | 3530 } else if (context->IsEffect()) { |
| 3497 current_block()->Goto(function_return(), state); | 3531 Goto(function_return(), state); |
| 3498 } else { | 3532 } else { |
| 3499 ASSERT(context->IsValue()); | 3533 ASSERT(context->IsValue()); |
| 3500 HValue* rhs = environment()->arguments_environment()->Lookup(1); | 3534 HValue* rhs = environment()->arguments_environment()->Lookup(1); |
| 3501 current_block()->AddLeaveInlined(rhs, state); | 3535 AddLeaveInlined(rhs, state); |
| 3502 } | 3536 } |
| 3503 } else { | 3537 } else { |
| 3504 // Return from a normal inlined function. Visit the subexpression in the | 3538 // Return from a normal inlined function. Visit the subexpression in the |
| 3505 // expression context of the call. | 3539 // expression context of the call. |
| 3506 if (context->IsTest()) { | 3540 if (context->IsTest()) { |
| 3507 TestContext* test = TestContext::cast(context); | 3541 TestContext* test = TestContext::cast(context); |
| 3508 VisitForControl(stmt->expression(), test->if_true(), test->if_false()); | 3542 VisitForControl(stmt->expression(), test->if_true(), test->if_false()); |
| 3509 } else if (context->IsEffect()) { | 3543 } else if (context->IsEffect()) { |
| 3510 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3544 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
| 3511 current_block()->Goto(function_return(), state); | 3545 Goto(function_return(), state); |
| 3512 } else { | 3546 } else { |
| 3513 ASSERT(context->IsValue()); | 3547 ASSERT(context->IsValue()); |
| 3514 CHECK_ALIVE(VisitForValue(stmt->expression())); | 3548 CHECK_ALIVE(VisitForValue(stmt->expression())); |
| 3515 current_block()->AddLeaveInlined(Pop(), state); | 3549 AddLeaveInlined(Pop(), state); |
| 3516 } | 3550 } |
| 3517 } | 3551 } |
| 3518 set_current_block(NULL); | 3552 set_current_block(NULL); |
| 3519 } | 3553 } |
| 3520 | 3554 |
| 3521 | 3555 |
| 3522 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 3556 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
| 3523 ASSERT(!HasStackOverflow()); | 3557 ASSERT(!HasStackOverflow()); |
| 3524 ASSERT(current_block() != NULL); | 3558 ASSERT(current_block() != NULL); |
| 3525 ASSERT(current_block()->HasPredecessor()); | 3559 ASSERT(current_block()->HasPredecessor()); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3553 | 3587 |
| 3554 HUnaryControlInstruction* string_check = NULL; | 3588 HUnaryControlInstruction* string_check = NULL; |
| 3555 HBasicBlock* not_string_block = NULL; | 3589 HBasicBlock* not_string_block = NULL; |
| 3556 | 3590 |
| 3557 // Test switch's tag value if all clauses are string literals | 3591 // Test switch's tag value if all clauses are string literals |
| 3558 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { | 3592 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { |
| 3559 first_test_block = graph()->CreateBasicBlock(); | 3593 first_test_block = graph()->CreateBasicBlock(); |
| 3560 not_string_block = graph()->CreateBasicBlock(); | 3594 not_string_block = graph()->CreateBasicBlock(); |
| 3561 string_check = New<HIsStringAndBranch>( | 3595 string_check = New<HIsStringAndBranch>( |
| 3562 tag_value, first_test_block, not_string_block); | 3596 tag_value, first_test_block, not_string_block); |
| 3563 current_block()->Finish(string_check); | 3597 FinishCurrentBlock(string_check); |
| 3564 | 3598 |
| 3565 set_current_block(first_test_block); | 3599 set_current_block(first_test_block); |
| 3566 } | 3600 } |
| 3567 | 3601 |
| 3568 // 1. Build all the tests, with dangling true branches | 3602 // 1. Build all the tests, with dangling true branches |
| 3569 BailoutId default_id = BailoutId::None(); | 3603 BailoutId default_id = BailoutId::None(); |
| 3570 for (int i = 0; i < clause_count; ++i) { | 3604 for (int i = 0; i < clause_count; ++i) { |
| 3571 CaseClause* clause = clauses->at(i); | 3605 CaseClause* clause = clauses->at(i); |
| 3572 if (clause->is_default()) { | 3606 if (clause->is_default()) { |
| 3573 default_id = clause->EntryId(); | 3607 default_id = clause->EntryId(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3596 Representation::Smi(), Representation::Smi()); | 3630 Representation::Smi(), Representation::Smi()); |
| 3597 compare = compare_; | 3631 compare = compare_; |
| 3598 } else { | 3632 } else { |
| 3599 compare = New<HStringCompareAndBranch>(tag_value, | 3633 compare = New<HStringCompareAndBranch>(tag_value, |
| 3600 label_value, | 3634 label_value, |
| 3601 Token::EQ_STRICT); | 3635 Token::EQ_STRICT); |
| 3602 } | 3636 } |
| 3603 | 3637 |
| 3604 compare->SetSuccessorAt(0, body_block); | 3638 compare->SetSuccessorAt(0, body_block); |
| 3605 compare->SetSuccessorAt(1, next_test_block); | 3639 compare->SetSuccessorAt(1, next_test_block); |
| 3606 current_block()->Finish(compare); | 3640 FinishCurrentBlock(compare); |
| 3607 | 3641 |
| 3608 set_current_block(next_test_block); | 3642 set_current_block(next_test_block); |
| 3609 } | 3643 } |
| 3610 | 3644 |
| 3611 // Save the current block to use for the default or to join with the | 3645 // Save the current block to use for the default or to join with the |
| 3612 // exit. | 3646 // exit. |
| 3613 HBasicBlock* last_block = current_block(); | 3647 HBasicBlock* last_block = current_block(); |
| 3614 | 3648 |
| 3615 if (not_string_block != NULL) { | 3649 if (not_string_block != NULL) { |
| 3616 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId(); | 3650 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId(); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3677 } | 3711 } |
| 3678 | 3712 |
| 3679 // Create an up-to-3-way join. Use the break block if it exists since | 3713 // Create an up-to-3-way join. Use the break block if it exists since |
| 3680 // it's already a join block. | 3714 // it's already a join block. |
| 3681 HBasicBlock* break_block = break_info.break_block(); | 3715 HBasicBlock* break_block = break_info.break_block(); |
| 3682 if (break_block == NULL) { | 3716 if (break_block == NULL) { |
| 3683 set_current_block(CreateJoin(fall_through_block, | 3717 set_current_block(CreateJoin(fall_through_block, |
| 3684 last_block, | 3718 last_block, |
| 3685 stmt->ExitId())); | 3719 stmt->ExitId())); |
| 3686 } else { | 3720 } else { |
| 3687 if (fall_through_block != NULL) fall_through_block->Goto(break_block); | 3721 if (fall_through_block != NULL) Goto(fall_through_block, break_block); |
| 3688 if (last_block != NULL) last_block->Goto(break_block); | 3722 if (last_block != NULL) Goto(last_block, break_block); |
| 3689 break_block->SetJoinId(stmt->ExitId()); | 3723 break_block->SetJoinId(stmt->ExitId()); |
| 3690 set_current_block(break_block); | 3724 set_current_block(break_block); |
| 3691 } | 3725 } |
| 3692 } | 3726 } |
| 3693 | 3727 |
| 3694 | 3728 |
| 3695 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 3729 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
| 3696 HBasicBlock* loop_entry, | 3730 HBasicBlock* loop_entry, |
| 3697 BreakAndContinueInfo* break_info) { | 3731 BreakAndContinueInfo* break_info) { |
| 3698 BreakAndContinueScope push(break_info, this); | 3732 BreakAndContinueScope push(break_info, this); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3883 HCompareNumericAndBranch* compare_index = | 3917 HCompareNumericAndBranch* compare_index = |
| 3884 New<HCompareNumericAndBranch>(index, limit, Token::LT); | 3918 New<HCompareNumericAndBranch>(index, limit, Token::LT); |
| 3885 compare_index->set_observed_input_representation( | 3919 compare_index->set_observed_input_representation( |
| 3886 Representation::Smi(), Representation::Smi()); | 3920 Representation::Smi(), Representation::Smi()); |
| 3887 | 3921 |
| 3888 HBasicBlock* loop_body = graph()->CreateBasicBlock(); | 3922 HBasicBlock* loop_body = graph()->CreateBasicBlock(); |
| 3889 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); | 3923 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); |
| 3890 | 3924 |
| 3891 compare_index->SetSuccessorAt(0, loop_body); | 3925 compare_index->SetSuccessorAt(0, loop_body); |
| 3892 compare_index->SetSuccessorAt(1, loop_successor); | 3926 compare_index->SetSuccessorAt(1, loop_successor); |
| 3893 current_block()->Finish(compare_index); | 3927 FinishCurrentBlock(compare_index); |
| 3894 | 3928 |
| 3895 set_current_block(loop_successor); | 3929 set_current_block(loop_successor); |
| 3896 Drop(5); | 3930 Drop(5); |
| 3897 | 3931 |
| 3898 set_current_block(loop_body); | 3932 set_current_block(loop_body); |
| 3899 | 3933 |
| 3900 HValue* key = Add<HLoadKeyed>( | 3934 HValue* key = Add<HLoadKeyed>( |
| 3901 environment()->ExpressionStackAt(2), // Enum cache. | 3935 environment()->ExpressionStackAt(2), // Enum cache. |
| 3902 environment()->ExpressionStackAt(0), // Iteration index. | 3936 environment()->ExpressionStackAt(0), // Iteration index. |
| 3903 environment()->ExpressionStackAt(0), | 3937 environment()->ExpressionStackAt(0), |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4134 } | 4168 } |
| 4135 } else { | 4169 } else { |
| 4136 HValue* context = environment()->context(); | 4170 HValue* context = environment()->context(); |
| 4137 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 4171 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 4138 AddInstruction(global_object); | 4172 AddInstruction(global_object); |
| 4139 HLoadGlobalGeneric* instr = | 4173 HLoadGlobalGeneric* instr = |
| 4140 new(zone()) HLoadGlobalGeneric(context, | 4174 new(zone()) HLoadGlobalGeneric(context, |
| 4141 global_object, | 4175 global_object, |
| 4142 variable->name(), | 4176 variable->name(), |
| 4143 ast_context()->is_for_typeof()); | 4177 ast_context()->is_for_typeof()); |
| 4144 instr->set_position(expr->position()); | |
| 4145 return ast_context()->ReturnInstruction(instr, expr->id()); | 4178 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4146 } | 4179 } |
| 4147 } | 4180 } |
| 4148 | 4181 |
| 4149 case Variable::PARAMETER: | 4182 case Variable::PARAMETER: |
| 4150 case Variable::LOCAL: { | 4183 case Variable::LOCAL: { |
| 4151 HValue* value = LookupAndMakeLive(variable); | 4184 HValue* value = LookupAndMakeLive(variable); |
| 4152 if (value == graph()->GetConstantHole()) { | 4185 if (value == graph()->GetConstantHole()) { |
| 4153 ASSERT(IsDeclaredVariableMode(variable->mode()) && | 4186 ASSERT(IsDeclaredVariableMode(variable->mode()) && |
| 4154 variable->mode() != VAR); | 4187 variable->mode() != VAR); |
| (...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4872 Add<HPushArgument>(Pop()); | 4905 Add<HPushArgument>(Pop()); |
| 4873 return New<HCallConstantFunction>(info->accessor(), 1); | 4906 return New<HCallConstantFunction>(info->accessor(), 1); |
| 4874 } | 4907 } |
| 4875 | 4908 |
| 4876 ASSERT(info->lookup()->IsConstant()); | 4909 ASSERT(info->lookup()->IsConstant()); |
| 4877 return New<HConstant>(info->constant()); | 4910 return New<HConstant>(info->constant()); |
| 4878 } | 4911 } |
| 4879 | 4912 |
| 4880 | 4913 |
| 4881 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 4914 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
| 4882 int position, | |
| 4883 BailoutId ast_id, | 4915 BailoutId ast_id, |
| 4884 BailoutId return_id, | 4916 BailoutId return_id, |
| 4885 HValue* object, | 4917 HValue* object, |
| 4886 SmallMapList* types, | 4918 SmallMapList* types, |
| 4887 Handle<String> name) { | 4919 Handle<String> name) { |
| 4888 // Something did not match; must use a polymorphic load. | 4920 // Something did not match; must use a polymorphic load. |
| 4889 int count = 0; | 4921 int count = 0; |
| 4890 HBasicBlock* join = NULL; | 4922 HBasicBlock* join = NULL; |
| 4891 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 4923 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| 4892 PropertyAccessInfo info(isolate(), types->at(i), name); | 4924 PropertyAccessInfo info(isolate(), types->at(i), name); |
| 4893 if (info.CanLoadMonomorphic()) { | 4925 if (info.CanLoadMonomorphic()) { |
| 4894 if (count == 0) { | 4926 if (count == 0) { |
| 4895 BuildCheckHeapObject(object); | 4927 BuildCheckHeapObject(object); |
| 4896 join = graph()->CreateBasicBlock(); | 4928 join = graph()->CreateBasicBlock(); |
| 4897 } | 4929 } |
| 4898 ++count; | 4930 ++count; |
| 4899 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 4931 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 4900 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 4932 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 4901 HCompareMap* compare = New<HCompareMap>( | 4933 HCompareMap* compare = New<HCompareMap>( |
| 4902 object, info.map(), if_true, if_false); | 4934 object, info.map(), if_true, if_false); |
| 4903 current_block()->Finish(compare); | 4935 FinishCurrentBlock(compare); |
| 4904 | 4936 |
| 4905 set_current_block(if_true); | 4937 set_current_block(if_true); |
| 4906 | 4938 |
| 4907 HInstruction* load = BuildLoadMonomorphic( | 4939 HInstruction* load = BuildLoadMonomorphic( |
| 4908 &info, object, compare, ast_id, return_id, FLAG_polymorphic_inlining); | 4940 &info, object, compare, ast_id, return_id, FLAG_polymorphic_inlining); |
| 4909 if (load == NULL) { | 4941 if (load == NULL) { |
| 4910 if (HasStackOverflow()) return; | 4942 if (HasStackOverflow()) return; |
| 4911 } else { | 4943 } else { |
| 4912 if (!load->IsLinked()) { | 4944 if (!load->IsLinked()) { |
| 4913 load->set_position(position); | |
| 4914 AddInstruction(load); | 4945 AddInstruction(load); |
| 4915 } | 4946 } |
| 4916 if (!ast_context()->IsEffect()) Push(load); | 4947 if (!ast_context()->IsEffect()) Push(load); |
| 4917 } | 4948 } |
| 4918 | 4949 |
| 4919 if (current_block() != NULL) current_block()->Goto(join); | 4950 if (current_block() != NULL) Goto(join); |
| 4920 set_current_block(if_false); | 4951 set_current_block(if_false); |
| 4921 } | 4952 } |
| 4922 } | 4953 } |
| 4923 | 4954 |
| 4924 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 4955 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 4925 // know about and do not want to handle ones we've never seen. Otherwise | 4956 // know about and do not want to handle ones we've never seen. Otherwise |
| 4926 // use a generic IC. | 4957 // use a generic IC. |
| 4927 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 4958 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 4928 // Because the deopt may be the only path in the polymorphic load, make sure | 4959 // Because the deopt may be the only path in the polymorphic load, make sure |
| 4929 // that the environment stack matches the depth on deopt that it otherwise | 4960 // that the environment stack matches the depth on deopt that it otherwise |
| 4930 // would have had after a successful load. | 4961 // would have had after a successful load. |
| 4931 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 4962 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
| 4932 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); | 4963 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); |
| 4933 } else { | 4964 } else { |
| 4934 HValue* context = environment()->context(); | 4965 HValue* context = environment()->context(); |
| 4935 HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name); | 4966 HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name); |
| 4936 load->set_position(position); | |
| 4937 AddInstruction(load); | 4967 AddInstruction(load); |
| 4938 if (!ast_context()->IsEffect()) Push(load); | 4968 if (!ast_context()->IsEffect()) Push(load); |
| 4939 | 4969 |
| 4940 if (join != NULL) { | 4970 if (join != NULL) { |
| 4941 current_block()->Goto(join); | 4971 Goto(join); |
| 4942 } else { | 4972 } else { |
| 4943 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 4973 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 4944 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 4974 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 4945 return; | 4975 return; |
| 4946 } | 4976 } |
| 4947 } | 4977 } |
| 4948 | 4978 |
| 4949 ASSERT(join != NULL); | 4979 ASSERT(join != NULL); |
| 4950 join->SetJoinId(ast_id); | 4980 join->SetJoinId(ast_id); |
| 4951 set_current_block(join); | 4981 set_current_block(join); |
| 4952 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 4982 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 4953 } | 4983 } |
| 4954 | 4984 |
| 4955 | 4985 |
| 4956 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( | 4986 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
| 4957 int position, | |
| 4958 BailoutId assignment_id, | 4987 BailoutId assignment_id, |
| 4959 HValue* object, | 4988 HValue* object, |
| 4960 HValue* value, | 4989 HValue* value, |
| 4961 SmallMapList* types, | 4990 SmallMapList* types, |
| 4962 Handle<String> name) { | 4991 Handle<String> name) { |
| 4963 // Use monomorphic store if property lookup results in the same field index | 4992 // Use monomorphic store if property lookup results in the same field index |
| 4964 // for all maps. Requires special map check on the set of all handled maps. | 4993 // for all maps. Requires special map check on the set of all handled maps. |
| 4965 if (types->length() > kMaxStorePolymorphism) return false; | 4994 if (types->length() > kMaxStorePolymorphism) return false; |
| 4966 | 4995 |
| 4967 LookupResult lookup(isolate()); | 4996 LookupResult lookup(isolate()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 4997 | 5026 |
| 4998 // Everything matched; can use monomorphic store. | 5027 // Everything matched; can use monomorphic store. |
| 4999 BuildCheckHeapObject(object); | 5028 BuildCheckHeapObject(object); |
| 5000 HCheckMaps* checked_object = Add<HCheckMaps>(object, types); | 5029 HCheckMaps* checked_object = Add<HCheckMaps>(object, types); |
| 5001 HInstruction* store; | 5030 HInstruction* store; |
| 5002 CHECK_ALIVE_OR_RETURN( | 5031 CHECK_ALIVE_OR_RETURN( |
| 5003 store = BuildStoreNamedField( | 5032 store = BuildStoreNamedField( |
| 5004 checked_object, name, value, types->at(count - 1), &lookup), | 5033 checked_object, name, value, types->at(count - 1), &lookup), |
| 5005 true); | 5034 true); |
| 5006 if (!ast_context()->IsEffect()) Push(value); | 5035 if (!ast_context()->IsEffect()) Push(value); |
| 5007 store->set_position(position); | |
| 5008 AddInstruction(store); | 5036 AddInstruction(store); |
| 5009 Add<HSimulate>(assignment_id); | 5037 Add<HSimulate>(assignment_id); |
| 5010 if (!ast_context()->IsEffect()) Drop(1); | 5038 if (!ast_context()->IsEffect()) Drop(1); |
| 5011 ast_context()->ReturnValue(value); | 5039 ast_context()->ReturnValue(value); |
| 5012 return true; | 5040 return true; |
| 5013 } | 5041 } |
| 5014 | 5042 |
| 5015 | 5043 |
| 5016 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 5044 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| 5017 int position, | |
| 5018 BailoutId assignment_id, | 5045 BailoutId assignment_id, |
| 5019 HValue* object, | 5046 HValue* object, |
| 5020 HValue* value, | 5047 HValue* value, |
| 5021 SmallMapList* types, | 5048 SmallMapList* types, |
| 5022 Handle<String> name) { | 5049 Handle<String> name) { |
| 5023 if (TryStorePolymorphicAsMonomorphic( | 5050 if (TryStorePolymorphicAsMonomorphic( |
| 5024 position, assignment_id, object, value, types, name)) { | 5051 assignment_id, object, value, types, name)) { |
| 5025 return; | 5052 return; |
| 5026 } | 5053 } |
| 5027 | 5054 |
| 5028 // TODO(ager): We should recognize when the prototype chains for different | 5055 // TODO(ager): We should recognize when the prototype chains for different |
| 5029 // maps are identical. In that case we can avoid repeatedly generating the | 5056 // maps are identical. In that case we can avoid repeatedly generating the |
| 5030 // same prototype map checks. | 5057 // same prototype map checks. |
| 5031 int count = 0; | 5058 int count = 0; |
| 5032 HBasicBlock* join = NULL; | 5059 HBasicBlock* join = NULL; |
| 5033 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 5060 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
| 5034 Handle<Map> map = types->at(i); | 5061 Handle<Map> map = types->at(i); |
| 5035 LookupResult lookup(isolate()); | 5062 LookupResult lookup(isolate()); |
| 5036 if (ComputeStoreField(map, name, &lookup)) { | 5063 if (ComputeStoreField(map, name, &lookup)) { |
| 5037 if (count == 0) { | 5064 if (count == 0) { |
| 5038 BuildCheckHeapObject(object); | 5065 BuildCheckHeapObject(object); |
| 5039 join = graph()->CreateBasicBlock(); | 5066 join = graph()->CreateBasicBlock(); |
| 5040 } | 5067 } |
| 5041 ++count; | 5068 ++count; |
| 5042 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5069 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 5043 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5070 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 5044 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false); | 5071 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false); |
| 5045 current_block()->Finish(compare); | 5072 FinishCurrentBlock(compare); |
| 5046 | 5073 |
| 5047 set_current_block(if_true); | 5074 set_current_block(if_true); |
| 5048 HInstruction* instr; | 5075 HInstruction* instr; |
| 5049 CHECK_ALIVE(instr = BuildStoreNamedField( | 5076 CHECK_ALIVE(instr = BuildStoreNamedField( |
| 5050 compare, name, value, map, &lookup)); | 5077 compare, name, value, map, &lookup)); |
| 5051 instr->set_position(position); | |
| 5052 // Goto will add the HSimulate for the store. | 5078 // Goto will add the HSimulate for the store. |
| 5053 AddInstruction(instr); | 5079 AddInstruction(instr); |
| 5054 if (!ast_context()->IsEffect()) Push(value); | 5080 if (!ast_context()->IsEffect()) Push(value); |
| 5055 current_block()->Goto(join); | 5081 Goto(join); |
| 5056 | 5082 |
| 5057 set_current_block(if_false); | 5083 set_current_block(if_false); |
| 5058 } | 5084 } |
| 5059 } | 5085 } |
| 5060 | 5086 |
| 5061 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 5087 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 5062 // know about and do not want to handle ones we've never seen. Otherwise | 5088 // know about and do not want to handle ones we've never seen. Otherwise |
| 5063 // use a generic IC. | 5089 // use a generic IC. |
| 5064 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 5090 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 5065 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join); | 5091 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join); |
| 5066 } else { | 5092 } else { |
| 5067 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); | 5093 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); |
| 5068 instr->set_position(position); | |
| 5069 AddInstruction(instr); | 5094 AddInstruction(instr); |
| 5070 | 5095 |
| 5071 if (join != NULL) { | 5096 if (join != NULL) { |
| 5072 if (!ast_context()->IsEffect()) { | 5097 if (!ast_context()->IsEffect()) { |
| 5073 Push(value); | 5098 Push(value); |
| 5074 } | 5099 } |
| 5075 current_block()->Goto(join); | 5100 Goto(join); |
| 5076 } else { | 5101 } else { |
| 5077 // The HSimulate for the store should not see the stored value in | 5102 // The HSimulate for the store should not see the stored value in |
| 5078 // effect contexts (it is not materialized at expr->id() in the | 5103 // effect contexts (it is not materialized at expr->id() in the |
| 5079 // unoptimized code). | 5104 // unoptimized code). |
| 5080 if (instr->HasObservableSideEffects()) { | 5105 if (instr->HasObservableSideEffects()) { |
| 5081 if (ast_context()->IsEffect()) { | 5106 if (ast_context()->IsEffect()) { |
| 5082 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); | 5107 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
| 5083 } else { | 5108 } else { |
| 5084 Push(value); | 5109 Push(value); |
| 5085 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); | 5110 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5120 BailoutId return_id, | 5145 BailoutId return_id, |
| 5121 bool is_uninitialized) { | 5146 bool is_uninitialized) { |
| 5122 HValue* value = environment()->ExpressionStackAt(0); | 5147 HValue* value = environment()->ExpressionStackAt(0); |
| 5123 | 5148 |
| 5124 if (!prop->key()->IsPropertyName()) { | 5149 if (!prop->key()->IsPropertyName()) { |
| 5125 // Keyed store. | 5150 // Keyed store. |
| 5126 HValue* key = environment()->ExpressionStackAt(1); | 5151 HValue* key = environment()->ExpressionStackAt(1); |
| 5127 HValue* object = environment()->ExpressionStackAt(2); | 5152 HValue* object = environment()->ExpressionStackAt(2); |
| 5128 bool has_side_effects = false; | 5153 bool has_side_effects = false; |
| 5129 HandleKeyedElementAccess(object, key, value, expr, return_id, | 5154 HandleKeyedElementAccess(object, key, value, expr, return_id, |
| 5130 expr->position(), | |
| 5131 true, // is_store | 5155 true, // is_store |
| 5132 &has_side_effects); | 5156 &has_side_effects); |
| 5133 Drop(3); | 5157 Drop(3); |
| 5134 Push(value); | 5158 Push(value); |
| 5135 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); | 5159 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); |
| 5136 return ast_context()->ReturnValue(Pop()); | 5160 return ast_context()->ReturnValue(Pop()); |
| 5137 } | 5161 } |
| 5138 | 5162 |
| 5139 // Named store. | 5163 // Named store. |
| 5140 HValue* object = environment()->ExpressionStackAt(1); | 5164 HValue* object = environment()->ExpressionStackAt(1); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 5169 instr = New<HCallConstantFunction>(setter, 2); | 5193 instr = New<HCallConstantFunction>(setter, 2); |
| 5170 } else { | 5194 } else { |
| 5171 Drop(2); | 5195 Drop(2); |
| 5172 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | 5196 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
| 5173 name, | 5197 name, |
| 5174 value, | 5198 value, |
| 5175 map)); | 5199 map)); |
| 5176 } | 5200 } |
| 5177 } else if (types != NULL && types->length() > 1) { | 5201 } else if (types != NULL && types->length() > 1) { |
| 5178 Drop(2); | 5202 Drop(2); |
| 5179 return HandlePolymorphicStoreNamedField( | 5203 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name); |
| 5180 expr->position(), ast_id, object, value, types, name); | |
| 5181 } else { | 5204 } else { |
| 5182 Drop(2); | 5205 Drop(2); |
| 5183 instr = BuildStoreNamedGeneric(object, name, value); | 5206 instr = BuildStoreNamedGeneric(object, name, value); |
| 5184 } | 5207 } |
| 5185 | 5208 |
| 5186 if (!ast_context()->IsEffect()) Push(value); | 5209 if (!ast_context()->IsEffect()) Push(value); |
| 5187 instr->set_position(expr->position()); | |
| 5188 AddInstruction(instr); | 5210 AddInstruction(instr); |
| 5189 if (instr->HasObservableSideEffects()) { | 5211 if (instr->HasObservableSideEffects()) { |
| 5190 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5212 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5191 } | 5213 } |
| 5192 if (!ast_context()->IsEffect()) Drop(1); | 5214 if (!ast_context()->IsEffect()) Drop(1); |
| 5193 return ast_context()->ReturnValue(value); | 5215 return ast_context()->ReturnValue(value); |
| 5194 } | 5216 } |
| 5195 | 5217 |
| 5196 | 5218 |
| 5197 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 5219 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 5198 Property* prop = expr->target()->AsProperty(); | 5220 Property* prop = expr->target()->AsProperty(); |
| 5199 ASSERT(prop != NULL); | 5221 ASSERT(prop != NULL); |
| 5200 CHECK_ALIVE(VisitForValue(prop->obj())); | 5222 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5201 if (!prop->key()->IsPropertyName()) { | 5223 if (!prop->key()->IsPropertyName()) { |
| 5202 CHECK_ALIVE(VisitForValue(prop->key())); | 5224 CHECK_ALIVE(VisitForValue(prop->key())); |
| 5203 } | 5225 } |
| 5204 CHECK_ALIVE(VisitForValue(expr->value())); | 5226 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5205 BuildStore(expr, prop, expr->id(), | 5227 BuildStore(expr, prop, expr->id(), |
| 5206 expr->AssignmentId(), expr->IsUninitialized()); | 5228 expr->AssignmentId(), expr->IsUninitialized()); |
| 5207 } | 5229 } |
| 5208 | 5230 |
| 5209 | 5231 |
| 5210 // Because not every expression has a position and there is not common | 5232 // Because not every expression has a position and there is not common |
| 5211 // superclass of Assignment and CountOperation, we cannot just pass the | 5233 // superclass of Assignment and CountOperation, we cannot just pass the |
| 5212 // owning expression instead of position and ast_id separately. | 5234 // owning expression instead of position and ast_id separately. |
| 5213 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 5235 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 5214 Variable* var, | 5236 Variable* var, |
| 5215 HValue* value, | 5237 HValue* value, |
| 5216 int position, | |
| 5217 BailoutId ast_id) { | 5238 BailoutId ast_id) { |
| 5218 LookupResult lookup(isolate()); | 5239 LookupResult lookup(isolate()); |
| 5219 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 5240 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 5220 if (type == kUseCell) { | 5241 if (type == kUseCell) { |
| 5221 Handle<GlobalObject> global(current_info()->global_object()); | 5242 Handle<GlobalObject> global(current_info()->global_object()); |
| 5222 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 5243 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 5223 if (cell->type()->IsConstant()) { | 5244 if (cell->type()->IsConstant()) { |
| 5224 IfBuilder builder(this); | 5245 IfBuilder builder(this); |
| 5225 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); | 5246 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); |
| 5226 if (cell->type()->AsConstant()->IsNumber()) { | 5247 if (cell->type()->AsConstant()->IsNumber()) { |
| 5227 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); | 5248 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); |
| 5228 } else { | 5249 } else { |
| 5229 builder.If<HCompareObjectEqAndBranch>(value, constant); | 5250 builder.If<HCompareObjectEqAndBranch>(value, constant); |
| 5230 } | 5251 } |
| 5231 builder.Then(); | 5252 builder.Then(); |
| 5232 builder.Else(); | 5253 builder.Else(); |
| 5233 Add<HDeoptimize>("Constant global variable assignment", | 5254 Add<HDeoptimize>("Constant global variable assignment", |
| 5234 Deoptimizer::EAGER); | 5255 Deoptimizer::EAGER); |
| 5235 builder.End(); | 5256 builder.End(); |
| 5236 } | 5257 } |
| 5237 HInstruction* instr = | 5258 HInstruction* instr = |
| 5238 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | 5259 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
| 5239 instr->set_position(position); | |
| 5240 if (instr->HasObservableSideEffects()) { | 5260 if (instr->HasObservableSideEffects()) { |
| 5241 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5261 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5242 } | 5262 } |
| 5243 } else { | 5263 } else { |
| 5244 HGlobalObject* global_object = Add<HGlobalObject>(); | 5264 HGlobalObject* global_object = Add<HGlobalObject>(); |
| 5245 HStoreGlobalGeneric* instr = | 5265 HStoreGlobalGeneric* instr = |
| 5246 Add<HStoreGlobalGeneric>(global_object, var->name(), | 5266 Add<HStoreGlobalGeneric>(global_object, var->name(), |
| 5247 value, function_strict_mode_flag()); | 5267 value, function_strict_mode_flag()); |
| 5248 instr->set_position(position); | 5268 USE(instr); |
| 5249 ASSERT(instr->HasObservableSideEffects()); | 5269 ASSERT(instr->HasObservableSideEffects()); |
| 5250 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5270 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5251 } | 5271 } |
| 5252 } | 5272 } |
| 5253 | 5273 |
| 5254 | 5274 |
| 5255 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5275 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 5256 Expression* target = expr->target(); | 5276 Expression* target = expr->target(); |
| 5257 VariableProxy* proxy = target->AsVariableProxy(); | 5277 VariableProxy* proxy = target->AsVariableProxy(); |
| 5258 Property* prop = target->AsProperty(); | 5278 Property* prop = target->AsProperty(); |
| 5259 ASSERT(proxy == NULL || prop == NULL); | 5279 ASSERT(proxy == NULL || prop == NULL); |
| 5260 | 5280 |
| 5261 // We have a second position recorded in the FullCodeGenerator to have | 5281 // We have a second position recorded in the FullCodeGenerator to have |
| 5262 // type feedback for the binary operation. | 5282 // type feedback for the binary operation. |
| 5263 BinaryOperation* operation = expr->binary_operation(); | 5283 BinaryOperation* operation = expr->binary_operation(); |
| 5264 | 5284 |
| 5265 if (proxy != NULL) { | 5285 if (proxy != NULL) { |
| 5266 Variable* var = proxy->var(); | 5286 Variable* var = proxy->var(); |
| 5267 if (var->mode() == LET) { | 5287 if (var->mode() == LET) { |
| 5268 return Bailout(kUnsupportedLetCompoundAssignment); | 5288 return Bailout(kUnsupportedLetCompoundAssignment); |
| 5269 } | 5289 } |
| 5270 | 5290 |
| 5271 CHECK_ALIVE(VisitForValue(operation)); | 5291 CHECK_ALIVE(VisitForValue(operation)); |
| 5272 | 5292 |
| 5273 switch (var->location()) { | 5293 switch (var->location()) { |
| 5274 case Variable::UNALLOCATED: | 5294 case Variable::UNALLOCATED: |
| 5275 HandleGlobalVariableAssignment(var, | 5295 HandleGlobalVariableAssignment(var, |
| 5276 Top(), | 5296 Top(), |
| 5277 expr->position(), | |
| 5278 expr->AssignmentId()); | 5297 expr->AssignmentId()); |
| 5279 break; | 5298 break; |
| 5280 | 5299 |
| 5281 case Variable::PARAMETER: | 5300 case Variable::PARAMETER: |
| 5282 case Variable::LOCAL: | 5301 case Variable::LOCAL: |
| 5283 if (var->mode() == CONST) { | 5302 if (var->mode() == CONST) { |
| 5284 return Bailout(kUnsupportedConstCompoundAssignment); | 5303 return Bailout(kUnsupportedConstCompoundAssignment); |
| 5285 } | 5304 } |
| 5286 BindIfLive(var, Top()); | 5305 BindIfLive(var, Top()); |
| 5287 break; | 5306 break; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5335 } else if (prop != NULL) { | 5354 } else if (prop != NULL) { |
| 5336 CHECK_ALIVE(VisitForValue(prop->obj())); | 5355 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5337 HValue* object = Top(); | 5356 HValue* object = Top(); |
| 5338 HValue* key = NULL; | 5357 HValue* key = NULL; |
| 5339 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || | 5358 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || |
| 5340 prop->IsStringAccess()) { | 5359 prop->IsStringAccess()) { |
| 5341 CHECK_ALIVE(VisitForValue(prop->key())); | 5360 CHECK_ALIVE(VisitForValue(prop->key())); |
| 5342 key = Top(); | 5361 key = Top(); |
| 5343 } | 5362 } |
| 5344 | 5363 |
| 5345 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); | 5364 CHECK_ALIVE(PushLoad(prop, object, key)); |
| 5346 | 5365 |
| 5347 CHECK_ALIVE(VisitForValue(expr->value())); | 5366 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5348 HValue* right = Pop(); | 5367 HValue* right = Pop(); |
| 5349 HValue* left = Pop(); | 5368 HValue* left = Pop(); |
| 5350 | 5369 |
| 5351 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5370 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5352 PushAndAdd(instr); | 5371 PushAndAdd(instr); |
| 5353 if (instr->HasObservableSideEffects()) { | 5372 if (instr->HasObservableSideEffects()) { |
| 5354 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); | 5373 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
| 5355 } | 5374 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5398 } | 5417 } |
| 5399 | 5418 |
| 5400 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments); | 5419 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments); |
| 5401 | 5420 |
| 5402 // Handle the assignment. | 5421 // Handle the assignment. |
| 5403 switch (var->location()) { | 5422 switch (var->location()) { |
| 5404 case Variable::UNALLOCATED: | 5423 case Variable::UNALLOCATED: |
| 5405 CHECK_ALIVE(VisitForValue(expr->value())); | 5424 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5406 HandleGlobalVariableAssignment(var, | 5425 HandleGlobalVariableAssignment(var, |
| 5407 Top(), | 5426 Top(), |
| 5408 expr->position(), | |
| 5409 expr->AssignmentId()); | 5427 expr->AssignmentId()); |
| 5410 return ast_context()->ReturnValue(Pop()); | 5428 return ast_context()->ReturnValue(Pop()); |
| 5411 | 5429 |
| 5412 case Variable::PARAMETER: | 5430 case Variable::PARAMETER: |
| 5413 case Variable::LOCAL: { | 5431 case Variable::LOCAL: { |
| 5414 // Perform an initialization check for let declared variables | 5432 // Perform an initialization check for let declared variables |
| 5415 // or parameters. | 5433 // or parameters. |
| 5416 if (var->mode() == LET && expr->op() == Token::ASSIGN) { | 5434 if (var->mode() == LET && expr->op() == Token::ASSIGN) { |
| 5417 HValue* env_value = environment()->Lookup(var); | 5435 HValue* env_value = environment()->Lookup(var); |
| 5418 if (env_value == graph()->GetConstantHole()) { | 5436 if (env_value == graph()->GetConstantHole()) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5497 ASSERT(!HasStackOverflow()); | 5515 ASSERT(!HasStackOverflow()); |
| 5498 ASSERT(current_block() != NULL); | 5516 ASSERT(current_block() != NULL); |
| 5499 ASSERT(current_block()->HasPredecessor()); | 5517 ASSERT(current_block()->HasPredecessor()); |
| 5500 // We don't optimize functions with invalid left-hand sides in | 5518 // We don't optimize functions with invalid left-hand sides in |
| 5501 // assignments, count operations, or for-in. Consequently throw can | 5519 // assignments, count operations, or for-in. Consequently throw can |
| 5502 // currently only occur in an effect context. | 5520 // currently only occur in an effect context. |
| 5503 ASSERT(ast_context()->IsEffect()); | 5521 ASSERT(ast_context()->IsEffect()); |
| 5504 CHECK_ALIVE(VisitForValue(expr->exception())); | 5522 CHECK_ALIVE(VisitForValue(expr->exception())); |
| 5505 | 5523 |
| 5506 HValue* value = environment()->Pop(); | 5524 HValue* value = environment()->Pop(); |
| 5507 HThrow* instr = Add<HThrow>(value); | 5525 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
| 5508 instr->set_position(expr->position()); | 5526 Add<HThrow>(value); |
| 5509 Add<HSimulate>(expr->id()); | 5527 Add<HSimulate>(expr->id()); |
| 5510 | 5528 |
| 5511 // If the throw definitely exits the function, we can finish with a dummy | 5529 // If the throw definitely exits the function, we can finish with a dummy |
| 5512 // control flow at this point. This is not the case if the throw is inside | 5530 // control flow at this point. This is not the case if the throw is inside |
| 5513 // an inlined function which may be replaced. | 5531 // an inlined function which may be replaced. |
| 5514 if (call_context() == NULL) { | 5532 if (call_context() == NULL) { |
| 5515 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5533 FinishExitCurrentBlock(new(zone()) HAbnormalExit); |
| 5516 set_current_block(NULL); | |
| 5517 } | 5534 } |
| 5518 } | 5535 } |
| 5519 | 5536 |
| 5520 | 5537 |
| 5521 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 5538 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 5522 HObjectAccess access) { | 5539 HObjectAccess access) { |
| 5523 if (FLAG_track_double_fields && access.representation().IsDouble()) { | 5540 if (FLAG_track_double_fields && access.representation().IsDouble()) { |
| 5524 // load the heap number | 5541 // load the heap number |
| 5525 HLoadNamedField* heap_number = Add<HLoadNamedField>( | 5542 HLoadNamedField* heap_number = Add<HLoadNamedField>( |
| 5526 object, access.WithRepresentation(Representation::Tagged())); | 5543 object, access.WithRepresentation(Representation::Tagged())); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5670 return instr; | 5687 return instr; |
| 5671 } | 5688 } |
| 5672 | 5689 |
| 5673 | 5690 |
| 5674 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 5691 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
| 5675 HValue* object, | 5692 HValue* object, |
| 5676 HValue* key, | 5693 HValue* key, |
| 5677 HValue* val, | 5694 HValue* val, |
| 5678 SmallMapList* maps, | 5695 SmallMapList* maps, |
| 5679 BailoutId ast_id, | 5696 BailoutId ast_id, |
| 5680 int position, | |
| 5681 bool is_store, | 5697 bool is_store, |
| 5682 KeyedAccessStoreMode store_mode, | 5698 KeyedAccessStoreMode store_mode, |
| 5683 bool* has_side_effects) { | 5699 bool* has_side_effects) { |
| 5684 *has_side_effects = false; | 5700 *has_side_effects = false; |
| 5685 BuildCheckHeapObject(object); | 5701 BuildCheckHeapObject(object); |
| 5686 | 5702 |
| 5687 if (!is_store) { | 5703 if (!is_store) { |
| 5688 HInstruction* consolidated_load = | 5704 HInstruction* consolidated_load = |
| 5689 TryBuildConsolidatedElementLoad(object, key, val, maps); | 5705 TryBuildConsolidatedElementLoad(object, key, val, maps); |
| 5690 if (consolidated_load != NULL) { | 5706 if (consolidated_load != NULL) { |
| 5691 *has_side_effects |= consolidated_load->HasObservableSideEffects(); | 5707 *has_side_effects |= consolidated_load->HasObservableSideEffects(); |
| 5692 if (position != RelocInfo::kNoPosition) { | |
| 5693 consolidated_load->set_position(position); | |
| 5694 } | |
| 5695 return consolidated_load; | 5708 return consolidated_load; |
| 5696 } | 5709 } |
| 5697 } | 5710 } |
| 5698 | 5711 |
| 5699 // Elements_kind transition support. | 5712 // Elements_kind transition support. |
| 5700 MapHandleList transition_target(maps->length()); | 5713 MapHandleList transition_target(maps->length()); |
| 5701 // Collect possible transition targets. | 5714 // Collect possible transition targets. |
| 5702 MapHandleList possible_transitioned_maps(maps->length()); | 5715 MapHandleList possible_transitioned_maps(maps->length()); |
| 5703 for (int i = 0; i < maps->length(); ++i) { | 5716 for (int i = 0; i < maps->length(); ++i) { |
| 5704 Handle<Map> map = maps->at(i); | 5717 Handle<Map> map = maps->at(i); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5741 if (untransitionable_map->has_slow_elements_kind() || | 5754 if (untransitionable_map->has_slow_elements_kind() || |
| 5742 !untransitionable_map->IsJSObjectMap()) { | 5755 !untransitionable_map->IsJSObjectMap()) { |
| 5743 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) | 5756 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) |
| 5744 : BuildLoadKeyedGeneric(object, key)); | 5757 : BuildLoadKeyedGeneric(object, key)); |
| 5745 } else { | 5758 } else { |
| 5746 instr = BuildMonomorphicElementAccess( | 5759 instr = BuildMonomorphicElementAccess( |
| 5747 object, key, val, transition, untransitionable_map, is_store, | 5760 object, key, val, transition, untransitionable_map, is_store, |
| 5748 store_mode); | 5761 store_mode); |
| 5749 } | 5762 } |
| 5750 *has_side_effects |= instr->HasObservableSideEffects(); | 5763 *has_side_effects |= instr->HasObservableSideEffects(); |
| 5751 if (position != RelocInfo::kNoPosition) instr->set_position(position); | |
| 5752 return is_store ? NULL : instr; | 5764 return is_store ? NULL : instr; |
| 5753 } | 5765 } |
| 5754 | 5766 |
| 5755 HBasicBlock* join = graph()->CreateBasicBlock(); | 5767 HBasicBlock* join = graph()->CreateBasicBlock(); |
| 5756 | 5768 |
| 5757 for (int i = 0; i < untransitionable_maps.length(); ++i) { | 5769 for (int i = 0; i < untransitionable_maps.length(); ++i) { |
| 5758 Handle<Map> map = untransitionable_maps[i]; | 5770 Handle<Map> map = untransitionable_maps[i]; |
| 5759 if (!map->IsJSObjectMap()) continue; | 5771 if (!map->IsJSObjectMap()) continue; |
| 5760 ElementsKind elements_kind = map->elements_kind(); | 5772 ElementsKind elements_kind = map->elements_kind(); |
| 5761 HBasicBlock* this_map = graph()->CreateBasicBlock(); | 5773 HBasicBlock* this_map = graph()->CreateBasicBlock(); |
| 5762 HBasicBlock* other_map = graph()->CreateBasicBlock(); | 5774 HBasicBlock* other_map = graph()->CreateBasicBlock(); |
| 5763 HCompareMap* mapcompare = | 5775 HCompareMap* mapcompare = |
| 5764 New<HCompareMap>(object, map, this_map, other_map); | 5776 New<HCompareMap>(object, map, this_map, other_map); |
| 5765 current_block()->Finish(mapcompare); | 5777 FinishCurrentBlock(mapcompare); |
| 5766 | 5778 |
| 5767 set_current_block(this_map); | 5779 set_current_block(this_map); |
| 5768 HInstruction* access = NULL; | 5780 HInstruction* access = NULL; |
| 5769 if (IsDictionaryElementsKind(elements_kind)) { | 5781 if (IsDictionaryElementsKind(elements_kind)) { |
| 5770 access = is_store | 5782 access = is_store |
| 5771 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val)) | 5783 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val)) |
| 5772 : AddInstruction(BuildLoadKeyedGeneric(object, key)); | 5784 : AddInstruction(BuildLoadKeyedGeneric(object, key)); |
| 5773 } else { | 5785 } else { |
| 5774 ASSERT(IsFastElementsKind(elements_kind) || | 5786 ASSERT(IsFastElementsKind(elements_kind) || |
| 5775 IsExternalArrayElementsKind(elements_kind)); | 5787 IsExternalArrayElementsKind(elements_kind)); |
| 5776 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); | 5788 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
| 5777 // Happily, mapcompare is a checked object. | 5789 // Happily, mapcompare is a checked object. |
| 5778 access = BuildUncheckedMonomorphicElementAccess( | 5790 access = BuildUncheckedMonomorphicElementAccess( |
| 5779 mapcompare, key, val, | 5791 mapcompare, key, val, |
| 5780 map->instance_type() == JS_ARRAY_TYPE, | 5792 map->instance_type() == JS_ARRAY_TYPE, |
| 5781 elements_kind, is_store, | 5793 elements_kind, is_store, |
| 5782 load_mode, | 5794 load_mode, |
| 5783 store_mode); | 5795 store_mode); |
| 5784 } | 5796 } |
| 5785 *has_side_effects |= access->HasObservableSideEffects(); | 5797 *has_side_effects |= access->HasObservableSideEffects(); |
| 5786 // The caller will use has_side_effects and add a correct Simulate. | 5798 // The caller will use has_side_effects and add a correct Simulate. |
| 5787 access->SetFlag(HValue::kHasNoObservableSideEffects); | 5799 access->SetFlag(HValue::kHasNoObservableSideEffects); |
| 5788 if (position != RelocInfo::kNoPosition) access->set_position(position); | |
| 5789 if (!is_store) { | 5800 if (!is_store) { |
| 5790 Push(access); | 5801 Push(access); |
| 5791 } | 5802 } |
| 5792 NoObservableSideEffectsScope scope(this); | 5803 NoObservableSideEffectsScope scope(this); |
| 5793 current_block()->GotoNoSimulate(join); | 5804 GotoNoSimulate(join); |
| 5794 set_current_block(other_map); | 5805 set_current_block(other_map); |
| 5795 } | 5806 } |
| 5796 | 5807 |
| 5797 // Deopt if none of the cases matched. | 5808 // Deopt if none of the cases matched. |
| 5798 NoObservableSideEffectsScope scope(this); | 5809 NoObservableSideEffectsScope scope(this); |
| 5799 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access", | 5810 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access", |
| 5800 join); | 5811 join); |
| 5801 set_current_block(join); | 5812 set_current_block(join); |
| 5802 return is_store ? NULL : Pop(); | 5813 return is_store ? NULL : Pop(); |
| 5803 } | 5814 } |
| 5804 | 5815 |
| 5805 | 5816 |
| 5806 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 5817 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
| 5807 HValue* obj, | 5818 HValue* obj, |
| 5808 HValue* key, | 5819 HValue* key, |
| 5809 HValue* val, | 5820 HValue* val, |
| 5810 Expression* expr, | 5821 Expression* expr, |
| 5811 BailoutId ast_id, | 5822 BailoutId ast_id, |
| 5812 int position, | |
| 5813 bool is_store, | 5823 bool is_store, |
| 5814 bool* has_side_effects) { | 5824 bool* has_side_effects) { |
| 5815 ASSERT(!expr->IsPropertyName()); | 5825 ASSERT(!expr->IsPropertyName()); |
| 5816 HInstruction* instr = NULL; | 5826 HInstruction* instr = NULL; |
| 5817 | 5827 |
| 5818 SmallMapList* types; | 5828 SmallMapList* types; |
| 5819 bool monomorphic = ComputeReceiverTypes(expr, obj, &types); | 5829 bool monomorphic = ComputeReceiverTypes(expr, obj, &types); |
| 5820 | 5830 |
| 5821 if (monomorphic) { | 5831 if (monomorphic) { |
| 5822 Handle<Map> map = types->first(); | 5832 Handle<Map> map = types->first(); |
| 5823 if (map->has_slow_elements_kind()) { | 5833 if (map->has_slow_elements_kind()) { |
| 5824 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 5834 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
| 5825 : BuildLoadKeyedGeneric(obj, key); | 5835 : BuildLoadKeyedGeneric(obj, key); |
| 5826 AddInstruction(instr); | 5836 AddInstruction(instr); |
| 5827 } else { | 5837 } else { |
| 5828 BuildCheckHeapObject(obj); | 5838 BuildCheckHeapObject(obj); |
| 5829 instr = BuildMonomorphicElementAccess( | 5839 instr = BuildMonomorphicElementAccess( |
| 5830 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | 5840 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); |
| 5831 } | 5841 } |
| 5832 } else if (types != NULL && !types->is_empty()) { | 5842 } else if (types != NULL && !types->is_empty()) { |
| 5833 return HandlePolymorphicElementAccess( | 5843 return HandlePolymorphicElementAccess( |
| 5834 obj, key, val, types, ast_id, position, is_store, | 5844 obj, key, val, types, ast_id, is_store, |
| 5835 expr->GetStoreMode(), has_side_effects); | 5845 expr->GetStoreMode(), has_side_effects); |
| 5836 } else { | 5846 } else { |
| 5837 if (is_store) { | 5847 if (is_store) { |
| 5838 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { | 5848 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { |
| 5839 Add<HDeoptimize>("Insufficient type feedback for keyed store", | 5849 Add<HDeoptimize>("Insufficient type feedback for keyed store", |
| 5840 Deoptimizer::SOFT); | 5850 Deoptimizer::SOFT); |
| 5841 } | 5851 } |
| 5842 instr = BuildStoreKeyedGeneric(obj, key, val); | 5852 instr = BuildStoreKeyedGeneric(obj, key, val); |
| 5843 } else { | 5853 } else { |
| 5844 if (expr->AsProperty()->IsUninitialized()) { | 5854 if (expr->AsProperty()->IsUninitialized()) { |
| 5845 Add<HDeoptimize>("Insufficient type feedback for keyed load", | 5855 Add<HDeoptimize>("Insufficient type feedback for keyed load", |
| 5846 Deoptimizer::SOFT); | 5856 Deoptimizer::SOFT); |
| 5847 } | 5857 } |
| 5848 instr = BuildLoadKeyedGeneric(obj, key); | 5858 instr = BuildLoadKeyedGeneric(obj, key); |
| 5849 } | 5859 } |
| 5850 AddInstruction(instr); | 5860 AddInstruction(instr); |
| 5851 } | 5861 } |
| 5852 if (position != RelocInfo::kNoPosition) instr->set_position(position); | |
| 5853 *has_side_effects = instr->HasObservableSideEffects(); | 5862 *has_side_effects = instr->HasObservableSideEffects(); |
| 5854 return instr; | 5863 return instr; |
| 5855 } | 5864 } |
| 5856 | 5865 |
| 5857 | 5866 |
| 5858 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( | 5867 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( |
| 5859 HValue* object, | 5868 HValue* object, |
| 5860 HValue* key, | 5869 HValue* key, |
| 5861 HValue* value) { | 5870 HValue* value) { |
| 5862 HValue* context = environment()->context(); | 5871 HValue* context = environment()->context(); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5941 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 5950 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
| 5942 } | 5951 } |
| 5943 } | 5952 } |
| 5944 ast_context()->ReturnInstruction(result, expr->id()); | 5953 ast_context()->ReturnInstruction(result, expr->id()); |
| 5945 return true; | 5954 return true; |
| 5946 } | 5955 } |
| 5947 | 5956 |
| 5948 | 5957 |
| 5949 void HOptimizedGraphBuilder::PushLoad(Property* expr, | 5958 void HOptimizedGraphBuilder::PushLoad(Property* expr, |
| 5950 HValue* object, | 5959 HValue* object, |
| 5951 HValue* key, | 5960 HValue* key) { |
| 5952 int position) { | |
| 5953 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 5961 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
| 5954 Push(object); | 5962 Push(object); |
| 5955 if (key != NULL) Push(key); | 5963 if (key != NULL) Push(key); |
| 5956 BuildLoad(expr, position, expr->LoadId()); | 5964 BuildLoad(expr, expr->LoadId()); |
| 5957 } | 5965 } |
| 5958 | 5966 |
| 5959 | 5967 |
| 5960 static bool AreStringTypes(SmallMapList* types) { | 5968 static bool AreStringTypes(SmallMapList* types) { |
| 5961 for (int i = 0; i < types->length(); i++) { | 5969 for (int i = 0; i < types->length(); i++) { |
| 5962 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; | 5970 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; |
| 5963 } | 5971 } |
| 5964 return true; | 5972 return true; |
| 5965 } | 5973 } |
| 5966 | 5974 |
| 5967 | 5975 |
| 5968 void HOptimizedGraphBuilder::BuildLoad(Property* expr, | 5976 void HOptimizedGraphBuilder::BuildLoad(Property* expr, |
| 5969 int position, | |
| 5970 BailoutId ast_id) { | 5977 BailoutId ast_id) { |
| 5971 HInstruction* instr = NULL; | 5978 HInstruction* instr = NULL; |
| 5972 if (expr->IsStringAccess()) { | 5979 if (expr->IsStringAccess()) { |
| 5973 HValue* index = Pop(); | 5980 HValue* index = Pop(); |
| 5974 HValue* string = Pop(); | 5981 HValue* string = Pop(); |
| 5975 HValue* context = environment()->context(); | 5982 HValue* context = environment()->context(); |
| 5976 HInstruction* char_code = | 5983 HInstruction* char_code = |
| 5977 BuildStringCharCodeAt(string, index); | 5984 BuildStringCharCodeAt(string, index); |
| 5978 AddInstruction(char_code); | 5985 AddInstruction(char_code); |
| 5979 instr = HStringCharFromCode::New(zone(), context, char_code); | 5986 instr = HStringCharFromCode::New(zone(), context, char_code); |
| 5980 | 5987 |
| 5981 } else if (expr->IsFunctionPrototype()) { | 5988 } else if (expr->IsFunctionPrototype()) { |
| 5982 HValue* function = Pop(); | 5989 HValue* function = Pop(); |
| 5983 BuildCheckHeapObject(function); | 5990 BuildCheckHeapObject(function); |
| 5984 instr = new(zone()) HLoadFunctionPrototype(function); | 5991 instr = new(zone()) HLoadFunctionPrototype(function); |
| 5985 | 5992 |
| 5986 } else if (expr->key()->IsPropertyName()) { | 5993 } else if (expr->key()->IsPropertyName()) { |
| 5987 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 5994 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 5988 HValue* object = Pop(); | 5995 HValue* object = Pop(); |
| 5989 | 5996 |
| 5990 SmallMapList* types; | 5997 SmallMapList* types; |
| 5991 ComputeReceiverTypes(expr, object, &types); | 5998 ComputeReceiverTypes(expr, object, &types); |
| 5992 ASSERT(types != NULL); | 5999 ASSERT(types != NULL); |
| 5993 | 6000 |
| 5994 if (types->length() > 0) { | 6001 if (types->length() > 0) { |
| 5995 PropertyAccessInfo info(isolate(), types->first(), name); | 6002 PropertyAccessInfo info(isolate(), types->first(), name); |
| 5996 if (!info.CanLoadAsMonomorphic(types)) { | 6003 if (!info.CanLoadAsMonomorphic(types)) { |
| 5997 return HandlePolymorphicLoadNamedField( | 6004 return HandlePolymorphicLoadNamedField( |
| 5998 position, ast_id, expr->LoadId(), object, types, name); | 6005 ast_id, expr->LoadId(), object, types, name); |
| 5999 } | 6006 } |
| 6000 | 6007 |
| 6001 BuildCheckHeapObject(object); | 6008 BuildCheckHeapObject(object); |
| 6002 HInstruction* checked_object; | 6009 HInstruction* checked_object; |
| 6003 if (AreStringTypes(types)) { | 6010 if (AreStringTypes(types)) { |
| 6004 checked_object = | 6011 checked_object = |
| 6005 AddInstruction(HCheckInstanceType::NewIsString(object, zone())); | 6012 AddInstruction(HCheckInstanceType::NewIsString(object, zone())); |
| 6006 } else { | 6013 } else { |
| 6007 checked_object = Add<HCheckMaps>(object, types); | 6014 checked_object = Add<HCheckMaps>(object, types); |
| 6008 } | 6015 } |
| 6009 instr = BuildLoadMonomorphic( | 6016 instr = BuildLoadMonomorphic( |
| 6010 &info, object, checked_object, ast_id, expr->LoadId()); | 6017 &info, object, checked_object, ast_id, expr->LoadId()); |
| 6011 if (instr == NULL) return; | 6018 if (instr == NULL) return; |
| 6012 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); | 6019 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); |
| 6013 } else { | 6020 } else { |
| 6014 instr = BuildLoadNamedGeneric(object, name, expr); | 6021 instr = BuildLoadNamedGeneric(object, name, expr); |
| 6015 } | 6022 } |
| 6016 | 6023 |
| 6017 } else { | 6024 } else { |
| 6018 HValue* key = Pop(); | 6025 HValue* key = Pop(); |
| 6019 HValue* obj = Pop(); | 6026 HValue* obj = Pop(); |
| 6020 | 6027 |
| 6021 bool has_side_effects = false; | 6028 bool has_side_effects = false; |
| 6022 HValue* load = HandleKeyedElementAccess( | 6029 HValue* load = HandleKeyedElementAccess( |
| 6023 obj, key, NULL, expr, ast_id, position, | 6030 obj, key, NULL, expr, ast_id, |
| 6024 false, // is_store | 6031 false, // is_store |
| 6025 &has_side_effects); | 6032 &has_side_effects); |
| 6026 if (has_side_effects) { | 6033 if (has_side_effects) { |
| 6027 if (ast_context()->IsEffect()) { | 6034 if (ast_context()->IsEffect()) { |
| 6028 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6035 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6029 } else { | 6036 } else { |
| 6030 Push(load); | 6037 Push(load); |
| 6031 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6038 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6032 Drop(1); | 6039 Drop(1); |
| 6033 } | 6040 } |
| 6034 } | 6041 } |
| 6035 return ast_context()->ReturnValue(load); | 6042 return ast_context()->ReturnValue(load); |
| 6036 } | 6043 } |
| 6037 instr->set_position(position); | |
| 6038 return ast_context()->ReturnInstruction(instr, ast_id); | 6044 return ast_context()->ReturnInstruction(instr, ast_id); |
| 6039 } | 6045 } |
| 6040 | 6046 |
| 6041 | 6047 |
| 6042 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 6048 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
| 6043 ASSERT(!HasStackOverflow()); | 6049 ASSERT(!HasStackOverflow()); |
| 6044 ASSERT(current_block() != NULL); | 6050 ASSERT(current_block() != NULL); |
| 6045 ASSERT(current_block()->HasPredecessor()); | 6051 ASSERT(current_block()->HasPredecessor()); |
| 6046 | 6052 |
| 6047 if (TryArgumentsAccess(expr)) return; | 6053 if (TryArgumentsAccess(expr)) return; |
| 6048 | 6054 |
| 6049 CHECK_ALIVE(VisitForValue(expr->obj())); | 6055 CHECK_ALIVE(VisitForValue(expr->obj())); |
| 6050 if ((!expr->IsFunctionPrototype() && !expr->key()->IsPropertyName()) || | 6056 if ((!expr->IsFunctionPrototype() && !expr->key()->IsPropertyName()) || |
| 6051 expr->IsStringAccess()) { | 6057 expr->IsStringAccess()) { |
| 6052 CHECK_ALIVE(VisitForValue(expr->key())); | 6058 CHECK_ALIVE(VisitForValue(expr->key())); |
| 6053 } | 6059 } |
| 6054 | 6060 |
| 6055 BuildLoad(expr, expr->position(), expr->id()); | 6061 BuildLoad(expr, expr->id()); |
| 6056 } | 6062 } |
| 6057 | 6063 |
| 6058 | 6064 |
| 6059 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, | 6065 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, |
| 6060 CompilationInfo* info) { | 6066 CompilationInfo* info) { |
| 6061 HConstant* constant_value = New<HConstant>(constant); | 6067 HConstant* constant_value = New<HConstant>(constant); |
| 6062 | 6068 |
| 6063 if (constant->map()->CanOmitMapChecks()) { | 6069 if (constant->map()->CanOmitMapChecks()) { |
| 6064 constant->map()->AddDependentCompilationInfo( | 6070 constant->map()->AddDependentCompilationInfo( |
| 6065 DependentCode::kPrototypeCheckGroup, info); | 6071 DependentCode::kPrototypeCheckGroup, info); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6158 SmartArrayPointer<char> caller_name = | 6164 SmartArrayPointer<char> caller_name = |
| 6159 caller->shared()->DebugName()->ToCString(); | 6165 caller->shared()->DebugName()->ToCString(); |
| 6160 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6166 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 6161 *name->ToCString(), *caller_name); | 6167 *name->ToCString(), *caller_name); |
| 6162 } | 6168 } |
| 6163 | 6169 |
| 6164 if (!TryInlineCall(expr)) { | 6170 if (!TryInlineCall(expr)) { |
| 6165 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6171 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 6166 HCallConstantFunction* call = | 6172 HCallConstantFunction* call = |
| 6167 New<HCallConstantFunction>(expr->target(), argument_count); | 6173 New<HCallConstantFunction>(expr->target(), argument_count); |
| 6168 call->set_position(expr->position()); | |
| 6169 PreProcessCall(call); | 6174 PreProcessCall(call); |
| 6170 AddInstruction(call); | 6175 AddInstruction(call); |
| 6171 if (!ast_context()->IsEffect()) Push(call); | 6176 if (!ast_context()->IsEffect()) Push(call); |
| 6172 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 6177 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 6173 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6178 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 6174 } | 6179 } |
| 6175 | 6180 |
| 6176 return true; | 6181 return true; |
| 6177 } | 6182 } |
| 6178 | 6183 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6222 for (int fn = 0; fn < ordered_functions; ++fn) { | 6227 for (int fn = 0; fn < ordered_functions; ++fn) { |
| 6223 int i = order[fn].index(); | 6228 int i = order[fn].index(); |
| 6224 Handle<Map> map = types->at(i); | 6229 Handle<Map> map = types->at(i); |
| 6225 if (fn == 0) { | 6230 if (fn == 0) { |
| 6226 // Only needed once. | 6231 // Only needed once. |
| 6227 join = graph()->CreateBasicBlock(); | 6232 join = graph()->CreateBasicBlock(); |
| 6228 if (handle_smi) { | 6233 if (handle_smi) { |
| 6229 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); | 6234 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
| 6230 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); | 6235 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
| 6231 number_block = graph()->CreateBasicBlock(); | 6236 number_block = graph()->CreateBasicBlock(); |
| 6232 current_block()->Finish(New<HIsSmiAndBranch>( | 6237 FinishCurrentBlock(New<HIsSmiAndBranch>( |
| 6233 receiver, empty_smi_block, not_smi_block)); | 6238 receiver, empty_smi_block, not_smi_block)); |
| 6234 empty_smi_block->Goto(number_block); | 6239 Goto(empty_smi_block, number_block); |
| 6235 set_current_block(not_smi_block); | 6240 set_current_block(not_smi_block); |
| 6236 } else { | 6241 } else { |
| 6237 BuildCheckHeapObject(receiver); | 6242 BuildCheckHeapObject(receiver); |
| 6238 } | 6243 } |
| 6239 } | 6244 } |
| 6240 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 6245 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 6241 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 6246 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 6242 HUnaryControlInstruction* compare; | 6247 HUnaryControlInstruction* compare; |
| 6243 | 6248 |
| 6244 if (handle_smi && map.is_identical_to(number_marker_map)) { | 6249 if (handle_smi && map.is_identical_to(number_marker_map)) { |
| 6245 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); | 6250 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); |
| 6246 map = initial_number_map; | 6251 map = initial_number_map; |
| 6247 expr->set_number_check( | 6252 expr->set_number_check( |
| 6248 Handle<JSObject>(JSObject::cast(map->prototype()))); | 6253 Handle<JSObject>(JSObject::cast(map->prototype()))); |
| 6249 } else if (map.is_identical_to(string_marker_map)) { | 6254 } else if (map.is_identical_to(string_marker_map)) { |
| 6250 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); | 6255 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); |
| 6251 map = initial_string_map; | 6256 map = initial_string_map; |
| 6252 expr->set_string_check( | 6257 expr->set_string_check( |
| 6253 Handle<JSObject>(JSObject::cast(map->prototype()))); | 6258 Handle<JSObject>(JSObject::cast(map->prototype()))); |
| 6254 } else { | 6259 } else { |
| 6255 compare = New<HCompareMap>(receiver, map, if_true, if_false); | 6260 compare = New<HCompareMap>(receiver, map, if_true, if_false); |
| 6256 expr->set_map_check(); | 6261 expr->set_map_check(); |
| 6257 } | 6262 } |
| 6258 | 6263 |
| 6259 current_block()->Finish(compare); | 6264 FinishCurrentBlock(compare); |
| 6260 | 6265 |
| 6261 if (expr->check_type() == NUMBER_CHECK) { | 6266 if (expr->check_type() == NUMBER_CHECK) { |
| 6262 if_true->Goto(number_block); | 6267 Goto(if_true, number_block); |
| 6263 if_true = number_block; | 6268 if_true = number_block; |
| 6264 number_block->SetJoinId(expr->id()); | 6269 number_block->SetJoinId(expr->id()); |
| 6265 } | 6270 } |
| 6266 set_current_block(if_true); | 6271 set_current_block(if_true); |
| 6267 | 6272 |
| 6268 expr->ComputeTarget(map, name); | 6273 expr->ComputeTarget(map, name); |
| 6269 AddCheckPrototypeMaps(expr->holder(), map); | 6274 AddCheckPrototypeMaps(expr->holder(), map); |
| 6270 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 6275 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
| 6271 Handle<JSFunction> caller = current_info()->closure(); | 6276 Handle<JSFunction> caller = current_info()->closure(); |
| 6272 SmartArrayPointer<char> caller_name = | 6277 SmartArrayPointer<char> caller_name = |
| 6273 caller->shared()->DebugName()->ToCString(); | 6278 caller->shared()->DebugName()->ToCString(); |
| 6274 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6279 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 6275 *name->ToCString(), | 6280 *name->ToCString(), |
| 6276 *caller_name); | 6281 *caller_name); |
| 6277 } | 6282 } |
| 6278 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 6283 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { |
| 6279 // Trying to inline will signal that we should bailout from the | 6284 // Trying to inline will signal that we should bailout from the |
| 6280 // entire compilation by setting stack overflow on the visitor. | 6285 // entire compilation by setting stack overflow on the visitor. |
| 6281 if (HasStackOverflow()) return; | 6286 if (HasStackOverflow()) return; |
| 6282 } else { | 6287 } else { |
| 6283 HCallConstantFunction* call = | 6288 HCallConstantFunction* call = |
| 6284 New<HCallConstantFunction>(expr->target(), argument_count); | 6289 New<HCallConstantFunction>(expr->target(), argument_count); |
| 6285 call->set_position(expr->position()); | |
| 6286 PreProcessCall(call); | 6290 PreProcessCall(call); |
| 6287 AddInstruction(call); | 6291 AddInstruction(call); |
| 6288 if (!ast_context()->IsEffect()) Push(call); | 6292 if (!ast_context()->IsEffect()) Push(call); |
| 6289 } | 6293 } |
| 6290 | 6294 |
| 6291 if (current_block() != NULL) current_block()->Goto(join); | 6295 if (current_block() != NULL) Goto(join); |
| 6292 set_current_block(if_false); | 6296 set_current_block(if_false); |
| 6293 } | 6297 } |
| 6294 | 6298 |
| 6295 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6299 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 6296 // know about and do not want to handle ones we've never seen. Otherwise | 6300 // know about and do not want to handle ones we've never seen. Otherwise |
| 6297 // use a generic IC. | 6301 // use a generic IC. |
| 6298 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6302 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 6299 // Because the deopt may be the only path in the polymorphic call, make sure | 6303 // Because the deopt may be the only path in the polymorphic call, make sure |
| 6300 // that the environment stack matches the depth on deopt that it otherwise | 6304 // that the environment stack matches the depth on deopt that it otherwise |
| 6301 // would have had after a successful call. | 6305 // would have had after a successful call. |
| 6302 Drop(argument_count); | 6306 Drop(argument_count); |
| 6303 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 6307 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
| 6304 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); | 6308 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); |
| 6305 } else { | 6309 } else { |
| 6306 HCallNamed* call = New<HCallNamed>(name, argument_count); | 6310 HCallNamed* call = New<HCallNamed>(name, argument_count); |
| 6307 call->set_position(expr->position()); | |
| 6308 PreProcessCall(call); | 6311 PreProcessCall(call); |
| 6309 | 6312 |
| 6310 if (join != NULL) { | 6313 if (join != NULL) { |
| 6311 AddInstruction(call); | 6314 AddInstruction(call); |
| 6312 if (!ast_context()->IsEffect()) Push(call); | 6315 if (!ast_context()->IsEffect()) Push(call); |
| 6313 current_block()->Goto(join); | 6316 Goto(join); |
| 6314 } else { | 6317 } else { |
| 6315 return ast_context()->ReturnInstruction(call, expr->id()); | 6318 return ast_context()->ReturnInstruction(call, expr->id()); |
| 6316 } | 6319 } |
| 6317 } | 6320 } |
| 6318 | 6321 |
| 6319 // We assume that control flow is always live after an expression. So | 6322 // We assume that control flow is always live after an expression. So |
| 6320 // even without predecessors to the join block, we set it as the exit | 6323 // even without predecessors to the join block, we set it as the exit |
| 6321 // block and continue by adding instructions there. | 6324 // block and continue by adding instructions there. |
| 6322 ASSERT(join != NULL); | 6325 ASSERT(join != NULL); |
| 6323 if (join->HasPredecessor()) { | 6326 if (join->HasPredecessor()) { |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6605 | 6608 |
| 6606 TraceInline(target, caller, NULL); | 6609 TraceInline(target, caller, NULL); |
| 6607 | 6610 |
| 6608 if (current_block() != NULL) { | 6611 if (current_block() != NULL) { |
| 6609 FunctionState* state = function_state(); | 6612 FunctionState* state = function_state(); |
| 6610 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 6613 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
| 6611 // Falling off the end of an inlined construct call. In a test context the | 6614 // Falling off the end of an inlined construct call. In a test context the |
| 6612 // return value will always evaluate to true, in a value context the | 6615 // return value will always evaluate to true, in a value context the |
| 6613 // return value is the newly allocated receiver. | 6616 // return value is the newly allocated receiver. |
| 6614 if (call_context()->IsTest()) { | 6617 if (call_context()->IsTest()) { |
| 6615 current_block()->Goto(inlined_test_context()->if_true(), state); | 6618 Goto(inlined_test_context()->if_true(), state); |
| 6616 } else if (call_context()->IsEffect()) { | 6619 } else if (call_context()->IsEffect()) { |
| 6617 current_block()->Goto(function_return(), state); | 6620 Goto(function_return(), state); |
| 6618 } else { | 6621 } else { |
| 6619 ASSERT(call_context()->IsValue()); | 6622 ASSERT(call_context()->IsValue()); |
| 6620 current_block()->AddLeaveInlined(implicit_return_value, state); | 6623 AddLeaveInlined(implicit_return_value, state); |
| 6621 } | 6624 } |
| 6622 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { | 6625 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { |
| 6623 // Falling off the end of an inlined setter call. The returned value is | 6626 // Falling off the end of an inlined setter call. The returned value is |
| 6624 // never used, the value of an assignment is always the value of the RHS | 6627 // never used, the value of an assignment is always the value of the RHS |
| 6625 // of the assignment. | 6628 // of the assignment. |
| 6626 if (call_context()->IsTest()) { | 6629 if (call_context()->IsTest()) { |
| 6627 inlined_test_context()->ReturnValue(implicit_return_value); | 6630 inlined_test_context()->ReturnValue(implicit_return_value); |
| 6628 } else if (call_context()->IsEffect()) { | 6631 } else if (call_context()->IsEffect()) { |
| 6629 current_block()->Goto(function_return(), state); | 6632 Goto(function_return(), state); |
| 6630 } else { | 6633 } else { |
| 6631 ASSERT(call_context()->IsValue()); | 6634 ASSERT(call_context()->IsValue()); |
| 6632 current_block()->AddLeaveInlined(implicit_return_value, state); | 6635 AddLeaveInlined(implicit_return_value, state); |
| 6633 } | 6636 } |
| 6634 } else { | 6637 } else { |
| 6635 // Falling off the end of a normal inlined function. This basically means | 6638 // Falling off the end of a normal inlined function. This basically means |
| 6636 // returning undefined. | 6639 // returning undefined. |
| 6637 if (call_context()->IsTest()) { | 6640 if (call_context()->IsTest()) { |
| 6638 current_block()->Goto(inlined_test_context()->if_false(), state); | 6641 Goto(inlined_test_context()->if_false(), state); |
| 6639 } else if (call_context()->IsEffect()) { | 6642 } else if (call_context()->IsEffect()) { |
| 6640 current_block()->Goto(function_return(), state); | 6643 Goto(function_return(), state); |
| 6641 } else { | 6644 } else { |
| 6642 ASSERT(call_context()->IsValue()); | 6645 ASSERT(call_context()->IsValue()); |
| 6643 current_block()->AddLeaveInlined(undefined, state); | 6646 AddLeaveInlined(undefined, state); |
| 6644 } | 6647 } |
| 6645 } | 6648 } |
| 6646 } | 6649 } |
| 6647 | 6650 |
| 6648 // Fix up the function exits. | 6651 // Fix up the function exits. |
| 6649 if (inlined_test_context() != NULL) { | 6652 if (inlined_test_context() != NULL) { |
| 6650 HBasicBlock* if_true = inlined_test_context()->if_true(); | 6653 HBasicBlock* if_true = inlined_test_context()->if_true(); |
| 6651 HBasicBlock* if_false = inlined_test_context()->if_false(); | 6654 HBasicBlock* if_false = inlined_test_context()->if_false(); |
| 6652 | 6655 |
| 6653 HEnterInlined* entry = function_state()->entry(); | 6656 HEnterInlined* entry = function_state()->entry(); |
| 6654 | 6657 |
| 6655 // Pop the return test context from the expression context stack. | 6658 // Pop the return test context from the expression context stack. |
| 6656 ASSERT(ast_context() == inlined_test_context()); | 6659 ASSERT(ast_context() == inlined_test_context()); |
| 6657 ClearInlinedTestContext(); | 6660 ClearInlinedTestContext(); |
| 6658 delete target_state; | 6661 delete target_state; |
| 6659 | 6662 |
| 6660 // Forward to the real test context. | 6663 // Forward to the real test context. |
| 6661 if (if_true->HasPredecessor()) { | 6664 if (if_true->HasPredecessor()) { |
| 6662 entry->RegisterReturnTarget(if_true, zone()); | 6665 entry->RegisterReturnTarget(if_true, zone()); |
| 6663 if_true->SetJoinId(ast_id); | 6666 if_true->SetJoinId(ast_id); |
| 6664 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); | 6667 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); |
| 6665 if_true->Goto(true_target, function_state()); | 6668 Goto(if_true, true_target, function_state()); |
| 6666 } | 6669 } |
| 6667 if (if_false->HasPredecessor()) { | 6670 if (if_false->HasPredecessor()) { |
| 6668 entry->RegisterReturnTarget(if_false, zone()); | 6671 entry->RegisterReturnTarget(if_false, zone()); |
| 6669 if_false->SetJoinId(ast_id); | 6672 if_false->SetJoinId(ast_id); |
| 6670 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); | 6673 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); |
| 6671 if_false->Goto(false_target, function_state()); | 6674 Goto(if_false, false_target, function_state()); |
| 6672 } | 6675 } |
| 6673 set_current_block(NULL); | 6676 set_current_block(NULL); |
| 6674 return true; | 6677 return true; |
| 6675 | 6678 |
| 6676 } else if (function_return()->HasPredecessor()) { | 6679 } else if (function_return()->HasPredecessor()) { |
| 6677 function_state()->entry()->RegisterReturnTarget(function_return(), zone()); | 6680 function_state()->entry()->RegisterReturnTarget(function_return(), zone()); |
| 6678 function_return()->SetJoinId(ast_id); | 6681 function_return()->SetJoinId(ast_id); |
| 6679 set_current_block(function_return()); | 6682 set_current_block(function_return()); |
| 6680 } else { | 6683 } else { |
| 6681 set_current_block(NULL); | 6684 set_current_block(NULL); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6768 case kMathLog: | 6771 case kMathLog: |
| 6769 case kMathSin: | 6772 case kMathSin: |
| 6770 case kMathCos: | 6773 case kMathCos: |
| 6771 case kMathTan: | 6774 case kMathTan: |
| 6772 if (expr->arguments()->length() == 1) { | 6775 if (expr->arguments()->length() == 1) { |
| 6773 HValue* argument = Pop(); | 6776 HValue* argument = Pop(); |
| 6774 HValue* context = environment()->context(); | 6777 HValue* context = environment()->context(); |
| 6775 Drop(1); // Receiver. | 6778 Drop(1); // Receiver. |
| 6776 HInstruction* op = | 6779 HInstruction* op = |
| 6777 HUnaryMathOperation::New(zone(), context, argument, id); | 6780 HUnaryMathOperation::New(zone(), context, argument, id); |
| 6778 op->set_position(expr->position()); | |
| 6779 if (drop_extra) Drop(1); // Optionally drop the function. | 6781 if (drop_extra) Drop(1); // Optionally drop the function. |
| 6780 ast_context()->ReturnInstruction(op, expr->id()); | 6782 ast_context()->ReturnInstruction(op, expr->id()); |
| 6781 return true; | 6783 return true; |
| 6782 } | 6784 } |
| 6783 break; | 6785 break; |
| 6784 case kMathImul: | 6786 case kMathImul: |
| 6785 if (expr->arguments()->length() == 2) { | 6787 if (expr->arguments()->length() == 2) { |
| 6786 HValue* right = Pop(); | 6788 HValue* right = Pop(); |
| 6787 HValue* left = Pop(); | 6789 HValue* left = Pop(); |
| 6788 Drop(1); // Receiver. | 6790 Drop(1); // Receiver. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6858 case kMathSin: | 6860 case kMathSin: |
| 6859 case kMathCos: | 6861 case kMathCos: |
| 6860 case kMathTan: | 6862 case kMathTan: |
| 6861 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { | 6863 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
| 6862 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6864 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 6863 HValue* argument = Pop(); | 6865 HValue* argument = Pop(); |
| 6864 HValue* context = environment()->context(); | 6866 HValue* context = environment()->context(); |
| 6865 Drop(1); // Receiver. | 6867 Drop(1); // Receiver. |
| 6866 HInstruction* op = | 6868 HInstruction* op = |
| 6867 HUnaryMathOperation::New(zone(), context, argument, id); | 6869 HUnaryMathOperation::New(zone(), context, argument, id); |
| 6868 op->set_position(expr->position()); | |
| 6869 ast_context()->ReturnInstruction(op, expr->id()); | 6870 ast_context()->ReturnInstruction(op, expr->id()); |
| 6870 return true; | 6871 return true; |
| 6871 } | 6872 } |
| 6872 break; | 6873 break; |
| 6873 case kMathPow: | 6874 case kMathPow: |
| 6874 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 6875 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
| 6875 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6876 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 6876 HValue* right = Pop(); | 6877 HValue* right = Pop(); |
| 6877 HValue* left = Pop(); | 6878 HValue* left = Pop(); |
| 6878 Pop(); // Pop receiver. | 6879 Pop(); // Pop receiver. |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6987 | 6988 |
| 6988 if (function_state()->outer() == NULL) { | 6989 if (function_state()->outer() == NULL) { |
| 6989 HInstruction* elements = Add<HArgumentsElements>(false); | 6990 HInstruction* elements = Add<HArgumentsElements>(false); |
| 6990 HInstruction* length = Add<HArgumentsLength>(elements); | 6991 HInstruction* length = Add<HArgumentsLength>(elements); |
| 6991 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); | 6992 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); |
| 6992 HInstruction* result = | 6993 HInstruction* result = |
| 6993 new(zone()) HApplyArguments(function, | 6994 new(zone()) HApplyArguments(function, |
| 6994 wrapped_receiver, | 6995 wrapped_receiver, |
| 6995 length, | 6996 length, |
| 6996 elements); | 6997 elements); |
| 6997 result->set_position(expr->position()); | |
| 6998 ast_context()->ReturnInstruction(result, expr->id()); | 6998 ast_context()->ReturnInstruction(result, expr->id()); |
| 6999 return true; | 6999 return true; |
| 7000 } else { | 7000 } else { |
| 7001 // We are inside inlined function and we know exactly what is inside | 7001 // We are inside inlined function and we know exactly what is inside |
| 7002 // arguments object. But we need to be able to materialize at deopt. | 7002 // arguments object. But we need to be able to materialize at deopt. |
| 7003 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), | 7003 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), |
| 7004 function_state()->entry()->arguments_object()->arguments_count()); | 7004 function_state()->entry()->arguments_object()->arguments_count()); |
| 7005 HArgumentsObject* args = function_state()->entry()->arguments_object(); | 7005 HArgumentsObject* args = function_state()->entry()->arguments_object(); |
| 7006 const ZoneList<HValue*>* arguments_values = args->arguments_values(); | 7006 const ZoneList<HValue*>* arguments_values = args->arguments_values(); |
| 7007 int arguments_count = arguments_values->length(); | 7007 int arguments_count = arguments_values->length(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 7025 PushAndAdd(New<HPushArgument>(arguments_values->at(i))); | 7025 PushAndAdd(New<HPushArgument>(arguments_values->at(i))); |
| 7026 } | 7026 } |
| 7027 | 7027 |
| 7028 HValue* context = environment()->context(); | 7028 HValue* context = environment()->context(); |
| 7029 HInvokeFunction* call = new(zone()) HInvokeFunction( | 7029 HInvokeFunction* call = new(zone()) HInvokeFunction( |
| 7030 context, | 7030 context, |
| 7031 function, | 7031 function, |
| 7032 known_function, | 7032 known_function, |
| 7033 arguments_count); | 7033 arguments_count); |
| 7034 Drop(arguments_count); | 7034 Drop(arguments_count); |
| 7035 call->set_position(expr->position()); | |
| 7036 ast_context()->ReturnInstruction(call, expr->id()); | 7035 ast_context()->ReturnInstruction(call, expr->id()); |
| 7037 return true; | 7036 return true; |
| 7038 } | 7037 } |
| 7039 } | 7038 } |
| 7040 | 7039 |
| 7041 | 7040 |
| 7042 void HOptimizedGraphBuilder::VisitCall(Call* expr) { | 7041 void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
| 7043 ASSERT(!HasStackOverflow()); | 7042 ASSERT(!HasStackOverflow()); |
| 7044 ASSERT(current_block() != NULL); | 7043 ASSERT(current_block() != NULL); |
| 7045 ASSERT(current_block()->HasPredecessor()); | 7044 ASSERT(current_block()->HasPredecessor()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 7056 CHECK_ALIVE(VisitForValue(prop->key())); | 7055 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7057 // Push receiver and key like the non-optimized code generator expects it. | 7056 // Push receiver and key like the non-optimized code generator expects it. |
| 7058 HValue* key = Pop(); | 7057 HValue* key = Pop(); |
| 7059 HValue* receiver = Pop(); | 7058 HValue* receiver = Pop(); |
| 7060 Push(key); | 7059 Push(key); |
| 7061 Push(receiver); | 7060 Push(receiver); |
| 7062 | 7061 |
| 7063 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7062 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 7064 | 7063 |
| 7065 call = New<HCallKeyed>(key, argument_count); | 7064 call = New<HCallKeyed>(key, argument_count); |
| 7066 call->set_position(expr->position()); | |
| 7067 Drop(argument_count + 1); // 1 is the key. | 7065 Drop(argument_count + 1); // 1 is the key. |
| 7068 return ast_context()->ReturnInstruction(call, expr->id()); | 7066 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7069 } | 7067 } |
| 7070 | 7068 |
| 7071 // Named function call. | 7069 // Named function call. |
| 7072 if (TryCallApply(expr)) return; | 7070 if (TryCallApply(expr)) return; |
| 7073 | 7071 |
| 7074 CHECK_ALIVE(VisitForValue(prop->obj())); | 7072 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7075 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7073 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 7076 | 7074 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7110 New<HCallConstantFunction>(expr->target(), argument_count)); | 7108 New<HCallConstantFunction>(expr->target(), argument_count)); |
| 7111 } | 7109 } |
| 7112 } else if (types != NULL && types->length() > 1) { | 7110 } else if (types != NULL && types->length() > 1) { |
| 7113 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 7111 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
| 7114 HandlePolymorphicCallNamed(expr, receiver, types, name); | 7112 HandlePolymorphicCallNamed(expr, receiver, types, name); |
| 7115 return; | 7113 return; |
| 7116 | 7114 |
| 7117 } else { | 7115 } else { |
| 7118 call = PreProcessCall(New<HCallNamed>(name, argument_count)); | 7116 call = PreProcessCall(New<HCallNamed>(name, argument_count)); |
| 7119 } | 7117 } |
| 7120 | |
| 7121 } else { | 7118 } else { |
| 7122 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7119 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 7123 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 7120 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
| 7124 return Bailout(kPossibleDirectCallToEval); | 7121 return Bailout(kPossibleDirectCallToEval); |
| 7125 } | 7122 } |
| 7126 | 7123 |
| 7127 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 7124 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
| 7128 if (global_call) { | 7125 if (global_call) { |
| 7129 Variable* var = proxy->var(); | 7126 Variable* var = proxy->var(); |
| 7130 bool known_global_function = false; | 7127 bool known_global_function = false; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7223 HGlobalObject* global_object = Add<HGlobalObject>(); | 7220 HGlobalObject* global_object = Add<HGlobalObject>(); |
| 7224 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object); | 7221 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object); |
| 7225 PushAndAdd(New<HPushArgument>(receiver)); | 7222 PushAndAdd(New<HPushArgument>(receiver)); |
| 7226 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7223 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 7227 | 7224 |
| 7228 call = New<HCallFunction>(function, argument_count); | 7225 call = New<HCallFunction>(function, argument_count); |
| 7229 Drop(argument_count + 1); | 7226 Drop(argument_count + 1); |
| 7230 } | 7227 } |
| 7231 } | 7228 } |
| 7232 | 7229 |
| 7233 call->set_position(expr->position()); | |
| 7234 return ast_context()->ReturnInstruction(call, expr->id()); | 7230 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7235 } | 7231 } |
| 7236 | 7232 |
| 7237 | 7233 |
| 7238 // Checks whether allocation using the given constructor can be inlined. | 7234 // Checks whether allocation using the given constructor can be inlined. |
| 7239 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 7235 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
| 7240 return constructor->has_initial_map() && | 7236 return constructor->has_initial_map() && |
| 7241 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 7237 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
| 7242 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && | 7238 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && |
| 7243 constructor->initial_map()->InitialPropertiesLength() == 0; | 7239 constructor->initial_map()->InitialPropertiesLength() == 0; |
| 7244 } | 7240 } |
| 7245 | 7241 |
| 7246 | 7242 |
| 7247 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 7243 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
| 7248 ASSERT(!HasStackOverflow()); | 7244 ASSERT(!HasStackOverflow()); |
| 7249 ASSERT(current_block() != NULL); | 7245 ASSERT(current_block() != NULL); |
| 7250 ASSERT(current_block()->HasPredecessor()); | 7246 ASSERT(current_block()->HasPredecessor()); |
| 7247 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
| 7251 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 7248 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
| 7252 Factory* factory = isolate()->factory(); | 7249 Factory* factory = isolate()->factory(); |
| 7253 | 7250 |
| 7254 if (FLAG_inline_construct && | 7251 if (FLAG_inline_construct && |
| 7255 expr->IsMonomorphic() && | 7252 expr->IsMonomorphic() && |
| 7256 IsAllocationInlineable(expr->target())) { | 7253 IsAllocationInlineable(expr->target())) { |
| 7257 // The constructor function is on the stack in the unoptimized code | 7254 // The constructor function is on the stack in the unoptimized code |
| 7258 // during evaluation of the arguments. | 7255 // during evaluation of the arguments. |
| 7259 CHECK_ALIVE(VisitForValue(expr->expression())); | 7256 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7260 HValue* function = Top(); | 7257 HValue* function = Top(); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7332 HInstruction* prev_instr = instr->previous(); | 7329 HInstruction* prev_instr = instr->previous(); |
| 7333 instr->DeleteAndReplaceWith(NULL); | 7330 instr->DeleteAndReplaceWith(NULL); |
| 7334 instr = prev_instr; | 7331 instr = prev_instr; |
| 7335 } | 7332 } |
| 7336 initial_map_value->DeleteAndReplaceWith(NULL); | 7333 initial_map_value->DeleteAndReplaceWith(NULL); |
| 7337 receiver->DeleteAndReplaceWith(NULL); | 7334 receiver->DeleteAndReplaceWith(NULL); |
| 7338 check->DeleteAndReplaceWith(NULL); | 7335 check->DeleteAndReplaceWith(NULL); |
| 7339 environment()->SetExpressionStackAt(receiver_index, function); | 7336 environment()->SetExpressionStackAt(receiver_index, function); |
| 7340 HInstruction* call = | 7337 HInstruction* call = |
| 7341 PreProcessCall(New<HCallNew>(function, argument_count)); | 7338 PreProcessCall(New<HCallNew>(function, argument_count)); |
| 7342 call->set_position(expr->position()); | |
| 7343 return ast_context()->ReturnInstruction(call, expr->id()); | 7339 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7344 } else { | 7340 } else { |
| 7345 // The constructor function is both an operand to the instruction and an | 7341 // The constructor function is both an operand to the instruction and an |
| 7346 // argument to the construct call. | 7342 // argument to the construct call. |
| 7347 Handle<JSFunction> array_function( | 7343 Handle<JSFunction> array_function( |
| 7348 isolate()->global_context()->array_function(), isolate()); | 7344 isolate()->global_context()->array_function(), isolate()); |
| 7349 CHECK_ALIVE(VisitArgument(expr->expression())); | 7345 CHECK_ALIVE(VisitArgument(expr->expression())); |
| 7350 HValue* constructor = HPushArgument::cast(Top())->argument(); | 7346 HValue* constructor = HPushArgument::cast(Top())->argument(); |
| 7351 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7347 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 7352 HBinaryCall* call; | 7348 HBinaryCall* call; |
| 7353 if (expr->target().is_identical_to(array_function)) { | 7349 if (expr->target().is_identical_to(array_function)) { |
| 7354 Handle<Cell> cell = expr->allocation_info_cell(); | 7350 Handle<Cell> cell = expr->allocation_info_cell(); |
| 7355 Add<HCheckValue>(constructor, array_function); | 7351 Add<HCheckValue>(constructor, array_function); |
| 7356 call = New<HCallNewArray>(constructor, argument_count, | 7352 call = New<HCallNewArray>(constructor, argument_count, |
| 7357 cell, expr->elements_kind()); | 7353 cell, expr->elements_kind()); |
| 7358 } else { | 7354 } else { |
| 7359 call = New<HCallNew>(constructor, argument_count); | 7355 call = New<HCallNew>(constructor, argument_count); |
| 7360 } | 7356 } |
| 7361 Drop(argument_count); | 7357 Drop(argument_count); |
| 7362 call->set_position(expr->position()); | |
| 7363 return ast_context()->ReturnInstruction(call, expr->id()); | 7358 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7364 } | 7359 } |
| 7365 } | 7360 } |
| 7366 | 7361 |
| 7367 | 7362 |
| 7368 // Support for generating inlined runtime functions. | 7363 // Support for generating inlined runtime functions. |
| 7369 | 7364 |
| 7370 // Lookup table for generators for runtime calls that are generated inline. | 7365 // Lookup table for generators for runtime calls that are generated inline. |
| 7371 // Elements of the table are member pointers to functions of | 7366 // Elements of the table are member pointers to functions of |
| 7372 // HOptimizedGraphBuilder. | 7367 // HOptimizedGraphBuilder. |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7583 if (key != NULL) Push(key); | 7578 if (key != NULL) Push(key); |
| 7584 Push(value); | 7579 Push(value); |
| 7585 BuildStore(expr, prop, ast_id, return_id); | 7580 BuildStore(expr, prop, ast_id, return_id); |
| 7586 } | 7581 } |
| 7587 | 7582 |
| 7588 | 7583 |
| 7589 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 7584 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| 7590 ASSERT(!HasStackOverflow()); | 7585 ASSERT(!HasStackOverflow()); |
| 7591 ASSERT(current_block() != NULL); | 7586 ASSERT(current_block() != NULL); |
| 7592 ASSERT(current_block()->HasPredecessor()); | 7587 ASSERT(current_block()->HasPredecessor()); |
| 7588 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
| 7593 Expression* target = expr->expression(); | 7589 Expression* target = expr->expression(); |
| 7594 VariableProxy* proxy = target->AsVariableProxy(); | 7590 VariableProxy* proxy = target->AsVariableProxy(); |
| 7595 Property* prop = target->AsProperty(); | 7591 Property* prop = target->AsProperty(); |
| 7596 if (proxy == NULL && prop == NULL) { | 7592 if (proxy == NULL && prop == NULL) { |
| 7597 return Bailout(kInvalidLhsInCountOperation); | 7593 return Bailout(kInvalidLhsInCountOperation); |
| 7598 } | 7594 } |
| 7599 | 7595 |
| 7600 // Match the full code generator stack by simulating an extra stack | 7596 // Match the full code generator stack by simulating an extra stack |
| 7601 // element for postfix operations in a non-effect context. The return | 7597 // element for postfix operations in a non-effect context. The return |
| 7602 // value is ToNumber(input). | 7598 // value is ToNumber(input). |
| (...skipping 12 matching lines...) Expand all Loading... |
| 7615 CHECK_ALIVE(VisitForValue(target)); | 7611 CHECK_ALIVE(VisitForValue(target)); |
| 7616 | 7612 |
| 7617 after = BuildIncrement(returns_original_input, expr); | 7613 after = BuildIncrement(returns_original_input, expr); |
| 7618 input = returns_original_input ? Top() : Pop(); | 7614 input = returns_original_input ? Top() : Pop(); |
| 7619 Push(after); | 7615 Push(after); |
| 7620 | 7616 |
| 7621 switch (var->location()) { | 7617 switch (var->location()) { |
| 7622 case Variable::UNALLOCATED: | 7618 case Variable::UNALLOCATED: |
| 7623 HandleGlobalVariableAssignment(var, | 7619 HandleGlobalVariableAssignment(var, |
| 7624 after, | 7620 after, |
| 7625 expr->position(), | |
| 7626 expr->AssignmentId()); | 7621 expr->AssignmentId()); |
| 7627 break; | 7622 break; |
| 7628 | 7623 |
| 7629 case Variable::PARAMETER: | 7624 case Variable::PARAMETER: |
| 7630 case Variable::LOCAL: | 7625 case Variable::LOCAL: |
| 7631 BindIfLive(var, after); | 7626 BindIfLive(var, after); |
| 7632 break; | 7627 break; |
| 7633 | 7628 |
| 7634 case Variable::CONTEXT: { | 7629 case Variable::CONTEXT: { |
| 7635 // Bail out if we try to mutate a parameter value in a function | 7630 // Bail out if we try to mutate a parameter value in a function |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7673 CHECK_ALIVE(VisitForValue(prop->obj())); | 7668 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7674 HValue* object = Top(); | 7669 HValue* object = Top(); |
| 7675 | 7670 |
| 7676 HValue* key = NULL; | 7671 HValue* key = NULL; |
| 7677 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || | 7672 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || |
| 7678 prop->IsStringAccess()) { | 7673 prop->IsStringAccess()) { |
| 7679 CHECK_ALIVE(VisitForValue(prop->key())); | 7674 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7680 key = Top(); | 7675 key = Top(); |
| 7681 } | 7676 } |
| 7682 | 7677 |
| 7683 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); | 7678 CHECK_ALIVE(PushLoad(prop, object, key)); |
| 7684 | 7679 |
| 7685 after = BuildIncrement(returns_original_input, expr); | 7680 after = BuildIncrement(returns_original_input, expr); |
| 7686 | 7681 |
| 7687 if (returns_original_input) { | 7682 if (returns_original_input) { |
| 7688 input = Pop(); | 7683 input = Pop(); |
| 7689 // Drop object and key to push it again in the effect context below. | 7684 // Drop object and key to push it again in the effect context below. |
| 7690 Drop(key == NULL ? 1 : 2); | 7685 Drop(key == NULL ? 1 : 2); |
| 7691 environment()->SetExpressionStackAt(0, input); | 7686 environment()->SetExpressionStackAt(0, input); |
| 7692 CHECK_ALIVE(BuildStoreForEffect( | 7687 CHECK_ALIVE(BuildStoreForEffect( |
| 7693 expr, prop, expr->id(), expr->AssignmentId(), object, key, after)); | 7688 expr, prop, expr->id(), expr->AssignmentId(), object, key, after)); |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8083 return ast_context()->ReturnValue(Pop()); | 8078 return ast_context()->ReturnValue(Pop()); |
| 8084 } | 8079 } |
| 8085 | 8080 |
| 8086 // We need an extra block to maintain edge-split form. | 8081 // We need an extra block to maintain edge-split form. |
| 8087 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 8082 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
| 8088 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 8083 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
| 8089 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); | 8084 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); |
| 8090 HBranch* test = is_logical_and | 8085 HBranch* test = is_logical_and |
| 8091 ? New<HBranch>(left_value, expected, eval_right, empty_block) | 8086 ? New<HBranch>(left_value, expected, eval_right, empty_block) |
| 8092 : New<HBranch>(left_value, expected, empty_block, eval_right); | 8087 : New<HBranch>(left_value, expected, empty_block, eval_right); |
| 8093 current_block()->Finish(test); | 8088 FinishCurrentBlock(test); |
| 8094 | 8089 |
| 8095 set_current_block(eval_right); | 8090 set_current_block(eval_right); |
| 8096 Drop(1); // Value of the left subexpression. | 8091 Drop(1); // Value of the left subexpression. |
| 8097 CHECK_BAILOUT(VisitForValue(expr->right())); | 8092 CHECK_BAILOUT(VisitForValue(expr->right())); |
| 8098 | 8093 |
| 8099 HBasicBlock* join_block = | 8094 HBasicBlock* join_block = |
| 8100 CreateJoin(empty_block, current_block(), expr->id()); | 8095 CreateJoin(empty_block, current_block(), expr->id()); |
| 8101 set_current_block(join_block); | 8096 set_current_block(join_block); |
| 8102 return ast_context()->ReturnValue(Pop()); | 8097 return ast_context()->ReturnValue(Pop()); |
| 8103 | 8098 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8140 set_current_block(join_block); | 8135 set_current_block(join_block); |
| 8141 // We did not materialize any value in the predecessor environments, | 8136 // We did not materialize any value in the predecessor environments, |
| 8142 // so there is no need to handle it here. | 8137 // so there is no need to handle it here. |
| 8143 } | 8138 } |
| 8144 } | 8139 } |
| 8145 | 8140 |
| 8146 | 8141 |
| 8147 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { | 8142 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { |
| 8148 CHECK_ALIVE(VisitForValue(expr->left())); | 8143 CHECK_ALIVE(VisitForValue(expr->left())); |
| 8149 CHECK_ALIVE(VisitForValue(expr->right())); | 8144 CHECK_ALIVE(VisitForValue(expr->right())); |
| 8145 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
| 8150 HValue* right = Pop(); | 8146 HValue* right = Pop(); |
| 8151 HValue* left = Pop(); | 8147 HValue* left = Pop(); |
| 8152 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 8148 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
| 8153 instr->set_position(expr->position()); | |
| 8154 return ast_context()->ReturnInstruction(instr, expr->id()); | 8149 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 8155 } | 8150 } |
| 8156 | 8151 |
| 8157 | 8152 |
| 8158 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 8153 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
| 8159 Expression* sub_expr, | 8154 Expression* sub_expr, |
| 8160 Handle<String> check) { | 8155 Handle<String> check) { |
| 8161 CHECK_ALIVE(VisitForTypeOf(sub_expr)); | 8156 CHECK_ALIVE(VisitForTypeOf(sub_expr)); |
| 8157 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
| 8162 HValue* value = Pop(); | 8158 HValue* value = Pop(); |
| 8163 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); | 8159 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); |
| 8164 instr->set_position(expr->position()); | |
| 8165 return ast_context()->ReturnControl(instr, expr->id()); | 8160 return ast_context()->ReturnControl(instr, expr->id()); |
| 8166 } | 8161 } |
| 8167 | 8162 |
| 8168 | 8163 |
| 8169 static bool IsLiteralCompareBool(Isolate* isolate, | 8164 static bool IsLiteralCompareBool(Isolate* isolate, |
| 8170 HValue* left, | 8165 HValue* left, |
| 8171 Token::Value op, | 8166 Token::Value op, |
| 8172 HValue* right) { | 8167 HValue* right) { |
| 8173 return op == Token::EQ_STRICT && | 8168 return op == Token::EQ_STRICT && |
| 8174 ((left->IsConstant() && | 8169 ((left->IsConstant() && |
| 8175 HConstant::cast(left)->handle(isolate)->IsBoolean()) || | 8170 HConstant::cast(left)->handle(isolate)->IsBoolean()) || |
| 8176 (right->IsConstant() && | 8171 (right->IsConstant() && |
| 8177 HConstant::cast(right)->handle(isolate)->IsBoolean())); | 8172 HConstant::cast(right)->handle(isolate)->IsBoolean())); |
| 8178 } | 8173 } |
| 8179 | 8174 |
| 8180 | 8175 |
| 8181 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 8176 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| 8182 ASSERT(!HasStackOverflow()); | 8177 ASSERT(!HasStackOverflow()); |
| 8183 ASSERT(current_block() != NULL); | 8178 ASSERT(current_block() != NULL); |
| 8184 ASSERT(current_block()->HasPredecessor()); | 8179 ASSERT(current_block()->HasPredecessor()); |
| 8185 | 8180 |
| 8181 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
| 8182 |
| 8186 // Check for a few fast cases. The AST visiting behavior must be in sync | 8183 // Check for a few fast cases. The AST visiting behavior must be in sync |
| 8187 // with the full codegen: We don't push both left and right values onto | 8184 // with the full codegen: We don't push both left and right values onto |
| 8188 // the expression stack when one side is a special-case literal. | 8185 // the expression stack when one side is a special-case literal. |
| 8189 Expression* sub_expr = NULL; | 8186 Expression* sub_expr = NULL; |
| 8190 Handle<String> check; | 8187 Handle<String> check; |
| 8191 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { | 8188 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { |
| 8192 return HandleLiteralCompareTypeof(expr, sub_expr, check); | 8189 return HandleLiteralCompareTypeof(expr, sub_expr, check); |
| 8193 } | 8190 } |
| 8194 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { | 8191 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { |
| 8195 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); | 8192 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); |
| 8196 } | 8193 } |
| 8197 if (expr->IsLiteralCompareNull(&sub_expr)) { | 8194 if (expr->IsLiteralCompareNull(&sub_expr)) { |
| 8198 return HandleLiteralCompareNil(expr, sub_expr, kNullValue); | 8195 return HandleLiteralCompareNil(expr, sub_expr, kNullValue); |
| 8199 } | 8196 } |
| 8200 | 8197 |
| 8201 if (IsClassOfTest(expr)) { | 8198 if (IsClassOfTest(expr)) { |
| 8202 CallRuntime* call = expr->left()->AsCallRuntime(); | 8199 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 8203 ASSERT(call->arguments()->length() == 1); | 8200 ASSERT(call->arguments()->length() == 1); |
| 8204 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8201 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 8205 HValue* value = Pop(); | 8202 HValue* value = Pop(); |
| 8206 Literal* literal = expr->right()->AsLiteral(); | 8203 Literal* literal = expr->right()->AsLiteral(); |
| 8207 Handle<String> rhs = Handle<String>::cast(literal->value()); | 8204 Handle<String> rhs = Handle<String>::cast(literal->value()); |
| 8208 HClassOfTestAndBranch* instr = | 8205 HClassOfTestAndBranch* instr = |
| 8209 new(zone()) HClassOfTestAndBranch(value, rhs); | 8206 new(zone()) HClassOfTestAndBranch(value, rhs); |
| 8210 instr->set_position(expr->position()); | |
| 8211 return ast_context()->ReturnControl(instr, expr->id()); | 8207 return ast_context()->ReturnControl(instr, expr->id()); |
| 8212 } | 8208 } |
| 8213 | 8209 |
| 8214 Handle<Type> left_type = expr->left()->bounds().lower; | 8210 Handle<Type> left_type = expr->left()->bounds().lower; |
| 8215 Handle<Type> right_type = expr->right()->bounds().lower; | 8211 Handle<Type> right_type = expr->right()->bounds().lower; |
| 8216 Handle<Type> combined_type = expr->combined_type(); | 8212 Handle<Type> combined_type = expr->combined_type(); |
| 8217 Representation combined_rep = Representation::FromType(combined_type); | 8213 Representation combined_rep = Representation::FromType(combined_type); |
| 8218 Representation left_rep = Representation::FromType(left_type); | 8214 Representation left_rep = Representation::FromType(left_type); |
| 8219 Representation right_rep = Representation::FromType(right_type); | 8215 Representation right_rep = Representation::FromType(right_type); |
| 8220 | 8216 |
| 8221 CHECK_ALIVE(VisitForValue(expr->left())); | 8217 CHECK_ALIVE(VisitForValue(expr->left())); |
| 8222 CHECK_ALIVE(VisitForValue(expr->right())); | 8218 CHECK_ALIVE(VisitForValue(expr->right())); |
| 8223 | 8219 |
| 8224 HValue* context = environment()->context(); | 8220 HValue* context = environment()->context(); |
| 8225 HValue* right = Pop(); | 8221 HValue* right = Pop(); |
| 8226 HValue* left = Pop(); | 8222 HValue* left = Pop(); |
| 8227 Token::Value op = expr->op(); | 8223 Token::Value op = expr->op(); |
| 8228 | 8224 |
| 8229 if (IsLiteralCompareBool(isolate(), left, op, right)) { | 8225 if (IsLiteralCompareBool(isolate(), left, op, right)) { |
| 8230 HCompareObjectEqAndBranch* result = | 8226 HCompareObjectEqAndBranch* result = |
| 8231 New<HCompareObjectEqAndBranch>(left, right); | 8227 New<HCompareObjectEqAndBranch>(left, right); |
| 8232 result->set_position(expr->position()); | |
| 8233 return ast_context()->ReturnControl(result, expr->id()); | 8228 return ast_context()->ReturnControl(result, expr->id()); |
| 8234 } | 8229 } |
| 8235 | 8230 |
| 8236 if (op == Token::INSTANCEOF) { | 8231 if (op == Token::INSTANCEOF) { |
| 8237 // Check to see if the rhs of the instanceof is a global function not | 8232 // Check to see if the rhs of the instanceof is a global function not |
| 8238 // residing in new space. If it is we assume that the function will stay the | 8233 // residing in new space. If it is we assume that the function will stay the |
| 8239 // same. | 8234 // same. |
| 8240 Handle<JSFunction> target = Handle<JSFunction>::null(); | 8235 Handle<JSFunction> target = Handle<JSFunction>::null(); |
| 8241 VariableProxy* proxy = expr->right()->AsVariableProxy(); | 8236 VariableProxy* proxy = expr->right()->AsVariableProxy(); |
| 8242 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); | 8237 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 8254 if (!isolate()->heap()->InNewSpace(*candidate)) { | 8249 if (!isolate()->heap()->InNewSpace(*candidate)) { |
| 8255 target = candidate; | 8250 target = candidate; |
| 8256 } | 8251 } |
| 8257 } | 8252 } |
| 8258 } | 8253 } |
| 8259 | 8254 |
| 8260 // If the target is not null we have found a known global function that is | 8255 // If the target is not null we have found a known global function that is |
| 8261 // assumed to stay the same for this instanceof. | 8256 // assumed to stay the same for this instanceof. |
| 8262 if (target.is_null()) { | 8257 if (target.is_null()) { |
| 8263 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); | 8258 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); |
| 8264 result->set_position(expr->position()); | |
| 8265 return ast_context()->ReturnInstruction(result, expr->id()); | 8259 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8266 } else { | 8260 } else { |
| 8267 Add<HCheckValue>(right, target); | 8261 Add<HCheckValue>(right, target); |
| 8268 HInstanceOfKnownGlobal* result = | 8262 HInstanceOfKnownGlobal* result = |
| 8269 New<HInstanceOfKnownGlobal>(left, target); | 8263 New<HInstanceOfKnownGlobal>(left, target); |
| 8270 result->set_position(expr->position()); | |
| 8271 return ast_context()->ReturnInstruction(result, expr->id()); | 8264 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8272 } | 8265 } |
| 8273 | 8266 |
| 8274 // Code below assumes that we don't fall through. | 8267 // Code below assumes that we don't fall through. |
| 8275 UNREACHABLE(); | 8268 UNREACHABLE(); |
| 8276 } else if (op == Token::IN) { | 8269 } else if (op == Token::IN) { |
| 8277 HValue* function = AddLoadJSBuiltin(Builtins::IN); | 8270 HValue* function = AddLoadJSBuiltin(Builtins::IN); |
| 8278 Add<HPushArgument>(left); | 8271 Add<HPushArgument>(left); |
| 8279 Add<HPushArgument>(right); | 8272 Add<HPushArgument>(right); |
| 8280 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 8273 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
| 8281 // even though we are certain to pass the correct number of arguments here. | 8274 // even though we are certain to pass the correct number of arguments here. |
| 8282 HInstruction* result = New<HInvokeFunction>(function, 2); | 8275 HInstruction* result = New<HInvokeFunction>(function, 2); |
| 8283 result->set_position(expr->position()); | |
| 8284 return ast_context()->ReturnInstruction(result, expr->id()); | 8276 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8285 } | 8277 } |
| 8286 | 8278 |
| 8287 // Cases handled below depend on collected type feedback. They should | 8279 // Cases handled below depend on collected type feedback. They should |
| 8288 // soft deoptimize when there is no type feedback. | 8280 // soft deoptimize when there is no type feedback. |
| 8289 if (combined_type->Is(Type::None())) { | 8281 if (combined_type->Is(Type::None())) { |
| 8290 Add<HDeoptimize>("Insufficient type feedback for combined type " | 8282 Add<HDeoptimize>("Insufficient type feedback for combined type " |
| 8291 "of binary operation", | 8283 "of binary operation", |
| 8292 Deoptimizer::SOFT); | 8284 Deoptimizer::SOFT); |
| 8293 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 8285 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
| 8294 } | 8286 } |
| 8295 | 8287 |
| 8296 if (combined_type->Is(Type::Receiver())) { | 8288 if (combined_type->Is(Type::Receiver())) { |
| 8297 switch (op) { | 8289 switch (op) { |
| 8298 case Token::EQ: | 8290 case Token::EQ: |
| 8299 case Token::EQ_STRICT: { | 8291 case Token::EQ_STRICT: { |
| 8300 // Can we get away with map check and not instance type check? | 8292 // Can we get away with map check and not instance type check? |
| 8301 if (combined_type->IsClass()) { | 8293 if (combined_type->IsClass()) { |
| 8302 Handle<Map> map = combined_type->AsClass(); | 8294 Handle<Map> map = combined_type->AsClass(); |
| 8303 AddCheckMap(left, map); | 8295 AddCheckMap(left, map); |
| 8304 AddCheckMap(right, map); | 8296 AddCheckMap(right, map); |
| 8305 HCompareObjectEqAndBranch* result = | 8297 HCompareObjectEqAndBranch* result = |
| 8306 New<HCompareObjectEqAndBranch>(left, right); | 8298 New<HCompareObjectEqAndBranch>(left, right); |
| 8307 result->set_position(expr->position()); | |
| 8308 return ast_context()->ReturnControl(result, expr->id()); | 8299 return ast_context()->ReturnControl(result, expr->id()); |
| 8309 } else { | 8300 } else { |
| 8310 BuildCheckHeapObject(left); | 8301 BuildCheckHeapObject(left); |
| 8311 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 8302 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
| 8312 BuildCheckHeapObject(right); | 8303 BuildCheckHeapObject(right); |
| 8313 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 8304 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
| 8314 HCompareObjectEqAndBranch* result = | 8305 HCompareObjectEqAndBranch* result = |
| 8315 New<HCompareObjectEqAndBranch>(left, right); | 8306 New<HCompareObjectEqAndBranch>(left, right); |
| 8316 result->set_position(expr->position()); | |
| 8317 return ast_context()->ReturnControl(result, expr->id()); | 8307 return ast_context()->ReturnControl(result, expr->id()); |
| 8318 } | 8308 } |
| 8319 } | 8309 } |
| 8320 default: | 8310 default: |
| 8321 return Bailout(kUnsupportedNonPrimitiveCompare); | 8311 return Bailout(kUnsupportedNonPrimitiveCompare); |
| 8322 } | 8312 } |
| 8323 } else if (combined_type->Is(Type::InternalizedString()) && | 8313 } else if (combined_type->Is(Type::InternalizedString()) && |
| 8324 Token::IsEqualityOp(op)) { | 8314 Token::IsEqualityOp(op)) { |
| 8325 BuildCheckHeapObject(left); | 8315 BuildCheckHeapObject(left); |
| 8326 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); | 8316 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); |
| 8327 BuildCheckHeapObject(right); | 8317 BuildCheckHeapObject(right); |
| 8328 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); | 8318 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); |
| 8329 HCompareObjectEqAndBranch* result = | 8319 HCompareObjectEqAndBranch* result = |
| 8330 New<HCompareObjectEqAndBranch>(left, right); | 8320 New<HCompareObjectEqAndBranch>(left, right); |
| 8331 result->set_position(expr->position()); | |
| 8332 return ast_context()->ReturnControl(result, expr->id()); | 8321 return ast_context()->ReturnControl(result, expr->id()); |
| 8333 } else if (combined_type->Is(Type::String())) { | 8322 } else if (combined_type->Is(Type::String())) { |
| 8334 BuildCheckHeapObject(left); | 8323 BuildCheckHeapObject(left); |
| 8335 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 8324 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 8336 BuildCheckHeapObject(right); | 8325 BuildCheckHeapObject(right); |
| 8337 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 8326 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| 8338 HStringCompareAndBranch* result = | 8327 HStringCompareAndBranch* result = |
| 8339 New<HStringCompareAndBranch>(left, right, op); | 8328 New<HStringCompareAndBranch>(left, right, op); |
| 8340 result->set_position(expr->position()); | |
| 8341 return ast_context()->ReturnControl(result, expr->id()); | 8329 return ast_context()->ReturnControl(result, expr->id()); |
| 8342 } else if (combined_type->NumClasses() == 1 && Token::IsEqualityOp(op)) { | 8330 } else if (combined_type->NumClasses() == 1 && Token::IsEqualityOp(op)) { |
| 8343 BuildCheckHeapObject(left); | 8331 BuildCheckHeapObject(left); |
| 8344 BuildCheckMap(left, combined_type->Classes().Current()); | 8332 BuildCheckMap(left, combined_type->Classes().Current()); |
| 8345 BuildCheckHeapObject(right); | 8333 BuildCheckHeapObject(right); |
| 8346 BuildCheckMap(right, combined_type->Classes().Current()); | 8334 BuildCheckMap(right, combined_type->Classes().Current()); |
| 8347 HCompareObjectEqAndBranch* result = | 8335 HCompareObjectEqAndBranch* result = |
| 8348 New<HCompareObjectEqAndBranch>(left, right); | 8336 New<HCompareObjectEqAndBranch>(left, right); |
| 8349 result->set_position(expr->position()); | |
| 8350 return ast_context()->ReturnInstruction(result, expr->id()); | 8337 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8351 } else if (combined_type->Is(Type::Receiver()) && Token::IsEqualityOp(op)) { | 8338 } else if (combined_type->Is(Type::Receiver()) && Token::IsEqualityOp(op)) { |
| 8352 BuildCheckHeapObject(left); | 8339 BuildCheckHeapObject(left); |
| 8353 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 8340 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
| 8354 BuildCheckHeapObject(right); | 8341 BuildCheckHeapObject(right); |
| 8355 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 8342 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
| 8356 HCompareObjectEqAndBranch* result = | 8343 HCompareObjectEqAndBranch* result = |
| 8357 New<HCompareObjectEqAndBranch>(left, right); | 8344 New<HCompareObjectEqAndBranch>(left, right); |
| 8358 result->set_position(expr->position()); | |
| 8359 return ast_context()->ReturnInstruction(result, expr->id()); | 8345 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8360 } else { | 8346 } else { |
| 8361 if (combined_rep.IsTagged() || combined_rep.IsNone()) { | 8347 if (combined_rep.IsTagged() || combined_rep.IsNone()) { |
| 8362 HCompareGeneric* result = | 8348 HCompareGeneric* result = |
| 8363 new(zone()) HCompareGeneric(context, left, right, op); | 8349 new(zone()) HCompareGeneric(context, left, right, op); |
| 8364 result->set_observed_input_representation(1, left_rep); | 8350 result->set_observed_input_representation(1, left_rep); |
| 8365 result->set_observed_input_representation(2, right_rep); | 8351 result->set_observed_input_representation(2, right_rep); |
| 8366 result->set_position(expr->position()); | |
| 8367 return ast_context()->ReturnInstruction(result, expr->id()); | 8352 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8368 } else { | 8353 } else { |
| 8369 HCompareNumericAndBranch* result = | 8354 HCompareNumericAndBranch* result = |
| 8370 New<HCompareNumericAndBranch>(left, right, op); | 8355 New<HCompareNumericAndBranch>(left, right, op); |
| 8371 result->set_observed_input_representation(left_rep, right_rep); | 8356 result->set_observed_input_representation(left_rep, right_rep); |
| 8372 result->set_position(expr->position()); | |
| 8373 return ast_context()->ReturnControl(result, expr->id()); | 8357 return ast_context()->ReturnControl(result, expr->id()); |
| 8374 } | 8358 } |
| 8375 } | 8359 } |
| 8376 } | 8360 } |
| 8377 | 8361 |
| 8378 | 8362 |
| 8379 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 8363 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
| 8380 Expression* sub_expr, | 8364 Expression* sub_expr, |
| 8381 NilValue nil) { | 8365 NilValue nil) { |
| 8382 ASSERT(!HasStackOverflow()); | 8366 ASSERT(!HasStackOverflow()); |
| 8383 ASSERT(current_block() != NULL); | 8367 ASSERT(current_block() != NULL); |
| 8384 ASSERT(current_block()->HasPredecessor()); | 8368 ASSERT(current_block()->HasPredecessor()); |
| 8385 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); | 8369 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); |
| 8370 if (!FLAG_opt_code_positions) SetSourcePosition(expr->position()); |
| 8386 CHECK_ALIVE(VisitForValue(sub_expr)); | 8371 CHECK_ALIVE(VisitForValue(sub_expr)); |
| 8387 HValue* value = Pop(); | 8372 HValue* value = Pop(); |
| 8388 if (expr->op() == Token::EQ_STRICT) { | 8373 if (expr->op() == Token::EQ_STRICT) { |
| 8389 HConstant* nil_constant = nil == kNullValue | 8374 HConstant* nil_constant = nil == kNullValue |
| 8390 ? graph()->GetConstantNull() | 8375 ? graph()->GetConstantNull() |
| 8391 : graph()->GetConstantUndefined(); | 8376 : graph()->GetConstantUndefined(); |
| 8392 HCompareObjectEqAndBranch* instr = | 8377 HCompareObjectEqAndBranch* instr = |
| 8393 New<HCompareObjectEqAndBranch>(value, nil_constant); | 8378 New<HCompareObjectEqAndBranch>(value, nil_constant); |
| 8394 instr->set_position(expr->position()); | |
| 8395 return ast_context()->ReturnControl(instr, expr->id()); | 8379 return ast_context()->ReturnControl(instr, expr->id()); |
| 8396 } else { | 8380 } else { |
| 8397 ASSERT_EQ(Token::EQ, expr->op()); | 8381 ASSERT_EQ(Token::EQ, expr->op()); |
| 8398 Handle<Type> type = expr->combined_type()->Is(Type::None()) | 8382 Handle<Type> type = expr->combined_type()->Is(Type::None()) |
| 8399 ? handle(Type::Any(), isolate_) | 8383 ? handle(Type::Any(), isolate_) |
| 8400 : expr->combined_type(); | 8384 : expr->combined_type(); |
| 8401 HIfContinuation continuation; | 8385 HIfContinuation continuation; |
| 8402 BuildCompareNil(value, type, expr->position(), &continuation); | 8386 BuildCompareNil(value, type, &continuation); |
| 8403 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 8387 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 8404 } | 8388 } |
| 8405 } | 8389 } |
| 8406 | 8390 |
| 8407 | 8391 |
| 8408 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 8392 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| 8409 // If we share optimized code between different closures, the | 8393 // If we share optimized code between different closures, the |
| 8410 // this-function is not a constant, except inside an inlined body. | 8394 // this-function is not a constant, except inside an inlined body. |
| 8411 if (function_state()->outer() != NULL) { | 8395 if (function_state()->outer() != NULL) { |
| 8412 return New<HConstant>( | 8396 return New<HConstant>( |
| (...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8976 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { | 8960 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { |
| 8977 ASSERT(call->arguments()->length() == 2); | 8961 ASSERT(call->arguments()->length() == 2); |
| 8978 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8962 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 8979 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 8963 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 8980 HValue* value = Pop(); | 8964 HValue* value = Pop(); |
| 8981 HValue* object = Pop(); | 8965 HValue* object = Pop(); |
| 8982 // Check if object is a not a smi. | 8966 // Check if object is a not a smi. |
| 8983 HBasicBlock* if_smi = graph()->CreateBasicBlock(); | 8967 HBasicBlock* if_smi = graph()->CreateBasicBlock(); |
| 8984 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); | 8968 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); |
| 8985 HBasicBlock* join = graph()->CreateBasicBlock(); | 8969 HBasicBlock* join = graph()->CreateBasicBlock(); |
| 8986 current_block()->Finish(New<HIsSmiAndBranch>(object, if_smi, if_heap_object)); | 8970 FinishCurrentBlock(New<HIsSmiAndBranch>(object, if_smi, if_heap_object)); |
| 8987 if_smi->Goto(join); | 8971 Goto(if_smi, join); |
| 8988 | 8972 |
| 8989 // Check if object is a JSValue. | 8973 // Check if object is a JSValue. |
| 8990 set_current_block(if_heap_object); | 8974 set_current_block(if_heap_object); |
| 8991 HHasInstanceTypeAndBranch* typecheck = | 8975 HHasInstanceTypeAndBranch* typecheck = |
| 8992 New<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE); | 8976 New<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE); |
| 8993 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); | 8977 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); |
| 8994 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); | 8978 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); |
| 8995 typecheck->SetSuccessorAt(0, if_js_value); | 8979 typecheck->SetSuccessorAt(0, if_js_value); |
| 8996 typecheck->SetSuccessorAt(1, not_js_value); | 8980 typecheck->SetSuccessorAt(1, not_js_value); |
| 8997 current_block()->Finish(typecheck); | 8981 FinishCurrentBlock(typecheck); |
| 8998 not_js_value->Goto(join); | 8982 Goto(not_js_value, join); |
| 8999 | 8983 |
| 9000 // Create in-object property store to kValueOffset. | 8984 // Create in-object property store to kValueOffset. |
| 9001 set_current_block(if_js_value); | 8985 set_current_block(if_js_value); |
| 9002 Add<HStoreNamedField>(object, | 8986 Add<HStoreNamedField>(object, |
| 9003 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); | 8987 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); |
| 9004 if_js_value->Goto(join); | 8988 Goto(if_js_value, join); |
| 9005 join->SetJoinId(call->id()); | 8989 join->SetJoinId(call->id()); |
| 9006 set_current_block(join); | 8990 set_current_block(join); |
| 9007 return ast_context()->ReturnValue(value); | 8991 return ast_context()->ReturnValue(value); |
| 9008 } | 8992 } |
| 9009 | 8993 |
| 9010 | 8994 |
| 9011 // Fast support for charCodeAt(n). | 8995 // Fast support for charCodeAt(n). |
| 9012 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 8996 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
| 9013 ASSERT(call->arguments()->length() == 2); | 8997 ASSERT(call->arguments()->length() == 2); |
| 9014 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8998 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9153 HValue* function = Pop(); | 9137 HValue* function = Pop(); |
| 9154 | 9138 |
| 9155 // Branch for function proxies, or other non-functions. | 9139 // Branch for function proxies, or other non-functions. |
| 9156 HHasInstanceTypeAndBranch* typecheck = | 9140 HHasInstanceTypeAndBranch* typecheck = |
| 9157 New<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE); | 9141 New<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE); |
| 9158 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); | 9142 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); |
| 9159 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); | 9143 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); |
| 9160 HBasicBlock* join = graph()->CreateBasicBlock(); | 9144 HBasicBlock* join = graph()->CreateBasicBlock(); |
| 9161 typecheck->SetSuccessorAt(0, if_jsfunction); | 9145 typecheck->SetSuccessorAt(0, if_jsfunction); |
| 9162 typecheck->SetSuccessorAt(1, if_nonfunction); | 9146 typecheck->SetSuccessorAt(1, if_nonfunction); |
| 9163 current_block()->Finish(typecheck); | 9147 FinishCurrentBlock(typecheck); |
| 9164 | 9148 |
| 9165 set_current_block(if_jsfunction); | 9149 set_current_block(if_jsfunction); |
| 9166 HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count); | 9150 HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count); |
| 9167 Drop(arg_count); | 9151 Drop(arg_count); |
| 9168 Push(invoke_result); | 9152 Push(invoke_result); |
| 9169 if_jsfunction->Goto(join); | 9153 Goto(if_jsfunction, join); |
| 9170 | 9154 |
| 9171 set_current_block(if_nonfunction); | 9155 set_current_block(if_nonfunction); |
| 9172 HInstruction* call_result = Add<HCallFunction>(function, arg_count); | 9156 HInstruction* call_result = Add<HCallFunction>(function, arg_count); |
| 9173 Drop(arg_count); | 9157 Drop(arg_count); |
| 9174 Push(call_result); | 9158 Push(call_result); |
| 9175 if_nonfunction->Goto(join); | 9159 Goto(if_nonfunction, join); |
| 9176 | 9160 |
| 9177 set_current_block(join); | 9161 set_current_block(join); |
| 9178 join->SetJoinId(call->id()); | 9162 join->SetJoinId(call->id()); |
| 9179 return ast_context()->ReturnValue(Pop()); | 9163 return ast_context()->ReturnValue(Pop()); |
| 9180 } | 9164 } |
| 9181 | 9165 |
| 9182 | 9166 |
| 9183 // Fast call to math functions. | 9167 // Fast call to math functions. |
| 9184 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { | 9168 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { |
| 9185 ASSERT_EQ(2, call->arguments()->length()); | 9169 ASSERT_EQ(2, call->arguments()->length()); |
| (...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9885 if (ShouldProduceTraceOutput()) { | 9869 if (ShouldProduceTraceOutput()) { |
| 9886 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9870 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9887 } | 9871 } |
| 9888 | 9872 |
| 9889 #ifdef DEBUG | 9873 #ifdef DEBUG |
| 9890 graph_->Verify(false); // No full verify. | 9874 graph_->Verify(false); // No full verify. |
| 9891 #endif | 9875 #endif |
| 9892 } | 9876 } |
| 9893 | 9877 |
| 9894 } } // namespace v8::internal | 9878 } } // namespace v8::internal |
| OLD | NEW |