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 |