OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 } | 1116 } |
1117 | 1117 |
1118 | 1118 |
1119 HInstruction* HGraphBuilder::BuildFastElementAccess( | 1119 HInstruction* HGraphBuilder::BuildFastElementAccess( |
1120 HValue* elements, | 1120 HValue* elements, |
1121 HValue* checked_key, | 1121 HValue* checked_key, |
1122 HValue* val, | 1122 HValue* val, |
1123 HValue* load_dependency, | 1123 HValue* load_dependency, |
1124 ElementsKind elements_kind, | 1124 ElementsKind elements_kind, |
1125 bool is_store, | 1125 bool is_store, |
| 1126 LoadKeyedHoleMode load_mode, |
1126 KeyedAccessStoreMode store_mode) { | 1127 KeyedAccessStoreMode store_mode) { |
1127 Zone* zone = this->zone(); | 1128 Zone* zone = this->zone(); |
1128 if (is_store) { | 1129 if (is_store) { |
1129 ASSERT(val != NULL); | 1130 ASSERT(val != NULL); |
1130 switch (elements_kind) { | 1131 switch (elements_kind) { |
1131 case FAST_SMI_ELEMENTS: | 1132 case FAST_SMI_ELEMENTS: |
1132 case FAST_HOLEY_SMI_ELEMENTS: | 1133 case FAST_HOLEY_SMI_ELEMENTS: |
1133 if (!val->type().IsSmi()) { | 1134 if (!val->type().IsSmi()) { |
1134 // Smi-only arrays need a smi check. | 1135 // Smi-only arrays need a smi check. |
1135 AddInstruction(new(zone) HCheckSmi(val)); | 1136 AddInstruction(new(zone) HCheckSmi(val)); |
1136 } | 1137 } |
1137 // Fall through. | 1138 // Fall through. |
1138 case FAST_ELEMENTS: | 1139 case FAST_ELEMENTS: |
1139 case FAST_HOLEY_ELEMENTS: | 1140 case FAST_HOLEY_ELEMENTS: |
1140 case FAST_DOUBLE_ELEMENTS: | 1141 case FAST_DOUBLE_ELEMENTS: |
1141 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1142 case FAST_HOLEY_DOUBLE_ELEMENTS: |
1142 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); | 1143 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); |
1143 default: | 1144 default: |
1144 UNREACHABLE(); | 1145 UNREACHABLE(); |
1145 return NULL; | 1146 return NULL; |
1146 } | 1147 } |
1147 } | 1148 } |
1148 // It's an element load (!is_store). | 1149 // It's an element load (!is_store). |
1149 return new(zone) HLoadKeyed(elements, | 1150 return new(zone) HLoadKeyed(elements, |
1150 checked_key, | 1151 checked_key, |
1151 load_dependency, | 1152 load_dependency, |
1152 elements_kind); | 1153 elements_kind, |
| 1154 load_mode); |
1153 } | 1155 } |
1154 | 1156 |
1155 | 1157 |
1156 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, | 1158 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, |
1157 HValue* elements, | 1159 HValue* elements, |
1158 ElementsKind kind, | 1160 ElementsKind kind, |
1159 HValue* length, | 1161 HValue* length, |
1160 HValue* key, | 1162 HValue* key, |
1161 bool is_js_array) { | 1163 bool is_js_array) { |
1162 Zone* zone = this->zone(); | 1164 Zone* zone = this->zone(); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1249 | 1251 |
1250 | 1252 |
1251 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1253 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
1252 HValue* object, | 1254 HValue* object, |
1253 HValue* key, | 1255 HValue* key, |
1254 HValue* val, | 1256 HValue* val, |
1255 HCheckMaps* mapcheck, | 1257 HCheckMaps* mapcheck, |
1256 bool is_js_array, | 1258 bool is_js_array, |
1257 ElementsKind elements_kind, | 1259 ElementsKind elements_kind, |
1258 bool is_store, | 1260 bool is_store, |
| 1261 LoadKeyedHoleMode load_mode, |
1259 KeyedAccessStoreMode store_mode, | 1262 KeyedAccessStoreMode store_mode, |
1260 Representation checked_index_representation) { | 1263 Representation checked_index_representation) { |
1261 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); | 1264 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); |
1262 Zone* zone = this->zone(); | 1265 Zone* zone = this->zone(); |
1263 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 1266 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
1264 // on a HElementsTransition instruction. The flag can also be removed if the | 1267 // on a HElementsTransition instruction. The flag can also be removed if the |
1265 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 1268 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
1266 // ElementsKind transitions. Finally, the dependency can be removed for stores | 1269 // ElementsKind transitions. Finally, the dependency can be removed for stores |
1267 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 1270 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
1268 // generated store code. | 1271 // generated store code. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1354 } else { | 1357 } else { |
1355 HCheckMaps* check_cow_map = HCheckMaps::New( | 1358 HCheckMaps* check_cow_map = HCheckMaps::New( |
1356 elements, isolate()->factory()->fixed_array_map(), zone); | 1359 elements, isolate()->factory()->fixed_array_map(), zone); |
1357 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1360 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1358 AddInstruction(check_cow_map); | 1361 AddInstruction(check_cow_map); |
1359 } | 1362 } |
1360 } | 1363 } |
1361 } | 1364 } |
1362 return AddInstruction( | 1365 return AddInstruction( |
1363 BuildFastElementAccess(elements, checked_key, val, mapcheck, | 1366 BuildFastElementAccess(elements, checked_key, val, mapcheck, |
1364 elements_kind, is_store, store_mode)); | 1367 elements_kind, is_store, load_mode, store_mode)); |
1365 } | 1368 } |
1366 | 1369 |
1367 | 1370 |
1368 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, | 1371 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, |
1369 ElementsKind kind, | 1372 ElementsKind kind, |
1370 HValue* capacity) { | 1373 HValue* capacity) { |
1371 Zone* zone = this->zone(); | 1374 Zone* zone = this->zone(); |
1372 | 1375 |
1373 int elements_size = IsFastDoubleElementsKind(kind) | 1376 int elements_size = IsFastDoubleElementsKind(kind) |
1374 ? kDoubleSize : kPointerSize; | 1377 ? kDoubleSize : kPointerSize; |
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2093 entry_block_(NULL), | 2096 entry_block_(NULL), |
2094 blocks_(8, info->zone()), | 2097 blocks_(8, info->zone()), |
2095 values_(16, info->zone()), | 2098 values_(16, info->zone()), |
2096 phi_list_(NULL), | 2099 phi_list_(NULL), |
2097 uint32_instructions_(NULL), | 2100 uint32_instructions_(NULL), |
2098 info_(info), | 2101 info_(info), |
2099 zone_(info->zone()), | 2102 zone_(info->zone()), |
2100 is_recursive_(false), | 2103 is_recursive_(false), |
2101 use_optimistic_licm_(false), | 2104 use_optimistic_licm_(false), |
2102 has_soft_deoptimize_(false), | 2105 has_soft_deoptimize_(false), |
| 2106 depends_on_empty_array_proto_elements_(false), |
2103 type_change_checksum_(0) { | 2107 type_change_checksum_(0) { |
2104 if (info->IsStub()) { | 2108 if (info->IsStub()) { |
2105 HydrogenCodeStub* stub = info->code_stub(); | 2109 HydrogenCodeStub* stub = info->code_stub(); |
2106 CodeStubInterfaceDescriptor* descriptor = | 2110 CodeStubInterfaceDescriptor* descriptor = |
2107 stub->GetInterfaceDescriptor(isolate_); | 2111 stub->GetInterfaceDescriptor(isolate_); |
2108 start_environment_ = | 2112 start_environment_ = |
2109 new(zone_) HEnvironment(zone_, descriptor->environment_length()); | 2113 new(zone_) HEnvironment(zone_, descriptor->environment_length()); |
2110 } else { | 2114 } else { |
2111 start_environment_ = | 2115 start_environment_ = |
2112 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); | 2116 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); |
(...skipping 5818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7931 HValue* val, | 7935 HValue* val, |
7932 HValue* dependency, | 7936 HValue* dependency, |
7933 Handle<Map> map, | 7937 Handle<Map> map, |
7934 bool is_store, | 7938 bool is_store, |
7935 KeyedAccessStoreMode store_mode) { | 7939 KeyedAccessStoreMode store_mode) { |
7936 HCheckMaps* mapcheck = HCheckMaps::New(object, map, zone(), dependency); | 7940 HCheckMaps* mapcheck = HCheckMaps::New(object, map, zone(), dependency); |
7937 AddInstruction(mapcheck); | 7941 AddInstruction(mapcheck); |
7938 if (dependency) { | 7942 if (dependency) { |
7939 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 7943 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
7940 } | 7944 } |
| 7945 |
| 7946 // Loads from a "stock" fast holey double arrays can elide the hole check. |
| 7947 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
| 7948 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
| 7949 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
| 7950 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
| 7951 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); |
| 7952 AddInstruction( |
| 7953 new(zone()) HCheckPrototypeMaps(prototype, object_prototype, zone())); |
| 7954 load_mode = ALLOW_RETURN_HOLE; |
| 7955 graph()->MarkDependsOnEmptyArrayProtoElements(); |
| 7956 } |
| 7957 |
7941 return BuildUncheckedMonomorphicElementAccess( | 7958 return BuildUncheckedMonomorphicElementAccess( |
7942 object, key, val, | 7959 object, key, val, |
7943 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | 7960 mapcheck, map->instance_type() == JS_ARRAY_TYPE, |
7944 map->elements_kind(), is_store, store_mode); | 7961 map->elements_kind(), is_store, load_mode, store_mode); |
7945 } | 7962 } |
7946 | 7963 |
7947 | 7964 |
7948 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( | 7965 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( |
7949 HValue* object, | 7966 HValue* object, |
7950 HValue* key, | 7967 HValue* key, |
7951 HValue* val, | 7968 HValue* val, |
7952 SmallMapList* maps) { | 7969 SmallMapList* maps) { |
7953 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | 7970 // For polymorphic loads of similar elements kinds (i.e. all tagged or all |
7954 // double), always use the "worst case" code without a transition. This is | 7971 // double), always use the "worst case" code without a transition. This is |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7989 } | 8006 } |
7990 } | 8007 } |
7991 if (!has_double_maps && !has_smi_or_object_maps) return NULL; | 8008 if (!has_double_maps && !has_smi_or_object_maps) return NULL; |
7992 | 8009 |
7993 HCheckMaps* check_maps = HCheckMaps::New(object, maps, zone()); | 8010 HCheckMaps* check_maps = HCheckMaps::New(object, maps, zone()); |
7994 AddInstruction(check_maps); | 8011 AddInstruction(check_maps); |
7995 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 8012 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
7996 object, key, val, check_maps, | 8013 object, key, val, check_maps, |
7997 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | 8014 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, |
7998 most_general_consolidated_map->elements_kind(), | 8015 most_general_consolidated_map->elements_kind(), |
7999 false, STANDARD_STORE); | 8016 false, NEVER_RETURN_HOLE, STANDARD_STORE); |
8000 return instr; | 8017 return instr; |
8001 } | 8018 } |
8002 | 8019 |
8003 | 8020 |
8004 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 8021 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
8005 HValue* object, | 8022 HValue* object, |
8006 HValue* key, | 8023 HValue* key, |
8007 HValue* val, | 8024 HValue* val, |
8008 Expression* prop, | 8025 Expression* prop, |
8009 BailoutId ast_id, | 8026 BailoutId ast_id, |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8162 current_block()->Finish(typecheck); | 8179 current_block()->Finish(typecheck); |
8163 | 8180 |
8164 set_current_block(if_jsarray); | 8181 set_current_block(if_jsarray); |
8165 HInstruction* length; | 8182 HInstruction* length; |
8166 length = AddInstruction( | 8183 length = AddInstruction( |
8167 HLoadNamedField::NewArrayLength(zone(), object, typecheck, | 8184 HLoadNamedField::NewArrayLength(zone(), object, typecheck, |
8168 HType::Smi())); | 8185 HType::Smi())); |
8169 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 8186 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
8170 access = AddInstruction(BuildFastElementAccess( | 8187 access = AddInstruction(BuildFastElementAccess( |
8171 elements, checked_key, val, elements_kind_branch, | 8188 elements, checked_key, val, elements_kind_branch, |
8172 elements_kind, is_store, STANDARD_STORE)); | 8189 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); |
8173 if (!is_store) { | 8190 if (!is_store) { |
8174 Push(access); | 8191 Push(access); |
8175 } | 8192 } |
8176 | 8193 |
8177 *has_side_effects |= access->HasObservableSideEffects(); | 8194 *has_side_effects |= access->HasObservableSideEffects(); |
8178 // The caller will use has_side_effects and add correct Simulate. | 8195 // The caller will use has_side_effects and add correct Simulate. |
8179 access->SetFlag(HValue::kHasNoObservableSideEffects); | 8196 access->SetFlag(HValue::kHasNoObservableSideEffects); |
8180 if (position != -1) { | 8197 if (position != -1) { |
8181 access->set_position(position); | 8198 access->set_position(position); |
8182 } | 8199 } |
8183 if_jsarray->GotoNoSimulate(join); | 8200 if_jsarray->GotoNoSimulate(join); |
8184 | 8201 |
8185 set_current_block(if_fastobject); | 8202 set_current_block(if_fastobject); |
8186 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 8203 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
8187 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 8204 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
8188 access = AddInstruction(BuildFastElementAccess( | 8205 access = AddInstruction(BuildFastElementAccess( |
8189 elements, checked_key, val, elements_kind_branch, | 8206 elements, checked_key, val, elements_kind_branch, |
8190 elements_kind, is_store, STANDARD_STORE)); | 8207 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); |
8191 } else if (elements_kind == DICTIONARY_ELEMENTS) { | 8208 } else if (elements_kind == DICTIONARY_ELEMENTS) { |
8192 if (is_store) { | 8209 if (is_store) { |
8193 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 8210 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
8194 } else { | 8211 } else { |
8195 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 8212 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
8196 } | 8213 } |
8197 } else { // External array elements. | 8214 } else { // External array elements. |
8198 access = AddInstruction(BuildExternalArrayElementAccess( | 8215 access = AddInstruction(BuildExternalArrayElementAccess( |
8199 external_elements, checked_key, val, | 8216 external_elements, checked_key, val, |
8200 elements_kind_branch, elements_kind, is_store)); | 8217 elements_kind_branch, elements_kind, is_store)); |
(...skipping 4170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12371 } | 12388 } |
12372 } | 12389 } |
12373 | 12390 |
12374 #ifdef DEBUG | 12391 #ifdef DEBUG |
12375 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 12392 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
12376 if (allocator_ != NULL) allocator_->Verify(); | 12393 if (allocator_ != NULL) allocator_->Verify(); |
12377 #endif | 12394 #endif |
12378 } | 12395 } |
12379 | 12396 |
12380 } } // namespace v8::internal | 12397 } } // namespace v8::internal |
OLD | NEW |