Revision: 7246
Author:   [email protected]
Date:     Thu Mar 17 10:25:54 2011
Log:      Refactor fast API call.

Make it use custom call generator infrastructure.

Review URL: http://codereview.chromium.org/6686003
http://code.google.com/p/v8/source/detail?r=7246

Modified:
 /branches/bleeding_edge/src/arm/stub-cache-arm.cc
 /branches/bleeding_edge/src/hydrogen.cc
 /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/stub-cache-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Wed Mar 9 07:01:16 2011 +++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Thu Mar 17 10:25:54 2011
@@ -2276,6 +2276,60 @@
   // Return the generated code.
   return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
 }
+
+
+MaybeObject* CallStubCompiler::CompileFastApiCall(
+    const CallOptimization& optimization,
+    Object* object,
+    JSObject* holder,
+    JSGlobalPropertyCell* cell,
+    JSFunction* function,
+    String* name) {
+  ASSERT(optimization.is_simple_api_call());
+  // Bail out if object is a global object as we don't want to
+  // repatch it to global receiver.
+  if (object->IsGlobalObject()) return Heap::undefined_value();
+  if (cell != NULL) return Heap::undefined_value();
+  int depth = optimization.GetPrototypeDepthOfExpectedType(
+            JSObject::cast(object), holder);
+  if (depth == kInvalidProtoDepth) return Heap::undefined_value();
+
+  Label miss, miss_before_stack_reserved;
+
+  GenerateNameCheck(name, &miss_before_stack_reserved);
+
+  // Get the receiver from the stack.
+  const int argc = arguments().immediate();
+  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+
+  // Check that the receiver isn't a smi.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, &miss_before_stack_reserved);
+
+  __ IncrementCounter(&Counters::call_const, 1, r0, r3);
+  __ IncrementCounter(&Counters::call_const_fast_api, 1, r0, r3);
+
+  ReserveSpaceForFastApiCall(masm(), r0);
+
+ // Check that the maps haven't changed and find a Holder as a side effect.
+  CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
+                  depth, &miss);
+
+ MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc);
+  if (result->IsFailure()) return result;
+
+  __ bind(&miss);
+  FreeSpaceForFastApiCall(masm());
+
+  __ bind(&miss_before_stack_reserved);
+  Object* obj;
+  { MaybeObject* maybe_obj = GenerateMissBranch();
+    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+  }
+
+  // Return the generated code.
+  return GetCode(function);
+}


 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
@@ -2287,22 +2341,18 @@
   //  -- r2    : name
   //  -- lr    : return address
   // -----------------------------------
-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder, NULL, function, name);
+        object, holder, NULL, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
-    if (!result->IsUndefined()) {
-      return result;
-    }
+    if (!result->IsUndefined()) return result;
   }

-  Label miss_in_smi_check;
-
-  GenerateNameCheck(name, &miss_in_smi_check);
+  Label miss;
+
+  GenerateNameCheck(name, &miss);

   // Get the receiver from the stack
   const int argc = arguments().immediate();
@@ -2311,39 +2361,25 @@
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
     __ tst(r1, Operand(kSmiTagMask));
-    __ b(eq, &miss_in_smi_check);
+    __ b(eq, &miss);
   }

   // Make sure that it's okay not to patch the on stack receiver
   // unless we're doing a receiver map check.
   ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);

-  CallOptimization optimization(function);
-  int depth = kInvalidProtoDepth;
-  Label miss;
-
+  SharedFunctionInfo* function_info = function->shared();
   switch (check) {
     case RECEIVER_MAP_CHECK:
       __ IncrementCounter(&Counters::call_const, 1, r0, r3);

-      if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
-        depth = optimization.GetPrototypeDepthOfExpectedType(
-            JSObject::cast(object), holder);
-      }
-
-      if (depth != kInvalidProtoDepth) {
-        __ IncrementCounter(&Counters::call_const_fast_api, 1, r0, r3);
-        ReserveSpaceForFastApiCall(masm(), r0);
-      }
-
       // Check that the maps haven't changed.
       CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
-                      depth, &miss);
+                      &miss);

       // Patch the receiver on the stack with the global proxy if
       // necessary.
       if (object->IsGlobalObject()) {
-        ASSERT(depth == kInvalidProtoDepth);
__ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
         __ str(r3, MemOperand(sp, argc * kPointerSize));
       }
@@ -2416,20 +2452,10 @@
       UNREACHABLE();
   }

-  if (depth != kInvalidProtoDepth) {
- MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc);
-    if (result->IsFailure()) return result;
-  } else {
-    __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
-  }
+  __ InvokeFunction(function, arguments(), JUMP_FUNCTION);

   // Handle call cache miss.
   __ bind(&miss);
-  if (depth != kInvalidProtoDepth) {
-    FreeSpaceForFastApiCall(masm());
-  }
-
-  __ bind(&miss_in_smi_check);
   Object* obj;
   { MaybeObject* maybe_obj = GenerateMissBranch();
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
@@ -2505,11 +2531,9 @@
   //  -- lr    : return address
   // -----------------------------------

-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder, cell, function, name);
+        object, holder, cell, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Thu Mar 17 07:30:48 2011
+++ /branches/bleeding_edge/src/hydrogen.cc     Thu Mar 17 10:25:54 2011
@@ -4222,13 +4222,6 @@
   ast_context()->ReturnInstruction(result, expr->id());
   return true;
 }
-
-
-static bool HasCustomCallGenerator(Handle<JSFunction> function) {
-  SharedFunctionInfo* info = function->shared();
-  return info->HasBuiltinFunctionId() &&
- CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id());
-}


 void HGraphBuilder::VisitCall(Call* expr) {
@@ -4288,13 +4281,11 @@
         return;
       }

-      if (HasCustomCallGenerator(expr->target()) ||
-          CallOptimization(*expr->target()).is_simple_api_call() ||
+      if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) ||
           expr->check_type() != RECEIVER_MAP_CHECK) {
         // When the target has a custom call IC generator, use the IC,
-        // because it is likely to generate better code.  Similarly, we
-        // generate better call stubs for some API functions.
-        // Also use the IC when a primitive receiver check is required.
+        // because it is likely to generate better code.  Also use the IC
+        // when a primitive receiver check is required.
         HContext* context = new HContext;
         AddInstruction(context);
call = PreProcessCall(new HCallNamed(context, name, argument_count));
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Wed Mar 9 07:01:16 2011 +++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Thu Mar 17 10:25:54 2011
@@ -2125,6 +2125,68 @@
   // Return the generated code.
   return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
 }
+
+
+MaybeObject* CallStubCompiler::CompileFastApiCall(
+    const CallOptimization& optimization,
+    Object* object,
+    JSObject* holder,
+    JSGlobalPropertyCell* cell,
+    JSFunction* function,
+    String* name) {
+  ASSERT(optimization.is_simple_api_call());
+  // Bail out if object is a global object as we don't want to
+  // repatch it to global receiver.
+  if (object->IsGlobalObject()) return Heap::undefined_value();
+  if (cell != NULL) return Heap::undefined_value();
+  int depth = optimization.GetPrototypeDepthOfExpectedType(
+            JSObject::cast(object), holder);
+  if (depth == kInvalidProtoDepth) return Heap::undefined_value();
+
+  Label miss, miss_before_stack_reserved;
+
+  GenerateNameCheck(name, &miss_before_stack_reserved);
+
+  // Get the receiver from the stack.
+  const int argc = arguments().immediate();
+  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+
+  // Check that the receiver isn't a smi.
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(zero, &miss_before_stack_reserved, not_taken);
+
+  __ IncrementCounter(&Counters::call_const, 1);
+  __ IncrementCounter(&Counters::call_const_fast_api, 1);
+
+  // Allocate space for v8::Arguments implicit values. Must be initialized
+  // before calling any runtime function.
+  __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
+
+ // Check that the maps haven't changed and find a Holder as a side effect.
+  CheckPrototypes(JSObject::cast(object), edx, holder,
+                  ebx, eax, edi, name, depth, &miss);
+
+  // Move the return address on top of the stack.
+  __ mov(eax, Operand(esp, 3 * kPointerSize));
+  __ mov(Operand(esp, 0 * kPointerSize), eax);
+
+  // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
+  // duplicate of return address and will be overwritten.
+  MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc);
+  if (result->IsFailure()) return result;
+
+  __ bind(&miss);
+  __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
+
+  __ bind(&miss_before_stack_reserved);
+  Object* obj;
+  { MaybeObject* maybe_obj = GenerateMissBranch();
+    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+  }
+
+  // Return the generated code.
+  return GetCode(function);
+}


 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
@@ -2140,20 +2202,18 @@
   //  -- esp[(argc + 1) * 4] : receiver
   // -----------------------------------

-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder, NULL, function, name);
+        object, holder, NULL, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
     if (!result->IsUndefined()) return result;
   }

-  Label miss_in_smi_check;
-
-  GenerateNameCheck(name, &miss_in_smi_check);
+  Label miss;
+
+  GenerateNameCheck(name, &miss);

   // Get the receiver from the stack.
   const int argc = arguments().immediate();
@@ -2162,42 +2222,25 @@
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
     __ test(edx, Immediate(kSmiTagMask));
-    __ j(zero, &miss_in_smi_check, not_taken);
+    __ j(zero, &miss, not_taken);
   }

   // Make sure that it's okay not to patch the on stack receiver
   // unless we're doing a receiver map check.
   ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);

-  CallOptimization optimization(function);
-  int depth = kInvalidProtoDepth;
-  Label miss;
-
+  SharedFunctionInfo* function_info = function->shared();
   switch (check) {
     case RECEIVER_MAP_CHECK:
       __ IncrementCounter(&Counters::call_const, 1);

-      if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
-        depth = optimization.GetPrototypeDepthOfExpectedType(
-            JSObject::cast(object), holder);
-      }
-
-      if (depth != kInvalidProtoDepth) {
-        __ IncrementCounter(&Counters::call_const_fast_api, 1);
-
- // Allocate space for v8::Arguments implicit values. Must be initialized
-        // before to call any runtime function.
- __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
-      }
-
       // Check that the maps haven't changed.
       CheckPrototypes(JSObject::cast(object), edx, holder,
-                      ebx, eax, edi, name, depth, &miss);
+                      ebx, eax, edi, name, &miss);

       // Patch the receiver on the stack with the global proxy if
       // necessary.
       if (object->IsGlobalObject()) {
-        ASSERT(depth == kInvalidProtoDepth);
__ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
         __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
       }
@@ -2268,25 +2311,10 @@
       UNREACHABLE();
   }

-  if (depth != kInvalidProtoDepth) {
-    // Move the return address on top of the stack.
-    __ mov(eax, Operand(esp, 3 * kPointerSize));
-    __ mov(Operand(esp, 0 * kPointerSize), eax);
-
- // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
-    // duplicate of return address and will be overwritten.
-    MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc);
-    if (result->IsFailure()) return result;
-  } else {
-    __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
-  }
+  __ InvokeFunction(function, arguments(), JUMP_FUNCTION);

   // Handle call cache miss.
   __ bind(&miss);
-  if (depth != kInvalidProtoDepth) {
-    __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
-  }
-  __ bind(&miss_in_smi_check);
   Object* obj;
   { MaybeObject* maybe_obj = GenerateMissBranch();
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
@@ -2378,11 +2406,9 @@
   //  -- esp[(argc + 1) * 4] : receiver
   // -----------------------------------

-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder, cell, function, name);
+        object, holder, cell, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
=======================================
--- /branches/bleeding_edge/src/stub-cache.cc   Wed Mar  9 07:01:16 2011
+++ /branches/bleeding_edge/src/stub-cache.cc   Thu Mar 17 10:25:54 2011
@@ -1726,32 +1726,51 @@
 }


-bool CallStubCompiler::HasCustomCallGenerator(BuiltinFunctionId id) {
+bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) {
+  SharedFunctionInfo* info = function->shared();
+  if (info->HasBuiltinFunctionId()) {
+    BuiltinFunctionId id = info->builtin_function_id();
 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
-  CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
+    CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
 #undef CALL_GENERATOR_CASE
+  }
+  CallOptimization optimization(function);
+  if (optimization.is_simple_api_call()) {
+    return true;
+  }
   return false;
 }


-MaybeObject* CallStubCompiler::CompileCustomCall(BuiltinFunctionId id,
-                                                 Object* object,
+MaybeObject* CallStubCompiler::CompileCustomCall(Object* object,
                                                  JSObject* holder,
JSGlobalPropertyCell* cell,
                                                  JSFunction* function,
                                                  String* fname) {
-#define CALL_GENERATOR_CASE(name)                          \
-  if (id == k##name) {                                     \
-    return CallStubCompiler::Compile##name##Call(object,   \
-                                                 holder,   \
-                                                 cell,     \
-                                                 function, \
-                                                 fname);   \
-  }
-  CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
+  ASSERT(HasCustomCallGenerator(function));
+
+  SharedFunctionInfo* info = function->shared();
+  if (info->HasBuiltinFunctionId()) {
+    BuiltinFunctionId id = info->builtin_function_id();
+#define CALL_GENERATOR_CASE(name)                           \
+    if (id == k##name) {                                    \
+      return CallStubCompiler::Compile##name##Call(object,  \
+                                                  holder,   \
+                                                  cell,     \
+                                                  function, \
+                                                  fname);   \
+    }
+    CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
 #undef CALL_GENERATOR_CASE
-  ASSERT(!HasCustomCallGenerator(id));
-  return Heap::undefined_value();
+  }
+  CallOptimization optimization(function);
+  ASSERT(optimization.is_simple_api_call());
+  return CompileFastApiCall(optimization,
+                            object,
+                            holder,
+                            cell,
+                            function,
+                            fname);
 }


=======================================
--- /branches/bleeding_edge/src/stub-cache.h    Wed Mar  9 07:01:16 2011
+++ /branches/bleeding_edge/src/stub-cache.h    Thu Mar 17 10:25:54 2011
@@ -680,6 +680,8 @@
   V(MathAbs)


+class CallOptimization;
+
 class CallStubCompiler: public StubCompiler {
  public:
   CallStubCompiler(int argc,
@@ -706,14 +708,13 @@
                                                  JSFunction* function,
                                                  String* name);

-  static bool HasCustomCallGenerator(BuiltinFunctionId id);
+  static bool HasCustomCallGenerator(JSFunction* function);

  private:
   // Compiles a custom call constant/global IC. For constant calls
   // cell is NULL. Returns undefined if there is no custom call code
   // for the given function or it can't be generated.
-  MUST_USE_RESULT MaybeObject* CompileCustomCall(BuiltinFunctionId id,
-                                                 Object* object,
+  MUST_USE_RESULT MaybeObject* CompileCustomCall(Object* object,
                                                  JSObject* holder,
JSGlobalPropertyCell* cell,
                                                  JSFunction* function,
@@ -728,6 +729,14 @@
   CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
 #undef DECLARE_CALL_GENERATOR

+  MUST_USE_RESULT MaybeObject* CompileFastApiCall(
+      const CallOptimization& optimization,
+      Object* object,
+      JSObject* holder,
+      JSGlobalPropertyCell* cell,
+      JSFunction* function,
+      String* name);
+
   const ParameterCount arguments_;
   const InLoopFlag in_loop_;
   const Code::Kind kind_;
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Wed Mar 9 07:01:16 2011 +++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Thu Mar 17 10:25:54 2011
@@ -1980,6 +1980,65 @@
   // Return the generated code.
   return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
 }
+
+
+MaybeObject* CallStubCompiler::CompileFastApiCall(
+    const CallOptimization& optimization,
+    Object* object,
+    JSObject* holder,
+    JSGlobalPropertyCell* cell,
+    JSFunction* function,
+    String* name) {
+  ASSERT(optimization.is_simple_api_call());
+  // Bail out if object is a global object as we don't want to
+  // repatch it to global receiver.
+  if (object->IsGlobalObject()) return Heap::undefined_value();
+  if (cell != NULL) return Heap::undefined_value();
+  int depth = optimization.GetPrototypeDepthOfExpectedType(
+            JSObject::cast(object), holder);
+  if (depth == kInvalidProtoDepth) return Heap::undefined_value();
+
+  Label miss, miss_before_stack_reserved;
+
+  GenerateNameCheck(name, &miss_before_stack_reserved);
+
+  // Get the receiver from the stack.
+  const int argc = arguments().immediate();
+  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(rdx, &miss_before_stack_reserved);
+
+  __ IncrementCounter(&Counters::call_const, 1);
+  __ IncrementCounter(&Counters::call_const_fast_api, 1);
+
+  // Allocate space for v8::Arguments implicit values. Must be initialized
+  // before calling any runtime function.
+  __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
+
+ // Check that the maps haven't changed and find a Holder as a side effect.
+  CheckPrototypes(JSObject::cast(object), rdx, holder,
+                  rbx, rax, rdi, name, depth, &miss);
+
+  // Move the return address on top of the stack.
+  __ movq(rax, Operand(rsp, 3 * kPointerSize));
+  __ movq(Operand(rsp, 0 * kPointerSize), rax);
+
+  MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc);
+  if (result->IsFailure()) return result;
+
+  __ bind(&miss);
+  __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
+
+  __ bind(&miss_before_stack_reserved);
+  Object* obj;
+  { MaybeObject* maybe_obj = GenerateMissBranch();
+    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+  }
+
+  // Return the generated code.
+  return GetCode(function);
+}


 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
@@ -1997,20 +2056,18 @@
   // rsp[(argc + 1) * 8] : argument 0 = receiver
   // -----------------------------------

-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder,  NULL, function, name);
+        object, holder, NULL, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
     if (!result->IsUndefined()) return result;
   }

-  Label miss_in_smi_check;
-
-  GenerateNameCheck(name, &miss_in_smi_check);
+  Label miss;
+
+  GenerateNameCheck(name, &miss);

   // Get the receiver from the stack.
   const int argc = arguments().immediate();
@@ -2018,42 +2075,25 @@

   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
-    __ JumpIfSmi(rdx, &miss_in_smi_check);
+    __ JumpIfSmi(rdx, &miss);
   }

   // Make sure that it's okay not to patch the on stack receiver
   // unless we're doing a receiver map check.
   ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);

-  CallOptimization optimization(function);
-  int depth = kInvalidProtoDepth;
-  Label miss;
-
+  SharedFunctionInfo* function_info = function->shared();
   switch (check) {
     case RECEIVER_MAP_CHECK:
       __ IncrementCounter(&Counters::call_const, 1);

-      if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
-        depth = optimization.GetPrototypeDepthOfExpectedType(
-            JSObject::cast(object), holder);
-      }
-
-      if (depth != kInvalidProtoDepth) {
-        __ IncrementCounter(&Counters::call_const_fast_api, 1);
-
- // Allocate space for v8::Arguments implicit values. Must be initialized
-        // before to call any runtime function.
-        __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
-      }
-
       // Check that the maps haven't changed.
       CheckPrototypes(JSObject::cast(object), rdx, holder,
-                      rbx, rax, rdi, name, depth, &miss);
+                      rbx, rax, rdi, name, &miss);

       // Patch the receiver on the stack with the global proxy if
       // necessary.
       if (object->IsGlobalObject()) {
-        ASSERT(depth == kInvalidProtoDepth);
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
         __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
       }
@@ -2123,27 +2163,10 @@
       UNREACHABLE();
   }

-  if (depth != kInvalidProtoDepth) {
-    // Move the return address on top of the stack.
-    __ movq(rax, Operand(rsp, 3 * kPointerSize));
-    __ movq(Operand(rsp, 0 * kPointerSize), rax);
-
- // rsp[2 * kPointerSize] is uninitialized, rsp[3 * kPointerSize] contains
-    // duplicate of return address and will be overwritten.
-    MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc);
-    if (result->IsFailure()) return result;
-  } else {
-    __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
-  }
+  __ InvokeFunction(function, arguments(), JUMP_FUNCTION);

   // Handle call cache miss.
   __ bind(&miss);
-  if (depth != kInvalidProtoDepth) {
-    __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
-  }
-
-  // Handle call cache miss.
-  __ bind(&miss_in_smi_check);
   Object* obj;
   { MaybeObject* maybe_obj = GenerateMissBranch();
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
@@ -2238,11 +2261,9 @@
   // rsp[(argc + 1) * 8] : argument 0 = receiver
   // -----------------------------------

-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder, cell, function, name);
+        object, holder, cell, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
@@ -2960,7 +2981,7 @@
   // ----------- S t a t e -------------
   //  -- rax    : key
   //  -- rdx    : receiver
-  //  -- esp[0] : return address
+  //  -- rsp[0] : return address
   // -----------------------------------
   Label miss;

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to