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

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: Review feedback 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
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2220 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698