Skip the CallFunctionStub when the callee function can be statically determined.
authortitzer@chromium.org <titzer@chromium.org>
Fri, 31 Oct 2014 16:35:42 +0000 (16:35 +0000)
committertitzer@chromium.org <titzer@chromium.org>
Fri, 31 Oct 2014 16:36:13 +0000 (16:36 +0000)
R=mstarzinger@chromium.org
BUG=

Review URL: https://codereview.chromium.org/694773002

Cr-Commit-Position: refs/heads/master@{#25042}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25042 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

12 files changed:
src/compiler/arm/linkage-arm.cc
src/compiler/arm64/linkage-arm64.cc
src/compiler/ia32/linkage-ia32.cc
src/compiler/js-generic-lowering.cc
src/compiler/js-generic-lowering.h
src/compiler/linkage-impl.h
src/compiler/linkage.cc
src/compiler/linkage.h
src/compiler/mips/linkage-mips.cc
src/compiler/raw-machine-assembler.cc
src/compiler/x64/linkage-x64.cc
test/cctest/compiler/test-linkage.cc

index 9a65ccc..2c644d6 100644 (file)
@@ -35,8 +35,9 @@ struct ArmLinkageHelperTraits {
 
 typedef LinkageHelper<ArmLinkageHelperTraits> LH;
 
-CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
-  return LH::GetJSCallDescriptor(zone, parameter_count);
+CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone,
+                                             CallDescriptor::Flags flags) {
+  return LH::GetJSCallDescriptor(zone, parameter_count, flags);
 }
 
 
index c50736c..bfa79da 100644 (file)
@@ -35,8 +35,9 @@ struct Arm64LinkageHelperTraits {
 
 typedef LinkageHelper<Arm64LinkageHelperTraits> LH;
 
-CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
-  return LH::GetJSCallDescriptor(zone, parameter_count);
+CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone,
+                                             CallDescriptor::Flags flags) {
+  return LH::GetJSCallDescriptor(zone, parameter_count, flags);
 }
 
 
index 8d85a9d..2d10f6f 100644 (file)
@@ -30,8 +30,9 @@ struct IA32LinkageHelperTraits {
 
 typedef LinkageHelper<IA32LinkageHelperTraits> LH;
 
-CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
-  return LH::GetJSCallDescriptor(zone, parameter_count);
+CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone,
+                                             CallDescriptor::Flags flags) {
+  return LH::GetJSCallDescriptor(zone, parameter_count, flags);
 }
 
 
index 11979ec..cb37a42 100644 (file)
@@ -9,6 +9,7 @@
 #include "src/compiler/js-generic-lowering.h"
 #include "src/compiler/machine-operator.h"
 #include "src/compiler/node-aux-data-inl.h"
+#include "src/compiler/node-matchers.h"
 #include "src/compiler/node-properties-inl.h"
 #include "src/unique.h"
 
@@ -405,15 +406,47 @@ void JSGenericLowering::LowerJSCallConstruct(Node* node) {
 }
 
 
-void JSGenericLowering::LowerJSCallFunction(Node* node) {
+bool JSGenericLowering::TryLowerDirectJSCall(Node* node) {
+  // Lower to a direct call to a constant JSFunction if the arity matches.
   const CallFunctionParameters& p = CallFunctionParametersOf(node->op());
-  CallFunctionStub stub(isolate(), static_cast<int>(p.arity() - 2), p.flags());
-  CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor();
-  CallDescriptor* desc = linkage()->GetStubCallDescriptor(
-      d, static_cast<int>(p.arity() - 1), FlagsForNode(node));
-  Node* stub_code = CodeConstant(stub.GetCode());
-  PatchInsertInput(node, 0, stub_code);
+  int arg_count = static_cast<int>(p.arity() - 2);
+  HeapObjectMatcher<JSFunction> func(node->InputAt(0));
+  if (!func.HasValue()) return false;
+
+  Handle<JSFunction> function = func.Value().handle();
+  if (arg_count != function->shared()->formal_parameter_count()) return false;
+
+  int index = NodeProperties::FirstContextIndex(node);
+
+  // TODO(titzer): total hack to share function context constants.
+  // Remove this when the JSGraph canonicalizes heap constants.
+  Node* context = node->InputAt(index);
+  HeapObjectMatcher<Context> context_const(context);
+  if (!context_const.HasValue() ||
+      *(context_const.Value().handle()) != function->context()) {
+    context = jsgraph()->HeapConstant(Handle<Context>(function->context()));
+  }
+  node->ReplaceInput(index, context);
+  CallDescriptor* desc = linkage()->GetJSCallDescriptor(
+      1 + arg_count, jsgraph()->zone(), FlagsForNode(node));
   PatchOperator(node, common()->Call(desc));
+  return true;
+}
+
+
+void JSGenericLowering::LowerJSCallFunction(Node* node) {
+  if (!TryLowerDirectJSCall(node)) {
+    // Call to computed function; use CallFunctionStub;
+    const CallFunctionParameters& p = CallFunctionParametersOf(node->op());
+    int arg_count = static_cast<int>(p.arity() - 2);
+    CallFunctionStub stub(isolate(), arg_count, p.flags());
+    CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor();
+    CallDescriptor* desc = linkage()->GetStubCallDescriptor(
+        d, static_cast<int>(p.arity() - 1), FlagsForNode(node));
+    Node* stub_code = CodeConstant(stub.GetCode());
+    PatchInsertInput(node, 0, stub_code);
+    PatchOperator(node, common()->Call(desc));
+  }
 }
 
 
index d01d395..63d8e93 100644 (file)
@@ -66,6 +66,8 @@ class JSGenericLowering : public Reducer {
   CompilationInfo* info_;
   JSGraph* jsgraph_;
   Linkage* linkage_;
+
+  bool TryLowerDirectJSCall(Node* node);
 };
 
 }  // namespace compiler
index 807d626..c964eee 100644 (file)
@@ -28,8 +28,8 @@ class LinkageHelper {
   }
 
   // TODO(turbofan): cache call descriptors for JSFunction calls.
-  static CallDescriptor* GetJSCallDescriptor(Zone* zone,
-                                             int js_parameter_count) {
+  static CallDescriptor* GetJSCallDescriptor(Zone* zone, int js_parameter_count,
+                                             CallDescriptor::Flags flags) {
     const size_t return_count = 1;
     const size_t context_count = 1;
     const size_t parameter_count = js_parameter_count + context_count;
@@ -56,16 +56,17 @@ class LinkageHelper {
     // The target for JS function calls is the JSFunction object.
     MachineType target_type = kMachAnyTagged;
     LinkageLocation target_loc = regloc(LinkageTraits::JSCallFunctionReg());
-    return new (zone) CallDescriptor(CallDescriptor::kCallJSFunction,  // kind
-                                     target_type,         // target MachineType
-                                     target_loc,          // target location
-                                     types.Build(),       // machine_sig
-                                     locations.Build(),   // location_sig
-                                     js_parameter_count,  // js_parameter_count
-                                     Operator::kNoProperties,  // properties
-                                     kNoCalleeSaved,           // callee-saved
-                                     CallDescriptor::kNeedsFrameState,  // flags
-                                     "js-call");
+    return new (zone) CallDescriptor(     // --
+        CallDescriptor::kCallJSFunction,  // kind
+        target_type,                      // target MachineType
+        target_loc,                       // target location
+        types.Build(),                    // machine_sig
+        locations.Build(),                // location_sig
+        js_parameter_count,               // js_parameter_count
+        Operator::kNoProperties,          // properties
+        kNoCalleeSaved,                   // callee-saved
+        flags,                            // flags
+        "js-call");
   }
 
 
@@ -116,16 +117,17 @@ class LinkageHelper {
     // The target for runtime calls is a code object.
     MachineType target_type = kMachAnyTagged;
     LinkageLocation target_loc = LinkageLocation::AnyRegister();
-    return new (zone) CallDescriptor(CallDescriptor::kCallCodeObject,  // kind
-                                     target_type,         // target MachineType
-                                     target_loc,          // target location
-                                     types.Build(),       // machine_sig
-                                     locations.Build(),   // location_sig
-                                     js_parameter_count,  // js_parameter_count
-                                     properties,          // properties
-                                     kNoCalleeSaved,      // callee-saved
-                                     flags,               // flags
-                                     function->name);     // debug name
+    return new (zone) CallDescriptor(     // --
+        CallDescriptor::kCallCodeObject,  // kind
+        target_type,                      // target MachineType
+        target_loc,                       // target location
+        types.Build(),                    // machine_sig
+        locations.Build(),                // location_sig
+        js_parameter_count,               // js_parameter_count
+        properties,                       // properties
+        kNoCalleeSaved,                   // callee-saved
+        flags,                            // flags
+        function->name);                  // debug name
   }
 
 
@@ -169,16 +171,17 @@ class LinkageHelper {
     // The target for stub calls is a code object.
     MachineType target_type = kMachAnyTagged;
     LinkageLocation target_loc = LinkageLocation::AnyRegister();
-    return new (zone) CallDescriptor(CallDescriptor::kCallCodeObject,  // kind
-                                     target_type,         // target MachineType
-                                     target_loc,          // target location
-                                     types.Build(),       // machine_sig
-                                     locations.Build(),   // location_sig
-                                     js_parameter_count,  // js_parameter_count
-                                     Operator::kNoProperties,  // properties
-                                     kNoCalleeSaved,  // callee-saved registers
-                                     flags,           // flags
-                                     descriptor.DebugName(zone->isolate()));
+    return new (zone) CallDescriptor(     // --
+        CallDescriptor::kCallCodeObject,  // kind
+        target_type,                      // target MachineType
+        target_loc,                       // target location
+        types.Build(),                    // machine_sig
+        locations.Build(),                // location_sig
+        js_parameter_count,               // js_parameter_count
+        Operator::kNoProperties,          // properties
+        kNoCalleeSaved,                   // callee-saved registers
+        flags,                            // flags
+        descriptor.DebugName(zone->isolate()));
   }
 
   static CallDescriptor* GetSimplifiedCDescriptor(Zone* zone,
@@ -201,15 +204,16 @@ class LinkageHelper {
     // The target for C calls is always an address (i.e. machine pointer).
     MachineType target_type = kMachPtr;
     LinkageLocation target_loc = LinkageLocation::AnyRegister();
-    return new (zone) CallDescriptor(CallDescriptor::kCallAddress,  // kind
-                                     target_type,        // target MachineType
-                                     target_loc,         // target location
-                                     msig,               // machine_sig
-                                     locations.Build(),  // location_sig
-                                     0,                  // js_parameter_count
-                                     Operator::kNoProperties,  // properties
-                                     LinkageTraits::CCalleeSaveRegisters(),
-                                     CallDescriptor::kNoFlags, "c-call");
+    return new (zone) CallDescriptor(  // --
+        CallDescriptor::kCallAddress,  // kind
+        target_type,                   // target MachineType
+        target_loc,                    // target location
+        msig,                          // machine_sig
+        locations.Build(),             // location_sig
+        0,                             // js_parameter_count
+        Operator::kNoProperties,       // properties
+        LinkageTraits::CCalleeSaveRegisters(), CallDescriptor::kNoFlags,
+        "c-call");
   }
 
   static LinkageLocation regloc(Register reg) {
index b586301..87aa81b 100644 (file)
@@ -42,13 +42,15 @@ CallDescriptor* Linkage::ComputeIncoming(Zone* zone, CompilationInfo* info) {
   if (info->function() != NULL) {
     // If we already have the function literal, use the number of parameters
     // plus the receiver.
-    return GetJSCallDescriptor(1 + info->function()->parameter_count(), zone);
+    return GetJSCallDescriptor(1 + info->function()->parameter_count(), zone,
+                               CallDescriptor::kNoFlags);
   }
   if (!info->closure().is_null()) {
     // If we are compiling a JS function, use a JS call descriptor,
     // plus the receiver.
     SharedFunctionInfo* shared = info->closure()->shared();
-    return GetJSCallDescriptor(1 + shared->formal_parameter_count(), zone);
+    return GetJSCallDescriptor(1 + shared->formal_parameter_count(), zone,
+                               CallDescriptor::kNoFlags);
   }
   if (info->code_stub() != NULL) {
     // Use the code stub interface descriptor.
@@ -88,8 +90,9 @@ FrameOffset Linkage::GetFrameOffset(int spill_slot, Frame* frame,
 }
 
 
-CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count) const {
-  return GetJSCallDescriptor(parameter_count, zone_);
+CallDescriptor* Linkage::GetJSCallDescriptor(
+    int parameter_count, CallDescriptor::Flags flags) const {
+  return GetJSCallDescriptor(parameter_count, zone_, flags);
 }
 
 
index d11fa12..60a2142 100644 (file)
@@ -174,8 +174,10 @@ class Linkage : public ZoneObject {
   // The call descriptor for this compilation unit describes the locations
   // of incoming parameters and the outgoing return value(s).
   CallDescriptor* GetIncomingDescriptor() const { return incoming_; }
-  CallDescriptor* GetJSCallDescriptor(int parameter_count) const;
-  static CallDescriptor* GetJSCallDescriptor(int parameter_count, Zone* zone);
+  CallDescriptor* GetJSCallDescriptor(int parameter_count,
+                                      CallDescriptor::Flags flags) const;
+  static CallDescriptor* GetJSCallDescriptor(int parameter_count, Zone* zone,
+                                             CallDescriptor::Flags flags);
   CallDescriptor* GetRuntimeCallDescriptor(
       Runtime::FunctionId function, int parameter_count,
       Operator::Properties properties) const;
index 91fe9c3..d4ec190 100644 (file)
@@ -35,8 +35,9 @@ struct MipsLinkageHelperTraits {
 
 typedef LinkageHelper<MipsLinkageHelperTraits> LH;
 
-CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
-  return LH::GetJSCallDescriptor(zone, parameter_count);
+CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone,
+                                             CallDescriptor::Flags flags) {
+  return LH::GetJSCallDescriptor(zone, parameter_count, flags);
 }
 
 
index 1d8b187..a8b658f 100644 (file)
@@ -99,7 +99,8 @@ Node* RawMachineAssembler::CallFunctionStub0(Node* function, Node* receiver,
 
 Node* RawMachineAssembler::CallJS0(Node* function, Node* receiver,
                                    Node* context, Node* frame_state) {
-  CallDescriptor* descriptor = Linkage::GetJSCallDescriptor(1, zone());
+  CallDescriptor* descriptor =
+      Linkage::GetJSCallDescriptor(1, zone(), CallDescriptor::kNeedsFrameState);
   Node* call = graph()->NewNode(common()->Call(descriptor), function, receiver,
                                 context, frame_state);
   schedule()->AddNode(CurrentBlock(), call);
index 0638591..7bf2c78 100644 (file)
@@ -49,8 +49,9 @@ struct X64LinkageHelperTraits {
 
 typedef LinkageHelper<X64LinkageHelperTraits> LH;
 
-CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
-  return LH::GetJSCallDescriptor(zone, parameter_count);
+CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone,
+                                             CallDescriptor::Flags flags) {
+  return LH::GetJSCallDescriptor(zone, parameter_count, flags);
 }
 
 
index 267d464..0d5ee8f 100644 (file)
@@ -90,7 +90,8 @@ TEST(TestLinkageJSCall) {
   Linkage linkage(info.zone(), &info);
 
   for (int i = 0; i < 32; i++) {
-    CallDescriptor* descriptor = linkage.GetJSCallDescriptor(i);
+    CallDescriptor* descriptor =
+        linkage.GetJSCallDescriptor(i, CallDescriptor::kNoFlags);
     CHECK_NE(NULL, descriptor);
     CHECK_EQ(i, descriptor->JSParameterCount());
     CHECK_EQ(1, descriptor->ReturnCount());