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

Side by Side Diff: src/hydrogen.cc

Issue 10170030: Implement tracking and optimizations of packed arrays (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: ia32 ready to go Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698