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