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

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: Rebase 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 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 HConstant* HGraph::GetConstant0() { 615 HConstant* HGraph::GetConstant0() {
613 return GetConstantInt32(&constant_0_, 0); 616 return GetConstantInt32(&constant_0_, 0);
614 } 617 }
615 618
616 619
617 HConstant* HGraph::GetConstant1() { 620 HConstant* HGraph::GetConstant1() {
618 return GetConstantInt32(&constant_1_, 1); 621 return GetConstantInt32(&constant_1_, 1);
619 } 622 }
620 623
621 624
625 HConstant* HGraph::GetConstant2() {
626 return GetConstantInt32(&constant_2_, 1);
Jakob Kummerow 2013/03/11 16:36:07 1 is the new 2?
danno 2013/03/13 15:36:26 Done.
627 }
628
629
622 HConstant* HGraph::GetConstantMinus1() { 630 HConstant* HGraph::GetConstantMinus1() {
623 return GetConstantInt32(&constant_minus1_, -1); 631 return GetConstantInt32(&constant_minus1_, -1);
624 } 632 }
625 633
626 634
627 HConstant* HGraph::GetConstantTrue() { 635 HConstant* HGraph::GetConstantTrue() {
628 return GetConstant(&constant_true_, isolate()->factory()->true_value()); 636 return GetConstant(&constant_true_, isolate()->factory()->true_value());
629 } 637 }
630 638
631 639
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 : builder_(builder), 701 : builder_(builder),
694 finished_(false), 702 finished_(false),
695 id_(id) { 703 id_(id) {
696 HEnvironment* env = builder->environment(); 704 HEnvironment* env = builder->environment();
697 first_true_block_ = builder->CreateBasicBlock(env->Copy()); 705 first_true_block_ = builder->CreateBasicBlock(env->Copy());
698 last_true_block_ = NULL; 706 last_true_block_ = NULL;
699 first_false_block_ = builder->CreateBasicBlock(env->Copy()); 707 first_false_block_ = builder->CreateBasicBlock(env->Copy());
700 } 708 }
701 709
702 710
703 HInstruction* HGraphBuilder::IfBuilder::BeginTrue( 711 HInstruction* HGraphBuilder::IfBuilder::BeginIf(
704 HValue* left, 712 HValue* left,
705 HValue* right, 713 HValue* right,
706 Token::Value token, 714 Token::Value token,
707 Representation input_representation) { 715 Representation input_representation) {
708 HCompareIDAndBranch* compare = 716 HCompareIDAndBranch* compare =
709 new(zone()) HCompareIDAndBranch(left, right, token); 717 new(zone()) HCompareIDAndBranch(left, right, token);
710 compare->set_observed_input_representation(input_representation, 718 compare->set_observed_input_representation(input_representation,
711 input_representation); 719 input_representation);
712 compare->ChangeRepresentation(input_representation); 720 compare->ChangeRepresentation(input_representation);
713 compare->SetSuccessorAt(0, first_true_block_); 721 compare->SetSuccessorAt(0, first_true_block_);
714 compare->SetSuccessorAt(1, first_false_block_); 722 compare->SetSuccessorAt(1, first_false_block_);
715 builder_->current_block()->Finish(compare); 723 builder_->current_block()->Finish(compare);
716 builder_->set_current_block(first_true_block_); 724 builder_->set_current_block(first_true_block_);
717 return compare; 725 return compare;
718 } 726 }
719 727
720 728
721 void HGraphBuilder::IfBuilder::BeginFalse() { 729 HInstruction* HGraphBuilder::IfBuilder::BeginIfObjectsEqual(
730 HValue* left,
731 HValue* right) {
732 HCompareObjectEqAndBranch* compare =
733 new(zone()) HCompareObjectEqAndBranch(left, right);
734 compare->SetSuccessorAt(0, first_true_block_);
735 compare->SetSuccessorAt(1, first_false_block_);
736 builder_->current_block()->Finish(compare);
737 builder_->set_current_block(first_true_block_);
738 return compare;
739 }
740
741
742 void HGraphBuilder::IfBuilder::BeginElse() {
722 last_true_block_ = builder_->current_block(); 743 last_true_block_ = builder_->current_block();
723 ASSERT(!last_true_block_->IsFinished()); 744 ASSERT(!last_true_block_->IsFinished());
724 builder_->set_current_block(first_false_block_); 745 builder_->set_current_block(first_false_block_);
725 } 746 }
726 747
727 748
728 void HGraphBuilder::IfBuilder::End() { 749 void HGraphBuilder::IfBuilder::End() {
729 ASSERT(!finished_); 750 ASSERT(!finished_);
730 ASSERT(!last_true_block_->IsFinished()); 751 ASSERT(!last_true_block_->IsFinished());
731 HBasicBlock* last_false_block = builder_->current_block(); 752 HBasicBlock* last_false_block = builder_->current_block();
732 ASSERT(!last_false_block->IsFinished()); 753 ASSERT(!last_false_block->IsFinished());
733 HEnvironment* merge_env = 754 HEnvironment* merge_env =
734 last_true_block_->last_environment()->Copy(); 755 last_true_block_->last_environment()->CopyWithoutHistory();
735 merge_block_ = builder_->CreateBasicBlock(merge_env); 756 merge_block_ = builder_->CreateBasicBlock(merge_env);
736 last_true_block_->Goto(merge_block_); 757 last_true_block_->Goto(merge_block_);
737 last_false_block->Goto(merge_block_); 758 last_false_block->Goto(merge_block_);
738 merge_block_->SetJoinId(id_); 759 merge_block_->SetJoinId(id_);
739 builder_->set_current_block(merge_block_); 760 builder_->set_current_block(merge_block_);
740 finished_ = true; 761 finished_ = true;
741 } 762 }
742 763
743 764
744 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, 765 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 ASSERT(current_block() != NULL); 867 ASSERT(current_block() != NULL);
847 current_block()->AddInstruction(instr); 868 current_block()->AddInstruction(instr);
848 return instr; 869 return instr;
849 } 870 }
850 871
851 872
852 void HGraphBuilder::AddSimulate(BailoutId id, 873 void HGraphBuilder::AddSimulate(BailoutId id,
853 RemovableSimulate removable) { 874 RemovableSimulate removable) {
854 ASSERT(current_block() != NULL); 875 ASSERT(current_block() != NULL);
855 current_block()->AddSimulate(id, removable); 876 current_block()->AddSimulate(id, removable);
877 environment()->set_ast_id(id);
856 } 878 }
857 879
858 880
859 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, 881 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index,
860 HValue* length, 882 HValue* length,
861 BoundsCheckKeyMode key_mode, 883 BoundsCheckKeyMode key_mode,
862 Representation r) { 884 Representation r) {
863 if (!index->type().IsSmi()) { 885 if (!index->type().IsSmi()) {
864 index = new(graph()->zone()) HCheckSmiOrInt32(index); 886 index = new(graph()->zone()) HCheckSmiOrInt32(index);
865 AddInstruction(HCheckSmiOrInt32::cast(index)); 887 AddInstruction(HCheckSmiOrInt32::cast(index));
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 } 965 }
944 } 966 }
945 967
946 968
947 HInstruction* HGraphBuilder::BuildFastElementAccess( 969 HInstruction* HGraphBuilder::BuildFastElementAccess(
948 HValue* elements, 970 HValue* elements,
949 HValue* checked_key, 971 HValue* checked_key,
950 HValue* val, 972 HValue* val,
951 HValue* load_dependency, 973 HValue* load_dependency,
952 ElementsKind elements_kind, 974 ElementsKind elements_kind,
953 bool is_store) { 975 bool is_store,
976 KeyedAccessStoreMode store_mode) {
954 Zone* zone = this->zone(); 977 Zone* zone = this->zone();
955 if (is_store) { 978 if (is_store) {
956 ASSERT(val != NULL); 979 ASSERT(val != NULL);
957 switch (elements_kind) { 980 switch (elements_kind) {
958 case FAST_SMI_ELEMENTS: 981 case FAST_SMI_ELEMENTS:
959 case FAST_HOLEY_SMI_ELEMENTS: 982 case FAST_HOLEY_SMI_ELEMENTS:
960 // Smi-only arrays need a smi check. 983 // Smi-only arrays need a smi check.
961 AddInstruction(new(zone) HCheckSmi(val)); 984 AddInstruction(new(zone) HCheckSmi(val));
962 // Fall through. 985 // Fall through.
963 case FAST_ELEMENTS: 986 case FAST_ELEMENTS:
964 case FAST_HOLEY_ELEMENTS: 987 case FAST_HOLEY_ELEMENTS:
965 case FAST_DOUBLE_ELEMENTS: 988 case FAST_DOUBLE_ELEMENTS:
966 case FAST_HOLEY_DOUBLE_ELEMENTS: 989 case FAST_HOLEY_DOUBLE_ELEMENTS:
967 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); 990 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind);
968 default: 991 default:
969 UNREACHABLE(); 992 UNREACHABLE();
970 return NULL; 993 return NULL;
971 } 994 }
972 } 995 }
973 // It's an element load (!is_store). 996 // It's an element load (!is_store).
974 return new(zone) HLoadKeyed(elements, 997 return new(zone) HLoadKeyed(elements,
975 checked_key, 998 checked_key,
976 load_dependency, 999 load_dependency,
977 elements_kind); 1000 elements_kind);
978 } 1001 }
979 1002
980 1003
1004 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
1005 HValue* elements,
1006 ElementsKind kind,
1007 HValue* length,
1008 HValue* key,
1009 bool is_js_array) {
1010 BailoutId ast_id = environment()->ast_id();
1011 Zone* zone = this->zone();
1012 IfBuilder length_checker_if(this, ast_id);
Jakob Kummerow 2013/03/11 16:36:07 nit: Drop the _if. Just length_checker. It's clean
danno 2013/03/13 15:36:26 Done.
1013
1014 length_checker_if.BeginIf(length, key, Token::EQ);
1015
1016 HValue* current_capacity =
1017 AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1018
1019 IfBuilder capacity_checker_if(this, ast_id);
Jakob Kummerow 2013/03/11 16:36:07 again
danno 2013/03/13 15:36:26 Done.
1020
1021 capacity_checker_if.BeginIf(length, current_capacity, Token::EQ);
1022
1023 HValue* context = environment()->LookupContext();
1024
1025 HValue* new_capacity =
1026 BuildNewElementsCapacity(context, current_capacity);
1027
1028 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1029 kind, length,
1030 new_capacity, ast_id);
1031
1032 environment()->Push(new_elements);
1033 capacity_checker_if.BeginElse();
1034
1035 environment()->Push(elements);
1036 capacity_checker_if.End();
1037
1038 if (is_js_array) {
1039 HValue* new_length = AddInstruction(
1040 HAdd::New(zone, context, length, graph_->GetConstant1()));
1041 new_length->ChangeRepresentation(Representation::Integer32());
1042 new_length->ClearFlag(HValue::kCanOverflow);
1043 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1044
1045 Isolate* isolate = graph()->isolate();
Jakob Kummerow 2013/03/11 16:36:07 no need for this, HGraphBuilder has an isolate() a
danno 2013/03/13 15:36:26 Done.
1046 Factory* factory = isolate->factory();
1047 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField(
1048 object,
1049 factory->length_field_string(),
1050 new_length, true,
1051 JSArray::kLengthOffset));
1052 length_store->SetGVNFlag(kChangesArrayLengths);
1053 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1054 }
1055
1056 length_checker_if.BeginElse();
1057
1058 AddBoundsCheck(key, length, ALLOW_SMI_KEY);
1059 environment()->Push(elements);
1060
1061 length_checker_if.End();
1062
1063 return environment()->Pop();
1064 }
1065
1066
1067 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
1068 HValue* elements,
1069 ElementsKind kind,
1070 HValue* length) {
1071 BailoutId ast_id = environment()->ast_id();
1072 Zone* zone = this->zone();
1073 Heap* heap = info_->isolate()->heap();
Jakob Kummerow 2013/03/11 16:36:07 s/info_->// (or s/info_/this/ if you like needless
danno 2013/03/13 15:36:26 Done.
1074 HValue* elements_map =
1075 AddInstruction(new(zone) HLoadNamedField(elements, true,
Jakob Kummerow 2013/03/11 16:36:07 Are you intentionally not using an HCompareMap ins
danno 2013/03/13 15:36:26 Done.
1076 JSObject::kMapOffset));
1077 Handle<Map> map(Handle<Map>(heap->fixed_cow_array_map()));
1078 HValue* cow_map =
1079 AddInstruction(new(zone) HConstant(map, Representation::Tagged()));
1080
1081 IfBuilder cow_checker(this, ast_id);
1082
1083 cow_checker.BeginIfObjectsEqual(elements_map, cow_map);
1084
1085 HValue* capacity =
1086 AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1087
1088 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1089 kind, length,
1090 capacity, ast_id);
1091
1092 environment()->Push(new_elements);
1093
1094 cow_checker.BeginElse();
1095
1096 environment()->Push(elements);
1097
1098 cow_checker.End();
1099
1100 return environment()->Pop();
1101 }
1102
1103
981 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 1104 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
982 HValue* object, 1105 HValue* object,
983 HValue* key, 1106 HValue* key,
984 HValue* val, 1107 HValue* val,
985 HCheckMaps* mapcheck, 1108 HCheckMaps* mapcheck,
986 bool is_js_array, 1109 bool is_js_array,
987 ElementsKind elements_kind, 1110 ElementsKind elements_kind,
988 bool is_store, 1111 bool is_store,
1112 KeyedAccessStoreMode store_mode,
989 Representation checked_index_representation) { 1113 Representation checked_index_representation) {
1114 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
990 Zone* zone = this->zone(); 1115 Zone* zone = this->zone();
991 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency 1116 // 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 1117 // 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 1118 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
994 // ElementsKind transitions. Finally, the dependency can be removed for stores 1119 // ElementsKind transitions. Finally, the dependency can be removed for stores
995 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the 1120 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
996 // generated store code. 1121 // generated store code.
997 if ((elements_kind == FAST_HOLEY_ELEMENTS) || 1122 if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
998 (elements_kind == FAST_ELEMENTS && is_store)) { 1123 (elements_kind == FAST_ELEMENTS && is_store)) {
999 if (mapcheck != NULL) { 1124 if (mapcheck != NULL) {
1000 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 1125 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
1001 } 1126 }
1002 } 1127 }
1003 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); 1128 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
1004 bool fast_elements = IsFastObjectElementsKind(elements_kind); 1129 bool fast_elements = IsFastObjectElementsKind(elements_kind);
1005 HInstruction* elements = 1130 HValue* elements =
1006 AddInstruction(new(zone) HLoadElements(object, mapcheck)); 1131 AddInstruction(new(zone) HLoadElements(object, mapcheck));
1007 if (is_store && (fast_elements || fast_smi_only_elements)) { 1132 if (is_store && (fast_elements || fast_smi_only_elements) &&
1133 store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
1008 HCheckMaps* check_cow_map = new(zone) HCheckMaps( 1134 HCheckMaps* check_cow_map = new(zone) HCheckMaps(
1009 elements, isolate()->factory()->fixed_array_map(), zone); 1135 elements, isolate()->factory()->fixed_array_map(), zone);
1010 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 1136 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1011 AddInstruction(check_cow_map); 1137 AddInstruction(check_cow_map);
1012 } 1138 }
1013 HInstruction* length = NULL; 1139 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) { 1140 if (is_js_array) {
1030 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, 1141 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck,
1031 HType::Smi())); 1142 HType::Smi()));
1032 } else { 1143 } else {
1033 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); 1144 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1034 } 1145 }
1035 checked_key = AddBoundsCheck( 1146 HValue* checked_key = NULL;
1036 key, length, ALLOW_SMI_KEY, checked_index_representation); 1147 if (IsExternalArrayElementsKind(elements_kind)) {
1037 return BuildFastElementAccess(elements, checked_key, val, mapcheck, 1148 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
1038 elements_kind, is_store); 1149 HLoadExternalArrayPointer* external_elements =
1150 new(zone) HLoadExternalArrayPointer(elements);
1151 AddInstruction(external_elements);
1152 HCheckSmiOrInt32* checked_index =
1153 new(graph()->zone()) HCheckSmiOrInt32(key);
1154 AddInstruction(checked_index);
1155 BailoutId previous_id = environment()->ast_id();
1156 ASSERT(!previous_id.IsNone());
1157 IfBuilder oob_ignore_check(this, previous_id);
Jakob Kummerow 2013/03/11 16:36:07 How about we call this IfBuilder length_checker (a
danno 2013/03/13 15:36:26 Done.
1158 oob_ignore_check.BeginIf(checked_index, length, Token::LT);
1159 IfBuilder oob_ignore_check2(this, previous_id);
Jakob Kummerow 2013/03/11 16:36:07 ...and this one negative_checker?
danno 2013/03/13 15:36:26 Done.
1160 HInstruction* bounds_check =
1161 oob_ignore_check2.BeginIf(checked_index,
1162 graph()->GetConstant0(),
1163 Token::LT);
1164 // Negative array indices can't be ignored and must be handled by the
1165 // runtime.
1166 AddSoftDeoptimize();
Jakob Kummerow 2013/03/11 16:36:07 You don't want a soft deopt here. HSoftDeoptimize
danno 2013/03/13 15:36:26 Done.
1167 oob_ignore_check2.BeginElse();
1168 HInstruction* result = BuildExternalArrayElementAccess(
1169 external_elements, key, val, bounds_check,
1170 elements_kind, is_store);
1171 AddInstruction(result);
1172 oob_ignore_check2.End();
1173 oob_ignore_check.BeginElse();
1174 oob_ignore_check.End();
1175 return result;
1176 } else {
1177 ASSERT(store_mode == STANDARD_STORE);
1178 checked_key = AddBoundsCheck(
1179 key, length, ALLOW_SMI_KEY, checked_index_representation);
1180 HLoadExternalArrayPointer* external_elements =
1181 new(zone) HLoadExternalArrayPointer(elements);
1182 AddInstruction(external_elements);
1183 return AddInstruction(BuildExternalArrayElementAccess(
1184 external_elements, checked_key, val, mapcheck,
1185 elements_kind, is_store));
1186 }
1187 }
1188 ASSERT(fast_smi_only_elements ||
1189 fast_elements ||
1190 IsFastDoubleElementsKind(elements_kind));
1191
1192 if (is_store && IsFastSmiElementsKind(elements_kind) &&
1193 val->type().IsTagged() && !val->type().IsSmi()) {
Jakob Kummerow 2013/03/11 16:36:07 Fun fact: there is no HType (except "uninitialized
danno 2013/03/13 15:36:26 Done.
1194 AddInstruction(new(zone) HCheckSmi(val));
1195 }
1196
1197 if (IsGrowStoreMode(store_mode)) {
1198 elements = BuildCheckForCapacityGrow(object, elements, elements_kind,
1199 length, key, is_js_array);
1200 checked_key = key;
1201 } else {
1202 checked_key = AddBoundsCheck(
1203 key, length, ALLOW_SMI_KEY, checked_index_representation);
1204
1205 if (is_store && (fast_elements || fast_smi_only_elements)) {
1206 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
1207 elements =
1208 BuildCopyElementsOnWrite(object, elements, elements_kind,
1209 length);
Jakob Kummerow 2013/03/11 16:36:07 nit: fits on the previous line
danno 2013/03/13 15:36:26 Done.
1210 } else {
1211 HCheckMaps* check_cow_map = new(zone) HCheckMaps(
1212 elements, Isolate::Current()->factory()->fixed_array_map(), zone);
Jakob Kummerow 2013/03/11 16:36:07 s/Isolate::Current()/isolate()/
danno 2013/03/13 15:36:26 Done.
1213 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1214 AddInstruction(check_cow_map);
1215 }
1216 }
1217 }
1218 return AddInstruction(
1219 BuildFastElementAccess(elements, checked_key, val, mapcheck,
1220 elements_kind, is_store, store_mode));
1039 } 1221 }
1040 1222
1041 1223
1042 HValue* HGraphBuilder::BuildAllocateElements(HContext* context, 1224 HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
1043 ElementsKind kind, 1225 ElementsKind kind,
1044 HValue* capacity) { 1226 HValue* capacity,
1227 BailoutId ast_id) {
1045 Zone* zone = this->zone(); 1228 Zone* zone = this->zone();
1046 1229
1047 int elements_size = IsFastDoubleElementsKind(kind) 1230 int elements_size = IsFastDoubleElementsKind(kind)
1048 ? kDoubleSize : kPointerSize; 1231 ? kDoubleSize : kPointerSize;
1049 HConstant* elements_size_value = 1232 HConstant* elements_size_value =
1050 new(zone) HConstant(elements_size, Representation::Integer32()); 1233 new(zone) HConstant(elements_size, Representation::Integer32());
1051 AddInstruction(elements_size_value); 1234 AddInstruction(elements_size_value);
1052 HValue* mul = AddInstruction( 1235 HValue* mul = AddInstruction(
1053 HMul::New(zone, context, capacity, elements_size_value)); 1236 HMul::New(zone, context, capacity, elements_size_value));
1054 mul->ChangeRepresentation(Representation::Integer32()); 1237 mul->ChangeRepresentation(Representation::Integer32());
(...skipping 14 matching lines...) Expand all
1069 } 1252 }
1070 1253
1071 HValue* elements = 1254 HValue* elements =
1072 AddInstruction(new(zone) HAllocate(context, total_size, 1255 AddInstruction(new(zone) HAllocate(context, total_size,
1073 HType::JSArray(), flags)); 1256 HType::JSArray(), flags));
1074 1257
1075 Factory* factory = isolate()->factory(); 1258 Factory* factory = isolate()->factory();
1076 Handle<Map> map = IsFastDoubleElementsKind(kind) 1259 Handle<Map> map = IsFastDoubleElementsKind(kind)
1077 ? factory->fixed_double_array_map() 1260 ? factory->fixed_double_array_map()
1078 : factory->fixed_array_map(); 1261 : factory->fixed_array_map();
1079 BuildStoreMap(elements, map, BailoutId::StubEntry()); 1262 BuildStoreMap(elements, map, ast_id);
1080 1263
1081 Handle<String> fixed_array_length_field_name = factory->length_field_string(); 1264 Handle<String> fixed_array_length_field_name = factory->length_field_string();
1082 HInstruction* store_length = 1265 HInstruction* store_length =
1083 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, 1266 new(zone) HStoreNamedField(elements, fixed_array_length_field_name,
1084 capacity, true, FixedArray::kLengthOffset); 1267 capacity, true, FixedArray::kLengthOffset);
1085 AddInstruction(store_length); 1268 AddInstruction(store_length);
1086 AddSimulate(BailoutId::StubEntry(), FIXED_SIMULATE); 1269 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1087 1270
1088 return elements; 1271 return elements;
1089 } 1272 }
1090 1273
1091 1274
1092 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, 1275 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
1093 HValue* map, 1276 HValue* map,
1094 BailoutId id) { 1277 BailoutId id) {
1095 Zone* zone = this->zone(); 1278 Zone* zone = this->zone();
1096 Factory* factory = isolate()->factory(); 1279 Factory* factory = isolate()->factory();
1097 Handle<String> map_field_name = factory->map_field_string(); 1280 Handle<String> map_field_name = factory->map_field_string();
1098 HInstruction* store_map = 1281 HInstruction* store_map =
1099 new(zone) HStoreNamedField(object, map_field_name, map, 1282 new(zone) HStoreNamedField(object, map_field_name, map,
1100 true, JSObject::kMapOffset); 1283 true, JSObject::kMapOffset);
1101 store_map->SetGVNFlag(kChangesMaps); 1284 store_map->SetGVNFlag(kChangesMaps);
1102 AddInstruction(store_map); 1285 AddInstruction(store_map);
1103 AddSimulate(id, FIXED_SIMULATE); 1286 AddSimulate(id, REMOVABLE_SIMULATE);
1104 return store_map; 1287 return store_map;
1105 } 1288 }
1106 1289
1107 1290
1108 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, 1291 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
1109 Handle<Map> map, 1292 Handle<Map> map,
1110 BailoutId id) { 1293 BailoutId id) {
1111 Zone* zone = this->zone(); 1294 Zone* zone = this->zone();
1112 HValue* map_constant = 1295 HValue* map_constant =
1113 AddInstruction(new(zone) HConstant(map, Representation::Tagged())); 1296 AddInstruction(new(zone) HConstant(map, Representation::Tagged()));
1114 return BuildStoreMap(object, map_constant, id); 1297 return BuildStoreMap(object, map_constant, id);
1115 } 1298 }
1116 1299
1117 1300
1118 void HGraphBuilder::BuildCopyElements(HContext* context, 1301 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context,
1302 HValue* old_capacity) {
1303 Zone* zone = this->zone();
1304 HValue* half_old_capacity =
1305 AddInstruction(HDiv::New(zone,
Jakob Kummerow 2013/03/11 16:36:07 prefer HSar (then you won't need GetConstant2() at
danno 2013/03/13 15:36:26 Done.
1306 context,
1307 old_capacity,
1308 graph_->GetConstant2()));
1309 half_old_capacity->ChangeRepresentation(Representation::Integer32());
1310 half_old_capacity->ClearFlag(HValue::kCanOverflow);
1311
1312 HValue* new_capacity = AddInstruction(
1313 HAdd::New(zone, context, half_old_capacity, old_capacity));
1314 new_capacity->ChangeRepresentation(Representation::Integer32());
1315 new_capacity->ClearFlag(HValue::kCanOverflow);
1316
1317 HValue* min_growth =
1318 AddInstruction(new(zone) HConstant(4, Representation::Integer32()));
Jakob Kummerow 2013/03/11 16:36:07 The C++ version (NewElementsCapacity in objects.h)
danno 2013/03/13 15:36:26 Done.
1319
1320 new_capacity = AddInstruction(
1321 HAdd::New(zone, context, new_capacity, min_growth));
1322 new_capacity->ChangeRepresentation(Representation::Integer32());
1323 new_capacity->ClearFlag(HValue::kCanOverflow);
1324
1325 return new_capacity;
1326 }
1327
1328
1329 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) {
1330 Zone* zone = this->zone();
1331 Heap* heap = info_->isolate()->heap();
Jakob Kummerow 2013/03/11 16:36:07 s/info_->//
danno 2013/03/13 15:36:26 Done.
1332 int element_size = IsFastDoubleElementsKind(kind)
1333 ? kDoubleSize
Jakob Kummerow 2013/03/11 16:36:07 nit: fits on previous line. For your copy/paste co
danno 2013/03/13 15:36:26 Done.
1334 : kPointerSize;
1335 int max_size = heap->MaxNewSpaceAllocationSize() / element_size;
1336 max_size -= sizeof(JSArray) / element_size;
Jakob Kummerow 2013/03/11 16:36:07 I think you mean s/sizeof(JSArray)/JSArray::kSize/
danno 2013/03/13 15:36:26 Done.
1337 HConstant* max_size_constant =
1338 new(zone) HConstant(max_size, Representation::Integer32());
1339 AddInstruction(max_size_constant);
1340 // Since we're forcing Integer32 representation for this HBoundsCheck,
Jakob Kummerow 2013/03/11 16:36:07 I'd prefer to make this explicit by passing (_, _,
danno 2013/03/13 15:36:26 Done.
1341 // there's no need to Smi-check the index.
1342 AddInstruction(new(zone) HBoundsCheck(length, max_size_constant));
1343 }
1344
1345
1346 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
1347 HValue* elements,
1348 ElementsKind kind,
1349 HValue* length,
1350 HValue* new_capacity,
1351 BailoutId ast_id) {
1352 Zone* zone = this->zone();
1353 HValue* context = environment()->LookupContext();
1354
1355 BuildNewSpaceArrayCheck(new_capacity, kind);
1356
1357 HValue* new_elements =
1358 BuildAllocateElements(context, kind, new_capacity, ast_id);
1359
1360 BuildCopyElements(context, elements, kind,
1361 new_elements, kind,
1362 length, new_capacity, ast_id);
1363
1364 Isolate* isolate = graph()->isolate();
Jakob Kummerow 2013/03/11 16:36:07 no need for this, just use [this->]isolate() direc
danno 2013/03/13 15:36:26 Done.
1365 Factory* factory = isolate->factory();
1366 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField(
1367 object,
1368 factory->elements_field_string(),
1369 new_elements, true,
1370 JSArray::kElementsOffset));
1371 elements_store->SetGVNFlag(kChangesElementsPointer);
1372
1373 return new_elements;
1374 }
1375
1376
1377 void HGraphBuilder::BuildFillElementsWithHole(HValue* context,
1378 HValue* elements,
1379 ElementsKind elements_kind,
1380 HValue* from,
1381 HValue* to,
1382 BailoutId ast_id) {
1383 // Fast elements kinds need to be initialized in case statements below cause
1384 // a garbage collection.
1385 Factory* factory = info_->isolate()->factory();
Jakob Kummerow 2013/03/11 16:36:07 s/info_->//
danno 2013/03/13 15:36:26 Done.
1386
1387 double nan_double = FixedDoubleArray::hole_nan_as_double();
1388 Zone* zone = this->zone();
1389 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
1390 ? AddInstruction(new(zone) HConstant(factory->the_hole_value(),
1391 Representation::Tagged()))
1392 : AddInstruction(new(zone) HConstant(nan_double,
1393 Representation::Double()));
1394
1395 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id);
1396
1397 HValue* key = builder.BeginBody(from, to, Token::LT);
1398
1399 AddInstruction(new(zone) HStoreKeyed(elements, key, hole,
1400 elements_kind));
Jakob Kummerow 2013/03/11 16:36:07 nit: fits on previous line
danno 2013/03/13 15:36:26 Done.
1401 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1402
1403 builder.EndBody();
1404 }
1405
1406
1407 void HGraphBuilder::BuildCopyElements(HValue* context,
1119 HValue* from_elements, 1408 HValue* from_elements,
1120 ElementsKind from_elements_kind, 1409 ElementsKind from_elements_kind,
1121 HValue* to_elements, 1410 HValue* to_elements,
1122 ElementsKind to_elements_kind, 1411 ElementsKind to_elements_kind,
1123 HValue* length) { 1412 HValue* length,
1124 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, 1413 HValue* capacity,
1125 BailoutId::StubEntry()); 1414 BailoutId ast_id) {
1415 bool pre_fill_with_holes =
1416 IsFastDoubleElementsKind(from_elements_kind) &&
1417 IsFastObjectElementsKind(to_elements_kind);
1126 1418
1127 HValue* key = builder.BeginBody(graph()->GetConstant0(), 1419 if (pre_fill_with_holes) {
1128 length, Token::LT); 1420 // If the copy might trigger a GC, make sure that the FixedArray is
1421 // pre-initialized with holes to make sure that it's always in a consistent
1422 // state.
1423 BuildFillElementsWithHole(context, to_elements, to_elements_kind,
1424 graph()->GetConstant0(), capacity, ast_id);
1425 }
1426
1427 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id);
1428
1429 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT);
1129 1430
1130 HValue* element = 1431 HValue* element =
1131 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, 1432 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL,
1132 from_elements_kind, 1433 from_elements_kind,
1133 ALLOW_RETURN_HOLE)); 1434 ALLOW_RETURN_HOLE));
1134 1435
1135 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element, 1436 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element,
1136 to_elements_kind)); 1437 to_elements_kind));
1137 AddSimulate(BailoutId::StubEntry(), REMOVABLE_SIMULATE); 1438 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1138 1439
1139 builder.EndBody(); 1440 builder.EndBody();
1441
1442 if (!pre_fill_with_holes && length != capacity) {
1443 // Fill unused capacity with the hole.
1444 BuildFillElementsWithHole(context, to_elements, to_elements_kind,
1445 key, capacity, ast_id);
1446 }
1140 } 1447 }
1141 1448
1142 1449
1450 void HGraphBuilder::AddSoftDeoptimize() {
1451 if (FLAG_always_opt) return;
1452 if (current_block()->IsDeoptimizing()) return;
1453 AddInstruction(new(zone()) HSoftDeoptimize());
1454 current_block()->MarkAsDeoptimizing();
1455 graph()->set_has_soft_deoptimize(true);
1456 }
1457
1458
1143 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, 1459 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info,
1144 TypeFeedbackOracle* oracle) 1460 TypeFeedbackOracle* oracle)
1145 : HGraphBuilder(info), 1461 : HGraphBuilder(info),
1146 function_state_(NULL), 1462 function_state_(NULL),
1147 initial_function_state_(this, info, oracle, NORMAL_RETURN), 1463 initial_function_state_(this, info, oracle, NORMAL_RETURN),
1148 ast_context_(NULL), 1464 ast_context_(NULL),
1149 break_scope_(NULL), 1465 break_scope_(NULL),
1150 inlined_count_(0), 1466 inlined_count_(0),
1151 globals_(10, info->zone()), 1467 globals_(10, info->zone()),
1152 inline_bailout_(false) { 1468 inline_bailout_(false) {
(...skipping 3339 matching lines...) Expand 10 before | Expand all | Expand 10 after
4492 current_block()->AddPhi(instr); 4808 current_block()->AddPhi(instr);
4493 } 4809 }
4494 4810
4495 4811
4496 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { 4812 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) {
4497 Push(instr); 4813 Push(instr);
4498 AddInstruction(instr); 4814 AddInstruction(instr);
4499 } 4815 }
4500 4816
4501 4817
4502 void HOptimizedGraphBuilder::AddSoftDeoptimize() {
4503 if (FLAG_always_opt) return;
4504 if (current_block()->IsDeoptimizing()) return;
4505 AddInstruction(new(zone()) HSoftDeoptimize());
4506 current_block()->MarkAsDeoptimizing();
4507 graph()->set_has_soft_deoptimize(true);
4508 }
4509
4510
4511 template <class Instruction> 4818 template <class Instruction>
4512 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { 4819 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
4513 int count = call->argument_count(); 4820 int count = call->argument_count();
4514 ZoneList<HValue*> arguments(count, zone()); 4821 ZoneList<HValue*> arguments(count, zone());
4515 for (int i = 0; i < count; ++i) { 4822 for (int i = 0; i < count; ++i) {
4516 arguments.Add(Pop(), zone()); 4823 arguments.Add(Pop(), zone());
4517 } 4824 }
4518 4825
4519 while (!arguments.is_empty()) { 4826 while (!arguments.is_empty()) {
4520 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); 4827 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast()));
(...skipping 2253 matching lines...) Expand 10 before | Expand all | Expand 10 after
6774 return new(zone()) HLoadKeyedGeneric(context, object, key); 7081 return new(zone()) HLoadKeyedGeneric(context, object, key);
6775 } 7082 }
6776 7083
6777 7084
6778 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( 7085 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
6779 HValue* object, 7086 HValue* object,
6780 HValue* key, 7087 HValue* key,
6781 HValue* val, 7088 HValue* val,
6782 HValue* dependency, 7089 HValue* dependency,
6783 Handle<Map> map, 7090 Handle<Map> map,
6784 bool is_store) { 7091 bool is_store,
7092 KeyedAccessStoreMode store_mode) {
6785 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, 7093 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map,
6786 zone(), dependency); 7094 zone(), dependency);
6787 AddInstruction(mapcheck); 7095 AddInstruction(mapcheck);
6788 if (dependency) { 7096 if (dependency) {
6789 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 7097 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
6790 } 7098 }
6791 return BuildUncheckedMonomorphicElementAccess( 7099 return BuildUncheckedMonomorphicElementAccess(
6792 object, key, val, 7100 object, key, val,
6793 mapcheck, map->instance_type() == JS_ARRAY_TYPE, 7101 mapcheck, map->instance_type() == JS_ARRAY_TYPE,
6794 map->elements_kind(), is_store); 7102 map->elements_kind(), is_store, store_mode);
6795 } 7103 }
6796 7104
6797 7105
6798 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( 7106 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
6799 HValue* object, 7107 HValue* object,
6800 HValue* key, 7108 HValue* key,
6801 HValue* val, 7109 HValue* val,
6802 SmallMapList* maps) { 7110 SmallMapList* maps) {
6803 // For polymorphic loads of similar elements kinds (i.e. all tagged or all 7111 // 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 7112 // double), always use the "worst case" code without a transition. This is
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
6839 } 7147 }
6840 } 7148 }
6841 if (!has_double_maps && !has_smi_or_object_maps) return NULL; 7149 if (!has_double_maps && !has_smi_or_object_maps) return NULL;
6842 7150
6843 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); 7151 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone());
6844 AddInstruction(check_maps); 7152 AddInstruction(check_maps);
6845 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( 7153 HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
6846 object, key, val, check_maps, 7154 object, key, val, check_maps,
6847 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, 7155 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
6848 most_general_consolidated_map->elements_kind(), 7156 most_general_consolidated_map->elements_kind(),
6849 false); 7157 false, STANDARD_STORE);
6850 return instr; 7158 return instr;
6851 } 7159 }
6852 7160
6853 7161
6854 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( 7162 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
6855 HValue* object, 7163 HValue* object,
6856 HValue* key, 7164 HValue* key,
6857 HValue* val, 7165 HValue* val,
6858 Expression* prop, 7166 Expression* prop,
6859 BailoutId ast_id, 7167 BailoutId ast_id,
6860 int position, 7168 int position,
6861 bool is_store, 7169 bool is_store,
7170 KeyedAccessStoreMode store_mode,
6862 bool* has_side_effects) { 7171 bool* has_side_effects) {
6863 *has_side_effects = false; 7172 *has_side_effects = false;
6864 AddInstruction(new(zone()) HCheckNonSmi(object)); 7173 AddInstruction(new(zone()) HCheckNonSmi(object));
6865 SmallMapList* maps = prop->GetReceiverTypes(); 7174 SmallMapList* maps = prop->GetReceiverTypes();
6866 bool todo_external_array = false; 7175 bool todo_external_array = false;
6867 7176
6868 if (!is_store) { 7177 if (!is_store) {
6869 HInstruction* consolidated_load = 7178 HInstruction* consolidated_load =
6870 TryBuildConsolidatedElementLoad(object, key, val, maps); 7179 TryBuildConsolidatedElementLoad(object, key, val, maps);
6871 if (consolidated_load != NULL) { 7180 if (consolidated_load != NULL) {
6872 AddInstruction(consolidated_load);
6873 *has_side_effects |= consolidated_load->HasObservableSideEffects(); 7181 *has_side_effects |= consolidated_load->HasObservableSideEffects();
6874 if (position != RelocInfo::kNoPosition) { 7182 if (position != RelocInfo::kNoPosition) {
6875 consolidated_load->set_position(position); 7183 consolidated_load->set_position(position);
6876 } 7184 }
6877 return consolidated_load; 7185 return consolidated_load;
6878 } 7186 }
6879 } 7187 }
6880 7188
6881 static const int kNumElementTypes = kElementsKindCount; 7189 static const int kNumElementTypes = kElementsKindCount;
6882 bool type_todo[kNumElementTypes]; 7190 bool type_todo[kNumElementTypes];
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
6929 } 7237 }
6930 7238
6931 // If only one map is left after transitioning, handle this case 7239 // If only one map is left after transitioning, handle this case
6932 // monomorphically. 7240 // monomorphically.
6933 if (num_untransitionable_maps == 1) { 7241 if (num_untransitionable_maps == 1) {
6934 HInstruction* instr = NULL; 7242 HInstruction* instr = NULL;
6935 if (untransitionable_map->has_slow_elements_kind()) { 7243 if (untransitionable_map->has_slow_elements_kind()) {
6936 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 7244 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
6937 : BuildLoadKeyedGeneric(object, key)); 7245 : BuildLoadKeyedGeneric(object, key));
6938 } else { 7246 } else {
6939 instr = AddInstruction(BuildMonomorphicElementAccess( 7247 instr = BuildMonomorphicElementAccess(
6940 object, key, val, transition, untransitionable_map, is_store)); 7248 object, key, val, transition, untransitionable_map, is_store,
7249 store_mode);
6941 } 7250 }
6942 *has_side_effects |= instr->HasObservableSideEffects(); 7251 *has_side_effects |= instr->HasObservableSideEffects();
6943 if (position != RelocInfo::kNoPosition) instr->set_position(position); 7252 if (position != RelocInfo::kNoPosition) instr->set_position(position);
6944 return is_store ? NULL : instr; 7253 return is_store ? NULL : instr;
6945 } 7254 }
6946 7255
6947 HInstruction* checkspec = 7256 HInstruction* checkspec =
6948 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); 7257 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone()));
6949 HBasicBlock* join = graph()->CreateBasicBlock(); 7258 HBasicBlock* join = graph()->CreateBasicBlock();
6950 7259
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
7011 typecheck->SetSuccessorAt(1, if_fastobject); 7320 typecheck->SetSuccessorAt(1, if_fastobject);
7012 current_block()->Finish(typecheck); 7321 current_block()->Finish(typecheck);
7013 7322
7014 set_current_block(if_jsarray); 7323 set_current_block(if_jsarray);
7015 HInstruction* length; 7324 HInstruction* length;
7016 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck, 7325 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck,
7017 HType::Smi())); 7326 HType::Smi()));
7018 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); 7327 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
7019 access = AddInstruction(BuildFastElementAccess( 7328 access = AddInstruction(BuildFastElementAccess(
7020 elements, checked_key, val, elements_kind_branch, 7329 elements, checked_key, val, elements_kind_branch,
7021 elements_kind, is_store)); 7330 elements_kind, is_store, STANDARD_STORE));
7022 if (!is_store) { 7331 if (!is_store) {
7023 Push(access); 7332 Push(access);
7024 } 7333 }
7025 7334
7026 *has_side_effects |= access->HasObservableSideEffects(); 7335 *has_side_effects |= access->HasObservableSideEffects();
7027 if (position != -1) { 7336 if (position != -1) {
7028 access->set_position(position); 7337 access->set_position(position);
7029 } 7338 }
7030 if_jsarray->Goto(join); 7339 if_jsarray->Goto(join);
7031 7340
7032 set_current_block(if_fastobject); 7341 set_current_block(if_fastobject);
7033 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 7342 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
7034 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); 7343 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
7035 access = AddInstruction(BuildFastElementAccess( 7344 access = AddInstruction(BuildFastElementAccess(
7036 elements, checked_key, val, elements_kind_branch, 7345 elements, checked_key, val, elements_kind_branch,
7037 elements_kind, is_store)); 7346 elements_kind, is_store, STANDARD_STORE));
7038 } else if (elements_kind == DICTIONARY_ELEMENTS) { 7347 } else if (elements_kind == DICTIONARY_ELEMENTS) {
7039 if (is_store) { 7348 if (is_store) {
7040 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); 7349 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
7041 } else { 7350 } else {
7042 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); 7351 access = AddInstruction(BuildLoadKeyedGeneric(object, key));
7043 } 7352 }
7044 } else { // External array elements. 7353 } else { // External array elements.
7045 access = AddInstruction(BuildExternalArrayElementAccess( 7354 access = AddInstruction(BuildExternalArrayElementAccess(
7046 external_elements, checked_key, val, 7355 external_elements, checked_key, val,
7047 elements_kind_branch, elements_kind, is_store)); 7356 elements_kind_branch, elements_kind, is_store));
(...skipping 25 matching lines...) Expand all
7073 int position, 7382 int position,
7074 bool is_store, 7383 bool is_store,
7075 bool* has_side_effects) { 7384 bool* has_side_effects) {
7076 ASSERT(!expr->IsPropertyName()); 7385 ASSERT(!expr->IsPropertyName());
7077 HInstruction* instr = NULL; 7386 HInstruction* instr = NULL;
7078 if (expr->IsMonomorphic()) { 7387 if (expr->IsMonomorphic()) {
7079 Handle<Map> map = expr->GetMonomorphicReceiverType(); 7388 Handle<Map> map = expr->GetMonomorphicReceiverType();
7080 if (map->has_slow_elements_kind()) { 7389 if (map->has_slow_elements_kind()) {
7081 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 7390 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
7082 : BuildLoadKeyedGeneric(obj, key); 7391 : BuildLoadKeyedGeneric(obj, key);
7392 AddInstruction(instr);
7083 } else { 7393 } else {
7084 AddInstruction(new(zone()) HCheckNonSmi(obj)); 7394 AddInstruction(new(zone()) HCheckNonSmi(obj));
7085 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); 7395 instr = BuildMonomorphicElementAccess(
7396 obj, key, val, NULL, map,
7397 is_store, expr->GetStoreMode());
Jakob Kummerow 2013/03/11 16:36:07 nit: fits on previous line
danno 2013/03/13 15:36:26 Done.
7086 } 7398 }
7087 } else if (expr->GetReceiverTypes() != NULL && 7399 } else if (expr->GetReceiverTypes() != NULL &&
7088 !expr->GetReceiverTypes()->is_empty()) { 7400 !expr->GetReceiverTypes()->is_empty()) {
7089 return HandlePolymorphicElementAccess( 7401 return HandlePolymorphicElementAccess(
7090 obj, key, val, expr, ast_id, position, is_store, has_side_effects); 7402 obj, key, val, expr, ast_id, position, is_store,
7403 expr->GetStoreMode(), has_side_effects);
7091 } else { 7404 } else {
7092 if (is_store) { 7405 if (is_store) {
7093 instr = BuildStoreKeyedGeneric(obj, key, val); 7406 instr = BuildStoreKeyedGeneric(obj, key, val);
7094 } else { 7407 } else {
7095 instr = BuildLoadKeyedGeneric(obj, key); 7408 instr = BuildLoadKeyedGeneric(obj, key);
7096 } 7409 }
7410 AddInstruction(instr);
7097 } 7411 }
7098 if (position != RelocInfo::kNoPosition) instr->set_position(position); 7412 if (position != RelocInfo::kNoPosition) instr->set_position(position);
7099 AddInstruction(instr);
7100 *has_side_effects = instr->HasObservableSideEffects(); 7413 *has_side_effects = instr->HasObservableSideEffects();
7101 return instr; 7414 return instr;
7102 } 7415 }
7103 7416
7104 7417
7105 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( 7418 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric(
7106 HValue* object, 7419 HValue* object,
7107 HValue* key, 7420 HValue* key,
7108 HValue* value) { 7421 HValue* value) {
7109 HValue* context = environment()->LookupContext(); 7422 HValue* context = environment()->LookupContext();
(...skipping 3753 matching lines...) Expand 10 before | Expand all | Expand 10 after
10863 } 11176 }
10864 } 11177 }
10865 11178
10866 #ifdef DEBUG 11179 #ifdef DEBUG
10867 if (graph_ != NULL) graph_->Verify(false); // No full verify. 11180 if (graph_ != NULL) graph_->Verify(false); // No full verify.
10868 if (allocator_ != NULL) allocator_->Verify(); 11181 if (allocator_ != NULL) allocator_->Verify();
10869 #endif 11182 #endif
10870 } 11183 }
10871 11184
10872 } } // namespace v8::internal 11185 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698