OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
107 phis_.RemoveElement(phi); | 107 phis_.RemoveElement(phi); |
108 phi->SetBlock(NULL); | 108 phi->SetBlock(NULL); |
109 } | 109 } |
110 | 110 |
111 | 111 |
112 void HBasicBlock::AddInstruction(HInstruction* instr) { | 112 void HBasicBlock::AddInstruction(HInstruction* instr) { |
113 ASSERT(!IsStartBlock() || !IsFinished()); | 113 ASSERT(!IsStartBlock() || !IsFinished()); |
114 ASSERT(!instr->IsLinked()); | 114 ASSERT(!instr->IsLinked()); |
115 ASSERT(!IsFinished()); | 115 ASSERT(!IsFinished()); |
116 if (first_ == NULL) { | 116 if (first_ == NULL) { |
117 ASSERT(last_environment() != NULL); | |
118 ASSERT(!last_environment()->ast_id().IsNone()); | |
117 HBlockEntry* entry = new(zone()) HBlockEntry(); | 119 HBlockEntry* entry = new(zone()) HBlockEntry(); |
118 entry->InitializeAsFirst(this); | 120 entry->InitializeAsFirst(this); |
119 first_ = last_ = entry; | 121 first_ = last_ = entry; |
120 } | 122 } |
121 instr->InsertAfter(last_); | 123 instr->InsertAfter(last_); |
122 } | 124 } |
123 | 125 |
124 | 126 |
125 HDeoptimize* HBasicBlock::CreateDeoptimize( | 127 HDeoptimize* HBasicBlock::CreateDeoptimize( |
126 HDeoptimize::UseEnvironment has_uses) { | 128 HDeoptimize::UseEnvironment has_uses) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
224 for (int i = 0; i < length; i++) { | 226 for (int i = 0; i < length; i++) { |
225 HBasicBlock* predecessor = predecessors_[i]; | 227 HBasicBlock* predecessor = predecessors_[i]; |
226 ASSERT(predecessor->end()->IsGoto()); | 228 ASSERT(predecessor->end()->IsGoto()); |
227 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); | 229 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); |
228 // We only need to verify the ID once. | 230 // We only need to verify the ID once. |
229 ASSERT(i != 0 || | 231 ASSERT(i != 0 || |
230 (predecessor->last_environment()->closure().is_null() || | 232 (predecessor->last_environment()->closure().is_null() || |
231 predecessor->last_environment()->closure()->shared() | 233 predecessor->last_environment()->closure()->shared() |
232 ->VerifyBailoutId(ast_id))); | 234 ->VerifyBailoutId(ast_id))); |
233 simulate->set_ast_id(ast_id); | 235 simulate->set_ast_id(ast_id); |
236 predecessor->last_environment()->set_ast_id(ast_id); | |
234 } | 237 } |
235 } | 238 } |
236 | 239 |
237 | 240 |
238 bool HBasicBlock::Dominates(HBasicBlock* other) const { | 241 bool HBasicBlock::Dominates(HBasicBlock* other) const { |
239 HBasicBlock* current = other->dominator(); | 242 HBasicBlock* current = other->dominator(); |
240 while (current != NULL) { | 243 while (current != NULL) { |
241 if (current == this) return true; | 244 if (current == this) return true; |
242 current = current->dominator(); | 245 current = current->dominator(); |
243 } | 246 } |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
637 HConstant* HGraph::GetConstantHole() { | 640 HConstant* HGraph::GetConstantHole() { |
638 return GetConstant(&constant_hole_, isolate()->factory()->the_hole_value()); | 641 return GetConstant(&constant_hole_, isolate()->factory()->the_hole_value()); |
639 } | 642 } |
640 | 643 |
641 | 644 |
642 HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder, BailoutId id) | 645 HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder, BailoutId id) |
643 : builder_(builder), | 646 : builder_(builder), |
644 finished_(false), | 647 finished_(false), |
645 id_(id) { | 648 id_(id) { |
646 HEnvironment* env = builder->environment(); | 649 HEnvironment* env = builder->environment(); |
647 failure_block_ = builder->CreateBasicBlock(env->Copy()); | 650 failure_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory()); |
648 merge_block_ = builder->CreateBasicBlock(env->Copy()); | 651 merge_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory()); |
649 } | 652 } |
650 | 653 |
651 | 654 |
652 void HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) { | 655 HValue* HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) { |
653 HEnvironment* env = builder_->environment(); | 656 HEnvironment* env = builder_->environment(); |
654 HIsNilAndBranch* compare = | 657 HIsNilAndBranch* compare = |
655 new(zone()) HIsNilAndBranch(value, kStrictEquality, kUndefinedValue); | 658 new(zone()) HIsNilAndBranch(value, kStrictEquality, kUndefinedValue); |
656 HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy()); | 659 HBasicBlock* success_block = |
657 HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy()); | 660 builder_->CreateBasicBlock(env->CopyWithoutHistory()); |
661 HBasicBlock* failure_block = | |
662 builder_->CreateBasicBlock(env->CopyWithoutHistory()); | |
658 compare->SetSuccessorAt(0, failure_block); | 663 compare->SetSuccessorAt(0, failure_block); |
659 compare->SetSuccessorAt(1, success_block); | 664 compare->SetSuccessorAt(1, success_block); |
660 failure_block->Goto(failure_block_); | 665 failure_block->Goto(failure_block_); |
661 builder_->current_block()->Finish(compare); | 666 builder_->current_block()->Finish(compare); |
662 builder_->set_current_block(success_block); | 667 builder_->set_current_block(success_block); |
668 return compare; | |
663 } | 669 } |
664 | 670 |
665 | 671 |
666 void HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left, HValue* right) { | 672 HValue* HGraphBuilder::CheckBuilder::CheckIntegerCompare(HValue* left, |
673 HValue* right, | |
674 Token::Value op) { | |
667 HEnvironment* env = builder_->environment(); | 675 HEnvironment* env = builder_->environment(); |
668 HCompareIDAndBranch* compare = | 676 HCompareIDAndBranch* compare = |
669 new(zone()) HCompareIDAndBranch(left, right, Token::EQ); | 677 new(zone()) HCompareIDAndBranch(left, right, op); |
670 compare->AssumeRepresentation(Representation::Integer32()); | 678 compare->AssumeRepresentation(Representation::Integer32()); |
671 HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy()); | 679 HBasicBlock* success_block = |
672 HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy()); | 680 builder_->CreateBasicBlock(env->CopyWithoutHistory()); |
681 HBasicBlock* failure_block = | |
682 builder_->CreateBasicBlock(env->CopyWithoutHistory()); | |
673 compare->SetSuccessorAt(0, success_block); | 683 compare->SetSuccessorAt(0, success_block); |
674 compare->SetSuccessorAt(1, failure_block); | 684 compare->SetSuccessorAt(1, failure_block); |
675 failure_block->Goto(failure_block_); | 685 failure_block->Goto(failure_block_); |
676 builder_->current_block()->Finish(compare); | 686 builder_->current_block()->Finish(compare); |
677 builder_->set_current_block(success_block); | 687 builder_->set_current_block(success_block); |
688 return compare; | |
678 } | 689 } |
679 | 690 |
680 | 691 |
692 HValue* HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left, | |
693 HValue* right) { | |
694 return CheckIntegerCompare(left, right, Token::EQ); | |
695 } | |
696 | |
697 | |
681 void HGraphBuilder::CheckBuilder::End() { | 698 void HGraphBuilder::CheckBuilder::End() { |
682 ASSERT(!finished_); | 699 ASSERT(!finished_); |
683 builder_->current_block()->Goto(merge_block_); | 700 builder_->current_block()->Goto(merge_block_); |
684 failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll); | 701 failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll); |
685 failure_block_->SetJoinId(id_); | 702 failure_block_->SetJoinId(id_); |
686 builder_->set_current_block(merge_block_); | 703 builder_->set_current_block(merge_block_); |
687 merge_block_->SetJoinId(id_); | 704 merge_block_->SetJoinId(id_); |
688 finished_ = true; | 705 finished_ = true; |
689 } | 706 } |
690 | 707 |
691 | 708 |
692 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, BailoutId id) | 709 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, BailoutId id) |
693 : builder_(builder), | 710 : builder_(builder), |
694 finished_(false), | 711 finished_(false), |
712 did_else_(false), | |
695 id_(id) { | 713 id_(id) { |
696 HEnvironment* env = builder->environment(); | 714 HEnvironment* env = builder->environment(); |
697 first_true_block_ = builder->CreateBasicBlock(env->Copy()); | 715 first_true_block_ = builder->CreateBasicBlock(env->Copy()); |
698 last_true_block_ = NULL; | 716 last_true_block_ = NULL; |
699 first_false_block_ = builder->CreateBasicBlock(env->Copy()); | 717 first_false_block_ = builder->CreateBasicBlock(env->Copy()); |
700 } | 718 } |
701 | 719 |
702 | 720 |
703 HInstruction* HGraphBuilder::IfBuilder::BeginTrue( | 721 HInstruction* HGraphBuilder::IfBuilder::BeginIf( |
704 HValue* left, | 722 HValue* left, |
705 HValue* right, | 723 HValue* right, |
706 Token::Value token, | 724 Token::Value token, |
707 Representation input_representation) { | 725 Representation input_representation) { |
708 HCompareIDAndBranch* compare = | 726 HCompareIDAndBranch* compare = |
709 new(zone()) HCompareIDAndBranch(left, right, token); | 727 new(zone()) HCompareIDAndBranch(left, right, token); |
710 compare->set_observed_input_representation(input_representation, | 728 compare->set_observed_input_representation(input_representation, |
711 input_representation); | 729 input_representation); |
712 compare->ChangeRepresentation(input_representation); | 730 compare->ChangeRepresentation(input_representation); |
713 compare->SetSuccessorAt(0, first_true_block_); | 731 compare->SetSuccessorAt(0, first_true_block_); |
714 compare->SetSuccessorAt(1, first_false_block_); | 732 compare->SetSuccessorAt(1, first_false_block_); |
715 builder_->current_block()->Finish(compare); | 733 builder_->current_block()->Finish(compare); |
716 builder_->set_current_block(first_true_block_); | 734 builder_->set_current_block(first_true_block_); |
717 return compare; | 735 return compare; |
718 } | 736 } |
719 | 737 |
720 | 738 |
721 void HGraphBuilder::IfBuilder::BeginFalse() { | 739 HInstruction* HGraphBuilder::IfBuilder::BeginIfObjectsEqual( |
740 HValue* left, | |
741 HValue* right) { | |
742 HCompareObjectEqAndBranch* compare = | |
743 new(zone()) HCompareObjectEqAndBranch(left, right); | |
744 compare->SetSuccessorAt(0, first_true_block_); | |
745 compare->SetSuccessorAt(1, first_false_block_); | |
746 builder_->current_block()->Finish(compare); | |
747 builder_->set_current_block(first_true_block_); | |
748 return compare; | |
749 } | |
750 | |
751 | |
752 HInstruction* HGraphBuilder::IfBuilder::BeginIfMapsEqual(HValue* value, | |
753 Handle<Map> map) { | |
754 HCompareMap* compare = new(zone()) | |
755 HCompareMap(value, map, first_true_block_, first_false_block_); | |
756 builder_->current_block()->Finish(compare); | |
757 builder_->set_current_block(first_true_block_); | |
758 return compare; | |
759 } | |
760 | |
761 | |
762 void HGraphBuilder::IfBuilder::BeginElse() { | |
722 last_true_block_ = builder_->current_block(); | 763 last_true_block_ = builder_->current_block(); |
723 ASSERT(!last_true_block_->IsFinished()); | 764 ASSERT(!last_true_block_->IsFinished()); |
724 builder_->set_current_block(first_false_block_); | 765 builder_->set_current_block(first_false_block_); |
766 did_else_ = true; | |
725 } | 767 } |
726 | 768 |
727 | 769 |
728 void HGraphBuilder::IfBuilder::End() { | 770 void HGraphBuilder::IfBuilder::End() { |
729 ASSERT(!finished_); | 771 ASSERT(!finished_); |
772 if (!did_else_) BeginElse(); | |
730 ASSERT(!last_true_block_->IsFinished()); | 773 ASSERT(!last_true_block_->IsFinished()); |
731 HBasicBlock* last_false_block = builder_->current_block(); | 774 HBasicBlock* last_false_block = builder_->current_block(); |
732 ASSERT(!last_false_block->IsFinished()); | 775 ASSERT(!last_false_block->IsFinished()); |
733 HEnvironment* merge_env = | 776 HEnvironment* merge_env = |
734 last_true_block_->last_environment()->Copy(); | 777 last_true_block_->last_environment()->CopyWithoutHistory(); |
735 merge_block_ = builder_->CreateBasicBlock(merge_env); | 778 merge_block_ = builder_->CreateBasicBlock(merge_env); |
736 last_true_block_->Goto(merge_block_); | 779 last_true_block_->Goto(merge_block_); |
737 last_false_block->Goto(merge_block_); | 780 last_false_block->Goto(merge_block_); |
738 merge_block_->SetJoinId(id_); | 781 merge_block_->SetJoinId(id_); |
739 builder_->set_current_block(merge_block_); | 782 builder_->set_current_block(merge_block_); |
740 finished_ = true; | 783 finished_ = true; |
741 } | 784 } |
742 | 785 |
743 | 786 |
744 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, | 787 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
846 ASSERT(current_block() != NULL); | 889 ASSERT(current_block() != NULL); |
847 current_block()->AddInstruction(instr); | 890 current_block()->AddInstruction(instr); |
848 return instr; | 891 return instr; |
849 } | 892 } |
850 | 893 |
851 | 894 |
852 void HGraphBuilder::AddSimulate(BailoutId id, | 895 void HGraphBuilder::AddSimulate(BailoutId id, |
853 RemovableSimulate removable) { | 896 RemovableSimulate removable) { |
854 ASSERT(current_block() != NULL); | 897 ASSERT(current_block() != NULL); |
855 current_block()->AddSimulate(id, removable); | 898 current_block()->AddSimulate(id, removable); |
899 environment()->set_ast_id(id); | |
856 } | 900 } |
857 | 901 |
858 | 902 |
859 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, | 903 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, |
860 HValue* length, | 904 HValue* length, |
861 BoundsCheckKeyMode key_mode, | 905 BoundsCheckKeyMode key_mode, |
862 Representation r) { | 906 Representation r) { |
863 if (!index->type().IsSmi()) { | 907 if (!index->type().IsSmi()) { |
864 index = new(graph()->zone()) HCheckSmiOrInt32(index); | 908 index = new(graph()->zone()) HCheckSmiOrInt32(index); |
865 AddInstruction(HCheckSmiOrInt32::cast(index)); | 909 AddInstruction(HCheckSmiOrInt32::cast(index)); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
943 } | 987 } |
944 } | 988 } |
945 | 989 |
946 | 990 |
947 HInstruction* HGraphBuilder::BuildFastElementAccess( | 991 HInstruction* HGraphBuilder::BuildFastElementAccess( |
948 HValue* elements, | 992 HValue* elements, |
949 HValue* checked_key, | 993 HValue* checked_key, |
950 HValue* val, | 994 HValue* val, |
951 HValue* load_dependency, | 995 HValue* load_dependency, |
952 ElementsKind elements_kind, | 996 ElementsKind elements_kind, |
953 bool is_store) { | 997 bool is_store, |
998 KeyedAccessStoreMode store_mode) { | |
954 Zone* zone = this->zone(); | 999 Zone* zone = this->zone(); |
955 if (is_store) { | 1000 if (is_store) { |
956 ASSERT(val != NULL); | 1001 ASSERT(val != NULL); |
957 switch (elements_kind) { | 1002 switch (elements_kind) { |
958 case FAST_SMI_ELEMENTS: | 1003 case FAST_SMI_ELEMENTS: |
959 case FAST_HOLEY_SMI_ELEMENTS: | 1004 case FAST_HOLEY_SMI_ELEMENTS: |
960 // Smi-only arrays need a smi check. | 1005 // Smi-only arrays need a smi check. |
961 AddInstruction(new(zone) HCheckSmi(val)); | 1006 AddInstruction(new(zone) HCheckSmi(val)); |
962 // Fall through. | 1007 // Fall through. |
963 case FAST_ELEMENTS: | 1008 case FAST_ELEMENTS: |
964 case FAST_HOLEY_ELEMENTS: | 1009 case FAST_HOLEY_ELEMENTS: |
965 case FAST_DOUBLE_ELEMENTS: | 1010 case FAST_DOUBLE_ELEMENTS: |
966 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1011 case FAST_HOLEY_DOUBLE_ELEMENTS: |
967 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); | 1012 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); |
968 default: | 1013 default: |
969 UNREACHABLE(); | 1014 UNREACHABLE(); |
970 return NULL; | 1015 return NULL; |
971 } | 1016 } |
972 } | 1017 } |
973 // It's an element load (!is_store). | 1018 // It's an element load (!is_store). |
974 return new(zone) HLoadKeyed(elements, | 1019 return new(zone) HLoadKeyed(elements, |
975 checked_key, | 1020 checked_key, |
976 load_dependency, | 1021 load_dependency, |
977 elements_kind); | 1022 elements_kind); |
978 } | 1023 } |
979 | 1024 |
980 | 1025 |
1026 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, | |
1027 HValue* elements, | |
1028 ElementsKind kind, | |
1029 HValue* length, | |
1030 HValue* key, | |
1031 bool is_js_array) { | |
1032 BailoutId ast_id = environment()->ast_id(); | |
1033 Zone* zone = this->zone(); | |
1034 IfBuilder length_checker(this, ast_id); | |
1035 | |
1036 length_checker.BeginIf(length, key, Token::EQ); | |
1037 | |
1038 HValue* current_capacity = | |
1039 AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | |
1040 | |
1041 IfBuilder capacity_checker(this, ast_id); | |
1042 | |
1043 capacity_checker.BeginIf(length, current_capacity, Token::EQ); | |
1044 | |
1045 HValue* context = environment()->LookupContext(); | |
1046 | |
1047 HValue* new_capacity = | |
1048 BuildNewElementsCapacity(context, current_capacity); | |
1049 | |
1050 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | |
1051 kind, length, | |
1052 new_capacity, ast_id); | |
1053 | |
1054 environment()->Push(new_elements); | |
1055 capacity_checker.BeginElse(); | |
1056 | |
1057 environment()->Push(elements); | |
1058 capacity_checker.End(); | |
1059 | |
1060 if (is_js_array) { | |
1061 HValue* new_length = AddInstruction( | |
1062 HAdd::New(zone, context, length, graph_->GetConstant1())); | |
1063 new_length->ChangeRepresentation(Representation::Integer32()); | |
1064 new_length->ClearFlag(HValue::kCanOverflow); | |
1065 AddSimulate(ast_id, REMOVABLE_SIMULATE); | |
1066 | |
1067 Factory* factory = isolate()->factory(); | |
1068 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField( | |
1069 object, | |
1070 factory->length_field_string(), | |
1071 new_length, true, | |
1072 JSArray::kLengthOffset)); | |
1073 length_store->SetGVNFlag(kChangesArrayLengths); | |
1074 AddSimulate(ast_id, REMOVABLE_SIMULATE); | |
1075 } | |
1076 | |
1077 length_checker.BeginElse(); | |
1078 | |
1079 AddBoundsCheck(key, length, ALLOW_SMI_KEY); | |
1080 environment()->Push(elements); | |
1081 | |
1082 length_checker.End(); | |
1083 | |
1084 return environment()->Pop(); | |
1085 } | |
1086 | |
1087 | |
1088 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, | |
1089 HValue* elements, | |
1090 ElementsKind kind, | |
1091 HValue* length) { | |
1092 BailoutId ast_id = environment()->ast_id(); | |
1093 Zone* zone = this->zone(); | |
1094 Heap* heap = isolate()->heap(); | |
1095 | |
1096 IfBuilder cow_checker(this, ast_id); | |
1097 | |
1098 cow_checker.BeginIfMapsEqual(elements, | |
1099 Handle<Map>(heap->fixed_cow_array_map())); | |
1100 | |
1101 HValue* capacity = | |
1102 AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | |
1103 | |
1104 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | |
1105 kind, length, | |
1106 capacity, ast_id); | |
1107 | |
1108 environment()->Push(new_elements); | |
1109 | |
1110 cow_checker.BeginElse(); | |
1111 | |
1112 environment()->Push(elements); | |
1113 | |
1114 cow_checker.End(); | |
1115 | |
1116 return environment()->Pop(); | |
1117 } | |
1118 | |
1119 | |
981 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1120 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
982 HValue* object, | 1121 HValue* object, |
983 HValue* key, | 1122 HValue* key, |
984 HValue* val, | 1123 HValue* val, |
985 HCheckMaps* mapcheck, | 1124 HCheckMaps* mapcheck, |
986 bool is_js_array, | 1125 bool is_js_array, |
987 ElementsKind elements_kind, | 1126 ElementsKind elements_kind, |
988 bool is_store, | 1127 bool is_store, |
1128 KeyedAccessStoreMode store_mode, | |
989 Representation checked_index_representation) { | 1129 Representation checked_index_representation) { |
1130 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); | |
990 Zone* zone = this->zone(); | 1131 Zone* zone = this->zone(); |
991 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 1132 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
992 // on a HElementsTransition instruction. The flag can also be removed if the | 1133 // on a HElementsTransition instruction. The flag can also be removed if the |
993 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 1134 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
994 // ElementsKind transitions. Finally, the dependency can be removed for stores | 1135 // ElementsKind transitions. Finally, the dependency can be removed for stores |
995 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 1136 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
996 // generated store code. | 1137 // generated store code. |
997 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | 1138 if ((elements_kind == FAST_HOLEY_ELEMENTS) || |
998 (elements_kind == FAST_ELEMENTS && is_store)) { | 1139 (elements_kind == FAST_ELEMENTS && is_store)) { |
999 if (mapcheck != NULL) { | 1140 if (mapcheck != NULL) { |
1000 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 1141 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
1001 } | 1142 } |
1002 } | 1143 } |
1003 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | 1144 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); |
1004 bool fast_elements = IsFastObjectElementsKind(elements_kind); | 1145 bool fast_elements = IsFastObjectElementsKind(elements_kind); |
1005 HInstruction* elements = | 1146 HValue* elements = |
1006 AddInstruction(new(zone) HLoadElements(object, mapcheck)); | 1147 AddInstruction(new(zone) HLoadElements(object, mapcheck)); |
1007 if (is_store && (fast_elements || fast_smi_only_elements)) { | 1148 if (is_store && (fast_elements || fast_smi_only_elements) && |
1149 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | |
1008 HCheckMaps* check_cow_map = new(zone) HCheckMaps( | 1150 HCheckMaps* check_cow_map = new(zone) HCheckMaps( |
1009 elements, isolate()->factory()->fixed_array_map(), zone); | 1151 elements, isolate()->factory()->fixed_array_map(), zone); |
1010 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1152 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1011 AddInstruction(check_cow_map); | 1153 AddInstruction(check_cow_map); |
1012 } | 1154 } |
1013 HInstruction* length = NULL; | 1155 HInstruction* length = NULL; |
1014 HInstruction* checked_key = NULL; | |
1015 if (IsExternalArrayElementsKind(elements_kind)) { | |
1016 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | |
1017 checked_key = AddBoundsCheck( | |
1018 key, length, ALLOW_SMI_KEY, checked_index_representation); | |
1019 HLoadExternalArrayPointer* external_elements = | |
1020 new(zone) HLoadExternalArrayPointer(elements); | |
1021 AddInstruction(external_elements); | |
1022 return BuildExternalArrayElementAccess( | |
1023 external_elements, checked_key, val, mapcheck, | |
1024 elements_kind, is_store); | |
1025 } | |
1026 ASSERT(fast_smi_only_elements || | |
1027 fast_elements || | |
1028 IsFastDoubleElementsKind(elements_kind)); | |
1029 if (is_js_array) { | 1156 if (is_js_array) { |
1030 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, | 1157 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, |
1031 HType::Smi())); | 1158 HType::Smi())); |
1032 } else { | 1159 } else { |
1033 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | 1160 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
1034 } | 1161 } |
1035 checked_key = AddBoundsCheck( | 1162 HValue* checked_key = NULL; |
1036 key, length, ALLOW_SMI_KEY, checked_index_representation); | 1163 if (IsExternalArrayElementsKind(elements_kind)) { |
1037 return BuildFastElementAccess(elements, checked_key, val, mapcheck, | 1164 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
1038 elements_kind, is_store); | 1165 HLoadExternalArrayPointer* external_elements = |
1166 new(zone) HLoadExternalArrayPointer(elements); | |
1167 AddInstruction(external_elements); | |
1168 BailoutId previous_id = environment()->ast_id(); | |
1169 ASSERT(!previous_id.IsNone()); | |
1170 IfBuilder length_checker(this, previous_id); | |
1171 length_checker.BeginIf(key, length, Token::LT); | |
1172 CheckBuilder negative_checker(this, previous_id); | |
1173 HValue* bounds_check = negative_checker.CheckIntegerCompare( | |
1174 key, graph()->GetConstant0(), Token::GTE); | |
1175 negative_checker.End(); | |
1176 HInstruction* result = BuildExternalArrayElementAccess( | |
1177 external_elements, key, val, bounds_check, | |
1178 elements_kind, is_store); | |
1179 AddInstruction(result); | |
1180 length_checker.End(); | |
1181 return result; | |
1182 } else { | |
1183 ASSERT(store_mode == STANDARD_STORE); | |
1184 checked_key = AddBoundsCheck( | |
1185 key, length, ALLOW_SMI_KEY, checked_index_representation); | |
1186 HLoadExternalArrayPointer* external_elements = | |
1187 new(zone) HLoadExternalArrayPointer(elements); | |
1188 AddInstruction(external_elements); | |
1189 return AddInstruction(BuildExternalArrayElementAccess( | |
1190 external_elements, checked_key, val, mapcheck, | |
1191 elements_kind, is_store)); | |
1192 } | |
1193 } | |
1194 ASSERT(fast_smi_only_elements || | |
1195 fast_elements || | |
1196 IsFastDoubleElementsKind(elements_kind)); | |
1197 | |
1198 if (is_store && IsFastSmiElementsKind(elements_kind) && | |
1199 val->type().IsTagged() && !val->type().IsSmi()) { | |
Jakob Kummerow
2013/03/14 15:00:20
I meant that you can remove the val->type().IsTagg
danno
2013/03/20 10:04:34
Done.
| |
1200 AddInstruction(new(zone) HCheckSmi(val)); | |
1201 } | |
1202 | |
1203 if (IsGrowStoreMode(store_mode)) { | |
1204 elements = BuildCheckForCapacityGrow(object, elements, elements_kind, | |
1205 length, key, is_js_array); | |
1206 checked_key = key; | |
1207 } else { | |
1208 checked_key = AddBoundsCheck( | |
1209 key, length, ALLOW_SMI_KEY, checked_index_representation); | |
1210 | |
1211 if (is_store && (fast_elements || fast_smi_only_elements)) { | |
1212 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | |
1213 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, | |
1214 length); | |
1215 } else { | |
1216 HCheckMaps* check_cow_map = new(zone) HCheckMaps( | |
1217 elements, isolate()->factory()->fixed_array_map(), zone); | |
1218 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | |
1219 AddInstruction(check_cow_map); | |
1220 } | |
1221 } | |
1222 } | |
1223 return AddInstruction( | |
1224 BuildFastElementAccess(elements, checked_key, val, mapcheck, | |
1225 elements_kind, is_store, store_mode)); | |
1039 } | 1226 } |
1040 | 1227 |
1041 | 1228 |
1042 HValue* HGraphBuilder::BuildAllocateElements(HContext* context, | 1229 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, |
1043 ElementsKind kind, | 1230 ElementsKind kind, |
1044 HValue* capacity) { | 1231 HValue* capacity, |
1232 BailoutId ast_id) { | |
1045 Zone* zone = this->zone(); | 1233 Zone* zone = this->zone(); |
1046 | 1234 |
1047 int elements_size = IsFastDoubleElementsKind(kind) | 1235 int elements_size = IsFastDoubleElementsKind(kind) |
1048 ? kDoubleSize : kPointerSize; | 1236 ? kDoubleSize : kPointerSize; |
1049 HConstant* elements_size_value = | 1237 HConstant* elements_size_value = |
1050 new(zone) HConstant(elements_size, Representation::Integer32()); | 1238 new(zone) HConstant(elements_size, Representation::Integer32()); |
1051 AddInstruction(elements_size_value); | 1239 AddInstruction(elements_size_value); |
1052 HValue* mul = AddInstruction( | 1240 HValue* mul = AddInstruction( |
1053 HMul::New(zone, context, capacity, elements_size_value)); | 1241 HMul::New(zone, context, capacity, elements_size_value)); |
1054 mul->ChangeRepresentation(Representation::Integer32()); | 1242 mul->ChangeRepresentation(Representation::Integer32()); |
(...skipping 14 matching lines...) Expand all Loading... | |
1069 } | 1257 } |
1070 | 1258 |
1071 HValue* elements = | 1259 HValue* elements = |
1072 AddInstruction(new(zone) HAllocate(context, total_size, | 1260 AddInstruction(new(zone) HAllocate(context, total_size, |
1073 HType::JSArray(), flags)); | 1261 HType::JSArray(), flags)); |
1074 | 1262 |
1075 Factory* factory = isolate()->factory(); | 1263 Factory* factory = isolate()->factory(); |
1076 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1264 Handle<Map> map = IsFastDoubleElementsKind(kind) |
1077 ? factory->fixed_double_array_map() | 1265 ? factory->fixed_double_array_map() |
1078 : factory->fixed_array_map(); | 1266 : factory->fixed_array_map(); |
1079 BuildStoreMap(elements, map, BailoutId::StubEntry()); | 1267 BuildStoreMap(elements, map, ast_id); |
1080 | 1268 |
1081 Handle<String> fixed_array_length_field_name = factory->length_field_string(); | 1269 Handle<String> fixed_array_length_field_name = factory->length_field_string(); |
1082 HInstruction* store_length = | 1270 HInstruction* store_length = |
1083 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, | 1271 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, |
1084 capacity, true, FixedArray::kLengthOffset); | 1272 capacity, true, FixedArray::kLengthOffset); |
1085 AddInstruction(store_length); | 1273 AddInstruction(store_length); |
1086 AddSimulate(BailoutId::StubEntry(), FIXED_SIMULATE); | 1274 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
1087 | 1275 |
1088 return elements; | 1276 return elements; |
1089 } | 1277 } |
1090 | 1278 |
1091 | 1279 |
1092 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | 1280 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, |
1093 HValue* map, | 1281 HValue* map, |
1094 BailoutId id) { | 1282 BailoutId id) { |
1095 Zone* zone = this->zone(); | 1283 Zone* zone = this->zone(); |
1096 Factory* factory = isolate()->factory(); | 1284 Factory* factory = isolate()->factory(); |
1097 Handle<String> map_field_name = factory->map_field_string(); | 1285 Handle<String> map_field_name = factory->map_field_string(); |
1098 HInstruction* store_map = | 1286 HInstruction* store_map = |
1099 new(zone) HStoreNamedField(object, map_field_name, map, | 1287 new(zone) HStoreNamedField(object, map_field_name, map, |
1100 true, JSObject::kMapOffset); | 1288 true, JSObject::kMapOffset); |
1101 store_map->SetGVNFlag(kChangesMaps); | 1289 store_map->SetGVNFlag(kChangesMaps); |
1102 AddInstruction(store_map); | 1290 AddInstruction(store_map); |
1103 AddSimulate(id, FIXED_SIMULATE); | 1291 AddSimulate(id, REMOVABLE_SIMULATE); |
1104 return store_map; | 1292 return store_map; |
1105 } | 1293 } |
1106 | 1294 |
1107 | 1295 |
1108 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | 1296 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, |
1109 Handle<Map> map, | 1297 Handle<Map> map, |
1110 BailoutId id) { | 1298 BailoutId id) { |
1111 Zone* zone = this->zone(); | 1299 Zone* zone = this->zone(); |
1112 HValue* map_constant = | 1300 HValue* map_constant = |
1113 AddInstruction(new(zone) HConstant(map, Representation::Tagged())); | 1301 AddInstruction(new(zone) HConstant(map, Representation::Tagged())); |
1114 return BuildStoreMap(object, map_constant, id); | 1302 return BuildStoreMap(object, map_constant, id); |
1115 } | 1303 } |
1116 | 1304 |
1117 | 1305 |
1118 void HGraphBuilder::BuildCopyElements(HContext* context, | 1306 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, |
1307 HValue* old_capacity) { | |
1308 Zone* zone = this->zone(); | |
1309 HValue* half_old_capacity = | |
1310 AddInstruction(HShr::New(zone, context, old_capacity, | |
1311 graph_->GetConstant1())); | |
1312 half_old_capacity->ChangeRepresentation(Representation::Integer32()); | |
1313 half_old_capacity->ClearFlag(HValue::kCanOverflow); | |
1314 | |
1315 HValue* new_capacity = AddInstruction( | |
1316 HAdd::New(zone, context, half_old_capacity, old_capacity)); | |
1317 new_capacity->ChangeRepresentation(Representation::Integer32()); | |
1318 new_capacity->ClearFlag(HValue::kCanOverflow); | |
1319 | |
1320 HValue* min_growth = | |
1321 AddInstruction(new(zone) HConstant(16, Representation::Integer32())); | |
1322 | |
1323 new_capacity = AddInstruction( | |
1324 HAdd::New(zone, context, new_capacity, min_growth)); | |
1325 new_capacity->ChangeRepresentation(Representation::Integer32()); | |
1326 new_capacity->ClearFlag(HValue::kCanOverflow); | |
1327 | |
1328 return new_capacity; | |
1329 } | |
1330 | |
1331 | |
1332 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { | |
1333 Zone* zone = this->zone(); | |
1334 Heap* heap = isolate()->heap(); | |
1335 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize | |
1336 : kPointerSize; | |
1337 int max_size = heap->MaxNewSpaceAllocationSize() / element_size; | |
1338 max_size -= JSArray::kSize / element_size; | |
1339 HConstant* max_size_constant = | |
1340 new(zone) HConstant(max_size, Representation::Integer32()); | |
1341 AddInstruction(max_size_constant); | |
1342 // Since we're forcing Integer32 representation for this HBoundsCheck, | |
1343 // there's no need to Smi-check the index. | |
1344 AddInstruction(new(zone) | |
1345 HBoundsCheck(length, max_size_constant, | |
1346 DONT_ALLOW_SMI_KEY, Representation::Integer32())); | |
1347 } | |
1348 | |
1349 | |
1350 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | |
1351 HValue* elements, | |
1352 ElementsKind kind, | |
1353 HValue* length, | |
1354 HValue* new_capacity, | |
1355 BailoutId ast_id) { | |
1356 Zone* zone = this->zone(); | |
1357 HValue* context = environment()->LookupContext(); | |
1358 | |
1359 BuildNewSpaceArrayCheck(new_capacity, kind); | |
1360 | |
1361 HValue* new_elements = | |
1362 BuildAllocateElements(context, kind, new_capacity, ast_id); | |
1363 | |
1364 BuildCopyElements(context, elements, kind, | |
1365 new_elements, kind, | |
1366 length, new_capacity, ast_id); | |
1367 | |
1368 Factory* factory = isolate()->factory(); | |
1369 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField( | |
1370 object, | |
1371 factory->elements_field_string(), | |
1372 new_elements, true, | |
1373 JSArray::kElementsOffset)); | |
1374 elements_store->SetGVNFlag(kChangesElementsPointer); | |
1375 | |
1376 return new_elements; | |
1377 } | |
1378 | |
1379 | |
1380 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, | |
1381 HValue* elements, | |
1382 ElementsKind elements_kind, | |
1383 HValue* from, | |
1384 HValue* to, | |
1385 BailoutId ast_id) { | |
1386 // Fast elements kinds need to be initialized in case statements below cause | |
1387 // a garbage collection. | |
1388 Factory* factory = isolate()->factory(); | |
1389 | |
1390 double nan_double = FixedDoubleArray::hole_nan_as_double(); | |
1391 Zone* zone = this->zone(); | |
1392 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | |
1393 ? AddInstruction(new(zone) HConstant(factory->the_hole_value(), | |
1394 Representation::Tagged())) | |
1395 : AddInstruction(new(zone) HConstant(nan_double, | |
1396 Representation::Double())); | |
1397 | |
1398 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id); | |
1399 | |
1400 HValue* key = builder.BeginBody(from, to, Token::LT); | |
1401 | |
1402 AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind)); | |
1403 AddSimulate(ast_id, REMOVABLE_SIMULATE); | |
1404 | |
1405 builder.EndBody(); | |
1406 } | |
1407 | |
1408 | |
1409 void HGraphBuilder::BuildCopyElements(HValue* context, | |
1119 HValue* from_elements, | 1410 HValue* from_elements, |
1120 ElementsKind from_elements_kind, | 1411 ElementsKind from_elements_kind, |
1121 HValue* to_elements, | 1412 HValue* to_elements, |
1122 ElementsKind to_elements_kind, | 1413 ElementsKind to_elements_kind, |
1123 HValue* length) { | 1414 HValue* length, |
1124 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, | 1415 HValue* capacity, |
1125 BailoutId::StubEntry()); | 1416 BailoutId ast_id) { |
1417 bool pre_fill_with_holes = | |
1418 IsFastDoubleElementsKind(from_elements_kind) && | |
1419 IsFastObjectElementsKind(to_elements_kind); | |
1126 | 1420 |
1127 HValue* key = builder.BeginBody(graph()->GetConstant0(), | 1421 if (pre_fill_with_holes) { |
1128 length, Token::LT); | 1422 // If the copy might trigger a GC, make sure that the FixedArray is |
1423 // pre-initialized with holes to make sure that it's always in a consistent | |
1424 // state. | |
1425 BuildFillElementsWithHole(context, to_elements, to_elements_kind, | |
1426 graph()->GetConstant0(), capacity, ast_id); | |
1427 } | |
1428 | |
1429 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id); | |
1430 | |
1431 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); | |
1129 | 1432 |
1130 HValue* element = | 1433 HValue* element = |
1131 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, | 1434 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, |
1132 from_elements_kind, | 1435 from_elements_kind, |
1133 ALLOW_RETURN_HOLE)); | 1436 ALLOW_RETURN_HOLE)); |
1134 | 1437 |
1135 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element, | 1438 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element, |
1136 to_elements_kind)); | 1439 to_elements_kind)); |
1137 AddSimulate(BailoutId::StubEntry(), REMOVABLE_SIMULATE); | 1440 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
1138 | 1441 |
1139 builder.EndBody(); | 1442 builder.EndBody(); |
1443 | |
1444 if (!pre_fill_with_holes && length != capacity) { | |
1445 // Fill unused capacity with the hole. | |
1446 BuildFillElementsWithHole(context, to_elements, to_elements_kind, | |
1447 key, capacity, ast_id); | |
1448 } | |
1140 } | 1449 } |
1141 | 1450 |
1142 | 1451 |
1143 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | 1452 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, |
1144 TypeFeedbackOracle* oracle) | 1453 TypeFeedbackOracle* oracle) |
1145 : HGraphBuilder(info), | 1454 : HGraphBuilder(info), |
1146 function_state_(NULL), | 1455 function_state_(NULL), |
1147 initial_function_state_(this, info, oracle, NORMAL_RETURN), | 1456 initial_function_state_(this, info, oracle, NORMAL_RETURN), |
1148 ast_context_(NULL), | 1457 ast_context_(NULL), |
1149 break_scope_(NULL), | 1458 break_scope_(NULL), |
(...skipping 5624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6774 return new(zone()) HLoadKeyedGeneric(context, object, key); | 7083 return new(zone()) HLoadKeyedGeneric(context, object, key); |
6775 } | 7084 } |
6776 | 7085 |
6777 | 7086 |
6778 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 7087 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( |
6779 HValue* object, | 7088 HValue* object, |
6780 HValue* key, | 7089 HValue* key, |
6781 HValue* val, | 7090 HValue* val, |
6782 HValue* dependency, | 7091 HValue* dependency, |
6783 Handle<Map> map, | 7092 Handle<Map> map, |
6784 bool is_store) { | 7093 bool is_store, |
7094 KeyedAccessStoreMode store_mode) { | |
6785 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, | 7095 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, |
6786 zone(), dependency); | 7096 zone(), dependency); |
6787 AddInstruction(mapcheck); | 7097 AddInstruction(mapcheck); |
6788 if (dependency) { | 7098 if (dependency) { |
6789 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 7099 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
6790 } | 7100 } |
6791 return BuildUncheckedMonomorphicElementAccess( | 7101 return BuildUncheckedMonomorphicElementAccess( |
6792 object, key, val, | 7102 object, key, val, |
6793 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | 7103 mapcheck, map->instance_type() == JS_ARRAY_TYPE, |
6794 map->elements_kind(), is_store); | 7104 map->elements_kind(), is_store, store_mode); |
6795 } | 7105 } |
6796 | 7106 |
6797 | 7107 |
6798 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( | 7108 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( |
6799 HValue* object, | 7109 HValue* object, |
6800 HValue* key, | 7110 HValue* key, |
6801 HValue* val, | 7111 HValue* val, |
6802 SmallMapList* maps) { | 7112 SmallMapList* maps) { |
6803 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | 7113 // For polymorphic loads of similar elements kinds (i.e. all tagged or all |
6804 // double), always use the "worst case" code without a transition. This is | 7114 // double), always use the "worst case" code without a transition. This is |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6839 } | 7149 } |
6840 } | 7150 } |
6841 if (!has_double_maps && !has_smi_or_object_maps) return NULL; | 7151 if (!has_double_maps && !has_smi_or_object_maps) return NULL; |
6842 | 7152 |
6843 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); | 7153 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); |
6844 AddInstruction(check_maps); | 7154 AddInstruction(check_maps); |
6845 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 7155 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
6846 object, key, val, check_maps, | 7156 object, key, val, check_maps, |
6847 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | 7157 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, |
6848 most_general_consolidated_map->elements_kind(), | 7158 most_general_consolidated_map->elements_kind(), |
6849 false); | 7159 false, STANDARD_STORE); |
6850 return instr; | 7160 return instr; |
6851 } | 7161 } |
6852 | 7162 |
6853 | 7163 |
6854 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 7164 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
6855 HValue* object, | 7165 HValue* object, |
6856 HValue* key, | 7166 HValue* key, |
6857 HValue* val, | 7167 HValue* val, |
6858 Expression* prop, | 7168 Expression* prop, |
6859 BailoutId ast_id, | 7169 BailoutId ast_id, |
6860 int position, | 7170 int position, |
6861 bool is_store, | 7171 bool is_store, |
7172 KeyedAccessStoreMode store_mode, | |
6862 bool* has_side_effects) { | 7173 bool* has_side_effects) { |
6863 *has_side_effects = false; | 7174 *has_side_effects = false; |
6864 AddInstruction(new(zone()) HCheckNonSmi(object)); | 7175 AddInstruction(new(zone()) HCheckNonSmi(object)); |
6865 SmallMapList* maps = prop->GetReceiverTypes(); | 7176 SmallMapList* maps = prop->GetReceiverTypes(); |
6866 bool todo_external_array = false; | 7177 bool todo_external_array = false; |
6867 | 7178 |
6868 if (!is_store) { | 7179 if (!is_store) { |
6869 HInstruction* consolidated_load = | 7180 HInstruction* consolidated_load = |
6870 TryBuildConsolidatedElementLoad(object, key, val, maps); | 7181 TryBuildConsolidatedElementLoad(object, key, val, maps); |
6871 if (consolidated_load != NULL) { | 7182 if (consolidated_load != NULL) { |
6872 AddInstruction(consolidated_load); | |
6873 *has_side_effects |= consolidated_load->HasObservableSideEffects(); | 7183 *has_side_effects |= consolidated_load->HasObservableSideEffects(); |
6874 if (position != RelocInfo::kNoPosition) { | 7184 if (position != RelocInfo::kNoPosition) { |
6875 consolidated_load->set_position(position); | 7185 consolidated_load->set_position(position); |
6876 } | 7186 } |
6877 return consolidated_load; | 7187 return consolidated_load; |
6878 } | 7188 } |
6879 } | 7189 } |
6880 | 7190 |
6881 static const int kNumElementTypes = kElementsKindCount; | 7191 static const int kNumElementTypes = kElementsKindCount; |
6882 bool type_todo[kNumElementTypes]; | 7192 bool type_todo[kNumElementTypes]; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6929 } | 7239 } |
6930 | 7240 |
6931 // If only one map is left after transitioning, handle this case | 7241 // If only one map is left after transitioning, handle this case |
6932 // monomorphically. | 7242 // monomorphically. |
6933 if (num_untransitionable_maps == 1) { | 7243 if (num_untransitionable_maps == 1) { |
6934 HInstruction* instr = NULL; | 7244 HInstruction* instr = NULL; |
6935 if (untransitionable_map->has_slow_elements_kind()) { | 7245 if (untransitionable_map->has_slow_elements_kind()) { |
6936 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) | 7246 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) |
6937 : BuildLoadKeyedGeneric(object, key)); | 7247 : BuildLoadKeyedGeneric(object, key)); |
6938 } else { | 7248 } else { |
6939 instr = AddInstruction(BuildMonomorphicElementAccess( | 7249 instr = BuildMonomorphicElementAccess( |
6940 object, key, val, transition, untransitionable_map, is_store)); | 7250 object, key, val, transition, untransitionable_map, is_store, |
7251 store_mode); | |
6941 } | 7252 } |
6942 *has_side_effects |= instr->HasObservableSideEffects(); | 7253 *has_side_effects |= instr->HasObservableSideEffects(); |
6943 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 7254 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
6944 return is_store ? NULL : instr; | 7255 return is_store ? NULL : instr; |
6945 } | 7256 } |
6946 | 7257 |
6947 HInstruction* checkspec = | 7258 HInstruction* checkspec = |
6948 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); | 7259 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); |
6949 HBasicBlock* join = graph()->CreateBasicBlock(); | 7260 HBasicBlock* join = graph()->CreateBasicBlock(); |
6950 | 7261 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7011 typecheck->SetSuccessorAt(1, if_fastobject); | 7322 typecheck->SetSuccessorAt(1, if_fastobject); |
7012 current_block()->Finish(typecheck); | 7323 current_block()->Finish(typecheck); |
7013 | 7324 |
7014 set_current_block(if_jsarray); | 7325 set_current_block(if_jsarray); |
7015 HInstruction* length; | 7326 HInstruction* length; |
7016 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck, | 7327 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck, |
7017 HType::Smi())); | 7328 HType::Smi())); |
7018 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 7329 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
7019 access = AddInstruction(BuildFastElementAccess( | 7330 access = AddInstruction(BuildFastElementAccess( |
7020 elements, checked_key, val, elements_kind_branch, | 7331 elements, checked_key, val, elements_kind_branch, |
7021 elements_kind, is_store)); | 7332 elements_kind, is_store, STANDARD_STORE)); |
7022 if (!is_store) { | 7333 if (!is_store) { |
7023 Push(access); | 7334 Push(access); |
7024 } | 7335 } |
7025 | 7336 |
7026 *has_side_effects |= access->HasObservableSideEffects(); | 7337 *has_side_effects |= access->HasObservableSideEffects(); |
7027 if (position != -1) { | 7338 if (position != -1) { |
7028 access->set_position(position); | 7339 access->set_position(position); |
7029 } | 7340 } |
7030 if_jsarray->Goto(join); | 7341 if_jsarray->Goto(join); |
7031 | 7342 |
7032 set_current_block(if_fastobject); | 7343 set_current_block(if_fastobject); |
7033 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 7344 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
7034 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 7345 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
7035 access = AddInstruction(BuildFastElementAccess( | 7346 access = AddInstruction(BuildFastElementAccess( |
7036 elements, checked_key, val, elements_kind_branch, | 7347 elements, checked_key, val, elements_kind_branch, |
7037 elements_kind, is_store)); | 7348 elements_kind, is_store, STANDARD_STORE)); |
7038 } else if (elements_kind == DICTIONARY_ELEMENTS) { | 7349 } else if (elements_kind == DICTIONARY_ELEMENTS) { |
7039 if (is_store) { | 7350 if (is_store) { |
7040 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 7351 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
7041 } else { | 7352 } else { |
7042 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 7353 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
7043 } | 7354 } |
7044 } else { // External array elements. | 7355 } else { // External array elements. |
7045 access = AddInstruction(BuildExternalArrayElementAccess( | 7356 access = AddInstruction(BuildExternalArrayElementAccess( |
7046 external_elements, checked_key, val, | 7357 external_elements, checked_key, val, |
7047 elements_kind_branch, elements_kind, is_store)); | 7358 elements_kind_branch, elements_kind, is_store)); |
(...skipping 25 matching lines...) Expand all Loading... | |
7073 int position, | 7384 int position, |
7074 bool is_store, | 7385 bool is_store, |
7075 bool* has_side_effects) { | 7386 bool* has_side_effects) { |
7076 ASSERT(!expr->IsPropertyName()); | 7387 ASSERT(!expr->IsPropertyName()); |
7077 HInstruction* instr = NULL; | 7388 HInstruction* instr = NULL; |
7078 if (expr->IsMonomorphic()) { | 7389 if (expr->IsMonomorphic()) { |
7079 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 7390 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
7080 if (map->has_slow_elements_kind()) { | 7391 if (map->has_slow_elements_kind()) { |
7081 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 7392 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
7082 : BuildLoadKeyedGeneric(obj, key); | 7393 : BuildLoadKeyedGeneric(obj, key); |
7394 AddInstruction(instr); | |
7083 } else { | 7395 } else { |
7084 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 7396 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
7085 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); | 7397 instr = BuildMonomorphicElementAccess( |
7398 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | |
7086 } | 7399 } |
7087 } else if (expr->GetReceiverTypes() != NULL && | 7400 } else if (expr->GetReceiverTypes() != NULL && |
7088 !expr->GetReceiverTypes()->is_empty()) { | 7401 !expr->GetReceiverTypes()->is_empty()) { |
7089 return HandlePolymorphicElementAccess( | 7402 return HandlePolymorphicElementAccess( |
7090 obj, key, val, expr, ast_id, position, is_store, has_side_effects); | 7403 obj, key, val, expr, ast_id, position, is_store, |
7404 expr->GetStoreMode(), has_side_effects); | |
7091 } else { | 7405 } else { |
7092 if (is_store) { | 7406 if (is_store) { |
7093 instr = BuildStoreKeyedGeneric(obj, key, val); | 7407 instr = BuildStoreKeyedGeneric(obj, key, val); |
7094 } else { | 7408 } else { |
7095 instr = BuildLoadKeyedGeneric(obj, key); | 7409 instr = BuildLoadKeyedGeneric(obj, key); |
7096 } | 7410 } |
7411 AddInstruction(instr); | |
7097 } | 7412 } |
7098 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 7413 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
7099 AddInstruction(instr); | |
7100 *has_side_effects = instr->HasObservableSideEffects(); | 7414 *has_side_effects = instr->HasObservableSideEffects(); |
7101 return instr; | 7415 return instr; |
7102 } | 7416 } |
7103 | 7417 |
7104 | 7418 |
7105 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( | 7419 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( |
7106 HValue* object, | 7420 HValue* object, |
7107 HValue* key, | 7421 HValue* key, |
7108 HValue* value) { | 7422 HValue* value) { |
7109 HValue* context = environment()->LookupContext(); | 7423 HValue* context = environment()->LookupContext(); |
(...skipping 3753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10863 } | 11177 } |
10864 } | 11178 } |
10865 | 11179 |
10866 #ifdef DEBUG | 11180 #ifdef DEBUG |
10867 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11181 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
10868 if (allocator_ != NULL) allocator_->Verify(); | 11182 if (allocator_ != NULL) allocator_->Verify(); |
10869 #endif | 11183 #endif |
10870 } | 11184 } |
10871 | 11185 |
10872 } } // namespace v8::internal | 11186 } } // namespace v8::internal |
OLD | NEW |