Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 21b83a2b2f011e185ea9c57bb211dd550e6757b2..62f342f9578f2f286da956100f83949a4907e595 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -4941,6 +4941,17 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( |
} |
+static bool CanLoadPropertyFromPrototype(Handle<Map> map, |
+ Handle<Name> name, |
+ LookupResult* lookup) { |
+ if (map->has_named_interceptor()) return false; |
+ if (map->is_dictionary_map()) return false; |
+ map->LookupDescriptor(NULL, *name, lookup); |
+ if (lookup->IsFound()) return false; |
+ return true; |
+} |
+ |
+ |
HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( |
Property* expr, |
HValue* object, |
@@ -4990,17 +5001,12 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( |
// Second chance: the property is on the prototype and all maps have the |
// same prototype. |
Handle<Map> map(types->at(0)); |
- if (map->has_named_interceptor()) return NULL; |
- if (map->is_dictionary_map()) return NULL; |
+ if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; |
Handle<Object> prototype(map->prototype(), isolate()); |
for (count = 1; count < types->length(); ++count) { |
Handle<Map> test_map(types->at(count)); |
- // Ensure the property is on the prototype, not the object itself. |
- if (map->has_named_interceptor()) return NULL; |
- if (test_map->is_dictionary_map()) return NULL; |
- test_map->LookupDescriptor(NULL, *name, &lookup); |
- if (lookup.IsFound()) return NULL; |
+ if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; |
if (test_map->prototype() != *prototype) return NULL; |
} |
@@ -6358,14 +6364,60 @@ inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) { |
} |
+bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic( |
+ Call* expr, |
+ HValue* receiver, |
+ SmallMapList* types, |
+ Handle<String> name) { |
+ if (types->length() > kMaxCallPolymorphism) return false; |
+ |
+ Handle<Map> map(types->at(0)); |
+ LookupResult lookup(isolate()); |
+ if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return false; |
+ |
+ Handle<Object> prototype(map->prototype(), isolate()); |
+ for (int count = 1; count < types->length(); ++count) { |
+ Handle<Map> test_map(types->at(count)); |
+ if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return false; |
+ if (test_map->prototype() != *prototype) return false; |
+ } |
+ |
+ if (!expr->ComputeTarget(map, name)) return false; |
+ |
+ BuildCheckHeapObject(receiver); |
+ AddInstruction(HCheckMaps::New(receiver, types, zone())); |
+ AddCheckPrototypeMaps(expr->holder(), map); |
+ if (FLAG_trace_inlining) { |
+ Handle<JSFunction> caller = current_info()->closure(); |
+ SmartArrayPointer<char> caller_name = |
+ caller->shared()->DebugName()->ToCString(); |
+ PrintF("Trying to inline the polymorphic call to %s from %s\n", |
+ *name->ToCString(), *caller_name); |
+ } |
+ |
+ if (!TryInlineCall(expr)) { |
+ int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
+ HCallConstantFunction* call = |
+ new(zone()) HCallConstantFunction(expr->target(), argument_count); |
+ call->set_position(expr->position()); |
+ PreProcessCall(call); |
+ AddInstruction(call); |
+ if (!ast_context()->IsEffect()) Push(call); |
mvstanton
2013/07/10 12:48:14
Could you explain what is happening with this ast_
Toon Verwaest
2013/07/10 13:04:03
This is boilerplate code that's all over. I'll jus
|
+ AddSimulate(expr->id(), REMOVABLE_SIMULATE); |
+ if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
+ } |
+ |
+ return true; |
+} |
+ |
+ |
void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( |
Call* expr, |
HValue* receiver, |
SmallMapList* types, |
Handle<String> name) { |
- // TODO(ager): We should recognize when the prototype chains for different |
- // maps are identical. In that case we can avoid repeatedly generating the |
- // same prototype map checks. |
+ if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return; |
+ |
int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
HBasicBlock* join = NULL; |
FunctionSorter order[kMaxCallPolymorphism]; |