Revision: 18146
Author:   [email protected]
Date:     Fri Nov 29 09:02:00 2013 UTC
Log:      Revert r18131 and r18139 "Clean up in the CallStubCompiler".

and "Fix register usage."

[email protected]

Review URL: https://codereview.chromium.org/96573002
http://code.google.com/p/v8/source/detail?r=18146

Modified:
 /branches/bleeding_edge/src/arm/macro-assembler-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.h
 /branches/bleeding_edge/src/arm/stub-cache-arm.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h
 /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
 /branches/bleeding_edge/src/stub-cache.cc
 /branches/bleeding_edge/src/stub-cache.h
 /branches/bleeding_edge/src/x64/macro-assembler-x64.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.h
 /branches/bleeding_edge/src/x64/stub-cache-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Thu Nov 28 15:26:04 2013 UTC +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Fri Nov 29 09:02:00 2013 UTC
@@ -1229,7 +1229,7 @@
 }


-void MacroAssembler::InvokeFunction(Register function,
+void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
                                     const ParameterCount& expected,
                                     const ParameterCount& actual,
                                     InvokeFlag flag,
@@ -1238,10 +1238,8 @@
   // You can't call a function without a valid frame.
   ASSERT(flag == JUMP_FUNCTION || has_frame());

- // Contract with called JS functions requires that function is passed in r1.
-  ASSERT(function.is(r1));
-
   // Get the function and setup the context.
+  Move(r1, function);
   ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));

   // We call indirectly through the code field in the function to
@@ -1250,17 +1248,6 @@
   ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
   InvokeCode(r3, expected, actual, flag, call_wrapper, call_kind);
 }
-
-
-void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
-                                    const ParameterCount& expected,
-                                    const ParameterCount& actual,
-                                    InvokeFlag flag,
-                                    const CallWrapper& call_wrapper,
-                                    CallKind call_kind) {
-  Move(r1, function);
-  InvokeFunction(r1, expected, actual, flag, call_wrapper, call_kind);
-}


 void MacroAssembler::IsObjectJSObjectType(Register heap_object,
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Thu Nov 28 15:26:04 2013 UTC +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Fri Nov 29 09:02:00 2013 UTC
@@ -613,13 +613,6 @@
                       const CallWrapper& call_wrapper,
                       CallKind call_kind);

-  void InvokeFunction(Register function,
-                      const ParameterCount& expected,
-                      const ParameterCount& actual,
-                      InvokeFlag flag,
-                      const CallWrapper& call_wrapper,
-                      CallKind call_kind);
-
   void InvokeFunction(Handle<JSFunction> function,
                       const ParameterCount& expected,
                       const ParameterCount& actual,
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Thu Nov 28 18:11:15 2013 UTC +++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Fri Nov 29 09:02:00 2013 UTC
@@ -740,6 +740,36 @@
     __ mov(this->name(), Operand(name));
   }
 }
+
+
+static void GenerateCallFunction(MacroAssembler* masm,
+                                 Handle<Object> object,
+                                 const ParameterCount& arguments,
+                                 Label* miss,
+                                 Code::ExtraICState extra_ic_state) {
+  // ----------- S t a t e -------------
+  //  -- r0: receiver
+  //  -- r1: function to call
+  // -----------------------------------
+
+  // Check that the function really is a function.
+  __ JumpIfSmi(r1, miss);
+  __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
+  __ b(ne, miss);
+
+  if (object->IsGlobalObject()) {
+    const int argc = arguments.immediate();
+    const int receiver_offset = argc * kPointerSize;
+    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
+    __ str(r3, MemOperand(sp, receiver_offset));
+  }
+
+  // Invoke the function.
+  CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+ __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind);
+}


 static void PushInterceptorArguments(MacroAssembler* masm,
@@ -925,7 +955,7 @@

 class CallInterceptorCompiler BASE_EMBEDDED {
  public:
-  CallInterceptorCompiler(CallStubCompiler* stub_compiler,
+  CallInterceptorCompiler(StubCompiler* stub_compiler,
                           const ParameterCount& arguments,
                           Register name,
                           ExtraICState extra_ic_state)
@@ -1037,8 +1067,13 @@
       GenerateFastApiDirectCall(
           masm, optimization, arguments_.immediate(), false);
     } else {
+      CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
+          ? CALL_AS_FUNCTION
+          : CALL_AS_METHOD;
       Handle<JSFunction> function = optimization.constant_function();
-      stub_compiler_->GenerateJumpFunction(object, function);
+      ParameterCount expected(function);
+      __ InvokeFunction(function, expected, arguments_,
+                        JUMP_FUNCTION, NullCallWrapper(), call_kind);
     }

     // Deferred code for fast API call case---clean preallocated space.
@@ -1104,7 +1139,7 @@
     __ b(ne, interceptor_succeeded);
   }

-  CallStubCompiler* stub_compiler_;
+  StubCompiler* stub_compiler_;
   const ParameterCount& arguments_;
   Register name_;
   ExtraICState extra_ic_state_;
@@ -1504,15 +1539,6 @@
     __ b(ne, miss);
   }
 }
-
-
-void CallStubCompiler::GenerateFunctionCheck(Register function,
-                                             Register scratch,
-                                             Label* miss) {
-  __ JumpIfSmi(function, miss);
-  __ CompareObjectType(function, scratch, scratch, JS_FUNCTION_TYPE);
-  __ b(ne, miss);
-}


 void CallStubCompiler::GenerateLoadFunctionFromCell(
@@ -1530,7 +1556,9 @@
     // the nice side effect that multiple closures based on the same
     // function can all use this call IC. Before we load through the
     // function, we have to verify that it still is a function.
-    GenerateFunctionCheck(r1, r3, miss);
+    __ JumpIfSmi(r1, miss);
+    __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
+    __ b(ne, miss);

     // Check the shared function info. Make sure it hasn't changed.
     __ Move(r3, Handle<SharedFunctionInfo>(function->shared()));
@@ -1562,7 +1590,8 @@
       object, holder, name, RECEIVER_MAP_CHECK, &miss);
   GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder),
index.translate(holder), Representation::Tagged());
-  GenerateJumpFunction(object, r1, &miss);
+
+  GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);

   HandlerFrontendFooter(&miss);

@@ -1977,7 +2006,8 @@
   __ bind(&miss);
   // Restore function name in r2.
   __ Move(r2, name);
-  HandlerFrontendFooter(&name_miss);
+  __ bind(&name_miss);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(type, name);
@@ -2043,7 +2073,8 @@
   __ bind(&miss);
   // Restore function name in r2.
   __ Move(r2, name);
-  HandlerFrontendFooter(&name_miss);
+  __ bind(&name_miss);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(type, name);
@@ -2090,10 +2121,12 @@
   StubRuntimeCallHelper call_helper;
   generator.GenerateSlow(masm(), call_helper);

+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
   __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
-  // it.
-  GenerateJumpFunctionIgnoreReceiver(function);
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);

   HandlerFrontendFooter(&miss);

@@ -2181,9 +2214,11 @@
   __ Ret();

   __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
-  // it.
-  GenerateJumpFunctionIgnoreReceiver(function);
+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);

   HandlerFrontendFooter(&miss);

@@ -2261,10 +2296,12 @@
   __ Drop(argc + 1);
   __ Ret();

+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
   __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
-  // it.
-  GenerateJumpFunctionIgnoreReceiver(function);
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);

   HandlerFrontendFooter(&miss);

@@ -2317,7 +2354,8 @@
   __ bind(&miss);
   FreeSpaceForFastApiCall(masm());

-  HandlerFrontendFooter(&miss_before_stack_reserved);
+  __ bind(&miss_before_stack_reserved);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(function);
@@ -2338,7 +2376,7 @@


 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
-  if (!object.is_null() && object->IsGlobalObject()) {
+  if (object->IsGlobalObject()) {
     const int argc = arguments().immediate();
     const int receiver_offset = argc * kPointerSize;
     __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
@@ -2434,18 +2472,39 @@
 }


-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
-                                            Register function,
-                                            Label* miss) {
-  ASSERT(function.is(r1));
-  // Check that the function really is a function.
-  GenerateFunctionCheck(function, r3, miss);
-  if (!function.is(r1)) __ mov(r1, function);
+void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), call_kind);
+}
+
+
+Handle<Code> CallStubCompiler::CompileCallConstant(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<Name> name,
+    CheckType check,
+    Handle<JSFunction> function) {
+  if (HasCustomCallGenerator(function)) {
+    Handle<Code> code = CompileCustomCall(object, holder,
+                                          Handle<Cell>::null(),
+ function, Handle<String>::cast(name),
+                                          Code::FAST);
+    // A null handle means bail out to the regular compiler code below.
+    if (!code.is_null()) return code;
+  }
+
+  Label miss;
+  HandlerFrontendHeader(object, holder, name, check, &miss);
   PatchGlobalProxy(object);
+  CompileHandlerBackend(function);
+  HandlerFrontendFooter(&miss);

-  // Invoke the function.
-  __ InvokeFunction(r1, arguments(), JUMP_FUNCTION,
-                    NullCallWrapper(), call_kind());
+  // Return the generated code.
+  return GetCode(function);
 }


@@ -2472,9 +2531,11 @@
   // Restore receiver.
   __ ldr(r0, MemOperand(sp, argc * kPointerSize));

-  GenerateJumpFunction(object, r1, &miss);
+  GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);

-  HandlerFrontendFooter(&miss);
+  // Handle call cache miss.
+  __ bind(&miss);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(Code::FAST, name);
@@ -2497,13 +2558,26 @@

   Label miss;
   HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
- // Potentially loads a closure that matches the shared function info of the
-  // function, rather than function.
   GenerateLoadFunctionFromCell(cell, function, &miss);
+  PatchGlobalProxy(object);
+
+  // Set up the context (function already in r1).
+  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));

+  // Jump to the cached code (tail call).
   Counters* counters = isolate()->counters();
   __ IncrementCounter(counters->call_global_inline(), 1, r3, r4);
-  GenerateJumpFunction(object, r1, function);
+  ParameterCount expected(function->shared()->formal_parameter_count());
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  // We call indirectly through the code field in the function to
+  // allow recompilation to take effect without changing any of the
+  // call sites.
+  __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
+  __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION,
+                NullCallWrapper(), call_kind);
+
   HandlerFrontendFooter(&miss);

   // Return the generated code.
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Thu Nov 28 15:26:04 2013 UTC +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Fri Nov 29 09:02:00 2013 UTC
@@ -2636,7 +2636,7 @@
 }


-void MacroAssembler::InvokeFunction(Register fun,
+void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
                                     const ParameterCount& expected,
                                     const ParameterCount& actual,
                                     InvokeFlag flag,
@@ -2645,23 +2645,16 @@
   // You can't call a function without a valid frame.
   ASSERT(flag == JUMP_FUNCTION || has_frame());

-  ASSERT(fun.is(edi));
+  // Get the function and setup the context.
+  LoadHeapObject(edi, function);
   mov(esi, FieldOperand(edi, JSFunction::kContextOffset));

+  // We call indirectly through the code field in the function to
+  // allow recompilation to take effect without changing any of the
+  // call sites.
   InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
              expected, actual, flag, call_wrapper, call_kind);
 }
-
-
-void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
-                                    const ParameterCount& expected,
-                                    const ParameterCount& actual,
-                                    InvokeFlag flag,
-                                    const CallWrapper& call_wrapper,
-                                    CallKind call_kind) {
-  LoadHeapObject(edi, function);
-  InvokeFunction(edi, expected, actual, flag, call_wrapper, call_kind);
-}


 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Thu Nov 28 15:26:04 2013 UTC +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Fri Nov 29 09:02:00 2013 UTC
@@ -349,13 +349,6 @@
                       const CallWrapper& call_wrapper,
                       CallKind call_kind);

-  void InvokeFunction(Register function,
-                      const ParameterCount& expected,
-                      const ParameterCount& actual,
-                      InvokeFlag flag,
-                      const CallWrapper& call_wrapper,
-                      CallKind call_kind);
-
   void InvokeFunction(Handle<JSFunction> function,
                       const ParameterCount& expected,
                       const ParameterCount& actual,
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Thu Nov 28 18:11:15 2013 UTC +++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Fri Nov 29 09:02:00 2013 UTC
@@ -645,7 +645,7 @@

 class CallInterceptorCompiler BASE_EMBEDDED {
  public:
-  CallInterceptorCompiler(CallStubCompiler* stub_compiler,
+  CallInterceptorCompiler(StubCompiler* stub_compiler,
                           const ParameterCount& arguments,
                           Register name,
                           ExtraICState extra_state)
@@ -756,8 +756,13 @@
     if (can_do_fast_api_call) {
       GenerateFastApiCall(masm, optimization, arguments_.immediate());
     } else {
-      Handle<JSFunction> fun = optimization.constant_function();
-      stub_compiler_->GenerateJumpFunction(object, fun);
+      CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+          ? CALL_AS_FUNCTION
+          : CALL_AS_METHOD;
+      Handle<JSFunction> function = optimization.constant_function();
+      ParameterCount expected(function);
+      __ InvokeFunction(function, expected, arguments_,
+                        JUMP_FUNCTION, NullCallWrapper(), call_kind);
     }

     // Deferred code for fast API call case---clean preallocated space.
@@ -825,7 +830,7 @@
     __ j(not_equal, interceptor_succeeded);
   }

-  CallStubCompiler* stub_compiler_;
+  StubCompiler* stub_compiler_;
   const ParameterCount& arguments_;
   Register name_;
   ExtraICState extra_state_;
@@ -1596,15 +1601,6 @@
   }
 }

-
-void CallStubCompiler::GenerateFunctionCheck(Register function,
-                                             Register scratch,
-                                             Label* miss) {
-  __ JumpIfSmi(function, miss);
-  __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
-  __ j(not_equal, miss);
-}
-

 void CallStubCompiler::GenerateLoadFunctionFromCell(
     Handle<Cell> cell,
@@ -1625,7 +1621,9 @@
     // the nice side effect that multiple closures based on the same
     // function can all use this call IC. Before we load through the
     // function, we have to verify that it still is a function.
-    GenerateFunctionCheck(edi, ebx, miss);
+    __ JumpIfSmi(edi, miss);
+    __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
+    __ j(not_equal, miss);

     // Check the shared function info. Make sure it hasn't changed.
     __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
@@ -1658,7 +1656,20 @@
   GenerateFastPropertyLoad(
       masm(), edi, reg, index.is_inobject(holder),
       index.translate(holder), Representation::Tagged());
-  GenerateJumpFunction(object, edi, &miss);
+
+  // Check that the function really is a function.
+  __ JumpIfSmi(edi, &miss);
+  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
+  __ j(not_equal, &miss);
+
+  PatchGlobalProxy(object);
+
+  // Invoke the function.
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
+                    NullCallWrapper(), call_kind);

   HandlerFrontendFooter(&miss);

@@ -2070,7 +2081,8 @@
   __ bind(&miss);
   // Restore function name in ecx.
   __ Set(ecx, Immediate(name));
-  HandlerFrontendFooter(&name_miss);
+  __ bind(&name_miss);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(type, name);
@@ -2138,7 +2150,8 @@
   __ bind(&miss);
   // Restore function name in ecx.
   __ Set(ecx, Immediate(name));
-  HandlerFrontendFooter(&name_miss);
+  __ bind(&name_miss);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(type, name);
@@ -2187,10 +2200,15 @@
   StubRuntimeCallHelper call_helper;
   generator.GenerateSlow(masm(), call_helper);

+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
   __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
-  // it.
-  GenerateJumpFunctionIgnoreReceiver(function);
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), call_kind);

   HandlerFrontendFooter(&miss);

@@ -2297,10 +2315,12 @@
   __ mov(eax, Operand(esp, 1 * kPointerSize));
   __ ret(2 * kPointerSize);

+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
   __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
-  // it.
-  GenerateJumpFunctionIgnoreReceiver(function);
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);

   HandlerFrontendFooter(&miss);

@@ -2384,10 +2404,12 @@
   __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
   __ ret(2 * kPointerSize);

+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
   __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
-  // it.
-  GenerateJumpFunctionIgnoreReceiver(function);
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);

   HandlerFrontendFooter(&miss);

@@ -2447,7 +2469,8 @@
   __ bind(&miss);
   __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));

-  HandlerFrontendFooter(&miss_before_stack_reserved);
+  __ bind(&miss_before_stack_reserved);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(function);
@@ -2466,7 +2489,7 @@


 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
-  if (!object.is_null() && object->IsGlobalObject()) {
+  if (object->IsGlobalObject()) {
     const int argc = arguments().immediate();
     const int receiver_offset = (argc + 1) * kPointerSize;
     __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
@@ -2556,18 +2579,40 @@
 }


-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
-                                            Register function,
-                                            Label* miss) {
-  // Check that the function really is a function.
-  GenerateFunctionCheck(function, ebx, miss);
+void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), call_kind);
+}

-  if (!function.is(edi)) __ mov(edi, function);
+
+Handle<Code> CallStubCompiler::CompileCallConstant(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<Name> name,
+    CheckType check,
+    Handle<JSFunction> function) {
+
+  if (HasCustomCallGenerator(function)) {
+    Handle<Code> code = CompileCustomCall(object, holder,
+                                          Handle<Cell>::null(),
+ function, Handle<String>::cast(name),
+                                          Code::FAST);
+    // A null handle means bail out to the regular compiler code below.
+    if (!code.is_null()) return code;
+  }
+
+  Label miss;
+  HandlerFrontendHeader(object, holder, name, check, &miss);
   PatchGlobalProxy(object);
+  CompileHandlerBackend(function);
+  HandlerFrontendFooter(&miss);

-  // Invoke the function.
-  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
-                    NullCallWrapper(), call_kind());
+  // Return the generated code.
+  return GetCode(function);
 }


@@ -2594,9 +2639,29 @@
   // Restore receiver.
   __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));

-  GenerateJumpFunction(object, eax, &miss);
+  // Check that the function really is a function.
+  __ JumpIfSmi(eax, &miss);
+  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
+  __ j(not_equal, &miss);
+
+  // Patch the receiver on the stack with the global proxy if
+  // necessary.
+  if (object->IsGlobalObject()) {
+    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+  }
+
+  // Invoke the function.
+  __ mov(edi, eax);
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
+                    NullCallWrapper(), call_kind);

-  HandlerFrontendFooter(&miss);
+  // Handle load cache miss.
+  __ bind(&miss);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(Code::FAST, name);
@@ -2619,10 +2684,25 @@

   Label miss;
   HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
- // Potentially loads a closure that matches the shared function info of the
-  // function, rather than function.
   GenerateLoadFunctionFromCell(cell, function, &miss);
-  GenerateJumpFunction(object, edi, function);
+  PatchGlobalProxy(object);
+
+  // Set up the context (function already in edi).
+  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
+
+  // Jump to the cached code (tail call).
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->call_global_inline(), 1);
+  ParameterCount expected(function->shared()->formal_parameter_count());
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  // We call indirectly through the code field in the function to
+  // allow recompilation to take effect without changing any of the
+  // call sites.
+  __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
+                expected, arguments(), JUMP_FUNCTION,
+                NullCallWrapper(), call_kind);

   HandlerFrontendFooter(&miss);

=======================================
--- /branches/bleeding_edge/src/stub-cache.cc   Thu Nov 28 18:13:30 2013 UTC
+++ /branches/bleeding_edge/src/stub-cache.cc   Fri Nov 29 09:02:00 2013 UTC
@@ -1128,67 +1128,10 @@
 #define __ ACCESS_MASM(masm())


-CallKind CallStubCompiler::call_kind() {
-  return CallICBase::Contextual::decode(extra_state_)
-      ? CALL_AS_FUNCTION
-      : CALL_AS_METHOD;
-}
-
-
 void CallStubCompiler::HandlerFrontendFooter(Label* miss) {
   __ bind(miss);
   GenerateMissBranch();
 }
-
-
-void CallStubCompiler::GenerateJumpFunctionIgnoreReceiver(
-    Handle<JSFunction> function) {
-  ParameterCount expected(function);
-  __ InvokeFunction(function, expected, arguments(),
-                    JUMP_FUNCTION, NullCallWrapper(), call_kind());
-}
-
-
-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
-                                            Handle<JSFunction> function) {
-  PatchGlobalProxy(object);
-  GenerateJumpFunctionIgnoreReceiver(function);
-}
-
-
-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
-                                            Register actual_closure,
-                                            Handle<JSFunction> function) {
-  PatchGlobalProxy(object);
-  ParameterCount expected(function);
-  __ InvokeFunction(actual_closure, expected, arguments(),
-                    JUMP_FUNCTION, NullCallWrapper(), call_kind());
-}
-
-
-Handle<Code> CallStubCompiler::CompileCallConstant(
-    Handle<Object> object,
-    Handle<JSObject> holder,
-    Handle<Name> name,
-    CheckType check,
-    Handle<JSFunction> function) {
-  if (HasCustomCallGenerator(function)) {
-    Handle<Code> code = CompileCustomCall(object, holder,
-                                          Handle<Cell>::null(),
- function, Handle<String>::cast(name),
-                                          Code::FAST);
-    // A null handle means bail out to the regular compiler code below.
-    if (!code.is_null()) return code;
-  }
-
-  Label miss;
-  HandlerFrontendHeader(object, holder, name, check, &miss);
-  GenerateJumpFunction(object, function);
-  HandlerFrontendFooter(&miss);
-
-  // Return the generated code.
-  return GetCode(function);
-}


 Register LoadStubCompiler::HandlerFrontendHeader(
=======================================
--- /branches/bleeding_edge/src/stub-cache.h    Thu Nov 28 18:13:30 2013 UTC
+++ /branches/bleeding_edge/src/stub-cache.h    Fri Nov 29 09:02:00 2013 UTC
@@ -919,17 +919,7 @@
                                  Label* miss);
   void HandlerFrontendFooter(Label* miss);

-  void GenerateJumpFunctionIgnoreReceiver(Handle<JSFunction> function);
-  void GenerateJumpFunction(Handle<Object> object,
-                            Handle<JSFunction> function);
-  void GenerateJumpFunction(Handle<Object> object,
-                            Register function,
-                            Label* miss);
- // Use to call |actual_closure|, a closure with the same shared function info
-  // as |function|.
-  void GenerateJumpFunction(Handle<Object> object,
-                            Register actual_closure,
-                            Handle<JSFunction> function);
+  void CompileHandlerBackend(Handle<JSFunction> function);

   Handle<Code> CompileCallConstant(Handle<Object> object,
                                    Handle<JSObject> holder,
@@ -978,8 +968,6 @@
                                   Handle<JSFunction> function,
                                   Handle<String> name);

-  CallKind call_kind();
-
   Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
   Handle<Code> GetCode(Handle<JSFunction> function);

@@ -993,8 +981,6 @@
                                     Handle<JSFunction> function,
                                     Label* miss);

- void GenerateFunctionCheck(Register function, Register scratch, Label* miss);
-
   // Generates a jump to CallIC miss stub.
   void GenerateMissBranch();

=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Thu Nov 28 15:26:04 2013 UTC +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Fri Nov 29 09:02:00 2013 UTC
@@ -3601,7 +3601,7 @@
 }


-void MacroAssembler::InvokeFunction(Register function,
+void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
                                     const ParameterCount& expected,
                                     const ParameterCount& actual,
                                     InvokeFlag flag,
@@ -3610,25 +3610,16 @@
   // You can't call a function without a valid frame.
   ASSERT(flag == JUMP_FUNCTION || has_frame());

-  ASSERT(function.is(rdi));
-  movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
-  // Advances rdx to the end of the Code object header, to the start of
-  // the executable code.
+  // Get the function and setup the context.
+  Move(rdi, function);
+  movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
+
+  // We call indirectly through the code field in the function to
+  // allow recompilation to take effect without changing any of the
+  // call sites.
   movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
-
   InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
 }
-
-
-void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
-                                    const ParameterCount& expected,
-                                    const ParameterCount& actual,
-                                    InvokeFlag flag,
-                                    const CallWrapper& call_wrapper,
-                                    CallKind call_kind) {
-  Move(rdi, function);
-  InvokeFunction(rdi, expected, actual, flag, call_wrapper, call_kind);
-}


 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Thu Nov 28 15:26:04 2013 UTC +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Fri Nov 29 09:02:00 2013 UTC
@@ -371,13 +371,6 @@
                       const CallWrapper& call_wrapper,
                       CallKind call_kind);

-  void InvokeFunction(Register function,
-                      const ParameterCount& expected,
-                      const ParameterCount& actual,
-                      InvokeFlag flag,
-                      const CallWrapper& call_wrapper,
-                      CallKind call_kind);
-
   void InvokeFunction(Handle<JSFunction> function,
                       const ParameterCount& expected,
                       const ParameterCount& actual,
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Thu Nov 28 18:11:15 2013 UTC +++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Fri Nov 29 09:02:00 2013 UTC
@@ -637,7 +637,7 @@

 class CallInterceptorCompiler BASE_EMBEDDED {
  public:
-  CallInterceptorCompiler(CallStubCompiler* stub_compiler,
+  CallInterceptorCompiler(StubCompiler* stub_compiler,
                           const ParameterCount& arguments,
                           Register name,
                           ExtraICState extra_ic_state)
@@ -748,8 +748,13 @@
     if (can_do_fast_api_call) {
       GenerateFastApiCall(masm, optimization, arguments_.immediate());
     } else {
+      CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
+          ? CALL_AS_FUNCTION
+          : CALL_AS_METHOD;
       Handle<JSFunction> fun = optimization.constant_function();
-      stub_compiler_->GenerateJumpFunction(object, fun);
+      ParameterCount expected(fun);
+      __ InvokeFunction(fun, expected, arguments_,
+                        JUMP_FUNCTION, NullCallWrapper(), call_kind);
     }

     // Deferred code for fast API call case---clean preallocated space.
@@ -817,7 +822,7 @@
     __ j(not_equal, interceptor_succeeded);
   }

-  CallStubCompiler* stub_compiler_;
+  StubCompiler* stub_compiler_;
   const ParameterCount& arguments_;
   Register name_;
   ExtraICState extra_ic_state_;
@@ -1530,15 +1535,6 @@
     __ j(not_equal, miss);
   }
 }
-
-
-void CallStubCompiler::GenerateFunctionCheck(Register function,
-                                             Register scratch,
-                                             Label* miss) {
-  __ JumpIfSmi(function, miss);
-  __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
-  __ j(not_equal, miss);
-}


 void CallStubCompiler::GenerateLoadFunctionFromCell(
@@ -1556,7 +1552,9 @@
     // the nice side effect that multiple closures based on the same
     // function can all use this call IC. Before we load through the
     // function, we have to verify that it still is a function.
-    GenerateFunctionCheck(rdi, rax, miss);
+    __ JumpIfSmi(rdi, miss);
+    __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax);
+    __ j(not_equal, miss);

     // Check the shared function info. Make sure it hasn't changed.
     __ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
@@ -1588,7 +1586,20 @@

   GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
index.translate(holder), Representation::Tagged());
-  GenerateJumpFunction(object, rdi, &miss);
+
+  // Check that the function really is a function.
+  __ JumpIfSmi(rdi, &miss);
+  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
+  __ j(not_equal, &miss);
+
+  PatchGlobalProxy(object);
+
+  // Invoke the function.
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
+                    NullCallWrapper(), call_kind);

   HandlerFrontendFooter(&miss);

@@ -2003,7 +2014,8 @@
   __ bind(&miss);
   // Restore function name in rcx.
   __ Move(rcx, name);
-  HandlerFrontendFooter(&name_miss);
+  __ bind(&name_miss);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(type, name);
@@ -2068,7 +2080,8 @@
   __ bind(&miss);
   // Restore function name in rcx.
   __ Move(rcx, name);
-  HandlerFrontendFooter(&name_miss);
+  __ bind(&name_miss);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(type, name);
@@ -2114,10 +2127,15 @@
   StubRuntimeCallHelper call_helper;
   generator.GenerateSlow(masm(), call_helper);

+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
   __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
-  // it.
-  GenerateJumpFunctionIgnoreReceiver(function);
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), call_kind);

   HandlerFrontendFooter(&miss);

@@ -2220,10 +2238,12 @@
   __ movq(rax, args.GetArgumentOperand(1));
   __ ret(2 * kPointerSize);

+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
   __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
-  // it.
-  GenerateJumpFunctionIgnoreReceiver(function);
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);

   HandlerFrontendFooter(&miss);

@@ -2304,10 +2324,15 @@
   __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx);
   __ ret(2 * kPointerSize);

+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
   __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
-  // it.
-  GenerateJumpFunctionIgnoreReceiver(function);
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), call_kind);

   HandlerFrontendFooter(&miss);

@@ -2365,7 +2390,8 @@
   __ bind(&miss);
   __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));

-  HandlerFrontendFooter(&miss_before_stack_reserved);
+  __ bind(&miss_before_stack_reserved);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(function);
@@ -2384,7 +2410,7 @@


 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
-  if (!object.is_null() && object->IsGlobalObject()) {
+  if (object->IsGlobalObject()) {
     StackArgumentsAccessor args(rsp, arguments());
     __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
     __ movq(args.GetReceiverOperand(), rdx);
@@ -2473,18 +2499,39 @@
 }


-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
-                                            Register function,
-                                            Label* miss) {
-  // Check that the function really is a function.
-  GenerateFunctionCheck(function, rbx, miss);
+void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), call_kind);
+}

-  if (!function.is(rdi)) __ movq(rdi, function);
+
+Handle<Code> CallStubCompiler::CompileCallConstant(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<Name> name,
+    CheckType check,
+    Handle<JSFunction> function) {
+  if (HasCustomCallGenerator(function)) {
+    Handle<Code> code = CompileCustomCall(object, holder,
+                                          Handle<PropertyCell>::null(),
+ function, Handle<String>::cast(name),
+                                          Code::FAST);
+    // A null handle means bail out to the regular compiler code below.
+    if (!code.is_null()) return code;
+  }
+
+  Label miss;
+  HandlerFrontendHeader(object, holder, name, check, &miss);
   PatchGlobalProxy(object);
+  CompileHandlerBackend(function);
+  HandlerFrontendFooter(&miss);

-  // Invoke the function.
-  __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
-                    NullCallWrapper(), call_kind());
+  // Return the generated code.
+  return GetCode(function);
 }


@@ -2508,9 +2555,29 @@
   // Restore receiver.
   __ movq(rdx, args.GetReceiverOperand());

-  GenerateJumpFunction(object, rax, &miss);
+  // Check that the function really is a function.
+  __ JumpIfSmi(rax, &miss);
+  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
+  __ j(not_equal, &miss);
+
+  // Patch the receiver on the stack with the global proxy if
+  // necessary.
+  if (object->IsGlobalObject()) {
+    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
+    __ movq(args.GetReceiverOperand(), rdx);
+  }
+
+  // Invoke the function.
+  __ movq(rdi, rax);
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
+                    NullCallWrapper(), call_kind);

-  HandlerFrontendFooter(&miss);
+  // Handle load cache miss.
+  __ bind(&miss);
+  GenerateMissBranch();

   // Return the generated code.
   return GetCode(Code::FAST, name);
@@ -2533,12 +2600,26 @@

   Label miss;
   HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
- // Potentially loads a closure that matches the shared function info of the
-  // function, rather than function.
   GenerateLoadFunctionFromCell(cell, function, &miss);
+  PatchGlobalProxy(object);
+
+  // Set up the context (function already in rdi).
+  __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
+
+  // Jump to the cached code (tail call).
   Counters* counters = isolate()->counters();
   __ IncrementCounter(counters->call_global_inline(), 1);
-  GenerateJumpFunction(object, rdi, function);
+  ParameterCount expected(function->shared()->formal_parameter_count());
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  // We call indirectly through the code field in the function to
+  // allow recompilation to take effect without changing any of the
+  // call sites.
+  __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
+  __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION,
+                NullCallWrapper(), call_kind);
+
   HandlerFrontendFooter(&miss);

   // Return the generated code.

--
--
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