Revision: 15593
Author:   [email protected]
Date:     Wed Jul 10 06:05:41 2013
Log:      Turn polymorphic calls using the same prototype monomorphic.

[email protected]

Review URL: https://chromiumcodereview.appspot.com/18918002
http://code.google.com/p/v8/source/detail?r=15593

Modified:
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/hydrogen.h

=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Wed Jul 10 05:19:02 2013
+++ /branches/bleeding_edge/src/hydrogen.cc     Wed Jul 10 06:05:41 2013
@@ -4941,6 +4941,17 @@
   // No luck, do a generic store.
   return BuildStoreNamedGeneric(object, name, value);
 }
+
+
+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(
@@ -4992,17 +5003,12 @@
   // 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;
   }

@@ -6360,15 +6366,61 @@
   return lhs.src_length() < rhs.src_length();
 }

+
+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);
+    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];
=======================================
--- /branches/bleeding_edge/src/hydrogen.h      Wed Jul 10 05:19:02 2013
+++ /branches/bleeding_edge/src/hydrogen.h      Wed Jul 10 06:05:41 2013
@@ -1759,6 +1759,10 @@
                                   HValue* receiver,
                                   SmallMapList* types,
                                   Handle<String> name);
+  bool TryCallPolymorphicAsMonomorphic(Call* expr,
+                                       HValue* receiver,
+                                       SmallMapList* types,
+                                       Handle<String> name);
   void HandleLiteralCompareTypeof(CompareOperation* expr,
                                   HTypeof* typeof_expr,
                                   Handle<String> check);

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to