| 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 |