Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/hydrogen.cc

Issue 12221064: Implement many KeyedStoreStubs using Crankshaft (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add runtime flag and address review feedback Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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::BeginIfMapEquals(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
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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 } 999 }
956 } 1000 }
957 1001
958 1002
959 HInstruction* HGraphBuilder::BuildFastElementAccess( 1003 HInstruction* HGraphBuilder::BuildFastElementAccess(
960 HValue* elements, 1004 HValue* elements,
961 HValue* checked_key, 1005 HValue* checked_key,
962 HValue* val, 1006 HValue* val,
963 HValue* load_dependency, 1007 HValue* load_dependency,
964 ElementsKind elements_kind, 1008 ElementsKind elements_kind,
965 bool is_store) { 1009 bool is_store,
1010 KeyedAccessStoreMode store_mode) {
966 Zone* zone = this->zone(); 1011 Zone* zone = this->zone();
967 if (is_store) { 1012 if (is_store) {
968 ASSERT(val != NULL); 1013 ASSERT(val != NULL);
969 switch (elements_kind) { 1014 switch (elements_kind) {
970 case FAST_SMI_ELEMENTS: 1015 case FAST_SMI_ELEMENTS:
971 case FAST_HOLEY_SMI_ELEMENTS: 1016 case FAST_HOLEY_SMI_ELEMENTS:
972 // Smi-only arrays need a smi check. 1017 // Smi-only arrays need a smi check.
973 AddInstruction(new(zone) HCheckSmi(val)); 1018 AddInstruction(new(zone) HCheckSmi(val));
974 // Fall through. 1019 // Fall through.
975 case FAST_ELEMENTS: 1020 case FAST_ELEMENTS:
976 case FAST_HOLEY_ELEMENTS: 1021 case FAST_HOLEY_ELEMENTS:
977 case FAST_DOUBLE_ELEMENTS: 1022 case FAST_DOUBLE_ELEMENTS:
978 case FAST_HOLEY_DOUBLE_ELEMENTS: 1023 case FAST_HOLEY_DOUBLE_ELEMENTS:
979 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); 1024 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind);
980 default: 1025 default:
981 UNREACHABLE(); 1026 UNREACHABLE();
982 return NULL; 1027 return NULL;
983 } 1028 }
984 } 1029 }
985 // It's an element load (!is_store). 1030 // It's an element load (!is_store).
986 return new(zone) HLoadKeyed(elements, 1031 return new(zone) HLoadKeyed(elements,
987 checked_key, 1032 checked_key,
988 load_dependency, 1033 load_dependency,
989 elements_kind); 1034 elements_kind);
990 } 1035 }
991 1036
992 1037
1038 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
1039 HValue* elements,
1040 ElementsKind kind,
1041 HValue* length,
1042 HValue* key,
1043 bool is_js_array) {
1044 BailoutId ast_id = environment()->ast_id();
1045 Zone* zone = this->zone();
1046 IfBuilder length_checker(this, ast_id);
1047
1048 length_checker.BeginIf(length, key, Token::EQ);
1049
1050 HValue* current_capacity =
1051 AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1052
1053 IfBuilder capacity_checker(this, ast_id);
1054
1055 capacity_checker.BeginIf(length, current_capacity, Token::EQ);
1056
1057 HValue* context = environment()->LookupContext();
1058
1059 HValue* new_capacity =
1060 BuildNewElementsCapacity(context, current_capacity);
1061
1062 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1063 kind, length,
1064 new_capacity, ast_id);
1065
1066 environment()->Push(new_elements);
1067 capacity_checker.BeginElse();
1068
1069 environment()->Push(elements);
1070 capacity_checker.End();
1071
1072 if (is_js_array) {
1073 HValue* new_length = AddInstruction(
1074 HAdd::New(zone, context, length, graph_->GetConstant1()));
1075 new_length->ChangeRepresentation(Representation::Integer32());
1076 new_length->ClearFlag(HValue::kCanOverflow);
1077 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1078
1079 Factory* factory = isolate()->factory();
1080 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField(
1081 object,
1082 factory->length_field_string(),
1083 new_length, true,
1084 JSArray::kLengthOffset));
1085 length_store->SetGVNFlag(kChangesArrayLengths);
1086 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1087 }
1088
1089 length_checker.BeginElse();
1090
1091 AddBoundsCheck(key, length, ALLOW_SMI_KEY);
1092 environment()->Push(elements);
1093
1094 length_checker.End();
1095
1096 return environment()->Pop();
1097 }
1098
1099
1100 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
1101 HValue* elements,
1102 ElementsKind kind,
1103 HValue* length) {
1104 BailoutId ast_id = environment()->ast_id();
1105 Zone* zone = this->zone();
1106 Heap* heap = isolate()->heap();
1107
1108 IfBuilder cow_checker(this, ast_id);
1109
1110 cow_checker.BeginIfMapEquals(elements,
1111 Handle<Map>(heap->fixed_cow_array_map()));
1112
1113 HValue* capacity =
1114 AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1115
1116 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1117 kind, length,
1118 capacity, ast_id);
1119
1120 environment()->Push(new_elements);
1121
1122 cow_checker.BeginElse();
1123
1124 environment()->Push(elements);
1125
1126 cow_checker.End();
1127
1128 return environment()->Pop();
1129 }
1130
1131
993 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 1132 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
994 HValue* object, 1133 HValue* object,
995 HValue* key, 1134 HValue* key,
996 HValue* val, 1135 HValue* val,
997 HCheckMaps* mapcheck, 1136 HCheckMaps* mapcheck,
998 bool is_js_array, 1137 bool is_js_array,
999 ElementsKind elements_kind, 1138 ElementsKind elements_kind,
1000 bool is_store, 1139 bool is_store,
1140 KeyedAccessStoreMode store_mode,
1001 Representation checked_index_representation) { 1141 Representation checked_index_representation) {
1142 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
1002 Zone* zone = this->zone(); 1143 Zone* zone = this->zone();
1003 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency 1144 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
1004 // on a HElementsTransition instruction. The flag can also be removed if the 1145 // on a HElementsTransition instruction. The flag can also be removed if the
1005 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further 1146 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
1006 // ElementsKind transitions. Finally, the dependency can be removed for stores 1147 // ElementsKind transitions. Finally, the dependency can be removed for stores
1007 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the 1148 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
1008 // generated store code. 1149 // generated store code.
1009 if ((elements_kind == FAST_HOLEY_ELEMENTS) || 1150 if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
1010 (elements_kind == FAST_ELEMENTS && is_store)) { 1151 (elements_kind == FAST_ELEMENTS && is_store)) {
1011 if (mapcheck != NULL) { 1152 if (mapcheck != NULL) {
1012 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 1153 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
1013 } 1154 }
1014 } 1155 }
1015 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); 1156 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
1016 bool fast_elements = IsFastObjectElementsKind(elements_kind); 1157 bool fast_elements = IsFastObjectElementsKind(elements_kind);
1017 HInstruction* elements = 1158 HValue* elements =
1018 AddInstruction(new(zone) HLoadElements(object, mapcheck)); 1159 AddInstruction(new(zone) HLoadElements(object, mapcheck));
1019 if (is_store && (fast_elements || fast_smi_only_elements)) { 1160 if (is_store && (fast_elements || fast_smi_only_elements) &&
1161 store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
1020 HCheckMaps* check_cow_map = new(zone) HCheckMaps( 1162 HCheckMaps* check_cow_map = new(zone) HCheckMaps(
1021 elements, isolate()->factory()->fixed_array_map(), zone); 1163 elements, isolate()->factory()->fixed_array_map(), zone);
1022 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 1164 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1023 AddInstruction(check_cow_map); 1165 AddInstruction(check_cow_map);
1024 } 1166 }
1025 HInstruction* length = NULL; 1167 HInstruction* length = NULL;
1026 HInstruction* checked_key = NULL;
1027 if (IsExternalArrayElementsKind(elements_kind)) {
1028 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1029 checked_key = AddBoundsCheck(
1030 key, length, ALLOW_SMI_KEY, checked_index_representation);
1031 HLoadExternalArrayPointer* external_elements =
1032 new(zone) HLoadExternalArrayPointer(elements);
1033 AddInstruction(external_elements);
1034 return BuildExternalArrayElementAccess(
1035 external_elements, checked_key, val, mapcheck,
1036 elements_kind, is_store);
1037 }
1038 ASSERT(fast_smi_only_elements ||
1039 fast_elements ||
1040 IsFastDoubleElementsKind(elements_kind));
1041 if (is_js_array) { 1168 if (is_js_array) {
1042 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, 1169 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck,
1043 HType::Smi())); 1170 HType::Smi()));
1044 } else { 1171 } else {
1045 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); 1172 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1046 } 1173 }
1047 checked_key = AddBoundsCheck( 1174 HValue* checked_key = NULL;
1048 key, length, ALLOW_SMI_KEY, checked_index_representation); 1175 if (IsExternalArrayElementsKind(elements_kind)) {
1049 return BuildFastElementAccess(elements, checked_key, val, mapcheck, 1176 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
1050 elements_kind, is_store); 1177 HLoadExternalArrayPointer* external_elements =
1178 new(zone) HLoadExternalArrayPointer(elements);
1179 AddInstruction(external_elements);
1180 BailoutId previous_id = environment()->ast_id();
1181 ASSERT(!previous_id.IsNone());
1182 IfBuilder length_checker(this, previous_id);
1183 length_checker.BeginIf(key, length, Token::LT);
1184 CheckBuilder negative_checker(this, previous_id);
1185 HValue* bounds_check = negative_checker.CheckIntegerCompare(
1186 key, graph()->GetConstant0(), Token::GTE);
1187 negative_checker.End();
1188 HInstruction* result = BuildExternalArrayElementAccess(
1189 external_elements, key, val, bounds_check,
1190 elements_kind, is_store);
1191 AddInstruction(result);
1192 length_checker.End();
1193 return result;
1194 } else {
1195 ASSERT(store_mode == STANDARD_STORE);
1196 checked_key = AddBoundsCheck(
1197 key, length, ALLOW_SMI_KEY, checked_index_representation);
1198 HLoadExternalArrayPointer* external_elements =
1199 new(zone) HLoadExternalArrayPointer(elements);
1200 AddInstruction(external_elements);
1201 return AddInstruction(BuildExternalArrayElementAccess(
1202 external_elements, checked_key, val, mapcheck,
1203 elements_kind, is_store));
1204 }
1205 }
1206 ASSERT(fast_smi_only_elements ||
1207 fast_elements ||
1208 IsFastDoubleElementsKind(elements_kind));
1209
1210 if (is_store && IsFastSmiElementsKind(elements_kind) &&
1211 !val->type().IsSmi()) {
1212 AddInstruction(new(zone) HCheckSmi(val));
1213 }
1214
1215 if (IsGrowStoreMode(store_mode)) {
1216 elements = BuildCheckForCapacityGrow(object, elements, elements_kind,
1217 length, key, is_js_array);
1218 checked_key = key;
1219 } else {
1220 checked_key = AddBoundsCheck(
1221 key, length, ALLOW_SMI_KEY, checked_index_representation);
1222
1223 if (is_store && (fast_elements || fast_smi_only_elements)) {
1224 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
1225 elements = BuildCopyElementsOnWrite(object, elements, elements_kind,
1226 length);
1227 } else {
1228 HCheckMaps* check_cow_map = new(zone) HCheckMaps(
1229 elements, isolate()->factory()->fixed_array_map(), zone);
1230 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1231 AddInstruction(check_cow_map);
1232 }
1233 }
1234 }
1235 return AddInstruction(
1236 BuildFastElementAccess(elements, checked_key, val, mapcheck,
1237 elements_kind, is_store, store_mode));
1051 } 1238 }
1052 1239
1053 1240
1054 HValue* HGraphBuilder::BuildAllocateElements(HContext* context, 1241 HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
1055 ElementsKind kind, 1242 ElementsKind kind,
1056 HValue* capacity) { 1243 HValue* capacity,
1244 BailoutId ast_id) {
1057 Zone* zone = this->zone(); 1245 Zone* zone = this->zone();
1058 1246
1059 int elements_size = IsFastDoubleElementsKind(kind) 1247 int elements_size = IsFastDoubleElementsKind(kind)
1060 ? kDoubleSize : kPointerSize; 1248 ? kDoubleSize : kPointerSize;
1061 HConstant* elements_size_value = 1249 HConstant* elements_size_value =
1062 new(zone) HConstant(elements_size, Representation::Integer32()); 1250 new(zone) HConstant(elements_size, Representation::Integer32());
1063 AddInstruction(elements_size_value); 1251 AddInstruction(elements_size_value);
1064 HValue* mul = AddInstruction( 1252 HValue* mul = AddInstruction(
1065 HMul::New(zone, context, capacity, elements_size_value)); 1253 HMul::New(zone, context, capacity, elements_size_value));
1066 mul->ChangeRepresentation(Representation::Integer32()); 1254 mul->ChangeRepresentation(Representation::Integer32());
(...skipping 14 matching lines...) Expand all
1081 } 1269 }
1082 1270
1083 HValue* elements = 1271 HValue* elements =
1084 AddInstruction(new(zone) HAllocate(context, total_size, 1272 AddInstruction(new(zone) HAllocate(context, total_size,
1085 HType::JSArray(), flags)); 1273 HType::JSArray(), flags));
1086 1274
1087 Factory* factory = isolate()->factory(); 1275 Factory* factory = isolate()->factory();
1088 Handle<Map> map = IsFastDoubleElementsKind(kind) 1276 Handle<Map> map = IsFastDoubleElementsKind(kind)
1089 ? factory->fixed_double_array_map() 1277 ? factory->fixed_double_array_map()
1090 : factory->fixed_array_map(); 1278 : factory->fixed_array_map();
1091 BuildStoreMap(elements, map, BailoutId::StubEntry()); 1279 BuildStoreMap(elements, map, ast_id);
1092 1280
1093 Handle<String> fixed_array_length_field_name = factory->length_field_string(); 1281 Handle<String> fixed_array_length_field_name = factory->length_field_string();
1094 HInstruction* store_length = 1282 HInstruction* store_length =
1095 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, 1283 new(zone) HStoreNamedField(elements, fixed_array_length_field_name,
1096 capacity, true, FixedArray::kLengthOffset); 1284 capacity, true, FixedArray::kLengthOffset);
1097 AddInstruction(store_length); 1285 AddInstruction(store_length);
1098 AddSimulate(BailoutId::StubEntry(), FIXED_SIMULATE); 1286 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1099 1287
1100 return elements; 1288 return elements;
1101 } 1289 }
1102 1290
1103 1291
1104 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, 1292 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
1105 HValue* map, 1293 HValue* map,
1106 BailoutId id) { 1294 BailoutId id) {
1107 Zone* zone = this->zone(); 1295 Zone* zone = this->zone();
1108 Factory* factory = isolate()->factory(); 1296 Factory* factory = isolate()->factory();
1109 Handle<String> map_field_name = factory->map_field_string(); 1297 Handle<String> map_field_name = factory->map_field_string();
1110 HInstruction* store_map = 1298 HInstruction* store_map =
1111 new(zone) HStoreNamedField(object, map_field_name, map, 1299 new(zone) HStoreNamedField(object, map_field_name, map,
1112 true, JSObject::kMapOffset); 1300 true, JSObject::kMapOffset);
1113 store_map->SetGVNFlag(kChangesMaps); 1301 store_map->SetGVNFlag(kChangesMaps);
1114 AddInstruction(store_map); 1302 AddInstruction(store_map);
1115 AddSimulate(id, FIXED_SIMULATE); 1303 AddSimulate(id, REMOVABLE_SIMULATE);
1116 return store_map; 1304 return store_map;
1117 } 1305 }
1118 1306
1119 1307
1120 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, 1308 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
1121 Handle<Map> map, 1309 Handle<Map> map,
1122 BailoutId id) { 1310 BailoutId id) {
1123 Zone* zone = this->zone(); 1311 Zone* zone = this->zone();
1124 HValue* map_constant = 1312 HValue* map_constant =
1125 AddInstruction(new(zone) HConstant(map, Representation::Tagged())); 1313 AddInstruction(new(zone) HConstant(map, Representation::Tagged()));
1126 return BuildStoreMap(object, map_constant, id); 1314 return BuildStoreMap(object, map_constant, id);
1127 } 1315 }
1128 1316
1129 1317
1130 void HGraphBuilder::BuildCopyElements(HContext* context, 1318 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context,
1319 HValue* old_capacity) {
1320 Zone* zone = this->zone();
1321 HValue* half_old_capacity =
1322 AddInstruction(HShr::New(zone, context, old_capacity,
1323 graph_->GetConstant1()));
1324 half_old_capacity->ChangeRepresentation(Representation::Integer32());
1325 half_old_capacity->ClearFlag(HValue::kCanOverflow);
1326
1327 HValue* new_capacity = AddInstruction(
1328 HAdd::New(zone, context, half_old_capacity, old_capacity));
1329 new_capacity->ChangeRepresentation(Representation::Integer32());
1330 new_capacity->ClearFlag(HValue::kCanOverflow);
1331
1332 HValue* min_growth =
1333 AddInstruction(new(zone) HConstant(16, Representation::Integer32()));
1334
1335 new_capacity = AddInstruction(
1336 HAdd::New(zone, context, new_capacity, min_growth));
1337 new_capacity->ChangeRepresentation(Representation::Integer32());
1338 new_capacity->ClearFlag(HValue::kCanOverflow);
1339
1340 return new_capacity;
1341 }
1342
1343
1344 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) {
1345 Zone* zone = this->zone();
1346 Heap* heap = isolate()->heap();
1347 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize
1348 : kPointerSize;
1349 int max_size = heap->MaxNewSpaceAllocationSize() / element_size;
1350 max_size -= JSArray::kSize / element_size;
1351 HConstant* max_size_constant =
1352 new(zone) HConstant(max_size, Representation::Integer32());
1353 AddInstruction(max_size_constant);
1354 // Since we're forcing Integer32 representation for this HBoundsCheck,
1355 // there's no need to Smi-check the index.
1356 AddInstruction(new(zone)
1357 HBoundsCheck(length, max_size_constant,
1358 DONT_ALLOW_SMI_KEY, Representation::Integer32()));
1359 }
1360
1361
1362 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
1363 HValue* elements,
1364 ElementsKind kind,
1365 HValue* length,
1366 HValue* new_capacity,
1367 BailoutId ast_id) {
1368 Zone* zone = this->zone();
1369 HValue* context = environment()->LookupContext();
1370
1371 BuildNewSpaceArrayCheck(new_capacity, kind);
1372
1373 HValue* new_elements =
1374 BuildAllocateElements(context, kind, new_capacity, ast_id);
1375
1376 BuildCopyElements(context, elements, kind,
1377 new_elements, kind,
1378 length, new_capacity, ast_id);
1379
1380 Factory* factory = isolate()->factory();
1381 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField(
1382 object,
1383 factory->elements_field_string(),
1384 new_elements, true,
1385 JSArray::kElementsOffset));
1386 elements_store->SetGVNFlag(kChangesElementsPointer);
1387
1388 return new_elements;
1389 }
1390
1391
1392 void HGraphBuilder::BuildFillElementsWithHole(HValue* context,
1393 HValue* elements,
1394 ElementsKind elements_kind,
1395 HValue* from,
1396 HValue* to,
1397 BailoutId ast_id) {
1398 // Fast elements kinds need to be initialized in case statements below cause
1399 // a garbage collection.
1400 Factory* factory = isolate()->factory();
1401
1402 double nan_double = FixedDoubleArray::hole_nan_as_double();
1403 Zone* zone = this->zone();
1404 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
1405 ? AddInstruction(new(zone) HConstant(factory->the_hole_value(),
1406 Representation::Tagged()))
1407 : AddInstruction(new(zone) HConstant(nan_double,
1408 Representation::Double()));
1409
1410 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id);
1411
1412 HValue* key = builder.BeginBody(from, to, Token::LT);
1413
1414 AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind));
1415 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1416
1417 builder.EndBody();
1418 }
1419
1420
1421 void HGraphBuilder::BuildCopyElements(HValue* context,
1131 HValue* from_elements, 1422 HValue* from_elements,
1132 ElementsKind from_elements_kind, 1423 ElementsKind from_elements_kind,
1133 HValue* to_elements, 1424 HValue* to_elements,
1134 ElementsKind to_elements_kind, 1425 ElementsKind to_elements_kind,
1135 HValue* length) { 1426 HValue* length,
1136 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, 1427 HValue* capacity,
1137 BailoutId::StubEntry()); 1428 BailoutId ast_id) {
1429 bool pre_fill_with_holes =
1430 IsFastDoubleElementsKind(from_elements_kind) &&
1431 IsFastObjectElementsKind(to_elements_kind);
1138 1432
1139 HValue* key = builder.BeginBody(graph()->GetConstant0(), 1433 if (pre_fill_with_holes) {
1140 length, Token::LT); 1434 // If the copy might trigger a GC, make sure that the FixedArray is
1435 // pre-initialized with holes to make sure that it's always in a consistent
1436 // state.
1437 BuildFillElementsWithHole(context, to_elements, to_elements_kind,
1438 graph()->GetConstant0(), capacity, ast_id);
1439 }
1440
1441 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id);
1442
1443 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT);
1141 1444
1142 HValue* element = 1445 HValue* element =
1143 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, 1446 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL,
1144 from_elements_kind, 1447 from_elements_kind,
1145 ALLOW_RETURN_HOLE)); 1448 ALLOW_RETURN_HOLE));
1146 1449
1147 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element, 1450 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element,
1148 to_elements_kind)); 1451 to_elements_kind));
1149 AddSimulate(BailoutId::StubEntry(), REMOVABLE_SIMULATE); 1452 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1150 1453
1151 builder.EndBody(); 1454 builder.EndBody();
1455
1456 if (!pre_fill_with_holes && length != capacity) {
1457 // Fill unused capacity with the hole.
1458 BuildFillElementsWithHole(context, to_elements, to_elements_kind,
1459 key, capacity, ast_id);
1460 }
1152 } 1461 }
1153 1462
1154 1463
1155 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, 1464 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info,
1156 TypeFeedbackOracle* oracle) 1465 TypeFeedbackOracle* oracle)
1157 : HGraphBuilder(info), 1466 : HGraphBuilder(info),
1158 function_state_(NULL), 1467 function_state_(NULL),
1159 initial_function_state_(this, info, oracle, NORMAL_RETURN), 1468 initial_function_state_(this, info, oracle, NORMAL_RETURN),
1160 ast_context_(NULL), 1469 ast_context_(NULL),
1161 break_scope_(NULL), 1470 break_scope_(NULL),
(...skipping 5620 matching lines...) Expand 10 before | Expand all | Expand 10 after
6782 return new(zone()) HLoadKeyedGeneric(context, object, key); 7091 return new(zone()) HLoadKeyedGeneric(context, object, key);
6783 } 7092 }
6784 7093
6785 7094
6786 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( 7095 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
6787 HValue* object, 7096 HValue* object,
6788 HValue* key, 7097 HValue* key,
6789 HValue* val, 7098 HValue* val,
6790 HValue* dependency, 7099 HValue* dependency,
6791 Handle<Map> map, 7100 Handle<Map> map,
6792 bool is_store) { 7101 bool is_store,
7102 KeyedAccessStoreMode store_mode) {
6793 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, 7103 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map,
6794 zone(), dependency); 7104 zone(), dependency);
6795 AddInstruction(mapcheck); 7105 AddInstruction(mapcheck);
6796 if (dependency) { 7106 if (dependency) {
6797 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 7107 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
6798 } 7108 }
6799 return BuildUncheckedMonomorphicElementAccess( 7109 return BuildUncheckedMonomorphicElementAccess(
6800 object, key, val, 7110 object, key, val,
6801 mapcheck, map->instance_type() == JS_ARRAY_TYPE, 7111 mapcheck, map->instance_type() == JS_ARRAY_TYPE,
6802 map->elements_kind(), is_store); 7112 map->elements_kind(), is_store, store_mode);
6803 } 7113 }
6804 7114
6805 7115
6806 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( 7116 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
6807 HValue* object, 7117 HValue* object,
6808 HValue* key, 7118 HValue* key,
6809 HValue* val, 7119 HValue* val,
6810 SmallMapList* maps) { 7120 SmallMapList* maps) {
6811 // For polymorphic loads of similar elements kinds (i.e. all tagged or all 7121 // For polymorphic loads of similar elements kinds (i.e. all tagged or all
6812 // double), always use the "worst case" code without a transition. This is 7122 // double), always use the "worst case" code without a transition. This is
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
6847 } 7157 }
6848 } 7158 }
6849 if (!has_double_maps && !has_smi_or_object_maps) return NULL; 7159 if (!has_double_maps && !has_smi_or_object_maps) return NULL;
6850 7160
6851 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); 7161 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone());
6852 AddInstruction(check_maps); 7162 AddInstruction(check_maps);
6853 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( 7163 HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
6854 object, key, val, check_maps, 7164 object, key, val, check_maps,
6855 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, 7165 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
6856 most_general_consolidated_map->elements_kind(), 7166 most_general_consolidated_map->elements_kind(),
6857 false); 7167 false, STANDARD_STORE);
6858 return instr; 7168 return instr;
6859 } 7169 }
6860 7170
6861 7171
6862 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( 7172 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
6863 HValue* object, 7173 HValue* object,
6864 HValue* key, 7174 HValue* key,
6865 HValue* val, 7175 HValue* val,
6866 Expression* prop, 7176 Expression* prop,
6867 BailoutId ast_id, 7177 BailoutId ast_id,
6868 int position, 7178 int position,
6869 bool is_store, 7179 bool is_store,
7180 KeyedAccessStoreMode store_mode,
6870 bool* has_side_effects) { 7181 bool* has_side_effects) {
6871 *has_side_effects = false; 7182 *has_side_effects = false;
6872 AddInstruction(new(zone()) HCheckNonSmi(object)); 7183 AddInstruction(new(zone()) HCheckNonSmi(object));
6873 SmallMapList* maps = prop->GetReceiverTypes(); 7184 SmallMapList* maps = prop->GetReceiverTypes();
6874 bool todo_external_array = false; 7185 bool todo_external_array = false;
6875 7186
6876 if (!is_store) { 7187 if (!is_store) {
6877 HInstruction* consolidated_load = 7188 HInstruction* consolidated_load =
6878 TryBuildConsolidatedElementLoad(object, key, val, maps); 7189 TryBuildConsolidatedElementLoad(object, key, val, maps);
6879 if (consolidated_load != NULL) { 7190 if (consolidated_load != NULL) {
6880 AddInstruction(consolidated_load);
6881 *has_side_effects |= consolidated_load->HasObservableSideEffects(); 7191 *has_side_effects |= consolidated_load->HasObservableSideEffects();
6882 if (position != RelocInfo::kNoPosition) { 7192 if (position != RelocInfo::kNoPosition) {
6883 consolidated_load->set_position(position); 7193 consolidated_load->set_position(position);
6884 } 7194 }
6885 return consolidated_load; 7195 return consolidated_load;
6886 } 7196 }
6887 } 7197 }
6888 7198
6889 static const int kNumElementTypes = kElementsKindCount; 7199 static const int kNumElementTypes = kElementsKindCount;
6890 bool type_todo[kNumElementTypes]; 7200 bool type_todo[kNumElementTypes];
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
6937 } 7247 }
6938 7248
6939 // If only one map is left after transitioning, handle this case 7249 // If only one map is left after transitioning, handle this case
6940 // monomorphically. 7250 // monomorphically.
6941 if (num_untransitionable_maps == 1) { 7251 if (num_untransitionable_maps == 1) {
6942 HInstruction* instr = NULL; 7252 HInstruction* instr = NULL;
6943 if (untransitionable_map->has_slow_elements_kind()) { 7253 if (untransitionable_map->has_slow_elements_kind()) {
6944 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 7254 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
6945 : BuildLoadKeyedGeneric(object, key)); 7255 : BuildLoadKeyedGeneric(object, key));
6946 } else { 7256 } else {
6947 instr = AddInstruction(BuildMonomorphicElementAccess( 7257 instr = BuildMonomorphicElementAccess(
6948 object, key, val, transition, untransitionable_map, is_store)); 7258 object, key, val, transition, untransitionable_map, is_store,
7259 store_mode);
6949 } 7260 }
6950 *has_side_effects |= instr->HasObservableSideEffects(); 7261 *has_side_effects |= instr->HasObservableSideEffects();
6951 if (position != RelocInfo::kNoPosition) instr->set_position(position); 7262 if (position != RelocInfo::kNoPosition) instr->set_position(position);
6952 return is_store ? NULL : instr; 7263 return is_store ? NULL : instr;
6953 } 7264 }
6954 7265
6955 HInstruction* checkspec = 7266 HInstruction* checkspec =
6956 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); 7267 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone()));
6957 HBasicBlock* join = graph()->CreateBasicBlock(); 7268 HBasicBlock* join = graph()->CreateBasicBlock();
6958 7269
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
7019 typecheck->SetSuccessorAt(1, if_fastobject); 7330 typecheck->SetSuccessorAt(1, if_fastobject);
7020 current_block()->Finish(typecheck); 7331 current_block()->Finish(typecheck);
7021 7332
7022 set_current_block(if_jsarray); 7333 set_current_block(if_jsarray);
7023 HInstruction* length; 7334 HInstruction* length;
7024 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck, 7335 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck,
7025 HType::Smi())); 7336 HType::Smi()));
7026 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); 7337 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
7027 access = AddInstruction(BuildFastElementAccess( 7338 access = AddInstruction(BuildFastElementAccess(
7028 elements, checked_key, val, elements_kind_branch, 7339 elements, checked_key, val, elements_kind_branch,
7029 elements_kind, is_store)); 7340 elements_kind, is_store, STANDARD_STORE));
7030 if (!is_store) { 7341 if (!is_store) {
7031 Push(access); 7342 Push(access);
7032 } 7343 }
7033 7344
7034 *has_side_effects |= access->HasObservableSideEffects(); 7345 *has_side_effects |= access->HasObservableSideEffects();
7035 if (position != -1) { 7346 if (position != -1) {
7036 access->set_position(position); 7347 access->set_position(position);
7037 } 7348 }
7038 if_jsarray->Goto(join); 7349 if_jsarray->Goto(join);
7039 7350
7040 set_current_block(if_fastobject); 7351 set_current_block(if_fastobject);
7041 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 7352 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
7042 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); 7353 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
7043 access = AddInstruction(BuildFastElementAccess( 7354 access = AddInstruction(BuildFastElementAccess(
7044 elements, checked_key, val, elements_kind_branch, 7355 elements, checked_key, val, elements_kind_branch,
7045 elements_kind, is_store)); 7356 elements_kind, is_store, STANDARD_STORE));
7046 } else if (elements_kind == DICTIONARY_ELEMENTS) { 7357 } else if (elements_kind == DICTIONARY_ELEMENTS) {
7047 if (is_store) { 7358 if (is_store) {
7048 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); 7359 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
7049 } else { 7360 } else {
7050 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); 7361 access = AddInstruction(BuildLoadKeyedGeneric(object, key));
7051 } 7362 }
7052 } else { // External array elements. 7363 } else { // External array elements.
7053 access = AddInstruction(BuildExternalArrayElementAccess( 7364 access = AddInstruction(BuildExternalArrayElementAccess(
7054 external_elements, checked_key, val, 7365 external_elements, checked_key, val,
7055 elements_kind_branch, elements_kind, is_store)); 7366 elements_kind_branch, elements_kind, is_store));
(...skipping 25 matching lines...) Expand all
7081 int position, 7392 int position,
7082 bool is_store, 7393 bool is_store,
7083 bool* has_side_effects) { 7394 bool* has_side_effects) {
7084 ASSERT(!expr->IsPropertyName()); 7395 ASSERT(!expr->IsPropertyName());
7085 HInstruction* instr = NULL; 7396 HInstruction* instr = NULL;
7086 if (expr->IsMonomorphic()) { 7397 if (expr->IsMonomorphic()) {
7087 Handle<Map> map = expr->GetMonomorphicReceiverType(); 7398 Handle<Map> map = expr->GetMonomorphicReceiverType();
7088 if (map->has_slow_elements_kind()) { 7399 if (map->has_slow_elements_kind()) {
7089 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 7400 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
7090 : BuildLoadKeyedGeneric(obj, key); 7401 : BuildLoadKeyedGeneric(obj, key);
7402 AddInstruction(instr);
7091 } else { 7403 } else {
7092 AddInstruction(new(zone()) HCheckNonSmi(obj)); 7404 AddInstruction(new(zone()) HCheckNonSmi(obj));
7093 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); 7405 instr = BuildMonomorphicElementAccess(
7406 obj, key, val, NULL, map, is_store, expr->GetStoreMode());
7094 } 7407 }
7095 } else if (expr->GetReceiverTypes() != NULL && 7408 } else if (expr->GetReceiverTypes() != NULL &&
7096 !expr->GetReceiverTypes()->is_empty()) { 7409 !expr->GetReceiverTypes()->is_empty()) {
7097 return HandlePolymorphicElementAccess( 7410 return HandlePolymorphicElementAccess(
7098 obj, key, val, expr, ast_id, position, is_store, has_side_effects); 7411 obj, key, val, expr, ast_id, position, is_store,
7412 expr->GetStoreMode(), has_side_effects);
7099 } else { 7413 } else {
7100 if (is_store) { 7414 if (is_store) {
7101 instr = BuildStoreKeyedGeneric(obj, key, val); 7415 instr = BuildStoreKeyedGeneric(obj, key, val);
7102 } else { 7416 } else {
7103 instr = BuildLoadKeyedGeneric(obj, key); 7417 instr = BuildLoadKeyedGeneric(obj, key);
7104 } 7418 }
7419 AddInstruction(instr);
7105 } 7420 }
7106 if (position != RelocInfo::kNoPosition) instr->set_position(position); 7421 if (position != RelocInfo::kNoPosition) instr->set_position(position);
7107 AddInstruction(instr);
7108 *has_side_effects = instr->HasObservableSideEffects(); 7422 *has_side_effects = instr->HasObservableSideEffects();
7109 return instr; 7423 return instr;
7110 } 7424 }
7111 7425
7112 7426
7113 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( 7427 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric(
7114 HValue* object, 7428 HValue* object,
7115 HValue* key, 7429 HValue* key,
7116 HValue* value) { 7430 HValue* value) {
7117 HValue* context = environment()->LookupContext(); 7431 HValue* context = environment()->LookupContext();
(...skipping 3810 matching lines...) Expand 10 before | Expand all | Expand 10 after
10928 } 11242 }
10929 } 11243 }
10930 11244
10931 #ifdef DEBUG 11245 #ifdef DEBUG
10932 if (graph_ != NULL) graph_->Verify(false); // No full verify. 11246 if (graph_ != NULL) graph_->Verify(false); // No full verify.
10933 if (allocator_ != NULL) allocator_->Verify(); 11247 if (allocator_ != NULL) allocator_->Verify();
10934 #endif 11248 #endif
10935 } 11249 }
10936 11250
10937 } } // namespace v8::internal 11251 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698