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 2135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3874 | 3874 |
3875 set_current_block(loop_successor); | 3875 set_current_block(loop_successor); |
3876 Drop(5); | 3876 Drop(5); |
3877 | 3877 |
3878 set_current_block(loop_body); | 3878 set_current_block(loop_body); |
3879 | 3879 |
3880 HValue* key = AddInstruction( | 3880 HValue* key = AddInstruction( |
3881 new(zone()) HLoadKeyedFastElement( | 3881 new(zone()) HLoadKeyedFastElement( |
3882 environment()->ExpressionStackAt(2), // Enum cache. | 3882 environment()->ExpressionStackAt(2), // Enum cache. |
3883 environment()->ExpressionStackAt(0), // Iteration index. | 3883 environment()->ExpressionStackAt(0), // Iteration index. |
3884 HLoadKeyedFastElement::OMIT_HOLE_CHECK)); | 3884 OMIT_HOLE_CHECK)); |
3885 | 3885 |
3886 // Check if the expected map still matches that of the enumerable. | 3886 // Check if the expected map still matches that of the enumerable. |
3887 // If not just deoptimize. | 3887 // If not just deoptimize. |
3888 AddInstruction(new(zone()) HCheckMapValue( | 3888 AddInstruction(new(zone()) HCheckMapValue( |
3889 environment()->ExpressionStackAt(4), | 3889 environment()->ExpressionStackAt(4), |
3890 environment()->ExpressionStackAt(3))); | 3890 environment()->ExpressionStackAt(3))); |
3891 | 3891 |
3892 Bind(each_var, key); | 3892 Bind(each_var, key); |
3893 | 3893 |
3894 BreakAndContinueInfo break_info(stmt, 5); | 3894 BreakAndContinueInfo break_info(stmt, 5); |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4165 int* max_properties, | 4165 int* max_properties, |
4166 int* total_size) { | 4166 int* total_size) { |
4167 ASSERT(max_depth >= 0 && *max_properties >= 0); | 4167 ASSERT(max_depth >= 0 && *max_properties >= 0); |
4168 if (max_depth == 0) return false; | 4168 if (max_depth == 0) return false; |
4169 | 4169 |
4170 Handle<FixedArrayBase> elements(boilerplate->elements()); | 4170 Handle<FixedArrayBase> elements(boilerplate->elements()); |
4171 if (elements->length() > 0 && | 4171 if (elements->length() > 0 && |
4172 elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) { | 4172 elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) { |
4173 if (boilerplate->HasFastDoubleElements()) { | 4173 if (boilerplate->HasFastDoubleElements()) { |
4174 *total_size += FixedDoubleArray::SizeFor(elements->length()); | 4174 *total_size += FixedDoubleArray::SizeFor(elements->length()); |
4175 } else if (boilerplate->HasFastElements()) { | 4175 } else if (boilerplate->HasFastObjectElements()) { |
4176 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 4176 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
4177 int length = elements->length(); | 4177 int length = elements->length(); |
4178 for (int i = 0; i < length; i++) { | 4178 for (int i = 0; i < length; i++) { |
4179 if ((*max_properties)-- == 0) return false; | 4179 if ((*max_properties)-- == 0) return false; |
4180 Handle<Object> value(fast_elements->get(i)); | 4180 Handle<Object> value(fast_elements->get(i)); |
4181 if (value->IsJSObject()) { | 4181 if (value->IsJSObject()) { |
4182 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 4182 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
4183 if (!IsFastLiteral(value_object, | 4183 if (!IsFastLiteral(value_object, |
4184 max_depth - 1, | 4184 max_depth - 1, |
4185 max_properties, | 4185 max_properties, |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4372 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); | 4372 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); |
4373 | 4373 |
4374 elements = new(zone()) HLoadElements(literal); | 4374 elements = new(zone()) HLoadElements(literal); |
4375 AddInstruction(elements); | 4375 AddInstruction(elements); |
4376 | 4376 |
4377 HValue* key = AddInstruction( | 4377 HValue* key = AddInstruction( |
4378 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), | 4378 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), |
4379 Representation::Integer32())); | 4379 Representation::Integer32())); |
4380 | 4380 |
4381 switch (boilerplate_elements_kind) { | 4381 switch (boilerplate_elements_kind) { |
4382 case FAST_SMI_ONLY_ELEMENTS: | 4382 case FAST_SMI_ELEMENTS: |
4383 case FAST_HOLEY_SMI_ELEMENTS: | |
4383 // Smi-only arrays need a smi check. | 4384 // Smi-only arrays need a smi check. |
4384 AddInstruction(new(zone()) HCheckSmi(value)); | 4385 AddInstruction(new(zone()) HCheckSmi(value)); |
4385 // Fall through. | 4386 // Fall through. |
4386 case FAST_ELEMENTS: | 4387 case FAST_ELEMENTS: |
4388 case FAST_HOLEY_ELEMENTS: | |
4387 AddInstruction(new(zone()) HStoreKeyedFastElement( | 4389 AddInstruction(new(zone()) HStoreKeyedFastElement( |
4388 elements, | 4390 elements, |
4389 key, | 4391 key, |
4390 value, | 4392 value, |
4391 boilerplate_elements_kind)); | 4393 boilerplate_elements_kind)); |
4392 break; | 4394 break; |
4393 case FAST_DOUBLE_ELEMENTS: | 4395 case FAST_DOUBLE_ELEMENTS: |
4396 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
4394 AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements, | 4397 AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements, |
4395 key, | 4398 key, |
4396 value)); | 4399 value)); |
4397 break; | 4400 break; |
4398 default: | 4401 default: |
4399 UNREACHABLE(); | 4402 UNREACHABLE(); |
4400 break; | 4403 break; |
4401 } | 4404 } |
4402 | 4405 |
4403 AddSimulate(expr->GetIdForElement(i)); | 4406 AddSimulate(expr->GetIdForElement(i)); |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5141 val, | 5144 val, |
5142 Representation::Integer32(), | 5145 Representation::Integer32(), |
5143 true, // Truncate to int32. | 5146 true, // Truncate to int32. |
5144 false)); // Don't deoptimize undefined (irrelevant here). | 5147 false)); // Don't deoptimize undefined (irrelevant here). |
5145 } | 5148 } |
5146 break; | 5149 break; |
5147 } | 5150 } |
5148 case EXTERNAL_FLOAT_ELEMENTS: | 5151 case EXTERNAL_FLOAT_ELEMENTS: |
5149 case EXTERNAL_DOUBLE_ELEMENTS: | 5152 case EXTERNAL_DOUBLE_ELEMENTS: |
5150 break; | 5153 break; |
5151 case FAST_SMI_ONLY_ELEMENTS: | 5154 case FAST_SMI_ELEMENTS: |
5152 case FAST_ELEMENTS: | 5155 case FAST_ELEMENTS: |
5153 case FAST_DOUBLE_ELEMENTS: | 5156 case FAST_DOUBLE_ELEMENTS: |
5157 case FAST_HOLEY_SMI_ELEMENTS: | |
5158 case FAST_HOLEY_ELEMENTS: | |
5159 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
5154 case DICTIONARY_ELEMENTS: | 5160 case DICTIONARY_ELEMENTS: |
5155 case NON_STRICT_ARGUMENTS_ELEMENTS: | 5161 case NON_STRICT_ARGUMENTS_ELEMENTS: |
5156 UNREACHABLE(); | 5162 UNREACHABLE(); |
5157 break; | 5163 break; |
5158 } | 5164 } |
5159 return new(zone()) HStoreKeyedSpecializedArrayElement( | 5165 return new(zone()) HStoreKeyedSpecializedArrayElement( |
5160 external_elements, checked_key, val, elements_kind); | 5166 external_elements, checked_key, val, elements_kind); |
5161 } else { | 5167 } else { |
5162 ASSERT(val == NULL); | 5168 ASSERT(val == NULL); |
5163 return new(zone()) HLoadKeyedSpecializedArrayElement( | 5169 return new(zone()) HLoadKeyedSpecializedArrayElement( |
5164 external_elements, checked_key, elements_kind); | 5170 external_elements, checked_key, elements_kind); |
5165 } | 5171 } |
5166 } | 5172 } |
5167 | 5173 |
5168 | 5174 |
5169 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, | 5175 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, |
5170 HValue* checked_key, | 5176 HValue* checked_key, |
5171 HValue* val, | 5177 HValue* val, |
5172 ElementsKind elements_kind, | 5178 ElementsKind elements_kind, |
5173 bool is_store) { | 5179 bool is_store) { |
5174 if (is_store) { | 5180 if (is_store) { |
5175 ASSERT(val != NULL); | 5181 ASSERT(val != NULL); |
5176 switch (elements_kind) { | 5182 switch (elements_kind) { |
5177 case FAST_DOUBLE_ELEMENTS: | 5183 case FAST_DOUBLE_ELEMENTS: |
5184 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
5178 return new(zone()) HStoreKeyedFastDoubleElement( | 5185 return new(zone()) HStoreKeyedFastDoubleElement( |
5179 elements, checked_key, val); | 5186 elements, checked_key, val); |
5180 case FAST_SMI_ONLY_ELEMENTS: | 5187 case FAST_SMI_ELEMENTS: |
5188 case FAST_HOLEY_SMI_ELEMENTS: | |
5181 // Smi-only arrays need a smi check. | 5189 // Smi-only arrays need a smi check. |
5182 AddInstruction(new(zone()) HCheckSmi(val)); | 5190 AddInstruction(new(zone()) HCheckSmi(val)); |
5183 // Fall through. | 5191 // Fall through. |
5184 case FAST_ELEMENTS: | 5192 case FAST_ELEMENTS: |
5193 case FAST_HOLEY_ELEMENTS: | |
5185 return new(zone()) HStoreKeyedFastElement( | 5194 return new(zone()) HStoreKeyedFastElement( |
5186 elements, checked_key, val, elements_kind); | 5195 elements, checked_key, val, elements_kind); |
5187 default: | 5196 default: |
5188 UNREACHABLE(); | 5197 UNREACHABLE(); |
5189 return NULL; | 5198 return NULL; |
5190 } | 5199 } |
5191 } | 5200 } |
5192 // It's an element load (!is_store). | 5201 // It's an element load (!is_store). |
5193 if (elements_kind == FAST_DOUBLE_ELEMENTS) { | 5202 HoleCheckMode mode = IsFastPackedElementsKind(elements_kind) ? |
5194 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key); | 5203 OMIT_HOLE_CHECK : |
5195 } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS. | 5204 PERFORM_HOLE_CHECK; |
5196 return new(zone()) HLoadKeyedFastElement(elements, checked_key); | 5205 if (IsFastDoubleElementsKind(elements_kind)) { |
5206 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key, mode); | |
5207 } else { // Smi or Object elements. | |
5208 return new(zone()) HLoadKeyedFastElement(elements, checked_key, mode); | |
5197 } | 5209 } |
5198 } | 5210 } |
5199 | 5211 |
5200 | 5212 |
5201 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, | 5213 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, |
5202 HValue* key, | 5214 HValue* key, |
5203 HValue* val, | 5215 HValue* val, |
5216 HValue* dependency, | |
5204 Handle<Map> map, | 5217 Handle<Map> map, |
5205 bool is_store) { | 5218 bool is_store) { |
5206 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMaps(object, map)); | 5219 HInstruction* mapcheck = AddInstruction(new(zone()) |
Jakob Kummerow
2012/05/13 21:55:27
nit: I'd break the line after "AddInstruction("
danno
2012/05/22 11:05:21
Done.
| |
5207 bool fast_smi_only_elements = map->has_fast_smi_only_elements(); | 5220 HCheckMaps(object, map, dependency)); |
5208 bool fast_elements = map->has_fast_elements(); | 5221 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
5222 // on a HElementsTransition instruction. The flag can also be removed if the | |
5223 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | |
5224 // ElementsKind transitions. Finally, the dependency can be removed for stores | |
5225 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | |
5226 // generated store code. | |
5227 if (dependency || | |
5228 (map->elements_kind() == FAST_HOLEY_ELEMENTS) || | |
5229 (map->elements_kind() == FAST_ELEMENTS && is_store)) { | |
5230 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | |
5231 } | |
5232 bool fast_smi_only_elements = map->has_fast_smi_elements(); | |
5233 bool fast_elements = map->has_fast_object_elements(); | |
5209 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); | 5234 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
5210 if (is_store && (fast_elements || fast_smi_only_elements)) { | 5235 if (is_store && (fast_elements || fast_smi_only_elements)) { |
5211 AddInstruction(new(zone()) HCheckMaps( | 5236 HCheckMaps* check_cow_map = new(zone()) HCheckMaps( |
5212 elements, isolate()->factory()->fixed_array_map())); | 5237 elements, isolate()->factory()->fixed_array_map()); |
5238 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | |
5239 AddInstruction(check_cow_map); | |
5213 } | 5240 } |
5214 HInstruction* length = NULL; | 5241 HInstruction* length = NULL; |
5215 HInstruction* checked_key = NULL; | 5242 HInstruction* checked_key = NULL; |
5216 if (map->has_external_array_elements()) { | 5243 if (map->has_external_array_elements()) { |
5217 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 5244 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
5218 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 5245 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
5219 HLoadExternalArrayPointer* external_elements = | 5246 HLoadExternalArrayPointer* external_elements = |
5220 new(zone()) HLoadExternalArrayPointer(elements); | 5247 new(zone()) HLoadExternalArrayPointer(elements); |
5221 AddInstruction(external_elements); | 5248 AddInstruction(external_elements); |
5222 return BuildExternalArrayElementAccess(external_elements, checked_key, | 5249 return BuildExternalArrayElementAccess(external_elements, checked_key, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5255 type_todo[i] = false; | 5282 type_todo[i] = false; |
5256 } | 5283 } |
5257 | 5284 |
5258 // Elements_kind transition support. | 5285 // Elements_kind transition support. |
5259 MapHandleList transition_target(maps->length()); | 5286 MapHandleList transition_target(maps->length()); |
5260 // Collect possible transition targets. | 5287 // Collect possible transition targets. |
5261 MapHandleList possible_transitioned_maps(maps->length()); | 5288 MapHandleList possible_transitioned_maps(maps->length()); |
5262 for (int i = 0; i < maps->length(); ++i) { | 5289 for (int i = 0; i < maps->length(); ++i) { |
5263 Handle<Map> map = maps->at(i); | 5290 Handle<Map> map = maps->at(i); |
5264 ElementsKind elements_kind = map->elements_kind(); | 5291 ElementsKind elements_kind = map->elements_kind(); |
5265 if (elements_kind == FAST_DOUBLE_ELEMENTS || | 5292 if (IsFastElementsKind(elements_kind) && |
5266 elements_kind == FAST_ELEMENTS) { | 5293 elements_kind != GetInitialFastElementsKind()) { |
5267 possible_transitioned_maps.Add(map); | 5294 possible_transitioned_maps.Add(map); |
5268 } | 5295 } |
5269 } | 5296 } |
5270 // Get transition target for each map (NULL == no transition). | 5297 // Get transition target for each map (NULL == no transition). |
5271 for (int i = 0; i < maps->length(); ++i) { | 5298 for (int i = 0; i < maps->length(); ++i) { |
5272 Handle<Map> map = maps->at(i); | 5299 Handle<Map> map = maps->at(i); |
5273 Handle<Map> transitioned_map = | 5300 Handle<Map> transitioned_map = |
5274 map->FindTransitionedMap(&possible_transitioned_maps); | 5301 map->FindTransitionedMap(&possible_transitioned_maps); |
5275 transition_target.Add(transitioned_map); | 5302 transition_target.Add(transitioned_map); |
5276 } | 5303 } |
5277 | 5304 |
5278 int num_untransitionable_maps = 0; | 5305 int num_untransitionable_maps = 0; |
5279 Handle<Map> untransitionable_map; | 5306 Handle<Map> untransitionable_map; |
5307 HTransitionElementsKind* transition = NULL; | |
5280 for (int i = 0; i < maps->length(); ++i) { | 5308 for (int i = 0; i < maps->length(); ++i) { |
5281 Handle<Map> map = maps->at(i); | 5309 Handle<Map> map = maps->at(i); |
5282 ASSERT(map->IsMap()); | 5310 ASSERT(map->IsMap()); |
5283 if (!transition_target.at(i).is_null()) { | 5311 if (!transition_target.at(i).is_null()) { |
5284 AddInstruction(new(zone()) HTransitionElementsKind( | 5312 ASSERT(Map::IsValidElementsTransition( |
5285 object, map, transition_target.at(i))); | 5313 map->elements_kind(), |
5314 transition_target.at(i)->elements_kind())); | |
5315 transition = new(zone()) HTransitionElementsKind( | |
5316 object, map, transition_target.at(i)); | |
5317 AddInstruction(transition); | |
5286 } else { | 5318 } else { |
5287 type_todo[map->elements_kind()] = true; | 5319 type_todo[map->elements_kind()] = true; |
5288 if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { | 5320 if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { |
5289 todo_external_array = true; | 5321 todo_external_array = true; |
5290 } | 5322 } |
5291 num_untransitionable_maps++; | 5323 num_untransitionable_maps++; |
5292 untransitionable_map = map; | 5324 untransitionable_map = map; |
5293 } | 5325 } |
5294 } | 5326 } |
5295 | 5327 |
5296 // If only one map is left after transitioning, handle this case | 5328 // If only one map is left after transitioning, handle this case |
5297 // monomorphically. | 5329 // monomorphically. |
5298 if (num_untransitionable_maps == 1) { | 5330 if (num_untransitionable_maps == 1) { |
5299 HInstruction* instr = NULL; | 5331 HInstruction* instr = NULL; |
5300 if (untransitionable_map->has_slow_elements_kind()) { | 5332 if (untransitionable_map->has_slow_elements_kind()) { |
5301 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) | 5333 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) |
5302 : BuildLoadKeyedGeneric(object, key)); | 5334 : BuildLoadKeyedGeneric(object, key)); |
5303 } else { | 5335 } else { |
5304 instr = AddInstruction(BuildMonomorphicElementAccess( | 5336 instr = AddInstruction(BuildMonomorphicElementAccess( |
5305 object, key, val, untransitionable_map, is_store)); | 5337 object, key, val, transition, untransitionable_map, is_store)); |
5306 } | 5338 } |
5307 *has_side_effects |= instr->HasObservableSideEffects(); | 5339 *has_side_effects |= instr->HasObservableSideEffects(); |
5308 instr->set_position(position); | 5340 instr->set_position(position); |
5309 return is_store ? NULL : instr; | 5341 return is_store ? NULL : instr; |
5310 } | 5342 } |
5311 | 5343 |
5312 AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); | 5344 AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); |
5313 HBasicBlock* join = graph()->CreateBasicBlock(); | 5345 HBasicBlock* join = graph()->CreateBasicBlock(); |
5314 | 5346 |
5315 HInstruction* elements_kind_instr = | 5347 HInstruction* elements_kind_instr = |
5316 AddInstruction(new(zone()) HElementsKind(object)); | 5348 AddInstruction(new(zone()) HElementsKind(object)); |
5317 HCompareConstantEqAndBranch* elements_kind_branch = NULL; | 5349 HCompareConstantEqAndBranch* elements_kind_branch = NULL; |
5318 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); | 5350 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
5319 HLoadExternalArrayPointer* external_elements = NULL; | 5351 HLoadExternalArrayPointer* external_elements = NULL; |
5320 HInstruction* checked_key = NULL; | 5352 HInstruction* checked_key = NULL; |
5321 | 5353 |
5322 // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS, | 5354 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds |
5323 // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS are handled before external | 5355 // are handled before external arrays. |
5324 // arrays. | 5356 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5325 STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5357 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5326 STATIC_ASSERT(FAST_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | |
5327 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5358 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5328 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5359 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
5329 | 5360 |
5330 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; | 5361 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; |
5331 elements_kind <= LAST_ELEMENTS_KIND; | 5362 elements_kind <= LAST_ELEMENTS_KIND; |
5332 elements_kind = ElementsKind(elements_kind + 1)) { | 5363 elements_kind = ElementsKind(elements_kind + 1)) { |
5333 // After having handled FAST_ELEMENTS, FAST_SMI_ONLY_ELEMENTS, | 5364 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some |
5334 // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS, we need to add some code | 5365 // code that's executed for all external array cases. |
5335 // that's executed for all external array cases. | |
5336 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == | 5366 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == |
5337 LAST_ELEMENTS_KIND); | 5367 LAST_ELEMENTS_KIND); |
5338 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND | 5368 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND |
5339 && todo_external_array) { | 5369 && todo_external_array) { |
5340 HInstruction* length = | 5370 HInstruction* length = |
5341 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 5371 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
5342 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 5372 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
5343 external_elements = new(zone()) HLoadExternalArrayPointer(elements); | 5373 external_elements = new(zone()) HLoadExternalArrayPointer(elements); |
5344 AddInstruction(external_elements); | 5374 AddInstruction(external_elements); |
5345 } | 5375 } |
5346 if (type_todo[elements_kind]) { | 5376 if (type_todo[elements_kind]) { |
5347 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5377 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
5348 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5378 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
5349 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( | 5379 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( |
5350 elements_kind_instr, elements_kind, Token::EQ_STRICT); | 5380 elements_kind_instr, elements_kind, Token::EQ_STRICT); |
5351 elements_kind_branch->SetSuccessorAt(0, if_true); | 5381 elements_kind_branch->SetSuccessorAt(0, if_true); |
5352 elements_kind_branch->SetSuccessorAt(1, if_false); | 5382 elements_kind_branch->SetSuccessorAt(1, if_false); |
5353 current_block()->Finish(elements_kind_branch); | 5383 current_block()->Finish(elements_kind_branch); |
5354 | 5384 |
5355 set_current_block(if_true); | 5385 set_current_block(if_true); |
5356 HInstruction* access; | 5386 HInstruction* access; |
5357 if (elements_kind == FAST_SMI_ONLY_ELEMENTS || | 5387 if (IsFastElementsKind(elements_kind)) { |
5358 elements_kind == FAST_ELEMENTS || | 5388 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { |
5359 elements_kind == FAST_DOUBLE_ELEMENTS) { | |
5360 if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) { | |
5361 AddInstruction(new(zone()) HCheckMaps( | 5389 AddInstruction(new(zone()) HCheckMaps( |
5362 elements, isolate()->factory()->fixed_array_map(), | 5390 elements, isolate()->factory()->fixed_array_map(), |
5363 elements_kind_branch)); | 5391 elements_kind_branch)); |
5364 } | 5392 } |
5365 // TODO(jkummerow): The need for these two blocks could be avoided | 5393 // TODO(jkummerow): The need for these two blocks could be avoided |
5366 // in one of two ways: | 5394 // in one of two ways: |
5367 // (1) Introduce ElementsKinds for JSArrays that are distinct from | 5395 // (1) Introduce ElementsKinds for JSArrays that are distinct from |
5368 // those for fast objects. | 5396 // those for fast objects. |
5369 // (2) Put the common instructions into a third "join" block. This | 5397 // (2) Put the common instructions into a third "join" block. This |
5370 // requires additional AST IDs that we can deopt to from inside | 5398 // requires additional AST IDs that we can deopt to from inside |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5437 bool* has_side_effects) { | 5465 bool* has_side_effects) { |
5438 ASSERT(!expr->IsPropertyName()); | 5466 ASSERT(!expr->IsPropertyName()); |
5439 HInstruction* instr = NULL; | 5467 HInstruction* instr = NULL; |
5440 if (expr->IsMonomorphic()) { | 5468 if (expr->IsMonomorphic()) { |
5441 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 5469 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
5442 if (map->has_slow_elements_kind()) { | 5470 if (map->has_slow_elements_kind()) { |
5443 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 5471 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
5444 : BuildLoadKeyedGeneric(obj, key); | 5472 : BuildLoadKeyedGeneric(obj, key); |
5445 } else { | 5473 } else { |
5446 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 5474 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
5447 instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store); | 5475 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); |
5448 } | 5476 } |
5449 } else if (expr->GetReceiverTypes() != NULL && | 5477 } else if (expr->GetReceiverTypes() != NULL && |
5450 !expr->GetReceiverTypes()->is_empty()) { | 5478 !expr->GetReceiverTypes()->is_empty()) { |
5451 return HandlePolymorphicElementAccess( | 5479 return HandlePolymorphicElementAccess( |
5452 obj, key, val, expr, ast_id, position, is_store, has_side_effects); | 5480 obj, key, val, expr, ast_id, position, is_store, has_side_effects); |
5453 } else { | 5481 } else { |
5454 if (is_store) { | 5482 if (is_store) { |
5455 instr = BuildStoreKeyedGeneric(obj, key, val); | 5483 instr = BuildStoreKeyedGeneric(obj, key, val); |
5456 } else { | 5484 } else { |
5457 instr = BuildLoadKeyedGeneric(obj, key); | 5485 instr = BuildLoadKeyedGeneric(obj, key); |
(...skipping 3402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8860 } | 8888 } |
8861 } | 8889 } |
8862 | 8890 |
8863 #ifdef DEBUG | 8891 #ifdef DEBUG |
8864 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 8892 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
8865 if (allocator_ != NULL) allocator_->Verify(); | 8893 if (allocator_ != NULL) allocator_->Verify(); |
8866 #endif | 8894 #endif |
8867 } | 8895 } |
8868 | 8896 |
8869 } } // namespace v8::internal | 8897 } } // namespace v8::internal |
OLD | NEW |