Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 58a9b78750bb7401bfdc9e167800f8f01d3ef078..3c03b1560841bcd17587293056cb0771d681f8a7 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -7131,22 +7131,31 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
HValue* object, |
SmallMapList* types, |
Handle<String> name) { |
- int count = 0; |
- int previous_field_offset = 0; |
- bool previous_field_is_in_object = false; |
- bool is_monomorphic_field = true; |
if (HandlePolymorphicArrayLengthLoad(expr, object, types, name)) |
return; |
- Handle<Map> map; |
- LookupResult lookup(isolate()); |
- for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
- map = types->at(i); |
- if (ComputeLoadStoreField(map, name, &lookup, false)) { |
+ AddInstruction(new(zone()) HCheckNonSmi(object)); |
+ |
+ // Use monomorphic load if property lookup results in the same field index |
+ // for all maps. Requires special map check on the set of all handled maps. |
+ HInstruction* instr = NULL; |
+ if (types->length() > 0 && types->length() <= kMaxLoadPolymorphism) { |
+ LookupResult lookup(isolate()); |
+ int previous_field_offset = 0; |
+ bool previous_field_is_in_object = false; |
+ Representation representation = Representation::None(); |
+ int count; |
+ for (count = 0; count < types->length(); ++count) { |
+ Handle<Map> map = types->at(count); |
+ if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
+ |
int index = ComputeLoadStoreFieldIndex(map, &lookup); |
+ Representation new_representation = |
+ ComputeLoadStoreRepresentation(map, &lookup); |
bool is_in_object = index < 0; |
int offset = index * kPointerSize; |
+ |
if (index < 0) { |
// Negative property indices are in-object properties, indexed |
// from the end of the fixed part of the object. |
@@ -7154,31 +7163,33 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
} else { |
offset += FixedArray::kHeaderSize; |
} |
+ |
if (count == 0) { |
previous_field_offset = offset; |
previous_field_is_in_object = is_in_object; |
- } else if (is_monomorphic_field) { |
- is_monomorphic_field = (offset == previous_field_offset) && |
- (is_in_object == previous_field_is_in_object); |
+ representation = new_representation; |
+ } else if (offset != previous_field_offset || |
+ is_in_object != previous_field_is_in_object || |
+ (FLAG_track_fields && |
+ !representation.IsCompatibleForLoad(new_representation))) { |
+ break; |
} |
- ++count; |
+ |
+ representation = representation.generalize(new_representation); |
+ } |
+ |
+ if (count == types->length()) { |
+ AddInstruction(HCheckMaps::New(object, types, zone())); |
+ instr = DoBuildLoadNamedField( |
+ object, previous_field_is_in_object, |
+ representation, previous_field_offset); |
} |
} |
- // Use monomorphic load if property lookup results in the same field index |
- // for all maps. Requires special map check on the set of all handled maps. |
- AddInstruction(new(zone()) HCheckNonSmi(object)); |
- HInstruction* instr; |
- if (count == types->length() && is_monomorphic_field) { |
- AddInstruction(HCheckMaps::New(object, types, zone())); |
- instr = BuildLoadNamedField(object, map, &lookup); |
- } else { |
+ if (instr == NULL) { |
HValue* context = environment()->LookupContext(); |
- instr = new(zone()) HLoadNamedFieldPolymorphic(context, |
- object, |
- types, |
- name, |
- zone()); |
+ instr = new(zone()) HLoadNamedFieldPolymorphic( |
+ context, object, types, name, zone()); |
} |
instr->set_position(expr->position()); |
@@ -7735,18 +7746,25 @@ HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField( |
HValue* object, |
Handle<Map> map, |
LookupResult* lookup) { |
- Representation representation = lookup->representation(); |
int index = lookup->GetLocalFieldIndexFromMap(*map); |
- if (index < 0) { |
- // Negative property indices are in-object properties, indexed |
- // from the end of the fixed part of the object. |
- int offset = (index * kPointerSize) + map->instance_size(); |
- return new(zone()) HLoadNamedField(object, true, representation, offset); |
- } else { |
- // Non-negative property indices are in the properties array. |
- int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
- return new(zone()) HLoadNamedField(object, false, representation, offset); |
- } |
+ // Negative property indices are in-object properties, indexed from the end of |
+ // the fixed part of the object. Non-negative property indices are in the |
+ // properties array. |
+ int inobject = index < 0; |
+ Representation representation = lookup->representation(); |
+ int offset = inobject |
+ ? index * kPointerSize + map->instance_size() |
+ : index * kPointerSize + FixedArray::kHeaderSize; |
+ return DoBuildLoadNamedField(object, inobject, representation, offset); |
+} |
+ |
+ |
+HLoadNamedField* HGraphBuilder::DoBuildLoadNamedField( |
+ HValue* object, |
+ bool inobject, |
+ Representation representation, |
+ int offset) { |
+ return new(zone()) HLoadNamedField(object, inobject, representation, offset); |
} |