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 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1702 bool hoisted = false; | 1702 bool hoisted = false; |
1703 if (instr->CheckFlag(HValue::kUseGVN)) { | 1703 if (instr->CheckFlag(HValue::kUseGVN)) { |
1704 TRACE_GVN_4("Checking instruction %d (%s) %s. Loop %s\n", | 1704 TRACE_GVN_4("Checking instruction %d (%s) %s. Loop %s\n", |
1705 instr->id(), | 1705 instr->id(), |
1706 instr->Mnemonic(), | 1706 instr->Mnemonic(), |
1707 *GetGVNFlagsString(instr->gvn_flags()), | 1707 *GetGVNFlagsString(instr->gvn_flags()), |
1708 *GetGVNFlagsString(loop_kills)); | 1708 *GetGVNFlagsString(loop_kills)); |
1709 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); | 1709 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); |
1710 if (instr->IsTransitionElementsKind()) { | 1710 if (instr->IsTransitionElementsKind()) { |
1711 // It's possible to hoist transitions out of a loop as long as the | 1711 // It's possible to hoist transitions out of a loop as long as the |
1712 // hoisting wouldn't move the transition past a DependsOn of one of it's | 1712 // hoisting wouldn't move the transition past an instruction that has a |
1713 // changes or any instructions that might change an objects map or | 1713 // DependsOn flag for anything it changes. |
1714 // elements contents. | |
1715 GVNFlagSet changes = instr->ChangesFlags(); | |
1716 GVNFlagSet hoist_depends_blockers = | 1714 GVNFlagSet hoist_depends_blockers = |
1717 HValue::ConvertChangesToDependsFlags(changes); | 1715 HValue::ConvertChangesToDependsFlags(instr->ChangesFlags()); |
1718 // In addition to not hoisting transitions above other instructions that | 1716 |
1719 // change dependencies that the transition changes, it must not be | 1717 // In addition, the transition must not be hoisted above elements kind |
1720 // hoisted above map changes and stores to an elements backing store | 1718 // changes, or if the transition is destructive to the elements buffer, |
1721 // that the transition might change. | 1719 // changes to array pointer or array contents. |
1722 GVNFlagSet hoist_change_blockers = changes; | 1720 GVNFlagSet hoist_change_blockers; |
1723 hoist_change_blockers.Add(kChangesMaps); | 1721 hoist_change_blockers.Add(kChangesElementsKind); |
1724 HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr); | 1722 HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr); |
1725 if (trans->original_map()->has_fast_double_elements()) { | 1723 if (trans->original_map()->has_fast_double_elements()) { |
| 1724 hoist_change_blockers.Add(kChangesElementsPointer); |
1726 hoist_change_blockers.Add(kChangesDoubleArrayElements); | 1725 hoist_change_blockers.Add(kChangesDoubleArrayElements); |
1727 } | 1726 } |
1728 if (trans->transitioned_map()->has_fast_double_elements()) { | 1727 if (trans->transitioned_map()->has_fast_double_elements()) { |
| 1728 hoist_change_blockers.Add(kChangesElementsPointer); |
1729 hoist_change_blockers.Add(kChangesArrayElements); | 1729 hoist_change_blockers.Add(kChangesArrayElements); |
1730 } | 1730 } |
1731 if (FLAG_trace_gvn) { | 1731 if (FLAG_trace_gvn) { |
1732 GVNFlagSet hoist_blockers = hoist_depends_blockers; | 1732 GVNFlagSet hoist_blockers = hoist_depends_blockers; |
1733 hoist_blockers.Add(hoist_change_blockers); | 1733 hoist_blockers.Add(hoist_change_blockers); |
1734 GVNFlagSet first_time = *first_time_changes; | 1734 GVNFlagSet first_time = *first_time_changes; |
1735 first_time.Add(*first_time_depends); | 1735 first_time.Add(*first_time_depends); |
1736 TRACE_GVN_4("Checking dependencies on HTransitionElementsKind " | 1736 TRACE_GVN_4("Checking dependencies on HTransitionElementsKind " |
1737 "%d (%s) hoist blockers: %s; " | 1737 "%d (%s) hoist blockers: %s; " |
1738 "first-time accumulated: %s\n", | 1738 "first-time accumulated: %s\n", |
(...skipping 2220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3959 | 3959 |
3960 set_current_block(loop_successor); | 3960 set_current_block(loop_successor); |
3961 Drop(5); | 3961 Drop(5); |
3962 | 3962 |
3963 set_current_block(loop_body); | 3963 set_current_block(loop_body); |
3964 | 3964 |
3965 HValue* key = AddInstruction( | 3965 HValue* key = AddInstruction( |
3966 new(zone()) HLoadKeyedFastElement( | 3966 new(zone()) HLoadKeyedFastElement( |
3967 environment()->ExpressionStackAt(2), // Enum cache. | 3967 environment()->ExpressionStackAt(2), // Enum cache. |
3968 environment()->ExpressionStackAt(0), // Iteration index. | 3968 environment()->ExpressionStackAt(0), // Iteration index. |
3969 HLoadKeyedFastElement::OMIT_HOLE_CHECK)); | 3969 OMIT_HOLE_CHECK)); |
3970 | 3970 |
3971 // Check if the expected map still matches that of the enumerable. | 3971 // Check if the expected map still matches that of the enumerable. |
3972 // If not just deoptimize. | 3972 // If not just deoptimize. |
3973 AddInstruction(new(zone()) HCheckMapValue( | 3973 AddInstruction(new(zone()) HCheckMapValue( |
3974 environment()->ExpressionStackAt(4), | 3974 environment()->ExpressionStackAt(4), |
3975 environment()->ExpressionStackAt(3))); | 3975 environment()->ExpressionStackAt(3))); |
3976 | 3976 |
3977 Bind(each_var, key); | 3977 Bind(each_var, key); |
3978 | 3978 |
3979 BreakAndContinueInfo break_info(stmt, 5); | 3979 BreakAndContinueInfo break_info(stmt, 5); |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4250 int* max_properties, | 4250 int* max_properties, |
4251 int* total_size) { | 4251 int* total_size) { |
4252 ASSERT(max_depth >= 0 && *max_properties >= 0); | 4252 ASSERT(max_depth >= 0 && *max_properties >= 0); |
4253 if (max_depth == 0) return false; | 4253 if (max_depth == 0) return false; |
4254 | 4254 |
4255 Handle<FixedArrayBase> elements(boilerplate->elements()); | 4255 Handle<FixedArrayBase> elements(boilerplate->elements()); |
4256 if (elements->length() > 0 && | 4256 if (elements->length() > 0 && |
4257 elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) { | 4257 elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) { |
4258 if (boilerplate->HasFastDoubleElements()) { | 4258 if (boilerplate->HasFastDoubleElements()) { |
4259 *total_size += FixedDoubleArray::SizeFor(elements->length()); | 4259 *total_size += FixedDoubleArray::SizeFor(elements->length()); |
4260 } else if (boilerplate->HasFastElements()) { | 4260 } else if (boilerplate->HasFastObjectElements()) { |
4261 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 4261 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
4262 int length = elements->length(); | 4262 int length = elements->length(); |
4263 for (int i = 0; i < length; i++) { | 4263 for (int i = 0; i < length; i++) { |
4264 if ((*max_properties)-- == 0) return false; | 4264 if ((*max_properties)-- == 0) return false; |
4265 Handle<Object> value(fast_elements->get(i)); | 4265 Handle<Object> value(fast_elements->get(i)); |
4266 if (value->IsJSObject()) { | 4266 if (value->IsJSObject()) { |
4267 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 4267 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
4268 if (!IsFastLiteral(value_object, | 4268 if (!IsFastLiteral(value_object, |
4269 max_depth - 1, | 4269 max_depth - 1, |
4270 max_properties, | 4270 max_properties, |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4457 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); | 4457 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); |
4458 | 4458 |
4459 elements = new(zone()) HLoadElements(literal); | 4459 elements = new(zone()) HLoadElements(literal); |
4460 AddInstruction(elements); | 4460 AddInstruction(elements); |
4461 | 4461 |
4462 HValue* key = AddInstruction( | 4462 HValue* key = AddInstruction( |
4463 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), | 4463 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), |
4464 Representation::Integer32())); | 4464 Representation::Integer32())); |
4465 | 4465 |
4466 switch (boilerplate_elements_kind) { | 4466 switch (boilerplate_elements_kind) { |
4467 case FAST_SMI_ONLY_ELEMENTS: | 4467 case FAST_SMI_ELEMENTS: |
| 4468 case FAST_HOLEY_SMI_ELEMENTS: |
4468 // Smi-only arrays need a smi check. | 4469 // Smi-only arrays need a smi check. |
4469 AddInstruction(new(zone()) HCheckSmi(value)); | 4470 AddInstruction(new(zone()) HCheckSmi(value)); |
4470 // Fall through. | 4471 // Fall through. |
4471 case FAST_ELEMENTS: | 4472 case FAST_ELEMENTS: |
| 4473 case FAST_HOLEY_ELEMENTS: |
4472 AddInstruction(new(zone()) HStoreKeyedFastElement( | 4474 AddInstruction(new(zone()) HStoreKeyedFastElement( |
4473 elements, | 4475 elements, |
4474 key, | 4476 key, |
4475 value, | 4477 value, |
4476 boilerplate_elements_kind)); | 4478 boilerplate_elements_kind)); |
4477 break; | 4479 break; |
4478 case FAST_DOUBLE_ELEMENTS: | 4480 case FAST_DOUBLE_ELEMENTS: |
| 4481 case FAST_HOLEY_DOUBLE_ELEMENTS: |
4479 AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements, | 4482 AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements, |
4480 key, | 4483 key, |
4481 value)); | 4484 value)); |
4482 break; | 4485 break; |
4483 default: | 4486 default: |
4484 UNREACHABLE(); | 4487 UNREACHABLE(); |
4485 break; | 4488 break; |
4486 } | 4489 } |
4487 | 4490 |
4488 AddSimulate(expr->GetIdForElement(i)); | 4491 AddSimulate(expr->GetIdForElement(i)); |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5226 val, | 5229 val, |
5227 Representation::Integer32(), | 5230 Representation::Integer32(), |
5228 true, // Truncate to int32. | 5231 true, // Truncate to int32. |
5229 false)); // Don't deoptimize undefined (irrelevant here). | 5232 false)); // Don't deoptimize undefined (irrelevant here). |
5230 } | 5233 } |
5231 break; | 5234 break; |
5232 } | 5235 } |
5233 case EXTERNAL_FLOAT_ELEMENTS: | 5236 case EXTERNAL_FLOAT_ELEMENTS: |
5234 case EXTERNAL_DOUBLE_ELEMENTS: | 5237 case EXTERNAL_DOUBLE_ELEMENTS: |
5235 break; | 5238 break; |
5236 case FAST_SMI_ONLY_ELEMENTS: | 5239 case FAST_SMI_ELEMENTS: |
5237 case FAST_ELEMENTS: | 5240 case FAST_ELEMENTS: |
5238 case FAST_DOUBLE_ELEMENTS: | 5241 case FAST_DOUBLE_ELEMENTS: |
| 5242 case FAST_HOLEY_SMI_ELEMENTS: |
| 5243 case FAST_HOLEY_ELEMENTS: |
| 5244 case FAST_HOLEY_DOUBLE_ELEMENTS: |
5239 case DICTIONARY_ELEMENTS: | 5245 case DICTIONARY_ELEMENTS: |
5240 case NON_STRICT_ARGUMENTS_ELEMENTS: | 5246 case NON_STRICT_ARGUMENTS_ELEMENTS: |
5241 UNREACHABLE(); | 5247 UNREACHABLE(); |
5242 break; | 5248 break; |
5243 } | 5249 } |
5244 return new(zone()) HStoreKeyedSpecializedArrayElement( | 5250 return new(zone()) HStoreKeyedSpecializedArrayElement( |
5245 external_elements, checked_key, val, elements_kind); | 5251 external_elements, checked_key, val, elements_kind); |
5246 } else { | 5252 } else { |
5247 ASSERT(val == NULL); | 5253 ASSERT(val == NULL); |
5248 return new(zone()) HLoadKeyedSpecializedArrayElement( | 5254 return new(zone()) HLoadKeyedSpecializedArrayElement( |
5249 external_elements, checked_key, elements_kind); | 5255 external_elements, checked_key, elements_kind); |
5250 } | 5256 } |
5251 } | 5257 } |
5252 | 5258 |
5253 | 5259 |
5254 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, | 5260 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, |
5255 HValue* checked_key, | 5261 HValue* checked_key, |
5256 HValue* val, | 5262 HValue* val, |
5257 ElementsKind elements_kind, | 5263 ElementsKind elements_kind, |
5258 bool is_store) { | 5264 bool is_store) { |
5259 if (is_store) { | 5265 if (is_store) { |
5260 ASSERT(val != NULL); | 5266 ASSERT(val != NULL); |
5261 switch (elements_kind) { | 5267 switch (elements_kind) { |
5262 case FAST_DOUBLE_ELEMENTS: | 5268 case FAST_DOUBLE_ELEMENTS: |
| 5269 case FAST_HOLEY_DOUBLE_ELEMENTS: |
5263 return new(zone()) HStoreKeyedFastDoubleElement( | 5270 return new(zone()) HStoreKeyedFastDoubleElement( |
5264 elements, checked_key, val); | 5271 elements, checked_key, val); |
5265 case FAST_SMI_ONLY_ELEMENTS: | 5272 case FAST_SMI_ELEMENTS: |
| 5273 case FAST_HOLEY_SMI_ELEMENTS: |
5266 // Smi-only arrays need a smi check. | 5274 // Smi-only arrays need a smi check. |
5267 AddInstruction(new(zone()) HCheckSmi(val)); | 5275 AddInstruction(new(zone()) HCheckSmi(val)); |
5268 // Fall through. | 5276 // Fall through. |
5269 case FAST_ELEMENTS: | 5277 case FAST_ELEMENTS: |
| 5278 case FAST_HOLEY_ELEMENTS: |
5270 return new(zone()) HStoreKeyedFastElement( | 5279 return new(zone()) HStoreKeyedFastElement( |
5271 elements, checked_key, val, elements_kind); | 5280 elements, checked_key, val, elements_kind); |
5272 default: | 5281 default: |
5273 UNREACHABLE(); | 5282 UNREACHABLE(); |
5274 return NULL; | 5283 return NULL; |
5275 } | 5284 } |
5276 } | 5285 } |
5277 // It's an element load (!is_store). | 5286 // It's an element load (!is_store). |
5278 if (elements_kind == FAST_DOUBLE_ELEMENTS) { | 5287 HoleCheckMode mode = IsFastPackedElementsKind(elements_kind) ? |
5279 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key); | 5288 OMIT_HOLE_CHECK : |
5280 } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS. | 5289 PERFORM_HOLE_CHECK; |
5281 return new(zone()) HLoadKeyedFastElement(elements, checked_key); | 5290 if (IsFastDoubleElementsKind(elements_kind)) { |
| 5291 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key, mode); |
| 5292 } else { // Smi or Object elements. |
| 5293 return new(zone()) HLoadKeyedFastElement(elements, checked_key, mode); |
5282 } | 5294 } |
5283 } | 5295 } |
5284 | 5296 |
5285 | 5297 |
5286 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, | 5298 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, |
5287 HValue* key, | 5299 HValue* key, |
5288 HValue* val, | 5300 HValue* val, |
| 5301 HValue* dependency, |
5289 Handle<Map> map, | 5302 Handle<Map> map, |
5290 bool is_store) { | 5303 bool is_store) { |
5291 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMaps(object, map)); | 5304 HInstruction* mapcheck = |
5292 bool fast_smi_only_elements = map->has_fast_smi_only_elements(); | 5305 AddInstruction(new(zone()) HCheckMaps(object, map, dependency)); |
5293 bool fast_elements = map->has_fast_elements(); | 5306 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
| 5307 // on a HElementsTransition instruction. The flag can also be removed if the |
| 5308 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
| 5309 // ElementsKind transitions. Finally, the dependency can be removed for stores |
| 5310 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
| 5311 // generated store code. |
| 5312 if (dependency || |
| 5313 (map->elements_kind() == FAST_HOLEY_ELEMENTS) || |
| 5314 (map->elements_kind() == FAST_ELEMENTS && is_store)) { |
| 5315 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
| 5316 } |
| 5317 bool fast_smi_only_elements = map->has_fast_smi_elements(); |
| 5318 bool fast_elements = map->has_fast_object_elements(); |
5294 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); | 5319 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
5295 if (is_store && (fast_elements || fast_smi_only_elements)) { | 5320 if (is_store && (fast_elements || fast_smi_only_elements)) { |
5296 AddInstruction(new(zone()) HCheckMaps( | 5321 HCheckMaps* check_cow_map = new(zone()) HCheckMaps( |
5297 elements, isolate()->factory()->fixed_array_map())); | 5322 elements, isolate()->factory()->fixed_array_map()); |
| 5323 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 5324 AddInstruction(check_cow_map); |
5298 } | 5325 } |
5299 HInstruction* length = NULL; | 5326 HInstruction* length = NULL; |
5300 HInstruction* checked_key = NULL; | 5327 HInstruction* checked_key = NULL; |
5301 if (map->has_external_array_elements()) { | 5328 if (map->has_external_array_elements()) { |
5302 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 5329 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
5303 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 5330 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
5304 HLoadExternalArrayPointer* external_elements = | 5331 HLoadExternalArrayPointer* external_elements = |
5305 new(zone()) HLoadExternalArrayPointer(elements); | 5332 new(zone()) HLoadExternalArrayPointer(elements); |
5306 AddInstruction(external_elements); | 5333 AddInstruction(external_elements); |
5307 return BuildExternalArrayElementAccess(external_elements, checked_key, | 5334 return BuildExternalArrayElementAccess(external_elements, checked_key, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5340 type_todo[i] = false; | 5367 type_todo[i] = false; |
5341 } | 5368 } |
5342 | 5369 |
5343 // Elements_kind transition support. | 5370 // Elements_kind transition support. |
5344 MapHandleList transition_target(maps->length()); | 5371 MapHandleList transition_target(maps->length()); |
5345 // Collect possible transition targets. | 5372 // Collect possible transition targets. |
5346 MapHandleList possible_transitioned_maps(maps->length()); | 5373 MapHandleList possible_transitioned_maps(maps->length()); |
5347 for (int i = 0; i < maps->length(); ++i) { | 5374 for (int i = 0; i < maps->length(); ++i) { |
5348 Handle<Map> map = maps->at(i); | 5375 Handle<Map> map = maps->at(i); |
5349 ElementsKind elements_kind = map->elements_kind(); | 5376 ElementsKind elements_kind = map->elements_kind(); |
5350 if (elements_kind == FAST_DOUBLE_ELEMENTS || | 5377 if (IsFastElementsKind(elements_kind) && |
5351 elements_kind == FAST_ELEMENTS) { | 5378 elements_kind != GetInitialFastElementsKind()) { |
5352 possible_transitioned_maps.Add(map); | 5379 possible_transitioned_maps.Add(map); |
5353 } | 5380 } |
5354 } | 5381 } |
5355 // Get transition target for each map (NULL == no transition). | 5382 // Get transition target for each map (NULL == no transition). |
5356 for (int i = 0; i < maps->length(); ++i) { | 5383 for (int i = 0; i < maps->length(); ++i) { |
5357 Handle<Map> map = maps->at(i); | 5384 Handle<Map> map = maps->at(i); |
5358 Handle<Map> transitioned_map = | 5385 Handle<Map> transitioned_map = |
5359 map->FindTransitionedMap(&possible_transitioned_maps); | 5386 map->FindTransitionedMap(&possible_transitioned_maps); |
5360 transition_target.Add(transitioned_map); | 5387 transition_target.Add(transitioned_map); |
5361 } | 5388 } |
5362 | 5389 |
5363 int num_untransitionable_maps = 0; | 5390 int num_untransitionable_maps = 0; |
5364 Handle<Map> untransitionable_map; | 5391 Handle<Map> untransitionable_map; |
| 5392 HTransitionElementsKind* transition = NULL; |
5365 for (int i = 0; i < maps->length(); ++i) { | 5393 for (int i = 0; i < maps->length(); ++i) { |
5366 Handle<Map> map = maps->at(i); | 5394 Handle<Map> map = maps->at(i); |
5367 ASSERT(map->IsMap()); | 5395 ASSERT(map->IsMap()); |
5368 if (!transition_target.at(i).is_null()) { | 5396 if (!transition_target.at(i).is_null()) { |
5369 AddInstruction(new(zone()) HTransitionElementsKind( | 5397 ASSERT(Map::IsValidElementsTransition( |
5370 object, map, transition_target.at(i))); | 5398 map->elements_kind(), |
| 5399 transition_target.at(i)->elements_kind())); |
| 5400 transition = new(zone()) HTransitionElementsKind( |
| 5401 object, map, transition_target.at(i)); |
| 5402 AddInstruction(transition); |
5371 } else { | 5403 } else { |
5372 type_todo[map->elements_kind()] = true; | 5404 type_todo[map->elements_kind()] = true; |
5373 if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { | 5405 if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { |
5374 todo_external_array = true; | 5406 todo_external_array = true; |
5375 } | 5407 } |
5376 num_untransitionable_maps++; | 5408 num_untransitionable_maps++; |
5377 untransitionable_map = map; | 5409 untransitionable_map = map; |
5378 } | 5410 } |
5379 } | 5411 } |
5380 | 5412 |
5381 // If only one map is left after transitioning, handle this case | 5413 // If only one map is left after transitioning, handle this case |
5382 // monomorphically. | 5414 // monomorphically. |
5383 if (num_untransitionable_maps == 1) { | 5415 if (num_untransitionable_maps == 1) { |
5384 HInstruction* instr = NULL; | 5416 HInstruction* instr = NULL; |
5385 if (untransitionable_map->has_slow_elements_kind()) { | 5417 if (untransitionable_map->has_slow_elements_kind()) { |
5386 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) | 5418 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) |
5387 : BuildLoadKeyedGeneric(object, key)); | 5419 : BuildLoadKeyedGeneric(object, key)); |
5388 } else { | 5420 } else { |
5389 instr = AddInstruction(BuildMonomorphicElementAccess( | 5421 instr = AddInstruction(BuildMonomorphicElementAccess( |
5390 object, key, val, untransitionable_map, is_store)); | 5422 object, key, val, transition, untransitionable_map, is_store)); |
5391 } | 5423 } |
5392 *has_side_effects |= instr->HasObservableSideEffects(); | 5424 *has_side_effects |= instr->HasObservableSideEffects(); |
5393 instr->set_position(position); | 5425 instr->set_position(position); |
5394 return is_store ? NULL : instr; | 5426 return is_store ? NULL : instr; |
5395 } | 5427 } |
5396 | 5428 |
5397 AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); | 5429 AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); |
5398 HBasicBlock* join = graph()->CreateBasicBlock(); | 5430 HBasicBlock* join = graph()->CreateBasicBlock(); |
5399 | 5431 |
5400 HInstruction* elements_kind_instr = | 5432 HInstruction* elements_kind_instr = |
5401 AddInstruction(new(zone()) HElementsKind(object)); | 5433 AddInstruction(new(zone()) HElementsKind(object)); |
5402 HCompareConstantEqAndBranch* elements_kind_branch = NULL; | 5434 HCompareConstantEqAndBranch* elements_kind_branch = NULL; |
5403 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); | 5435 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
5404 HLoadExternalArrayPointer* external_elements = NULL; | 5436 HLoadExternalArrayPointer* external_elements = NULL; |
5405 HInstruction* checked_key = NULL; | 5437 HInstruction* checked_key = NULL; |
5406 | 5438 |
5407 // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS, | 5439 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds |
5408 // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS are handled before external | 5440 // are handled before external arrays. |
5409 // arrays. | 5441 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5410 STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5442 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5411 STATIC_ASSERT(FAST_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | |
5412 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5443 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5413 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5444 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5414 | 5445 |
5415 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; | 5446 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; |
5416 elements_kind <= LAST_ELEMENTS_KIND; | 5447 elements_kind <= LAST_ELEMENTS_KIND; |
5417 elements_kind = ElementsKind(elements_kind + 1)) { | 5448 elements_kind = ElementsKind(elements_kind + 1)) { |
5418 // After having handled FAST_ELEMENTS, FAST_SMI_ONLY_ELEMENTS, | 5449 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some |
5419 // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS, we need to add some code | 5450 // code that's executed for all external array cases. |
5420 // that's executed for all external array cases. | |
5421 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == | 5451 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == |
5422 LAST_ELEMENTS_KIND); | 5452 LAST_ELEMENTS_KIND); |
5423 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND | 5453 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND |
5424 && todo_external_array) { | 5454 && todo_external_array) { |
5425 HInstruction* length = | 5455 HInstruction* length = |
5426 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 5456 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
5427 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 5457 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
5428 external_elements = new(zone()) HLoadExternalArrayPointer(elements); | 5458 external_elements = new(zone()) HLoadExternalArrayPointer(elements); |
5429 AddInstruction(external_elements); | 5459 AddInstruction(external_elements); |
5430 } | 5460 } |
5431 if (type_todo[elements_kind]) { | 5461 if (type_todo[elements_kind]) { |
5432 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5462 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
5433 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5463 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
5434 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( | 5464 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( |
5435 elements_kind_instr, elements_kind, Token::EQ_STRICT); | 5465 elements_kind_instr, elements_kind, Token::EQ_STRICT); |
5436 elements_kind_branch->SetSuccessorAt(0, if_true); | 5466 elements_kind_branch->SetSuccessorAt(0, if_true); |
5437 elements_kind_branch->SetSuccessorAt(1, if_false); | 5467 elements_kind_branch->SetSuccessorAt(1, if_false); |
5438 current_block()->Finish(elements_kind_branch); | 5468 current_block()->Finish(elements_kind_branch); |
5439 | 5469 |
5440 set_current_block(if_true); | 5470 set_current_block(if_true); |
5441 HInstruction* access; | 5471 HInstruction* access; |
5442 if (elements_kind == FAST_SMI_ONLY_ELEMENTS || | 5472 if (IsFastElementsKind(elements_kind)) { |
5443 elements_kind == FAST_ELEMENTS || | 5473 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { |
5444 elements_kind == FAST_DOUBLE_ELEMENTS) { | |
5445 if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) { | |
5446 AddInstruction(new(zone()) HCheckMaps( | 5474 AddInstruction(new(zone()) HCheckMaps( |
5447 elements, isolate()->factory()->fixed_array_map(), | 5475 elements, isolate()->factory()->fixed_array_map(), |
5448 elements_kind_branch)); | 5476 elements_kind_branch)); |
5449 } | 5477 } |
5450 // TODO(jkummerow): The need for these two blocks could be avoided | 5478 // TODO(jkummerow): The need for these two blocks could be avoided |
5451 // in one of two ways: | 5479 // in one of two ways: |
5452 // (1) Introduce ElementsKinds for JSArrays that are distinct from | 5480 // (1) Introduce ElementsKinds for JSArrays that are distinct from |
5453 // those for fast objects. | 5481 // those for fast objects. |
5454 // (2) Put the common instructions into a third "join" block. This | 5482 // (2) Put the common instructions into a third "join" block. This |
5455 // requires additional AST IDs that we can deopt to from inside | 5483 // requires additional AST IDs that we can deopt to from inside |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5522 bool* has_side_effects) { | 5550 bool* has_side_effects) { |
5523 ASSERT(!expr->IsPropertyName()); | 5551 ASSERT(!expr->IsPropertyName()); |
5524 HInstruction* instr = NULL; | 5552 HInstruction* instr = NULL; |
5525 if (expr->IsMonomorphic()) { | 5553 if (expr->IsMonomorphic()) { |
5526 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 5554 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
5527 if (map->has_slow_elements_kind()) { | 5555 if (map->has_slow_elements_kind()) { |
5528 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 5556 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
5529 : BuildLoadKeyedGeneric(obj, key); | 5557 : BuildLoadKeyedGeneric(obj, key); |
5530 } else { | 5558 } else { |
5531 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 5559 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
5532 instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store); | 5560 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); |
5533 } | 5561 } |
5534 } else if (expr->GetReceiverTypes() != NULL && | 5562 } else if (expr->GetReceiverTypes() != NULL && |
5535 !expr->GetReceiverTypes()->is_empty()) { | 5563 !expr->GetReceiverTypes()->is_empty()) { |
5536 return HandlePolymorphicElementAccess( | 5564 return HandlePolymorphicElementAccess( |
5537 obj, key, val, expr, ast_id, position, is_store, has_side_effects); | 5565 obj, key, val, expr, ast_id, position, is_store, has_side_effects); |
5538 } else { | 5566 } else { |
5539 if (is_store) { | 5567 if (is_store) { |
5540 instr = BuildStoreKeyedGeneric(obj, key, val); | 5568 instr = BuildStoreKeyedGeneric(obj, key, val); |
5541 } else { | 5569 } else { |
5542 instr = BuildLoadKeyedGeneric(obj, key); | 5570 instr = BuildLoadKeyedGeneric(obj, key); |
(...skipping 3394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8937 } | 8965 } |
8938 } | 8966 } |
8939 | 8967 |
8940 #ifdef DEBUG | 8968 #ifdef DEBUG |
8941 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 8969 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
8942 if (allocator_ != NULL) allocator_->Verify(); | 8970 if (allocator_ != NULL) allocator_->Verify(); |
8943 #endif | 8971 #endif |
8944 } | 8972 } |
8945 | 8973 |
8946 } } // namespace v8::internal | 8974 } } // namespace v8::internal |
OLD | NEW |