Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 9c83380492f6158b14d3c181c345980ddb44936d..c8ce91c784f86e526141477a6f37201bc75b334b 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -3871,14 +3871,15 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
} |
-// Sets the lookup result and returns true if the store can be inlined. |
+// Sets the lookup result and returns true if the load/store can be inlined. |
static bool ComputeStoredField(Handle<Map> type, |
danno
2012/03/09 11:52:58
Rename to something like ComputeLoadStoreField
Michael Starzinger
2012/03/12 11:37:11
Done.
|
Handle<String> name, |
- LookupResult* lookup) { |
+ LookupResult* lookup, |
+ bool is_store) { |
type->LookupInDescriptors(NULL, *name, lookup); |
if (!lookup->IsFound()) return false; |
if (lookup->type() == FIELD) return true; |
- return (lookup->type() == MAP_TRANSITION) && |
+ return is_store && (lookup->type() == MAP_TRANSITION) && |
(type->unused_property_fields() > 0); |
} |
@@ -3957,7 +3958,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, |
LookupResult lookup(isolate()); |
SmallMapList* types = expr->GetReceiverTypes(); |
bool is_monomorphic = expr->IsMonomorphic() && |
- ComputeStoredField(types->first(), name, &lookup); |
+ ComputeStoredField(types->first(), name, &lookup, true); |
return is_monomorphic |
? BuildStoreNamedField(object, name, value, types->first(), &lookup, |
@@ -3966,6 +3967,47 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, |
} |
+void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
+ HValue* object, |
+ SmallMapList* types, |
+ Handle<String> name) { |
+ int count = 0; |
+ int previous_field_index = 0; |
+ bool is_monomorphic_field = true; |
+ Handle<Map> map; |
+ LookupResult lookup(isolate()); |
+ for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
danno
2012/03/09 11:52:58
kMaxStorePolymorphism seems to be inappropriately
Michael Starzinger
2012/03/12 11:37:11
Done. That actually should have been kMaxLoadPolym
|
+ map = types->at(i); |
+ if (ComputeStoredField(map, name, &lookup, false)) { |
+ int index = ComputeStoredFieldIndex(map, name, &lookup); |
+ if (count == 0) { |
+ previous_field_index = index; |
+ } else if (is_monomorphic_field) { |
+ is_monomorphic_field = (index == previous_field_index); |
+ } |
+ ++count; |
+ } |
+ } |
+ |
+ // 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; |
+ if (count == types->length() && is_monomorphic_field) { |
+ AddInstruction(new(zone()) HCheckMapSet(object, types)); |
+ instr = BuildLoadNamedField(object, expr, map, &lookup, false); |
+ } else { |
+ HValue* context = environment()->LookupContext(); |
+ instr = new(zone()) HLoadNamedFieldPolymorphic(context, |
+ object, |
+ types, |
+ name); |
+ } |
+ |
+ instr->set_position(expr->position()); |
+ return ast_context()->ReturnInstruction(instr, expr->id()); |
+} |
+ |
+ |
void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, |
HValue* object, |
HValue* value, |
@@ -3979,7 +4021,7 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, |
for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
Handle<Map> map = types->at(i); |
LookupResult lookup(isolate()); |
- if (ComputeStoredField(map, name, &lookup)) { |
+ if (ComputeStoredField(map, name, &lookup, true)) { |
if (count == 0) { |
AddInstruction(new(zone()) HCheckNonSmi(object)); // Only needed once. |
join = graph()->CreateBasicBlock(); |
@@ -4953,8 +4995,8 @@ void HGraphBuilder::VisitProperty(Property* expr) { |
instr = BuildLoadNamed(obj, expr, types->first(), name); |
} else if (types != NULL && types->length() > 1) { |
AddInstruction(new(zone()) HCheckNonSmi(obj)); |
- HValue* context = environment()->LookupContext(); |
- instr = new(zone()) HLoadNamedFieldPolymorphic(context, obj, types, name); |
+ HandlePolymorphicLoadNamedField(expr, obj, types, name); |
+ return; |
} else { |
instr = BuildLoadNamedGeneric(obj, expr); |
} |