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

Side by Side Diff: src/hydrogen.cc

Issue 10442015: Rollback of r11638, r11636 on trunk branch. (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: 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 an instruction that has a 1712 // hoisting wouldn't move the transition past a DependsOn of one of it's
1713 // DependsOn flag for anything it changes. 1713 // changes or any instructions that might change an objects map or
1714 // elements contents.
1715 GVNFlagSet changes = instr->ChangesFlags();
1714 GVNFlagSet hoist_depends_blockers = 1716 GVNFlagSet hoist_depends_blockers =
1715 HValue::ConvertChangesToDependsFlags(instr->ChangesFlags()); 1717 HValue::ConvertChangesToDependsFlags(changes);
1716 1718 // In addition to not hoisting transitions above other instructions that
1717 // In addition, the transition must not be hoisted above elements kind 1719 // change dependencies that the transition changes, it must not be
1718 // changes, or if the transition is destructive to the elements buffer, 1720 // hoisted above map changes and stores to an elements backing store
1719 // changes to array pointer or array contents. 1721 // that the transition might change.
1720 GVNFlagSet hoist_change_blockers; 1722 GVNFlagSet hoist_change_blockers = changes;
1721 hoist_change_blockers.Add(kChangesElementsKind); 1723 hoist_change_blockers.Add(kChangesMaps);
1722 HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr); 1724 HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr);
1723 if (trans->original_map()->has_fast_double_elements()) { 1725 if (trans->original_map()->has_fast_double_elements()) {
1724 hoist_change_blockers.Add(kChangesElementsPointer);
1725 hoist_change_blockers.Add(kChangesDoubleArrayElements); 1726 hoist_change_blockers.Add(kChangesDoubleArrayElements);
1726 } 1727 }
1727 if (trans->transitioned_map()->has_fast_double_elements()) { 1728 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 OMIT_HOLE_CHECK)); 3969 HLoadKeyedFastElement::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->HasFastObjectElements()) { 4260 } else if (boilerplate->HasFastElements()) {
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_ELEMENTS: 4467 case FAST_SMI_ONLY_ELEMENTS:
4468 case FAST_HOLEY_SMI_ELEMENTS:
4469 // Smi-only arrays need a smi check. 4468 // Smi-only arrays need a smi check.
4470 AddInstruction(new(zone()) HCheckSmi(value)); 4469 AddInstruction(new(zone()) HCheckSmi(value));
4471 // Fall through. 4470 // Fall through.
4472 case FAST_ELEMENTS: 4471 case FAST_ELEMENTS:
4473 case FAST_HOLEY_ELEMENTS:
4474 AddInstruction(new(zone()) HStoreKeyedFastElement( 4472 AddInstruction(new(zone()) HStoreKeyedFastElement(
4475 elements, 4473 elements,
4476 key, 4474 key,
4477 value, 4475 value,
4478 boilerplate_elements_kind)); 4476 boilerplate_elements_kind));
4479 break; 4477 break;
4480 case FAST_DOUBLE_ELEMENTS: 4478 case FAST_DOUBLE_ELEMENTS:
4481 case FAST_HOLEY_DOUBLE_ELEMENTS:
4482 AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements, 4479 AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements,
4483 key, 4480 key,
4484 value)); 4481 value));
4485 break; 4482 break;
4486 default: 4483 default:
4487 UNREACHABLE(); 4484 UNREACHABLE();
4488 break; 4485 break;
4489 } 4486 }
4490 4487
4491 AddSimulate(expr->GetIdForElement(i)); 4488 AddSimulate(expr->GetIdForElement(i));
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after
5229 val, 5226 val,
5230 Representation::Integer32(), 5227 Representation::Integer32(),
5231 true, // Truncate to int32. 5228 true, // Truncate to int32.
5232 false)); // Don't deoptimize undefined (irrelevant here). 5229 false)); // Don't deoptimize undefined (irrelevant here).
5233 } 5230 }
5234 break; 5231 break;
5235 } 5232 }
5236 case EXTERNAL_FLOAT_ELEMENTS: 5233 case EXTERNAL_FLOAT_ELEMENTS:
5237 case EXTERNAL_DOUBLE_ELEMENTS: 5234 case EXTERNAL_DOUBLE_ELEMENTS:
5238 break; 5235 break;
5239 case FAST_SMI_ELEMENTS: 5236 case FAST_SMI_ONLY_ELEMENTS:
5240 case FAST_ELEMENTS: 5237 case FAST_ELEMENTS:
5241 case FAST_DOUBLE_ELEMENTS: 5238 case FAST_DOUBLE_ELEMENTS:
5242 case FAST_HOLEY_SMI_ELEMENTS:
5243 case FAST_HOLEY_ELEMENTS:
5244 case FAST_HOLEY_DOUBLE_ELEMENTS:
5245 case DICTIONARY_ELEMENTS: 5239 case DICTIONARY_ELEMENTS:
5246 case NON_STRICT_ARGUMENTS_ELEMENTS: 5240 case NON_STRICT_ARGUMENTS_ELEMENTS:
5247 UNREACHABLE(); 5241 UNREACHABLE();
5248 break; 5242 break;
5249 } 5243 }
5250 return new(zone()) HStoreKeyedSpecializedArrayElement( 5244 return new(zone()) HStoreKeyedSpecializedArrayElement(
5251 external_elements, checked_key, val, elements_kind); 5245 external_elements, checked_key, val, elements_kind);
5252 } else { 5246 } else {
5253 ASSERT(val == NULL); 5247 ASSERT(val == NULL);
5254 return new(zone()) HLoadKeyedSpecializedArrayElement( 5248 return new(zone()) HLoadKeyedSpecializedArrayElement(
5255 external_elements, checked_key, elements_kind); 5249 external_elements, checked_key, elements_kind);
5256 } 5250 }
5257 } 5251 }
5258 5252
5259 5253
5260 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, 5254 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
5261 HValue* checked_key, 5255 HValue* checked_key,
5262 HValue* val, 5256 HValue* val,
5263 ElementsKind elements_kind, 5257 ElementsKind elements_kind,
5264 bool is_store) { 5258 bool is_store) {
5265 if (is_store) { 5259 if (is_store) {
5266 ASSERT(val != NULL); 5260 ASSERT(val != NULL);
5267 switch (elements_kind) { 5261 switch (elements_kind) {
5268 case FAST_DOUBLE_ELEMENTS: 5262 case FAST_DOUBLE_ELEMENTS:
5269 case FAST_HOLEY_DOUBLE_ELEMENTS:
5270 return new(zone()) HStoreKeyedFastDoubleElement( 5263 return new(zone()) HStoreKeyedFastDoubleElement(
5271 elements, checked_key, val); 5264 elements, checked_key, val);
5272 case FAST_SMI_ELEMENTS: 5265 case FAST_SMI_ONLY_ELEMENTS:
5273 case FAST_HOLEY_SMI_ELEMENTS:
5274 // Smi-only arrays need a smi check. 5266 // Smi-only arrays need a smi check.
5275 AddInstruction(new(zone()) HCheckSmi(val)); 5267 AddInstruction(new(zone()) HCheckSmi(val));
5276 // Fall through. 5268 // Fall through.
5277 case FAST_ELEMENTS: 5269 case FAST_ELEMENTS:
5278 case FAST_HOLEY_ELEMENTS:
5279 return new(zone()) HStoreKeyedFastElement( 5270 return new(zone()) HStoreKeyedFastElement(
5280 elements, checked_key, val, elements_kind); 5271 elements, checked_key, val, elements_kind);
5281 default: 5272 default:
5282 UNREACHABLE(); 5273 UNREACHABLE();
5283 return NULL; 5274 return NULL;
5284 } 5275 }
5285 } 5276 }
5286 // It's an element load (!is_store). 5277 // It's an element load (!is_store).
5287 HoleCheckMode mode = IsFastPackedElementsKind(elements_kind) ? 5278 if (elements_kind == FAST_DOUBLE_ELEMENTS) {
5288 OMIT_HOLE_CHECK : 5279 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
5289 PERFORM_HOLE_CHECK; 5280 } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS.
5290 if (IsFastDoubleElementsKind(elements_kind)) { 5281 return new(zone()) HLoadKeyedFastElement(elements, checked_key);
5291 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key, mode);
5292 } else { // Smi or Object elements.
5293 return new(zone()) HLoadKeyedFastElement(elements, checked_key, mode);
5294 } 5282 }
5295 } 5283 }
5296 5284
5297 5285
5298 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, 5286 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
5299 HValue* key, 5287 HValue* key,
5300 HValue* val, 5288 HValue* val,
5301 HValue* dependency,
5302 Handle<Map> map, 5289 Handle<Map> map,
5303 bool is_store) { 5290 bool is_store) {
5304 HInstruction* mapcheck = 5291 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMaps(object, map));
5305 AddInstruction(new(zone()) HCheckMaps(object, map, dependency)); 5292 bool fast_smi_only_elements = map->has_fast_smi_only_elements();
5306 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency 5293 bool fast_elements = map->has_fast_elements();
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();
5319 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); 5294 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
5320 if (is_store && (fast_elements || fast_smi_only_elements)) { 5295 if (is_store && (fast_elements || fast_smi_only_elements)) {
5321 HCheckMaps* check_cow_map = new(zone()) HCheckMaps( 5296 AddInstruction(new(zone()) HCheckMaps(
5322 elements, isolate()->factory()->fixed_array_map()); 5297 elements, isolate()->factory()->fixed_array_map()));
5323 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
5324 AddInstruction(check_cow_map);
5325 } 5298 }
5326 HInstruction* length = NULL; 5299 HInstruction* length = NULL;
5327 HInstruction* checked_key = NULL; 5300 HInstruction* checked_key = NULL;
5328 if (map->has_external_array_elements()) { 5301 if (map->has_external_array_elements()) {
5329 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 5302 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
5330 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 5303 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
5331 HLoadExternalArrayPointer* external_elements = 5304 HLoadExternalArrayPointer* external_elements =
5332 new(zone()) HLoadExternalArrayPointer(elements); 5305 new(zone()) HLoadExternalArrayPointer(elements);
5333 AddInstruction(external_elements); 5306 AddInstruction(external_elements);
5334 return BuildExternalArrayElementAccess(external_elements, checked_key, 5307 return BuildExternalArrayElementAccess(external_elements, checked_key,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
5367 type_todo[i] = false; 5340 type_todo[i] = false;
5368 } 5341 }
5369 5342
5370 // Elements_kind transition support. 5343 // Elements_kind transition support.
5371 MapHandleList transition_target(maps->length()); 5344 MapHandleList transition_target(maps->length());
5372 // Collect possible transition targets. 5345 // Collect possible transition targets.
5373 MapHandleList possible_transitioned_maps(maps->length()); 5346 MapHandleList possible_transitioned_maps(maps->length());
5374 for (int i = 0; i < maps->length(); ++i) { 5347 for (int i = 0; i < maps->length(); ++i) {
5375 Handle<Map> map = maps->at(i); 5348 Handle<Map> map = maps->at(i);
5376 ElementsKind elements_kind = map->elements_kind(); 5349 ElementsKind elements_kind = map->elements_kind();
5377 if (IsFastElementsKind(elements_kind) && 5350 if (elements_kind == FAST_DOUBLE_ELEMENTS ||
5378 elements_kind != GetInitialFastElementsKind()) { 5351 elements_kind == FAST_ELEMENTS) {
5379 possible_transitioned_maps.Add(map); 5352 possible_transitioned_maps.Add(map);
5380 } 5353 }
5381 } 5354 }
5382 // Get transition target for each map (NULL == no transition). 5355 // Get transition target for each map (NULL == no transition).
5383 for (int i = 0; i < maps->length(); ++i) { 5356 for (int i = 0; i < maps->length(); ++i) {
5384 Handle<Map> map = maps->at(i); 5357 Handle<Map> map = maps->at(i);
5385 Handle<Map> transitioned_map = 5358 Handle<Map> transitioned_map =
5386 map->FindTransitionedMap(&possible_transitioned_maps); 5359 map->FindTransitionedMap(&possible_transitioned_maps);
5387 transition_target.Add(transitioned_map); 5360 transition_target.Add(transitioned_map);
5388 } 5361 }
5389 5362
5390 int num_untransitionable_maps = 0; 5363 int num_untransitionable_maps = 0;
5391 Handle<Map> untransitionable_map; 5364 Handle<Map> untransitionable_map;
5392 HTransitionElementsKind* transition = NULL;
5393 for (int i = 0; i < maps->length(); ++i) { 5365 for (int i = 0; i < maps->length(); ++i) {
5394 Handle<Map> map = maps->at(i); 5366 Handle<Map> map = maps->at(i);
5395 ASSERT(map->IsMap()); 5367 ASSERT(map->IsMap());
5396 if (!transition_target.at(i).is_null()) { 5368 if (!transition_target.at(i).is_null()) {
5397 ASSERT(Map::IsValidElementsTransition( 5369 AddInstruction(new(zone()) HTransitionElementsKind(
5398 map->elements_kind(), 5370 object, map, transition_target.at(i)));
5399 transition_target.at(i)->elements_kind()));
5400 transition = new(zone()) HTransitionElementsKind(
5401 object, map, transition_target.at(i));
5402 AddInstruction(transition);
5403 } else { 5371 } else {
5404 type_todo[map->elements_kind()] = true; 5372 type_todo[map->elements_kind()] = true;
5405 if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { 5373 if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) {
5406 todo_external_array = true; 5374 todo_external_array = true;
5407 } 5375 }
5408 num_untransitionable_maps++; 5376 num_untransitionable_maps++;
5409 untransitionable_map = map; 5377 untransitionable_map = map;
5410 } 5378 }
5411 } 5379 }
5412 5380
5413 // If only one map is left after transitioning, handle this case 5381 // If only one map is left after transitioning, handle this case
5414 // monomorphically. 5382 // monomorphically.
5415 if (num_untransitionable_maps == 1) { 5383 if (num_untransitionable_maps == 1) {
5416 HInstruction* instr = NULL; 5384 HInstruction* instr = NULL;
5417 if (untransitionable_map->has_slow_elements_kind()) { 5385 if (untransitionable_map->has_slow_elements_kind()) {
5418 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 5386 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
5419 : BuildLoadKeyedGeneric(object, key)); 5387 : BuildLoadKeyedGeneric(object, key));
5420 } else { 5388 } else {
5421 instr = AddInstruction(BuildMonomorphicElementAccess( 5389 instr = AddInstruction(BuildMonomorphicElementAccess(
5422 object, key, val, transition, untransitionable_map, is_store)); 5390 object, key, val, untransitionable_map, is_store));
5423 } 5391 }
5424 *has_side_effects |= instr->HasObservableSideEffects(); 5392 *has_side_effects |= instr->HasObservableSideEffects();
5425 instr->set_position(position); 5393 instr->set_position(position);
5426 return is_store ? NULL : instr; 5394 return is_store ? NULL : instr;
5427 } 5395 }
5428 5396
5429 AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); 5397 AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
5430 HBasicBlock* join = graph()->CreateBasicBlock(); 5398 HBasicBlock* join = graph()->CreateBasicBlock();
5431 5399
5432 HInstruction* elements_kind_instr = 5400 HInstruction* elements_kind_instr =
5433 AddInstruction(new(zone()) HElementsKind(object)); 5401 AddInstruction(new(zone()) HElementsKind(object));
5434 HCompareConstantEqAndBranch* elements_kind_branch = NULL; 5402 HCompareConstantEqAndBranch* elements_kind_branch = NULL;
5435 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); 5403 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
5436 HLoadExternalArrayPointer* external_elements = NULL; 5404 HLoadExternalArrayPointer* external_elements = NULL;
5437 HInstruction* checked_key = NULL; 5405 HInstruction* checked_key = NULL;
5438 5406
5439 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds 5407 // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS,
5440 // are handled before external arrays. 5408 // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS are handled before external
5441 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5409 // arrays.
5442 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5410 STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
5411 STATIC_ASSERT(FAST_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
5443 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5412 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
5444 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5413 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
5445 5414
5446 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; 5415 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND;
5447 elements_kind <= LAST_ELEMENTS_KIND; 5416 elements_kind <= LAST_ELEMENTS_KIND;
5448 elements_kind = ElementsKind(elements_kind + 1)) { 5417 elements_kind = ElementsKind(elements_kind + 1)) {
5449 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some 5418 // After having handled FAST_ELEMENTS, FAST_SMI_ONLY_ELEMENTS,
5450 // code that's executed for all external array cases. 5419 // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS, we need to add some code
5420 // that's executed for all external array cases.
5451 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == 5421 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND ==
5452 LAST_ELEMENTS_KIND); 5422 LAST_ELEMENTS_KIND);
5453 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND 5423 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
5454 && todo_external_array) { 5424 && todo_external_array) {
5455 HInstruction* length = 5425 HInstruction* length =
5456 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 5426 AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
5457 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 5427 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
5458 external_elements = new(zone()) HLoadExternalArrayPointer(elements); 5428 external_elements = new(zone()) HLoadExternalArrayPointer(elements);
5459 AddInstruction(external_elements); 5429 AddInstruction(external_elements);
5460 } 5430 }
5461 if (type_todo[elements_kind]) { 5431 if (type_todo[elements_kind]) {
5462 HBasicBlock* if_true = graph()->CreateBasicBlock(); 5432 HBasicBlock* if_true = graph()->CreateBasicBlock();
5463 HBasicBlock* if_false = graph()->CreateBasicBlock(); 5433 HBasicBlock* if_false = graph()->CreateBasicBlock();
5464 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( 5434 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch(
5465 elements_kind_instr, elements_kind, Token::EQ_STRICT); 5435 elements_kind_instr, elements_kind, Token::EQ_STRICT);
5466 elements_kind_branch->SetSuccessorAt(0, if_true); 5436 elements_kind_branch->SetSuccessorAt(0, if_true);
5467 elements_kind_branch->SetSuccessorAt(1, if_false); 5437 elements_kind_branch->SetSuccessorAt(1, if_false);
5468 current_block()->Finish(elements_kind_branch); 5438 current_block()->Finish(elements_kind_branch);
5469 5439
5470 set_current_block(if_true); 5440 set_current_block(if_true);
5471 HInstruction* access; 5441 HInstruction* access;
5472 if (IsFastElementsKind(elements_kind)) { 5442 if (elements_kind == FAST_SMI_ONLY_ELEMENTS ||
5473 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { 5443 elements_kind == FAST_ELEMENTS ||
5444 elements_kind == FAST_DOUBLE_ELEMENTS) {
5445 if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) {
5474 AddInstruction(new(zone()) HCheckMaps( 5446 AddInstruction(new(zone()) HCheckMaps(
5475 elements, isolate()->factory()->fixed_array_map(), 5447 elements, isolate()->factory()->fixed_array_map(),
5476 elements_kind_branch)); 5448 elements_kind_branch));
5477 } 5449 }
5478 // TODO(jkummerow): The need for these two blocks could be avoided 5450 // TODO(jkummerow): The need for these two blocks could be avoided
5479 // in one of two ways: 5451 // in one of two ways:
5480 // (1) Introduce ElementsKinds for JSArrays that are distinct from 5452 // (1) Introduce ElementsKinds for JSArrays that are distinct from
5481 // those for fast objects. 5453 // those for fast objects.
5482 // (2) Put the common instructions into a third "join" block. This 5454 // (2) Put the common instructions into a third "join" block. This
5483 // requires additional AST IDs that we can deopt to from inside 5455 // requires additional AST IDs that we can deopt to from inside
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
5550 bool* has_side_effects) { 5522 bool* has_side_effects) {
5551 ASSERT(!expr->IsPropertyName()); 5523 ASSERT(!expr->IsPropertyName());
5552 HInstruction* instr = NULL; 5524 HInstruction* instr = NULL;
5553 if (expr->IsMonomorphic()) { 5525 if (expr->IsMonomorphic()) {
5554 Handle<Map> map = expr->GetMonomorphicReceiverType(); 5526 Handle<Map> map = expr->GetMonomorphicReceiverType();
5555 if (map->has_slow_elements_kind()) { 5527 if (map->has_slow_elements_kind()) {
5556 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 5528 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
5557 : BuildLoadKeyedGeneric(obj, key); 5529 : BuildLoadKeyedGeneric(obj, key);
5558 } else { 5530 } else {
5559 AddInstruction(new(zone()) HCheckNonSmi(obj)); 5531 AddInstruction(new(zone()) HCheckNonSmi(obj));
5560 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); 5532 instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store);
5561 } 5533 }
5562 } else if (expr->GetReceiverTypes() != NULL && 5534 } else if (expr->GetReceiverTypes() != NULL &&
5563 !expr->GetReceiverTypes()->is_empty()) { 5535 !expr->GetReceiverTypes()->is_empty()) {
5564 return HandlePolymorphicElementAccess( 5536 return HandlePolymorphicElementAccess(
5565 obj, key, val, expr, ast_id, position, is_store, has_side_effects); 5537 obj, key, val, expr, ast_id, position, is_store, has_side_effects);
5566 } else { 5538 } else {
5567 if (is_store) { 5539 if (is_store) {
5568 instr = BuildStoreKeyedGeneric(obj, key, val); 5540 instr = BuildStoreKeyedGeneric(obj, key, val);
5569 } else { 5541 } else {
5570 instr = BuildLoadKeyedGeneric(obj, key); 5542 instr = BuildLoadKeyedGeneric(obj, key);
(...skipping 3394 matching lines...) Expand 10 before | Expand all | Expand 10 after
8965 } 8937 }
8966 } 8938 }
8967 8939
8968 #ifdef DEBUG 8940 #ifdef DEBUG
8969 if (graph_ != NULL) graph_->Verify(false); // No full verify. 8941 if (graph_ != NULL) graph_->Verify(false); // No full verify.
8970 if (allocator_ != NULL) allocator_->Verify(); 8942 if (allocator_ != NULL) allocator_->Verify();
8971 #endif 8943 #endif
8972 } 8944 }
8973 8945
8974 } } // namespace v8::internal 8946 } } // 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