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