| OLD | NEW |
| 1 // Copyright 2012 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
| 15 // | 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 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 #include "hydrogen-gvn.h" | |
| 30 | 29 |
| 31 #include <algorithm> | 30 #include <algorithm> |
| 32 | 31 |
| 33 #include "v8.h" | 32 #include "v8.h" |
| 34 #include "codegen.h" | 33 #include "codegen.h" |
| 35 #include "full-codegen.h" | 34 #include "full-codegen.h" |
| 36 #include "hashmap.h" | 35 #include "hashmap.h" |
| 36 #include "hydrogen-bce.h" |
| 37 #include "hydrogen-dce.h" |
| 37 #include "hydrogen-environment-liveness.h" | 38 #include "hydrogen-environment-liveness.h" |
| 39 #include "hydrogen-escape-analysis.h" |
| 40 #include "hydrogen-infer-representation.h" |
| 41 #include "hydrogen-infer-types.h" |
| 42 #include "hydrogen-gvn.h" |
| 43 #include "hydrogen-osr.h" |
| 44 #include "hydrogen-range-analysis.h" |
| 45 #include "hydrogen-redundant-phi.h" |
| 46 #include "hydrogen-representation-changes.h" |
| 47 #include "hydrogen-sce.h" |
| 48 #include "hydrogen-uint32-analysis.h" |
| 38 #include "lithium-allocator.h" | 49 #include "lithium-allocator.h" |
| 39 #include "parser.h" | 50 #include "parser.h" |
| 40 #include "scopeinfo.h" | 51 #include "scopeinfo.h" |
| 41 #include "scopes.h" | 52 #include "scopes.h" |
| 42 #include "stub-cache.h" | 53 #include "stub-cache.h" |
| 43 #include "typing.h" | 54 #include "typing.h" |
| 44 | 55 |
| 45 #if V8_TARGET_ARCH_IA32 | 56 #if V8_TARGET_ARCH_IA32 |
| 46 #include "ia32/lithium-codegen-ia32.h" | 57 #include "ia32/lithium-codegen-ia32.h" |
| 47 #elif V8_TARGET_ARCH_X64 | 58 #elif V8_TARGET_ARCH_X64 |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 } | 532 } |
| 522 | 533 |
| 523 int visited_count_; | 534 int visited_count_; |
| 524 ZoneList<HBasicBlock*> stack_; | 535 ZoneList<HBasicBlock*> stack_; |
| 525 BitVector reachable_; | 536 BitVector reachable_; |
| 526 HBasicBlock* dont_visit_; | 537 HBasicBlock* dont_visit_; |
| 527 }; | 538 }; |
| 528 | 539 |
| 529 | 540 |
| 530 void HGraph::Verify(bool do_full_verify) const { | 541 void HGraph::Verify(bool do_full_verify) const { |
| 531 Heap::RelocationLock(isolate()->heap()); | 542 Heap::RelocationLock relocation_lock(isolate()->heap()); |
| 532 AllowHandleDereference allow_deref; | 543 AllowHandleDereference allow_deref; |
| 533 AllowDeferredHandleDereference allow_deferred_deref; | 544 AllowDeferredHandleDereference allow_deferred_deref; |
| 534 for (int i = 0; i < blocks_.length(); i++) { | 545 for (int i = 0; i < blocks_.length(); i++) { |
| 535 HBasicBlock* block = blocks_.at(i); | 546 HBasicBlock* block = blocks_.at(i); |
| 536 | 547 |
| 537 block->Verify(); | 548 block->Verify(); |
| 538 | 549 |
| 539 // Check that every block contains at least one node and that only the last | 550 // Check that every block contains at least one node and that only the last |
| 540 // node is a control instruction. | 551 // node is a control instruction. |
| 541 HInstruction* current = block->first(); | 552 HInstruction* current = block->first(); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 639 #define DEFINE_GET_CONSTANT(Name, name, htype, boolean_value) \ | 650 #define DEFINE_GET_CONSTANT(Name, name, htype, boolean_value) \ |
| 640 HConstant* HGraph::GetConstant##Name() { \ | 651 HConstant* HGraph::GetConstant##Name() { \ |
| 641 if (!constant_##name##_.is_set()) { \ | 652 if (!constant_##name##_.is_set()) { \ |
| 642 HConstant* constant = new(zone()) HConstant( \ | 653 HConstant* constant = new(zone()) HConstant( \ |
| 643 isolate()->factory()->name##_value(), \ | 654 isolate()->factory()->name##_value(), \ |
| 644 UniqueValueId(isolate()->heap()->name##_value()), \ | 655 UniqueValueId(isolate()->heap()->name##_value()), \ |
| 645 Representation::Tagged(), \ | 656 Representation::Tagged(), \ |
| 646 htype, \ | 657 htype, \ |
| 647 false, \ | 658 false, \ |
| 648 true, \ | 659 true, \ |
| 660 false, \ |
| 649 boolean_value); \ | 661 boolean_value); \ |
| 650 constant->InsertAfter(GetConstantUndefined()); \ | 662 constant->InsertAfter(GetConstantUndefined()); \ |
| 651 constant_##name##_.set(constant); \ | 663 constant_##name##_.set(constant); \ |
| 652 } \ | 664 } \ |
| 653 return constant_##name##_.get(); \ | 665 return constant_##name##_.get(); \ |
| 654 } | 666 } |
| 655 | 667 |
| 656 | 668 |
| 657 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) | 669 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) |
| 658 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) | 670 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) |
| 659 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) | 671 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) |
| 660 DEFINE_GET_CONSTANT(Null, null, HType::Tagged(), false) | 672 DEFINE_GET_CONSTANT(Null, null, HType::Tagged(), false) |
| 661 | 673 |
| 662 | 674 |
| 663 #undef DEFINE_GET_CONSTANT | 675 #undef DEFINE_GET_CONSTANT |
| 664 | 676 |
| 665 | 677 |
| 666 HConstant* HGraph::GetInvalidContext() { | 678 HConstant* HGraph::GetInvalidContext() { |
| 667 return GetConstant(&constant_invalid_context_, 0xFFFFC0C7); | 679 return GetConstant(&constant_invalid_context_, 0xFFFFC0C7); |
| 668 } | 680 } |
| 669 | 681 |
| 670 | 682 |
| 683 bool HGraph::IsStandardConstant(HConstant* constant) { |
| 684 if (constant == GetConstantUndefined()) return true; |
| 685 if (constant == GetConstant0()) return true; |
| 686 if (constant == GetConstant1()) return true; |
| 687 if (constant == GetConstantMinus1()) return true; |
| 688 if (constant == GetConstantTrue()) return true; |
| 689 if (constant == GetConstantFalse()) return true; |
| 690 if (constant == GetConstantHole()) return true; |
| 691 if (constant == GetConstantNull()) return true; |
| 692 return false; |
| 693 } |
| 694 |
| 695 |
| 671 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) | 696 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) |
| 672 : builder_(builder), | 697 : builder_(builder), |
| 673 position_(position), | 698 position_(position), |
| 674 finished_(false), | 699 finished_(false), |
| 675 did_then_(false), | 700 did_then_(false), |
| 676 did_else_(false), | 701 did_else_(false), |
| 677 did_and_(false), | 702 did_and_(false), |
| 678 did_or_(false), | 703 did_or_(false), |
| 679 captured_(false), | 704 captured_(false), |
| 680 needs_compare_(true), | 705 needs_compare_(true), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 701 first_true_block_(NULL), | 726 first_true_block_(NULL), |
| 702 first_false_block_(NULL), | 727 first_false_block_(NULL), |
| 703 split_edge_merge_block_(NULL), | 728 split_edge_merge_block_(NULL), |
| 704 merge_block_(NULL) { | 729 merge_block_(NULL) { |
| 705 continuation->Continue(&first_true_block_, | 730 continuation->Continue(&first_true_block_, |
| 706 &first_false_block_, | 731 &first_false_block_, |
| 707 &position_); | 732 &position_); |
| 708 } | 733 } |
| 709 | 734 |
| 710 | 735 |
| 711 HInstruction* HGraphBuilder::IfBuilder::IfCompare( | |
| 712 HValue* left, | |
| 713 HValue* right, | |
| 714 Token::Value token) { | |
| 715 HCompareIDAndBranch* compare = | |
| 716 new(zone()) HCompareIDAndBranch(left, right, token); | |
| 717 AddCompare(compare); | |
| 718 return compare; | |
| 719 } | |
| 720 | |
| 721 | |
| 722 HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left, | |
| 723 Handle<Map> map) { | |
| 724 HCompareMap* compare = | |
| 725 new(zone()) HCompareMap(left, map, first_true_block_, first_false_block_); | |
| 726 AddCompare(compare); | |
| 727 return compare; | |
| 728 } | |
| 729 | |
| 730 | |
| 731 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { | 736 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { |
| 732 if (split_edge_merge_block_ != NULL) { | 737 if (split_edge_merge_block_ != NULL) { |
| 733 HEnvironment* env = first_false_block_->last_environment(); | 738 HEnvironment* env = first_false_block_->last_environment(); |
| 734 HBasicBlock* split_edge = | 739 HBasicBlock* split_edge = |
| 735 builder_->CreateBasicBlock(env->Copy()); | 740 builder_->CreateBasicBlock(env->Copy()); |
| 736 if (did_or_) { | 741 if (did_or_) { |
| 737 compare->SetSuccessorAt(0, split_edge); | 742 compare->SetSuccessorAt(0, split_edge); |
| 738 compare->SetSuccessorAt(1, first_false_block_); | 743 compare->SetSuccessorAt(1, first_false_block_); |
| 739 } else { | 744 } else { |
| 740 compare->SetSuccessorAt(0, first_true_block_); | 745 compare->SetSuccessorAt(0, first_true_block_); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 did_then_ = true; | 806 did_then_ = true; |
| 802 if (needs_compare_) { | 807 if (needs_compare_) { |
| 803 // Handle if's without any expressions, they jump directly to the "else" | 808 // Handle if's without any expressions, they jump directly to the "else" |
| 804 // branch. However, we must pretend that the "then" branch is reachable, | 809 // branch. However, we must pretend that the "then" branch is reachable, |
| 805 // so that the graph builder visits it and sees any live range extending | 810 // so that the graph builder visits it and sees any live range extending |
| 806 // constructs within it. | 811 // constructs within it. |
| 807 HConstant* constant_false = builder_->graph()->GetConstantFalse(); | 812 HConstant* constant_false = builder_->graph()->GetConstantFalse(); |
| 808 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); | 813 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); |
| 809 boolean_type.Add(ToBooleanStub::BOOLEAN); | 814 boolean_type.Add(ToBooleanStub::BOOLEAN); |
| 810 HBranch* branch = | 815 HBranch* branch = |
| 811 new(zone()) HBranch(constant_false, first_true_block_, | 816 new(zone()) HBranch(constant_false, boolean_type, first_true_block_, |
| 812 first_false_block_, boolean_type); | 817 first_false_block_); |
| 813 builder_->current_block()->Finish(branch); | 818 builder_->current_block()->Finish(branch); |
| 814 } | 819 } |
| 815 builder_->set_current_block(first_true_block_); | 820 builder_->set_current_block(first_true_block_); |
| 816 } | 821 } |
| 817 | 822 |
| 818 | 823 |
| 819 void HGraphBuilder::IfBuilder::Else() { | 824 void HGraphBuilder::IfBuilder::Else() { |
| 820 ASSERT(did_then_); | 825 ASSERT(did_then_); |
| 821 ASSERT(!captured_); | 826 ASSERT(!captured_); |
| 822 ASSERT(!finished_); | 827 ASSERT(!finished_); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 builder_->current_block()->GotoNoSimulate(header_block_); | 911 builder_->current_block()->GotoNoSimulate(header_block_); |
| 907 | 912 |
| 908 HEnvironment* body_env = env->Copy(); | 913 HEnvironment* body_env = env->Copy(); |
| 909 HEnvironment* exit_env = env->Copy(); | 914 HEnvironment* exit_env = env->Copy(); |
| 910 body_block_ = builder_->CreateBasicBlock(body_env); | 915 body_block_ = builder_->CreateBasicBlock(body_env); |
| 911 exit_block_ = builder_->CreateBasicBlock(exit_env); | 916 exit_block_ = builder_->CreateBasicBlock(exit_env); |
| 912 // Remove the phi from the expression stack | 917 // Remove the phi from the expression stack |
| 913 body_env->Pop(); | 918 body_env->Pop(); |
| 914 | 919 |
| 915 builder_->set_current_block(header_block_); | 920 builder_->set_current_block(header_block_); |
| 916 HCompareIDAndBranch* compare = | 921 HCompareNumericAndBranch* compare = |
| 917 new(zone()) HCompareIDAndBranch(phi_, terminating, token); | 922 new(zone()) HCompareNumericAndBranch(phi_, terminating, token); |
| 918 compare->SetSuccessorAt(0, body_block_); | 923 compare->SetSuccessorAt(0, body_block_); |
| 919 compare->SetSuccessorAt(1, exit_block_); | 924 compare->SetSuccessorAt(1, exit_block_); |
| 920 builder_->current_block()->Finish(compare); | 925 builder_->current_block()->Finish(compare); |
| 921 | 926 |
| 922 builder_->set_current_block(body_block_); | 927 builder_->set_current_block(body_block_); |
| 923 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { | 928 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { |
| 924 HValue* one = builder_->graph()->GetConstant1(); | 929 HValue* one = builder_->graph()->GetConstant1(); |
| 925 if (direction_ == kPreIncrement) { | 930 if (direction_ == kPreIncrement) { |
| 926 increment_ = HAdd::New(zone(), context_, phi_, one); | 931 increment_ = HAdd::New(zone(), context_, phi_, one); |
| 927 } else { | 932 } else { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 984 | 989 |
| 985 | 990 |
| 986 void HGraphBuilder::AddSimulate(BailoutId id, | 991 void HGraphBuilder::AddSimulate(BailoutId id, |
| 987 RemovableSimulate removable) { | 992 RemovableSimulate removable) { |
| 988 ASSERT(current_block() != NULL); | 993 ASSERT(current_block() != NULL); |
| 989 ASSERT(no_side_effects_scope_count_ == 0); | 994 ASSERT(no_side_effects_scope_count_ == 0); |
| 990 current_block()->AddSimulate(id, removable); | 995 current_block()->AddSimulate(id, removable); |
| 991 } | 996 } |
| 992 | 997 |
| 993 | 998 |
| 994 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, HValue* length) { | |
| 995 HBoundsCheck* result = new(graph()->zone()) HBoundsCheck(index, length); | |
| 996 AddInstruction(result); | |
| 997 return result; | |
| 998 } | |
| 999 | |
| 1000 | |
| 1001 HReturn* HGraphBuilder::AddReturn(HValue* value) { | 999 HReturn* HGraphBuilder::AddReturn(HValue* value) { |
| 1002 HValue* context = environment()->LookupContext(); | 1000 HValue* context = environment()->LookupContext(); |
| 1003 int num_parameters = graph()->info()->num_parameters(); | 1001 int num_parameters = graph()->info()->num_parameters(); |
| 1004 HValue* params = AddInstruction(new(graph()->zone()) | 1002 HValue* params = Add<HConstant>(num_parameters); |
| 1005 HConstant(num_parameters)); | |
| 1006 HReturn* return_instruction = new(graph()->zone()) | 1003 HReturn* return_instruction = new(graph()->zone()) |
| 1007 HReturn(value, context, params); | 1004 HReturn(value, context, params); |
| 1008 current_block()->FinishExit(return_instruction); | 1005 current_block()->FinishExit(return_instruction); |
| 1009 return return_instruction; | 1006 return return_instruction; |
| 1010 } | 1007 } |
| 1011 | 1008 |
| 1012 | 1009 |
| 1010 void HGraphBuilder::AddSoftDeoptimize(SoftDeoptimizeMode mode) { |
| 1011 isolate()->counters()->soft_deopts_requested()->Increment(); |
| 1012 if (FLAG_always_opt && mode == CAN_OMIT_SOFT_DEOPT) return; |
| 1013 if (current_block()->IsDeoptimizing()) return; |
| 1014 Add<HSoftDeoptimize>(); |
| 1015 isolate()->counters()->soft_deopts_inserted()->Increment(); |
| 1016 current_block()->MarkAsDeoptimizing(); |
| 1017 graph()->set_has_soft_deoptimize(true); |
| 1018 } |
| 1019 |
| 1020 |
| 1013 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 1021 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
| 1014 HBasicBlock* b = graph()->CreateBasicBlock(); | 1022 HBasicBlock* b = graph()->CreateBasicBlock(); |
| 1015 b->SetInitialEnvironment(env); | 1023 b->SetInitialEnvironment(env); |
| 1016 return b; | 1024 return b; |
| 1017 } | 1025 } |
| 1018 | 1026 |
| 1019 | 1027 |
| 1020 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 1028 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
| 1021 HBasicBlock* header = graph()->CreateBasicBlock(); | 1029 HBasicBlock* header = graph()->CreateBasicBlock(); |
| 1022 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 1030 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
| 1023 header->SetInitialEnvironment(entry_env); | 1031 header->SetInitialEnvironment(entry_env); |
| 1024 header->AttachLoopInformation(); | 1032 header->AttachLoopInformation(); |
| 1025 return header; | 1033 return header; |
| 1026 } | 1034 } |
| 1027 | 1035 |
| 1028 | 1036 |
| 1029 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { | 1037 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { |
| 1030 if (obj->type().IsHeapObject()) return obj; | 1038 if (obj->type().IsHeapObject()) return obj; |
| 1031 HCheckHeapObject* check = new(zone()) HCheckHeapObject(obj); | 1039 return Add<HCheckHeapObject>(obj); |
| 1032 AddInstruction(check); | |
| 1033 return check; | |
| 1034 } | 1040 } |
| 1035 | 1041 |
| 1036 | 1042 |
| 1037 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, | 1043 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, |
| 1038 Handle<Map> map) { | 1044 Handle<Map> map) { |
| 1039 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); | 1045 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); |
| 1040 AddInstruction(check); | 1046 AddInstruction(check); |
| 1041 return check; | 1047 return check; |
| 1042 } | 1048 } |
| 1043 | 1049 |
| 1044 | 1050 |
| 1045 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( | 1051 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( |
| 1046 HValue* external_elements, | 1052 HValue* external_elements, |
| 1047 HValue* checked_key, | 1053 HValue* checked_key, |
| 1048 HValue* val, | 1054 HValue* val, |
| 1049 HValue* dependency, | 1055 HValue* dependency, |
| 1050 ElementsKind elements_kind, | 1056 ElementsKind elements_kind, |
| 1051 bool is_store) { | 1057 bool is_store) { |
| 1052 Zone* zone = this->zone(); | 1058 Zone* zone = this->zone(); |
| 1053 if (is_store) { | 1059 if (is_store) { |
| 1054 ASSERT(val != NULL); | 1060 ASSERT(val != NULL); |
| 1055 switch (elements_kind) { | 1061 switch (elements_kind) { |
| 1056 case EXTERNAL_PIXEL_ELEMENTS: { | 1062 case EXTERNAL_PIXEL_ELEMENTS: { |
| 1057 val = AddInstruction(new(zone) HClampToUint8(val)); | 1063 val = Add<HClampToUint8>(val); |
| 1058 break; | 1064 break; |
| 1059 } | 1065 } |
| 1060 case EXTERNAL_BYTE_ELEMENTS: | 1066 case EXTERNAL_BYTE_ELEMENTS: |
| 1061 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 1067 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 1062 case EXTERNAL_SHORT_ELEMENTS: | 1068 case EXTERNAL_SHORT_ELEMENTS: |
| 1063 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 1069 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 1064 case EXTERNAL_INT_ELEMENTS: | 1070 case EXTERNAL_INT_ELEMENTS: |
| 1065 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | 1071 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 1066 break; | 1072 break; |
| 1067 } | 1073 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1131 | 1137 |
| 1132 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, | 1138 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, |
| 1133 HValue* elements, | 1139 HValue* elements, |
| 1134 ElementsKind kind, | 1140 ElementsKind kind, |
| 1135 HValue* length, | 1141 HValue* length, |
| 1136 HValue* key, | 1142 HValue* key, |
| 1137 bool is_js_array) { | 1143 bool is_js_array) { |
| 1138 Zone* zone = this->zone(); | 1144 Zone* zone = this->zone(); |
| 1139 IfBuilder length_checker(this); | 1145 IfBuilder length_checker(this); |
| 1140 | 1146 |
| 1141 length_checker.IfCompare(length, key, Token::EQ); | 1147 length_checker.If<HCompareNumericAndBranch>(length, key, Token::EQ); |
| 1142 length_checker.Then(); | 1148 length_checker.Then(); |
| 1143 | 1149 |
| 1144 HValue* current_capacity = | 1150 HValue* current_capacity = AddLoadFixedArrayLength(elements); |
| 1145 AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | |
| 1146 | 1151 |
| 1147 IfBuilder capacity_checker(this); | 1152 IfBuilder capacity_checker(this); |
| 1148 | 1153 |
| 1149 capacity_checker.IfCompare(length, current_capacity, Token::EQ); | 1154 capacity_checker.If<HCompareNumericAndBranch>(length, current_capacity, |
| 1155 Token::EQ); |
| 1150 capacity_checker.Then(); | 1156 capacity_checker.Then(); |
| 1151 | 1157 |
| 1152 HValue* context = environment()->LookupContext(); | 1158 HValue* context = environment()->LookupContext(); |
| 1153 | 1159 |
| 1154 HValue* new_capacity = | 1160 HValue* new_capacity = |
| 1155 BuildNewElementsCapacity(context, current_capacity); | 1161 BuildNewElementsCapacity(context, current_capacity); |
| 1156 | 1162 |
| 1157 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | 1163 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
| 1158 kind, length, | 1164 kind, length, |
| 1159 new_capacity); | 1165 new_capacity); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1170 new_length->ClearFlag(HValue::kCanOverflow); | 1176 new_length->ClearFlag(HValue::kCanOverflow); |
| 1171 | 1177 |
| 1172 Representation representation = IsFastElementsKind(kind) | 1178 Representation representation = IsFastElementsKind(kind) |
| 1173 ? Representation::Smi() : Representation::Tagged(); | 1179 ? Representation::Smi() : Representation::Tagged(); |
| 1174 AddStore(object, HObjectAccess::ForArrayLength(), new_length, | 1180 AddStore(object, HObjectAccess::ForArrayLength(), new_length, |
| 1175 representation); | 1181 representation); |
| 1176 } | 1182 } |
| 1177 | 1183 |
| 1178 length_checker.Else(); | 1184 length_checker.Else(); |
| 1179 | 1185 |
| 1180 AddBoundsCheck(key, length); | 1186 Add<HBoundsCheck>(key, length); |
| 1181 environment()->Push(elements); | 1187 environment()->Push(elements); |
| 1182 | 1188 |
| 1183 length_checker.End(); | 1189 length_checker.End(); |
| 1184 | 1190 |
| 1185 return environment()->Pop(); | 1191 return environment()->Pop(); |
| 1186 } | 1192 } |
| 1187 | 1193 |
| 1188 | 1194 |
| 1189 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, | 1195 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, |
| 1190 HValue* elements, | 1196 HValue* elements, |
| 1191 ElementsKind kind, | 1197 ElementsKind kind, |
| 1192 HValue* length) { | 1198 HValue* length) { |
| 1193 Zone* zone = this->zone(); | 1199 Factory* factory = isolate()->factory(); |
| 1194 Heap* heap = isolate()->heap(); | |
| 1195 | 1200 |
| 1196 IfBuilder cow_checker(this); | 1201 IfBuilder cow_checker(this); |
| 1197 | 1202 |
| 1198 cow_checker.IfCompareMap(elements, | 1203 cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map()); |
| 1199 Handle<Map>(heap->fixed_cow_array_map())); | |
| 1200 cow_checker.Then(); | 1204 cow_checker.Then(); |
| 1201 | 1205 |
| 1202 HValue* capacity = | 1206 HValue* capacity = AddLoadFixedArrayLength(elements); |
| 1203 AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | |
| 1204 | 1207 |
| 1205 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | 1208 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
| 1206 kind, length, capacity); | 1209 kind, length, capacity); |
| 1207 | 1210 |
| 1208 environment()->Push(new_elements); | 1211 environment()->Push(new_elements); |
| 1209 | 1212 |
| 1210 cow_checker.Else(); | 1213 cow_checker.Else(); |
| 1211 | 1214 |
| 1212 environment()->Push(elements); | 1215 environment()->Push(elements); |
| 1213 | 1216 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1248 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1251 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
| 1249 HCheckMaps* check_cow_map = HCheckMaps::New( | 1252 HCheckMaps* check_cow_map = HCheckMaps::New( |
| 1250 elements, isolate()->factory()->fixed_array_map(), zone); | 1253 elements, isolate()->factory()->fixed_array_map(), zone); |
| 1251 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1254 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 1252 AddInstruction(check_cow_map); | 1255 AddInstruction(check_cow_map); |
| 1253 } | 1256 } |
| 1254 HInstruction* length = NULL; | 1257 HInstruction* length = NULL; |
| 1255 if (is_js_array) { | 1258 if (is_js_array) { |
| 1256 length = AddLoad(object, HObjectAccess::ForArrayLength(), mapcheck, | 1259 length = AddLoad(object, HObjectAccess::ForArrayLength(), mapcheck, |
| 1257 Representation::Smi()); | 1260 Representation::Smi()); |
| 1258 length->set_type(HType::Smi()); | |
| 1259 } else { | 1261 } else { |
| 1260 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | 1262 length = AddLoadFixedArrayLength(elements); |
| 1261 } | 1263 } |
| 1264 length->set_type(HType::Smi()); |
| 1262 HValue* checked_key = NULL; | 1265 HValue* checked_key = NULL; |
| 1263 if (IsExternalArrayElementsKind(elements_kind)) { | 1266 if (IsExternalArrayElementsKind(elements_kind)) { |
| 1264 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1267 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
| 1265 NoObservableSideEffectsScope no_effects(this); | 1268 NoObservableSideEffectsScope no_effects(this); |
| 1266 HLoadExternalArrayPointer* external_elements = | 1269 HLoadExternalArrayPointer* external_elements = |
| 1267 new(zone) HLoadExternalArrayPointer(elements); | 1270 Add<HLoadExternalArrayPointer>(elements); |
| 1268 AddInstruction(external_elements); | |
| 1269 IfBuilder length_checker(this); | 1271 IfBuilder length_checker(this); |
| 1270 length_checker.IfCompare(key, length, Token::LT); | 1272 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
| 1271 length_checker.Then(); | 1273 length_checker.Then(); |
| 1272 IfBuilder negative_checker(this); | 1274 IfBuilder negative_checker(this); |
| 1273 HValue* bounds_check = negative_checker.IfCompare( | 1275 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
| 1274 key, graph()->GetConstant0(), Token::GTE); | 1276 key, graph()->GetConstant0(), Token::GTE); |
| 1275 negative_checker.Then(); | 1277 negative_checker.Then(); |
| 1276 HInstruction* result = BuildExternalArrayElementAccess( | 1278 HInstruction* result = BuildExternalArrayElementAccess( |
| 1277 external_elements, key, val, bounds_check, | 1279 external_elements, key, val, bounds_check, |
| 1278 elements_kind, is_store); | 1280 elements_kind, is_store); |
| 1279 AddInstruction(result); | 1281 AddInstruction(result); |
| 1280 negative_checker.ElseDeopt(); | 1282 negative_checker.ElseDeopt(); |
| 1281 length_checker.End(); | 1283 length_checker.End(); |
| 1282 return result; | 1284 return result; |
| 1283 } else { | 1285 } else { |
| 1284 ASSERT(store_mode == STANDARD_STORE); | 1286 ASSERT(store_mode == STANDARD_STORE); |
| 1285 checked_key = AddBoundsCheck(key, length); | 1287 checked_key = Add<HBoundsCheck>(key, length); |
| 1286 HLoadExternalArrayPointer* external_elements = | 1288 HLoadExternalArrayPointer* external_elements = |
| 1287 new(zone) HLoadExternalArrayPointer(elements); | 1289 Add<HLoadExternalArrayPointer>(elements); |
| 1288 AddInstruction(external_elements); | |
| 1289 return AddInstruction(BuildExternalArrayElementAccess( | 1290 return AddInstruction(BuildExternalArrayElementAccess( |
| 1290 external_elements, checked_key, val, mapcheck, | 1291 external_elements, checked_key, val, mapcheck, |
| 1291 elements_kind, is_store)); | 1292 elements_kind, is_store)); |
| 1292 } | 1293 } |
| 1293 } | 1294 } |
| 1294 ASSERT(fast_smi_only_elements || | 1295 ASSERT(fast_smi_only_elements || |
| 1295 fast_elements || | 1296 fast_elements || |
| 1296 IsFastDoubleElementsKind(elements_kind)); | 1297 IsFastDoubleElementsKind(elements_kind)); |
| 1297 | 1298 |
| 1298 // In case val is stored into a fast smi array, assure that the value is a smi | 1299 // In case val is stored into a fast smi array, assure that the value is a smi |
| 1299 // before manipulating the backing store. Otherwise the actual store may | 1300 // before manipulating the backing store. Otherwise the actual store may |
| 1300 // deopt, leaving the backing store in an invalid state. | 1301 // deopt, leaving the backing store in an invalid state. |
| 1301 if (is_store && IsFastSmiElementsKind(elements_kind) && | 1302 if (is_store && IsFastSmiElementsKind(elements_kind) && |
| 1302 !val->type().IsSmi()) { | 1303 !val->type().IsSmi()) { |
| 1303 val = AddInstruction(new(zone) HForceRepresentation( | 1304 val = Add<HForceRepresentation>(val, Representation::Smi()); |
| 1304 val, Representation::Smi())); | |
| 1305 } | 1305 } |
| 1306 | 1306 |
| 1307 if (IsGrowStoreMode(store_mode)) { | 1307 if (IsGrowStoreMode(store_mode)) { |
| 1308 NoObservableSideEffectsScope no_effects(this); | 1308 NoObservableSideEffectsScope no_effects(this); |
| 1309 elements = BuildCheckForCapacityGrow(object, elements, elements_kind, | 1309 elements = BuildCheckForCapacityGrow(object, elements, elements_kind, |
| 1310 length, key, is_js_array); | 1310 length, key, is_js_array); |
| 1311 checked_key = key; | 1311 checked_key = key; |
| 1312 } else { | 1312 } else { |
| 1313 checked_key = AddBoundsCheck(key, length); | 1313 checked_key = Add<HBoundsCheck>(key, length); |
| 1314 | 1314 |
| 1315 if (is_store && (fast_elements || fast_smi_only_elements)) { | 1315 if (is_store && (fast_elements || fast_smi_only_elements)) { |
| 1316 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | 1316 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { |
| 1317 NoObservableSideEffectsScope no_effects(this); | 1317 NoObservableSideEffectsScope no_effects(this); |
| 1318 | 1318 |
| 1319 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, | 1319 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, |
| 1320 length); | 1320 length); |
| 1321 } else { | 1321 } else { |
| 1322 HCheckMaps* check_cow_map = HCheckMaps::New( | 1322 HCheckMaps* check_cow_map = HCheckMaps::New( |
| 1323 elements, isolate()->factory()->fixed_array_map(), zone); | 1323 elements, isolate()->factory()->fixed_array_map(), zone); |
| 1324 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1324 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 1325 AddInstruction(check_cow_map); | 1325 AddInstruction(check_cow_map); |
| 1326 } | 1326 } |
| 1327 } | 1327 } |
| 1328 } | 1328 } |
| 1329 return AddInstruction( | 1329 return AddInstruction( |
| 1330 BuildFastElementAccess(elements, checked_key, val, mapcheck, | 1330 BuildFastElementAccess(elements, checked_key, val, mapcheck, |
| 1331 elements_kind, is_store, load_mode, store_mode)); | 1331 elements_kind, is_store, load_mode, store_mode)); |
| 1332 } | 1332 } |
| 1333 | 1333 |
| 1334 | 1334 |
| 1335 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, | 1335 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, |
| 1336 ElementsKind kind, | 1336 ElementsKind kind, |
| 1337 HValue* capacity) { | 1337 HValue* capacity) { |
| 1338 Zone* zone = this->zone(); | 1338 Zone* zone = this->zone(); |
| 1339 | 1339 |
| 1340 int elements_size = IsFastDoubleElementsKind(kind) | 1340 int elements_size = IsFastDoubleElementsKind(kind) |
| 1341 ? kDoubleSize : kPointerSize; | 1341 ? kDoubleSize : kPointerSize; |
| 1342 HConstant* elements_size_value = new(zone) HConstant(elements_size); | 1342 HConstant* elements_size_value = Add<HConstant>(elements_size); |
| 1343 AddInstruction(elements_size_value); | |
| 1344 HValue* mul = AddInstruction( | 1343 HValue* mul = AddInstruction( |
| 1345 HMul::New(zone, context, capacity, elements_size_value)); | 1344 HMul::New(zone, context, capacity, elements_size_value)); |
| 1346 mul->ClearFlag(HValue::kCanOverflow); | 1345 mul->ClearFlag(HValue::kCanOverflow); |
| 1347 | 1346 |
| 1348 HConstant* header_size = new(zone) HConstant(FixedArray::kHeaderSize); | 1347 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); |
| 1349 AddInstruction(header_size); | |
| 1350 HValue* total_size = AddInstruction( | 1348 HValue* total_size = AddInstruction( |
| 1351 HAdd::New(zone, context, mul, header_size)); | 1349 HAdd::New(zone, context, mul, header_size)); |
| 1352 total_size->ClearFlag(HValue::kCanOverflow); | 1350 total_size->ClearFlag(HValue::kCanOverflow); |
| 1353 | 1351 |
| 1354 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); | 1352 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); |
| 1355 if (isolate()->heap()->ShouldGloballyPretenure()) { | 1353 if (isolate()->heap()->ShouldGloballyPretenure()) { |
| 1356 // TODO(hpayer): When pretenuring can be internalized, flags can become | 1354 // TODO(hpayer): When pretenuring can be internalized, flags can become |
| 1357 // private to HAllocate. | 1355 // private to HAllocate. |
| 1358 if (IsFastDoubleElementsKind(kind)) { | 1356 if (IsFastDoubleElementsKind(kind)) { |
| 1359 flags = static_cast<HAllocate::Flags>( | 1357 flags = static_cast<HAllocate::Flags>( |
| 1360 flags | HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); | 1358 flags | HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); |
| 1361 } else { | 1359 } else { |
| 1362 flags = static_cast<HAllocate::Flags>( | 1360 flags = static_cast<HAllocate::Flags>( |
| 1363 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | 1361 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); |
| 1364 } | 1362 } |
| 1365 } | 1363 } |
| 1366 | 1364 |
| 1367 HValue* elements = | 1365 return Add<HAllocate>(context, total_size, HType::JSArray(), flags); |
| 1368 AddInstruction(new(zone) HAllocate(context, total_size, | |
| 1369 HType::JSArray(), flags)); | |
| 1370 return elements; | |
| 1371 } | 1366 } |
| 1372 | 1367 |
| 1373 | 1368 |
| 1374 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, | 1369 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, |
| 1375 ElementsKind kind, | 1370 ElementsKind kind, |
| 1376 HValue* capacity) { | 1371 HValue* capacity) { |
| 1377 Factory* factory = isolate()->factory(); | 1372 Factory* factory = isolate()->factory(); |
| 1378 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1373 Handle<Map> map = IsFastDoubleElementsKind(kind) |
| 1379 ? factory->fixed_double_array_map() | 1374 ? factory->fixed_double_array_map() |
| 1380 : factory->fixed_array_map(); | 1375 : factory->fixed_array_map(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1399 | 1394 |
| 1400 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, | 1395 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, |
| 1401 HValue* array_map, | 1396 HValue* array_map, |
| 1402 AllocationSiteMode mode, | 1397 AllocationSiteMode mode, |
| 1403 HValue* allocation_site_payload, | 1398 HValue* allocation_site_payload, |
| 1404 HValue* length_field) { | 1399 HValue* length_field) { |
| 1405 | 1400 |
| 1406 AddStore(array, HObjectAccess::ForMap(), array_map); | 1401 AddStore(array, HObjectAccess::ForMap(), array_map); |
| 1407 | 1402 |
| 1408 HConstant* empty_fixed_array = | 1403 HConstant* empty_fixed_array = |
| 1409 new(zone()) HConstant(isolate()->factory()->empty_fixed_array()); | 1404 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
| 1410 AddInstruction(empty_fixed_array); | |
| 1411 | 1405 |
| 1412 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 1406 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 1413 AddStore(array, access, empty_fixed_array); | 1407 AddStore(array, access, empty_fixed_array); |
| 1414 AddStore(array, HObjectAccess::ForArrayLength(), length_field); | 1408 AddStore(array, HObjectAccess::ForArrayLength(), length_field); |
| 1415 | 1409 |
| 1416 if (mode == TRACK_ALLOCATION_SITE) { | 1410 if (mode == TRACK_ALLOCATION_SITE) { |
| 1417 BuildCreateAllocationSiteInfo(array, | 1411 BuildCreateAllocationSiteInfo(array, |
| 1418 JSArray::kSize, | 1412 JSArray::kSize, |
| 1419 allocation_site_payload); | 1413 allocation_site_payload); |
| 1420 } | 1414 } |
| 1421 | 1415 |
| 1422 int elements_location = JSArray::kSize; | 1416 int elements_location = JSArray::kSize; |
| 1423 if (mode == TRACK_ALLOCATION_SITE) { | 1417 if (mode == TRACK_ALLOCATION_SITE) { |
| 1424 elements_location += AllocationSiteInfo::kSize; | 1418 elements_location += AllocationSiteInfo::kSize; |
| 1425 } | 1419 } |
| 1426 | 1420 |
| 1427 HInnerAllocatedObject* elements = new(zone()) HInnerAllocatedObject( | 1421 HInnerAllocatedObject* elements = |
| 1428 array, elements_location); | 1422 Add<HInnerAllocatedObject>(array, elements_location); |
| 1429 AddInstruction(elements); | |
| 1430 | |
| 1431 AddStore(array, HObjectAccess::ForElementsPointer(), elements); | 1423 AddStore(array, HObjectAccess::ForElementsPointer(), elements); |
| 1432 return elements; | 1424 return elements; |
| 1433 } | 1425 } |
| 1434 | 1426 |
| 1435 | 1427 |
| 1436 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | 1428 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, |
| 1437 HValue* typecheck) { | 1429 HValue* typecheck) { |
| 1438 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); | 1430 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); |
| 1439 } | 1431 } |
| 1440 | 1432 |
| 1441 | 1433 |
| 1434 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
| 1435 HLoadNamedField* instr = AddLoad(object, HObjectAccess::ForFixedArrayLength(), |
| 1436 NULL, Representation::Smi()); |
| 1437 instr->set_type(HType::Smi()); |
| 1438 return instr; |
| 1439 } |
| 1440 |
| 1441 |
| 1442 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, | 1442 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, |
| 1443 HValue* old_capacity) { | 1443 HValue* old_capacity) { |
| 1444 Zone* zone = this->zone(); | 1444 Zone* zone = this->zone(); |
| 1445 HValue* half_old_capacity = | 1445 HValue* half_old_capacity = |
| 1446 AddInstruction(HShr::New(zone, context, old_capacity, | 1446 AddInstruction(HShr::New(zone, context, old_capacity, |
| 1447 graph_->GetConstant1())); | 1447 graph_->GetConstant1())); |
| 1448 half_old_capacity->ClearFlag(HValue::kCanOverflow); | 1448 half_old_capacity->ClearFlag(HValue::kCanOverflow); |
| 1449 | 1449 |
| 1450 HValue* new_capacity = AddInstruction( | 1450 HValue* new_capacity = AddInstruction( |
| 1451 HAdd::New(zone, context, half_old_capacity, old_capacity)); | 1451 HAdd::New(zone, context, half_old_capacity, old_capacity)); |
| 1452 new_capacity->ClearFlag(HValue::kCanOverflow); | 1452 new_capacity->ClearFlag(HValue::kCanOverflow); |
| 1453 | 1453 |
| 1454 HValue* min_growth = AddInstruction(new(zone) HConstant(16)); | 1454 HValue* min_growth = Add<HConstant>(16); |
| 1455 | 1455 |
| 1456 new_capacity = AddInstruction( | 1456 new_capacity = AddInstruction( |
| 1457 HAdd::New(zone, context, new_capacity, min_growth)); | 1457 HAdd::New(zone, context, new_capacity, min_growth)); |
| 1458 new_capacity->ClearFlag(HValue::kCanOverflow); | 1458 new_capacity->ClearFlag(HValue::kCanOverflow); |
| 1459 | 1459 |
| 1460 return new_capacity; | 1460 return new_capacity; |
| 1461 } | 1461 } |
| 1462 | 1462 |
| 1463 | 1463 |
| 1464 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { | 1464 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { |
| 1465 Zone* zone = this->zone(); | |
| 1466 Heap* heap = isolate()->heap(); | 1465 Heap* heap = isolate()->heap(); |
| 1467 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize | 1466 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize |
| 1468 : kPointerSize; | 1467 : kPointerSize; |
| 1469 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size; | 1468 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size; |
| 1470 max_size -= JSArray::kSize / element_size; | 1469 max_size -= JSArray::kSize / element_size; |
| 1471 HConstant* max_size_constant = new(zone) HConstant(max_size); | 1470 HConstant* max_size_constant = Add<HConstant>(max_size); |
| 1472 AddInstruction(max_size_constant); | |
| 1473 // Since we're forcing Integer32 representation for this HBoundsCheck, | 1471 // Since we're forcing Integer32 representation for this HBoundsCheck, |
| 1474 // there's no need to Smi-check the index. | 1472 // there's no need to Smi-check the index. |
| 1475 AddInstruction(new(zone) HBoundsCheck(length, max_size_constant)); | 1473 Add<HBoundsCheck>(length, max_size_constant); |
| 1476 } | 1474 } |
| 1477 | 1475 |
| 1478 | 1476 |
| 1479 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 1477 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
| 1480 HValue* elements, | 1478 HValue* elements, |
| 1481 ElementsKind kind, | 1479 ElementsKind kind, |
| 1482 HValue* length, | 1480 HValue* length, |
| 1483 HValue* new_capacity) { | 1481 HValue* new_capacity) { |
| 1484 HValue* context = environment()->LookupContext(); | 1482 HValue* context = environment()->LookupContext(); |
| 1485 | 1483 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1501 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, | 1499 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, |
| 1502 HValue* elements, | 1500 HValue* elements, |
| 1503 ElementsKind elements_kind, | 1501 ElementsKind elements_kind, |
| 1504 HValue* from, | 1502 HValue* from, |
| 1505 HValue* to) { | 1503 HValue* to) { |
| 1506 // Fast elements kinds need to be initialized in case statements below cause | 1504 // Fast elements kinds need to be initialized in case statements below cause |
| 1507 // a garbage collection. | 1505 // a garbage collection. |
| 1508 Factory* factory = isolate()->factory(); | 1506 Factory* factory = isolate()->factory(); |
| 1509 | 1507 |
| 1510 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 1508 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
| 1511 Zone* zone = this->zone(); | |
| 1512 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 1509 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
| 1513 ? AddInstruction(new(zone) HConstant(factory->the_hole_value())) | 1510 ? Add<HConstant>(factory->the_hole_value()) |
| 1514 : AddInstruction(new(zone) HConstant(nan_double)); | 1511 : Add<HConstant>(nan_double); |
| 1515 | 1512 |
| 1516 // Special loop unfolding case | 1513 // Special loop unfolding case |
| 1517 static const int kLoopUnfoldLimit = 4; | 1514 static const int kLoopUnfoldLimit = 4; |
| 1518 bool unfold_loop = false; | 1515 bool unfold_loop = false; |
| 1519 int initial_capacity = JSArray::kPreallocatedArrayElements; | 1516 int initial_capacity = JSArray::kPreallocatedArrayElements; |
| 1520 if (from->IsConstant() && to->IsConstant() && | 1517 if (from->IsConstant() && to->IsConstant() && |
| 1521 initial_capacity <= kLoopUnfoldLimit) { | 1518 initial_capacity <= kLoopUnfoldLimit) { |
| 1522 HConstant* constant_from = HConstant::cast(from); | 1519 HConstant* constant_from = HConstant::cast(from); |
| 1523 HConstant* constant_to = HConstant::cast(to); | 1520 HConstant* constant_to = HConstant::cast(to); |
| 1524 | 1521 |
| 1525 if (constant_from->HasInteger32Value() && | 1522 if (constant_from->HasInteger32Value() && |
| 1526 constant_from->Integer32Value() == 0 && | 1523 constant_from->Integer32Value() == 0 && |
| 1527 constant_to->HasInteger32Value() && | 1524 constant_to->HasInteger32Value() && |
| 1528 constant_to->Integer32Value() == initial_capacity) { | 1525 constant_to->Integer32Value() == initial_capacity) { |
| 1529 unfold_loop = true; | 1526 unfold_loop = true; |
| 1530 } | 1527 } |
| 1531 } | 1528 } |
| 1532 | 1529 |
| 1533 // Since we're about to store a hole value, the store instruction below must | 1530 // Since we're about to store a hole value, the store instruction below must |
| 1534 // assume an elements kind that supports heap object values. | 1531 // assume an elements kind that supports heap object values. |
| 1535 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 1532 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
| 1536 elements_kind = FAST_HOLEY_ELEMENTS; | 1533 elements_kind = FAST_HOLEY_ELEMENTS; |
| 1537 } | 1534 } |
| 1538 | 1535 |
| 1539 if (unfold_loop) { | 1536 if (unfold_loop) { |
| 1540 for (int i = 0; i < initial_capacity; i++) { | 1537 for (int i = 0; i < initial_capacity; i++) { |
| 1541 HInstruction* key = AddInstruction(new(zone) HConstant(i)); | 1538 HInstruction* key = Add<HConstant>(i); |
| 1542 AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind)); | 1539 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
| 1543 } | 1540 } |
| 1544 } else { | 1541 } else { |
| 1545 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); | 1542 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); |
| 1546 | 1543 |
| 1547 HValue* key = builder.BeginBody(from, to, Token::LT); | 1544 HValue* key = builder.BeginBody(from, to, Token::LT); |
| 1548 | 1545 |
| 1549 AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind)); | 1546 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
| 1550 | 1547 |
| 1551 builder.EndBody(); | 1548 builder.EndBody(); |
| 1552 } | 1549 } |
| 1553 } | 1550 } |
| 1554 | 1551 |
| 1555 | 1552 |
| 1556 void HGraphBuilder::BuildCopyElements(HValue* context, | 1553 void HGraphBuilder::BuildCopyElements(HValue* context, |
| 1557 HValue* from_elements, | 1554 HValue* from_elements, |
| 1558 ElementsKind from_elements_kind, | 1555 ElementsKind from_elements_kind, |
| 1559 HValue* to_elements, | 1556 HValue* to_elements, |
| 1560 ElementsKind to_elements_kind, | 1557 ElementsKind to_elements_kind, |
| 1561 HValue* length, | 1558 HValue* length, |
| 1562 HValue* capacity) { | 1559 HValue* capacity) { |
| 1563 bool pre_fill_with_holes = | 1560 bool pre_fill_with_holes = |
| 1564 IsFastDoubleElementsKind(from_elements_kind) && | 1561 IsFastDoubleElementsKind(from_elements_kind) && |
| 1565 IsFastObjectElementsKind(to_elements_kind); | 1562 IsFastObjectElementsKind(to_elements_kind); |
| 1566 | 1563 |
| 1567 if (pre_fill_with_holes) { | 1564 if (pre_fill_with_holes) { |
| 1568 // If the copy might trigger a GC, make sure that the FixedArray is | 1565 // If the copy might trigger a GC, make sure that the FixedArray is |
| 1569 // pre-initialized with holes to make sure that it's always in a consistent | 1566 // pre-initialized with holes to make sure that it's always in a consistent |
| 1570 // state. | 1567 // state. |
| 1571 BuildFillElementsWithHole(context, to_elements, to_elements_kind, | 1568 BuildFillElementsWithHole(context, to_elements, to_elements_kind, |
| 1572 graph()->GetConstant0(), capacity); | 1569 graph()->GetConstant0(), capacity); |
| 1573 } | 1570 } |
| 1574 | 1571 |
| 1575 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); | 1572 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); |
| 1576 | 1573 |
| 1577 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); | 1574 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); |
| 1578 | 1575 |
| 1579 HValue* element = | 1576 HValue* element = Add<HLoadKeyed>(from_elements, key, |
| 1580 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, | 1577 static_cast<HValue*>(NULL), |
| 1581 from_elements_kind, | 1578 from_elements_kind, |
| 1582 ALLOW_RETURN_HOLE)); | 1579 ALLOW_RETURN_HOLE); |
| 1583 | 1580 |
| 1584 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind) | 1581 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind) |
| 1585 ? FAST_HOLEY_ELEMENTS : to_elements_kind; | 1582 ? FAST_HOLEY_ELEMENTS : to_elements_kind; |
| 1586 HInstruction* holey_store = AddInstruction( | 1583 HInstruction* holey_store = Add<HStoreKeyed>(to_elements, key, |
| 1587 new(zone()) HStoreKeyed(to_elements, key, element, holey_kind)); | 1584 element, holey_kind); |
| 1588 // Allow NaN hole values to converted to their tagged counterparts. | 1585 // Allow NaN hole values to converted to their tagged counterparts. |
| 1589 if (IsFastHoleyElementsKind(to_elements_kind)) { | 1586 if (IsFastHoleyElementsKind(to_elements_kind)) { |
| 1590 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN); | 1587 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 1591 } | 1588 } |
| 1592 | 1589 |
| 1593 builder.EndBody(); | 1590 builder.EndBody(); |
| 1594 | 1591 |
| 1595 if (!pre_fill_with_holes && length != capacity) { | 1592 if (!pre_fill_with_holes && length != capacity) { |
| 1596 // Fill unused capacity with the hole. | 1593 // Fill unused capacity with the hole. |
| 1597 BuildFillElementsWithHole(context, to_elements, to_elements_kind, | 1594 BuildFillElementsWithHole(context, to_elements, to_elements_kind, |
| 1598 key, capacity); | 1595 key, capacity); |
| 1599 } | 1596 } |
| 1600 } | 1597 } |
| 1601 | 1598 |
| 1602 | 1599 |
| 1603 HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, | 1600 HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, |
| 1604 HValue* boilerplate, | 1601 HValue* boilerplate, |
| 1602 HValue* allocation_site, |
| 1605 AllocationSiteMode mode, | 1603 AllocationSiteMode mode, |
| 1606 ElementsKind kind, | 1604 ElementsKind kind, |
| 1607 int length) { | 1605 int length) { |
| 1608 Zone* zone = this->zone(); | |
| 1609 | |
| 1610 NoObservableSideEffectsScope no_effects(this); | 1606 NoObservableSideEffectsScope no_effects(this); |
| 1611 | 1607 |
| 1612 // All sizes here are multiples of kPointerSize. | 1608 // All sizes here are multiples of kPointerSize. |
| 1613 int size = JSArray::kSize; | 1609 int size = JSArray::kSize; |
| 1614 if (mode == TRACK_ALLOCATION_SITE) { | 1610 if (mode == TRACK_ALLOCATION_SITE) { |
| 1615 size += AllocationSiteInfo::kSize; | 1611 size += AllocationSiteInfo::kSize; |
| 1616 } | 1612 } |
| 1617 int elems_offset = size; | 1613 int elems_offset = size; |
| 1618 if (length > 0) { | 1614 if (length > 0) { |
| 1619 size += IsFastDoubleElementsKind(kind) | 1615 size += IsFastDoubleElementsKind(kind) |
| 1620 ? FixedDoubleArray::SizeFor(length) | 1616 ? FixedDoubleArray::SizeFor(length) |
| 1621 : FixedArray::SizeFor(length); | 1617 : FixedArray::SizeFor(length); |
| 1622 } | 1618 } |
| 1623 | 1619 |
| 1624 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind); | 1620 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind); |
| 1625 // Allocate both the JS array and the elements array in one big | 1621 // Allocate both the JS array and the elements array in one big |
| 1626 // allocation. This avoids multiple limit checks. | 1622 // allocation. This avoids multiple limit checks. |
| 1627 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(size)); | 1623 HValue* size_in_bytes = Add<HConstant>(size); |
| 1628 HInstruction* object = | 1624 HInstruction* object = Add<HAllocate>(context, |
| 1629 AddInstruction(new(zone) HAllocate(context, | 1625 size_in_bytes, |
| 1630 size_in_bytes, | 1626 HType::JSObject(), |
| 1631 HType::JSObject(), | 1627 allocate_flags); |
| 1632 allocate_flags)); | |
| 1633 | 1628 |
| 1634 // Copy the JS array part. | 1629 // Copy the JS array part. |
| 1635 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 1630 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
| 1636 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 1631 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
| 1637 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); | 1632 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
| 1638 AddStore(object, access, AddLoad(boilerplate, access)); | 1633 AddStore(object, access, AddLoad(boilerplate, access)); |
| 1639 } | 1634 } |
| 1640 } | 1635 } |
| 1641 | 1636 |
| 1642 // Create an allocation site info if requested. | 1637 // Create an allocation site info if requested. |
| 1643 if (mode == TRACK_ALLOCATION_SITE) { | 1638 if (mode == TRACK_ALLOCATION_SITE) { |
| 1644 BuildCreateAllocationSiteInfo(object, JSArray::kSize, boilerplate); | 1639 BuildCreateAllocationSiteInfo(object, JSArray::kSize, allocation_site); |
| 1645 } | 1640 } |
| 1646 | 1641 |
| 1647 if (length > 0) { | 1642 if (length > 0) { |
| 1648 // Get hold of the elements array of the boilerplate and setup the | 1643 // Get hold of the elements array of the boilerplate and setup the |
| 1649 // elements pointer in the resulting object. | 1644 // elements pointer in the resulting object. |
| 1650 HValue* boilerplate_elements = AddLoadElements(boilerplate); | 1645 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
| 1651 HValue* object_elements = | 1646 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); |
| 1652 AddInstruction(new(zone) HInnerAllocatedObject(object, elems_offset)); | |
| 1653 AddStore(object, HObjectAccess::ForElementsPointer(), object_elements); | 1647 AddStore(object, HObjectAccess::ForElementsPointer(), object_elements); |
| 1654 | 1648 |
| 1655 // Copy the elements array header. | 1649 // Copy the elements array header. |
| 1656 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | 1650 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
| 1657 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | 1651 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); |
| 1658 AddStore(object_elements, access, AddLoad(boilerplate_elements, access)); | 1652 AddStore(object_elements, access, AddLoad(boilerplate_elements, access)); |
| 1659 } | 1653 } |
| 1660 | 1654 |
| 1661 // Copy the elements array contents. | 1655 // Copy the elements array contents. |
| 1662 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold | 1656 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold |
| 1663 // copying loops with constant length up to a given boundary and use this | 1657 // copying loops with constant length up to a given boundary and use this |
| 1664 // helper here instead. | 1658 // helper here instead. |
| 1665 for (int i = 0; i < length; i++) { | 1659 for (int i = 0; i < length; i++) { |
| 1666 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); | 1660 HValue* key_constant = Add<HConstant>(i); |
| 1667 HInstruction* value = | 1661 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, |
| 1668 AddInstruction(new(zone) HLoadKeyed(boilerplate_elements, | 1662 static_cast<HValue*>(NULL), kind); |
| 1669 key_constant, | 1663 Add<HStoreKeyed>(object_elements, key_constant, value, kind); |
| 1670 NULL, | |
| 1671 kind)); | |
| 1672 AddInstruction(new(zone) HStoreKeyed(object_elements, | |
| 1673 key_constant, | |
| 1674 value, | |
| 1675 kind)); | |
| 1676 } | 1664 } |
| 1677 } | 1665 } |
| 1678 | 1666 |
| 1679 return object; | 1667 return object; |
| 1680 } | 1668 } |
| 1681 | 1669 |
| 1682 | 1670 |
| 1671 HInstruction* HGraphBuilder::BuildUnaryMathOp( |
| 1672 HValue* input, Handle<Type> type, Token::Value operation) { |
| 1673 // We only handle the numeric cases here |
| 1674 type = handle( |
| 1675 Type::Intersect(type, handle(Type::Number(), isolate())), isolate()); |
| 1676 |
| 1677 switch (operation) { |
| 1678 default: |
| 1679 UNREACHABLE(); |
| 1680 case Token::SUB: { |
| 1681 HInstruction* instr = |
| 1682 HMul::New(zone(), environment()->LookupContext(), |
| 1683 input, graph()->GetConstantMinus1()); |
| 1684 Representation rep = Representation::FromType(type); |
| 1685 if (type->Is(Type::None())) { |
| 1686 AddSoftDeoptimize(); |
| 1687 } |
| 1688 if (instr->IsBinaryOperation()) { |
| 1689 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
| 1690 binop->set_observed_input_representation(1, rep); |
| 1691 binop->set_observed_input_representation(2, rep); |
| 1692 } |
| 1693 return instr; |
| 1694 } |
| 1695 case Token::BIT_NOT: |
| 1696 if (type->Is(Type::None())) { |
| 1697 AddSoftDeoptimize(); |
| 1698 } |
| 1699 return new(zone()) HBitNot(input); |
| 1700 } |
| 1701 } |
| 1702 |
| 1703 |
| 1683 void HGraphBuilder::BuildCompareNil( | 1704 void HGraphBuilder::BuildCompareNil( |
| 1684 HValue* value, | 1705 HValue* value, |
| 1685 Handle<Type> type, | 1706 Handle<Type> type, |
| 1686 int position, | 1707 int position, |
| 1687 HIfContinuation* continuation) { | 1708 HIfContinuation* continuation) { |
| 1688 IfBuilder if_nil(this, position); | 1709 IfBuilder if_nil(this, position); |
| 1689 bool needs_or = false; | 1710 bool needs_or = false; |
| 1690 if (type->Maybe(Type::Null())) { | 1711 if (type->Maybe(Type::Null())) { |
| 1691 if (needs_or) if_nil.Or(); | 1712 if (needs_or) if_nil.Or(); |
| 1692 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); | 1713 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1715 if_nil.Deopt(); | 1736 if_nil.Deopt(); |
| 1716 } | 1737 } |
| 1717 } | 1738 } |
| 1718 | 1739 |
| 1719 if_nil.CaptureContinuation(continuation); | 1740 if_nil.CaptureContinuation(continuation); |
| 1720 } | 1741 } |
| 1721 | 1742 |
| 1722 | 1743 |
| 1723 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object, | 1744 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object, |
| 1724 int previous_object_size, | 1745 int previous_object_size, |
| 1725 HValue* payload) { | 1746 HValue* alloc_site) { |
| 1726 HInnerAllocatedObject* alloc_site = new(zone()) | 1747 ASSERT(alloc_site != NULL); |
| 1727 HInnerAllocatedObject(previous_object, previous_object_size); | 1748 HInnerAllocatedObject* alloc_site_info = Add<HInnerAllocatedObject>( |
| 1728 AddInstruction(alloc_site); | 1749 previous_object, previous_object_size); |
| 1729 Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); | 1750 Handle<Map> alloc_site_info_map( |
| 1730 AddStoreMapConstant(alloc_site, alloc_site_map); | 1751 isolate()->heap()->allocation_site_info_map()); |
| 1731 HObjectAccess access = HObjectAccess::ForAllocationSitePayload(); | 1752 AddStoreMapConstant(alloc_site_info, alloc_site_info_map); |
| 1732 AddStore(alloc_site, access, payload); | 1753 HObjectAccess access = HObjectAccess::ForAllocationSiteInfoSite(); |
| 1733 return alloc_site; | 1754 AddStore(alloc_site_info, access, alloc_site); |
| 1755 return alloc_site_info; |
| 1734 } | 1756 } |
| 1735 | 1757 |
| 1736 | 1758 |
| 1737 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) { | 1759 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) { |
| 1738 // Get the global context, then the native context | 1760 // Get the global context, then the native context |
| 1739 HInstruction* global_object = AddInstruction(new(zone()) | 1761 HInstruction* global_object = Add<HGlobalObject>(context); |
| 1740 HGlobalObject(context)); | |
| 1741 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 1762 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
| 1742 GlobalObject::kNativeContextOffset); | 1763 GlobalObject::kNativeContextOffset); |
| 1743 return AddLoad(global_object, access); | 1764 return AddLoad(global_object, access); |
| 1744 } | 1765 } |
| 1745 | 1766 |
| 1746 | 1767 |
| 1747 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) { | 1768 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) { |
| 1748 HInstruction* native_context = BuildGetNativeContext(context); | 1769 HInstruction* native_context = BuildGetNativeContext(context); |
| 1749 HInstruction* index = AddInstruction(new(zone()) | 1770 HInstruction* index = |
| 1750 HConstant(Context::ARRAY_FUNCTION_INDEX)); | 1771 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); |
| 1751 | 1772 return Add<HLoadKeyed>( |
| 1752 return AddInstruction(new (zone()) | 1773 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1753 HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS)); | |
| 1754 } | 1774 } |
| 1755 | 1775 |
| 1756 | 1776 |
| 1757 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 1777 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
| 1758 ElementsKind kind, | 1778 ElementsKind kind, |
| 1759 HValue* allocation_site_payload, | 1779 HValue* allocation_site_payload, |
| 1760 bool disable_allocation_sites) : | 1780 HValue* constructor_function, |
| 1781 AllocationSiteOverrideMode override_mode) : |
| 1761 builder_(builder), | 1782 builder_(builder), |
| 1762 kind_(kind), | 1783 kind_(kind), |
| 1763 allocation_site_payload_(allocation_site_payload), | 1784 allocation_site_payload_(allocation_site_payload), |
| 1764 constructor_function_(NULL) { | 1785 constructor_function_(constructor_function) { |
| 1765 mode_ = disable_allocation_sites | 1786 mode_ = override_mode == DISABLE_ALLOCATION_SITES |
| 1766 ? DONT_TRACK_ALLOCATION_SITE | 1787 ? DONT_TRACK_ALLOCATION_SITE |
| 1767 : AllocationSiteInfo::GetMode(kind); | 1788 : AllocationSite::GetMode(kind); |
| 1768 } | 1789 } |
| 1769 | 1790 |
| 1770 | 1791 |
| 1771 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 1792 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
| 1772 ElementsKind kind, | 1793 ElementsKind kind, |
| 1773 HValue* constructor_function) : | 1794 HValue* constructor_function) : |
| 1774 builder_(builder), | 1795 builder_(builder), |
| 1775 kind_(kind), | 1796 kind_(kind), |
| 1776 mode_(DONT_TRACK_ALLOCATION_SITE), | 1797 mode_(DONT_TRACK_ALLOCATION_SITE), |
| 1777 allocation_site_payload_(NULL), | 1798 allocation_site_payload_(NULL), |
| 1778 constructor_function_(constructor_function) { | 1799 constructor_function_(constructor_function) { |
| 1779 } | 1800 } |
| 1780 | 1801 |
| 1781 | 1802 |
| 1782 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { | 1803 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { |
| 1804 if (kind_ == GetInitialFastElementsKind()) { |
| 1805 // No need for a context lookup if the kind_ matches the initial |
| 1806 // map, because we can just load the map in that case. |
| 1807 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 1808 HInstruction* load = |
| 1809 builder()->BuildLoadNamedField(constructor_function_, |
| 1810 access, |
| 1811 Representation::Tagged()); |
| 1812 return builder()->AddInstruction(load); |
| 1813 } |
| 1814 |
| 1783 HInstruction* native_context = builder()->BuildGetNativeContext(context); | 1815 HInstruction* native_context = builder()->BuildGetNativeContext(context); |
| 1816 HInstruction* index = builder()->Add<HConstant>( |
| 1817 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); |
| 1784 | 1818 |
| 1785 HInstruction* index = builder()->AddInstruction(new(zone()) | 1819 HInstruction* map_array = builder()->Add<HLoadKeyed>( |
| 1786 HConstant(Context::JS_ARRAY_MAPS_INDEX)); | 1820 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1787 | 1821 |
| 1788 HInstruction* map_array = builder()->AddInstruction(new(zone()) | 1822 HInstruction* kind_index = builder()->Add<HConstant>(kind_); |
| 1789 HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS)); | |
| 1790 | 1823 |
| 1791 HInstruction* kind_index = builder()->AddInstruction(new(zone()) | 1824 return builder()->Add<HLoadKeyed>( |
| 1792 HConstant(kind_)); | 1825 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1793 | |
| 1794 return builder()->AddInstruction(new(zone()) | |
| 1795 HLoadKeyed(map_array, kind_index, NULL, FAST_ELEMENTS)); | |
| 1796 } | 1826 } |
| 1797 | 1827 |
| 1798 | 1828 |
| 1799 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 1829 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
| 1800 // Find the map near the constructor function | 1830 // Find the map near the constructor function |
| 1801 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1831 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 1802 return AddInstruction( | 1832 return builder()->AddInstruction( |
| 1803 builder()->BuildLoadNamedField(constructor_function_, | 1833 builder()->BuildLoadNamedField(constructor_function_, |
| 1804 access, | 1834 access, |
| 1805 Representation::Tagged())); | 1835 Representation::Tagged())); |
| 1806 } | 1836 } |
| 1807 | 1837 |
| 1808 | 1838 |
| 1809 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1839 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
| 1810 HValue* length_node) { | 1840 HValue* length_node) { |
| 1811 HValue* context = builder()->environment()->LookupContext(); | 1841 HValue* context = builder()->environment()->LookupContext(); |
| 1812 ASSERT(length_node != NULL); | 1842 ASSERT(length_node != NULL); |
| 1813 | 1843 |
| 1814 int base_size = JSArray::kSize; | 1844 int base_size = JSArray::kSize; |
| 1815 if (mode_ == TRACK_ALLOCATION_SITE) { | 1845 if (mode_ == TRACK_ALLOCATION_SITE) { |
| 1816 base_size += AllocationSiteInfo::kSize; | 1846 base_size += AllocationSiteInfo::kSize; |
| 1817 } | 1847 } |
| 1818 | 1848 |
| 1819 if (IsFastDoubleElementsKind(kind_)) { | 1849 if (IsFastDoubleElementsKind(kind_)) { |
| 1820 base_size += FixedDoubleArray::kHeaderSize; | 1850 base_size += FixedDoubleArray::kHeaderSize; |
| 1821 } else { | 1851 } else { |
| 1822 base_size += FixedArray::kHeaderSize; | 1852 base_size += FixedArray::kHeaderSize; |
| 1823 } | 1853 } |
| 1824 | 1854 |
| 1825 HInstruction* elements_size_value = new(zone()) HConstant(elements_size()); | 1855 HInstruction* elements_size_value = |
| 1826 AddInstruction(elements_size_value); | 1856 builder()->Add<HConstant>(elements_size()); |
| 1827 HInstruction* mul = HMul::New(zone(), context, length_node, | 1857 HInstruction* mul = HMul::New(zone(), context, length_node, |
| 1828 elements_size_value); | 1858 elements_size_value); |
| 1829 mul->ClearFlag(HValue::kCanOverflow); | 1859 mul->ClearFlag(HValue::kCanOverflow); |
| 1830 AddInstruction(mul); | 1860 builder()->AddInstruction(mul); |
| 1831 | 1861 |
| 1832 HInstruction* base = new(zone()) HConstant(base_size); | 1862 HInstruction* base = builder()->Add<HConstant>(base_size); |
| 1833 AddInstruction(base); | |
| 1834 HInstruction* total_size = HAdd::New(zone(), context, base, mul); | 1863 HInstruction* total_size = HAdd::New(zone(), context, base, mul); |
| 1835 total_size->ClearFlag(HValue::kCanOverflow); | 1864 total_size->ClearFlag(HValue::kCanOverflow); |
| 1836 AddInstruction(total_size); | 1865 builder()->AddInstruction(total_size); |
| 1837 return total_size; | 1866 return total_size; |
| 1838 } | 1867 } |
| 1839 | 1868 |
| 1840 | 1869 |
| 1841 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { | 1870 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { |
| 1842 int base_size = JSArray::kSize; | 1871 int base_size = JSArray::kSize; |
| 1843 if (mode_ == TRACK_ALLOCATION_SITE) { | 1872 if (mode_ == TRACK_ALLOCATION_SITE) { |
| 1844 base_size += AllocationSiteInfo::kSize; | 1873 base_size += AllocationSiteInfo::kSize; |
| 1845 } | 1874 } |
| 1846 | 1875 |
| 1847 base_size += IsFastDoubleElementsKind(kind_) | 1876 base_size += IsFastDoubleElementsKind(kind_) |
| 1848 ? FixedDoubleArray::SizeFor(initial_capacity()) | 1877 ? FixedDoubleArray::SizeFor(initial_capacity()) |
| 1849 : FixedArray::SizeFor(initial_capacity()); | 1878 : FixedArray::SizeFor(initial_capacity()); |
| 1850 | 1879 |
| 1851 HConstant* array_size = new(zone()) HConstant(base_size); | 1880 return builder()->Add<HConstant>(base_size); |
| 1852 AddInstruction(array_size); | |
| 1853 return array_size; | |
| 1854 } | 1881 } |
| 1855 | 1882 |
| 1856 | 1883 |
| 1857 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { | 1884 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { |
| 1858 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); | 1885 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); |
| 1859 HConstant* capacity = new(zone()) HConstant(initial_capacity()); | 1886 HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); |
| 1860 AddInstruction(capacity); | |
| 1861 return AllocateArray(size_in_bytes, | 1887 return AllocateArray(size_in_bytes, |
| 1862 capacity, | 1888 capacity, |
| 1863 builder()->graph()->GetConstant0(), | 1889 builder()->graph()->GetConstant0(), |
| 1864 true); | 1890 true); |
| 1865 } | 1891 } |
| 1866 | 1892 |
| 1867 | 1893 |
| 1868 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, | 1894 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, |
| 1869 HValue* length_field, | 1895 HValue* length_field, |
| 1870 bool fill_with_hole) { | 1896 bool fill_with_hole) { |
| 1871 HValue* size_in_bytes = EstablishAllocationSize(capacity); | 1897 HValue* size_in_bytes = EstablishAllocationSize(capacity); |
| 1872 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); | 1898 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); |
| 1873 } | 1899 } |
| 1874 | 1900 |
| 1875 | 1901 |
| 1876 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, | 1902 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, |
| 1877 HValue* capacity, | 1903 HValue* capacity, |
| 1878 HValue* length_field, | 1904 HValue* length_field, |
| 1879 bool fill_with_hole) { | 1905 bool fill_with_hole) { |
| 1880 HValue* context = builder()->environment()->LookupContext(); | 1906 HValue* context = builder()->environment()->LookupContext(); |
| 1881 | 1907 |
| 1882 // Allocate (dealing with failure appropriately) | 1908 // Allocate (dealing with failure appropriately) |
| 1883 HAllocate::Flags flags = HAllocate::DefaultFlags(kind_); | 1909 HAllocate::Flags flags = HAllocate::DefaultFlags(kind_); |
| 1884 HAllocate* new_object = new(zone()) HAllocate(context, size_in_bytes, | 1910 HAllocate* new_object = builder()->Add<HAllocate>(context, size_in_bytes, |
| 1885 HType::JSArray(), flags); | 1911 HType::JSArray(), flags); |
| 1886 AddInstruction(new_object); | |
| 1887 | 1912 |
| 1888 // Fill in the fields: map, properties, length | 1913 // Fill in the fields: map, properties, length |
| 1889 HValue* map; | 1914 HValue* map; |
| 1890 if (constructor_function_ != NULL) { | 1915 if (allocation_site_payload_ == NULL) { |
| 1891 map = EmitInternalMapCode(); | 1916 map = EmitInternalMapCode(); |
| 1892 } else { | 1917 } else { |
| 1893 map = EmitMapCode(context); | 1918 map = EmitMapCode(context); |
| 1894 } | 1919 } |
| 1895 elements_location_ = builder()->BuildJSArrayHeader(new_object, | 1920 elements_location_ = builder()->BuildJSArrayHeader(new_object, |
| 1896 map, | 1921 map, |
| 1897 mode_, | 1922 mode_, |
| 1898 allocation_site_payload_, | 1923 allocation_site_payload_, |
| 1899 length_field); | 1924 length_field); |
| 1900 | 1925 |
| 1901 // Initialize the elements | 1926 // Initialize the elements |
| 1902 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); | 1927 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); |
| 1903 | 1928 |
| 1904 if (fill_with_hole) { | 1929 if (fill_with_hole) { |
| 1905 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, | 1930 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, |
| 1906 graph()->GetConstant0(), capacity); | 1931 graph()->GetConstant0(), capacity); |
| 1907 } | 1932 } |
| 1908 | 1933 |
| 1909 return new_object; | 1934 return new_object; |
| 1910 } | 1935 } |
| 1911 | 1936 |
| 1912 | 1937 |
| 1913 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, | 1938 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, |
| 1914 HObjectAccess access, | 1939 HObjectAccess access, |
| 1915 HValue *val, | 1940 HValue *val, |
| 1916 Representation representation) { | 1941 Representation representation) { |
| 1917 HStoreNamedField *instr = new(zone()) | 1942 return Add<HStoreNamedField>(object, access, val, representation); |
| 1918 HStoreNamedField(object, access, val, representation); | |
| 1919 AddInstruction(instr); | |
| 1920 return instr; | |
| 1921 } | 1943 } |
| 1922 | 1944 |
| 1923 | 1945 |
| 1924 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, | 1946 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, |
| 1925 HObjectAccess access, | 1947 HObjectAccess access, |
| 1926 HValue *typecheck, | 1948 HValue *typecheck, |
| 1927 Representation representation) { | 1949 Representation representation) { |
| 1928 HLoadNamedField *instr = | 1950 return Add<HLoadNamedField>(object, access, typecheck, representation); |
| 1929 new(zone()) HLoadNamedField(object, access, typecheck, representation); | |
| 1930 AddInstruction(instr); | |
| 1931 return instr; | |
| 1932 } | 1951 } |
| 1933 | 1952 |
| 1934 | 1953 |
| 1935 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | 1954 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, |
| 1936 Handle<Map> map) { | 1955 Handle<Map> map) { |
| 1937 HValue* constant = AddInstruction(new(zone()) HConstant(map)); | 1956 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), |
| 1938 HStoreNamedField *instr = | 1957 Add<HConstant>(map)); |
| 1939 new(zone()) HStoreNamedField(object, HObjectAccess::ForMap(), constant); | |
| 1940 AddInstruction(instr); | |
| 1941 return instr; | |
| 1942 } | 1958 } |
| 1943 | 1959 |
| 1944 | 1960 |
| 1961 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin, |
| 1962 HContext* context) { |
| 1963 HGlobalObject* global_object = Add<HGlobalObject>(context); |
| 1964 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
| 1965 GlobalObject::kBuiltinsOffset); |
| 1966 HValue* builtins = AddLoad(global_object, access); |
| 1967 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset( |
| 1968 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); |
| 1969 return AddLoad(builtins, function_access); |
| 1970 } |
| 1971 |
| 1972 |
| 1945 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) | 1973 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) |
| 1946 : HGraphBuilder(info), | 1974 : HGraphBuilder(info), |
| 1947 function_state_(NULL), | 1975 function_state_(NULL), |
| 1948 initial_function_state_(this, info, NORMAL_RETURN), | 1976 initial_function_state_(this, info, NORMAL_RETURN), |
| 1949 ast_context_(NULL), | 1977 ast_context_(NULL), |
| 1950 break_scope_(NULL), | 1978 break_scope_(NULL), |
| 1951 inlined_count_(0), | 1979 inlined_count_(0), |
| 1952 globals_(10, info->zone()), | 1980 globals_(10, info->zone()), |
| 1953 inline_bailout_(false) { | 1981 inline_bailout_(false), |
| 1982 osr_(new(info->zone()) HOsrBuilder(this)) { |
| 1954 // This is not initialized in the initializer list because the | 1983 // This is not initialized in the initializer list because the |
| 1955 // constructor for the initial state relies on function_state_ == NULL | 1984 // constructor for the initial state relies on function_state_ == NULL |
| 1956 // to know it's the initial state. | 1985 // to know it's the initial state. |
| 1957 function_state_= &initial_function_state_; | 1986 function_state_= &initial_function_state_; |
| 1958 InitializeAstVisitor(); | 1987 InitializeAstVisitor(); |
| 1959 } | 1988 } |
| 1960 | 1989 |
| 1961 | 1990 |
| 1962 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, | 1991 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, |
| 1963 HBasicBlock* second, | 1992 HBasicBlock* second, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2011 | 2040 |
| 2012 | 2041 |
| 2013 HGraph::HGraph(CompilationInfo* info) | 2042 HGraph::HGraph(CompilationInfo* info) |
| 2014 : isolate_(info->isolate()), | 2043 : isolate_(info->isolate()), |
| 2015 next_block_id_(0), | 2044 next_block_id_(0), |
| 2016 entry_block_(NULL), | 2045 entry_block_(NULL), |
| 2017 blocks_(8, info->zone()), | 2046 blocks_(8, info->zone()), |
| 2018 values_(16, info->zone()), | 2047 values_(16, info->zone()), |
| 2019 phi_list_(NULL), | 2048 phi_list_(NULL), |
| 2020 uint32_instructions_(NULL), | 2049 uint32_instructions_(NULL), |
| 2050 osr_(NULL), |
| 2021 info_(info), | 2051 info_(info), |
| 2022 zone_(info->zone()), | 2052 zone_(info->zone()), |
| 2023 is_recursive_(false), | 2053 is_recursive_(false), |
| 2024 use_optimistic_licm_(false), | 2054 use_optimistic_licm_(false), |
| 2025 has_soft_deoptimize_(false), | 2055 has_soft_deoptimize_(false), |
| 2026 depends_on_empty_array_proto_elements_(false), | 2056 depends_on_empty_array_proto_elements_(false), |
| 2027 type_change_checksum_(0), | 2057 type_change_checksum_(0), |
| 2028 maximum_environment_size_(0) { | 2058 maximum_environment_size_(0) { |
| 2029 if (info->IsStub()) { | 2059 if (info->IsStub()) { |
| 2030 HydrogenCodeStub* stub = info->code_stub(); | 2060 HydrogenCodeStub* stub = info->code_stub(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2046 HBasicBlock* result = new(zone()) HBasicBlock(this); | 2076 HBasicBlock* result = new(zone()) HBasicBlock(this); |
| 2047 blocks_.Add(result, zone()); | 2077 blocks_.Add(result, zone()); |
| 2048 return result; | 2078 return result; |
| 2049 } | 2079 } |
| 2050 | 2080 |
| 2051 | 2081 |
| 2052 void HGraph::FinalizeUniqueValueIds() { | 2082 void HGraph::FinalizeUniqueValueIds() { |
| 2053 DisallowHeapAllocation no_gc; | 2083 DisallowHeapAllocation no_gc; |
| 2054 ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread()); | 2084 ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread()); |
| 2055 for (int i = 0; i < blocks()->length(); ++i) { | 2085 for (int i = 0; i < blocks()->length(); ++i) { |
| 2056 for (HInstruction* instr = blocks()->at(i)->first(); | 2086 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { |
| 2057 instr != NULL; | 2087 it.Current()->FinalizeUniqueValueId(); |
| 2058 instr = instr->next()) { | |
| 2059 instr->FinalizeUniqueValueId(); | |
| 2060 } | 2088 } |
| 2061 } | 2089 } |
| 2062 } | 2090 } |
| 2063 | 2091 |
| 2064 | 2092 |
| 2065 void HGraph::Canonicalize() { | 2093 void HGraph::Canonicalize() { |
| 2066 HPhase phase("H_Canonicalize", this); | 2094 HPhase phase("H_Canonicalize", this); |
| 2067 // Before removing no-op instructions, save their semantic value. | 2095 // Before removing no-op instructions, save their semantic value. |
| 2068 // We must be careful not to set the flag unnecessarily, because GVN | 2096 // We must be careful not to set the flag unnecessarily, because GVN |
| 2069 // cannot identify two instructions when their flag value differs. | 2097 // cannot identify two instructions when their flag value differs. |
| 2070 for (int i = 0; i < blocks()->length(); ++i) { | 2098 for (int i = 0; i < blocks()->length(); ++i) { |
| 2071 HInstruction* instr = blocks()->at(i)->first(); | 2099 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { |
| 2072 while (instr != NULL) { | 2100 HInstruction* instr = it.Current(); |
| 2073 if (instr->IsArithmeticBinaryOperation() && | 2101 if (instr->IsArithmeticBinaryOperation() && |
| 2074 instr->representation().IsInteger32() && | 2102 instr->representation().IsInteger32() && |
| 2075 instr->HasAtLeastOneUseWithFlagAndNoneWithout( | 2103 instr->HasAtLeastOneUseWithFlagAndNoneWithout( |
| 2076 HInstruction::kTruncatingToInt32)) { | 2104 HInstruction::kTruncatingToInt32)) { |
| 2077 instr->SetFlag(HInstruction::kAllUsesTruncatingToInt32); | 2105 instr->SetFlag(HInstruction::kAllUsesTruncatingToInt32); |
| 2078 } | 2106 } |
| 2079 instr = instr->next(); | |
| 2080 } | 2107 } |
| 2081 } | 2108 } |
| 2082 // Perform actual Canonicalization pass. | 2109 // Perform actual Canonicalization pass. |
| 2083 for (int i = 0; i < blocks()->length(); ++i) { | 2110 for (int i = 0; i < blocks()->length(); ++i) { |
| 2084 HInstruction* instr = blocks()->at(i)->first(); | 2111 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { |
| 2085 while (instr != NULL) { | 2112 HInstruction* instr = it.Current(); |
| 2086 HValue* value = instr->Canonicalize(); | 2113 HValue* value = instr->Canonicalize(); |
| 2087 if (value != instr) instr->DeleteAndReplaceWith(value); | 2114 if (value != instr) instr->DeleteAndReplaceWith(value); |
| 2088 instr = instr->next(); | |
| 2089 } | 2115 } |
| 2090 } | 2116 } |
| 2091 } | 2117 } |
| 2092 | 2118 |
| 2119 |
| 2093 // Block ordering was implemented with two mutually recursive methods, | 2120 // Block ordering was implemented with two mutually recursive methods, |
| 2094 // HGraph::Postorder and HGraph::PostorderLoopBlocks. | 2121 // HGraph::Postorder and HGraph::PostorderLoopBlocks. |
| 2095 // The recursion could lead to stack overflow so the algorithm has been | 2122 // The recursion could lead to stack overflow so the algorithm has been |
| 2096 // implemented iteratively. | 2123 // implemented iteratively. |
| 2097 // At a high level the algorithm looks like this: | 2124 // At a high level the algorithm looks like this: |
| 2098 // | 2125 // |
| 2099 // Postorder(block, loop_header) : { | 2126 // Postorder(block, loop_header) : { |
| 2100 // if (block has already been visited or is of another loop) return; | 2127 // if (block has already been visited or is of another loop) return; |
| 2101 // mark block as visited; | 2128 // mark block as visited; |
| 2102 // if (block is a loop header) { | 2129 // if (block is a loop header) { |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2453 const ZoneList<HBasicBlock*>* predecessors = block->predecessors(); | 2480 const ZoneList<HBasicBlock*>* predecessors = block->predecessors(); |
| 2454 int predecessors_length = predecessors->length(); | 2481 int predecessors_length = predecessors->length(); |
| 2455 bool all_predecessors_deoptimizing = (predecessors_length > 0); | 2482 bool all_predecessors_deoptimizing = (predecessors_length > 0); |
| 2456 for (int j = 0; j < predecessors_length; ++j) { | 2483 for (int j = 0; j < predecessors_length; ++j) { |
| 2457 if (!predecessors->at(j)->IsDeoptimizing()) { | 2484 if (!predecessors->at(j)->IsDeoptimizing()) { |
| 2458 all_predecessors_deoptimizing = false; | 2485 all_predecessors_deoptimizing = false; |
| 2459 break; | 2486 break; |
| 2460 } | 2487 } |
| 2461 } | 2488 } |
| 2462 if (all_predecessors_deoptimizing) nullify = true; | 2489 if (all_predecessors_deoptimizing) nullify = true; |
| 2463 for (HInstruction* instr = block->first(); instr != NULL; | 2490 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 2464 instr = instr->next()) { | 2491 HInstruction* instr = it.Current(); |
| 2465 // Leave the basic structure of the graph intact. | 2492 // Leave the basic structure of the graph intact. |
| 2466 if (instr->IsBlockEntry()) continue; | 2493 if (instr->IsBlockEntry()) continue; |
| 2467 if (instr->IsControlInstruction()) continue; | 2494 if (instr->IsControlInstruction()) continue; |
| 2468 if (instr->IsSimulate()) continue; | 2495 if (instr->IsSimulate()) continue; |
| 2469 if (instr->IsEnterInlined()) continue; | 2496 if (instr->IsEnterInlined()) continue; |
| 2470 if (instr->IsLeaveInlined()) continue; | 2497 if (instr->IsLeaveInlined()) continue; |
| 2471 if (nullify) { | 2498 if (nullify) { |
| 2472 HInstruction* last_dummy = NULL; | 2499 HInstruction* last_dummy = NULL; |
| 2473 for (int j = 0; j < instr->OperandCount(); ++j) { | 2500 for (int j = 0; j < instr->OperandCount(); ++j) { |
| 2474 HValue* operand = instr->OperandAt(j); | 2501 HValue* operand = instr->OperandAt(j); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2498 } | 2525 } |
| 2499 if (instr->IsSoftDeoptimize()) { | 2526 if (instr->IsSoftDeoptimize()) { |
| 2500 ASSERT(block->IsDeoptimizing()); | 2527 ASSERT(block->IsDeoptimizing()); |
| 2501 nullify = true; | 2528 nullify = true; |
| 2502 } | 2529 } |
| 2503 } | 2530 } |
| 2504 } | 2531 } |
| 2505 } | 2532 } |
| 2506 | 2533 |
| 2507 | 2534 |
| 2508 // Replace all phis consisting of a single non-loop operand plus any number of | |
| 2509 // loop operands by that single non-loop operand. | |
| 2510 void HGraph::EliminateRedundantPhis() { | |
| 2511 HPhase phase("H_Redundant phi elimination", this); | |
| 2512 | |
| 2513 // We do a simple fixed point iteration without any work list, because | |
| 2514 // machine-generated JavaScript can lead to a very dense Hydrogen graph with | |
| 2515 // an enormous work list and will consequently result in OOM. Experiments | |
| 2516 // showed that this simple algorithm is good enough, and even e.g. tracking | |
| 2517 // the set or range of blocks to consider is not a real improvement. | |
| 2518 bool need_another_iteration; | |
| 2519 ZoneList<HPhi*> redundant_phis(blocks_.length(), zone()); | |
| 2520 do { | |
| 2521 need_another_iteration = false; | |
| 2522 for (int i = 0; i < blocks_.length(); ++i) { | |
| 2523 HBasicBlock* block = blocks_[i]; | |
| 2524 for (int j = 0; j < block->phis()->length(); j++) { | |
| 2525 HPhi* phi = block->phis()->at(j); | |
| 2526 HValue* replacement = phi->GetRedundantReplacement(); | |
| 2527 if (replacement != NULL) { | |
| 2528 // Remember phi to avoid concurrent modification of the block's phis. | |
| 2529 redundant_phis.Add(phi, zone()); | |
| 2530 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { | |
| 2531 HValue* value = it.value(); | |
| 2532 value->SetOperandAt(it.index(), replacement); | |
| 2533 need_another_iteration |= value->IsPhi(); | |
| 2534 } | |
| 2535 } | |
| 2536 } | |
| 2537 for (int i = 0; i < redundant_phis.length(); i++) { | |
| 2538 block->RemovePhi(redundant_phis[i]); | |
| 2539 } | |
| 2540 redundant_phis.Clear(); | |
| 2541 } | |
| 2542 } while (need_another_iteration); | |
| 2543 | |
| 2544 #if DEBUG | |
| 2545 // Make sure that we *really* removed all redundant phis. | |
| 2546 for (int i = 0; i < blocks_.length(); ++i) { | |
| 2547 for (int j = 0; j < blocks_[i]->phis()->length(); j++) { | |
| 2548 ASSERT(blocks_[i]->phis()->at(j)->GetRedundantReplacement() == NULL); | |
| 2549 } | |
| 2550 } | |
| 2551 #endif | |
| 2552 } | |
| 2553 | |
| 2554 | |
| 2555 bool HGraph::CheckArgumentsPhiUses() { | 2535 bool HGraph::CheckArgumentsPhiUses() { |
| 2556 int block_count = blocks_.length(); | 2536 int block_count = blocks_.length(); |
| 2557 for (int i = 0; i < block_count; ++i) { | 2537 for (int i = 0; i < block_count; ++i) { |
| 2558 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { | 2538 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { |
| 2559 HPhi* phi = blocks_[i]->phis()->at(j); | 2539 HPhi* phi = blocks_[i]->phis()->at(j); |
| 2560 // We don't support phi uses of arguments for now. | 2540 // We don't support phi uses of arguments for now. |
| 2561 if (phi->CheckFlag(HValue::kIsArguments)) return false; | 2541 if (phi->CheckFlag(HValue::kIsArguments)) return false; |
| 2562 } | 2542 } |
| 2563 } | 2543 } |
| 2564 return true; | 2544 return true; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2585 phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone()); | 2565 phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone()); |
| 2586 for (int i = 0; i < block_count; ++i) { | 2566 for (int i = 0; i < block_count; ++i) { |
| 2587 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { | 2567 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { |
| 2588 HPhi* phi = blocks_[i]->phis()->at(j); | 2568 HPhi* phi = blocks_[i]->phis()->at(j); |
| 2589 phi_list_->Add(phi, zone()); | 2569 phi_list_->Add(phi, zone()); |
| 2590 } | 2570 } |
| 2591 } | 2571 } |
| 2592 } | 2572 } |
| 2593 | 2573 |
| 2594 | 2574 |
| 2595 void HGraph::InferTypes(ZoneList<HValue*>* worklist) { | |
| 2596 BitVector in_worklist(GetMaximumValueID(), zone()); | |
| 2597 for (int i = 0; i < worklist->length(); ++i) { | |
| 2598 ASSERT(!in_worklist.Contains(worklist->at(i)->id())); | |
| 2599 in_worklist.Add(worklist->at(i)->id()); | |
| 2600 } | |
| 2601 | |
| 2602 while (!worklist->is_empty()) { | |
| 2603 HValue* current = worklist->RemoveLast(); | |
| 2604 in_worklist.Remove(current->id()); | |
| 2605 if (current->UpdateInferredType()) { | |
| 2606 for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) { | |
| 2607 HValue* use = it.value(); | |
| 2608 if (!in_worklist.Contains(use->id())) { | |
| 2609 in_worklist.Add(use->id()); | |
| 2610 worklist->Add(use, zone()); | |
| 2611 } | |
| 2612 } | |
| 2613 } | |
| 2614 } | |
| 2615 } | |
| 2616 | |
| 2617 | |
| 2618 class HRangeAnalysis BASE_EMBEDDED { | |
| 2619 public: | |
| 2620 explicit HRangeAnalysis(HGraph* graph) : | |
| 2621 graph_(graph), zone_(graph->zone()), changed_ranges_(16, zone_) { } | |
| 2622 | |
| 2623 void Analyze(); | |
| 2624 | |
| 2625 private: | |
| 2626 void TraceRange(const char* msg, ...); | |
| 2627 void Analyze(HBasicBlock* block); | |
| 2628 void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest); | |
| 2629 void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other); | |
| 2630 void InferRange(HValue* value); | |
| 2631 void RollBackTo(int index); | |
| 2632 void AddRange(HValue* value, Range* range); | |
| 2633 | |
| 2634 HGraph* graph_; | |
| 2635 Zone* zone_; | |
| 2636 ZoneList<HValue*> changed_ranges_; | |
| 2637 }; | |
| 2638 | |
| 2639 | |
| 2640 void HRangeAnalysis::TraceRange(const char* msg, ...) { | |
| 2641 if (FLAG_trace_range) { | |
| 2642 va_list arguments; | |
| 2643 va_start(arguments, msg); | |
| 2644 OS::VPrint(msg, arguments); | |
| 2645 va_end(arguments); | |
| 2646 } | |
| 2647 } | |
| 2648 | |
| 2649 | |
| 2650 void HRangeAnalysis::Analyze() { | |
| 2651 HPhase phase("H_Range analysis", graph_); | |
| 2652 Analyze(graph_->entry_block()); | |
| 2653 } | |
| 2654 | |
| 2655 | |
| 2656 void HRangeAnalysis::Analyze(HBasicBlock* block) { | |
| 2657 TraceRange("Analyzing block B%d\n", block->block_id()); | |
| 2658 | |
| 2659 int last_changed_range = changed_ranges_.length() - 1; | |
| 2660 | |
| 2661 // Infer range based on control flow. | |
| 2662 if (block->predecessors()->length() == 1) { | |
| 2663 HBasicBlock* pred = block->predecessors()->first(); | |
| 2664 if (pred->end()->IsCompareIDAndBranch()) { | |
| 2665 InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block); | |
| 2666 } | |
| 2667 } | |
| 2668 | |
| 2669 // Process phi instructions. | |
| 2670 for (int i = 0; i < block->phis()->length(); ++i) { | |
| 2671 HPhi* phi = block->phis()->at(i); | |
| 2672 InferRange(phi); | |
| 2673 } | |
| 2674 | |
| 2675 // Go through all instructions of the current block. | |
| 2676 HInstruction* instr = block->first(); | |
| 2677 while (instr != block->end()) { | |
| 2678 InferRange(instr); | |
| 2679 instr = instr->next(); | |
| 2680 } | |
| 2681 | |
| 2682 // Continue analysis in all dominated blocks. | |
| 2683 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { | |
| 2684 Analyze(block->dominated_blocks()->at(i)); | |
| 2685 } | |
| 2686 | |
| 2687 RollBackTo(last_changed_range); | |
| 2688 } | |
| 2689 | |
| 2690 | |
| 2691 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test, | |
| 2692 HBasicBlock* dest) { | |
| 2693 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); | |
| 2694 if (test->representation().IsSmiOrInteger32()) { | |
| 2695 Token::Value op = test->token(); | |
| 2696 if (test->SecondSuccessor() == dest) { | |
| 2697 op = Token::NegateCompareOp(op); | |
| 2698 } | |
| 2699 Token::Value inverted_op = Token::ReverseCompareOp(op); | |
| 2700 UpdateControlFlowRange(op, test->left(), test->right()); | |
| 2701 UpdateControlFlowRange(inverted_op, test->right(), test->left()); | |
| 2702 } | |
| 2703 } | |
| 2704 | |
| 2705 | |
| 2706 // We know that value [op] other. Use this information to update the range on | |
| 2707 // value. | |
| 2708 void HRangeAnalysis::UpdateControlFlowRange(Token::Value op, | |
| 2709 HValue* value, | |
| 2710 HValue* other) { | |
| 2711 Range temp_range; | |
| 2712 Range* range = other->range() != NULL ? other->range() : &temp_range; | |
| 2713 Range* new_range = NULL; | |
| 2714 | |
| 2715 TraceRange("Control flow range infer %d %s %d\n", | |
| 2716 value->id(), | |
| 2717 Token::Name(op), | |
| 2718 other->id()); | |
| 2719 | |
| 2720 if (op == Token::EQ || op == Token::EQ_STRICT) { | |
| 2721 // The same range has to apply for value. | |
| 2722 new_range = range->Copy(zone_); | |
| 2723 } else if (op == Token::LT || op == Token::LTE) { | |
| 2724 new_range = range->CopyClearLower(zone_); | |
| 2725 if (op == Token::LT) { | |
| 2726 new_range->AddConstant(-1); | |
| 2727 } | |
| 2728 } else if (op == Token::GT || op == Token::GTE) { | |
| 2729 new_range = range->CopyClearUpper(zone_); | |
| 2730 if (op == Token::GT) { | |
| 2731 new_range->AddConstant(1); | |
| 2732 } | |
| 2733 } | |
| 2734 | |
| 2735 if (new_range != NULL && !new_range->IsMostGeneric()) { | |
| 2736 AddRange(value, new_range); | |
| 2737 } | |
| 2738 } | |
| 2739 | |
| 2740 | |
| 2741 void HRangeAnalysis::InferRange(HValue* value) { | |
| 2742 ASSERT(!value->HasRange()); | |
| 2743 if (!value->representation().IsNone()) { | |
| 2744 value->ComputeInitialRange(zone_); | |
| 2745 Range* range = value->range(); | |
| 2746 TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n", | |
| 2747 value->id(), | |
| 2748 value->Mnemonic(), | |
| 2749 range->lower(), | |
| 2750 range->upper()); | |
| 2751 } | |
| 2752 } | |
| 2753 | |
| 2754 | |
| 2755 void HRangeAnalysis::RollBackTo(int index) { | |
| 2756 for (int i = index + 1; i < changed_ranges_.length(); ++i) { | |
| 2757 changed_ranges_[i]->RemoveLastAddedRange(); | |
| 2758 } | |
| 2759 changed_ranges_.Rewind(index + 1); | |
| 2760 } | |
| 2761 | |
| 2762 | |
| 2763 void HRangeAnalysis::AddRange(HValue* value, Range* range) { | |
| 2764 Range* original_range = value->range(); | |
| 2765 value->AddNewRange(range, zone_); | |
| 2766 changed_ranges_.Add(value, zone_); | |
| 2767 Range* new_range = value->range(); | |
| 2768 TraceRange("Updated range of %d set to [%d,%d]\n", | |
| 2769 value->id(), | |
| 2770 new_range->lower(), | |
| 2771 new_range->upper()); | |
| 2772 if (original_range != NULL) { | |
| 2773 TraceRange("Original range was [%d,%d]\n", | |
| 2774 original_range->lower(), | |
| 2775 original_range->upper()); | |
| 2776 } | |
| 2777 TraceRange("New information was [%d,%d]\n", | |
| 2778 range->lower(), | |
| 2779 range->upper()); | |
| 2780 } | |
| 2781 | |
| 2782 | |
| 2783 class HStackCheckEliminator BASE_EMBEDDED { | |
| 2784 public: | |
| 2785 explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { } | |
| 2786 | |
| 2787 void Process(); | |
| 2788 | |
| 2789 private: | |
| 2790 HGraph* graph_; | |
| 2791 }; | |
| 2792 | |
| 2793 | |
| 2794 void HStackCheckEliminator::Process() { | |
| 2795 HPhase phase("H_Stack check elimination", graph_); | |
| 2796 // For each loop block walk the dominator tree from the backwards branch to | |
| 2797 // the loop header. If a call instruction is encountered the backwards branch | |
| 2798 // is dominated by a call and the stack check in the backwards branch can be | |
| 2799 // removed. | |
| 2800 for (int i = 0; i < graph_->blocks()->length(); i++) { | |
| 2801 HBasicBlock* block = graph_->blocks()->at(i); | |
| 2802 if (block->IsLoopHeader()) { | |
| 2803 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge(); | |
| 2804 HBasicBlock* dominator = back_edge; | |
| 2805 while (true) { | |
| 2806 HInstruction* instr = dominator->first(); | |
| 2807 while (instr != NULL) { | |
| 2808 if (instr->IsCall()) { | |
| 2809 block->loop_information()->stack_check()->Eliminate(); | |
| 2810 break; | |
| 2811 } | |
| 2812 instr = instr->next(); | |
| 2813 } | |
| 2814 | |
| 2815 // Done when the loop header is processed. | |
| 2816 if (dominator == block) break; | |
| 2817 | |
| 2818 // Move up the dominator tree. | |
| 2819 dominator = dominator->dominator(); | |
| 2820 } | |
| 2821 } | |
| 2822 } | |
| 2823 } | |
| 2824 | |
| 2825 | |
| 2826 void HInferRepresentation::AddToWorklist(HValue* current) { | |
| 2827 if (current->representation().IsTagged()) return; | |
| 2828 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; | |
| 2829 if (in_worklist_.Contains(current->id())) return; | |
| 2830 worklist_.Add(current, zone()); | |
| 2831 in_worklist_.Add(current->id()); | |
| 2832 } | |
| 2833 | |
| 2834 | |
| 2835 void HInferRepresentation::Analyze() { | |
| 2836 HPhase phase("H_Infer representations", graph_); | |
| 2837 | |
| 2838 // (1) Initialize bit vectors and count real uses. Each phi gets a | |
| 2839 // bit-vector of length <number of phis>. | |
| 2840 const ZoneList<HPhi*>* phi_list = graph_->phi_list(); | |
| 2841 int phi_count = phi_list->length(); | |
| 2842 ZoneList<BitVector*> connected_phis(phi_count, graph_->zone()); | |
| 2843 for (int i = 0; i < phi_count; ++i) { | |
| 2844 phi_list->at(i)->InitRealUses(i); | |
| 2845 BitVector* connected_set = new(zone()) BitVector(phi_count, graph_->zone()); | |
| 2846 connected_set->Add(i); | |
| 2847 connected_phis.Add(connected_set, zone()); | |
| 2848 } | |
| 2849 | |
| 2850 // (2) Do a fixed point iteration to find the set of connected phis. A | |
| 2851 // phi is connected to another phi if its value is used either directly or | |
| 2852 // indirectly through a transitive closure of the def-use relation. | |
| 2853 bool change = true; | |
| 2854 while (change) { | |
| 2855 change = false; | |
| 2856 // We normally have far more "forward edges" than "backward edges", | |
| 2857 // so we terminate faster when we walk backwards. | |
| 2858 for (int i = phi_count - 1; i >= 0; --i) { | |
| 2859 HPhi* phi = phi_list->at(i); | |
| 2860 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { | |
| 2861 HValue* use = it.value(); | |
| 2862 if (use->IsPhi()) { | |
| 2863 int id = HPhi::cast(use)->phi_id(); | |
| 2864 if (connected_phis[i]->UnionIsChanged(*connected_phis[id])) | |
| 2865 change = true; | |
| 2866 } | |
| 2867 } | |
| 2868 } | |
| 2869 } | |
| 2870 | |
| 2871 // Set truncation flags for groups of connected phis. This is a conservative | |
| 2872 // approximation; the flag will be properly re-computed after representations | |
| 2873 // have been determined. | |
| 2874 if (phi_count > 0) { | |
| 2875 BitVector* done = new(zone()) BitVector(phi_count, graph_->zone()); | |
| 2876 for (int i = 0; i < phi_count; ++i) { | |
| 2877 if (done->Contains(i)) continue; | |
| 2878 | |
| 2879 // Check if all uses of all connected phis in this group are truncating. | |
| 2880 bool all_uses_everywhere_truncating = true; | |
| 2881 for (BitVector::Iterator it(connected_phis.at(i)); | |
| 2882 !it.Done(); | |
| 2883 it.Advance()) { | |
| 2884 int index = it.Current(); | |
| 2885 all_uses_everywhere_truncating &= | |
| 2886 phi_list->at(index)->CheckFlag(HInstruction::kTruncatingToInt32); | |
| 2887 done->Add(index); | |
| 2888 } | |
| 2889 if (all_uses_everywhere_truncating) { | |
| 2890 continue; // Great, nothing to do. | |
| 2891 } | |
| 2892 // Clear truncation flag of this group of connected phis. | |
| 2893 for (BitVector::Iterator it(connected_phis.at(i)); | |
| 2894 !it.Done(); | |
| 2895 it.Advance()) { | |
| 2896 int index = it.Current(); | |
| 2897 phi_list->at(index)->ClearFlag(HInstruction::kTruncatingToInt32); | |
| 2898 } | |
| 2899 } | |
| 2900 } | |
| 2901 | |
| 2902 // Simplify constant phi inputs where possible. | |
| 2903 // This step uses kTruncatingToInt32 flags of phis. | |
| 2904 for (int i = 0; i < phi_count; ++i) { | |
| 2905 phi_list->at(i)->SimplifyConstantInputs(); | |
| 2906 } | |
| 2907 | |
| 2908 // Use the phi reachability information from step 2 to | |
| 2909 // sum up the non-phi use counts of all connected phis. | |
| 2910 for (int i = 0; i < phi_count; ++i) { | |
| 2911 HPhi* phi = phi_list->at(i); | |
| 2912 for (BitVector::Iterator it(connected_phis.at(i)); | |
| 2913 !it.Done(); | |
| 2914 it.Advance()) { | |
| 2915 int index = it.Current(); | |
| 2916 HPhi* it_use = phi_list->at(index); | |
| 2917 if (index != i) phi->AddNonPhiUsesFrom(it_use); // Don't count twice. | |
| 2918 } | |
| 2919 } | |
| 2920 | |
| 2921 // Initialize work list | |
| 2922 for (int i = 0; i < graph_->blocks()->length(); ++i) { | |
| 2923 HBasicBlock* block = graph_->blocks()->at(i); | |
| 2924 const ZoneList<HPhi*>* phis = block->phis(); | |
| 2925 for (int j = 0; j < phis->length(); ++j) { | |
| 2926 AddToWorklist(phis->at(j)); | |
| 2927 } | |
| 2928 | |
| 2929 HInstruction* current = block->first(); | |
| 2930 while (current != NULL) { | |
| 2931 AddToWorklist(current); | |
| 2932 current = current->next(); | |
| 2933 } | |
| 2934 } | |
| 2935 | |
| 2936 // Do a fixed point iteration, trying to improve representations | |
| 2937 while (!worklist_.is_empty()) { | |
| 2938 HValue* current = worklist_.RemoveLast(); | |
| 2939 in_worklist_.Remove(current->id()); | |
| 2940 current->InferRepresentation(this); | |
| 2941 } | |
| 2942 | |
| 2943 // Lastly: any instruction that we don't have representation information | |
| 2944 // for defaults to Tagged. | |
| 2945 for (int i = 0; i < graph_->blocks()->length(); ++i) { | |
| 2946 HBasicBlock* block = graph_->blocks()->at(i); | |
| 2947 const ZoneList<HPhi*>* phis = block->phis(); | |
| 2948 for (int j = 0; j < phis->length(); ++j) { | |
| 2949 HPhi* phi = phis->at(j); | |
| 2950 if (phi->representation().IsNone()) { | |
| 2951 phi->ChangeRepresentation(Representation::Tagged()); | |
| 2952 } | |
| 2953 } | |
| 2954 for (HInstruction* current = block->first(); | |
| 2955 current != NULL; current = current->next()) { | |
| 2956 if (current->representation().IsNone() && | |
| 2957 current->CheckFlag(HInstruction::kFlexibleRepresentation)) { | |
| 2958 if (current->CheckFlag(HInstruction::kCannotBeTagged)) { | |
| 2959 current->ChangeRepresentation(Representation::Double()); | |
| 2960 } else { | |
| 2961 current->ChangeRepresentation(Representation::Tagged()); | |
| 2962 } | |
| 2963 } | |
| 2964 } | |
| 2965 } | |
| 2966 } | |
| 2967 | |
| 2968 | |
| 2969 void HGraph::MergeRemovableSimulates() { | 2575 void HGraph::MergeRemovableSimulates() { |
| 2970 HPhase phase("H_Merge removable simulates", this); | 2576 HPhase phase("H_Merge removable simulates", this); |
| 2971 ZoneList<HSimulate*> mergelist(2, zone()); | 2577 ZoneList<HSimulate*> mergelist(2, zone()); |
| 2972 for (int i = 0; i < blocks()->length(); ++i) { | 2578 for (int i = 0; i < blocks()->length(); ++i) { |
| 2973 HBasicBlock* block = blocks()->at(i); | 2579 HBasicBlock* block = blocks()->at(i); |
| 2974 // Make sure the merge list is empty at the start of a block. | 2580 // Make sure the merge list is empty at the start of a block. |
| 2975 ASSERT(mergelist.is_empty()); | 2581 ASSERT(mergelist.is_empty()); |
| 2976 // Nasty heuristic: Never remove the first simulate in a block. This | 2582 // Nasty heuristic: Never remove the first simulate in a block. This |
| 2977 // just so happens to have a beneficial effect on register allocation. | 2583 // just so happens to have a beneficial effect on register allocation. |
| 2978 bool first = true; | 2584 bool first = true; |
| 2979 for (HInstruction* current = block->first(); | 2585 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 2980 current != NULL; current = current->next()) { | 2586 HInstruction* current = it.Current(); |
| 2981 if (current->IsLeaveInlined()) { | 2587 if (current->IsLeaveInlined()) { |
| 2982 // Never fold simulates from inlined environments into simulates | 2588 // Never fold simulates from inlined environments into simulates |
| 2983 // in the outer environment. | 2589 // in the outer environment. |
| 2984 // (Before each HEnterInlined, there is a non-foldable HSimulate | 2590 // (Before each HEnterInlined, there is a non-foldable HSimulate |
| 2985 // anyway, so we get the barrier in the other direction for free.) | 2591 // anyway, so we get the barrier in the other direction for free.) |
| 2986 // Simply remove all accumulated simulates without merging. This | 2592 // Simply remove all accumulated simulates without merging. This |
| 2987 // is safe because simulates after instructions with side effects | 2593 // is safe because simulates after instructions with side effects |
| 2988 // are never added to the merge list. | 2594 // are never added to the merge list. |
| 2989 while (!mergelist.is_empty()) { | 2595 while (!mergelist.is_empty()) { |
| 2990 mergelist.RemoveLast()->DeleteAndReplaceWith(NULL); | 2596 mergelist.RemoveLast()->DeleteAndReplaceWith(NULL); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3022 | 2628 |
| 3023 if (!mergelist.is_empty()) { | 2629 if (!mergelist.is_empty()) { |
| 3024 // Merge the accumulated simulates at the end of the block. | 2630 // Merge the accumulated simulates at the end of the block. |
| 3025 HSimulate* last = mergelist.RemoveLast(); | 2631 HSimulate* last = mergelist.RemoveLast(); |
| 3026 last->MergeWith(&mergelist); | 2632 last->MergeWith(&mergelist); |
| 3027 } | 2633 } |
| 3028 } | 2634 } |
| 3029 } | 2635 } |
| 3030 | 2636 |
| 3031 | 2637 |
| 3032 void HGraph::InitializeInferredTypes() { | |
| 3033 HPhase phase("H_Inferring types", this); | |
| 3034 InitializeInferredTypes(0, this->blocks_.length() - 1); | |
| 3035 } | |
| 3036 | |
| 3037 | |
| 3038 void HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) { | |
| 3039 for (int i = from_inclusive; i <= to_inclusive; ++i) { | |
| 3040 HBasicBlock* block = blocks_[i]; | |
| 3041 | |
| 3042 const ZoneList<HPhi*>* phis = block->phis(); | |
| 3043 for (int j = 0; j < phis->length(); j++) { | |
| 3044 phis->at(j)->UpdateInferredType(); | |
| 3045 } | |
| 3046 | |
| 3047 HInstruction* current = block->first(); | |
| 3048 while (current != NULL) { | |
| 3049 current->UpdateInferredType(); | |
| 3050 current = current->next(); | |
| 3051 } | |
| 3052 | |
| 3053 if (block->IsLoopHeader()) { | |
| 3054 HBasicBlock* last_back_edge = | |
| 3055 block->loop_information()->GetLastBackEdge(); | |
| 3056 InitializeInferredTypes(i + 1, last_back_edge->block_id()); | |
| 3057 // Skip all blocks already processed by the recursive call. | |
| 3058 i = last_back_edge->block_id(); | |
| 3059 // Update phis of the loop header now after the whole loop body is | |
| 3060 // guaranteed to be processed. | |
| 3061 ZoneList<HValue*> worklist(block->phis()->length(), zone()); | |
| 3062 for (int j = 0; j < block->phis()->length(); ++j) { | |
| 3063 worklist.Add(block->phis()->at(j), zone()); | |
| 3064 } | |
| 3065 InferTypes(&worklist); | |
| 3066 } | |
| 3067 } | |
| 3068 } | |
| 3069 | |
| 3070 | |
| 3071 void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) { | 2638 void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) { |
| 3072 HValue* current = value; | 2639 HValue* current = value; |
| 3073 while (current != NULL) { | 2640 while (current != NULL) { |
| 3074 if (visited->Contains(current->id())) return; | 2641 if (visited->Contains(current->id())) return; |
| 3075 | 2642 |
| 3076 // For phis, we must propagate the check to all of its inputs. | 2643 // For phis, we must propagate the check to all of its inputs. |
| 3077 if (current->IsPhi()) { | 2644 if (current->IsPhi()) { |
| 3078 visited->Add(current->id()); | 2645 visited->Add(current->id()); |
| 3079 HPhi* phi = HPhi::cast(current); | 2646 HPhi* phi = HPhi::cast(current); |
| 3080 for (int i = 0; i < phi->OperandCount(); ++i) { | 2647 for (int i = 0; i < phi->OperandCount(); ++i) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3100 visited->Add(minmax->id()); | 2667 visited->Add(minmax->id()); |
| 3101 PropagateMinusZeroChecks(minmax->left(), visited); | 2668 PropagateMinusZeroChecks(minmax->left(), visited); |
| 3102 PropagateMinusZeroChecks(minmax->right(), visited); | 2669 PropagateMinusZeroChecks(minmax->right(), visited); |
| 3103 } | 2670 } |
| 3104 | 2671 |
| 3105 current = current->EnsureAndPropagateNotMinusZero(visited); | 2672 current = current->EnsureAndPropagateNotMinusZero(visited); |
| 3106 } | 2673 } |
| 3107 } | 2674 } |
| 3108 | 2675 |
| 3109 | 2676 |
| 3110 void HGraph::InsertRepresentationChangeForUse(HValue* value, | |
| 3111 HValue* use_value, | |
| 3112 int use_index, | |
| 3113 Representation to) { | |
| 3114 // Insert the representation change right before its use. For phi-uses we | |
| 3115 // insert at the end of the corresponding predecessor. | |
| 3116 HInstruction* next = NULL; | |
| 3117 if (use_value->IsPhi()) { | |
| 3118 next = use_value->block()->predecessors()->at(use_index)->end(); | |
| 3119 } else { | |
| 3120 next = HInstruction::cast(use_value); | |
| 3121 } | |
| 3122 // For constants we try to make the representation change at compile | |
| 3123 // time. When a representation change is not possible without loss of | |
| 3124 // information we treat constants like normal instructions and insert the | |
| 3125 // change instructions for them. | |
| 3126 HInstruction* new_value = NULL; | |
| 3127 bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); | |
| 3128 bool allow_undefined_as_nan = | |
| 3129 use_value->CheckFlag(HValue::kAllowUndefinedAsNaN); | |
| 3130 if (value->IsConstant()) { | |
| 3131 HConstant* constant = HConstant::cast(value); | |
| 3132 // Try to create a new copy of the constant with the new representation. | |
| 3133 new_value = (is_truncating && to.IsInteger32()) | |
| 3134 ? constant->CopyToTruncatedInt32(zone()) | |
| 3135 : constant->CopyToRepresentation(to, zone()); | |
| 3136 } | |
| 3137 | |
| 3138 if (new_value == NULL) { | |
| 3139 new_value = new(zone()) HChange(value, to, | |
| 3140 is_truncating, allow_undefined_as_nan); | |
| 3141 } | |
| 3142 | |
| 3143 new_value->InsertBefore(next); | |
| 3144 use_value->SetOperandAt(use_index, new_value); | |
| 3145 } | |
| 3146 | |
| 3147 | |
| 3148 void HGraph::InsertRepresentationChangesForValue(HValue* value) { | |
| 3149 Representation r = value->representation(); | |
| 3150 if (r.IsNone()) return; | |
| 3151 if (value->HasNoUses()) return; | |
| 3152 | |
| 3153 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { | |
| 3154 HValue* use_value = it.value(); | |
| 3155 int use_index = it.index(); | |
| 3156 Representation req = use_value->RequiredInputRepresentation(use_index); | |
| 3157 if (req.IsNone() || req.Equals(r)) continue; | |
| 3158 InsertRepresentationChangeForUse(value, use_value, use_index, req); | |
| 3159 } | |
| 3160 if (value->HasNoUses()) { | |
| 3161 ASSERT(value->IsConstant()); | |
| 3162 value->DeleteAndReplaceWith(NULL); | |
| 3163 } | |
| 3164 | |
| 3165 // The only purpose of a HForceRepresentation is to represent the value | |
| 3166 // after the (possible) HChange instruction. We make it disappear. | |
| 3167 if (value->IsForceRepresentation()) { | |
| 3168 value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value()); | |
| 3169 } | |
| 3170 } | |
| 3171 | |
| 3172 | |
| 3173 void HGraph::InsertRepresentationChanges() { | |
| 3174 HPhase phase("H_Representation changes", this); | |
| 3175 | |
| 3176 // Compute truncation flag for phis: Initially assume that all | |
| 3177 // int32-phis allow truncation and iteratively remove the ones that | |
| 3178 // are used in an operation that does not allow a truncating | |
| 3179 // conversion. | |
| 3180 ZoneList<HPhi*> worklist(8, zone()); | |
| 3181 | |
| 3182 for (int i = 0; i < phi_list()->length(); i++) { | |
| 3183 HPhi* phi = phi_list()->at(i); | |
| 3184 if (phi->representation().IsInteger32()) { | |
| 3185 phi->SetFlag(HValue::kTruncatingToInt32); | |
| 3186 } | |
| 3187 } | |
| 3188 | |
| 3189 for (int i = 0; i < phi_list()->length(); i++) { | |
| 3190 HPhi* phi = phi_list()->at(i); | |
| 3191 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { | |
| 3192 // If a Phi is used as a non-truncating int32 or as a double, | |
| 3193 // clear its "truncating" flag. | |
| 3194 HValue* use = it.value(); | |
| 3195 Representation input_representation = | |
| 3196 use->RequiredInputRepresentation(it.index()); | |
| 3197 if (!input_representation.IsInteger32() || | |
| 3198 !use->CheckFlag(HValue::kTruncatingToInt32)) { | |
| 3199 if (FLAG_trace_representation) { | |
| 3200 PrintF("#%d Phi is not truncating because of #%d %s\n", | |
| 3201 phi->id(), it.value()->id(), it.value()->Mnemonic()); | |
| 3202 } | |
| 3203 phi->ClearFlag(HValue::kTruncatingToInt32); | |
| 3204 worklist.Add(phi, zone()); | |
| 3205 break; | |
| 3206 } | |
| 3207 } | |
| 3208 } | |
| 3209 | |
| 3210 while (!worklist.is_empty()) { | |
| 3211 HPhi* current = worklist.RemoveLast(); | |
| 3212 for (int i = 0; i < current->OperandCount(); ++i) { | |
| 3213 HValue* input = current->OperandAt(i); | |
| 3214 if (input->IsPhi() && | |
| 3215 input->representation().IsInteger32() && | |
| 3216 input->CheckFlag(HValue::kTruncatingToInt32)) { | |
| 3217 if (FLAG_trace_representation) { | |
| 3218 PrintF("#%d Phi is not truncating because of #%d %s\n", | |
| 3219 input->id(), current->id(), current->Mnemonic()); | |
| 3220 } | |
| 3221 input->ClearFlag(HValue::kTruncatingToInt32); | |
| 3222 worklist.Add(HPhi::cast(input), zone()); | |
| 3223 } | |
| 3224 } | |
| 3225 } | |
| 3226 | |
| 3227 for (int i = 0; i < blocks_.length(); ++i) { | |
| 3228 // Process phi instructions first. | |
| 3229 const ZoneList<HPhi*>* phis = blocks_[i]->phis(); | |
| 3230 for (int j = 0; j < phis->length(); j++) { | |
| 3231 InsertRepresentationChangesForValue(phis->at(j)); | |
| 3232 } | |
| 3233 | |
| 3234 // Process normal instructions. | |
| 3235 HInstruction* current = blocks_[i]->first(); | |
| 3236 while (current != NULL) { | |
| 3237 HInstruction* next = current->next(); | |
| 3238 InsertRepresentationChangesForValue(current); | |
| 3239 current = next; | |
| 3240 } | |
| 3241 } | |
| 3242 } | |
| 3243 | |
| 3244 | |
| 3245 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { | 2677 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { |
| 3246 if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return; | 2678 if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return; |
| 3247 phi->ClearFlag(HValue::kAllowUndefinedAsNaN); | 2679 phi->ClearFlag(HValue::kAllowUndefinedAsNaN); |
| 3248 for (int i = 0; i < phi->OperandCount(); ++i) { | 2680 for (int i = 0; i < phi->OperandCount(); ++i) { |
| 3249 HValue* input = phi->OperandAt(i); | 2681 HValue* input = phi->OperandAt(i); |
| 3250 if (input->IsPhi()) { | 2682 if (input->IsPhi()) { |
| 3251 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input)); | 2683 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input)); |
| 3252 } | 2684 } |
| 3253 } | 2685 } |
| 3254 } | 2686 } |
| 3255 | 2687 |
| 3256 | 2688 |
| 3257 void HGraph::MarkDeoptimizeOnUndefined() { | 2689 void HGraph::MarkDeoptimizeOnUndefined() { |
| 3258 HPhase phase("H_MarkDeoptimizeOnUndefined", this); | 2690 HPhase phase("H_MarkDeoptimizeOnUndefined", this); |
| 3259 // Compute DeoptimizeOnUndefined flag for phis. | 2691 // Compute DeoptimizeOnUndefined flag for phis. Any phi that can reach a use |
| 3260 // Any phi that can reach a use with DeoptimizeOnUndefined set must | 2692 // with DeoptimizeOnUndefined set must have DeoptimizeOnUndefined set. |
| 3261 // have DeoptimizeOnUndefined set. Currently only HCompareIDAndBranch, with | 2693 // Currently only HCompareNumericAndBranch, with double input representation, |
| 3262 // double input representation, has this flag set. | 2694 // has this flag set. The flag is used by HChange tagged->double, which must |
| 3263 // The flag is used by HChange tagged->double, which must deoptimize | 2695 // deoptimize if one of its uses has this flag set. |
| 3264 // if one of its uses has this flag set. | |
| 3265 for (int i = 0; i < phi_list()->length(); i++) { | 2696 for (int i = 0; i < phi_list()->length(); i++) { |
| 3266 HPhi* phi = phi_list()->at(i); | 2697 HPhi* phi = phi_list()->at(i); |
| 3267 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { | 2698 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
| 3268 HValue* use_value = it.value(); | 2699 HValue* use_value = it.value(); |
| 3269 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) { | 2700 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) { |
| 3270 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); | 2701 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); |
| 3271 break; | 2702 break; |
| 3272 } | 2703 } |
| 3273 } | 2704 } |
| 3274 } | 2705 } |
| 3275 } | 2706 } |
| 3276 | 2707 |
| 3277 | 2708 |
| 3278 // Discover instructions that can be marked with kUint32 flag allowing | |
| 3279 // them to produce full range uint32 values. | |
| 3280 class Uint32Analysis BASE_EMBEDDED { | |
| 3281 public: | |
| 3282 explicit Uint32Analysis(Zone* zone) : zone_(zone), phis_(4, zone) { } | |
| 3283 | |
| 3284 void Analyze(HInstruction* current); | |
| 3285 | |
| 3286 void UnmarkUnsafePhis(); | |
| 3287 | |
| 3288 private: | |
| 3289 bool IsSafeUint32Use(HValue* val, HValue* use); | |
| 3290 bool Uint32UsesAreSafe(HValue* uint32val); | |
| 3291 bool CheckPhiOperands(HPhi* phi); | |
| 3292 void UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist); | |
| 3293 | |
| 3294 Zone* zone_; | |
| 3295 ZoneList<HPhi*> phis_; | |
| 3296 }; | |
| 3297 | |
| 3298 | |
| 3299 bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) { | |
| 3300 // Operations that operatate on bits are safe. | |
| 3301 if (use->IsBitwise() || | |
| 3302 use->IsShl() || | |
| 3303 use->IsSar() || | |
| 3304 use->IsShr() || | |
| 3305 use->IsBitNot()) { | |
| 3306 return true; | |
| 3307 } else if (use->IsChange() || use->IsSimulate()) { | |
| 3308 // Conversions and deoptimization have special support for unt32. | |
| 3309 return true; | |
| 3310 } else if (use->IsStoreKeyed()) { | |
| 3311 HStoreKeyed* store = HStoreKeyed::cast(use); | |
| 3312 if (store->is_external()) { | |
| 3313 // Storing a value into an external integer array is a bit level | |
| 3314 // operation. | |
| 3315 if (store->value() == val) { | |
| 3316 // Clamping or a conversion to double should have beed inserted. | |
| 3317 ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS); | |
| 3318 ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS); | |
| 3319 ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS); | |
| 3320 return true; | |
| 3321 } | |
| 3322 } | |
| 3323 } | |
| 3324 | |
| 3325 return false; | |
| 3326 } | |
| 3327 | |
| 3328 | |
| 3329 // Iterate over all uses and verify that they are uint32 safe: either don't | |
| 3330 // distinguish between int32 and uint32 due to their bitwise nature or | |
| 3331 // have special support for uint32 values. | |
| 3332 // Encountered phis are optimisitically treated as safe uint32 uses, | |
| 3333 // marked with kUint32 flag and collected in the phis_ list. A separate | |
| 3334 // path will be performed later by UnmarkUnsafePhis to clear kUint32 from | |
| 3335 // phis that are not actually uint32-safe (it requries fix point iteration). | |
| 3336 bool Uint32Analysis::Uint32UsesAreSafe(HValue* uint32val) { | |
| 3337 bool collect_phi_uses = false; | |
| 3338 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) { | |
| 3339 HValue* use = it.value(); | |
| 3340 | |
| 3341 if (use->IsPhi()) { | |
| 3342 if (!use->CheckFlag(HInstruction::kUint32)) { | |
| 3343 // There is a phi use of this value from a phis that is not yet | |
| 3344 // collected in phis_ array. Separate pass is required. | |
| 3345 collect_phi_uses = true; | |
| 3346 } | |
| 3347 | |
| 3348 // Optimistically treat phis as uint32 safe. | |
| 3349 continue; | |
| 3350 } | |
| 3351 | |
| 3352 if (!IsSafeUint32Use(uint32val, use)) { | |
| 3353 return false; | |
| 3354 } | |
| 3355 } | |
| 3356 | |
| 3357 if (collect_phi_uses) { | |
| 3358 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) { | |
| 3359 HValue* use = it.value(); | |
| 3360 | |
| 3361 // There is a phi use of this value from a phis that is not yet | |
| 3362 // collected in phis_ array. Separate pass is required. | |
| 3363 if (use->IsPhi() && !use->CheckFlag(HInstruction::kUint32)) { | |
| 3364 use->SetFlag(HInstruction::kUint32); | |
| 3365 phis_.Add(HPhi::cast(use), zone_); | |
| 3366 } | |
| 3367 } | |
| 3368 } | |
| 3369 | |
| 3370 return true; | |
| 3371 } | |
| 3372 | |
| 3373 | |
| 3374 // Analyze instruction and mark it with kUint32 if all its uses are uint32 | |
| 3375 // safe. | |
| 3376 void Uint32Analysis::Analyze(HInstruction* current) { | |
| 3377 if (Uint32UsesAreSafe(current)) current->SetFlag(HInstruction::kUint32); | |
| 3378 } | |
| 3379 | |
| 3380 | |
| 3381 // Check if all operands to the given phi are marked with kUint32 flag. | |
| 3382 bool Uint32Analysis::CheckPhiOperands(HPhi* phi) { | |
| 3383 if (!phi->CheckFlag(HInstruction::kUint32)) { | |
| 3384 // This phi is not uint32 safe. No need to check operands. | |
| 3385 return false; | |
| 3386 } | |
| 3387 | |
| 3388 for (int j = 0; j < phi->OperandCount(); j++) { | |
| 3389 HValue* operand = phi->OperandAt(j); | |
| 3390 if (!operand->CheckFlag(HInstruction::kUint32)) { | |
| 3391 // Lazyly mark constants that fit into uint32 range with kUint32 flag. | |
| 3392 if (operand->IsInteger32Constant() && | |
| 3393 operand->GetInteger32Constant() >= 0) { | |
| 3394 operand->SetFlag(HInstruction::kUint32); | |
| 3395 continue; | |
| 3396 } | |
| 3397 | |
| 3398 // This phi is not safe, some operands are not uint32 values. | |
| 3399 return false; | |
| 3400 } | |
| 3401 } | |
| 3402 | |
| 3403 return true; | |
| 3404 } | |
| 3405 | |
| 3406 | |
| 3407 // Remove kUint32 flag from the phi itself and its operands. If any operand | |
| 3408 // was a phi marked with kUint32 place it into a worklist for | |
| 3409 // transitive clearing of kUint32 flag. | |
| 3410 void Uint32Analysis::UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist) { | |
| 3411 phi->ClearFlag(HInstruction::kUint32); | |
| 3412 for (int j = 0; j < phi->OperandCount(); j++) { | |
| 3413 HValue* operand = phi->OperandAt(j); | |
| 3414 if (operand->CheckFlag(HInstruction::kUint32)) { | |
| 3415 operand->ClearFlag(HInstruction::kUint32); | |
| 3416 if (operand->IsPhi()) { | |
| 3417 worklist->Add(HPhi::cast(operand), zone_); | |
| 3418 } | |
| 3419 } | |
| 3420 } | |
| 3421 } | |
| 3422 | |
| 3423 | |
| 3424 void Uint32Analysis::UnmarkUnsafePhis() { | |
| 3425 // No phis were collected. Nothing to do. | |
| 3426 if (phis_.length() == 0) return; | |
| 3427 | |
| 3428 // Worklist used to transitively clear kUint32 from phis that | |
| 3429 // are used as arguments to other phis. | |
| 3430 ZoneList<HPhi*> worklist(phis_.length(), zone_); | |
| 3431 | |
| 3432 // Phi can be used as a uint32 value if and only if | |
| 3433 // all its operands are uint32 values and all its | |
| 3434 // uses are uint32 safe. | |
| 3435 | |
| 3436 // Iterate over collected phis and unmark those that | |
| 3437 // are unsafe. When unmarking phi unmark its operands | |
| 3438 // and add it to the worklist if it is a phi as well. | |
| 3439 // Phis that are still marked as safe are shifted down | |
| 3440 // so that all safe phis form a prefix of the phis_ array. | |
| 3441 int phi_count = 0; | |
| 3442 for (int i = 0; i < phis_.length(); i++) { | |
| 3443 HPhi* phi = phis_[i]; | |
| 3444 | |
| 3445 if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) { | |
| 3446 phis_[phi_count++] = phi; | |
| 3447 } else { | |
| 3448 UnmarkPhi(phi, &worklist); | |
| 3449 } | |
| 3450 } | |
| 3451 | |
| 3452 // Now phis array contains only those phis that have safe | |
| 3453 // non-phi uses. Start transitively clearing kUint32 flag | |
| 3454 // from phi operands of discovered non-safe phies until | |
| 3455 // only safe phies are left. | |
| 3456 while (!worklist.is_empty()) { | |
| 3457 while (!worklist.is_empty()) { | |
| 3458 HPhi* phi = worklist.RemoveLast(); | |
| 3459 UnmarkPhi(phi, &worklist); | |
| 3460 } | |
| 3461 | |
| 3462 // Check if any operands to safe phies were unmarked | |
| 3463 // turning a safe phi into unsafe. The same value | |
| 3464 // can flow into several phis. | |
| 3465 int new_phi_count = 0; | |
| 3466 for (int i = 0; i < phi_count; i++) { | |
| 3467 HPhi* phi = phis_[i]; | |
| 3468 | |
| 3469 if (CheckPhiOperands(phi)) { | |
| 3470 phis_[new_phi_count++] = phi; | |
| 3471 } else { | |
| 3472 UnmarkPhi(phi, &worklist); | |
| 3473 } | |
| 3474 } | |
| 3475 phi_count = new_phi_count; | |
| 3476 } | |
| 3477 } | |
| 3478 | |
| 3479 | |
| 3480 void HGraph::ComputeSafeUint32Operations() { | |
| 3481 HPhase phase("H_Compute safe UInt32 operations", this); | |
| 3482 if (uint32_instructions_ == NULL) return; | |
| 3483 | |
| 3484 Uint32Analysis analysis(zone()); | |
| 3485 for (int i = 0; i < uint32_instructions_->length(); ++i) { | |
| 3486 HInstruction* current = uint32_instructions_->at(i); | |
| 3487 if (current->IsLinked() && current->representation().IsInteger32()) { | |
| 3488 analysis.Analyze(current); | |
| 3489 } | |
| 3490 } | |
| 3491 | |
| 3492 // Some phis might have been optimistically marked with kUint32 flag. | |
| 3493 // Remove this flag from those phis that are unsafe and propagate | |
| 3494 // this information transitively potentially clearing kUint32 flag | |
| 3495 // from some non-phi operations that are used as operands to unsafe phis. | |
| 3496 analysis.UnmarkUnsafePhis(); | |
| 3497 } | |
| 3498 | |
| 3499 | |
| 3500 void HGraph::ComputeMinusZeroChecks() { | 2709 void HGraph::ComputeMinusZeroChecks() { |
| 3501 HPhase phase("H_Compute minus zero checks", this); | 2710 HPhase phase("H_Compute minus zero checks", this); |
| 3502 BitVector visited(GetMaximumValueID(), zone()); | 2711 BitVector visited(GetMaximumValueID(), zone()); |
| 3503 for (int i = 0; i < blocks_.length(); ++i) { | 2712 for (int i = 0; i < blocks_.length(); ++i) { |
| 3504 for (HInstruction* current = blocks_[i]->first(); | 2713 for (HInstructionIterator it(blocks_[i]); !it.Done(); it.Advance()) { |
| 3505 current != NULL; | 2714 HInstruction* current = it.Current(); |
| 3506 current = current->next()) { | |
| 3507 if (current->IsChange()) { | 2715 if (current->IsChange()) { |
| 3508 HChange* change = HChange::cast(current); | 2716 HChange* change = HChange::cast(current); |
| 3509 // Propagate flags for negative zero checks upwards from conversions | 2717 // Propagate flags for negative zero checks upwards from conversions |
| 3510 // int32-to-tagged and int32-to-double. | 2718 // int32-to-tagged and int32-to-double. |
| 3511 Representation from = change->value()->representation(); | 2719 Representation from = change->value()->representation(); |
| 3512 ASSERT(from.Equals(change->from())); | 2720 ASSERT(from.Equals(change->from())); |
| 3513 if (from.IsInteger32()) { | 2721 if (from.IsInteger32()) { |
| 3514 ASSERT(change->to().IsTagged() || | 2722 ASSERT(change->to().IsTagged() || |
| 3515 change->to().IsDouble() || | 2723 change->to().IsDouble() || |
| 3516 change->to().IsSmi()); | 2724 change->to().IsSmi()); |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3778 builder->current_block()->Goto(if_true(), builder->function_state()); | 2986 builder->current_block()->Goto(if_true(), builder->function_state()); |
| 3779 } else { | 2987 } else { |
| 3780 builder->current_block()->Goto(if_false(), builder->function_state()); | 2988 builder->current_block()->Goto(if_false(), builder->function_state()); |
| 3781 } | 2989 } |
| 3782 builder->set_current_block(NULL); | 2990 builder->set_current_block(NULL); |
| 3783 return; | 2991 return; |
| 3784 } | 2992 } |
| 3785 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | 2993 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
| 3786 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | 2994 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
| 3787 ToBooleanStub::Types expected(condition()->to_boolean_types()); | 2995 ToBooleanStub::Types expected(condition()->to_boolean_types()); |
| 3788 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); | 2996 HBranch* test = new(zone()) HBranch(value, expected, empty_true, empty_false); |
| 3789 builder->current_block()->Finish(test); | 2997 builder->current_block()->Finish(test); |
| 3790 | 2998 |
| 3791 empty_true->Goto(if_true(), builder->function_state()); | 2999 empty_true->Goto(if_true(), builder->function_state()); |
| 3792 empty_false->Goto(if_false(), builder->function_state()); | 3000 empty_false->Goto(if_false(), builder->function_state()); |
| 3793 builder->set_current_block(NULL); | 3001 builder->set_current_block(NULL); |
| 3794 } | 3002 } |
| 3795 | 3003 |
| 3796 | 3004 |
| 3797 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. | 3005 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. |
| 3798 #define CHECK_BAILOUT(call) \ | 3006 #define CHECK_BAILOUT(call) \ |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3846 void HOptimizedGraphBuilder::VisitForControl(Expression* expr, | 3054 void HOptimizedGraphBuilder::VisitForControl(Expression* expr, |
| 3847 HBasicBlock* true_block, | 3055 HBasicBlock* true_block, |
| 3848 HBasicBlock* false_block) { | 3056 HBasicBlock* false_block) { |
| 3849 TestContext for_test(this, expr, true_block, false_block); | 3057 TestContext for_test(this, expr, true_block, false_block); |
| 3850 Visit(expr); | 3058 Visit(expr); |
| 3851 } | 3059 } |
| 3852 | 3060 |
| 3853 | 3061 |
| 3854 void HOptimizedGraphBuilder::VisitArgument(Expression* expr) { | 3062 void HOptimizedGraphBuilder::VisitArgument(Expression* expr) { |
| 3855 CHECK_ALIVE(VisitForValue(expr)); | 3063 CHECK_ALIVE(VisitForValue(expr)); |
| 3856 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); | 3064 Push(Add<HPushArgument>(Pop())); |
| 3857 } | 3065 } |
| 3858 | 3066 |
| 3859 | 3067 |
| 3860 void HOptimizedGraphBuilder::VisitArgumentList( | 3068 void HOptimizedGraphBuilder::VisitArgumentList( |
| 3861 ZoneList<Expression*>* arguments) { | 3069 ZoneList<Expression*>* arguments) { |
| 3862 for (int i = 0; i < arguments->length(); i++) { | 3070 for (int i = 0; i < arguments->length(); i++) { |
| 3863 CHECK_ALIVE(VisitArgument(arguments->at(i))); | 3071 CHECK_ALIVE(VisitArgument(arguments->at(i))); |
| 3864 } | 3072 } |
| 3865 } | 3073 } |
| 3866 | 3074 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3912 | 3120 |
| 3913 // Handle implicit declaration of the function name in named function | 3121 // Handle implicit declaration of the function name in named function |
| 3914 // expressions before other declarations. | 3122 // expressions before other declarations. |
| 3915 if (scope->is_function_scope() && scope->function() != NULL) { | 3123 if (scope->is_function_scope() && scope->function() != NULL) { |
| 3916 VisitVariableDeclaration(scope->function()); | 3124 VisitVariableDeclaration(scope->function()); |
| 3917 } | 3125 } |
| 3918 VisitDeclarations(scope->declarations()); | 3126 VisitDeclarations(scope->declarations()); |
| 3919 AddSimulate(BailoutId::Declarations()); | 3127 AddSimulate(BailoutId::Declarations()); |
| 3920 | 3128 |
| 3921 HValue* context = environment()->LookupContext(); | 3129 HValue* context = environment()->LookupContext(); |
| 3922 AddInstruction( | 3130 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); |
| 3923 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); | |
| 3924 | 3131 |
| 3925 VisitStatements(current_info()->function()->body()); | 3132 VisitStatements(current_info()->function()->body()); |
| 3926 if (HasStackOverflow()) return false; | 3133 if (HasStackOverflow()) return false; |
| 3927 | 3134 |
| 3928 if (current_block() != NULL) { | 3135 if (current_block() != NULL) { |
| 3929 AddReturn(graph()->GetConstantUndefined()); | 3136 AddReturn(graph()->GetConstantUndefined()); |
| 3930 set_current_block(NULL); | 3137 set_current_block(NULL); |
| 3931 } | 3138 } |
| 3932 | 3139 |
| 3933 // If the checksum of the number of type info changes is the same as the | 3140 // If the checksum of the number of type info changes is the same as the |
| 3934 // last time this function was compiled, then this recompile is likely not | 3141 // last time this function was compiled, then this recompile is likely not |
| 3935 // due to missing/inadequate type feedback, but rather too aggressive | 3142 // due to missing/inadequate type feedback, but rather too aggressive |
| 3936 // optimization. Disable optimistic LICM in that case. | 3143 // optimization. Disable optimistic LICM in that case. |
| 3937 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); | 3144 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); |
| 3938 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 3145 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 3939 Handle<TypeFeedbackInfo> type_info( | 3146 Handle<TypeFeedbackInfo> type_info( |
| 3940 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | 3147 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); |
| 3941 int checksum = type_info->own_type_change_checksum(); | 3148 int checksum = type_info->own_type_change_checksum(); |
| 3942 int composite_checksum = graph()->update_type_change_checksum(checksum); | 3149 int composite_checksum = graph()->update_type_change_checksum(checksum); |
| 3943 graph()->set_use_optimistic_licm( | 3150 graph()->set_use_optimistic_licm( |
| 3944 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | 3151 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
| 3945 type_info->set_inlined_type_change_checksum(composite_checksum); | 3152 type_info->set_inlined_type_change_checksum(composite_checksum); |
| 3946 | 3153 |
| 3154 // Perform any necessary OSR-specific cleanups or changes to the graph. |
| 3155 osr_->FinishGraph(); |
| 3156 |
| 3947 return true; | 3157 return true; |
| 3948 } | 3158 } |
| 3949 | 3159 |
| 3950 | 3160 |
| 3951 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { | 3161 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { |
| 3952 *bailout_reason = SmartArrayPointer<char>(); | 3162 *bailout_reason = SmartArrayPointer<char>(); |
| 3953 OrderBlocks(); | 3163 OrderBlocks(); |
| 3954 AssignDominators(); | 3164 AssignDominators(); |
| 3955 | 3165 |
| 3956 // We need to create a HConstant "zero" now so that GVN will fold every | 3166 // We need to create a HConstant "zero" now so that GVN will fold every |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3967 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) { | 3177 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) { |
| 3968 Run<HEnvironmentLivenessAnalysisPhase>(); | 3178 Run<HEnvironmentLivenessAnalysisPhase>(); |
| 3969 } | 3179 } |
| 3970 | 3180 |
| 3971 PropagateDeoptimizingMark(); | 3181 PropagateDeoptimizingMark(); |
| 3972 if (!CheckConstPhiUses()) { | 3182 if (!CheckConstPhiUses()) { |
| 3973 *bailout_reason = SmartArrayPointer<char>(StrDup( | 3183 *bailout_reason = SmartArrayPointer<char>(StrDup( |
| 3974 "Unsupported phi use of const variable")); | 3184 "Unsupported phi use of const variable")); |
| 3975 return false; | 3185 return false; |
| 3976 } | 3186 } |
| 3977 EliminateRedundantPhis(); | 3187 Run<HRedundantPhiEliminationPhase>(); |
| 3978 if (!CheckArgumentsPhiUses()) { | 3188 if (!CheckArgumentsPhiUses()) { |
| 3979 *bailout_reason = SmartArrayPointer<char>(StrDup( | 3189 *bailout_reason = SmartArrayPointer<char>(StrDup( |
| 3980 "Unsupported phi use of arguments")); | 3190 "Unsupported phi use of arguments")); |
| 3981 return false; | 3191 return false; |
| 3982 } | 3192 } |
| 3983 | 3193 |
| 3984 // Remove dead code and phis | 3194 // Remove dead code and phis |
| 3985 if (FLAG_dead_code_elimination) { | 3195 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
| 3986 DeadCodeElimination("H_Eliminate early dead code"); | |
| 3987 } | |
| 3988 CollectPhis(); | 3196 CollectPhis(); |
| 3989 | 3197 |
| 3990 if (has_osr_loop_entry()) { | 3198 if (has_osr()) osr()->FinishOsrValues(); |
| 3991 const ZoneList<HPhi*>* phis = osr_loop_entry()->phis(); | |
| 3992 for (int j = 0; j < phis->length(); j++) { | |
| 3993 HPhi* phi = phis->at(j); | |
| 3994 osr_values()->at(phi->merged_index())->set_incoming_value(phi); | |
| 3995 } | |
| 3996 } | |
| 3997 | 3199 |
| 3998 HInferRepresentation rep(this); | 3200 Run<HInferRepresentationPhase>(); |
| 3999 rep.Analyze(); | |
| 4000 | 3201 |
| 4001 // Remove HSimulate instructions that have turned out not to be needed | 3202 // Remove HSimulate instructions that have turned out not to be needed |
| 4002 // after all by folding them into the following HSimulate. | 3203 // after all by folding them into the following HSimulate. |
| 4003 // This must happen after inferring representations. | 3204 // This must happen after inferring representations. |
| 4004 MergeRemovableSimulates(); | 3205 MergeRemovableSimulates(); |
| 4005 | 3206 |
| 4006 MarkDeoptimizeOnUndefined(); | 3207 MarkDeoptimizeOnUndefined(); |
| 4007 InsertRepresentationChanges(); | 3208 Run<HRepresentationChangesPhase>(); |
| 4008 | 3209 |
| 4009 InitializeInferredTypes(); | 3210 Run<HInferTypesPhase>(); |
| 4010 | 3211 |
| 4011 // Must be performed before canonicalization to ensure that Canonicalize | 3212 // Must be performed before canonicalization to ensure that Canonicalize |
| 4012 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with | 3213 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with |
| 4013 // zero. | 3214 // zero. |
| 4014 if (FLAG_opt_safe_uint32_operations) ComputeSafeUint32Operations(); | 3215 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); |
| 4015 | 3216 |
| 4016 if (FLAG_use_canonicalizing) Canonicalize(); | 3217 if (FLAG_use_canonicalizing) Canonicalize(); |
| 4017 | 3218 |
| 3219 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); |
| 3220 |
| 4018 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); | 3221 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); |
| 4019 | 3222 |
| 4020 if (FLAG_use_range) { | 3223 if (FLAG_use_range) Run<HRangeAnalysisPhase>(); |
| 4021 HRangeAnalysis rangeAnalysis(this); | 3224 |
| 4022 rangeAnalysis.Analyze(); | |
| 4023 } | |
| 4024 ComputeMinusZeroChecks(); | 3225 ComputeMinusZeroChecks(); |
| 4025 | 3226 |
| 4026 // Eliminate redundant stack checks on backwards branches. | 3227 // Eliminate redundant stack checks on backwards branches. |
| 4027 HStackCheckEliminator sce(this); | 3228 Run<HStackCheckEliminationPhase>(); |
| 4028 sce.Process(); | |
| 4029 | 3229 |
| 4030 if (FLAG_idefs) SetupInformativeDefinitions(); | 3230 if (FLAG_idefs) SetupInformativeDefinitions(); |
| 4031 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { | 3231 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { |
| 4032 EliminateRedundantBoundsChecks(); | 3232 Run<HBoundsCheckEliminationPhase>(); |
| 4033 } | 3233 } |
| 4034 if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations(); | 3234 if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations(); |
| 4035 if (FLAG_dead_code_elimination) { | 3235 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
| 4036 DeadCodeElimination("H_Eliminate late dead code"); | |
| 4037 } | |
| 4038 | 3236 |
| 4039 RestoreActualValues(); | 3237 RestoreActualValues(); |
| 4040 | 3238 |
| 4041 return true; | 3239 return true; |
| 4042 } | 3240 } |
| 4043 | 3241 |
| 4044 | 3242 |
| 4045 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { | 3243 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { |
| 4046 for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) { | 3244 for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) { |
| 4047 HPhi* phi = block->phis()->at(phi_index); | 3245 HPhi* phi = block->phis()->at(phi_index); |
| 4048 phi->AddInformativeDefinitions(); | 3246 phi->AddInformativeDefinitions(); |
| 4049 phi->SetFlag(HValue::kIDefsProcessingDone); | 3247 phi->SetFlag(HValue::kIDefsProcessingDone); |
| 4050 // We do not support phis that "redefine just one operand". | 3248 // We do not support phis that "redefine just one operand". |
| 4051 ASSERT(!phi->IsInformativeDefinition()); | 3249 ASSERT(!phi->IsInformativeDefinition()); |
| 4052 } | 3250 } |
| 4053 | 3251 |
| 4054 for (HInstruction* i = block->first(); i != NULL; i = i->next()) { | 3252 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 3253 HInstruction* i = it.Current(); |
| 4055 i->AddInformativeDefinitions(); | 3254 i->AddInformativeDefinitions(); |
| 4056 i->SetFlag(HValue::kIDefsProcessingDone); | 3255 i->SetFlag(HValue::kIDefsProcessingDone); |
| 4057 i->UpdateRedefinedUsesWhileSettingUpInformativeDefinitions(); | 3256 i->UpdateRedefinedUsesWhileSettingUpInformativeDefinitions(); |
| 4058 } | 3257 } |
| 4059 } | 3258 } |
| 4060 | 3259 |
| 4061 | 3260 |
| 4062 // This method is recursive, so if its stack frame is large it could | 3261 // This method is recursive, so if its stack frame is large it could |
| 4063 // cause a stack overflow. | 3262 // cause a stack overflow. |
| 4064 // To keep the individual stack frames small we do the actual work inside | 3263 // To keep the individual stack frames small we do the actual work inside |
| 4065 // SetupInformativeDefinitionsInBlock(); | 3264 // SetupInformativeDefinitionsInBlock(); |
| 4066 void HGraph::SetupInformativeDefinitionsRecursively(HBasicBlock* block) { | 3265 void HGraph::SetupInformativeDefinitionsRecursively(HBasicBlock* block) { |
| 4067 SetupInformativeDefinitionsInBlock(block); | 3266 SetupInformativeDefinitionsInBlock(block); |
| 4068 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { | 3267 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { |
| 4069 SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i)); | 3268 SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i)); |
| 4070 } | 3269 } |
| 4071 | 3270 |
| 4072 for (HInstruction* i = block->first(); i != NULL; i = i->next()) { | 3271 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 3272 HInstruction* i = it.Current(); |
| 4073 if (i->IsBoundsCheck()) { | 3273 if (i->IsBoundsCheck()) { |
| 4074 HBoundsCheck* check = HBoundsCheck::cast(i); | 3274 HBoundsCheck* check = HBoundsCheck::cast(i); |
| 4075 check->ApplyIndexChange(); | 3275 check->ApplyIndexChange(); |
| 4076 } | 3276 } |
| 4077 } | 3277 } |
| 4078 } | 3278 } |
| 4079 | 3279 |
| 4080 | 3280 |
| 4081 void HGraph::SetupInformativeDefinitions() { | 3281 void HGraph::SetupInformativeDefinitions() { |
| 4082 HPhase phase("H_Setup informative definitions", this); | 3282 HPhase phase("H_Setup informative definitions", this); |
| 4083 SetupInformativeDefinitionsRecursively(entry_block()); | 3283 SetupInformativeDefinitionsRecursively(entry_block()); |
| 4084 } | 3284 } |
| 4085 | 3285 |
| 4086 | 3286 |
| 4087 // We try to "factor up" HBoundsCheck instructions towards the root of the | |
| 4088 // dominator tree. | |
| 4089 // For now we handle checks where the index is like "exp + int32value". | |
| 4090 // If in the dominator tree we check "exp + v1" and later (dominated) | |
| 4091 // "exp + v2", if v2 <= v1 we can safely remove the second check, and if | |
| 4092 // v2 > v1 we can use v2 in the 1st check and again remove the second. | |
| 4093 // To do so we keep a dictionary of all checks where the key if the pair | |
| 4094 // "exp, length". | |
| 4095 // The class BoundsCheckKey represents this key. | |
| 4096 class BoundsCheckKey : public ZoneObject { | |
| 4097 public: | |
| 4098 HValue* IndexBase() const { return index_base_; } | |
| 4099 HValue* Length() const { return length_; } | |
| 4100 | |
| 4101 uint32_t Hash() { | |
| 4102 return static_cast<uint32_t>(index_base_->Hashcode() ^ length_->Hashcode()); | |
| 4103 } | |
| 4104 | |
| 4105 static BoundsCheckKey* Create(Zone* zone, | |
| 4106 HBoundsCheck* check, | |
| 4107 int32_t* offset) { | |
| 4108 if (!check->index()->representation().IsSmiOrInteger32()) return NULL; | |
| 4109 | |
| 4110 HValue* index_base = NULL; | |
| 4111 HConstant* constant = NULL; | |
| 4112 bool is_sub = false; | |
| 4113 | |
| 4114 if (check->index()->IsAdd()) { | |
| 4115 HAdd* index = HAdd::cast(check->index()); | |
| 4116 if (index->left()->IsConstant()) { | |
| 4117 constant = HConstant::cast(index->left()); | |
| 4118 index_base = index->right(); | |
| 4119 } else if (index->right()->IsConstant()) { | |
| 4120 constant = HConstant::cast(index->right()); | |
| 4121 index_base = index->left(); | |
| 4122 } | |
| 4123 } else if (check->index()->IsSub()) { | |
| 4124 HSub* index = HSub::cast(check->index()); | |
| 4125 is_sub = true; | |
| 4126 if (index->left()->IsConstant()) { | |
| 4127 constant = HConstant::cast(index->left()); | |
| 4128 index_base = index->right(); | |
| 4129 } else if (index->right()->IsConstant()) { | |
| 4130 constant = HConstant::cast(index->right()); | |
| 4131 index_base = index->left(); | |
| 4132 } | |
| 4133 } | |
| 4134 | |
| 4135 if (constant != NULL && constant->HasInteger32Value()) { | |
| 4136 *offset = is_sub ? - constant->Integer32Value() | |
| 4137 : constant->Integer32Value(); | |
| 4138 } else { | |
| 4139 *offset = 0; | |
| 4140 index_base = check->index(); | |
| 4141 } | |
| 4142 | |
| 4143 return new(zone) BoundsCheckKey(index_base, check->length()); | |
| 4144 } | |
| 4145 | |
| 4146 private: | |
| 4147 BoundsCheckKey(HValue* index_base, HValue* length) | |
| 4148 : index_base_(index_base), | |
| 4149 length_(length) { } | |
| 4150 | |
| 4151 HValue* index_base_; | |
| 4152 HValue* length_; | |
| 4153 }; | |
| 4154 | |
| 4155 | |
| 4156 // Data about each HBoundsCheck that can be eliminated or moved. | |
| 4157 // It is the "value" in the dictionary indexed by "base-index, length" | |
| 4158 // (the key is BoundsCheckKey). | |
| 4159 // We scan the code with a dominator tree traversal. | |
| 4160 // Traversing the dominator tree we keep a stack (implemented as a singly | |
| 4161 // linked list) of "data" for each basic block that contains a relevant check | |
| 4162 // with the same key (the dictionary holds the head of the list). | |
| 4163 // We also keep all the "data" created for a given basic block in a list, and | |
| 4164 // use it to "clean up" the dictionary when backtracking in the dominator tree | |
| 4165 // traversal. | |
| 4166 // Doing this each dictionary entry always directly points to the check that | |
| 4167 // is dominating the code being examined now. | |
| 4168 // We also track the current "offset" of the index expression and use it to | |
| 4169 // decide if any check is already "covered" (so it can be removed) or not. | |
| 4170 class BoundsCheckBbData: public ZoneObject { | |
| 4171 public: | |
| 4172 BoundsCheckKey* Key() const { return key_; } | |
| 4173 int32_t LowerOffset() const { return lower_offset_; } | |
| 4174 int32_t UpperOffset() const { return upper_offset_; } | |
| 4175 HBasicBlock* BasicBlock() const { return basic_block_; } | |
| 4176 HBoundsCheck* LowerCheck() const { return lower_check_; } | |
| 4177 HBoundsCheck* UpperCheck() const { return upper_check_; } | |
| 4178 BoundsCheckBbData* NextInBasicBlock() const { return next_in_bb_; } | |
| 4179 BoundsCheckBbData* FatherInDominatorTree() const { return father_in_dt_; } | |
| 4180 | |
| 4181 bool OffsetIsCovered(int32_t offset) const { | |
| 4182 return offset >= LowerOffset() && offset <= UpperOffset(); | |
| 4183 } | |
| 4184 | |
| 4185 bool HasSingleCheck() { return lower_check_ == upper_check_; } | |
| 4186 | |
| 4187 // The goal of this method is to modify either upper_offset_ or | |
| 4188 // lower_offset_ so that also new_offset is covered (the covered | |
| 4189 // range grows). | |
| 4190 // | |
| 4191 // The precondition is that new_check follows UpperCheck() and | |
| 4192 // LowerCheck() in the same basic block, and that new_offset is not | |
| 4193 // covered (otherwise we could simply remove new_check). | |
| 4194 // | |
| 4195 // If HasSingleCheck() is true then new_check is added as "second check" | |
| 4196 // (either upper or lower; note that HasSingleCheck() becomes false). | |
| 4197 // Otherwise one of the current checks is modified so that it also covers | |
| 4198 // new_offset, and new_check is removed. | |
| 4199 // | |
| 4200 // If the check cannot be modified because the context is unknown it | |
| 4201 // returns false, otherwise it returns true. | |
| 4202 bool CoverCheck(HBoundsCheck* new_check, | |
| 4203 int32_t new_offset) { | |
| 4204 ASSERT(new_check->index()->representation().IsSmiOrInteger32()); | |
| 4205 bool keep_new_check = false; | |
| 4206 | |
| 4207 if (new_offset > upper_offset_) { | |
| 4208 upper_offset_ = new_offset; | |
| 4209 if (HasSingleCheck()) { | |
| 4210 keep_new_check = true; | |
| 4211 upper_check_ = new_check; | |
| 4212 } else { | |
| 4213 bool result = BuildOffsetAdd(upper_check_, | |
| 4214 &added_upper_index_, | |
| 4215 &added_upper_offset_, | |
| 4216 Key()->IndexBase(), | |
| 4217 new_check->index()->representation(), | |
| 4218 new_offset); | |
| 4219 if (!result) return false; | |
| 4220 upper_check_->ReplaceAllUsesWith(upper_check_->index()); | |
| 4221 upper_check_->SetOperandAt(0, added_upper_index_); | |
| 4222 } | |
| 4223 } else if (new_offset < lower_offset_) { | |
| 4224 lower_offset_ = new_offset; | |
| 4225 if (HasSingleCheck()) { | |
| 4226 keep_new_check = true; | |
| 4227 lower_check_ = new_check; | |
| 4228 } else { | |
| 4229 bool result = BuildOffsetAdd(lower_check_, | |
| 4230 &added_lower_index_, | |
| 4231 &added_lower_offset_, | |
| 4232 Key()->IndexBase(), | |
| 4233 new_check->index()->representation(), | |
| 4234 new_offset); | |
| 4235 if (!result) return false; | |
| 4236 lower_check_->ReplaceAllUsesWith(lower_check_->index()); | |
| 4237 lower_check_->SetOperandAt(0, added_lower_index_); | |
| 4238 } | |
| 4239 } else { | |
| 4240 ASSERT(false); | |
| 4241 } | |
| 4242 | |
| 4243 if (!keep_new_check) { | |
| 4244 new_check->DeleteAndReplaceWith(new_check->ActualValue()); | |
| 4245 } | |
| 4246 | |
| 4247 return true; | |
| 4248 } | |
| 4249 | |
| 4250 void RemoveZeroOperations() { | |
| 4251 RemoveZeroAdd(&added_lower_index_, &added_lower_offset_); | |
| 4252 RemoveZeroAdd(&added_upper_index_, &added_upper_offset_); | |
| 4253 } | |
| 4254 | |
| 4255 BoundsCheckBbData(BoundsCheckKey* key, | |
| 4256 int32_t lower_offset, | |
| 4257 int32_t upper_offset, | |
| 4258 HBasicBlock* bb, | |
| 4259 HBoundsCheck* lower_check, | |
| 4260 HBoundsCheck* upper_check, | |
| 4261 BoundsCheckBbData* next_in_bb, | |
| 4262 BoundsCheckBbData* father_in_dt) | |
| 4263 : key_(key), | |
| 4264 lower_offset_(lower_offset), | |
| 4265 upper_offset_(upper_offset), | |
| 4266 basic_block_(bb), | |
| 4267 lower_check_(lower_check), | |
| 4268 upper_check_(upper_check), | |
| 4269 added_lower_index_(NULL), | |
| 4270 added_lower_offset_(NULL), | |
| 4271 added_upper_index_(NULL), | |
| 4272 added_upper_offset_(NULL), | |
| 4273 next_in_bb_(next_in_bb), | |
| 4274 father_in_dt_(father_in_dt) { } | |
| 4275 | |
| 4276 private: | |
| 4277 BoundsCheckKey* key_; | |
| 4278 int32_t lower_offset_; | |
| 4279 int32_t upper_offset_; | |
| 4280 HBasicBlock* basic_block_; | |
| 4281 HBoundsCheck* lower_check_; | |
| 4282 HBoundsCheck* upper_check_; | |
| 4283 HInstruction* added_lower_index_; | |
| 4284 HConstant* added_lower_offset_; | |
| 4285 HInstruction* added_upper_index_; | |
| 4286 HConstant* added_upper_offset_; | |
| 4287 BoundsCheckBbData* next_in_bb_; | |
| 4288 BoundsCheckBbData* father_in_dt_; | |
| 4289 | |
| 4290 // Given an existing add instruction and a bounds check it tries to | |
| 4291 // find the current context (either of the add or of the check index). | |
| 4292 HValue* IndexContext(HInstruction* add, HBoundsCheck* check) { | |
| 4293 if (add != NULL && add->IsAdd()) { | |
| 4294 return HAdd::cast(add)->context(); | |
| 4295 } | |
| 4296 if (check->index()->IsBinaryOperation()) { | |
| 4297 return HBinaryOperation::cast(check->index())->context(); | |
| 4298 } | |
| 4299 return NULL; | |
| 4300 } | |
| 4301 | |
| 4302 // This function returns false if it cannot build the add because the | |
| 4303 // current context cannot be determined. | |
| 4304 bool BuildOffsetAdd(HBoundsCheck* check, | |
| 4305 HInstruction** add, | |
| 4306 HConstant** constant, | |
| 4307 HValue* original_value, | |
| 4308 Representation representation, | |
| 4309 int32_t new_offset) { | |
| 4310 HValue* index_context = IndexContext(*add, check); | |
| 4311 if (index_context == NULL) return false; | |
| 4312 | |
| 4313 HConstant* new_constant = new(BasicBlock()->zone()) HConstant( | |
| 4314 new_offset, representation); | |
| 4315 if (*add == NULL) { | |
| 4316 new_constant->InsertBefore(check); | |
| 4317 (*add) = HAdd::New( | |
| 4318 BasicBlock()->zone(), index_context, original_value, new_constant); | |
| 4319 (*add)->AssumeRepresentation(representation); | |
| 4320 (*add)->InsertBefore(check); | |
| 4321 } else { | |
| 4322 new_constant->InsertBefore(*add); | |
| 4323 (*constant)->DeleteAndReplaceWith(new_constant); | |
| 4324 } | |
| 4325 *constant = new_constant; | |
| 4326 return true; | |
| 4327 } | |
| 4328 | |
| 4329 void RemoveZeroAdd(HInstruction** add, HConstant** constant) { | |
| 4330 if (*add != NULL && (*add)->IsAdd() && (*constant)->Integer32Value() == 0) { | |
| 4331 (*add)->DeleteAndReplaceWith(HAdd::cast(*add)->left()); | |
| 4332 (*constant)->DeleteAndReplaceWith(NULL); | |
| 4333 } | |
| 4334 } | |
| 4335 }; | |
| 4336 | |
| 4337 | |
| 4338 static bool BoundsCheckKeyMatch(void* key1, void* key2) { | |
| 4339 BoundsCheckKey* k1 = static_cast<BoundsCheckKey*>(key1); | |
| 4340 BoundsCheckKey* k2 = static_cast<BoundsCheckKey*>(key2); | |
| 4341 return k1->IndexBase() == k2->IndexBase() && k1->Length() == k2->Length(); | |
| 4342 } | |
| 4343 | |
| 4344 | |
| 4345 class BoundsCheckTable : private ZoneHashMap { | |
| 4346 public: | |
| 4347 BoundsCheckBbData** LookupOrInsert(BoundsCheckKey* key, Zone* zone) { | |
| 4348 return reinterpret_cast<BoundsCheckBbData**>( | |
| 4349 &(Lookup(key, key->Hash(), true, ZoneAllocationPolicy(zone))->value)); | |
| 4350 } | |
| 4351 | |
| 4352 void Insert(BoundsCheckKey* key, BoundsCheckBbData* data, Zone* zone) { | |
| 4353 Lookup(key, key->Hash(), true, ZoneAllocationPolicy(zone))->value = data; | |
| 4354 } | |
| 4355 | |
| 4356 void Delete(BoundsCheckKey* key) { | |
| 4357 Remove(key, key->Hash()); | |
| 4358 } | |
| 4359 | |
| 4360 explicit BoundsCheckTable(Zone* zone) | |
| 4361 : ZoneHashMap(BoundsCheckKeyMatch, ZoneHashMap::kDefaultHashMapCapacity, | |
| 4362 ZoneAllocationPolicy(zone)) { } | |
| 4363 }; | |
| 4364 | |
| 4365 | |
| 4366 // Eliminates checks in bb and recursively in the dominated blocks. | |
| 4367 // Also replace the results of check instructions with the original value, if | |
| 4368 // the result is used. This is safe now, since we don't do code motion after | |
| 4369 // this point. It enables better register allocation since the value produced | |
| 4370 // by check instructions is really a copy of the original value. | |
| 4371 void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb, | |
| 4372 BoundsCheckTable* table) { | |
| 4373 BoundsCheckBbData* bb_data_list = NULL; | |
| 4374 | |
| 4375 for (HInstruction* i = bb->first(); i != NULL; i = i->next()) { | |
| 4376 if (!i->IsBoundsCheck()) continue; | |
| 4377 | |
| 4378 HBoundsCheck* check = HBoundsCheck::cast(i); | |
| 4379 int32_t offset; | |
| 4380 BoundsCheckKey* key = | |
| 4381 BoundsCheckKey::Create(zone(), check, &offset); | |
| 4382 if (key == NULL) continue; | |
| 4383 BoundsCheckBbData** data_p = table->LookupOrInsert(key, zone()); | |
| 4384 BoundsCheckBbData* data = *data_p; | |
| 4385 if (data == NULL) { | |
| 4386 bb_data_list = new(zone()) BoundsCheckBbData(key, | |
| 4387 offset, | |
| 4388 offset, | |
| 4389 bb, | |
| 4390 check, | |
| 4391 check, | |
| 4392 bb_data_list, | |
| 4393 NULL); | |
| 4394 *data_p = bb_data_list; | |
| 4395 } else if (data->OffsetIsCovered(offset)) { | |
| 4396 check->DeleteAndReplaceWith(check->ActualValue()); | |
| 4397 } else if (data->BasicBlock() != bb || | |
| 4398 !data->CoverCheck(check, offset)) { | |
| 4399 // If the check is in the current BB we try to modify it by calling | |
| 4400 // "CoverCheck", but if also that fails we record the current offsets | |
| 4401 // in a new data instance because from now on they are covered. | |
| 4402 int32_t new_lower_offset = offset < data->LowerOffset() | |
| 4403 ? offset | |
| 4404 : data->LowerOffset(); | |
| 4405 int32_t new_upper_offset = offset > data->UpperOffset() | |
| 4406 ? offset | |
| 4407 : data->UpperOffset(); | |
| 4408 bb_data_list = new(zone()) BoundsCheckBbData(key, | |
| 4409 new_lower_offset, | |
| 4410 new_upper_offset, | |
| 4411 bb, | |
| 4412 data->LowerCheck(), | |
| 4413 data->UpperCheck(), | |
| 4414 bb_data_list, | |
| 4415 data); | |
| 4416 table->Insert(key, bb_data_list, zone()); | |
| 4417 } | |
| 4418 } | |
| 4419 | |
| 4420 for (int i = 0; i < bb->dominated_blocks()->length(); ++i) { | |
| 4421 EliminateRedundantBoundsChecks(bb->dominated_blocks()->at(i), table); | |
| 4422 } | |
| 4423 | |
| 4424 for (BoundsCheckBbData* data = bb_data_list; | |
| 4425 data != NULL; | |
| 4426 data = data->NextInBasicBlock()) { | |
| 4427 data->RemoveZeroOperations(); | |
| 4428 if (data->FatherInDominatorTree()) { | |
| 4429 table->Insert(data->Key(), data->FatherInDominatorTree(), zone()); | |
| 4430 } else { | |
| 4431 table->Delete(data->Key()); | |
| 4432 } | |
| 4433 } | |
| 4434 } | |
| 4435 | |
| 4436 | |
| 4437 void HGraph::EliminateRedundantBoundsChecks() { | |
| 4438 HPhase phase("H_Eliminate bounds checks", this); | |
| 4439 BoundsCheckTable checks_table(zone()); | |
| 4440 EliminateRedundantBoundsChecks(entry_block(), &checks_table); | |
| 4441 } | |
| 4442 | |
| 4443 | |
| 4444 static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) { | 3287 static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) { |
| 4445 HValue* index = array_operation->GetKey()->ActualValue(); | 3288 HValue* index = array_operation->GetKey()->ActualValue(); |
| 4446 if (!index->representation().IsSmiOrInteger32()) return; | 3289 if (!index->representation().IsSmiOrInteger32()) return; |
| 4447 | 3290 |
| 4448 HConstant* constant; | 3291 HConstant* constant; |
| 4449 HValue* subexpression; | 3292 HValue* subexpression; |
| 4450 int32_t sign; | 3293 int32_t sign; |
| 4451 if (index->IsAdd()) { | 3294 if (index->IsAdd()) { |
| 4452 sign = 1; | 3295 sign = 1; |
| 4453 HAdd* add = HAdd::cast(index); | 3296 HAdd* add = HAdd::cast(index); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4487 } | 3330 } |
| 4488 ASSERT(value >= 0); | 3331 ASSERT(value >= 0); |
| 4489 array_operation->SetIndexOffset(static_cast<uint32_t>(value)); | 3332 array_operation->SetIndexOffset(static_cast<uint32_t>(value)); |
| 4490 array_operation->SetDehoisted(true); | 3333 array_operation->SetDehoisted(true); |
| 4491 } | 3334 } |
| 4492 | 3335 |
| 4493 | 3336 |
| 4494 void HGraph::DehoistSimpleArrayIndexComputations() { | 3337 void HGraph::DehoistSimpleArrayIndexComputations() { |
| 4495 HPhase phase("H_Dehoist index computations", this); | 3338 HPhase phase("H_Dehoist index computations", this); |
| 4496 for (int i = 0; i < blocks()->length(); ++i) { | 3339 for (int i = 0; i < blocks()->length(); ++i) { |
| 4497 for (HInstruction* instr = blocks()->at(i)->first(); | 3340 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { |
| 4498 instr != NULL; | 3341 HInstruction* instr = it.Current(); |
| 4499 instr = instr->next()) { | |
| 4500 ArrayInstructionInterface* array_instruction = NULL; | 3342 ArrayInstructionInterface* array_instruction = NULL; |
| 4501 if (instr->IsLoadKeyed()) { | 3343 if (instr->IsLoadKeyed()) { |
| 4502 HLoadKeyed* op = HLoadKeyed::cast(instr); | 3344 HLoadKeyed* op = HLoadKeyed::cast(instr); |
| 4503 array_instruction = static_cast<ArrayInstructionInterface*>(op); | 3345 array_instruction = static_cast<ArrayInstructionInterface*>(op); |
| 4504 } else if (instr->IsStoreKeyed()) { | 3346 } else if (instr->IsStoreKeyed()) { |
| 4505 HStoreKeyed* op = HStoreKeyed::cast(instr); | 3347 HStoreKeyed* op = HStoreKeyed::cast(instr); |
| 4506 array_instruction = static_cast<ArrayInstructionInterface*>(op); | 3348 array_instruction = static_cast<ArrayInstructionInterface*>(op); |
| 4507 } else { | 3349 } else { |
| 4508 continue; | 3350 continue; |
| 4509 } | 3351 } |
| 4510 DehoistArrayIndex(array_instruction); | 3352 DehoistArrayIndex(array_instruction); |
| 4511 } | 3353 } |
| 4512 } | 3354 } |
| 4513 } | 3355 } |
| 4514 | 3356 |
| 4515 | 3357 |
| 4516 void HGraph::DeadCodeElimination(const char* phase_name) { | |
| 4517 HPhase phase(phase_name, this); | |
| 4518 MarkLiveInstructions(); | |
| 4519 RemoveDeadInstructions(); | |
| 4520 } | |
| 4521 | |
| 4522 | |
| 4523 void HGraph::MarkLiveInstructions() { | |
| 4524 ZoneList<HValue*> worklist(blocks_.length(), zone()); | |
| 4525 | |
| 4526 // Mark initial root instructions for dead code elimination. | |
| 4527 for (int i = 0; i < blocks()->length(); ++i) { | |
| 4528 HBasicBlock* block = blocks()->at(i); | |
| 4529 for (HInstruction* instr = block->first(); | |
| 4530 instr != NULL; | |
| 4531 instr = instr->next()) { | |
| 4532 if (instr->CannotBeEliminated()) MarkLive(NULL, instr, &worklist); | |
| 4533 } | |
| 4534 for (int j = 0; j < block->phis()->length(); j++) { | |
| 4535 HPhi* phi = block->phis()->at(j); | |
| 4536 if (phi->CannotBeEliminated()) MarkLive(NULL, phi, &worklist); | |
| 4537 } | |
| 4538 } | |
| 4539 | |
| 4540 // Transitively mark all inputs of live instructions live. | |
| 4541 while (!worklist.is_empty()) { | |
| 4542 HValue* instr = worklist.RemoveLast(); | |
| 4543 for (int i = 0; i < instr->OperandCount(); ++i) { | |
| 4544 MarkLive(instr, instr->OperandAt(i), &worklist); | |
| 4545 } | |
| 4546 } | |
| 4547 } | |
| 4548 | |
| 4549 | |
| 4550 void HGraph::MarkLive(HValue* ref, HValue* instr, ZoneList<HValue*>* worklist) { | |
| 4551 if (!instr->CheckFlag(HValue::kIsLive)) { | |
| 4552 instr->SetFlag(HValue::kIsLive); | |
| 4553 worklist->Add(instr, zone()); | |
| 4554 | |
| 4555 if (FLAG_trace_dead_code_elimination) { | |
| 4556 HeapStringAllocator allocator; | |
| 4557 StringStream stream(&allocator); | |
| 4558 if (ref != NULL) { | |
| 4559 ref->PrintTo(&stream); | |
| 4560 } else { | |
| 4561 stream.Add("root "); | |
| 4562 } | |
| 4563 stream.Add(" -> "); | |
| 4564 instr->PrintTo(&stream); | |
| 4565 PrintF("[MarkLive %s]\n", *stream.ToCString()); | |
| 4566 } | |
| 4567 } | |
| 4568 } | |
| 4569 | |
| 4570 | |
| 4571 void HGraph::RemoveDeadInstructions() { | |
| 4572 ZoneList<HPhi*> dead_phis(blocks_.length(), zone()); | |
| 4573 | |
| 4574 // Remove any instruction not marked kIsLive. | |
| 4575 for (int i = 0; i < blocks()->length(); ++i) { | |
| 4576 HBasicBlock* block = blocks()->at(i); | |
| 4577 for (HInstruction* instr = block->first(); | |
| 4578 instr != NULL; | |
| 4579 instr = instr->next()) { | |
| 4580 if (!instr->CheckFlag(HValue::kIsLive)) { | |
| 4581 // Instruction has not been marked live; assume it is dead and remove. | |
| 4582 // TODO(titzer): we don't remove constants because some special ones | |
| 4583 // might be used by later phases and are assumed to be in the graph | |
| 4584 if (!instr->IsConstant()) instr->DeleteAndReplaceWith(NULL); | |
| 4585 } else { | |
| 4586 // Clear the liveness flag to leave the graph clean for the next DCE. | |
| 4587 instr->ClearFlag(HValue::kIsLive); | |
| 4588 } | |
| 4589 } | |
| 4590 // Collect phis that are dead and remove them in the next pass. | |
| 4591 for (int j = 0; j < block->phis()->length(); j++) { | |
| 4592 HPhi* phi = block->phis()->at(j); | |
| 4593 if (!phi->CheckFlag(HValue::kIsLive)) { | |
| 4594 dead_phis.Add(phi, zone()); | |
| 4595 } else { | |
| 4596 phi->ClearFlag(HValue::kIsLive); | |
| 4597 } | |
| 4598 } | |
| 4599 } | |
| 4600 | |
| 4601 // Process phis separately to avoid simultaneously mutating the phi list. | |
| 4602 while (!dead_phis.is_empty()) { | |
| 4603 HPhi* phi = dead_phis.RemoveLast(); | |
| 4604 HBasicBlock* block = phi->block(); | |
| 4605 phi->DeleteAndReplaceWith(NULL); | |
| 4606 block->RecordDeletedPhi(phi->merged_index()); | |
| 4607 } | |
| 4608 } | |
| 4609 | |
| 4610 | |
| 4611 void HGraph::RestoreActualValues() { | 3358 void HGraph::RestoreActualValues() { |
| 4612 HPhase phase("H_Restore actual values", this); | 3359 HPhase phase("H_Restore actual values", this); |
| 4613 | 3360 |
| 4614 for (int block_index = 0; block_index < blocks()->length(); block_index++) { | 3361 for (int block_index = 0; block_index < blocks()->length(); block_index++) { |
| 4615 HBasicBlock* block = blocks()->at(block_index); | 3362 HBasicBlock* block = blocks()->at(block_index); |
| 4616 | 3363 |
| 4617 #ifdef DEBUG | 3364 #ifdef DEBUG |
| 4618 for (int i = 0; i < block->phis()->length(); i++) { | 3365 for (int i = 0; i < block->phis()->length(); i++) { |
| 4619 HPhi* phi = block->phis()->at(i); | 3366 HPhi* phi = block->phis()->at(i); |
| 4620 ASSERT(phi->ActualValue() == phi); | 3367 ASSERT(phi->ActualValue() == phi); |
| 4621 } | 3368 } |
| 4622 #endif | 3369 #endif |
| 4623 | 3370 |
| 4624 for (HInstruction* instruction = block->first(); | 3371 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 4625 instruction != NULL; | 3372 HInstruction* instruction = it.Current(); |
| 4626 instruction = instruction->next()) { | |
| 4627 if (instruction->ActualValue() != instruction) { | 3373 if (instruction->ActualValue() != instruction) { |
| 4628 ASSERT(instruction->IsInformativeDefinition()); | 3374 ASSERT(instruction->IsInformativeDefinition()); |
| 4629 if (instruction->IsPurelyInformativeDefinition()) { | 3375 if (instruction->IsPurelyInformativeDefinition()) { |
| 4630 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); | 3376 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); |
| 4631 } else { | 3377 } else { |
| 4632 instruction->ReplaceAllUsesWith(instruction->ActualValue()); | 3378 instruction->ReplaceAllUsesWith(instruction->ActualValue()); |
| 4633 } | 3379 } |
| 4634 } | 3380 } |
| 4635 } | 3381 } |
| 4636 } | 3382 } |
| 4637 } | 3383 } |
| 4638 | 3384 |
| 4639 | 3385 |
| 4640 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { | 3386 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { |
| 4641 Push(instr); | 3387 Push(instr); |
| 4642 AddInstruction(instr); | 3388 AddInstruction(instr); |
| 4643 } | 3389 } |
| 4644 | 3390 |
| 4645 | 3391 |
| 4646 void HOptimizedGraphBuilder::AddSoftDeoptimize() { | |
| 4647 isolate()->counters()->soft_deopts_requested()->Increment(); | |
| 4648 if (FLAG_always_opt) return; | |
| 4649 if (current_block()->IsDeoptimizing()) return; | |
| 4650 AddInstruction(new(zone()) HSoftDeoptimize()); | |
| 4651 isolate()->counters()->soft_deopts_inserted()->Increment(); | |
| 4652 current_block()->MarkAsDeoptimizing(); | |
| 4653 graph()->set_has_soft_deoptimize(true); | |
| 4654 } | |
| 4655 | |
| 4656 | |
| 4657 template <class Instruction> | 3392 template <class Instruction> |
| 4658 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { | 3393 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { |
| 4659 int count = call->argument_count(); | 3394 int count = call->argument_count(); |
| 4660 ZoneList<HValue*> arguments(count, zone()); | 3395 ZoneList<HValue*> arguments(count, zone()); |
| 4661 for (int i = 0; i < count; ++i) { | 3396 for (int i = 0; i < count; ++i) { |
| 4662 arguments.Add(Pop(), zone()); | 3397 arguments.Add(Pop(), zone()); |
| 4663 } | 3398 } |
| 4664 | 3399 |
| 4665 while (!arguments.is_empty()) { | 3400 while (!arguments.is_empty()) { |
| 4666 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); | 3401 Add<HPushArgument>(arguments.RemoveLast()); |
| 4667 } | 3402 } |
| 4668 return call; | 3403 return call; |
| 4669 } | 3404 } |
| 4670 | 3405 |
| 4671 | 3406 |
| 4672 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { | 3407 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { |
| 4673 HConstant* undefined_constant = new(zone()) HConstant( | 3408 HConstant* undefined_constant = Add<HConstant>( |
| 4674 isolate()->factory()->undefined_value()); | 3409 isolate()->factory()->undefined_value()); |
| 4675 AddInstruction(undefined_constant); | |
| 4676 graph()->set_undefined_constant(undefined_constant); | 3410 graph()->set_undefined_constant(undefined_constant); |
| 4677 | 3411 |
| 4678 // Create an arguments object containing the initial parameters. Set the | 3412 // Create an arguments object containing the initial parameters. Set the |
| 4679 // initial values of parameters including "this" having parameter index 0. | 3413 // initial values of parameters including "this" having parameter index 0. |
| 4680 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); | 3414 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); |
| 4681 HArgumentsObject* arguments_object = | 3415 HArgumentsObject* arguments_object = |
| 4682 new(zone()) HArgumentsObject(environment()->parameter_count(), zone()); | 3416 new(zone()) HArgumentsObject(environment()->parameter_count(), zone()); |
| 4683 for (int i = 0; i < environment()->parameter_count(); ++i) { | 3417 for (int i = 0; i < environment()->parameter_count(); ++i) { |
| 4684 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); | 3418 HInstruction* parameter = Add<HParameter>(i); |
| 4685 arguments_object->AddArgument(parameter, zone()); | 3419 arguments_object->AddArgument(parameter, zone()); |
| 4686 environment()->Bind(i, parameter); | 3420 environment()->Bind(i, parameter); |
| 4687 } | 3421 } |
| 4688 AddInstruction(arguments_object); | 3422 AddInstruction(arguments_object); |
| 4689 graph()->SetArgumentsObject(arguments_object); | 3423 graph()->SetArgumentsObject(arguments_object); |
| 4690 | 3424 |
| 4691 // First special is HContext. | 3425 // First special is HContext. |
| 4692 HInstruction* context = AddInstruction(new(zone()) HContext); | 3426 HInstruction* context = Add<HContext>(); |
| 4693 environment()->BindContext(context); | 3427 environment()->BindContext(context); |
| 4694 | 3428 |
| 4695 // Initialize specials and locals to undefined. | 3429 // Initialize specials and locals to undefined. |
| 4696 for (int i = environment()->parameter_count() + 1; | 3430 for (int i = environment()->parameter_count() + 1; |
| 4697 i < environment()->length(); | 3431 i < environment()->length(); |
| 4698 ++i) { | 3432 ++i) { |
| 4699 environment()->Bind(i, undefined_constant); | 3433 environment()->Bind(i, undefined_constant); |
| 4700 } | 3434 } |
| 4701 | 3435 |
| 4702 // Handle the arguments and arguments shadow variables specially (they do | 3436 // Handle the arguments and arguments shadow variables specially (they do |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4998 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 3732 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
| 4999 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 3733 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
| 5000 | 3734 |
| 5001 HControlInstruction* compare; | 3735 HControlInstruction* compare; |
| 5002 | 3736 |
| 5003 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { | 3737 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { |
| 5004 if (!clause->compare_type()->Is(Type::Smi())) { | 3738 if (!clause->compare_type()->Is(Type::Smi())) { |
| 5005 AddSoftDeoptimize(); | 3739 AddSoftDeoptimize(); |
| 5006 } | 3740 } |
| 5007 | 3741 |
| 5008 HCompareIDAndBranch* compare_ = | 3742 HCompareNumericAndBranch* compare_ = |
| 5009 new(zone()) HCompareIDAndBranch(tag_value, | 3743 new(zone()) HCompareNumericAndBranch(tag_value, |
| 5010 label_value, | 3744 label_value, |
| 5011 Token::EQ_STRICT); | 3745 Token::EQ_STRICT); |
| 5012 compare_->set_observed_input_representation( | 3746 compare_->set_observed_input_representation( |
| 5013 Representation::Smi(), Representation::Smi()); | 3747 Representation::Smi(), Representation::Smi()); |
| 5014 compare = compare_; | 3748 compare = compare_; |
| 5015 } else { | 3749 } else { |
| 5016 compare = new(zone()) HStringCompareAndBranch(context, tag_value, | 3750 compare = new(zone()) HStringCompareAndBranch(context, tag_value, |
| 5017 label_value, | 3751 label_value, |
| 5018 Token::EQ_STRICT); | 3752 Token::EQ_STRICT); |
| 5019 } | 3753 } |
| 5020 | 3754 |
| 5021 compare->SetSuccessorAt(0, body_block); | 3755 compare->SetSuccessorAt(0, body_block); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5095 stmt->ExitId())); | 3829 stmt->ExitId())); |
| 5096 } else { | 3830 } else { |
| 5097 if (fall_through_block != NULL) fall_through_block->Goto(break_block); | 3831 if (fall_through_block != NULL) fall_through_block->Goto(break_block); |
| 5098 if (last_block != NULL) last_block->Goto(break_block); | 3832 if (last_block != NULL) last_block->Goto(break_block); |
| 5099 break_block->SetJoinId(stmt->ExitId()); | 3833 break_block->SetJoinId(stmt->ExitId()); |
| 5100 set_current_block(break_block); | 3834 set_current_block(break_block); |
| 5101 } | 3835 } |
| 5102 } | 3836 } |
| 5103 | 3837 |
| 5104 | 3838 |
| 5105 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { | |
| 5106 return statement->OsrEntryId() == current_info()->osr_ast_id(); | |
| 5107 } | |
| 5108 | |
| 5109 | |
| 5110 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | |
| 5111 if (!HasOsrEntryAt(statement)) return false; | |
| 5112 | |
| 5113 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); | |
| 5114 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); | |
| 5115 HValue* true_value = graph()->GetConstantTrue(); | |
| 5116 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); | |
| 5117 current_block()->Finish(test); | |
| 5118 | |
| 5119 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); | |
| 5120 non_osr_entry->Goto(loop_predecessor); | |
| 5121 | |
| 5122 set_current_block(osr_entry); | |
| 5123 osr_entry->set_osr_entry(); | |
| 5124 BailoutId osr_entry_id = statement->OsrEntryId(); | |
| 5125 int first_expression_index = environment()->first_expression_index(); | |
| 5126 int length = environment()->length(); | |
| 5127 ZoneList<HUnknownOSRValue*>* osr_values = | |
| 5128 new(zone()) ZoneList<HUnknownOSRValue*>(length, zone()); | |
| 5129 | |
| 5130 for (int i = 0; i < first_expression_index; ++i) { | |
| 5131 HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue; | |
| 5132 AddInstruction(osr_value); | |
| 5133 environment()->Bind(i, osr_value); | |
| 5134 osr_values->Add(osr_value, zone()); | |
| 5135 } | |
| 5136 | |
| 5137 if (first_expression_index != length) { | |
| 5138 environment()->Drop(length - first_expression_index); | |
| 5139 for (int i = first_expression_index; i < length; ++i) { | |
| 5140 HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue; | |
| 5141 AddInstruction(osr_value); | |
| 5142 environment()->Push(osr_value); | |
| 5143 osr_values->Add(osr_value, zone()); | |
| 5144 } | |
| 5145 } | |
| 5146 | |
| 5147 graph()->set_osr_values(osr_values); | |
| 5148 | |
| 5149 AddSimulate(osr_entry_id); | |
| 5150 AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); | |
| 5151 HContext* context = new(zone()) HContext; | |
| 5152 AddInstruction(context); | |
| 5153 environment()->BindContext(context); | |
| 5154 current_block()->Goto(loop_predecessor); | |
| 5155 loop_predecessor->SetJoinId(statement->EntryId()); | |
| 5156 set_current_block(loop_predecessor); | |
| 5157 return true; | |
| 5158 } | |
| 5159 | |
| 5160 | |
| 5161 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 3839 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
| 5162 HBasicBlock* loop_entry, | 3840 HBasicBlock* loop_entry, |
| 5163 BreakAndContinueInfo* break_info) { | 3841 BreakAndContinueInfo* break_info) { |
| 5164 BreakAndContinueScope push(break_info, this); | 3842 BreakAndContinueScope push(break_info, this); |
| 5165 AddSimulate(stmt->StackCheckId()); | 3843 AddSimulate(stmt->StackCheckId()); |
| 5166 HValue* context = environment()->LookupContext(); | 3844 HValue* context = environment()->LookupContext(); |
| 5167 HStackCheck* stack_check = | 3845 HStackCheck* stack_check = Add<HStackCheck>( |
| 5168 new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch); | 3846 context, HStackCheck::kBackwardsBranch); |
| 5169 AddInstruction(stack_check); | |
| 5170 ASSERT(loop_entry->IsLoopHeader()); | 3847 ASSERT(loop_entry->IsLoopHeader()); |
| 5171 loop_entry->loop_information()->set_stack_check(stack_check); | 3848 loop_entry->loop_information()->set_stack_check(stack_check); |
| 5172 CHECK_BAILOUT(Visit(stmt->body())); | 3849 CHECK_BAILOUT(Visit(stmt->body())); |
| 5173 } | 3850 } |
| 5174 | 3851 |
| 5175 | 3852 |
| 5176 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 3853 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 5177 ASSERT(!HasStackOverflow()); | 3854 ASSERT(!HasStackOverflow()); |
| 5178 ASSERT(current_block() != NULL); | 3855 ASSERT(current_block() != NULL); |
| 5179 ASSERT(current_block()->HasPredecessor()); | 3856 ASSERT(current_block()->HasPredecessor()); |
| 5180 ASSERT(current_block() != NULL); | 3857 ASSERT(current_block() != NULL); |
| 5181 bool osr_entry = PreProcessOsrEntry(stmt); | 3858 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt); |
| 5182 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | |
| 5183 current_block()->Goto(loop_entry); | |
| 5184 set_current_block(loop_entry); | |
| 5185 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | |
| 5186 | 3859 |
| 5187 BreakAndContinueInfo break_info(stmt); | 3860 BreakAndContinueInfo break_info(stmt); |
| 5188 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); | 3861 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); |
| 5189 HBasicBlock* body_exit = | 3862 HBasicBlock* body_exit = |
| 5190 JoinContinue(stmt, current_block(), break_info.continue_block()); | 3863 JoinContinue(stmt, current_block(), break_info.continue_block()); |
| 5191 HBasicBlock* loop_successor = NULL; | 3864 HBasicBlock* loop_successor = NULL; |
| 5192 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { | 3865 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { |
| 5193 set_current_block(body_exit); | 3866 set_current_block(body_exit); |
| 5194 // The block for a true condition, the actual predecessor block of the | 3867 // The block for a true condition, the actual predecessor block of the |
| 5195 // back edge. | 3868 // back edge. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5214 break_info.break_block()); | 3887 break_info.break_block()); |
| 5215 set_current_block(loop_exit); | 3888 set_current_block(loop_exit); |
| 5216 } | 3889 } |
| 5217 | 3890 |
| 5218 | 3891 |
| 5219 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 3892 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
| 5220 ASSERT(!HasStackOverflow()); | 3893 ASSERT(!HasStackOverflow()); |
| 5221 ASSERT(current_block() != NULL); | 3894 ASSERT(current_block() != NULL); |
| 5222 ASSERT(current_block()->HasPredecessor()); | 3895 ASSERT(current_block()->HasPredecessor()); |
| 5223 ASSERT(current_block() != NULL); | 3896 ASSERT(current_block() != NULL); |
| 5224 bool osr_entry = PreProcessOsrEntry(stmt); | 3897 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt); |
| 5225 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | |
| 5226 current_block()->Goto(loop_entry); | |
| 5227 set_current_block(loop_entry); | |
| 5228 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | |
| 5229 | |
| 5230 | 3898 |
| 5231 // If the condition is constant true, do not generate a branch. | 3899 // If the condition is constant true, do not generate a branch. |
| 5232 HBasicBlock* loop_successor = NULL; | 3900 HBasicBlock* loop_successor = NULL; |
| 5233 if (!stmt->cond()->ToBooleanIsTrue()) { | 3901 if (!stmt->cond()->ToBooleanIsTrue()) { |
| 5234 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 3902 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
| 5235 loop_successor = graph()->CreateBasicBlock(); | 3903 loop_successor = graph()->CreateBasicBlock(); |
| 5236 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); | 3904 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
| 5237 if (body_entry->HasPredecessor()) { | 3905 if (body_entry->HasPredecessor()) { |
| 5238 body_entry->SetJoinId(stmt->BodyId()); | 3906 body_entry->SetJoinId(stmt->BodyId()); |
| 5239 set_current_block(body_entry); | 3907 set_current_block(body_entry); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 5261 | 3929 |
| 5262 | 3930 |
| 5263 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { | 3931 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { |
| 5264 ASSERT(!HasStackOverflow()); | 3932 ASSERT(!HasStackOverflow()); |
| 5265 ASSERT(current_block() != NULL); | 3933 ASSERT(current_block() != NULL); |
| 5266 ASSERT(current_block()->HasPredecessor()); | 3934 ASSERT(current_block()->HasPredecessor()); |
| 5267 if (stmt->init() != NULL) { | 3935 if (stmt->init() != NULL) { |
| 5268 CHECK_ALIVE(Visit(stmt->init())); | 3936 CHECK_ALIVE(Visit(stmt->init())); |
| 5269 } | 3937 } |
| 5270 ASSERT(current_block() != NULL); | 3938 ASSERT(current_block() != NULL); |
| 5271 bool osr_entry = PreProcessOsrEntry(stmt); | 3939 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt); |
| 5272 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | |
| 5273 current_block()->Goto(loop_entry); | |
| 5274 set_current_block(loop_entry); | |
| 5275 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | |
| 5276 | 3940 |
| 5277 HBasicBlock* loop_successor = NULL; | 3941 HBasicBlock* loop_successor = NULL; |
| 5278 if (stmt->cond() != NULL) { | 3942 if (stmt->cond() != NULL) { |
| 5279 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 3943 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
| 5280 loop_successor = graph()->CreateBasicBlock(); | 3944 loop_successor = graph()->CreateBasicBlock(); |
| 5281 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); | 3945 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
| 5282 if (body_entry->HasPredecessor()) { | 3946 if (body_entry->HasPredecessor()) { |
| 5283 body_entry->SetJoinId(stmt->BodyId()); | 3947 body_entry->SetJoinId(stmt->BodyId()); |
| 5284 set_current_block(body_entry); | 3948 set_current_block(body_entry); |
| 5285 } | 3949 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5328 if (!stmt->each()->IsVariableProxy() || | 3992 if (!stmt->each()->IsVariableProxy() || |
| 5329 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { | 3993 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { |
| 5330 return Bailout("ForInStatement with non-local each variable"); | 3994 return Bailout("ForInStatement with non-local each variable"); |
| 5331 } | 3995 } |
| 5332 | 3996 |
| 5333 Variable* each_var = stmt->each()->AsVariableProxy()->var(); | 3997 Variable* each_var = stmt->each()->AsVariableProxy()->var(); |
| 5334 | 3998 |
| 5335 CHECK_ALIVE(VisitForValue(stmt->enumerable())); | 3999 CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
| 5336 HValue* enumerable = Top(); // Leave enumerable at the top. | 4000 HValue* enumerable = Top(); // Leave enumerable at the top. |
| 5337 | 4001 |
| 5338 HInstruction* map = AddInstruction(new(zone()) HForInPrepareMap( | 4002 HInstruction* map = Add<HForInPrepareMap>( |
| 5339 environment()->LookupContext(), enumerable)); | 4003 environment()->LookupContext(), enumerable); |
| 5340 AddSimulate(stmt->PrepareId()); | 4004 AddSimulate(stmt->PrepareId()); |
| 5341 | 4005 |
| 5342 HInstruction* array = AddInstruction( | 4006 HInstruction* array = Add<HForInCacheArray>( |
| 5343 new(zone()) HForInCacheArray( | 4007 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); |
| 5344 enumerable, | |
| 5345 map, | |
| 5346 DescriptorArray::kEnumCacheBridgeCacheIndex)); | |
| 5347 | 4008 |
| 5348 HInstruction* enum_length = AddInstruction(new(zone()) HMapEnumLength(map)); | 4009 HInstruction* enum_length = Add<HMapEnumLength>(map); |
| 5349 | 4010 |
| 5350 HInstruction* start_index = AddInstruction(new(zone()) HConstant(0)); | 4011 HInstruction* start_index = Add<HConstant>(0); |
| 5351 | 4012 |
| 5352 Push(map); | 4013 Push(map); |
| 5353 Push(array); | 4014 Push(array); |
| 5354 Push(enum_length); | 4015 Push(enum_length); |
| 5355 Push(start_index); | 4016 Push(start_index); |
| 5356 | 4017 |
| 5357 HInstruction* index_cache = AddInstruction( | 4018 HInstruction* index_cache = Add<HForInCacheArray>( |
| 5358 new(zone()) HForInCacheArray( | 4019 enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex); |
| 5359 enumerable, | |
| 5360 map, | |
| 5361 DescriptorArray::kEnumCacheBridgeIndicesCacheIndex)); | |
| 5362 HForInCacheArray::cast(array)->set_index_cache( | 4020 HForInCacheArray::cast(array)->set_index_cache( |
| 5363 HForInCacheArray::cast(index_cache)); | 4021 HForInCacheArray::cast(index_cache)); |
| 5364 | 4022 |
| 5365 bool osr_entry = PreProcessOsrEntry(stmt); | 4023 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt); |
| 5366 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | |
| 5367 current_block()->Goto(loop_entry); | |
| 5368 set_current_block(loop_entry); | |
| 5369 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | |
| 5370 | 4024 |
| 5371 HValue* index = environment()->ExpressionStackAt(0); | 4025 HValue* index = environment()->ExpressionStackAt(0); |
| 5372 HValue* limit = environment()->ExpressionStackAt(1); | 4026 HValue* limit = environment()->ExpressionStackAt(1); |
| 5373 | 4027 |
| 5374 // Check that we still have more keys. | 4028 // Check that we still have more keys. |
| 5375 HCompareIDAndBranch* compare_index = | 4029 HCompareNumericAndBranch* compare_index = |
| 5376 new(zone()) HCompareIDAndBranch(index, limit, Token::LT); | 4030 new(zone()) HCompareNumericAndBranch(index, limit, Token::LT); |
| 5377 compare_index->set_observed_input_representation( | 4031 compare_index->set_observed_input_representation( |
| 5378 Representation::Smi(), Representation::Smi()); | 4032 Representation::Smi(), Representation::Smi()); |
| 5379 | 4033 |
| 5380 HBasicBlock* loop_body = graph()->CreateBasicBlock(); | 4034 HBasicBlock* loop_body = graph()->CreateBasicBlock(); |
| 5381 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); | 4035 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); |
| 5382 | 4036 |
| 5383 compare_index->SetSuccessorAt(0, loop_body); | 4037 compare_index->SetSuccessorAt(0, loop_body); |
| 5384 compare_index->SetSuccessorAt(1, loop_successor); | 4038 compare_index->SetSuccessorAt(1, loop_successor); |
| 5385 current_block()->Finish(compare_index); | 4039 current_block()->Finish(compare_index); |
| 5386 | 4040 |
| 5387 set_current_block(loop_successor); | 4041 set_current_block(loop_successor); |
| 5388 Drop(5); | 4042 Drop(5); |
| 5389 | 4043 |
| 5390 set_current_block(loop_body); | 4044 set_current_block(loop_body); |
| 5391 | 4045 |
| 5392 HValue* key = AddInstruction( | 4046 HValue* key = Add<HLoadKeyed>( |
| 5393 new(zone()) HLoadKeyed( | 4047 environment()->ExpressionStackAt(2), // Enum cache. |
| 5394 environment()->ExpressionStackAt(2), // Enum cache. | 4048 environment()->ExpressionStackAt(0), // Iteration index. |
| 5395 environment()->ExpressionStackAt(0), // Iteration index. | 4049 environment()->ExpressionStackAt(0), |
| 5396 environment()->ExpressionStackAt(0), | 4050 FAST_ELEMENTS); |
| 5397 FAST_ELEMENTS)); | |
| 5398 | 4051 |
| 5399 // Check if the expected map still matches that of the enumerable. | 4052 // Check if the expected map still matches that of the enumerable. |
| 5400 // If not just deoptimize. | 4053 // If not just deoptimize. |
| 5401 AddInstruction(new(zone()) HCheckMapValue( | 4054 Add<HCheckMapValue>(environment()->ExpressionStackAt(4), |
| 5402 environment()->ExpressionStackAt(4), | 4055 environment()->ExpressionStackAt(3)); |
| 5403 environment()->ExpressionStackAt(3))); | |
| 5404 | 4056 |
| 5405 Bind(each_var, key); | 4057 Bind(each_var, key); |
| 5406 | 4058 |
| 5407 BreakAndContinueInfo break_info(stmt, 5); | 4059 BreakAndContinueInfo break_info(stmt, 5); |
| 5408 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); | 4060 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); |
| 5409 | 4061 |
| 5410 HBasicBlock* body_exit = | 4062 HBasicBlock* body_exit = |
| 5411 JoinContinue(stmt, current_block(), break_info.continue_block()); | 4063 JoinContinue(stmt, current_block(), break_info.continue_block()); |
| 5412 | 4064 |
| 5413 if (body_exit != NULL) { | 4065 if (body_exit != NULL) { |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5566 | 4218 |
| 5567 return kUseCell; | 4219 return kUseCell; |
| 5568 } | 4220 } |
| 5569 | 4221 |
| 5570 | 4222 |
| 5571 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 4223 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 5572 ASSERT(var->IsContextSlot()); | 4224 ASSERT(var->IsContextSlot()); |
| 5573 HValue* context = environment()->LookupContext(); | 4225 HValue* context = environment()->LookupContext(); |
| 5574 int length = current_info()->scope()->ContextChainLength(var->scope()); | 4226 int length = current_info()->scope()->ContextChainLength(var->scope()); |
| 5575 while (length-- > 0) { | 4227 while (length-- > 0) { |
| 5576 HInstruction* context_instruction = new(zone()) HOuterContext(context); | 4228 context = Add<HOuterContext>(context); |
| 5577 AddInstruction(context_instruction); | |
| 5578 context = context_instruction; | |
| 5579 } | 4229 } |
| 5580 return context; | 4230 return context; |
| 5581 } | 4231 } |
| 5582 | 4232 |
| 5583 | 4233 |
| 5584 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 4234 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 5585 ASSERT(!HasStackOverflow()); | 4235 ASSERT(!HasStackOverflow()); |
| 5586 ASSERT(current_block() != NULL); | 4236 ASSERT(current_block() != NULL); |
| 5587 ASSERT(current_block()->HasPredecessor()); | 4237 ASSERT(current_block()->HasPredecessor()); |
| 5588 Variable* variable = expr->var(); | 4238 Variable* variable = expr->var(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5606 LookupGlobalProperty(variable, &lookup, false); | 4256 LookupGlobalProperty(variable, &lookup, false); |
| 5607 | 4257 |
| 5608 if (type == kUseCell && | 4258 if (type == kUseCell && |
| 5609 current_info()->global_object()->IsAccessCheckNeeded()) { | 4259 current_info()->global_object()->IsAccessCheckNeeded()) { |
| 5610 type = kUseGeneric; | 4260 type = kUseGeneric; |
| 5611 } | 4261 } |
| 5612 | 4262 |
| 5613 if (type == kUseCell) { | 4263 if (type == kUseCell) { |
| 5614 Handle<GlobalObject> global(current_info()->global_object()); | 4264 Handle<GlobalObject> global(current_info()->global_object()); |
| 5615 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 4265 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 5616 HLoadGlobalCell* instr = | 4266 if (cell->type()->IsConstant()) { |
| 5617 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); | 4267 cell->AddDependentCompilationInfo(top_info()); |
| 5618 return ast_context()->ReturnInstruction(instr, expr->id()); | 4268 Handle<Object> constant_object = cell->type()->AsConstant(); |
| 4269 if (constant_object->IsConsString()) { |
| 4270 constant_object = |
| 4271 FlattenGetString(Handle<String>::cast(constant_object)); |
| 4272 } |
| 4273 HConstant* constant = new(zone()) HConstant(constant_object); |
| 4274 return ast_context()->ReturnInstruction(constant, expr->id()); |
| 4275 } else { |
| 4276 HLoadGlobalCell* instr = |
| 4277 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); |
| 4278 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4279 } |
| 5619 } else { | 4280 } else { |
| 5620 HValue* context = environment()->LookupContext(); | 4281 HValue* context = environment()->LookupContext(); |
| 5621 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 4282 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 5622 AddInstruction(global_object); | 4283 AddInstruction(global_object); |
| 5623 HLoadGlobalGeneric* instr = | 4284 HLoadGlobalGeneric* instr = |
| 5624 new(zone()) HLoadGlobalGeneric(context, | 4285 new(zone()) HLoadGlobalGeneric(context, |
| 5625 global_object, | 4286 global_object, |
| 5626 variable->name(), | 4287 variable->name(), |
| 5627 ast_context()->is_for_typeof()); | 4288 ast_context()->is_for_typeof()); |
| 5628 instr->set_position(expr->position()); | 4289 instr->set_position(expr->position()); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5861 &data_size, | 4522 &data_size, |
| 5862 &pointer_size)) { | 4523 &pointer_size)) { |
| 5863 Handle<JSObject> original_boilerplate_object = | 4524 Handle<JSObject> original_boilerplate_object = |
| 5864 Handle<JSObject>::cast(original_boilerplate); | 4525 Handle<JSObject>::cast(original_boilerplate); |
| 5865 Handle<JSObject> boilerplate_object = | 4526 Handle<JSObject> boilerplate_object = |
| 5866 DeepCopy(original_boilerplate_object); | 4527 DeepCopy(original_boilerplate_object); |
| 5867 | 4528 |
| 5868 literal = BuildFastLiteral(context, | 4529 literal = BuildFastLiteral(context, |
| 5869 boilerplate_object, | 4530 boilerplate_object, |
| 5870 original_boilerplate_object, | 4531 original_boilerplate_object, |
| 4532 Handle<Object>::null(), |
| 5871 data_size, | 4533 data_size, |
| 5872 pointer_size, | 4534 pointer_size, |
| 5873 DONT_TRACK_ALLOCATION_SITE); | 4535 DONT_TRACK_ALLOCATION_SITE); |
| 5874 } else { | 4536 } else { |
| 5875 NoObservableSideEffectsScope no_effects(this); | 4537 NoObservableSideEffectsScope no_effects(this); |
| 5876 Handle<FixedArray> closure_literals(closure->literals(), isolate()); | 4538 Handle<FixedArray> closure_literals(closure->literals(), isolate()); |
| 5877 Handle<FixedArray> constant_properties = expr->constant_properties(); | 4539 Handle<FixedArray> constant_properties = expr->constant_properties(); |
| 5878 int literal_index = expr->literal_index(); | 4540 int literal_index = expr->literal_index(); |
| 5879 int flags = expr->fast_elements() | 4541 int flags = expr->fast_elements() |
| 5880 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; | 4542 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; |
| 5881 flags |= expr->has_function() | 4543 flags |= expr->has_function() |
| 5882 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; | 4544 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; |
| 5883 | 4545 |
| 5884 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 4546 Add<HPushArgument>(Add<HConstant>(closure_literals)); |
| 5885 new(zone()) HConstant(closure_literals)))); | 4547 Add<HPushArgument>(Add<HConstant>(literal_index)); |
| 5886 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 4548 Add<HPushArgument>(Add<HConstant>(constant_properties)); |
| 5887 new(zone()) HConstant(literal_index)))); | 4549 Add<HPushArgument>(Add<HConstant>(flags)); |
| 5888 AddInstruction(new(zone()) HPushArgument(AddInstruction( | |
| 5889 new(zone()) HConstant(constant_properties)))); | |
| 5890 AddInstruction(new(zone()) HPushArgument(AddInstruction( | |
| 5891 new(zone()) HConstant(flags)))); | |
| 5892 | 4550 |
| 5893 Runtime::FunctionId function_id = | 4551 Runtime::FunctionId function_id = |
| 5894 (expr->depth() > 1 || expr->may_store_doubles()) | 4552 (expr->depth() > 1 || expr->may_store_doubles()) |
| 5895 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow; | 4553 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow; |
| 5896 literal = AddInstruction( | 4554 literal = Add<HCallRuntime>(context, |
| 5897 new(zone()) HCallRuntime(context, | 4555 isolate()->factory()->empty_string(), |
| 5898 isolate()->factory()->empty_string(), | 4556 Runtime::FunctionForId(function_id), |
| 5899 Runtime::FunctionForId(function_id), | 4557 4); |
| 5900 4)); | |
| 5901 } | 4558 } |
| 5902 | 4559 |
| 5903 // The object is expected in the bailout environment during computation | 4560 // The object is expected in the bailout environment during computation |
| 5904 // of the property values and is the value of the entire expression. | 4561 // of the property values and is the value of the entire expression. |
| 5905 Push(literal); | 4562 Push(literal); |
| 5906 | 4563 |
| 5907 expr->CalculateEmitStore(zone()); | 4564 expr->CalculateEmitStore(zone()); |
| 5908 | 4565 |
| 5909 for (int i = 0; i < expr->properties()->length(); i++) { | 4566 for (int i = 0; i < expr->properties()->length(); i++) { |
| 5910 ObjectLiteral::Property* property = expr->properties()->at(i); | 4567 ObjectLiteral::Property* property = expr->properties()->at(i); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5956 default: UNREACHABLE(); | 4613 default: UNREACHABLE(); |
| 5957 } | 4614 } |
| 5958 } | 4615 } |
| 5959 | 4616 |
| 5960 if (expr->has_function()) { | 4617 if (expr->has_function()) { |
| 5961 // Return the result of the transformation to fast properties | 4618 // Return the result of the transformation to fast properties |
| 5962 // instead of the original since this operation changes the map | 4619 // instead of the original since this operation changes the map |
| 5963 // of the object. This makes sure that the original object won't | 4620 // of the object. This makes sure that the original object won't |
| 5964 // be used by other optimized code before it is transformed | 4621 // be used by other optimized code before it is transformed |
| 5965 // (e.g. because of code motion). | 4622 // (e.g. because of code motion). |
| 5966 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); | 4623 HToFastProperties* result = Add<HToFastProperties>(Pop()); |
| 5967 AddInstruction(result); | |
| 5968 return ast_context()->ReturnValue(result); | 4624 return ast_context()->ReturnValue(result); |
| 5969 } else { | 4625 } else { |
| 5970 return ast_context()->ReturnValue(Pop()); | 4626 return ast_context()->ReturnValue(Pop()); |
| 5971 } | 4627 } |
| 5972 } | 4628 } |
| 5973 | 4629 |
| 5974 | 4630 |
| 5975 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 4631 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| 5976 ASSERT(!HasStackOverflow()); | 4632 ASSERT(!HasStackOverflow()); |
| 5977 ASSERT(current_block() != NULL); | 4633 ASSERT(current_block() != NULL); |
| 5978 ASSERT(current_block()->HasPredecessor()); | 4634 ASSERT(current_block()->HasPredecessor()); |
| 5979 ZoneList<Expression*>* subexprs = expr->values(); | 4635 ZoneList<Expression*>* subexprs = expr->values(); |
| 5980 int length = subexprs->length(); | 4636 int length = subexprs->length(); |
| 5981 HValue* context = environment()->LookupContext(); | 4637 HValue* context = environment()->LookupContext(); |
| 5982 HInstruction* literal; | 4638 HInstruction* literal; |
| 5983 | 4639 |
| 4640 Handle<AllocationSite> site; |
| 5984 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); | 4641 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); |
| 5985 Handle<Object> raw_boilerplate(literals->get(expr->literal_index()), | 4642 bool uninitialized = false; |
| 5986 isolate()); | 4643 Handle<Object> literals_cell(literals->get(expr->literal_index()), |
| 5987 | 4644 isolate()); |
| 5988 if (raw_boilerplate->IsUndefined()) { | 4645 Handle<Object> raw_boilerplate; |
| 4646 if (literals_cell->IsUndefined()) { |
| 4647 uninitialized = true; |
| 5989 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( | 4648 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( |
| 5990 isolate(), literals, expr->constant_elements()); | 4649 isolate(), literals, expr->constant_elements()); |
| 5991 if (raw_boilerplate.is_null()) { | 4650 if (raw_boilerplate.is_null()) { |
| 5992 return Bailout("array boilerplate creation failed"); | 4651 return Bailout("array boilerplate creation failed"); |
| 5993 } | 4652 } |
| 5994 literals->set(expr->literal_index(), *raw_boilerplate); | 4653 |
| 4654 site = isolate()->factory()->NewAllocationSite(); |
| 4655 site->set_payload(*raw_boilerplate); |
| 4656 literals->set(expr->literal_index(), *site); |
| 4657 |
| 5995 if (JSObject::cast(*raw_boilerplate)->elements()->map() == | 4658 if (JSObject::cast(*raw_boilerplate)->elements()->map() == |
| 5996 isolate()->heap()->fixed_cow_array_map()) { | 4659 isolate()->heap()->fixed_cow_array_map()) { |
| 5997 isolate()->counters()->cow_arrays_created_runtime()->Increment(); | 4660 isolate()->counters()->cow_arrays_created_runtime()->Increment(); |
| 5998 } | 4661 } |
| 4662 } else { |
| 4663 ASSERT(literals_cell->IsAllocationSite()); |
| 4664 site = Handle<AllocationSite>::cast(literals_cell); |
| 4665 raw_boilerplate = Handle<Object>(site->payload(), isolate()); |
| 5999 } | 4666 } |
| 6000 | 4667 |
| 4668 ASSERT(!raw_boilerplate.is_null()); |
| 4669 ASSERT(site->IsLiteralSite()); |
| 4670 |
| 6001 Handle<JSObject> original_boilerplate_object = | 4671 Handle<JSObject> original_boilerplate_object = |
| 6002 Handle<JSObject>::cast(raw_boilerplate); | 4672 Handle<JSObject>::cast(raw_boilerplate); |
| 6003 ElementsKind boilerplate_elements_kind = | 4673 ElementsKind boilerplate_elements_kind = |
| 6004 Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind(); | 4674 Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind(); |
| 6005 | 4675 |
| 6006 // TODO(mvstanton): This heuristic is only a temporary solution. In the | 4676 // TODO(mvstanton): This heuristic is only a temporary solution. In the |
| 6007 // end, we want to quit creating allocation site info after a certain number | 4677 // end, we want to quit creating allocation site info after a certain number |
| 6008 // of GCs for a call site. | 4678 // of GCs for a call site. |
| 6009 AllocationSiteMode mode = AllocationSiteInfo::GetMode( | 4679 AllocationSiteMode mode = AllocationSite::GetMode( |
| 6010 boilerplate_elements_kind); | 4680 boilerplate_elements_kind); |
| 6011 | 4681 |
| 6012 // Check whether to use fast or slow deep-copying for boilerplate. | 4682 // Check whether to use fast or slow deep-copying for boilerplate. |
| 6013 int data_size = 0; | 4683 int data_size = 0; |
| 6014 int pointer_size = 0; | 4684 int pointer_size = 0; |
| 6015 int max_properties = kMaxFastLiteralProperties; | 4685 int max_properties = kMaxFastLiteralProperties; |
| 6016 if (IsFastLiteral(original_boilerplate_object, | 4686 if (IsFastLiteral(original_boilerplate_object, |
| 6017 kMaxFastLiteralDepth, | 4687 kMaxFastLiteralDepth, |
| 6018 &max_properties, | 4688 &max_properties, |
| 6019 &data_size, | 4689 &data_size, |
| 6020 &pointer_size)) { | 4690 &pointer_size)) { |
| 6021 if (mode == TRACK_ALLOCATION_SITE) { | 4691 if (mode == TRACK_ALLOCATION_SITE) { |
| 6022 pointer_size += AllocationSiteInfo::kSize; | 4692 pointer_size += AllocationSiteInfo::kSize; |
| 6023 } | 4693 } |
| 6024 | 4694 |
| 6025 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); | 4695 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); |
| 6026 literal = BuildFastLiteral(context, | 4696 literal = BuildFastLiteral(context, |
| 6027 boilerplate_object, | 4697 boilerplate_object, |
| 6028 original_boilerplate_object, | 4698 original_boilerplate_object, |
| 4699 site, |
| 6029 data_size, | 4700 data_size, |
| 6030 pointer_size, | 4701 pointer_size, |
| 6031 mode); | 4702 mode); |
| 6032 } else { | 4703 } else { |
| 6033 NoObservableSideEffectsScope no_effects(this); | 4704 NoObservableSideEffectsScope no_effects(this); |
| 6034 // Boilerplate already exists and constant elements are never accessed, | 4705 // Boilerplate already exists and constant elements are never accessed, |
| 6035 // pass an empty fixed array to the runtime function instead. | 4706 // pass an empty fixed array to the runtime function instead. |
| 6036 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); | 4707 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); |
| 6037 int literal_index = expr->literal_index(); | 4708 int literal_index = expr->literal_index(); |
| 6038 | 4709 |
| 6039 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 4710 Add<HPushArgument>(Add<HConstant>(literals)); |
| 6040 new(zone()) HConstant(literals)))); | 4711 Add<HPushArgument>(Add<HConstant>(literal_index)); |
| 6041 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 4712 Add<HPushArgument>(Add<HConstant>(constants)); |
| 6042 new(zone()) HConstant(literal_index)))); | |
| 6043 AddInstruction(new(zone()) HPushArgument(AddInstruction( | |
| 6044 new(zone()) HConstant(constants)))); | |
| 6045 | 4713 |
| 6046 Runtime::FunctionId function_id = (expr->depth() > 1) | 4714 Runtime::FunctionId function_id = (expr->depth() > 1) |
| 6047 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; | 4715 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; |
| 6048 literal = AddInstruction( | 4716 literal = Add<HCallRuntime>(context, |
| 6049 new(zone()) HCallRuntime(context, | 4717 isolate()->factory()->empty_string(), |
| 6050 isolate()->factory()->empty_string(), | 4718 Runtime::FunctionForId(function_id), |
| 6051 Runtime::FunctionForId(function_id), | 4719 3); |
| 6052 3)); | |
| 6053 | 4720 |
| 6054 // De-opt if elements kind changed from boilerplate_elements_kind. | 4721 // De-opt if elements kind changed from boilerplate_elements_kind. |
| 6055 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), | 4722 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), |
| 6056 isolate()); | 4723 isolate()); |
| 6057 AddInstruction(HCheckMaps::New(literal, map, zone())); | 4724 AddInstruction(HCheckMaps::New(literal, map, zone())); |
| 6058 } | 4725 } |
| 6059 | 4726 |
| 6060 // The array is expected in the bailout environment during computation | 4727 // The array is expected in the bailout environment during computation |
| 6061 // of the property values and is the value of the entire expression. | 4728 // of the property values and is the value of the entire expression. |
| 6062 Push(literal); | 4729 Push(literal); |
| 6063 // The literal index is on the stack, too. | 4730 // The literal index is on the stack, too. |
| 6064 Push(AddInstruction(new(zone()) HConstant(expr->literal_index()))); | 4731 Push(Add<HConstant>(expr->literal_index())); |
| 6065 | 4732 |
| 6066 HInstruction* elements = NULL; | 4733 HInstruction* elements = NULL; |
| 6067 | 4734 |
| 6068 for (int i = 0; i < length; i++) { | 4735 for (int i = 0; i < length; i++) { |
| 6069 Expression* subexpr = subexprs->at(i); | 4736 Expression* subexpr = subexprs->at(i); |
| 6070 // If the subexpression is a literal or a simple materialized literal it | 4737 // If the subexpression is a literal or a simple materialized literal it |
| 6071 // is already set in the cloned array. | 4738 // is already set in the cloned array. |
| 6072 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 4739 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| 6073 | 4740 |
| 6074 CHECK_ALIVE(VisitForValue(subexpr)); | 4741 CHECK_ALIVE(VisitForValue(subexpr)); |
| 6075 HValue* value = Pop(); | 4742 HValue* value = Pop(); |
| 6076 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); | 4743 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); |
| 6077 | 4744 |
| 6078 elements = AddLoadElements(literal); | 4745 elements = AddLoadElements(literal); |
| 6079 | 4746 |
| 6080 HValue* key = AddInstruction(new(zone()) HConstant(i)); | 4747 HValue* key = Add<HConstant>(i); |
| 6081 | 4748 |
| 6082 switch (boilerplate_elements_kind) { | 4749 switch (boilerplate_elements_kind) { |
| 6083 case FAST_SMI_ELEMENTS: | 4750 case FAST_SMI_ELEMENTS: |
| 6084 case FAST_HOLEY_SMI_ELEMENTS: | 4751 case FAST_HOLEY_SMI_ELEMENTS: |
| 6085 case FAST_ELEMENTS: | 4752 case FAST_ELEMENTS: |
| 6086 case FAST_HOLEY_ELEMENTS: | 4753 case FAST_HOLEY_ELEMENTS: |
| 6087 case FAST_DOUBLE_ELEMENTS: | 4754 case FAST_DOUBLE_ELEMENTS: |
| 6088 case FAST_HOLEY_DOUBLE_ELEMENTS: | 4755 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
| 6089 AddInstruction(new(zone()) HStoreKeyed( | 4756 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, |
| 6090 elements, | 4757 boilerplate_elements_kind); |
| 6091 key, | 4758 instr->SetUninitialized(uninitialized); |
| 6092 value, | |
| 6093 boilerplate_elements_kind)); | |
| 6094 break; | 4759 break; |
| 4760 } |
| 6095 default: | 4761 default: |
| 6096 UNREACHABLE(); | 4762 UNREACHABLE(); |
| 6097 break; | 4763 break; |
| 6098 } | 4764 } |
| 6099 | 4765 |
| 6100 AddSimulate(expr->GetIdForElement(i)); | 4766 AddSimulate(expr->GetIdForElement(i)); |
| 6101 } | 4767 } |
| 6102 | 4768 |
| 6103 Drop(1); // array literal index | 4769 Drop(1); // array literal index |
| 6104 return ast_context()->ReturnValue(Pop()); | 4770 return ast_context()->ReturnValue(Pop()); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6180 // We only need to check up to the preexisting property. | 4846 // We only need to check up to the preexisting property. |
| 6181 proto = proto_result.holder(); | 4847 proto = proto_result.holder(); |
| 6182 } else { | 4848 } else { |
| 6183 // Otherwise, find the top prototype. | 4849 // Otherwise, find the top prototype. |
| 6184 while (proto->GetPrototype(isolate())->IsJSObject()) { | 4850 while (proto->GetPrototype(isolate())->IsJSObject()) { |
| 6185 proto = proto->GetPrototype(isolate()); | 4851 proto = proto->GetPrototype(isolate()); |
| 6186 } | 4852 } |
| 6187 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 4853 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
| 6188 } | 4854 } |
| 6189 ASSERT(proto->IsJSObject()); | 4855 ASSERT(proto->IsJSObject()); |
| 6190 AddInstruction(new(zone()) HCheckPrototypeMaps( | 4856 Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())), |
| 6191 Handle<JSObject>(JSObject::cast(map->prototype())), | 4857 Handle<JSObject>(JSObject::cast(proto)), |
| 6192 Handle<JSObject>(JSObject::cast(proto)), | 4858 zone(), top_info()); |
| 6193 zone(), | |
| 6194 top_info())); | |
| 6195 } | 4859 } |
| 6196 | 4860 |
| 6197 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | 4861 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
| 6198 Representation representation = ComputeLoadStoreRepresentation(map, lookup); | 4862 Representation representation = ComputeLoadStoreRepresentation(map, lookup); |
| 6199 bool transition_to_field = lookup->IsTransitionToField(*map); | 4863 bool transition_to_field = lookup->IsTransitionToField(*map); |
| 6200 | 4864 |
| 6201 HStoreNamedField *instr; | 4865 HStoreNamedField *instr; |
| 6202 if (FLAG_track_double_fields && representation.IsDouble()) { | 4866 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 6203 if (transition_to_field) { | 4867 if (transition_to_field) { |
| 6204 // The store requires a mutable HeapNumber to be allocated. | 4868 // The store requires a mutable HeapNumber to be allocated. |
| 6205 NoObservableSideEffectsScope no_side_effects(this); | 4869 NoObservableSideEffectsScope no_side_effects(this); |
| 6206 HInstruction* heap_number_size = AddInstruction(new(zone()) HConstant( | 4870 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); |
| 6207 HeapNumber::kSize)); | 4871 HInstruction* double_box = Add<HAllocate>( |
| 6208 HInstruction* double_box = AddInstruction(new(zone()) HAllocate( | |
| 6209 environment()->LookupContext(), heap_number_size, | 4872 environment()->LookupContext(), heap_number_size, |
| 6210 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE)); | 4873 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE); |
| 6211 AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); | 4874 AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); |
| 6212 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 4875 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), |
| 6213 value, Representation::Double()); | 4876 value, Representation::Double()); |
| 6214 instr = new(zone()) HStoreNamedField(object, field_access, double_box); | 4877 instr = new(zone()) HStoreNamedField(object, field_access, double_box); |
| 6215 } else { | 4878 } else { |
| 6216 // Already holds a HeapNumber; load the box and write its value field. | 4879 // Already holds a HeapNumber; load the box and write its value field. |
| 6217 HInstruction* double_box = AddLoad(object, field_access); | 4880 HInstruction* double_box = AddLoad(object, field_access); |
| 6218 double_box->set_type(HType::HeapNumber()); | 4881 double_box->set_type(HType::HeapNumber()); |
| 6219 instr = new(zone()) HStoreNamedField(double_box, | 4882 instr = new(zone()) HStoreNamedField(double_box, |
| 6220 HObjectAccess::ForHeapNumberValue(), value, Representation::Double()); | 4883 HObjectAccess::ForHeapNumberValue(), value, Representation::Double()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 6250 } | 4913 } |
| 6251 | 4914 |
| 6252 | 4915 |
| 6253 HInstruction* HOptimizedGraphBuilder::BuildCallSetter( | 4916 HInstruction* HOptimizedGraphBuilder::BuildCallSetter( |
| 6254 HValue* object, | 4917 HValue* object, |
| 6255 HValue* value, | 4918 HValue* value, |
| 6256 Handle<Map> map, | 4919 Handle<Map> map, |
| 6257 Handle<JSFunction> setter, | 4920 Handle<JSFunction> setter, |
| 6258 Handle<JSObject> holder) { | 4921 Handle<JSObject> holder) { |
| 6259 AddCheckConstantFunction(holder, object, map); | 4922 AddCheckConstantFunction(holder, object, map); |
| 6260 AddInstruction(new(zone()) HPushArgument(object)); | 4923 Add<HPushArgument>(object); |
| 6261 AddInstruction(new(zone()) HPushArgument(value)); | 4924 Add<HPushArgument>(value); |
| 6262 return new(zone()) HCallConstantFunction(setter, 2); | 4925 return new(zone()) HCallConstantFunction(setter, 2); |
| 6263 } | 4926 } |
| 6264 | 4927 |
| 6265 | 4928 |
| 6266 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( | 4929 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( |
| 6267 HValue* object, | 4930 HValue* object, |
| 6268 Handle<String> name, | 4931 Handle<String> name, |
| 6269 HValue* value, | 4932 HValue* value, |
| 6270 Handle<Map> map) { | 4933 Handle<Map> map) { |
| 6271 // Handle a store to a known field. | 4934 // Handle a store to a known field. |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6430 LookupResult lookup(isolate()); | 5093 LookupResult lookup(isolate()); |
| 6431 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 5094 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 6432 if (count == 0) { | 5095 if (count == 0) { |
| 6433 BuildCheckHeapObject(object); | 5096 BuildCheckHeapObject(object); |
| 6434 join = graph()->CreateBasicBlock(); | 5097 join = graph()->CreateBasicBlock(); |
| 6435 } | 5098 } |
| 6436 ++count; | 5099 ++count; |
| 6437 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5100 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 6438 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5101 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 6439 HCompareMap* compare = | 5102 HCompareMap* compare = |
| 6440 new(zone()) HCompareMap(object, map, if_true, if_false); | 5103 new(zone()) HCompareMap(object, map, if_true, if_false); |
| 6441 current_block()->Finish(compare); | 5104 current_block()->Finish(compare); |
| 6442 | 5105 |
| 6443 set_current_block(if_true); | 5106 set_current_block(if_true); |
| 6444 HInstruction* instr; | 5107 HInstruction* instr; |
| 6445 CHECK_ALIVE( | 5108 CHECK_ALIVE( |
| 6446 instr = BuildStoreNamedField(object, name, value, map, &lookup)); | 5109 instr = BuildStoreNamedField(object, name, value, map, &lookup)); |
| 6447 instr->set_position(position); | 5110 instr->set_position(position); |
| 6448 // Goto will add the HSimulate for the store. | 5111 // Goto will add the HSimulate for the store. |
| 6449 AddInstruction(instr); | 5112 AddInstruction(instr); |
| 6450 if (!ast_context()->IsEffect()) Push(value); | 5113 if (!ast_context()->IsEffect()) Push(value); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6531 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 5194 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 6532 Variable* var, | 5195 Variable* var, |
| 6533 HValue* value, | 5196 HValue* value, |
| 6534 int position, | 5197 int position, |
| 6535 BailoutId ast_id) { | 5198 BailoutId ast_id) { |
| 6536 LookupResult lookup(isolate()); | 5199 LookupResult lookup(isolate()); |
| 6537 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 5200 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 6538 if (type == kUseCell) { | 5201 if (type == kUseCell) { |
| 6539 Handle<GlobalObject> global(current_info()->global_object()); | 5202 Handle<GlobalObject> global(current_info()->global_object()); |
| 6540 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 5203 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 5204 if (cell->type()->IsConstant()) { |
| 5205 IfBuilder builder(this); |
| 5206 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); |
| 5207 if (cell->type()->AsConstant()->IsNumber()) { |
| 5208 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); |
| 5209 } else { |
| 5210 builder.If<HCompareObjectEqAndBranch>(value, constant); |
| 5211 } |
| 5212 builder.Then(); |
| 5213 builder.Else(); |
| 5214 AddSoftDeoptimize(MUST_EMIT_SOFT_DEOPT); |
| 5215 builder.End(); |
| 5216 } |
| 6541 HInstruction* instr = | 5217 HInstruction* instr = |
| 6542 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); | 5218 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
| 6543 instr->set_position(position); | 5219 instr->set_position(position); |
| 6544 AddInstruction(instr); | |
| 6545 if (instr->HasObservableSideEffects()) { | 5220 if (instr->HasObservableSideEffects()) { |
| 6546 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 5221 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 6547 } | 5222 } |
| 6548 } else { | 5223 } else { |
| 6549 HValue* context = environment()->LookupContext(); | 5224 HValue* context = environment()->LookupContext(); |
| 6550 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 5225 HGlobalObject* global_object = Add<HGlobalObject>(context); |
| 6551 AddInstruction(global_object); | |
| 6552 HStoreGlobalGeneric* instr = | 5226 HStoreGlobalGeneric* instr = |
| 6553 new(zone()) HStoreGlobalGeneric(context, | 5227 Add<HStoreGlobalGeneric>(context, global_object, var->name(), |
| 6554 global_object, | 5228 value, function_strict_mode_flag()); |
| 6555 var->name(), | |
| 6556 value, | |
| 6557 function_strict_mode_flag()); | |
| 6558 instr->set_position(position); | 5229 instr->set_position(position); |
| 6559 AddInstruction(instr); | |
| 6560 ASSERT(instr->HasObservableSideEffects()); | 5230 ASSERT(instr->HasObservableSideEffects()); |
| 6561 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 5231 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 6562 } | 5232 } |
| 6563 } | 5233 } |
| 6564 | 5234 |
| 6565 | 5235 |
| 6566 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, | 5236 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, |
| 6567 BailoutId id, | 5237 BailoutId id, |
| 6568 int position, | 5238 int position, |
| 6569 BailoutId assignment_id, | 5239 BailoutId assignment_id, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 6585 if (monomorphic) { | 5255 if (monomorphic) { |
| 6586 Handle<JSFunction> setter; | 5256 Handle<JSFunction> setter; |
| 6587 Handle<JSObject> holder; | 5257 Handle<JSObject> holder; |
| 6588 if (LookupSetter(map, name, &setter, &holder)) { | 5258 if (LookupSetter(map, name, &setter, &holder)) { |
| 6589 AddCheckConstantFunction(holder, object, map); | 5259 AddCheckConstantFunction(holder, object, map); |
| 6590 if (FLAG_inline_accessors && | 5260 if (FLAG_inline_accessors && |
| 6591 TryInlineSetter(setter, id, assignment_id, value)) { | 5261 TryInlineSetter(setter, id, assignment_id, value)) { |
| 6592 return; | 5262 return; |
| 6593 } | 5263 } |
| 6594 Drop(2); | 5264 Drop(2); |
| 6595 AddInstruction(new(zone()) HPushArgument(object)); | 5265 Add<HPushArgument>(object); |
| 6596 AddInstruction(new(zone()) HPushArgument(value)); | 5266 Add<HPushArgument>(value); |
| 6597 instr = new(zone()) HCallConstantFunction(setter, 2); | 5267 instr = new(zone()) HCallConstantFunction(setter, 2); |
| 6598 } else { | 5268 } else { |
| 6599 Drop(2); | 5269 Drop(2); |
| 6600 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | 5270 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
| 6601 name, | 5271 name, |
| 6602 value, | 5272 value, |
| 6603 map)); | 5273 map)); |
| 6604 } | 5274 } |
| 6605 | 5275 |
| 6606 } else if (types != NULL && types->length() > 1) { | 5276 } else if (types != NULL && types->length() > 1) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6683 return ast_context()->ReturnValue(Pop()); | 5353 return ast_context()->ReturnValue(Pop()); |
| 6684 case CONST_HARMONY: | 5354 case CONST_HARMONY: |
| 6685 // This case is checked statically so no need to | 5355 // This case is checked statically so no need to |
| 6686 // perform checks here | 5356 // perform checks here |
| 6687 UNREACHABLE(); | 5357 UNREACHABLE(); |
| 6688 default: | 5358 default: |
| 6689 mode = HStoreContextSlot::kNoCheck; | 5359 mode = HStoreContextSlot::kNoCheck; |
| 6690 } | 5360 } |
| 6691 | 5361 |
| 6692 HValue* context = BuildContextChainWalk(var); | 5362 HValue* context = BuildContextChainWalk(var); |
| 6693 HStoreContextSlot* instr = | 5363 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
| 6694 new(zone()) HStoreContextSlot(context, var->index(), mode, Top()); | 5364 mode, Top()); |
| 6695 AddInstruction(instr); | |
| 6696 if (instr->HasObservableSideEffects()) { | 5365 if (instr->HasObservableSideEffects()) { |
| 6697 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5366 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 6698 } | 5367 } |
| 6699 break; | 5368 break; |
| 6700 } | 5369 } |
| 6701 | 5370 |
| 6702 case Variable::LOOKUP: | 5371 case Variable::LOOKUP: |
| 6703 return Bailout("compound assignment to lookup slot"); | 5372 return Bailout("compound assignment to lookup slot"); |
| 6704 } | 5373 } |
| 6705 return ast_context()->ReturnValue(Pop()); | 5374 return ast_context()->ReturnValue(Pop()); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6815 if (var->mode() == CONST) { | 5484 if (var->mode() == CONST) { |
| 6816 if (expr->op() != Token::INIT_CONST) { | 5485 if (expr->op() != Token::INIT_CONST) { |
| 6817 CHECK_ALIVE(VisitForValue(expr->value())); | 5486 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6818 return ast_context()->ReturnValue(Pop()); | 5487 return ast_context()->ReturnValue(Pop()); |
| 6819 } | 5488 } |
| 6820 | 5489 |
| 6821 if (var->IsStackAllocated()) { | 5490 if (var->IsStackAllocated()) { |
| 6822 // We insert a use of the old value to detect unsupported uses of const | 5491 // We insert a use of the old value to detect unsupported uses of const |
| 6823 // variables (e.g. initialization inside a loop). | 5492 // variables (e.g. initialization inside a loop). |
| 6824 HValue* old_value = environment()->Lookup(var); | 5493 HValue* old_value = environment()->Lookup(var); |
| 6825 AddInstruction(new(zone()) HUseConst(old_value)); | 5494 Add<HUseConst>(old_value); |
| 6826 } | 5495 } |
| 6827 } else if (var->mode() == CONST_HARMONY) { | 5496 } else if (var->mode() == CONST_HARMONY) { |
| 6828 if (expr->op() != Token::INIT_CONST_HARMONY) { | 5497 if (expr->op() != Token::INIT_CONST_HARMONY) { |
| 6829 return Bailout("non-initializer assignment to const"); | 5498 return Bailout("non-initializer assignment to const"); |
| 6830 } | 5499 } |
| 6831 } | 5500 } |
| 6832 | 5501 |
| 6833 if (proxy->IsArguments()) return Bailout("assignment to arguments"); | 5502 if (proxy->IsArguments()) return Bailout("assignment to arguments"); |
| 6834 | 5503 |
| 6835 // Handle the assignment. | 5504 // Handle the assignment. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6896 expr->op() == Token::INIT_LET || | 5565 expr->op() == Token::INIT_LET || |
| 6897 expr->op() == Token::INIT_CONST_HARMONY) { | 5566 expr->op() == Token::INIT_CONST_HARMONY) { |
| 6898 mode = HStoreContextSlot::kNoCheck; | 5567 mode = HStoreContextSlot::kNoCheck; |
| 6899 } else { | 5568 } else { |
| 6900 ASSERT(expr->op() == Token::INIT_CONST); | 5569 ASSERT(expr->op() == Token::INIT_CONST); |
| 6901 | 5570 |
| 6902 mode = HStoreContextSlot::kCheckIgnoreAssignment; | 5571 mode = HStoreContextSlot::kCheckIgnoreAssignment; |
| 6903 } | 5572 } |
| 6904 | 5573 |
| 6905 HValue* context = BuildContextChainWalk(var); | 5574 HValue* context = BuildContextChainWalk(var); |
| 6906 HStoreContextSlot* instr = new(zone()) HStoreContextSlot( | 5575 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
| 6907 context, var->index(), mode, Top()); | 5576 mode, Top()); |
| 6908 AddInstruction(instr); | |
| 6909 if (instr->HasObservableSideEffects()) { | 5577 if (instr->HasObservableSideEffects()) { |
| 6910 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5578 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 6911 } | 5579 } |
| 6912 return ast_context()->ReturnValue(Pop()); | 5580 return ast_context()->ReturnValue(Pop()); |
| 6913 } | 5581 } |
| 6914 | 5582 |
| 6915 case Variable::LOOKUP: | 5583 case Variable::LOOKUP: |
| 6916 return Bailout("assignment to LOOKUP variable"); | 5584 return Bailout("assignment to LOOKUP variable"); |
| 6917 } | 5585 } |
| 6918 } else { | 5586 } else { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 6932 ASSERT(current_block() != NULL); | 5600 ASSERT(current_block() != NULL); |
| 6933 ASSERT(current_block()->HasPredecessor()); | 5601 ASSERT(current_block()->HasPredecessor()); |
| 6934 // We don't optimize functions with invalid left-hand sides in | 5602 // We don't optimize functions with invalid left-hand sides in |
| 6935 // assignments, count operations, or for-in. Consequently throw can | 5603 // assignments, count operations, or for-in. Consequently throw can |
| 6936 // currently only occur in an effect context. | 5604 // currently only occur in an effect context. |
| 6937 ASSERT(ast_context()->IsEffect()); | 5605 ASSERT(ast_context()->IsEffect()); |
| 6938 CHECK_ALIVE(VisitForValue(expr->exception())); | 5606 CHECK_ALIVE(VisitForValue(expr->exception())); |
| 6939 | 5607 |
| 6940 HValue* context = environment()->LookupContext(); | 5608 HValue* context = environment()->LookupContext(); |
| 6941 HValue* value = environment()->Pop(); | 5609 HValue* value = environment()->Pop(); |
| 6942 HThrow* instr = new(zone()) HThrow(context, value); | 5610 HThrow* instr = Add<HThrow>(context, value); |
| 6943 instr->set_position(expr->position()); | 5611 instr->set_position(expr->position()); |
| 6944 AddInstruction(instr); | |
| 6945 AddSimulate(expr->id()); | 5612 AddSimulate(expr->id()); |
| 6946 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5613 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 6947 set_current_block(NULL); | 5614 set_current_block(NULL); |
| 6948 } | 5615 } |
| 6949 | 5616 |
| 6950 | 5617 |
| 6951 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( | 5618 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( |
| 6952 HValue* object, | 5619 HValue* object, |
| 6953 HObjectAccess access, | 5620 HObjectAccess access, |
| 6954 Representation representation) { | 5621 Representation representation) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 6980 return new(zone()) HLoadNamedGeneric(context, object, name); | 5647 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 6981 } | 5648 } |
| 6982 | 5649 |
| 6983 | 5650 |
| 6984 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 5651 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
| 6985 HValue* object, | 5652 HValue* object, |
| 6986 Handle<Map> map, | 5653 Handle<Map> map, |
| 6987 Handle<JSFunction> getter, | 5654 Handle<JSFunction> getter, |
| 6988 Handle<JSObject> holder) { | 5655 Handle<JSObject> holder) { |
| 6989 AddCheckConstantFunction(holder, object, map); | 5656 AddCheckConstantFunction(holder, object, map); |
| 6990 AddInstruction(new(zone()) HPushArgument(object)); | 5657 Add<HPushArgument>(object); |
| 6991 return new(zone()) HCallConstantFunction(getter, 1); | 5658 return new(zone()) HCallConstantFunction(getter, 1); |
| 6992 } | 5659 } |
| 6993 | 5660 |
| 6994 | 5661 |
| 6995 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( | 5662 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( |
| 6996 HValue* object, | 5663 HValue* object, |
| 6997 Handle<String> name, | 5664 Handle<String> name, |
| 6998 Property* expr, | 5665 Property* expr, |
| 6999 Handle<Map> map) { | 5666 Handle<Map> map) { |
| 7000 // Handle a load from a known field. | 5667 // Handle a load from a known field. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 7025 return new(zone()) HConstant(function); | 5692 return new(zone()) HConstant(function); |
| 7026 } | 5693 } |
| 7027 | 5694 |
| 7028 // Handle a load from a known field somewhere in the prototype chain. | 5695 // Handle a load from a known field somewhere in the prototype chain. |
| 7029 LookupInPrototypes(map, name, &lookup); | 5696 LookupInPrototypes(map, name, &lookup); |
| 7030 if (lookup.IsField()) { | 5697 if (lookup.IsField()) { |
| 7031 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5698 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7032 Handle<JSObject> holder(lookup.holder()); | 5699 Handle<JSObject> holder(lookup.holder()); |
| 7033 Handle<Map> holder_map(holder->map()); | 5700 Handle<Map> holder_map(holder->map()); |
| 7034 AddCheckMap(object, map); | 5701 AddCheckMap(object, map); |
| 7035 AddInstruction(new(zone()) HCheckPrototypeMaps( | 5702 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); |
| 7036 prototype, holder, zone(), top_info())); | 5703 HValue* holder_value = Add<HConstant>(holder); |
| 7037 HValue* holder_value = AddInstruction(new(zone()) HConstant(holder)); | |
| 7038 return BuildLoadNamedField(holder_value, | 5704 return BuildLoadNamedField(holder_value, |
| 7039 HObjectAccess::ForField(holder_map, &lookup, name), | 5705 HObjectAccess::ForField(holder_map, &lookup, name), |
| 7040 ComputeLoadStoreRepresentation(map, &lookup)); | 5706 ComputeLoadStoreRepresentation(map, &lookup)); |
| 7041 } | 5707 } |
| 7042 | 5708 |
| 7043 // Handle a load of a constant function somewhere in the prototype chain. | 5709 // Handle a load of a constant function somewhere in the prototype chain. |
| 7044 if (lookup.IsConstantFunction()) { | 5710 if (lookup.IsConstantFunction()) { |
| 7045 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5711 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7046 Handle<JSObject> holder(lookup.holder()); | 5712 Handle<JSObject> holder(lookup.holder()); |
| 7047 Handle<Map> holder_map(holder->map()); | 5713 Handle<Map> holder_map(holder->map()); |
| 7048 AddCheckMap(object, map); | 5714 AddCheckMap(object, map); |
| 7049 AddInstruction(new(zone()) HCheckPrototypeMaps( | 5715 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); |
| 7050 prototype, holder, zone(), top_info())); | |
| 7051 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); | 5716 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); |
| 7052 return new(zone()) HConstant(function); | 5717 return new(zone()) HConstant(function); |
| 7053 } | 5718 } |
| 7054 | 5719 |
| 7055 // No luck, do a generic load. | 5720 // No luck, do a generic load. |
| 7056 return BuildLoadNamedGeneric(object, name, expr); | 5721 return BuildLoadNamedGeneric(object, name, expr); |
| 7057 } | 5722 } |
| 7058 | 5723 |
| 7059 | 5724 |
| 7060 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 5725 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 7077 if (dependency) { | 5742 if (dependency) { |
| 7078 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 5743 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
| 7079 } | 5744 } |
| 7080 | 5745 |
| 7081 // Loads from a "stock" fast holey double arrays can elide the hole check. | 5746 // Loads from a "stock" fast holey double arrays can elide the hole check. |
| 7082 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 5747 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
| 7083 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 5748 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
| 7084 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 5749 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
| 7085 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); | 5750 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
| 7086 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); | 5751 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); |
| 7087 AddInstruction(new(zone()) HCheckPrototypeMaps( | 5752 Add<HCheckPrototypeMaps>(prototype, object_prototype, zone(), top_info()); |
| 7088 prototype, object_prototype, zone(), top_info())); | |
| 7089 load_mode = ALLOW_RETURN_HOLE; | 5753 load_mode = ALLOW_RETURN_HOLE; |
| 7090 graph()->MarkDependsOnEmptyArrayProtoElements(); | 5754 graph()->MarkDependsOnEmptyArrayProtoElements(); |
| 7091 } | 5755 } |
| 7092 | 5756 |
| 7093 return BuildUncheckedMonomorphicElementAccess( | 5757 return BuildUncheckedMonomorphicElementAccess( |
| 7094 object, key, val, | 5758 object, key, val, |
| 7095 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | 5759 mapcheck, map->instance_type() == JS_ARRAY_TYPE, |
| 7096 map->elements_kind(), is_store, load_mode, store_mode); | 5760 map->elements_kind(), is_store, load_mode, store_mode); |
| 7097 } | 5761 } |
| 7098 | 5762 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7210 Handle<Map> untransitionable_map; | 5874 Handle<Map> untransitionable_map; |
| 7211 HTransitionElementsKind* transition = NULL; | 5875 HTransitionElementsKind* transition = NULL; |
| 7212 for (int i = 0; i < maps->length(); ++i) { | 5876 for (int i = 0; i < maps->length(); ++i) { |
| 7213 Handle<Map> map = maps->at(i); | 5877 Handle<Map> map = maps->at(i); |
| 7214 ASSERT(map->IsMap()); | 5878 ASSERT(map->IsMap()); |
| 7215 if (!transition_target.at(i).is_null()) { | 5879 if (!transition_target.at(i).is_null()) { |
| 7216 ASSERT(Map::IsValidElementsTransition( | 5880 ASSERT(Map::IsValidElementsTransition( |
| 7217 map->elements_kind(), | 5881 map->elements_kind(), |
| 7218 transition_target.at(i)->elements_kind())); | 5882 transition_target.at(i)->elements_kind())); |
| 7219 HValue* context = environment()->LookupContext(); | 5883 HValue* context = environment()->LookupContext(); |
| 7220 transition = new(zone()) HTransitionElementsKind( | 5884 transition = Add<HTransitionElementsKind>(context, object, map, |
| 7221 context, object, map, transition_target.at(i)); | 5885 transition_target.at(i)); |
| 7222 AddInstruction(transition); | |
| 7223 } else { | 5886 } else { |
| 7224 type_todo[map->elements_kind()] = true; | 5887 type_todo[map->elements_kind()] = true; |
| 7225 if (IsExternalArrayElementsKind(map->elements_kind())) { | 5888 if (IsExternalArrayElementsKind(map->elements_kind())) { |
| 7226 todo_external_array = true; | 5889 todo_external_array = true; |
| 7227 } | 5890 } |
| 7228 num_untransitionable_maps++; | 5891 num_untransitionable_maps++; |
| 7229 untransitionable_map = map; | 5892 untransitionable_map = map; |
| 7230 } | 5893 } |
| 7231 } | 5894 } |
| 7232 | 5895 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 7245 } | 5908 } |
| 7246 *has_side_effects |= instr->HasObservableSideEffects(); | 5909 *has_side_effects |= instr->HasObservableSideEffects(); |
| 7247 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5910 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
| 7248 return is_store ? NULL : instr; | 5911 return is_store ? NULL : instr; |
| 7249 } | 5912 } |
| 7250 | 5913 |
| 7251 HInstruction* checkspec = | 5914 HInstruction* checkspec = |
| 7252 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); | 5915 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); |
| 7253 HBasicBlock* join = graph()->CreateBasicBlock(); | 5916 HBasicBlock* join = graph()->CreateBasicBlock(); |
| 7254 | 5917 |
| 7255 HInstruction* elements_kind_instr = | 5918 HInstruction* elements_kind_instr = Add<HElementsKind>(object); |
| 7256 AddInstruction(new(zone()) HElementsKind(object)); | |
| 7257 HInstruction* elements = AddLoadElements(object, checkspec); | 5919 HInstruction* elements = AddLoadElements(object, checkspec); |
| 7258 HLoadExternalArrayPointer* external_elements = NULL; | 5920 HLoadExternalArrayPointer* external_elements = NULL; |
| 7259 HInstruction* checked_key = NULL; | 5921 HInstruction* checked_key = NULL; |
| 7260 | 5922 |
| 7261 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds | 5923 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds |
| 7262 // are handled before external arrays. | 5924 // are handled before external arrays. |
| 7263 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5925 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
| 7264 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5926 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
| 7265 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5927 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
| 7266 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5928 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
| 7267 | 5929 |
| 7268 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; | 5930 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; |
| 7269 elements_kind <= LAST_ELEMENTS_KIND; | 5931 elements_kind <= LAST_ELEMENTS_KIND; |
| 7270 elements_kind = ElementsKind(elements_kind + 1)) { | 5932 elements_kind = ElementsKind(elements_kind + 1)) { |
| 7271 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some | 5933 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some |
| 7272 // code that's executed for all external array cases. | 5934 // code that's executed for all external array cases. |
| 7273 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == | 5935 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == |
| 7274 LAST_ELEMENTS_KIND); | 5936 LAST_ELEMENTS_KIND); |
| 7275 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND | 5937 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND |
| 7276 && todo_external_array) { | 5938 && todo_external_array) { |
| 7277 HInstruction* length = | 5939 HInstruction* length = AddLoadFixedArrayLength(elements); |
| 7278 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 5940 checked_key = Add<HBoundsCheck>(key, length); |
| 7279 checked_key = AddBoundsCheck(key, length); | 5941 external_elements = Add<HLoadExternalArrayPointer>(elements); |
| 7280 external_elements = new(zone()) HLoadExternalArrayPointer(elements); | |
| 7281 AddInstruction(external_elements); | |
| 7282 } | 5942 } |
| 7283 if (type_todo[elements_kind]) { | 5943 if (type_todo[elements_kind]) { |
| 7284 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5944 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 7285 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5945 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 7286 HCompareConstantEqAndBranch* elements_kind_branch = | 5946 HCompareConstantEqAndBranch* elements_kind_branch = |
| 7287 new(zone()) HCompareConstantEqAndBranch( | 5947 new(zone()) HCompareConstantEqAndBranch( |
| 7288 elements_kind_instr, elements_kind, Token::EQ_STRICT); | 5948 elements_kind_instr, elements_kind, Token::EQ_STRICT); |
| 7289 elements_kind_branch->SetSuccessorAt(0, if_true); | 5949 elements_kind_branch->SetSuccessorAt(0, if_true); |
| 7290 elements_kind_branch->SetSuccessorAt(1, if_false); | 5950 elements_kind_branch->SetSuccessorAt(1, if_false); |
| 7291 current_block()->Finish(elements_kind_branch); | 5951 current_block()->Finish(elements_kind_branch); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 7312 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | 5972 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
| 7313 typecheck->SetSuccessorAt(0, if_jsarray); | 5973 typecheck->SetSuccessorAt(0, if_jsarray); |
| 7314 typecheck->SetSuccessorAt(1, if_fastobject); | 5974 typecheck->SetSuccessorAt(1, if_fastobject); |
| 7315 current_block()->Finish(typecheck); | 5975 current_block()->Finish(typecheck); |
| 7316 | 5976 |
| 7317 set_current_block(if_jsarray); | 5977 set_current_block(if_jsarray); |
| 7318 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(), | 5978 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(), |
| 7319 typecheck, Representation::Smi()); | 5979 typecheck, Representation::Smi()); |
| 7320 length->set_type(HType::Smi()); | 5980 length->set_type(HType::Smi()); |
| 7321 | 5981 |
| 7322 checked_key = AddBoundsCheck(key, length); | 5982 checked_key = Add<HBoundsCheck>(key, length); |
| 7323 access = AddInstruction(BuildFastElementAccess( | 5983 access = AddInstruction(BuildFastElementAccess( |
| 7324 elements, checked_key, val, elements_kind_branch, | 5984 elements, checked_key, val, elements_kind_branch, |
| 7325 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); | 5985 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); |
| 7326 if (!is_store) { | 5986 if (!is_store) { |
| 7327 Push(access); | 5987 Push(access); |
| 7328 } | 5988 } |
| 7329 | 5989 |
| 7330 *has_side_effects |= access->HasObservableSideEffects(); | 5990 *has_side_effects |= access->HasObservableSideEffects(); |
| 7331 // The caller will use has_side_effects and add correct Simulate. | 5991 // The caller will use has_side_effects and add correct Simulate. |
| 7332 access->SetFlag(HValue::kHasNoObservableSideEffects); | 5992 access->SetFlag(HValue::kHasNoObservableSideEffects); |
| 7333 if (position != -1) { | 5993 if (position != -1) { |
| 7334 access->set_position(position); | 5994 access->set_position(position); |
| 7335 } | 5995 } |
| 7336 if_jsarray->GotoNoSimulate(join); | 5996 if_jsarray->GotoNoSimulate(join); |
| 7337 | 5997 |
| 7338 set_current_block(if_fastobject); | 5998 set_current_block(if_fastobject); |
| 7339 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 5999 length = AddLoadFixedArrayLength(elements); |
| 7340 checked_key = AddBoundsCheck(key, length); | 6000 checked_key = Add<HBoundsCheck>(key, length); |
| 7341 access = AddInstruction(BuildFastElementAccess( | 6001 access = AddInstruction(BuildFastElementAccess( |
| 7342 elements, checked_key, val, elements_kind_branch, | 6002 elements, checked_key, val, elements_kind_branch, |
| 7343 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); | 6003 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); |
| 7344 } else if (elements_kind == DICTIONARY_ELEMENTS) { | 6004 } else if (elements_kind == DICTIONARY_ELEMENTS) { |
| 7345 if (is_store) { | 6005 if (is_store) { |
| 7346 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 6006 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
| 7347 } else { | 6007 } else { |
| 7348 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 6008 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
| 7349 } | 6009 } |
| 7350 } else { // External array elements. | 6010 } else { // External array elements. |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7462 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { | 6122 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { |
| 7463 return false; | 6123 return false; |
| 7464 } | 6124 } |
| 7465 | 6125 |
| 7466 HInstruction* result = NULL; | 6126 HInstruction* result = NULL; |
| 7467 if (expr->key()->IsPropertyName()) { | 6127 if (expr->key()->IsPropertyName()) { |
| 7468 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6128 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 7469 if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("length"))) return false; | 6129 if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("length"))) return false; |
| 7470 | 6130 |
| 7471 if (function_state()->outer() == NULL) { | 6131 if (function_state()->outer() == NULL) { |
| 7472 HInstruction* elements = AddInstruction( | 6132 HInstruction* elements = Add<HArgumentsElements>(false); |
| 7473 new(zone()) HArgumentsElements(false)); | |
| 7474 result = new(zone()) HArgumentsLength(elements); | 6133 result = new(zone()) HArgumentsLength(elements); |
| 7475 } else { | 6134 } else { |
| 7476 // Number of arguments without receiver. | 6135 // Number of arguments without receiver. |
| 7477 int argument_count = environment()-> | 6136 int argument_count = environment()-> |
| 7478 arguments_environment()->parameter_count() - 1; | 6137 arguments_environment()->parameter_count() - 1; |
| 7479 result = new(zone()) HConstant(argument_count); | 6138 result = new(zone()) HConstant(argument_count); |
| 7480 } | 6139 } |
| 7481 } else { | 6140 } else { |
| 7482 Push(graph()->GetArgumentsObject()); | 6141 Push(graph()->GetArgumentsObject()); |
| 7483 VisitForValue(expr->key()); | 6142 VisitForValue(expr->key()); |
| 7484 if (HasStackOverflow() || current_block() == NULL) return true; | 6143 if (HasStackOverflow() || current_block() == NULL) return true; |
| 7485 HValue* key = Pop(); | 6144 HValue* key = Pop(); |
| 7486 Drop(1); // Arguments object. | 6145 Drop(1); // Arguments object. |
| 7487 if (function_state()->outer() == NULL) { | 6146 if (function_state()->outer() == NULL) { |
| 7488 HInstruction* elements = AddInstruction( | 6147 HInstruction* elements = Add<HArgumentsElements>(false); |
| 7489 new(zone()) HArgumentsElements(false)); | 6148 HInstruction* length = Add<HArgumentsLength>(elements); |
| 7490 HInstruction* length = AddInstruction( | 6149 HInstruction* checked_key = Add<HBoundsCheck>(key, length); |
| 7491 new(zone()) HArgumentsLength(elements)); | |
| 7492 HInstruction* checked_key = AddBoundsCheck(key, length); | |
| 7493 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 6150 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
| 7494 } else { | 6151 } else { |
| 7495 EnsureArgumentsArePushedForAccess(); | 6152 EnsureArgumentsArePushedForAccess(); |
| 7496 | 6153 |
| 7497 // Number of arguments without receiver. | 6154 // Number of arguments without receiver. |
| 7498 HInstruction* elements = function_state()->arguments_elements(); | 6155 HInstruction* elements = function_state()->arguments_elements(); |
| 7499 int argument_count = environment()-> | 6156 int argument_count = environment()-> |
| 7500 arguments_environment()->parameter_count() - 1; | 6157 arguments_environment()->parameter_count() - 1; |
| 7501 HInstruction* length = AddInstruction(new(zone()) HConstant( | 6158 HInstruction* length = Add<HConstant>(argument_count); |
| 7502 argument_count)); | 6159 HInstruction* checked_key = Add<HBoundsCheck>(key, length); |
| 7503 HInstruction* checked_key = AddBoundsCheck(key, length); | |
| 7504 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 6160 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
| 7505 } | 6161 } |
| 7506 } | 6162 } |
| 7507 ast_context()->ReturnInstruction(result, expr->id()); | 6163 ast_context()->ReturnInstruction(result, expr->id()); |
| 7508 return true; | 6164 return true; |
| 7509 } | 6165 } |
| 7510 | 6166 |
| 7511 | 6167 |
| 7512 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 6168 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
| 7513 ASSERT(!HasStackOverflow()); | 6169 ASSERT(!HasStackOverflow()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7552 } else if (object->HasMonomorphicJSObjectType()) { | 6208 } else if (object->HasMonomorphicJSObjectType()) { |
| 7553 map = object->GetMonomorphicJSObjectMap(); | 6209 map = object->GetMonomorphicJSObjectMap(); |
| 7554 monomorphic = !map->is_dictionary_map(); | 6210 monomorphic = !map->is_dictionary_map(); |
| 7555 } | 6211 } |
| 7556 if (monomorphic) { | 6212 if (monomorphic) { |
| 7557 Handle<JSFunction> getter; | 6213 Handle<JSFunction> getter; |
| 7558 Handle<JSObject> holder; | 6214 Handle<JSObject> holder; |
| 7559 if (LookupGetter(map, name, &getter, &holder)) { | 6215 if (LookupGetter(map, name, &getter, &holder)) { |
| 7560 AddCheckConstantFunction(holder, Top(), map); | 6216 AddCheckConstantFunction(holder, Top(), map); |
| 7561 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; | 6217 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; |
| 7562 AddInstruction(new(zone()) HPushArgument(Pop())); | 6218 Add<HPushArgument>(Pop()); |
| 7563 instr = new(zone()) HCallConstantFunction(getter, 1); | 6219 instr = new(zone()) HCallConstantFunction(getter, 1); |
| 7564 } else { | 6220 } else { |
| 7565 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); | 6221 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); |
| 7566 } | 6222 } |
| 7567 } else if (types != NULL && types->length() > 1) { | 6223 } else if (types != NULL && types->length() > 1) { |
| 7568 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); | 6224 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); |
| 7569 } else { | 6225 } else { |
| 7570 instr = BuildLoadNamedGeneric(Pop(), name, expr); | 6226 instr = BuildLoadNamedGeneric(Pop(), name, expr); |
| 7571 } | 6227 } |
| 7572 | 6228 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 7594 } | 6250 } |
| 7595 instr->set_position(expr->position()); | 6251 instr->set_position(expr->position()); |
| 7596 return ast_context()->ReturnInstruction(instr, expr->id()); | 6252 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7597 } | 6253 } |
| 7598 | 6254 |
| 7599 | 6255 |
| 7600 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 6256 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 7601 Handle<Map> receiver_map) { | 6257 Handle<Map> receiver_map) { |
| 7602 if (!holder.is_null()) { | 6258 if (!holder.is_null()) { |
| 7603 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 6259 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
| 7604 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6260 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); |
| 7605 prototype, holder, zone(), top_info())); | |
| 7606 } | 6261 } |
| 7607 } | 6262 } |
| 7608 | 6263 |
| 7609 | 6264 |
| 7610 void HOptimizedGraphBuilder::AddCheckConstantFunction( | 6265 void HOptimizedGraphBuilder::AddCheckConstantFunction( |
| 7611 Handle<JSObject> holder, | 6266 Handle<JSObject> holder, |
| 7612 HValue* receiver, | 6267 HValue* receiver, |
| 7613 Handle<Map> receiver_map) { | 6268 Handle<Map> receiver_map) { |
| 7614 // Constant functions have the nice property that the map will change if they | 6269 // Constant functions have the nice property that the map will change if they |
| 7615 // are overwritten. Therefore it is enough to check the map of the holder and | 6270 // are overwritten. Therefore it is enough to check the map of the holder and |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7867 int nodes_added = InliningAstSize(target); | 6522 int nodes_added = InliningAstSize(target); |
| 7868 if (nodes_added == kNotInlinable) return false; | 6523 if (nodes_added == kNotInlinable) return false; |
| 7869 | 6524 |
| 7870 Handle<JSFunction> caller = current_info()->closure(); | 6525 Handle<JSFunction> caller = current_info()->closure(); |
| 7871 | 6526 |
| 7872 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { | 6527 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { |
| 7873 TraceInline(target, caller, "target AST is too large [early]"); | 6528 TraceInline(target, caller, "target AST is too large [early]"); |
| 7874 return false; | 6529 return false; |
| 7875 } | 6530 } |
| 7876 | 6531 |
| 7877 #if !defined(V8_TARGET_ARCH_IA32) | 6532 #if !V8_TARGET_ARCH_IA32 |
| 7878 // Target must be able to use caller's context. | 6533 // Target must be able to use caller's context. |
| 7879 CompilationInfo* outer_info = current_info(); | 6534 CompilationInfo* outer_info = current_info(); |
| 7880 if (target->context() != outer_info->closure()->context() || | 6535 if (target->context() != outer_info->closure()->context() || |
| 7881 outer_info->scope()->contains_with() || | 6536 outer_info->scope()->contains_with() || |
| 7882 outer_info->scope()->num_heap_slots() > 0) { | 6537 outer_info->scope()->num_heap_slots() > 0) { |
| 7883 TraceInline(target, caller, "target requires context change"); | 6538 TraceInline(target, caller, "target requires context change"); |
| 7884 return false; | 6539 return false; |
| 7885 } | 6540 } |
| 7886 #endif | 6541 #endif |
| 7887 | 6542 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8016 HConstant* undefined = graph()->GetConstantUndefined(); | 6671 HConstant* undefined = graph()->GetConstantUndefined(); |
| 8017 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( | 6672 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( |
| 8018 target, function, call_kind, inlining_kind); | 6673 target, function, call_kind, inlining_kind); |
| 8019 HEnvironment* inner_env = | 6674 HEnvironment* inner_env = |
| 8020 environment()->CopyForInlining(target, | 6675 environment()->CopyForInlining(target, |
| 8021 arguments_count, | 6676 arguments_count, |
| 8022 function, | 6677 function, |
| 8023 undefined, | 6678 undefined, |
| 8024 function_state()->inlining_kind(), | 6679 function_state()->inlining_kind(), |
| 8025 undefined_receiver); | 6680 undefined_receiver); |
| 8026 #ifdef V8_TARGET_ARCH_IA32 | 6681 #if V8_TARGET_ARCH_IA32 |
| 8027 // IA32 only, overwrite the caller's context in the deoptimization | 6682 // IA32 only, overwrite the caller's context in the deoptimization |
| 8028 // environment with the correct one. | 6683 // environment with the correct one. |
| 8029 // | 6684 // |
| 8030 // TODO(kmillikin): implement the same inlining on other platforms so we | 6685 // TODO(kmillikin): implement the same inlining on other platforms so we |
| 8031 // can remove the unsightly ifdefs in this function. | 6686 // can remove the unsightly ifdefs in this function. |
| 8032 HConstant* context = | 6687 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); |
| 8033 new(zone()) HConstant(Handle<Context>(target->context())); | |
| 8034 AddInstruction(context); | |
| 8035 inner_env->BindContext(context); | 6688 inner_env->BindContext(context); |
| 8036 #endif | 6689 #endif |
| 8037 | 6690 |
| 8038 AddSimulate(return_id); | 6691 AddSimulate(return_id); |
| 8039 current_block()->UpdateEnvironment(inner_env); | 6692 current_block()->UpdateEnvironment(inner_env); |
| 8040 HArgumentsObject* arguments_object = NULL; | 6693 HArgumentsObject* arguments_object = NULL; |
| 8041 | 6694 |
| 8042 // If the function uses arguments object create and bind one, also copy | 6695 // If the function uses arguments object create and bind one, also copy |
| 8043 // current arguments values to use them for materialization. | 6696 // current arguments values to use them for materialization. |
| 8044 if (function->scope()->arguments() != NULL) { | 6697 if (function->scope()->arguments() != NULL) { |
| 8045 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 6698 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
| 8046 HEnvironment* arguments_env = inner_env->arguments_environment(); | 6699 HEnvironment* arguments_env = inner_env->arguments_environment(); |
| 8047 int arguments_count = arguments_env->parameter_count(); | 6700 int arguments_count = arguments_env->parameter_count(); |
| 8048 arguments_object = new(zone()) HArgumentsObject(arguments_count, zone()); | 6701 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); |
| 8049 inner_env->Bind(function->scope()->arguments(), arguments_object); | 6702 inner_env->Bind(function->scope()->arguments(), arguments_object); |
| 8050 for (int i = 0; i < arguments_count; i++) { | 6703 for (int i = 0; i < arguments_count; i++) { |
| 8051 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); | 6704 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); |
| 8052 } | 6705 } |
| 8053 AddInstruction(arguments_object); | |
| 8054 } | 6706 } |
| 8055 | 6707 |
| 8056 HEnterInlined* enter_inlined = | 6708 HEnterInlined* enter_inlined = |
| 8057 new(zone()) HEnterInlined(target, | 6709 Add<HEnterInlined>(target, arguments_count, function, |
| 8058 arguments_count, | 6710 function_state()->inlining_kind(), |
| 8059 function, | 6711 function->scope()->arguments(), |
| 8060 function_state()->inlining_kind(), | 6712 arguments_object, undefined_receiver, zone()); |
| 8061 function->scope()->arguments(), | |
| 8062 arguments_object, | |
| 8063 undefined_receiver, | |
| 8064 zone()); | |
| 8065 function_state()->set_entry(enter_inlined); | 6713 function_state()->set_entry(enter_inlined); |
| 8066 AddInstruction(enter_inlined); | |
| 8067 | 6714 |
| 8068 VisitDeclarations(target_info.scope()->declarations()); | 6715 VisitDeclarations(target_info.scope()->declarations()); |
| 8069 VisitStatements(function->body()); | 6716 VisitStatements(function->body()); |
| 8070 if (HasStackOverflow()) { | 6717 if (HasStackOverflow()) { |
| 8071 // Bail out if the inline function did, as we cannot residualize a call | 6718 // Bail out if the inline function did, as we cannot residualize a call |
| 8072 // instead. | 6719 // instead. |
| 8073 TraceInline(target, caller, "inline graph construction failed"); | 6720 TraceInline(target, caller, "inline graph construction failed"); |
| 8074 target_shared->DisableOptimization("inlining bailed out"); | 6721 target_shared->DisableOptimization("inlining bailed out"); |
| 8075 inline_bailout_ = true; | 6722 inline_bailout_ = true; |
| 8076 delete target_state; | 6723 delete target_state; |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8294 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 6941 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 8295 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 6942 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 8296 switch (id) { | 6943 switch (id) { |
| 8297 case kStringCharCodeAt: | 6944 case kStringCharCodeAt: |
| 8298 case kStringCharAt: | 6945 case kStringCharAt: |
| 8299 if (argument_count == 2 && check_type == STRING_CHECK) { | 6946 if (argument_count == 2 && check_type == STRING_CHECK) { |
| 8300 HValue* index = Pop(); | 6947 HValue* index = Pop(); |
| 8301 HValue* string = Pop(); | 6948 HValue* string = Pop(); |
| 8302 HValue* context = environment()->LookupContext(); | 6949 HValue* context = environment()->LookupContext(); |
| 8303 ASSERT(!expr->holder().is_null()); | 6950 ASSERT(!expr->holder().is_null()); |
| 8304 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6951 Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck( |
| 8305 Call::GetPrototypeForPrimitiveCheck(STRING_CHECK, | 6952 STRING_CHECK, expr->holder()->GetIsolate()), |
| 8306 expr->holder()->GetIsolate()), | 6953 expr->holder(), zone(), top_info()); |
| 8307 expr->holder(), | |
| 8308 zone(), | |
| 8309 top_info())); | |
| 8310 HInstruction* char_code = | 6954 HInstruction* char_code = |
| 8311 BuildStringCharCodeAt(context, string, index); | 6955 BuildStringCharCodeAt(context, string, index); |
| 8312 if (id == kStringCharCodeAt) { | 6956 if (id == kStringCharCodeAt) { |
| 8313 ast_context()->ReturnInstruction(char_code, expr->id()); | 6957 ast_context()->ReturnInstruction(char_code, expr->id()); |
| 8314 return true; | 6958 return true; |
| 8315 } | 6959 } |
| 8316 AddInstruction(char_code); | 6960 AddInstruction(char_code); |
| 8317 HInstruction* result = | 6961 HInstruction* result = |
| 8318 HStringCharFromCode::New(zone(), context, char_code); | 6962 HStringCharFromCode::New(zone(), context, char_code); |
| 8319 ast_context()->ReturnInstruction(result, expr->id()); | 6963 ast_context()->ReturnInstruction(result, expr->id()); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8390 } | 7034 } |
| 8391 ast_context()->ReturnInstruction(result, expr->id()); | 7035 ast_context()->ReturnInstruction(result, expr->id()); |
| 8392 return true; | 7036 return true; |
| 8393 } | 7037 } |
| 8394 break; | 7038 break; |
| 8395 case kMathRandom: | 7039 case kMathRandom: |
| 8396 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { | 7040 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { |
| 8397 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 7041 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 8398 Drop(1); // Receiver. | 7042 Drop(1); // Receiver. |
| 8399 HValue* context = environment()->LookupContext(); | 7043 HValue* context = environment()->LookupContext(); |
| 8400 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 7044 HGlobalObject* global_object = Add<HGlobalObject>(context); |
| 8401 AddInstruction(global_object); | |
| 8402 HRandom* result = new(zone()) HRandom(global_object); | 7045 HRandom* result = new(zone()) HRandom(global_object); |
| 8403 ast_context()->ReturnInstruction(result, expr->id()); | 7046 ast_context()->ReturnInstruction(result, expr->id()); |
| 8404 return true; | 7047 return true; |
| 8405 } | 7048 } |
| 8406 break; | 7049 break; |
| 8407 case kMathMax: | 7050 case kMathMax: |
| 8408 case kMathMin: | 7051 case kMathMin: |
| 8409 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 7052 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
| 8410 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 7053 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 8411 HValue* right = Pop(); | 7054 HValue* right = Pop(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8470 if (HasStackOverflow() || current_block() == NULL) return true; | 7113 if (HasStackOverflow() || current_block() == NULL) return true; |
| 8471 HValue* function = Top(); | 7114 HValue* function = Top(); |
| 8472 AddCheckConstantFunction(expr->holder(), function, function_map); | 7115 AddCheckConstantFunction(expr->holder(), function, function_map); |
| 8473 Drop(1); | 7116 Drop(1); |
| 8474 | 7117 |
| 8475 VisitForValue(args->at(0)); | 7118 VisitForValue(args->at(0)); |
| 8476 if (HasStackOverflow() || current_block() == NULL) return true; | 7119 if (HasStackOverflow() || current_block() == NULL) return true; |
| 8477 HValue* receiver = Pop(); | 7120 HValue* receiver = Pop(); |
| 8478 | 7121 |
| 8479 if (function_state()->outer() == NULL) { | 7122 if (function_state()->outer() == NULL) { |
| 8480 HInstruction* elements = AddInstruction( | 7123 HInstruction* elements = Add<HArgumentsElements>(false); |
| 8481 new(zone()) HArgumentsElements(false)); | 7124 HInstruction* length = Add<HArgumentsLength>(elements); |
| 8482 HInstruction* length = | 7125 HValue* wrapped_receiver = Add<HWrapReceiver>(receiver, function); |
| 8483 AddInstruction(new(zone()) HArgumentsLength(elements)); | |
| 8484 HValue* wrapped_receiver = | |
| 8485 AddInstruction(new(zone()) HWrapReceiver(receiver, function)); | |
| 8486 HInstruction* result = | 7126 HInstruction* result = |
| 8487 new(zone()) HApplyArguments(function, | 7127 new(zone()) HApplyArguments(function, |
| 8488 wrapped_receiver, | 7128 wrapped_receiver, |
| 8489 length, | 7129 length, |
| 8490 elements); | 7130 elements); |
| 8491 result->set_position(expr->position()); | 7131 result->set_position(expr->position()); |
| 8492 ast_context()->ReturnInstruction(result, expr->id()); | 7132 ast_context()->ReturnInstruction(result, expr->id()); |
| 8493 return true; | 7133 return true; |
| 8494 } else { | 7134 } else { |
| 8495 // We are inside inlined function and we know exactly what is inside | 7135 // We are inside inlined function and we know exactly what is inside |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8700 if (known_global_function) { | 7340 if (known_global_function) { |
| 8701 // Push the global object instead of the global receiver because | 7341 // Push the global object instead of the global receiver because |
| 8702 // code generated by the full code generator expects it. | 7342 // code generated by the full code generator expects it. |
| 8703 HValue* context = environment()->LookupContext(); | 7343 HValue* context = environment()->LookupContext(); |
| 8704 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 7344 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 8705 PushAndAdd(global_object); | 7345 PushAndAdd(global_object); |
| 8706 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7346 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8707 | 7347 |
| 8708 CHECK_ALIVE(VisitForValue(expr->expression())); | 7348 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8709 HValue* function = Pop(); | 7349 HValue* function = Pop(); |
| 8710 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); | 7350 Add<HCheckFunction>(function, expr->target()); |
| 8711 | 7351 |
| 8712 // Replace the global object with the global receiver. | 7352 // Replace the global object with the global receiver. |
| 8713 HGlobalReceiver* global_receiver = | 7353 HGlobalReceiver* global_receiver = Add<HGlobalReceiver>(global_object); |
| 8714 new(zone()) HGlobalReceiver(global_object); | |
| 8715 // Index of the receiver from the top of the expression stack. | 7354 // Index of the receiver from the top of the expression stack. |
| 8716 const int receiver_index = argument_count - 1; | 7355 const int receiver_index = argument_count - 1; |
| 8717 AddInstruction(global_receiver); | |
| 8718 ASSERT(environment()->ExpressionStackAt(receiver_index)-> | 7356 ASSERT(environment()->ExpressionStackAt(receiver_index)-> |
| 8719 IsGlobalObject()); | 7357 IsGlobalObject()); |
| 8720 environment()->SetExpressionStackAt(receiver_index, global_receiver); | 7358 environment()->SetExpressionStackAt(receiver_index, global_receiver); |
| 8721 | 7359 |
| 8722 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. | 7360 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. |
| 8723 if (FLAG_trace_inlining) { | 7361 if (FLAG_trace_inlining) { |
| 8724 PrintF("Inlining builtin "); | 7362 PrintF("Inlining builtin "); |
| 8725 expr->target()->ShortPrint(); | 7363 expr->target()->ShortPrint(); |
| 8726 PrintF("\n"); | 7364 PrintF("\n"); |
| 8727 } | 7365 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 8738 // because it is likely to generate better code. | 7376 // because it is likely to generate better code. |
| 8739 HValue* context = environment()->LookupContext(); | 7377 HValue* context = environment()->LookupContext(); |
| 8740 call = PreProcessCall( | 7378 call = PreProcessCall( |
| 8741 new(zone()) HCallNamed(context, var->name(), argument_count)); | 7379 new(zone()) HCallNamed(context, var->name(), argument_count)); |
| 8742 } else { | 7380 } else { |
| 8743 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 7381 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
| 8744 argument_count)); | 7382 argument_count)); |
| 8745 } | 7383 } |
| 8746 } else { | 7384 } else { |
| 8747 HValue* context = environment()->LookupContext(); | 7385 HValue* context = environment()->LookupContext(); |
| 8748 HGlobalObject* receiver = new(zone()) HGlobalObject(context); | 7386 HGlobalObject* receiver = Add<HGlobalObject>(context); |
| 8749 AddInstruction(receiver); | |
| 8750 PushAndAdd(new(zone()) HPushArgument(receiver)); | 7387 PushAndAdd(new(zone()) HPushArgument(receiver)); |
| 8751 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7388 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 8752 | 7389 |
| 8753 call = new(zone()) HCallGlobal(context, var->name(), argument_count); | 7390 call = new(zone()) HCallGlobal(context, var->name(), argument_count); |
| 8754 Drop(argument_count); | 7391 Drop(argument_count); |
| 8755 } | 7392 } |
| 8756 | 7393 |
| 8757 } else if (expr->IsMonomorphic()) { | 7394 } else if (expr->IsMonomorphic()) { |
| 8758 // The function is on the stack in the unoptimized code during | 7395 // The function is on the stack in the unoptimized code during |
| 8759 // evaluation of the arguments. | 7396 // evaluation of the arguments. |
| 8760 CHECK_ALIVE(VisitForValue(expr->expression())); | 7397 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8761 HValue* function = Top(); | 7398 HValue* function = Top(); |
| 8762 HValue* context = environment()->LookupContext(); | 7399 HValue* context = environment()->LookupContext(); |
| 8763 HGlobalObject* global = new(zone()) HGlobalObject(context); | 7400 HGlobalObject* global = Add<HGlobalObject>(context); |
| 8764 AddInstruction(global); | |
| 8765 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); | 7401 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); |
| 8766 PushAndAdd(receiver); | 7402 PushAndAdd(receiver); |
| 8767 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7403 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8768 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); | 7404 Add<HCheckFunction>(function, expr->target()); |
| 8769 | 7405 |
| 8770 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. | 7406 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. |
| 8771 if (FLAG_trace_inlining) { | 7407 if (FLAG_trace_inlining) { |
| 8772 PrintF("Inlining builtin "); | 7408 PrintF("Inlining builtin "); |
| 8773 expr->target()->ShortPrint(); | 7409 expr->target()->ShortPrint(); |
| 8774 PrintF("\n"); | 7410 PrintF("\n"); |
| 8775 } | 7411 } |
| 8776 return; | 7412 return; |
| 8777 } | 7413 } |
| 8778 | 7414 |
| 8779 if (TryInlineCall(expr, true)) { // Drop function from environment. | 7415 if (TryInlineCall(expr, true)) { // Drop function from environment. |
| 8780 return; | 7416 return; |
| 8781 } else { | 7417 } else { |
| 8782 call = PreProcessCall( | 7418 call = PreProcessCall( |
| 8783 new(zone()) HInvokeFunction(context, | 7419 new(zone()) HInvokeFunction(context, |
| 8784 function, | 7420 function, |
| 8785 expr->target(), | 7421 expr->target(), |
| 8786 argument_count)); | 7422 argument_count)); |
| 8787 Drop(1); // The function. | 7423 Drop(1); // The function. |
| 8788 } | 7424 } |
| 8789 | 7425 |
| 8790 } else { | 7426 } else { |
| 8791 CHECK_ALIVE(VisitForValue(expr->expression())); | 7427 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8792 HValue* function = Top(); | 7428 HValue* function = Top(); |
| 8793 HValue* context = environment()->LookupContext(); | 7429 HValue* context = environment()->LookupContext(); |
| 8794 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 7430 HGlobalObject* global_object = Add<HGlobalObject>(context); |
| 8795 AddInstruction(global_object); | 7431 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object); |
| 8796 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object); | |
| 8797 AddInstruction(receiver); | |
| 8798 PushAndAdd(new(zone()) HPushArgument(receiver)); | 7432 PushAndAdd(new(zone()) HPushArgument(receiver)); |
| 8799 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7433 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 8800 | 7434 |
| 8801 call = new(zone()) HCallFunction(context, function, argument_count); | 7435 call = new(zone()) HCallFunction(context, function, argument_count); |
| 8802 Drop(argument_count + 1); | 7436 Drop(argument_count + 1); |
| 8803 } | 7437 } |
| 8804 } | 7438 } |
| 8805 | 7439 |
| 8806 call->set_position(expr->position()); | 7440 call->set_position(expr->position()); |
| 8807 return ast_context()->ReturnInstruction(call, expr->id()); | 7441 return ast_context()->ReturnInstruction(call, expr->id()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 8825 | 7459 |
| 8826 if (FLAG_inline_construct && | 7460 if (FLAG_inline_construct && |
| 8827 expr->IsMonomorphic() && | 7461 expr->IsMonomorphic() && |
| 8828 IsAllocationInlineable(expr->target())) { | 7462 IsAllocationInlineable(expr->target())) { |
| 8829 // The constructor function is on the stack in the unoptimized code | 7463 // The constructor function is on the stack in the unoptimized code |
| 8830 // during evaluation of the arguments. | 7464 // during evaluation of the arguments. |
| 8831 CHECK_ALIVE(VisitForValue(expr->expression())); | 7465 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8832 HValue* function = Top(); | 7466 HValue* function = Top(); |
| 8833 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7467 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8834 Handle<JSFunction> constructor = expr->target(); | 7468 Handle<JSFunction> constructor = expr->target(); |
| 8835 HValue* check = AddInstruction( | 7469 HValue* check = Add<HCheckFunction>(function, constructor); |
| 8836 new(zone()) HCheckFunction(function, constructor)); | |
| 8837 | 7470 |
| 8838 // Force completion of inobject slack tracking before generating | 7471 // Force completion of inobject slack tracking before generating |
| 8839 // allocation code to finalize instance size. | 7472 // allocation code to finalize instance size. |
| 8840 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { | 7473 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { |
| 8841 constructor->shared()->CompleteInobjectSlackTracking(); | 7474 constructor->shared()->CompleteInobjectSlackTracking(); |
| 8842 } | 7475 } |
| 8843 | 7476 |
| 8844 // Replace the constructor function with a newly allocated receiver. | 7477 // Replace the constructor function with a newly allocated receiver. |
| 8845 HInstruction* receiver = new(zone()) HAllocateObject(context, constructor); | 7478 HInstruction* receiver = Add<HAllocateObject>(context, constructor); |
| 8846 // Index of the receiver from the top of the expression stack. | 7479 // Index of the receiver from the top of the expression stack. |
| 8847 const int receiver_index = argument_count - 1; | 7480 const int receiver_index = argument_count - 1; |
| 8848 AddInstruction(receiver); | |
| 8849 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); | 7481 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); |
| 8850 environment()->SetExpressionStackAt(receiver_index, receiver); | 7482 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 8851 | 7483 |
| 8852 if (TryInlineConstruct(expr, receiver)) return; | 7484 if (TryInlineConstruct(expr, receiver)) return; |
| 8853 | 7485 |
| 8854 // TODO(mstarzinger): For now we remove the previous HAllocateObject and | 7486 // TODO(mstarzinger): For now we remove the previous HAllocateObject and |
| 8855 // add HPushArgument for the arguments in case inlining failed. What we | 7487 // add HPushArgument for the arguments in case inlining failed. What we |
| 8856 // actually should do is emit HInvokeFunction on the constructor instead | 7488 // actually should do is emit HInvokeFunction on the constructor instead |
| 8857 // of using HCallNew as a fallback. | 7489 // of using HCallNew as a fallback. |
| 8858 receiver->DeleteAndReplaceWith(NULL); | 7490 receiver->DeleteAndReplaceWith(NULL); |
| 8859 check->DeleteAndReplaceWith(NULL); | 7491 check->DeleteAndReplaceWith(NULL); |
| 8860 environment()->SetExpressionStackAt(receiver_index, function); | 7492 environment()->SetExpressionStackAt(receiver_index, function); |
| 8861 HInstruction* call = PreProcessCall( | 7493 HInstruction* call = PreProcessCall( |
| 8862 new(zone()) HCallNew(context, function, argument_count)); | 7494 new(zone()) HCallNew(context, function, argument_count)); |
| 8863 call->set_position(expr->position()); | 7495 call->set_position(expr->position()); |
| 8864 return ast_context()->ReturnInstruction(call, expr->id()); | 7496 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8865 } else { | 7497 } else { |
| 8866 // The constructor function is both an operand to the instruction and an | 7498 // The constructor function is both an operand to the instruction and an |
| 8867 // argument to the construct call. | 7499 // argument to the construct call. |
| 8868 Handle<JSFunction> array_function( | 7500 Handle<JSFunction> array_function( |
| 8869 isolate()->global_context()->array_function(), isolate()); | 7501 isolate()->global_context()->array_function(), isolate()); |
| 8870 CHECK_ALIVE(VisitArgument(expr->expression())); | 7502 CHECK_ALIVE(VisitArgument(expr->expression())); |
| 8871 HValue* constructor = HPushArgument::cast(Top())->argument(); | 7503 HValue* constructor = HPushArgument::cast(Top())->argument(); |
| 8872 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7504 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 8873 HCallNew* call; | 7505 HCallNew* call; |
| 8874 if (expr->target().is_identical_to(array_function)) { | 7506 if (expr->target().is_identical_to(array_function)) { |
| 8875 Handle<Cell> cell = expr->allocation_info_cell(); | 7507 Handle<Cell> cell = expr->allocation_info_cell(); |
| 8876 AddInstruction(new(zone()) HCheckFunction(constructor, array_function)); | 7508 Add<HCheckFunction>(constructor, array_function); |
| 8877 call = new(zone()) HCallNewArray(context, constructor, argument_count, | 7509 call = new(zone()) HCallNewArray(context, constructor, argument_count, |
| 8878 cell); | 7510 cell, expr->elements_kind()); |
| 8879 } else { | 7511 } else { |
| 8880 call = new(zone()) HCallNew(context, constructor, argument_count); | 7512 call = new(zone()) HCallNew(context, constructor, argument_count); |
| 8881 } | 7513 } |
| 8882 Drop(argument_count); | 7514 Drop(argument_count); |
| 8883 call->set_position(expr->position()); | 7515 call->set_position(expr->position()); |
| 8884 return ast_context()->ReturnInstruction(call, expr->id()); | 7516 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8885 } | 7517 } |
| 8886 } | 7518 } |
| 8887 | 7519 |
| 8888 | 7520 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9002 HValue* value = Pop(); | 7634 HValue* value = Pop(); |
| 9003 HValue* context = environment()->LookupContext(); | 7635 HValue* context = environment()->LookupContext(); |
| 9004 HInstruction* instr = new(zone()) HTypeof(context, value); | 7636 HInstruction* instr = new(zone()) HTypeof(context, value); |
| 9005 return ast_context()->ReturnInstruction(instr, expr->id()); | 7637 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9006 } | 7638 } |
| 9007 | 7639 |
| 9008 | 7640 |
| 9009 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { | 7641 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
| 9010 CHECK_ALIVE(VisitForValue(expr->expression())); | 7642 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 9011 HValue* value = Pop(); | 7643 HValue* value = Pop(); |
| 9012 HValue* context = environment()->LookupContext(); | |
| 9013 HInstruction* instr = | |
| 9014 HMul::New(zone(), context, value, graph()->GetConstantMinus1()); | |
| 9015 Handle<Type> operand_type = expr->expression()->lower_type(); | 7644 Handle<Type> operand_type = expr->expression()->lower_type(); |
| 9016 Representation rep = ToRepresentation(operand_type); | 7645 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); |
| 9017 if (operand_type->Is(Type::None())) { | |
| 9018 AddSoftDeoptimize(); | |
| 9019 } | |
| 9020 if (instr->IsBinaryOperation()) { | |
| 9021 HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep); | |
| 9022 HBinaryOperation::cast(instr)->set_observed_input_representation(2, rep); | |
| 9023 } | |
| 9024 return ast_context()->ReturnInstruction(instr, expr->id()); | 7646 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9025 } | 7647 } |
| 9026 | 7648 |
| 9027 | 7649 |
| 9028 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 7650 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
| 9029 CHECK_ALIVE(VisitForValue(expr->expression())); | 7651 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 9030 HValue* value = Pop(); | 7652 HValue* value = Pop(); |
| 9031 Handle<Type> operand_type = expr->expression()->lower_type(); | 7653 Handle<Type> operand_type = expr->expression()->lower_type(); |
| 9032 if (operand_type->Is(Type::None())) { | 7654 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT); |
| 9033 AddSoftDeoptimize(); | |
| 9034 } | |
| 9035 HInstruction* instr = new(zone()) HBitNot(value); | |
| 9036 return ast_context()->ReturnInstruction(instr, expr->id()); | 7655 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9037 } | 7656 } |
| 9038 | 7657 |
| 9039 | 7658 |
| 9040 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 7659 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { |
| 9041 if (ast_context()->IsTest()) { | 7660 if (ast_context()->IsTest()) { |
| 9042 TestContext* context = TestContext::cast(ast_context()); | 7661 TestContext* context = TestContext::cast(ast_context()); |
| 9043 VisitForControl(expr->expression(), | 7662 VisitForControl(expr->expression(), |
| 9044 context->if_false(), | 7663 context->if_false(), |
| 9045 context->if_true()); | 7664 context->if_true()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9079 set_current_block(join); | 7698 set_current_block(join); |
| 9080 if (join != NULL) return ast_context()->ReturnValue(Pop()); | 7699 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
| 9081 } | 7700 } |
| 9082 | 7701 |
| 9083 | 7702 |
| 9084 HInstruction* HOptimizedGraphBuilder::BuildIncrement( | 7703 HInstruction* HOptimizedGraphBuilder::BuildIncrement( |
| 9085 bool returns_original_input, | 7704 bool returns_original_input, |
| 9086 CountOperation* expr) { | 7705 CountOperation* expr) { |
| 9087 // The input to the count operation is on top of the expression stack. | 7706 // The input to the count operation is on top of the expression stack. |
| 9088 TypeInfo info = expr->type(); | 7707 TypeInfo info = expr->type(); |
| 9089 Representation rep = ToRepresentation(info); | 7708 Representation rep = Representation::FromType(info); |
| 9090 if (rep.IsNone() || rep.IsTagged()) { | 7709 if (rep.IsNone() || rep.IsTagged()) { |
| 9091 rep = Representation::Smi(); | 7710 rep = Representation::Smi(); |
| 9092 } | 7711 } |
| 9093 | 7712 |
| 9094 if (returns_original_input) { | 7713 if (returns_original_input) { |
| 9095 // We need an explicit HValue representing ToNumber(input). The | 7714 // We need an explicit HValue representing ToNumber(input). The |
| 9096 // actual HChange instruction we need is (sometimes) added in a later | 7715 // actual HChange instruction we need is (sometimes) added in a later |
| 9097 // phase, so it is not available now to be used as an input to HAdd and | 7716 // phase, so it is not available now to be used as an input to HAdd and |
| 9098 // as the return value. | 7717 // as the return value. |
| 9099 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); | 7718 HInstruction* number_input = Add<HForceRepresentation>(Pop(), rep); |
| 9100 if (!rep.IsDouble()) { | 7719 if (!rep.IsDouble()) { |
| 9101 number_input->SetFlag(HInstruction::kFlexibleRepresentation); | 7720 number_input->SetFlag(HInstruction::kFlexibleRepresentation); |
| 9102 number_input->SetFlag(HInstruction::kCannotBeTagged); | 7721 number_input->SetFlag(HInstruction::kCannotBeTagged); |
| 9103 } | 7722 } |
| 9104 AddInstruction(number_input); | |
| 9105 Push(number_input); | 7723 Push(number_input); |
| 9106 } | 7724 } |
| 9107 | 7725 |
| 9108 // The addition has no side effects, so we do not need | 7726 // The addition has no side effects, so we do not need |
| 9109 // to simulate the expression stack after this instruction. | 7727 // to simulate the expression stack after this instruction. |
| 9110 // Any later failures deopt to the load of the input or earlier. | 7728 // Any later failures deopt to the load of the input or earlier. |
| 9111 HConstant* delta = (expr->op() == Token::INC) | 7729 HConstant* delta = (expr->op() == Token::INC) |
| 9112 ? graph()->GetConstant1() | 7730 ? graph()->GetConstant1() |
| 9113 : graph()->GetConstantMinus1(); | 7731 : graph()->GetConstantMinus1(); |
| 9114 HValue* context = environment()->LookupContext(); | 7732 HValue* context = environment()->LookupContext(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9177 for (int i = 0; i < count; ++i) { | 7795 for (int i = 0; i < count; ++i) { |
| 9178 if (var == current_info()->scope()->parameter(i)) { | 7796 if (var == current_info()->scope()->parameter(i)) { |
| 9179 return Bailout("assignment to parameter in arguments object"); | 7797 return Bailout("assignment to parameter in arguments object"); |
| 9180 } | 7798 } |
| 9181 } | 7799 } |
| 9182 } | 7800 } |
| 9183 | 7801 |
| 9184 HValue* context = BuildContextChainWalk(var); | 7802 HValue* context = BuildContextChainWalk(var); |
| 9185 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 7803 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
| 9186 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 7804 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
| 9187 HStoreContextSlot* instr = | 7805 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
| 9188 new(zone()) HStoreContextSlot(context, var->index(), mode, after); | 7806 mode, after); |
| 9189 AddInstruction(instr); | |
| 9190 if (instr->HasObservableSideEffects()) { | 7807 if (instr->HasObservableSideEffects()) { |
| 9191 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7808 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 9192 } | 7809 } |
| 9193 break; | 7810 break; |
| 9194 } | 7811 } |
| 9195 | 7812 |
| 9196 case Variable::LOOKUP: | 7813 case Variable::LOOKUP: |
| 9197 return Bailout("lookup variable in count operation"); | 7814 return Bailout("lookup variable in count operation"); |
| 9198 } | 7815 } |
| 9199 | 7816 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9318 if (i < 0 || i >= s->length()) { | 7935 if (i < 0 || i >= s->length()) { |
| 9319 return new(zone()) HConstant(OS::nan_value()); | 7936 return new(zone()) HConstant(OS::nan_value()); |
| 9320 } | 7937 } |
| 9321 return new(zone()) HConstant(s->Get(i)); | 7938 return new(zone()) HConstant(s->Get(i)); |
| 9322 } | 7939 } |
| 9323 } | 7940 } |
| 9324 BuildCheckHeapObject(string); | 7941 BuildCheckHeapObject(string); |
| 9325 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 7942 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
| 9326 HInstruction* length = HStringLength::New(zone(), string); | 7943 HInstruction* length = HStringLength::New(zone(), string); |
| 9327 AddInstruction(length); | 7944 AddInstruction(length); |
| 9328 HInstruction* checked_index = AddBoundsCheck(index, length); | 7945 HInstruction* checked_index = Add<HBoundsCheck>(index, length); |
| 9329 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 7946 return new(zone()) HStringCharCodeAt(context, string, checked_index); |
| 9330 } | 7947 } |
| 9331 | 7948 |
| 7949 |
| 9332 // Checks if the given shift amounts have form: (sa) and (32 - sa). | 7950 // Checks if the given shift amounts have form: (sa) and (32 - sa). |
| 9333 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 7951 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
| 9334 HValue* const32_minus_sa) { | 7952 HValue* const32_minus_sa) { |
| 9335 if (!const32_minus_sa->IsSub()) return false; | 7953 if (!const32_minus_sa->IsSub()) return false; |
| 9336 HSub* sub = HSub::cast(const32_minus_sa); | 7954 HSub* sub = HSub::cast(const32_minus_sa); |
| 9337 if (sa != sub->right()) return false; | 7955 if (sa != sub->right()) return false; |
| 9338 HValue* const32 = sub->left(); | 7956 HValue* const32 = sub->left(); |
| 9339 if (!const32->IsConstant() || | 7957 if (!const32->IsConstant() || |
| 9340 HConstant::cast(const32)->Integer32Value() != 32) { | 7958 HConstant::cast(const32)->Integer32Value() != 32) { |
| 9341 return false; | 7959 return false; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9389 | 8007 |
| 9390 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 8008 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 9391 BinaryOperation* expr, | 8009 BinaryOperation* expr, |
| 9392 HValue* left, | 8010 HValue* left, |
| 9393 HValue* right) { | 8011 HValue* right) { |
| 9394 HValue* context = environment()->LookupContext(); | 8012 HValue* context = environment()->LookupContext(); |
| 9395 Handle<Type> left_type = expr->left()->lower_type(); | 8013 Handle<Type> left_type = expr->left()->lower_type(); |
| 9396 Handle<Type> right_type = expr->right()->lower_type(); | 8014 Handle<Type> right_type = expr->right()->lower_type(); |
| 9397 Handle<Type> result_type = expr->lower_type(); | 8015 Handle<Type> result_type = expr->lower_type(); |
| 9398 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 8016 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 9399 Representation left_rep = ToRepresentation(left_type); | 8017 Representation left_rep = Representation::FromType(left_type); |
| 9400 Representation right_rep = ToRepresentation(right_type); | 8018 Representation right_rep = Representation::FromType(right_type); |
| 9401 Representation result_rep = ToRepresentation(result_type); | 8019 Representation result_rep = Representation::FromType(result_type); |
| 8020 |
| 9402 if (left_type->Is(Type::None())) { | 8021 if (left_type->Is(Type::None())) { |
| 9403 AddSoftDeoptimize(); | 8022 AddSoftDeoptimize(); |
| 9404 // TODO(rossberg): we should be able to get rid of non-continuous defaults. | 8023 // TODO(rossberg): we should be able to get rid of non-continuous defaults. |
| 9405 left_type = handle(Type::Any(), isolate()); | 8024 left_type = handle(Type::Any(), isolate()); |
| 9406 } | 8025 } |
| 9407 if (right_type->Is(Type::None())) { | 8026 if (right_type->Is(Type::None())) { |
| 9408 AddSoftDeoptimize(); | 8027 AddSoftDeoptimize(); |
| 9409 right_type = handle(Type::Any(), isolate()); | 8028 right_type = handle(Type::Any(), isolate()); |
| 9410 } | 8029 } |
| 9411 HInstruction* instr = NULL; | 8030 HInstruction* instr = NULL; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9552 CHECK_ALIVE(VisitForValue(expr->right())); | 8171 CHECK_ALIVE(VisitForValue(expr->right())); |
| 9553 } | 8172 } |
| 9554 return ast_context()->ReturnValue(Pop()); | 8173 return ast_context()->ReturnValue(Pop()); |
| 9555 } | 8174 } |
| 9556 | 8175 |
| 9557 // We need an extra block to maintain edge-split form. | 8176 // We need an extra block to maintain edge-split form. |
| 9558 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 8177 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
| 9559 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 8178 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
| 9560 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); | 8179 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); |
| 9561 HBranch* test = is_logical_and | 8180 HBranch* test = is_logical_and |
| 9562 ? new(zone()) HBranch(left_value, eval_right, empty_block, expected) | 8181 ? new(zone()) HBranch(left_value, expected, eval_right, empty_block) |
| 9563 : new(zone()) HBranch(left_value, empty_block, eval_right, expected); | 8182 : new(zone()) HBranch(left_value, expected, empty_block, eval_right); |
| 9564 current_block()->Finish(test); | 8183 current_block()->Finish(test); |
| 9565 | 8184 |
| 9566 set_current_block(eval_right); | 8185 set_current_block(eval_right); |
| 9567 Drop(1); // Value of the left subexpression. | 8186 Drop(1); // Value of the left subexpression. |
| 9568 CHECK_BAILOUT(VisitForValue(expr->right())); | 8187 CHECK_BAILOUT(VisitForValue(expr->right())); |
| 9569 | 8188 |
| 9570 HBasicBlock* join_block = | 8189 HBasicBlock* join_block = |
| 9571 CreateJoin(empty_block, current_block(), expr->id()); | 8190 CreateJoin(empty_block, current_block(), expr->id()); |
| 9572 set_current_block(join_block); | 8191 set_current_block(join_block); |
| 9573 return ast_context()->ReturnValue(Pop()); | 8192 return ast_context()->ReturnValue(Pop()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9619 CHECK_ALIVE(VisitForValue(expr->left())); | 8238 CHECK_ALIVE(VisitForValue(expr->left())); |
| 9620 CHECK_ALIVE(VisitForValue(expr->right())); | 8239 CHECK_ALIVE(VisitForValue(expr->right())); |
| 9621 HValue* right = Pop(); | 8240 HValue* right = Pop(); |
| 9622 HValue* left = Pop(); | 8241 HValue* left = Pop(); |
| 9623 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 8242 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
| 9624 instr->set_position(expr->position()); | 8243 instr->set_position(expr->position()); |
| 9625 return ast_context()->ReturnInstruction(instr, expr->id()); | 8244 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9626 } | 8245 } |
| 9627 | 8246 |
| 9628 | 8247 |
| 9629 // TODO(rossberg): this should die eventually. | |
| 9630 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) { | |
| 9631 if (info.IsUninitialized()) return Representation::None(); | |
| 9632 // TODO(verwaest): Return Smi rather than Integer32. | |
| 9633 if (info.IsSmi()) return Representation::Integer32(); | |
| 9634 if (info.IsInteger32()) return Representation::Integer32(); | |
| 9635 if (info.IsDouble()) return Representation::Double(); | |
| 9636 if (info.IsNumber()) return Representation::Double(); | |
| 9637 return Representation::Tagged(); | |
| 9638 } | |
| 9639 | |
| 9640 | |
| 9641 Representation HOptimizedGraphBuilder::ToRepresentation(Handle<Type> type) { | |
| 9642 if (type->Is(Type::None())) return Representation::None(); | |
| 9643 if (type->Is(Type::Signed32())) return Representation::Integer32(); | |
| 9644 if (type->Is(Type::Number())) return Representation::Double(); | |
| 9645 return Representation::Tagged(); | |
| 9646 } | |
| 9647 | |
| 9648 | |
| 9649 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 8248 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
| 9650 HTypeof* typeof_expr, | 8249 HTypeof* typeof_expr, |
| 9651 Handle<String> check) { | 8250 Handle<String> check) { |
| 9652 // Note: The HTypeof itself is removed during canonicalization, if possible. | 8251 // Note: The HTypeof itself is removed during canonicalization, if possible. |
| 9653 HValue* value = typeof_expr->value(); | 8252 HValue* value = typeof_expr->value(); |
| 9654 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); | 8253 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); |
| 9655 instr->set_position(expr->position()); | 8254 instr->set_position(expr->position()); |
| 9656 return ast_context()->ReturnControl(instr, expr->id()); | 8255 return ast_context()->ReturnControl(instr, expr->id()); |
| 9657 } | 8256 } |
| 9658 | 8257 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9731 Handle<String> rhs = Handle<String>::cast(literal->value()); | 8330 Handle<String> rhs = Handle<String>::cast(literal->value()); |
| 9732 HClassOfTestAndBranch* instr = | 8331 HClassOfTestAndBranch* instr = |
| 9733 new(zone()) HClassOfTestAndBranch(value, rhs); | 8332 new(zone()) HClassOfTestAndBranch(value, rhs); |
| 9734 instr->set_position(expr->position()); | 8333 instr->set_position(expr->position()); |
| 9735 return ast_context()->ReturnControl(instr, expr->id()); | 8334 return ast_context()->ReturnControl(instr, expr->id()); |
| 9736 } | 8335 } |
| 9737 | 8336 |
| 9738 Handle<Type> left_type = expr->left()->lower_type(); | 8337 Handle<Type> left_type = expr->left()->lower_type(); |
| 9739 Handle<Type> right_type = expr->right()->lower_type(); | 8338 Handle<Type> right_type = expr->right()->lower_type(); |
| 9740 Handle<Type> combined_type = expr->combined_type(); | 8339 Handle<Type> combined_type = expr->combined_type(); |
| 9741 Representation combined_rep = ToRepresentation(combined_type); | 8340 Representation combined_rep = Representation::FromType(combined_type); |
| 9742 Representation left_rep = ToRepresentation(left_type); | 8341 Representation left_rep = Representation::FromType(left_type); |
| 9743 Representation right_rep = ToRepresentation(right_type); | 8342 Representation right_rep = Representation::FromType(right_type); |
| 9744 // Check if this expression was ever executed according to type feedback. | |
| 9745 // Note that for the special typeof/null/undefined cases we get unknown here. | |
| 9746 if (combined_type->Is(Type::None())) { | |
| 9747 AddSoftDeoptimize(); | |
| 9748 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | |
| 9749 } | |
| 9750 | 8343 |
| 9751 CHECK_ALIVE(VisitForValue(expr->left())); | 8344 CHECK_ALIVE(VisitForValue(expr->left())); |
| 9752 CHECK_ALIVE(VisitForValue(expr->right())); | 8345 CHECK_ALIVE(VisitForValue(expr->right())); |
| 9753 | 8346 |
| 9754 HValue* context = environment()->LookupContext(); | 8347 HValue* context = environment()->LookupContext(); |
| 9755 HValue* right = Pop(); | 8348 HValue* right = Pop(); |
| 9756 HValue* left = Pop(); | 8349 HValue* left = Pop(); |
| 9757 Token::Value op = expr->op(); | 8350 Token::Value op = expr->op(); |
| 9758 | 8351 |
| 9759 HTypeof* typeof_expr = NULL; | 8352 HTypeof* typeof_expr = NULL; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9800 } | 8393 } |
| 9801 } | 8394 } |
| 9802 | 8395 |
| 9803 // If the target is not null we have found a known global function that is | 8396 // If the target is not null we have found a known global function that is |
| 9804 // assumed to stay the same for this instanceof. | 8397 // assumed to stay the same for this instanceof. |
| 9805 if (target.is_null()) { | 8398 if (target.is_null()) { |
| 9806 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); | 8399 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); |
| 9807 result->set_position(expr->position()); | 8400 result->set_position(expr->position()); |
| 9808 return ast_context()->ReturnInstruction(result, expr->id()); | 8401 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9809 } else { | 8402 } else { |
| 9810 AddInstruction(new(zone()) HCheckFunction(right, target)); | 8403 Add<HCheckFunction>(right, target); |
| 9811 HInstanceOfKnownGlobal* result = | 8404 HInstanceOfKnownGlobal* result = |
| 9812 new(zone()) HInstanceOfKnownGlobal(context, left, target); | 8405 new(zone()) HInstanceOfKnownGlobal(context, left, target); |
| 9813 result->set_position(expr->position()); | 8406 result->set_position(expr->position()); |
| 9814 return ast_context()->ReturnInstruction(result, expr->id()); | 8407 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9815 } | 8408 } |
| 8409 |
| 8410 // Code below assumes that we don't fall through. |
| 8411 UNREACHABLE(); |
| 9816 } else if (op == Token::IN) { | 8412 } else if (op == Token::IN) { |
| 9817 HIn* result = new(zone()) HIn(context, left, right); | 8413 HIn* result = new(zone()) HIn(context, left, right); |
| 9818 result->set_position(expr->position()); | 8414 result->set_position(expr->position()); |
| 9819 return ast_context()->ReturnInstruction(result, expr->id()); | 8415 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9820 } else if (combined_type->Is(Type::Receiver())) { | 8416 } |
| 8417 |
| 8418 // Cases handled below depend on collected type feedback. They should |
| 8419 // soft deoptimize when there is no type feedback. |
| 8420 if (combined_type->Is(Type::None())) { |
| 8421 AddSoftDeoptimize(); |
| 8422 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
| 8423 } |
| 8424 |
| 8425 if (combined_type->Is(Type::Receiver())) { |
| 9821 switch (op) { | 8426 switch (op) { |
| 9822 case Token::EQ: | 8427 case Token::EQ: |
| 9823 case Token::EQ_STRICT: { | 8428 case Token::EQ_STRICT: { |
| 9824 // Can we get away with map check and not instance type check? | 8429 // Can we get away with map check and not instance type check? |
| 9825 if (combined_type->IsClass()) { | 8430 if (combined_type->IsClass()) { |
| 9826 Handle<Map> map = combined_type->AsClass(); | 8431 Handle<Map> map = combined_type->AsClass(); |
| 9827 AddCheckMapsWithTransitions(left, map); | 8432 AddCheckMapsWithTransitions(left, map); |
| 9828 AddCheckMapsWithTransitions(right, map); | 8433 AddCheckMapsWithTransitions(right, map); |
| 9829 HCompareObjectEqAndBranch* result = | 8434 HCompareObjectEqAndBranch* result = |
| 9830 new(zone()) HCompareObjectEqAndBranch(left, right); | 8435 new(zone()) HCompareObjectEqAndBranch(left, right); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 9856 return ast_context()->ReturnControl(result, expr->id()); | 8461 return ast_context()->ReturnControl(result, expr->id()); |
| 9857 } else { | 8462 } else { |
| 9858 if (combined_rep.IsTagged() || combined_rep.IsNone()) { | 8463 if (combined_rep.IsTagged() || combined_rep.IsNone()) { |
| 9859 HCompareGeneric* result = | 8464 HCompareGeneric* result = |
| 9860 new(zone()) HCompareGeneric(context, left, right, op); | 8465 new(zone()) HCompareGeneric(context, left, right, op); |
| 9861 result->set_observed_input_representation(1, left_rep); | 8466 result->set_observed_input_representation(1, left_rep); |
| 9862 result->set_observed_input_representation(2, right_rep); | 8467 result->set_observed_input_representation(2, right_rep); |
| 9863 result->set_position(expr->position()); | 8468 result->set_position(expr->position()); |
| 9864 return ast_context()->ReturnInstruction(result, expr->id()); | 8469 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9865 } else { | 8470 } else { |
| 9866 // TODO(verwaest): Remove once ToRepresentation properly returns Smi when | 8471 // TODO(verwaest): Remove once Representation::FromType properly |
| 9867 // the IC measures Smi. | 8472 // returns Smi when the IC measures Smi. |
| 9868 if (left_type->Is(Type::Smi())) left_rep = Representation::Smi(); | 8473 if (left_type->Is(Type::Smi())) left_rep = Representation::Smi(); |
| 9869 if (right_type->Is(Type::Smi())) right_rep = Representation::Smi(); | 8474 if (right_type->Is(Type::Smi())) right_rep = Representation::Smi(); |
| 9870 HCompareIDAndBranch* result = | 8475 HCompareNumericAndBranch* result = |
| 9871 new(zone()) HCompareIDAndBranch(left, right, op); | 8476 new(zone()) HCompareNumericAndBranch(left, right, op); |
| 9872 result->set_observed_input_representation(left_rep, right_rep); | 8477 result->set_observed_input_representation(left_rep, right_rep); |
| 9873 result->set_position(expr->position()); | 8478 result->set_position(expr->position()); |
| 9874 return ast_context()->ReturnControl(result, expr->id()); | 8479 return ast_context()->ReturnControl(result, expr->id()); |
| 9875 } | 8480 } |
| 9876 } | 8481 } |
| 9877 } | 8482 } |
| 9878 | 8483 |
| 9879 | 8484 |
| 9880 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 8485 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
| 9881 HValue* value, | 8486 HValue* value, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 9911 } else { | 8516 } else { |
| 9912 return new(zone()) HThisFunction; | 8517 return new(zone()) HThisFunction; |
| 9913 } | 8518 } |
| 9914 } | 8519 } |
| 9915 | 8520 |
| 9916 | 8521 |
| 9917 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 8522 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
| 9918 HValue* context, | 8523 HValue* context, |
| 9919 Handle<JSObject> boilerplate_object, | 8524 Handle<JSObject> boilerplate_object, |
| 9920 Handle<JSObject> original_boilerplate_object, | 8525 Handle<JSObject> original_boilerplate_object, |
| 8526 Handle<Object> allocation_site, |
| 9921 int data_size, | 8527 int data_size, |
| 9922 int pointer_size, | 8528 int pointer_size, |
| 9923 AllocationSiteMode mode) { | 8529 AllocationSiteMode mode) { |
| 9924 Zone* zone = this->zone(); | |
| 9925 NoObservableSideEffectsScope no_effects(this); | 8530 NoObservableSideEffectsScope no_effects(this); |
| 9926 | 8531 |
| 9927 HInstruction* target = NULL; | 8532 HInstruction* target = NULL; |
| 9928 HInstruction* data_target = NULL; | 8533 HInstruction* data_target = NULL; |
| 9929 | 8534 |
| 9930 HAllocate::Flags flags = HAllocate::DefaultFlags(); | 8535 HAllocate::Flags flags = HAllocate::DefaultFlags(); |
| 9931 | 8536 |
| 9932 if (isolate()->heap()->ShouldGloballyPretenure()) { | 8537 if (isolate()->heap()->ShouldGloballyPretenure()) { |
| 9933 if (data_size != 0) { | 8538 if (data_size != 0) { |
| 9934 HAllocate::Flags data_flags = | 8539 HAllocate::Flags data_flags = |
| 9935 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() | | 8540 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() | |
| 9936 HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); | 8541 HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); |
| 9937 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(data_size)); | 8542 HValue* size_in_bytes = Add<HConstant>(data_size); |
| 9938 data_target = AddInstruction(new(zone) HAllocate( | 8543 data_target = Add<HAllocate>(context, size_in_bytes, |
| 9939 context, size_in_bytes, HType::JSObject(), data_flags)); | 8544 HType::JSObject(), data_flags); |
| 9940 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); | 8545 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); |
| 9941 AddStoreMapConstant(data_target, free_space_map); | 8546 AddStoreMapConstant(data_target, free_space_map); |
| 9942 HObjectAccess access = | 8547 HObjectAccess access = |
| 9943 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); | 8548 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); |
| 9944 AddStore(data_target, access, size_in_bytes); | 8549 AddStore(data_target, access, size_in_bytes); |
| 9945 } | 8550 } |
| 9946 if (pointer_size != 0) { | 8551 if (pointer_size != 0) { |
| 9947 flags = static_cast<HAllocate::Flags>( | 8552 flags = static_cast<HAllocate::Flags>( |
| 9948 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | 8553 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); |
| 9949 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(pointer_size)); | 8554 HValue* size_in_bytes = Add<HConstant>(pointer_size); |
| 9950 target = AddInstruction(new(zone) HAllocate(context, | 8555 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags); |
| 9951 size_in_bytes, HType::JSObject(), flags)); | |
| 9952 } | 8556 } |
| 9953 } else { | 8557 } else { |
| 9954 HValue* size_in_bytes = | 8558 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size); |
| 9955 AddInstruction(new(zone) HConstant(data_size + pointer_size)); | 8559 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags); |
| 9956 target = AddInstruction(new(zone) HAllocate(context, size_in_bytes, | |
| 9957 HType::JSObject(), flags)); | |
| 9958 } | 8560 } |
| 9959 | 8561 |
| 9960 int offset = 0; | 8562 int offset = 0; |
| 9961 int data_offset = 0; | 8563 int data_offset = 0; |
| 9962 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, target, | 8564 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, |
| 9963 &offset, data_target, &data_offset, mode); | 8565 allocation_site, target, &offset, data_target, |
| 8566 &data_offset, mode); |
| 9964 return target; | 8567 return target; |
| 9965 } | 8568 } |
| 9966 | 8569 |
| 9967 | 8570 |
| 9968 void HOptimizedGraphBuilder::BuildEmitDeepCopy( | 8571 void HOptimizedGraphBuilder::BuildEmitDeepCopy( |
| 9969 Handle<JSObject> boilerplate_object, | 8572 Handle<JSObject> boilerplate_object, |
| 9970 Handle<JSObject> original_boilerplate_object, | 8573 Handle<JSObject> original_boilerplate_object, |
| 8574 Handle<Object> allocation_site_object, |
| 9971 HInstruction* target, | 8575 HInstruction* target, |
| 9972 int* offset, | 8576 int* offset, |
| 9973 HInstruction* data_target, | 8577 HInstruction* data_target, |
| 9974 int* data_offset, | 8578 int* data_offset, |
| 9975 AllocationSiteMode mode) { | 8579 AllocationSiteMode mode) { |
| 9976 Zone* zone = this->zone(); | 8580 Zone* zone = this->zone(); |
| 9977 | 8581 |
| 8582 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && |
| 8583 boilerplate_object->map()->CanTrackAllocationSite(); |
| 8584 |
| 8585 // If using allocation sites, then the payload on the site should already |
| 8586 // be filled in as a valid (boilerplate) array. |
| 8587 ASSERT(!create_allocation_site_info || |
| 8588 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); |
| 8589 |
| 8590 HInstruction* allocation_site = NULL; |
| 8591 |
| 8592 if (create_allocation_site_info) { |
| 8593 allocation_site = AddInstruction(new(zone) HConstant( |
| 8594 allocation_site_object, Representation::Tagged())); |
| 8595 } |
| 8596 |
| 8597 // Only elements backing stores for non-COW arrays need to be copied. |
| 9978 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 8598 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
| 9979 Handle<FixedArrayBase> original_elements( | 8599 Handle<FixedArrayBase> original_elements( |
| 9980 original_boilerplate_object->elements()); | 8600 original_boilerplate_object->elements()); |
| 9981 ElementsKind kind = boilerplate_object->map()->elements_kind(); | 8601 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
| 9982 | 8602 |
| 9983 int object_offset = *offset; | 8603 int object_offset = *offset; |
| 9984 int object_size = boilerplate_object->map()->instance_size(); | 8604 int object_size = boilerplate_object->map()->instance_size(); |
| 9985 int elements_size = (elements->length() > 0 && | 8605 int elements_size = (elements->length() > 0 && |
| 9986 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? | 8606 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? |
| 9987 elements->Size() : 0; | 8607 elements->Size() : 0; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 10001 | 8621 |
| 10002 // Copy object elements if non-COW. | 8622 // Copy object elements if non-COW. |
| 10003 HValue* object_elements = BuildEmitObjectHeader(boilerplate_object, target, | 8623 HValue* object_elements = BuildEmitObjectHeader(boilerplate_object, target, |
| 10004 data_target, object_offset, elements_offset, elements_size); | 8624 data_target, object_offset, elements_offset, elements_size); |
| 10005 if (object_elements != NULL) { | 8625 if (object_elements != NULL) { |
| 10006 BuildEmitElements(elements, original_elements, kind, object_elements, | 8626 BuildEmitElements(elements, original_elements, kind, object_elements, |
| 10007 target, offset, data_target, data_offset); | 8627 target, offset, data_target, data_offset); |
| 10008 } | 8628 } |
| 10009 | 8629 |
| 10010 // Copy in-object properties. | 8630 // Copy in-object properties. |
| 10011 HValue* object_properties = | 8631 if (boilerplate_object->map()->NumberOfFields() != 0) { |
| 10012 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); | 8632 HValue* object_properties = |
| 10013 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, | 8633 Add<HInnerAllocatedObject>(target, object_offset); |
| 10014 object_properties, target, offset, data_target, data_offset); | 8634 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, |
| 8635 object_properties, target, offset, data_target, data_offset); |
| 8636 } |
| 10015 | 8637 |
| 10016 // Create allocation site info. | 8638 // Create allocation site info. |
| 10017 if (mode == TRACK_ALLOCATION_SITE && | 8639 if (mode == TRACK_ALLOCATION_SITE && |
| 10018 boilerplate_object->map()->CanTrackAllocationSite()) { | 8640 boilerplate_object->map()->CanTrackAllocationSite()) { |
| 10019 elements_offset += AllocationSiteInfo::kSize; | 8641 elements_offset += AllocationSiteInfo::kSize; |
| 10020 *offset += AllocationSiteInfo::kSize; | 8642 *offset += AllocationSiteInfo::kSize; |
| 10021 HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant( | 8643 BuildCreateAllocationSiteInfo(target, JSArray::kSize, allocation_site); |
| 10022 original_boilerplate_object)); | |
| 10023 BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate); | |
| 10024 } | 8644 } |
| 10025 } | 8645 } |
| 10026 | 8646 |
| 10027 | 8647 |
| 10028 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( | 8648 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( |
| 10029 Handle<JSObject> boilerplate_object, | 8649 Handle<JSObject> boilerplate_object, |
| 10030 HInstruction* target, | 8650 HInstruction* target, |
| 10031 HInstruction* data_target, | 8651 HInstruction* data_target, |
| 10032 int object_offset, | 8652 int object_offset, |
| 10033 int elements_offset, | 8653 int elements_offset, |
| 10034 int elements_size) { | 8654 int elements_size) { |
| 10035 ASSERT(boilerplate_object->properties()->length() == 0); | 8655 ASSERT(boilerplate_object->properties()->length() == 0); |
| 10036 Zone* zone = this->zone(); | |
| 10037 HValue* result = NULL; | 8656 HValue* result = NULL; |
| 10038 | 8657 |
| 10039 HValue* object_header = | 8658 HValue* object_header = Add<HInnerAllocatedObject>(target, object_offset); |
| 10040 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); | |
| 10041 Handle<Map> boilerplate_object_map(boilerplate_object->map()); | 8659 Handle<Map> boilerplate_object_map(boilerplate_object->map()); |
| 10042 AddStoreMapConstant(object_header, boilerplate_object_map); | 8660 AddStoreMapConstant(object_header, boilerplate_object_map); |
| 10043 | 8661 |
| 10044 HInstruction* elements; | 8662 HInstruction* elements; |
| 10045 if (elements_size == 0) { | 8663 if (elements_size == 0) { |
| 10046 Handle<Object> elements_field = | 8664 Handle<Object> elements_field = |
| 10047 Handle<Object>(boilerplate_object->elements(), isolate()); | 8665 Handle<Object>(boilerplate_object->elements(), isolate()); |
| 10048 elements = AddInstruction(new(zone) HConstant(elements_field)); | 8666 elements = Add<HConstant>(elements_field); |
| 10049 } else { | 8667 } else { |
| 10050 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { | 8668 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { |
| 10051 elements = AddInstruction(new(zone) HInnerAllocatedObject( | 8669 elements = Add<HInnerAllocatedObject>(data_target, elements_offset); |
| 10052 data_target, elements_offset)); | |
| 10053 } else { | 8670 } else { |
| 10054 elements = AddInstruction(new(zone) HInnerAllocatedObject( | 8671 elements = Add<HInnerAllocatedObject>(target, elements_offset); |
| 10055 target, elements_offset)); | |
| 10056 } | 8672 } |
| 10057 result = elements; | 8673 result = elements; |
| 10058 } | 8674 } |
| 10059 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements); | 8675 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements); |
| 10060 | 8676 |
| 10061 Handle<Object> properties_field = | 8677 Handle<Object> properties_field = |
| 10062 Handle<Object>(boilerplate_object->properties(), isolate()); | 8678 Handle<Object>(boilerplate_object->properties(), isolate()); |
| 10063 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 8679 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); |
| 10064 HInstruction* properties = AddInstruction(new(zone) HConstant( | 8680 HInstruction* properties = Add<HConstant>(properties_field); |
| 10065 properties_field)); | |
| 10066 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 8681 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 10067 AddStore(object_header, access, properties); | 8682 AddStore(object_header, access, properties); |
| 10068 | 8683 |
| 10069 if (boilerplate_object->IsJSArray()) { | 8684 if (boilerplate_object->IsJSArray()) { |
| 10070 Handle<JSArray> boilerplate_array = | 8685 Handle<JSArray> boilerplate_array = |
| 10071 Handle<JSArray>::cast(boilerplate_object); | 8686 Handle<JSArray>::cast(boilerplate_object); |
| 10072 Handle<Object> length_field = | 8687 Handle<Object> length_field = |
| 10073 Handle<Object>(boilerplate_array->length(), isolate()); | 8688 Handle<Object>(boilerplate_array->length(), isolate()); |
| 10074 HInstruction* length = AddInstruction(new(zone) HConstant(length_field)); | 8689 HInstruction* length = Add<HConstant>(length_field); |
| 10075 | 8690 |
| 10076 ASSERT(boilerplate_array->length()->IsSmi()); | 8691 ASSERT(boilerplate_array->length()->IsSmi()); |
| 10077 Representation representation = | 8692 Representation representation = |
| 10078 IsFastElementsKind(boilerplate_array->GetElementsKind()) | 8693 IsFastElementsKind(boilerplate_array->GetElementsKind()) |
| 10079 ? Representation::Smi() : Representation::Tagged(); | 8694 ? Representation::Smi() : Representation::Tagged(); |
| 10080 AddStore(object_header, HObjectAccess::ForArrayLength(), | 8695 AddStore(object_header, HObjectAccess::ForArrayLength(), |
| 10081 length, representation); | 8696 length, representation); |
| 10082 } | 8697 } |
| 10083 | 8698 |
| 10084 return result; | 8699 return result; |
| 10085 } | 8700 } |
| 10086 | 8701 |
| 10087 | 8702 |
| 10088 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 8703 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
| 10089 Handle<JSObject> boilerplate_object, | 8704 Handle<JSObject> boilerplate_object, |
| 10090 Handle<JSObject> original_boilerplate_object, | 8705 Handle<JSObject> original_boilerplate_object, |
| 10091 HValue* object_properties, | 8706 HValue* object_properties, |
| 10092 HInstruction* target, | 8707 HInstruction* target, |
| 10093 int* offset, | 8708 int* offset, |
| 10094 HInstruction* data_target, | 8709 HInstruction* data_target, |
| 10095 int* data_offset) { | 8710 int* data_offset) { |
| 10096 Zone* zone = this->zone(); | |
| 10097 Handle<DescriptorArray> descriptors( | 8711 Handle<DescriptorArray> descriptors( |
| 10098 boilerplate_object->map()->instance_descriptors()); | 8712 boilerplate_object->map()->instance_descriptors()); |
| 10099 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); | 8713 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); |
| 10100 | 8714 |
| 10101 int copied_fields = 0; | 8715 int copied_fields = 0; |
| 10102 for (int i = 0; i < limit; i++) { | 8716 for (int i = 0; i < limit; i++) { |
| 10103 PropertyDetails details = descriptors->GetDetails(i); | 8717 PropertyDetails details = descriptors->GetDetails(i); |
| 10104 if (details.type() != FIELD) continue; | 8718 if (details.type() != FIELD) continue; |
| 10105 copied_fields++; | 8719 copied_fields++; |
| 10106 int index = descriptors->GetFieldIndex(i); | 8720 int index = descriptors->GetFieldIndex(i); |
| 10107 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); | 8721 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); |
| 10108 Handle<Name> name(descriptors->GetKey(i)); | 8722 Handle<Name> name(descriptors->GetKey(i)); |
| 10109 Handle<Object> value = | 8723 Handle<Object> value = |
| 10110 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), | 8724 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), |
| 10111 isolate()); | 8725 isolate()); |
| 10112 | 8726 |
| 10113 // The access for the store depends on the type of the boilerplate. | 8727 // The access for the store depends on the type of the boilerplate. |
| 10114 HObjectAccess access = boilerplate_object->IsJSArray() ? | 8728 HObjectAccess access = boilerplate_object->IsJSArray() ? |
| 10115 HObjectAccess::ForJSArrayOffset(property_offset) : | 8729 HObjectAccess::ForJSArrayOffset(property_offset) : |
| 10116 HObjectAccess::ForJSObjectOffset(property_offset); | 8730 HObjectAccess::ForJSObjectOffset(property_offset); |
| 10117 | 8731 |
| 10118 if (value->IsJSObject()) { | 8732 if (value->IsJSObject()) { |
| 10119 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 8733 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 10120 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 8734 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
| 10121 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), | 8735 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), |
| 10122 isolate())); | 8736 isolate())); |
| 10123 HInstruction* value_instruction = | 8737 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target, |
| 10124 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); | 8738 *offset); |
| 10125 | 8739 |
| 10126 AddStore(object_properties, access, value_instruction); | 8740 AddStore(object_properties, access, value_instruction); |
| 10127 | 8741 BuildEmitDeepCopy(value_object, original_value_object, |
| 10128 BuildEmitDeepCopy(value_object, original_value_object, target, | 8742 Handle<Object>::null(), target, |
| 10129 offset, data_target, data_offset, DONT_TRACK_ALLOCATION_SITE); | 8743 offset, data_target, data_offset, |
| 8744 DONT_TRACK_ALLOCATION_SITE); |
| 10130 } else { | 8745 } else { |
| 10131 Representation representation = details.representation(); | 8746 Representation representation = details.representation(); |
| 10132 HInstruction* value_instruction = | 8747 HInstruction* value_instruction = Add<HConstant>(value); |
| 10133 AddInstruction(new(zone) HConstant(value)); | |
| 10134 | 8748 |
| 10135 if (representation.IsDouble()) { | 8749 if (representation.IsDouble()) { |
| 10136 // Allocate a HeapNumber box and store the value into it. | 8750 // Allocate a HeapNumber box and store the value into it. |
| 10137 HInstruction* double_box; | 8751 HInstruction* double_box; |
| 10138 if (data_target != NULL) { | 8752 if (data_target != NULL) { |
| 10139 double_box = AddInstruction(new(zone) HInnerAllocatedObject( | 8753 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); |
| 10140 data_target, *data_offset)); | |
| 10141 *data_offset += HeapNumber::kSize; | 8754 *data_offset += HeapNumber::kSize; |
| 10142 } else { | 8755 } else { |
| 10143 double_box = AddInstruction(new(zone) HInnerAllocatedObject( | 8756 double_box = Add<HInnerAllocatedObject>(target, *offset); |
| 10144 target, *offset)); | |
| 10145 *offset += HeapNumber::kSize; | 8757 *offset += HeapNumber::kSize; |
| 10146 } | 8758 } |
| 10147 AddStoreMapConstant(double_box, | 8759 AddStoreMapConstant(double_box, |
| 10148 isolate()->factory()->heap_number_map()); | 8760 isolate()->factory()->heap_number_map()); |
| 10149 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 8761 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), |
| 10150 value_instruction, Representation::Double()); | 8762 value_instruction, Representation::Double()); |
| 10151 value_instruction = double_box; | 8763 value_instruction = double_box; |
| 10152 } | 8764 } |
| 10153 | 8765 |
| 10154 AddStore(object_properties, access, value_instruction); | 8766 AddStore(object_properties, access, value_instruction); |
| 10155 } | 8767 } |
| 10156 } | 8768 } |
| 10157 | 8769 |
| 10158 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 8770 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
| 10159 HInstruction* value_instruction = AddInstruction(new(zone) | 8771 HInstruction* value_instruction = |
| 10160 HConstant(isolate()->factory()->one_pointer_filler_map())); | 8772 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); |
| 10161 for (int i = copied_fields; i < inobject_properties; i++) { | 8773 for (int i = copied_fields; i < inobject_properties; i++) { |
| 10162 ASSERT(boilerplate_object->IsJSObject()); | 8774 ASSERT(boilerplate_object->IsJSObject()); |
| 10163 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); | 8775 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); |
| 10164 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); | 8776 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); |
| 10165 AddStore(object_properties, access, value_instruction); | 8777 AddStore(object_properties, access, value_instruction); |
| 10166 } | 8778 } |
| 10167 } | 8779 } |
| 10168 | 8780 |
| 10169 | 8781 |
| 10170 void HOptimizedGraphBuilder::BuildEmitElements( | 8782 void HOptimizedGraphBuilder::BuildEmitElements( |
| 10171 Handle<FixedArrayBase> elements, | 8783 Handle<FixedArrayBase> elements, |
| 10172 Handle<FixedArrayBase> original_elements, | 8784 Handle<FixedArrayBase> original_elements, |
| 10173 ElementsKind kind, | 8785 ElementsKind kind, |
| 10174 HValue* object_elements, | 8786 HValue* object_elements, |
| 10175 HInstruction* target, | 8787 HInstruction* target, |
| 10176 int* offset, | 8788 int* offset, |
| 10177 HInstruction* data_target, | 8789 HInstruction* data_target, |
| 10178 int* data_offset) { | 8790 int* data_offset) { |
| 10179 Zone* zone = this->zone(); | |
| 10180 | |
| 10181 int elements_length = elements->length(); | 8791 int elements_length = elements->length(); |
| 10182 HValue* object_elements_length = | 8792 HValue* object_elements_length = Add<HConstant>(elements_length); |
| 10183 AddInstruction(new(zone) HConstant(elements_length)); | |
| 10184 | 8793 |
| 10185 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); | 8794 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); |
| 10186 | 8795 |
| 10187 // Copy elements backing store content. | 8796 // Copy elements backing store content. |
| 10188 if (elements->IsFixedDoubleArray()) { | 8797 if (elements->IsFixedDoubleArray()) { |
| 10189 BuildEmitFixedDoubleArray(elements, kind, object_elements); | 8798 BuildEmitFixedDoubleArray(elements, kind, object_elements); |
| 10190 } else if (elements->IsFixedArray()) { | 8799 } else if (elements->IsFixedArray()) { |
| 10191 BuildEmitFixedArray(elements, original_elements, kind, object_elements, | 8800 BuildEmitFixedArray(elements, original_elements, kind, object_elements, |
| 10192 target, offset, data_target, data_offset); | 8801 target, offset, data_target, data_offset); |
| 10193 } else { | 8802 } else { |
| 10194 UNREACHABLE(); | 8803 UNREACHABLE(); |
| 10195 } | 8804 } |
| 10196 } | 8805 } |
| 10197 | 8806 |
| 10198 | 8807 |
| 10199 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( | 8808 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( |
| 10200 Handle<FixedArrayBase> elements, | 8809 Handle<FixedArrayBase> elements, |
| 10201 ElementsKind kind, | 8810 ElementsKind kind, |
| 10202 HValue* object_elements) { | 8811 HValue* object_elements) { |
| 10203 Zone* zone = this->zone(); | 8812 HInstruction* boilerplate_elements = Add<HConstant>(elements); |
| 10204 HInstruction* boilerplate_elements = | |
| 10205 AddInstruction(new(zone) HConstant(elements)); | |
| 10206 int elements_length = elements->length(); | 8813 int elements_length = elements->length(); |
| 10207 for (int i = 0; i < elements_length; i++) { | 8814 for (int i = 0; i < elements_length; i++) { |
| 10208 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); | 8815 HValue* key_constant = Add<HConstant>(i); |
| 10209 HInstruction* value_instruction = | 8816 HInstruction* value_instruction = |
| 10210 AddInstruction(new(zone) HLoadKeyed( | 8817 Add<HLoadKeyed>(boilerplate_elements, key_constant, |
| 10211 boilerplate_elements, key_constant, NULL, kind, ALLOW_RETURN_HOLE)); | 8818 static_cast<HValue*>(NULL), kind, |
| 10212 HInstruction* store = AddInstruction(new(zone) HStoreKeyed( | 8819 ALLOW_RETURN_HOLE); |
| 10213 object_elements, key_constant, value_instruction, kind)); | 8820 HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant, |
| 8821 value_instruction, kind); |
| 10214 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 8822 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 10215 } | 8823 } |
| 10216 } | 8824 } |
| 10217 | 8825 |
| 10218 | 8826 |
| 10219 void HOptimizedGraphBuilder::BuildEmitFixedArray( | 8827 void HOptimizedGraphBuilder::BuildEmitFixedArray( |
| 10220 Handle<FixedArrayBase> elements, | 8828 Handle<FixedArrayBase> elements, |
| 10221 Handle<FixedArrayBase> original_elements, | 8829 Handle<FixedArrayBase> original_elements, |
| 10222 ElementsKind kind, | 8830 ElementsKind kind, |
| 10223 HValue* object_elements, | 8831 HValue* object_elements, |
| 10224 HInstruction* target, | 8832 HInstruction* target, |
| 10225 int* offset, | 8833 int* offset, |
| 10226 HInstruction* data_target, | 8834 HInstruction* data_target, |
| 10227 int* data_offset) { | 8835 int* data_offset) { |
| 10228 Zone* zone = this->zone(); | 8836 HInstruction* boilerplate_elements = Add<HConstant>(elements); |
| 10229 HInstruction* boilerplate_elements = | |
| 10230 AddInstruction(new(zone) HConstant(elements)); | |
| 10231 int elements_length = elements->length(); | 8837 int elements_length = elements->length(); |
| 10232 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 8838 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 10233 Handle<FixedArray> original_fast_elements = | 8839 Handle<FixedArray> original_fast_elements = |
| 10234 Handle<FixedArray>::cast(original_elements); | 8840 Handle<FixedArray>::cast(original_elements); |
| 10235 for (int i = 0; i < elements_length; i++) { | 8841 for (int i = 0; i < elements_length; i++) { |
| 10236 Handle<Object> value(fast_elements->get(i), isolate()); | 8842 Handle<Object> value(fast_elements->get(i), isolate()); |
| 10237 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); | 8843 HValue* key_constant = Add<HConstant>(i); |
| 10238 if (value->IsJSObject()) { | 8844 if (value->IsJSObject()) { |
| 10239 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 8845 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 10240 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 8846 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
| 10241 Handle<Object>(original_fast_elements->get(i), isolate())); | 8847 Handle<Object>(original_fast_elements->get(i), isolate())); |
| 10242 HInstruction* value_instruction = | 8848 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target, |
| 10243 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); | 8849 *offset); |
| 10244 AddInstruction(new(zone) HStoreKeyed( | 8850 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); |
| 10245 object_elements, key_constant, value_instruction, kind)); | 8851 BuildEmitDeepCopy(value_object, original_value_object, |
| 10246 BuildEmitDeepCopy(value_object, original_value_object, target, | 8852 Handle<Object>::null(), target, |
| 10247 offset, data_target, data_offset, DONT_TRACK_ALLOCATION_SITE); | 8853 offset, data_target, data_offset, |
| 8854 DONT_TRACK_ALLOCATION_SITE); |
| 10248 } else { | 8855 } else { |
| 10249 HInstruction* value_instruction = | 8856 HInstruction* value_instruction = |
| 10250 AddInstruction(new(zone) HLoadKeyed( | 8857 Add<HLoadKeyed>(boilerplate_elements, key_constant, |
| 10251 boilerplate_elements, key_constant, NULL, kind, | 8858 static_cast<HValue*>(NULL), kind, |
| 10252 ALLOW_RETURN_HOLE)); | 8859 ALLOW_RETURN_HOLE); |
| 10253 AddInstruction(new(zone) HStoreKeyed( | 8860 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); |
| 10254 object_elements, key_constant, value_instruction, kind)); | |
| 10255 } | 8861 } |
| 10256 } | 8862 } |
| 10257 } | 8863 } |
| 10258 | 8864 |
| 8865 |
| 10259 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 8866 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 10260 ASSERT(!HasStackOverflow()); | 8867 ASSERT(!HasStackOverflow()); |
| 10261 ASSERT(current_block() != NULL); | 8868 ASSERT(current_block() != NULL); |
| 10262 ASSERT(current_block()->HasPredecessor()); | 8869 ASSERT(current_block()->HasPredecessor()); |
| 10263 HInstruction* instr = BuildThisFunction(); | 8870 HInstruction* instr = BuildThisFunction(); |
| 10264 return ast_context()->ReturnInstruction(instr, expr->id()); | 8871 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 10265 } | 8872 } |
| 10266 | 8873 |
| 10267 | 8874 |
| 10268 void HOptimizedGraphBuilder::VisitDeclarations( | 8875 void HOptimizedGraphBuilder::VisitDeclarations( |
| 10269 ZoneList<Declaration*>* declarations) { | 8876 ZoneList<Declaration*>* declarations) { |
| 10270 ASSERT(globals_.is_empty()); | 8877 ASSERT(globals_.is_empty()); |
| 10271 AstVisitor::VisitDeclarations(declarations); | 8878 AstVisitor::VisitDeclarations(declarations); |
| 10272 if (!globals_.is_empty()) { | 8879 if (!globals_.is_empty()) { |
| 10273 Handle<FixedArray> array = | 8880 Handle<FixedArray> array = |
| 10274 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 8881 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
| 10275 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 8882 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
| 10276 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | | 8883 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | |
| 10277 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | | 8884 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | |
| 10278 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); | 8885 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); |
| 10279 HInstruction* result = new(zone()) HDeclareGlobals( | 8886 Add<HDeclareGlobals>(environment()->LookupContext(), array, flags); |
| 10280 environment()->LookupContext(), array, flags); | |
| 10281 AddInstruction(result); | |
| 10282 globals_.Clear(); | 8887 globals_.Clear(); |
| 10283 } | 8888 } |
| 10284 } | 8889 } |
| 10285 | 8890 |
| 10286 | 8891 |
| 10287 void HOptimizedGraphBuilder::VisitVariableDeclaration( | 8892 void HOptimizedGraphBuilder::VisitVariableDeclaration( |
| 10288 VariableDeclaration* declaration) { | 8893 VariableDeclaration* declaration) { |
| 10289 VariableProxy* proxy = declaration->proxy(); | 8894 VariableProxy* proxy = declaration->proxy(); |
| 10290 VariableMode mode = declaration->mode(); | 8895 VariableMode mode = declaration->mode(); |
| 10291 Variable* variable = proxy->var(); | 8896 Variable* variable = proxy->var(); |
| 10292 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; | 8897 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; |
| 10293 switch (variable->location()) { | 8898 switch (variable->location()) { |
| 10294 case Variable::UNALLOCATED: | 8899 case Variable::UNALLOCATED: |
| 10295 globals_.Add(variable->name(), zone()); | 8900 globals_.Add(variable->name(), zone()); |
| 10296 globals_.Add(variable->binding_needs_init() | 8901 globals_.Add(variable->binding_needs_init() |
| 10297 ? isolate()->factory()->the_hole_value() | 8902 ? isolate()->factory()->the_hole_value() |
| 10298 : isolate()->factory()->undefined_value(), zone()); | 8903 : isolate()->factory()->undefined_value(), zone()); |
| 10299 return; | 8904 return; |
| 10300 case Variable::PARAMETER: | 8905 case Variable::PARAMETER: |
| 10301 case Variable::LOCAL: | 8906 case Variable::LOCAL: |
| 10302 if (hole_init) { | 8907 if (hole_init) { |
| 10303 HValue* value = graph()->GetConstantHole(); | 8908 HValue* value = graph()->GetConstantHole(); |
| 10304 environment()->Bind(variable, value); | 8909 environment()->Bind(variable, value); |
| 10305 } | 8910 } |
| 10306 break; | 8911 break; |
| 10307 case Variable::CONTEXT: | 8912 case Variable::CONTEXT: |
| 10308 if (hole_init) { | 8913 if (hole_init) { |
| 10309 HValue* value = graph()->GetConstantHole(); | 8914 HValue* value = graph()->GetConstantHole(); |
| 10310 HValue* context = environment()->LookupContext(); | 8915 HValue* context = environment()->LookupContext(); |
| 10311 HStoreContextSlot* store = new(zone()) HStoreContextSlot( | 8916 HStoreContextSlot* store = Add<HStoreContextSlot>( |
| 10312 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8917 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
| 10313 AddInstruction(store); | |
| 10314 if (store->HasObservableSideEffects()) { | 8918 if (store->HasObservableSideEffects()) { |
| 10315 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8919 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
| 10316 } | 8920 } |
| 10317 } | 8921 } |
| 10318 break; | 8922 break; |
| 10319 case Variable::LOOKUP: | 8923 case Variable::LOOKUP: |
| 10320 return Bailout("unsupported lookup slot in declaration"); | 8924 return Bailout("unsupported lookup slot in declaration"); |
| 10321 } | 8925 } |
| 10322 } | 8926 } |
| 10323 | 8927 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 10340 case Variable::LOCAL: { | 8944 case Variable::LOCAL: { |
| 10341 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8945 CHECK_ALIVE(VisitForValue(declaration->fun())); |
| 10342 HValue* value = Pop(); | 8946 HValue* value = Pop(); |
| 10343 BindIfLive(variable, value); | 8947 BindIfLive(variable, value); |
| 10344 break; | 8948 break; |
| 10345 } | 8949 } |
| 10346 case Variable::CONTEXT: { | 8950 case Variable::CONTEXT: { |
| 10347 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8951 CHECK_ALIVE(VisitForValue(declaration->fun())); |
| 10348 HValue* value = Pop(); | 8952 HValue* value = Pop(); |
| 10349 HValue* context = environment()->LookupContext(); | 8953 HValue* context = environment()->LookupContext(); |
| 10350 HStoreContextSlot* store = new(zone()) HStoreContextSlot( | 8954 HStoreContextSlot* store = Add<HStoreContextSlot>( |
| 10351 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8955 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
| 10352 AddInstruction(store); | |
| 10353 if (store->HasObservableSideEffects()) { | 8956 if (store->HasObservableSideEffects()) { |
| 10354 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8957 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
| 10355 } | 8958 } |
| 10356 break; | 8959 break; |
| 10357 } | 8960 } |
| 10358 case Variable::LOOKUP: | 8961 case Variable::LOOKUP: |
| 10359 return Bailout("unsupported lookup slot in declaration"); | 8962 return Bailout("unsupported lookup slot in declaration"); |
| 10360 } | 8963 } |
| 10361 } | 8964 } |
| 10362 | 8965 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10514 } | 9117 } |
| 10515 | 9118 |
| 10516 | 9119 |
| 10517 // Support for arguments.length and arguments[?]. | 9120 // Support for arguments.length and arguments[?]. |
| 10518 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 9121 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
| 10519 // Our implementation of arguments (based on this stack frame or an | 9122 // Our implementation of arguments (based on this stack frame or an |
| 10520 // adapter below it) does not work for inlined functions. This runtime | 9123 // adapter below it) does not work for inlined functions. This runtime |
| 10521 // function is blacklisted by AstNode::IsInlineable. | 9124 // function is blacklisted by AstNode::IsInlineable. |
| 10522 ASSERT(function_state()->outer() == NULL); | 9125 ASSERT(function_state()->outer() == NULL); |
| 10523 ASSERT(call->arguments()->length() == 0); | 9126 ASSERT(call->arguments()->length() == 0); |
| 10524 HInstruction* elements = AddInstruction( | 9127 HInstruction* elements = Add<HArgumentsElements>(false); |
| 10525 new(zone()) HArgumentsElements(false)); | |
| 10526 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); | 9128 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); |
| 10527 return ast_context()->ReturnInstruction(result, call->id()); | 9129 return ast_context()->ReturnInstruction(result, call->id()); |
| 10528 } | 9130 } |
| 10529 | 9131 |
| 10530 | 9132 |
| 10531 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { | 9133 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { |
| 10532 // Our implementation of arguments (based on this stack frame or an | 9134 // Our implementation of arguments (based on this stack frame or an |
| 10533 // adapter below it) does not work for inlined functions. This runtime | 9135 // adapter below it) does not work for inlined functions. This runtime |
| 10534 // function is blacklisted by AstNode::IsInlineable. | 9136 // function is blacklisted by AstNode::IsInlineable. |
| 10535 ASSERT(function_state()->outer() == NULL); | 9137 ASSERT(function_state()->outer() == NULL); |
| 10536 ASSERT(call->arguments()->length() == 1); | 9138 ASSERT(call->arguments()->length() == 1); |
| 10537 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9139 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10538 HValue* index = Pop(); | 9140 HValue* index = Pop(); |
| 10539 HInstruction* elements = AddInstruction( | 9141 HInstruction* elements = Add<HArgumentsElements>(false); |
| 10540 new(zone()) HArgumentsElements(false)); | 9142 HInstruction* length = Add<HArgumentsLength>(elements); |
| 10541 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); | 9143 HInstruction* checked_index = Add<HBoundsCheck>(index, length); |
| 10542 HInstruction* checked_index = AddBoundsCheck(index, length); | |
| 10543 HAccessArgumentsAt* result = | 9144 HAccessArgumentsAt* result = |
| 10544 new(zone()) HAccessArgumentsAt(elements, length, checked_index); | 9145 new(zone()) HAccessArgumentsAt(elements, length, checked_index); |
| 10545 return ast_context()->ReturnInstruction(result, call->id()); | 9146 return ast_context()->ReturnInstruction(result, call->id()); |
| 10546 } | 9147 } |
| 10547 | 9148 |
| 10548 | 9149 |
| 10549 // Support for accessing the class and value fields of an object. | 9150 // Support for accessing the class and value fields of an object. |
| 10550 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { | 9151 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { |
| 10551 // The special form detected by IsClassOfTest is detected before we get here | 9152 // The special form detected by IsClassOfTest is detected before we get here |
| 10552 // and does not cause a bailout. | 9153 // and does not cause a bailout. |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10696 | 9297 |
| 10697 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { | 9298 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { |
| 10698 // %_Log is ignored in optimized code. | 9299 // %_Log is ignored in optimized code. |
| 10699 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 9300 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| 10700 } | 9301 } |
| 10701 | 9302 |
| 10702 | 9303 |
| 10703 // Fast support for Math.random(). | 9304 // Fast support for Math.random(). |
| 10704 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | 9305 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
| 10705 HValue* context = environment()->LookupContext(); | 9306 HValue* context = environment()->LookupContext(); |
| 10706 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 9307 HGlobalObject* global_object = Add<HGlobalObject>(context); |
| 10707 AddInstruction(global_object); | |
| 10708 HRandom* result = new(zone()) HRandom(global_object); | 9308 HRandom* result = new(zone()) HRandom(global_object); |
| 10709 return ast_context()->ReturnInstruction(result, call->id()); | 9309 return ast_context()->ReturnInstruction(result, call->id()); |
| 10710 } | 9310 } |
| 10711 | 9311 |
| 10712 | 9312 |
| 10713 // Fast support for StringAdd. | 9313 // Fast support for StringAdd. |
| 10714 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 9314 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
| 10715 ASSERT_EQ(2, call->arguments()->length()); | 9315 ASSERT_EQ(2, call->arguments()->length()); |
| 10716 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9316 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 10717 HValue* context = environment()->LookupContext(); | 9317 HValue* context = environment()->LookupContext(); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10803 HHasInstanceTypeAndBranch* typecheck = | 9403 HHasInstanceTypeAndBranch* typecheck = |
| 10804 new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE); | 9404 new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE); |
| 10805 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); | 9405 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); |
| 10806 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); | 9406 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); |
| 10807 HBasicBlock* join = graph()->CreateBasicBlock(); | 9407 HBasicBlock* join = graph()->CreateBasicBlock(); |
| 10808 typecheck->SetSuccessorAt(0, if_jsfunction); | 9408 typecheck->SetSuccessorAt(0, if_jsfunction); |
| 10809 typecheck->SetSuccessorAt(1, if_nonfunction); | 9409 typecheck->SetSuccessorAt(1, if_nonfunction); |
| 10810 current_block()->Finish(typecheck); | 9410 current_block()->Finish(typecheck); |
| 10811 | 9411 |
| 10812 set_current_block(if_jsfunction); | 9412 set_current_block(if_jsfunction); |
| 10813 HInstruction* invoke_result = AddInstruction( | 9413 HInstruction* invoke_result = |
| 10814 new(zone()) HInvokeFunction(context, function, arg_count)); | 9414 Add<HInvokeFunction>(context, function, arg_count); |
| 10815 Drop(arg_count); | 9415 Drop(arg_count); |
| 10816 Push(invoke_result); | 9416 Push(invoke_result); |
| 10817 if_jsfunction->Goto(join); | 9417 if_jsfunction->Goto(join); |
| 10818 | 9418 |
| 10819 set_current_block(if_nonfunction); | 9419 set_current_block(if_nonfunction); |
| 10820 HInstruction* call_result = AddInstruction( | 9420 HInstruction* call_result = Add<HCallFunction>(context, function, arg_count); |
| 10821 new(zone()) HCallFunction(context, function, arg_count)); | |
| 10822 Drop(arg_count); | 9421 Drop(arg_count); |
| 10823 Push(call_result); | 9422 Push(call_result); |
| 10824 if_nonfunction->Goto(join); | 9423 if_nonfunction->Goto(join); |
| 10825 | 9424 |
| 10826 set_current_block(join); | 9425 set_current_block(join); |
| 10827 join->SetJoinId(call->id()); | 9426 join->SetJoinId(call->id()); |
| 10828 return ast_context()->ReturnValue(Pop()); | 9427 return ast_context()->ReturnValue(Pop()); |
| 10829 } | 9428 } |
| 10830 | 9429 |
| 10831 | 9430 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10924 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) { | 9523 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) { |
| 10925 return Bailout("inlined runtime function: GeneratorNext"); | 9524 return Bailout("inlined runtime function: GeneratorNext"); |
| 10926 } | 9525 } |
| 10927 | 9526 |
| 10928 | 9527 |
| 10929 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) { | 9528 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) { |
| 10930 return Bailout("inlined runtime function: GeneratorThrow"); | 9529 return Bailout("inlined runtime function: GeneratorThrow"); |
| 10931 } | 9530 } |
| 10932 | 9531 |
| 10933 | 9532 |
| 9533 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode( |
| 9534 CallRuntime* call) { |
| 9535 AddInstruction(new(zone()) HDebugBreak()); |
| 9536 return ast_context()->ReturnValue(graph()->GetConstant0()); |
| 9537 } |
| 9538 |
| 9539 |
| 10934 #undef CHECK_BAILOUT | 9540 #undef CHECK_BAILOUT |
| 10935 #undef CHECK_ALIVE | 9541 #undef CHECK_ALIVE |
| 10936 | 9542 |
| 10937 | 9543 |
| 10938 HEnvironment::HEnvironment(HEnvironment* outer, | 9544 HEnvironment::HEnvironment(HEnvironment* outer, |
| 10939 Scope* scope, | 9545 Scope* scope, |
| 10940 Handle<JSFunction> closure, | 9546 Handle<JSFunction> closure, |
| 10941 Zone* zone) | 9547 Zone* zone) |
| 10942 : closure_(closure), | 9548 : closure_(closure), |
| 10943 values_(0, zone), | 9549 values_(0, zone), |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11334 trace_.Add("%d ", phi->merged_index()); | 9940 trace_.Add("%d ", phi->merged_index()); |
| 11335 phi->PrintNameTo(&trace_); | 9941 phi->PrintNameTo(&trace_); |
| 11336 trace_.Add(" "); | 9942 trace_.Add(" "); |
| 11337 phi->PrintTo(&trace_); | 9943 phi->PrintTo(&trace_); |
| 11338 trace_.Add("\n"); | 9944 trace_.Add("\n"); |
| 11339 } | 9945 } |
| 11340 } | 9946 } |
| 11341 | 9947 |
| 11342 { | 9948 { |
| 11343 Tag HIR_tag(this, "HIR"); | 9949 Tag HIR_tag(this, "HIR"); |
| 11344 HInstruction* instruction = current->first(); | 9950 for (HInstructionIterator it(current); !it.Done(); it.Advance()) { |
| 11345 while (instruction != NULL) { | 9951 HInstruction* instruction = it.Current(); |
| 11346 int bci = 0; | 9952 int bci = 0; |
| 11347 int uses = instruction->UseCount(); | 9953 int uses = instruction->UseCount(); |
| 11348 PrintIndent(); | 9954 PrintIndent(); |
| 11349 trace_.Add("%d %d ", bci, uses); | 9955 trace_.Add("%d %d ", bci, uses); |
| 11350 instruction->PrintNameTo(&trace_); | 9956 instruction->PrintNameTo(&trace_); |
| 11351 trace_.Add(" "); | 9957 trace_.Add(" "); |
| 11352 instruction->PrintTo(&trace_); | 9958 instruction->PrintTo(&trace_); |
| 11353 trace_.Add(" <|@\n"); | 9959 trace_.Add(" <|@\n"); |
| 11354 instruction = instruction->next(); | |
| 11355 } | 9960 } |
| 11356 } | 9961 } |
| 11357 | 9962 |
| 11358 | 9963 |
| 11359 if (chunk != NULL) { | 9964 if (chunk != NULL) { |
| 11360 Tag LIR_tag(this, "LIR"); | 9965 Tag LIR_tag(this, "LIR"); |
| 11361 int first_index = current->first_instruction_index(); | 9966 int first_index = current->first_instruction_index(); |
| 11362 int last_index = current->last_instruction_index(); | 9967 int last_index = current->last_instruction_index(); |
| 11363 if (first_index != -1 && last_index != -1) { | 9968 if (first_index != -1 && last_index != -1) { |
| 11364 const ZoneList<LInstruction*>* instructions = chunk->instructions(); | 9969 const ZoneList<LInstruction*>* instructions = chunk->instructions(); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11540 if (ShouldProduceTraceOutput()) { | 10145 if (ShouldProduceTraceOutput()) { |
| 11541 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10146 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11542 } | 10147 } |
| 11543 | 10148 |
| 11544 #ifdef DEBUG | 10149 #ifdef DEBUG |
| 11545 graph_->Verify(false); // No full verify. | 10150 graph_->Verify(false); // No full verify. |
| 11546 #endif | 10151 #endif |
| 11547 } | 10152 } |
| 11548 | 10153 |
| 11549 } } // namespace v8::internal | 10154 } } // namespace v8::internal |
| OLD | NEW |