Use the HandlerFrontendHeader in most call compilers.
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 28 Nov 2013 13:56:49 +0000 (13:56 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 28 Nov 2013 13:56:49 +0000 (13:56 +0000)
R=ishell@chromium.org

Review URL: https://chromiumcodereview.appspot.com/83753002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18125 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/stub-cache-arm.cc
src/ia32/stub-cache-ia32.cc
src/stub-cache.cc
src/stub-cache.h
src/x64/stub-cache-x64.cc

index 00ea079..b9623fa 100644 (file)
@@ -757,11 +757,11 @@ static void GenerateCallFunction(MacroAssembler* masm,
   __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
   __ b(ne, miss);
 
-  // Patch the receiver on the stack with the global proxy if
-  // necessary.
   if (object->IsGlobalObject()) {
+    const int argc = arguments.immediate();
+    const int receiver_offset = argc * kPointerSize;
     __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
-    __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize));
+    __ str(r3, MemOperand(sp, receiver_offset));
   }
 
   // Invoke the function.
@@ -1541,25 +1541,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
 }
 
 
-void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
-                                                   Handle<JSObject> holder,
-                                                   Handle<Name> name,
-                                                   Label* miss) {
-  ASSERT(holder->IsGlobalObject());
-
-  // Get the number of arguments.
-  const int argc = arguments().immediate();
-
-  // Get the receiver from the stack.
-  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
-
-  // Check that the maps haven't changed.
-  __ JumpIfSmi(r0, miss);
-  CheckPrototypes(
-      IC::CurrentTypeOf(object, isolate()), r0, holder, r3, r1, r4, name, miss);
-}
-
-
 void CallStubCompiler::GenerateLoadFunctionFromCell(
     Handle<Cell> cell,
     Handle<JSFunction> function,
@@ -1603,33 +1584,16 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
                                                 PropertyIndex index,
                                                 Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  // -----------------------------------
   Label miss;
 
-  GenerateNameCheck(name, &miss);
-
-  const int argc = arguments().immediate();
-
-  // Get the receiver of the function from the stack into r0.
-  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(r0, &miss);
-
-  // Do the right check and compute the holder register.
-  Register reg = CheckPrototypes(
-      IC::CurrentTypeOf(object, isolate()),
-      r0, holder, r1, r3, r4, name, &miss);
+  Register reg = HandlerFrontendHeader(
+      object, holder, name, RECEIVER_MAP_CHECK, &miss);
   GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder),
                            index.translate(holder), Representation::Tagged());
 
   GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::FAST, name);
@@ -1645,31 +1609,16 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
     Code::StubType type) {
   Label miss;
 
-  // Check that function is still array
-  const int argc = arguments().immediate();
-  GenerateNameCheck(name, &miss);
-  Register receiver = r1;
-
-  if (cell.is_null()) {
-    __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
-
-    // Check that the receiver isn't a smi.
-    __ JumpIfSmi(receiver, &miss);
-
-    // Check that the maps haven't changed.
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()), receiver, holder,
-        r3, r0, r4, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
   Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
   site->SetElementsKind(GetInitialFastElementsKind());
   Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
+  const int argc = arguments().immediate();
   __ mov(r0, Operand(argc));
   __ mov(r2, Operand(site_feedback_cell));
   __ mov(r1, Operand(function));
@@ -1677,8 +1626,7 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
   ArrayConstructorStub stub(isolate());
   __ TailCallStub(&stub);
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1692,14 +1640,6 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -1708,21 +1648,12 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  Register receiver = r1;
-  // Get the receiver from the stack
-  const int argc = arguments().immediate();
-  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(receiver, &miss);
-
-  // Check that the maps haven't changed.
-  CheckPrototypes(
-      IC::CurrentTypeOf(object, isolate()), receiver, holder,
-      r3, r0, r4, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  Register receiver = r0;
+  Register scratch = r1;
 
+  const int argc = arguments().immediate();
   if (argc == 0) {
     // Nothing to do, just return the length.
     __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
@@ -1741,20 +1672,20 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
 
       // Check that the elements are in fast mode and writable.
       __ CheckMap(elements,
-                  r0,
+                  scratch,
                   Heap::kFixedArrayMapRootIndex,
                   &check_double,
                   DONT_DO_SMI_CHECK);
 
-      // Get the array's length into r0 and calculate new length.
-      __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
-      __ add(r0, r0, Operand(Smi::FromInt(argc)));
+      // Get the array's length into scratch and calculate new length.
+      __ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ add(scratch, scratch, Operand(Smi::FromInt(argc)));
 
       // Get the elements' length.
       __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
 
       // Check if we could survive without allocation.
-      __ cmp(r0, r4);
+      __ cmp(scratch, r4);
       __ b(gt, &attempt_to_grow_elements);
 
       // Check if value is a smi.
@@ -1762,49 +1693,50 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
       __ JumpIfNotSmi(r4, &with_write_barrier);
 
       // Save new length.
-      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
 
       // Store the value.
       // We may need a register containing the address end_elements below,
       // so write back the value in end_elements.
-      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
+      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
       const int kEndElementsOffset =
           FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
       __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
 
       // Check for a smi.
       __ Drop(argc + 1);
+      __ mov(r0, scratch);
       __ Ret();
 
       __ bind(&check_double);
 
       // Check that the elements are in fast mode and writable.
       __ CheckMap(elements,
-                  r0,
+                  scratch,
                   Heap::kFixedDoubleArrayMapRootIndex,
                   &call_builtin,
                   DONT_DO_SMI_CHECK);
 
-      // Get the array's length into r0 and calculate new length.
-      __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
-      __ add(r0, r0, Operand(Smi::FromInt(argc)));
+      // Get the array's length into scratch and calculate new length.
+      __ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ add(scratch, scratch, Operand(Smi::FromInt(argc)));
 
       // Get the elements' length.
       __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
 
       // Check if we could survive without allocation.
-      __ cmp(r0, r4);
+      __ cmp(scratch, r4);
       __ b(gt, &call_builtin);
 
       __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
-      __ StoreNumberToDoubleElements(r4, r0, elements, r5, d0,
+      __ StoreNumberToDoubleElements(r4, scratch, elements, r5, d0,
                                      &call_builtin, argc * kDoubleSize);
 
       // Save new length.
-      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
 
-      // Check for a smi.
       __ Drop(argc + 1);
+      __ mov(r0, scratch);
       __ Ret();
 
       __ bind(&with_write_barrier);
@@ -1855,12 +1787,12 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
       }
 
       // Save new length.
-      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
 
       // Store the value.
       // We may need a register containing the address end_elements below,
       // so write back the value in end_elements.
-      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
+      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
       __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
 
       __ RecordWrite(elements,
@@ -1871,10 +1803,11 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
                      EMIT_REMEMBERED_SET,
                      OMIT_SMI_CHECK);
       __ Drop(argc + 1);
+      __ mov(r0, scratch);
       __ Ret();
 
       __ bind(&attempt_to_grow_elements);
-      // r0: array's length + 1.
+      // scratch: array's length + 1.
 
       if (!FLAG_inline_new) {
         __ b(&call_builtin);
@@ -1896,7 +1829,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
 
       const int kAllocationDelta = 4;
       // Load top and check if it is the end of elements.
-      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
+      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
       __ add(end_elements, end_elements, Operand(kEndElementsOffset));
       __ mov(r4, Operand(new_space_allocation_top));
       __ ldr(r3, MemOperand(r4));
@@ -1921,13 +1854,14 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
       }
 
       // Update elements' and array's sizes.
-      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
       __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
       __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
       __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
 
       // Elements are in new space, so write barrier is not required.
       __ Drop(argc + 1);
+      __ mov(r0, scratch);
       __ Ret();
     }
     __ bind(&call_builtin);
@@ -1935,9 +1869,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
         ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1);
   }
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1951,14 +1883,6 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -1967,26 +1891,18 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
   }
 
   Label miss, return_undefined, call_builtin;
-  Register receiver = r1;
+  Register receiver = r0;
+  Register scratch = r1;
   Register elements = r3;
-  GenerateNameCheck(name, &miss);
-
-  // Get the receiver from the stack
-  const int argc = arguments().immediate();
-  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(receiver, &miss);
 
-  // Check that the maps haven't changed.
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), receiver, holder,
-                  elements, r4, r0, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   // Get the elements array of the object.
   __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
 
   // Check that the elements are in fast mode and writable.
   __ CheckMap(elements,
-              r0,
+              scratch,
               Heap::kFixedArrayMapRootIndex,
               &call_builtin,
               DONT_DO_SMI_CHECK);
@@ -2001,8 +1917,8 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
   // We can't address the last element in one operation. Compute the more
   // expensive shift first, and use an offset later on.
   __ add(elements, elements, Operand::PointerOffsetFromSmiKey(r4));
-  __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize));
-  __ cmp(r0, r6);
+  __ ldr(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize));
+  __ cmp(scratch, r6);
   __ b(eq, &call_builtin);
 
   // Set the array's length.
@@ -2010,7 +1926,9 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
 
   // Fill with the hole.
   __ str(r6, FieldMemOperand(elements, FixedArray::kHeaderSize));
+  const int argc = arguments().immediate();
   __ Drop(argc + 1);
+  __ mov(r0, scratch);
   __ Ret();
 
   __ bind(&return_undefined);
@@ -2022,9 +1940,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
   __ TailCallExternalReference(
       ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2038,18 +1954,9 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2                     : function name
-  //  -- lr                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
 
-  const int argc = arguments().immediate();
   Label miss;
   Label name_miss;
   Label index_out_of_range;
@@ -2060,22 +1967,13 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
        DEFAULT_STRING_STUB)) {
     index_out_of_range_label = &miss;
   }
-  GenerateNameCheck(name, &name_miss);
-
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            r0,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate())));
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      r0, holder, r1, r3, r4, name, &miss);
 
-  Register receiver = r1;
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
+
+  Register receiver = r0;
   Register index = r4;
-  Register result = r0;
+  Register result = r1;
+  const int argc = arguments().immediate();
   __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
   if (argc > 0) {
     __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
@@ -2092,6 +1990,7 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
                                       STRING_INDEX_IS_NUMBER);
   generator.GenerateFast(masm());
   __ Drop(argc + 1);
+  __ mov(r0, result);
   __ Ret();
 
   StubRuntimeCallHelper call_helper;
@@ -2122,14 +2021,6 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2                     : function name
-  //  -- lr                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
 
@@ -2143,24 +2034,13 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
        DEFAULT_STRING_STUB)) {
     index_out_of_range_label = &miss;
   }
-  GenerateNameCheck(name, &name_miss);
-
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            r0,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate())));
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      r0, holder, r1, r3, r4, name, &miss);
+
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
   Register receiver = r0;
   Register index = r4;
   Register scratch = r3;
-  Register result = r0;
-  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
+  Register result = r1;
   if (argc > 0) {
     __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
   } else {
@@ -2177,6 +2057,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
                                   STRING_INDEX_IS_NUMBER);
   generator.GenerateFast(masm());
   __ Drop(argc + 1);
+  __ mov(r0, result);
   __ Ret();
 
   StubRuntimeCallHelper call_helper;
@@ -2207,14 +2088,6 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2                     : function name
-  //  -- lr                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
 
   // If the object is not a JSObject or we got an unexpected number of
@@ -2222,20 +2095,10 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-
-  if (cell.is_null()) {
-    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
-
-    __ JumpIfSmi(r1, &miss);
 
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()),
-        r1, holder, r0, r3, r4, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2265,9 +2128,7 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // r2: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2281,32 +2142,16 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2                     : function name
-  //  -- lr                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss, slow;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
-    __ JumpIfSmi(r1, &miss);
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()),
-        r1, holder, r0, r3, r4, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2375,9 +2220,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // r2: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2391,31 +2234,16 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2                     : function name
-  //  -- lr                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-  if (cell.is_null()) {
-    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
-    __ JumpIfSmi(r1, &miss);
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()),
-        r1, holder, r0, r3, r4, name, &miss);
-  } else {
+
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2475,9 +2303,7 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // r2: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2549,24 +2375,37 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
 }
 
 
-void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
-                                              Handle<JSObject> holder,
-                                              Handle<Name> name,
-                                              CheckType check) {
+void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
+  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));
+  }
+}
+
+
+Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
+                                                 Handle<JSObject> holder,
+                                                 Handle<Name> name,
+                                                 CheckType check,
+                                                 Label* miss) {
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
   // -----------------------------------
-  Label miss;
-  GenerateNameCheck(name, &miss);
+  GenerateNameCheck(name, miss);
+
+  Register reg = r0;
 
   // Get the receiver from the stack
   const int argc = arguments().immediate();
-  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+  const int receiver_offset = argc * kPointerSize;
+  __ ldr(r0, MemOperand(sp, receiver_offset));
 
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
-    __ JumpIfSmi(r1, &miss);
+    __ JumpIfSmi(r0, miss);
   }
 
   // Make sure that it's okay not to patch the on stack receiver
@@ -2574,85 +2413,62 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
   ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
   switch (check) {
     case RECEIVER_MAP_CHECK:
-      __ IncrementCounter(isolate()->counters()->call_const(), 1, r0, r3);
+      __ IncrementCounter(isolate()->counters()->call_const(), 1, r1, r3);
 
       // Check that the maps haven't changed.
-      CheckPrototypes(
+      reg = CheckPrototypes(
           IC::CurrentTypeOf(object, isolate()),
-          r1, holder, r0, r3, r4, name, &miss);
-
-      // Patch the receiver on the stack with the global proxy if
-      // necessary.
-      if (object->IsGlobalObject()) {
-        __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
-        __ str(r3, MemOperand(sp, argc * kPointerSize));
-      }
+          reg, holder, r1, r3, r4, name, miss);
       break;
 
     case STRING_CHECK: {
       // Check that the object is a string.
-      __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
-      __ b(ge, &miss);
+      __ CompareObjectType(reg, r3, r3, FIRST_NONSTRING_TYPE);
+      __ b(ge, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::STRING_FUNCTION_INDEX, r0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          r0, holder, r3, r1, r4, name, &miss);
+          masm(), Context::STRING_FUNCTION_INDEX, r1, miss);
       break;
     }
     case SYMBOL_CHECK: {
       // Check that the object is a symbol.
-      __ CompareObjectType(r1, r1, r3, SYMBOL_TYPE);
-      __ b(ne, &miss);
+      __ CompareObjectType(reg, r3, r3, SYMBOL_TYPE);
+      __ b(ne, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::SYMBOL_FUNCTION_INDEX, r0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          r0, holder, r3, r1, r4, name, &miss);
+          masm(), Context::SYMBOL_FUNCTION_INDEX, r1, miss);
       break;
     }
     case NUMBER_CHECK: {
       Label fast;
       // Check that the object is a smi or a heap number.
-      __ JumpIfSmi(r1, &fast);
-      __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
-      __ b(ne, &miss);
+      __ JumpIfSmi(reg, &fast);
+      __ CompareObjectType(reg, r3, r3, HEAP_NUMBER_TYPE);
+      __ b(ne, miss);
       __ bind(&fast);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          r0, holder, r3, r1, r4, name, &miss);
+          masm(), Context::NUMBER_FUNCTION_INDEX, r1, miss);
       break;
     }
     case BOOLEAN_CHECK: {
-      GenerateBooleanCheck(r1, &miss);
+      GenerateBooleanCheck(reg, miss);
 
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          r0, holder, r3, r1, r4, name, &miss);
+          masm(), Context::BOOLEAN_FUNCTION_INDEX, r1, miss);
       break;
     }
   }
 
-  Label success;
-  __ b(&success);
-
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  if (check != RECEIVER_MAP_CHECK) {
+    Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
+    reg = CheckPrototypes(
+        IC::CurrentTypeOf(prototype, isolate()),
+        r1, holder, r1, r3, r4, name, miss);
+  }
 
-  __ bind(&success);
+  return reg;
 }
 
 
@@ -2681,8 +2497,11 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
     if (!code.is_null()) return code;
   }
 
-  CompileHandlerFrontend(object, holder, name, check);
+  Label miss;
+  HandlerFrontendHeader(object, holder, name, check, &miss);
+  PatchGlobalProxy(object);
   CompileHandlerBackend(function);
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(function);
@@ -2692,10 +2511,6 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
                                                       Handle<JSObject> holder,
                                                       Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  // -----------------------------------
   Label miss;
   GenerateNameCheck(name, &miss);
 
@@ -2733,10 +2548,6 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
     Handle<PropertyCell> cell,
     Handle<JSFunction> function,
     Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  // -----------------------------------
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(
         object, holder, cell, function, Handle<String>::cast(name),
@@ -2746,19 +2557,9 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-
-  // Get the number of arguments.
-  const int argc = arguments().immediate();
-  GenerateGlobalReceiverCheck(object, holder, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
   GenerateLoadFunctionFromCell(cell, function, &miss);
-
-  // Patch the receiver on the stack with the global proxy if
-  // necessary.
-  if (object->IsGlobalObject()) {
-    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
-    __ str(r3, MemOperand(sp, argc * kPointerSize));
-  }
+  PatchGlobalProxy(object);
 
   // Set up the context (function already in r1).
   __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
@@ -2777,10 +2578,7 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
   __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION,
                 NullCallWrapper(), call_kind);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::NORMAL, name);
index 1c98c98..416137b 100644 (file)
@@ -1602,26 +1602,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
 }
 
 
-void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
-                                                   Handle<JSObject> holder,
-                                                   Handle<Name> name,
-                                                   Label* miss) {
-  ASSERT(holder->IsGlobalObject());
-
-  // Get the number of arguments.
-  const int argc = arguments().immediate();
-
-  // Get the receiver from the stack.
-  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-
-
-  // Check that the maps haven't changed.
-  __ JumpIfSmi(edx, miss);
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                  ebx, eax, edi, name, miss);
-}
-
-
 void CallStubCompiler::GenerateLoadFunctionFromCell(
     Handle<Cell> cell,
     Handle<JSFunction> function,
@@ -1668,27 +1648,10 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
                                                 PropertyIndex index,
                                                 Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
   Label miss;
 
-  GenerateNameCheck(name, &miss);
-
-  // 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.
-  __ JumpIfSmi(edx, &miss);
-
-  // Do the right check and compute the holder register.
-  Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx,
-                                 holder, ebx, eax, edi, name, &miss);
+  Register reg = HandlerFrontendHeader(
+      object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   GenerateFastPropertyLoad(
       masm(), edi, reg, index.is_inobject(holder),
@@ -1699,12 +1662,7 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
   __ CmpObjectType(edi, 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);
-  }
+  PatchGlobalProxy(object);
 
   // Invoke the function.
   CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
@@ -1713,9 +1671,7 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
   __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
                     NullCallWrapper(), call_kind);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::FAST, name);
@@ -1731,28 +1687,16 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
     Code::StubType type) {
   Label miss;
 
-  // Check that function is still array
-  const int argc = arguments().immediate();
-  GenerateNameCheck(name, &miss);
-
-  if (cell.is_null()) {
-    // Get the receiver from the stack.
-    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-
-    // Check that the receiver isn't a smi.
-    __ JumpIfSmi(edx, &miss);
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                    ebx, eax, edi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
   Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
   site->SetElementsKind(GetInitialFastElementsKind());
   Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
+  const int argc = arguments().immediate();
   __ mov(eax, Immediate(argc));
   __ mov(ebx, site_feedback_cell);
   __ mov(edi, function);
@@ -1760,8 +1704,7 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
   ArrayConstructorStub stub(isolate());
   __ TailCallStub(&stub);
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1775,14 +1718,6 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -1792,18 +1727,9 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
 
   Label miss;
 
-  GenerateNameCheck(name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
-  // 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.
-  __ JumpIfSmi(edx, &miss);
-
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                  ebx, eax, edi, name, &miss);
-
   if (argc == 0) {
     // Noop, return the length.
     __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
@@ -2021,8 +1947,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
         1);
   }
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2036,14 +1961,6 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -2053,16 +1970,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
 
   Label miss, return_undefined, call_builtin;
 
-  GenerateNameCheck(name, &miss);
-
-  // 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.
-  __ JumpIfSmi(edx, &miss);
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                  ebx, eax, edi, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   // Get the elements array of the object.
   __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
@@ -2094,6 +2002,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
                       ecx, times_half_pointer_size,
                       FixedArray::kHeaderSize),
          Immediate(factory()->the_hole_value()));
+  const int argc = arguments().immediate();
   __ ret((argc + 1) * kPointerSize);
 
   __ bind(&return_undefined);
@@ -2106,8 +2015,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
       argc + 1,
       1);
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2121,14 +2029,6 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : function name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) {
     return Handle<Code>::null();
@@ -2147,18 +2047,7 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
     index_out_of_range_label = &miss;
   }
 
-  GenerateNameCheck(name, &name_miss);
-
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            eax,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      eax, holder, ebx, edx, edi, name, &miss);
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
   Register receiver = ebx;
   Register index = edi;
@@ -2207,14 +2096,6 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : function name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) {
     return Handle<Code>::null();
@@ -2233,18 +2114,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
     index_out_of_range_label = &miss;
   }
 
-  GenerateNameCheck(name, &name_miss);
-
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            eax,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      eax, holder, ebx, edx, edi, name, &miss);
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
   Register receiver = eax;
   Register index = edi;
@@ -2295,14 +2165,6 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : function name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
 
   // If the object is not a JSObject or we got an unexpected number of
@@ -2312,18 +2174,10 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ mov(edx, Operand(esp, 2 * kPointerSize));
-    STATIC_ASSERT(kSmiTag == 0);
-    __ JumpIfSmi(edx, &miss);
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                    ebx, eax, edi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2356,9 +2210,7 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), call_kind);
 
-  __ bind(&miss);
-  // ecx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2372,14 +2224,6 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   if (!CpuFeatures::IsSupported(SSE2)) {
     return Handle<Code>::null();
   }
@@ -2395,20 +2239,10 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-
-  if (cell.is_null()) {
-    __ mov(edx, Operand(esp, 2 * kPointerSize));
 
-    STATIC_ASSERT(kSmiTag == 0);
-    __ JumpIfSmi(edx, &miss);
-
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                    ebx, eax, edi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2488,9 +2322,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // ecx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2504,14 +2336,6 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
 
   // If the object is not a JSObject or we got an unexpected number of
@@ -2521,20 +2345,10 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ mov(edx, Operand(esp, 2 * kPointerSize));
-
-    STATIC_ASSERT(kSmiTag == 0);
-    __ JumpIfSmi(edx, &miss);
-
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                    ebx, eax, edi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2597,9 +2411,7 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // ecx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2676,27 +2488,32 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
 }
 
 
-void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
-                                              Handle<JSObject> holder,
-                                              Handle<Name> name,
-                                              CheckType check) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-  Label miss;
-  GenerateNameCheck(name, &miss);
+void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
+  if (object->IsGlobalObject()) {
+    const int argc = arguments().immediate();
+    const int receiver_offset = (argc + 1) * kPointerSize;
+    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+    __ mov(Operand(esp, receiver_offset), edx);
+  }
+}
+
+
+Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
+                                                 Handle<JSObject> holder,
+                                                 Handle<Name> name,
+                                                 CheckType check,
+                                                 Label* miss) {
+  GenerateNameCheck(name, miss);
+
+  Register reg = edx;
 
-  // Get the receiver from the stack.
   const int argc = arguments().immediate();
-  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+  const int receiver_offset = (argc + 1) * kPointerSize;
+  __ mov(reg, Operand(esp, receiver_offset));
 
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
-    __ JumpIfSmi(edx, &miss);
+    __ JumpIfSmi(reg, miss);
   }
 
   // Make sure that it's okay not to patch the on stack receiver
@@ -2707,80 +2524,58 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
       __ IncrementCounter(isolate()->counters()->call_const(), 1);
 
       // Check that the maps haven't changed.
-      CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                      ebx, eax, edi, name, &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);
-      }
+      reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
+                            ebx, eax, edi, name, miss);
+
       break;
 
     case STRING_CHECK: {
       // Check that the object is a string.
-      __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax);
-      __ j(above_equal, &miss);
+      __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, eax);
+      __ j(above_equal, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::STRING_FUNCTION_INDEX, eax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          eax, holder, ebx, edx, edi, name, &miss);
+          masm(), Context::STRING_FUNCTION_INDEX, eax, miss);
       break;
     }
     case SYMBOL_CHECK: {
       // Check that the object is a symbol.
-      __ CmpObjectType(edx, SYMBOL_TYPE, eax);
-      __ j(not_equal, &miss);
+      __ CmpObjectType(reg, SYMBOL_TYPE, eax);
+      __ j(not_equal, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::SYMBOL_FUNCTION_INDEX, eax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          eax, holder, ebx, edx, edi, name, &miss);
+          masm(), Context::SYMBOL_FUNCTION_INDEX, eax, miss);
       break;
     }
     case NUMBER_CHECK: {
       Label fast;
       // Check that the object is a smi or a heap number.
-      __ JumpIfSmi(edx, &fast);
-      __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
-      __ j(not_equal, &miss);
+      __ JumpIfSmi(reg, &fast);
+      __ CmpObjectType(reg, HEAP_NUMBER_TYPE, eax);
+      __ j(not_equal, miss);
       __ bind(&fast);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          eax, holder, ebx, edx, edi, name, &miss);
+          masm(), Context::NUMBER_FUNCTION_INDEX, eax, miss);
       break;
     }
     case BOOLEAN_CHECK: {
-      GenerateBooleanCheck(edx, &miss);
+      GenerateBooleanCheck(reg, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          eax, holder, ebx, edx, edi, name, &miss);
+          masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, miss);
       break;
     }
   }
 
-  Label success;
-  __ jmp(&success);
-
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  if (check != RECEIVER_MAP_CHECK) {
+    Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
+    reg = CheckPrototypes(
+        IC::CurrentTypeOf(prototype, isolate()),
+        eax, holder, ebx, edx, edi, name, miss);
+  }
 
-  __ bind(&success);
+  return reg;
 }
 
 
@@ -2810,8 +2605,11 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
     if (!code.is_null()) return code;
   }
 
-  CompileHandlerFrontend(object, holder, name, check);
+  Label miss;
+  HandlerFrontendHeader(object, holder, name, check, &miss);
+  PatchGlobalProxy(object);
   CompileHandlerBackend(function);
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(function);
@@ -2821,13 +2619,6 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
                                                       Handle<JSObject> holder,
                                                       Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
   Label miss;
 
   GenerateNameCheck(name, &miss);
@@ -2883,14 +2674,6 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
     Handle<PropertyCell> cell,
     Handle<JSFunction> function,
     Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(
         object, holder, cell, function, Handle<String>::cast(name),
@@ -2900,18 +2683,9 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-
-  // Get the number of arguments.
-  const int argc = arguments().immediate();
-  GenerateGlobalReceiverCheck(object, holder, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
   GenerateLoadFunctionFromCell(cell, function, &miss);
-
-  // Patch the receiver on the stack with the global proxy.
-  if (object->IsGlobalObject()) {
-    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
-    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
-  }
+  PatchGlobalProxy(object);
 
   // Set up the context (function already in edi).
   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
@@ -2930,10 +2704,7 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
                 expected, arguments(), JUMP_FUNCTION,
                 NullCallWrapper(), call_kind);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  __ IncrementCounter(counters->call_global_inline_miss(), 1);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::NORMAL, name);
index 06edc0d..631d64a 100644 (file)
@@ -1126,6 +1126,12 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
 #define __ ACCESS_MASM(masm())
 
 
+void CallStubCompiler::HandlerFrontendFooter(Label* miss) {
+  __ bind(miss);
+  GenerateMissBranch();
+}
+
+
 Register LoadStubCompiler::HandlerFrontendHeader(
     Handle<Type> type,
     Register object_reg,
index 199fca5..223a7fc 100644 (file)
@@ -906,10 +906,17 @@ class CallStubCompiler: public StubCompiler {
                                 PropertyIndex index,
                                 Handle<Name> name);
 
-  void CompileHandlerFrontend(Handle<Object> object,
-                              Handle<JSObject> holder,
-                              Handle<Name> name,
-                              CheckType check);
+  // Patch the global proxy over the global object if the global object is the
+  // receiver.
+  void PatchGlobalProxy(Handle<Object> object);
+
+  // Returns the register containing the holder of |name|.
+  Register HandlerFrontendHeader(Handle<Object> object,
+                                 Handle<JSObject> holder,
+                                 Handle<Name> name,
+                                 CheckType check,
+                                 Label* miss);
+  void HandlerFrontendFooter(Label* miss);
 
   void CompileHandlerBackend(Handle<JSFunction> function);
 
@@ -967,11 +974,6 @@ class CallStubCompiler: public StubCompiler {
 
   void GenerateNameCheck(Handle<Name> name, Label* miss);
 
-  void GenerateGlobalReceiverCheck(Handle<JSObject> object,
-                                   Handle<JSObject> holder,
-                                   Handle<Name> name,
-                                   Label* miss);
-
   // Generates code to load the function from the cell checking that
   // it still contains the same function.
   void GenerateLoadFunctionFromCell(Handle<Cell> cell,
index e64698c..948d61e 100644 (file)
@@ -1537,23 +1537,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
 }
 
 
-void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
-                                                   Handle<JSObject> holder,
-                                                   Handle<Name> name,
-                                                   Label* miss) {
-  ASSERT(holder->IsGlobalObject());
-
-  StackArgumentsAccessor args(rsp, arguments());
-  __ movq(rdx, args.GetReceiverOperand());
-
-
-  // Check that the maps haven't changed.
-  __ JumpIfSmi(rdx, miss);
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                  rbx, rax, rdi, name, miss);
-}
-
-
 void CallStubCompiler::GenerateLoadFunctionFromCell(
     Handle<Cell> cell,
     Handle<JSFunction> function,
@@ -1596,28 +1579,10 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
                                                 PropertyIndex index,
                                                 Handle<Name> name) {
-  // ----------- S t a t e -------------
-  // rcx                 : function name
-  // rsp[0]              : return address
-  // rsp[8]              : argument argc
-  // rsp[16]             : argument argc - 1
-  // ...
-  // rsp[argc * 8]       : argument 1
-  // rsp[(argc + 1) * 8] : argument 0 = receiver
-  // -----------------------------------
   Label miss;
 
-  GenerateNameCheck(name, &miss);
-
-  StackArgumentsAccessor args(rsp, arguments());
-  __ movq(rdx, args.GetReceiverOperand());
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(rdx, &miss);
-
-  // Do the right check and compute the holder register.
-  Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx,
-                                 holder, rbx, rax, rdi, name, &miss);
+  Register reg = HandlerFrontendHeader(
+      object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
                            index.translate(holder), Representation::Tagged());
@@ -1627,12 +1592,7 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
   __ CmpObjectType(rdi, 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);
-  }
+  PatchGlobalProxy(object);
 
   // Invoke the function.
   CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
@@ -1641,9 +1601,7 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
   __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
                     NullCallWrapper(), call_kind);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::FAST, name);
@@ -1659,28 +1617,16 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
     Code::StubType type) {
   Label miss;
 
-  // Check that function is still array
-  const int argc = arguments().immediate();
-  StackArgumentsAccessor args(rsp, argc);
-  GenerateNameCheck(name, &miss);
-
-  if (cell.is_null()) {
-    __ movq(rdx, args.GetReceiverOperand());
-
-    // Check that the receiver isn't a smi.
-    __ JumpIfSmi(rdx, &miss);
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                    rbx, rax, rdi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
   Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
   site->SetElementsKind(GetInitialFastElementsKind());
   Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
+  const int argc = arguments().immediate();
   __ movq(rax, Immediate(argc));
   __ Move(rbx, site_feedback_cell);
   __ Move(rdi, function);
@@ -1688,8 +1634,7 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
   ArrayConstructorStub stub(isolate());
   __ TailCallStub(&stub);
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1719,18 +1664,11 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
+
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   const int argc = arguments().immediate();
   StackArgumentsAccessor args(rsp, argc);
-  __ movq(rdx, args.GetReceiverOperand());
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(rdx, &miss);
-
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                  rbx, rax, rdi, name, &miss);
-
   if (argc == 0) {
     // Noop, return the length.
     __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
@@ -1943,8 +1881,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
                                  1);
   }
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1958,14 +1895,6 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 8] : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -1974,17 +1903,8 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
   }
 
   Label miss, return_undefined, call_builtin;
-  GenerateNameCheck(name, &miss);
-
-  const int argc = arguments().immediate();
-  StackArgumentsAccessor args(rsp, argc);
-  __ movq(rdx, args.GetReceiverOperand());
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(rdx, &miss);
 
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                  rbx, rax, rdi, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   // Get the elements array of the object.
   __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
@@ -2017,6 +1937,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
                        rcx, times_pointer_size,
                        FixedArray::kHeaderSize),
           r9);
+  const int argc = arguments().immediate();
   __ ret((argc + 1) * kPointerSize);
 
   __ bind(&return_undefined);
@@ -2029,8 +1950,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
       argc + 1,
       1);
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2044,20 +1964,9 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : function name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 8] : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
 
-  const int argc = arguments().immediate();
-  StackArgumentsAccessor args(rsp, argc);
-
   Label miss;
   Label name_miss;
   Label index_out_of_range;
@@ -2067,22 +1976,15 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
        DEFAULT_STRING_STUB)) {
     index_out_of_range_label = &miss;
   }
-  GenerateNameCheck(name, &name_miss);
-
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            rax,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      rax, holder, rbx, rdx, rdi, name, &miss);
+
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
   Register receiver = rbx;
   Register index = rdi;
   Register result = rax;
+  const int argc = arguments().immediate();
+  StackArgumentsAccessor args(rsp, argc);
+
   __ movq(receiver, args.GetReceiverOperand());
   if (argc > 0) {
     __ movq(index, args.GetArgumentOperand(1));
@@ -2127,14 +2029,6 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : function name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 8] : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
 
@@ -2150,18 +2044,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
        DEFAULT_STRING_STUB)) {
     index_out_of_range_label = &miss;
   }
-  GenerateNameCheck(name, &name_miss);
-
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            rax,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      rax, holder, rbx, rdx, rdi, name, &miss);
+
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
   Register receiver = rax;
   Register index = rdi;
@@ -2211,14 +2095,6 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : function name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 8] : receiver
-  // -----------------------------------
-
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
   const int argc = arguments().immediate();
@@ -2226,17 +2102,10 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ movq(rdx, args.GetReceiverOperand());
-    __ JumpIfSmi(rdx, &miss);
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                    rbx, rax, rdi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2268,9 +2137,7 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), call_kind);
 
-  __ bind(&miss);
-  // rcx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2284,13 +2151,6 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 4] : receiver
-  // -----------------------------------
   const int argc = arguments().immediate();
   StackArgumentsAccessor args(rsp, argc);
 
@@ -2300,21 +2160,11 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
     return Handle<Code>::null();
   }
 
-  Label miss;
-  GenerateNameCheck(name, &miss);
-
-  if (cell.is_null()) {
-    __ movq(rdx, args.GetReceiverOperand());
+  Label miss, slow;
 
-    STATIC_ASSERT(kSmiTag == 0);
-    __ JumpIfSmi(rdx, &miss);
-
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                    rbx, rax, rdi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2327,7 +2177,6 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
   __ JumpIfSmi(rax, &smi);
 
   // Check if the argument is a heap number and load its value into xmm0.
-  Label slow;
   __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
   __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
 
@@ -2396,9 +2245,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // rcx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2412,14 +2259,6 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : function name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 8] : receiver
-  // -----------------------------------
-
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
   const int argc = arguments().immediate();
@@ -2427,19 +2266,13 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ movq(rdx, args.GetReceiverOperand());
-    __ JumpIfSmi(rdx, &miss);
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                    rbx, rax, rdi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
+
   // Load the (only) argument into rax.
   __ movq(rax, args.GetArgumentOperand(1));
 
@@ -2501,9 +2334,7 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), call_kind);
 
-  __ bind(&miss);
-  // rcx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2578,28 +2409,30 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
 }
 
 
-void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
-                                              Handle<JSObject> holder,
-                                              Handle<Name> name,
-                                              CheckType check) {
-  // ----------- S t a t e -------------
-  // rcx                 : function name
-  // rsp[0]              : return address
-  // rsp[8]              : argument argc
-  // rsp[16]             : argument argc - 1
-  // ...
-  // rsp[argc * 8]       : argument 1
-  // rsp[(argc + 1) * 8] : argument 0 = receiver
-  // -----------------------------------
-  Label miss;
-  GenerateNameCheck(name, &miss);
+void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
+  if (object->IsGlobalObject()) {
+    StackArgumentsAccessor args(rsp, arguments());
+    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
+    __ movq(args.GetReceiverOperand(), rdx);
+  }
+}
+
+
+Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
+                                                 Handle<JSObject> holder,
+                                                 Handle<Name> name,
+                                                 CheckType check,
+                                                 Label* miss) {
+  GenerateNameCheck(name, miss);
+
+  Register reg = rdx;
 
   StackArgumentsAccessor args(rsp, arguments());
-  __ movq(rdx, args.GetReceiverOperand());
+  __ movq(reg, args.GetReceiverOperand());
 
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
-    __ JumpIfSmi(rdx, &miss);
+    __ JumpIfSmi(reg, miss);
   }
 
   // Make sure that it's okay not to patch the on stack receiver
@@ -2612,80 +2445,57 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
       __ IncrementCounter(counters->call_const(), 1);
 
       // Check that the maps haven't changed.
-      CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                      rbx, rax, rdi, name, &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);
-      }
+      reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
+                            rbx, rax, rdi, name, miss);
       break;
 
     case STRING_CHECK: {
       // Check that the object is a string.
-      __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
-      __ j(above_equal, &miss);
+      __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, rax);
+      __ j(above_equal, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::STRING_FUNCTION_INDEX, rax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          rax, holder, rbx, rdx, rdi, name, &miss);
+          masm(), Context::STRING_FUNCTION_INDEX, rax, miss);
       break;
     }
     case SYMBOL_CHECK: {
       // Check that the object is a symbol.
-      __ CmpObjectType(rdx, SYMBOL_TYPE, rax);
-      __ j(not_equal, &miss);
+      __ CmpObjectType(reg, SYMBOL_TYPE, rax);
+      __ j(not_equal, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::SYMBOL_FUNCTION_INDEX, rax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          rax, holder, rbx, rdx, rdi, name, &miss);
+          masm(), Context::SYMBOL_FUNCTION_INDEX, rax, miss);
       break;
     }
     case NUMBER_CHECK: {
       Label fast;
       // Check that the object is a smi or a heap number.
-      __ JumpIfSmi(rdx, &fast);
-      __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax);
-      __ j(not_equal, &miss);
+      __ JumpIfSmi(reg, &fast);
+      __ CmpObjectType(reg, HEAP_NUMBER_TYPE, rax);
+      __ j(not_equal, miss);
       __ bind(&fast);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          rax, holder, rbx, rdx, rdi, name, &miss);
+          masm(), Context::NUMBER_FUNCTION_INDEX, rax, miss);
       break;
     }
     case BOOLEAN_CHECK: {
-      GenerateBooleanCheck(rdx, &miss);
+      GenerateBooleanCheck(reg, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          rax, holder, rbx, rdx, rdi, name, &miss);
+          masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, miss);
       break;
     }
   }
 
-  Label success;
-  __ jmp(&success);
-
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  if (check != RECEIVER_MAP_CHECK) {
+    Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
+    reg = CheckPrototypes(
+        IC::CurrentTypeOf(prototype, isolate()),
+        rax, holder, rbx, rdx, rdi, name, miss);
+  }
 
-  __ bind(&success);
+  return reg;
 }
 
 
@@ -2714,8 +2524,11 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
     if (!code.is_null()) return code;
   }
 
-  CompileHandlerFrontend(object, holder, name, check);
+  Label miss;
+  HandlerFrontendHeader(object, holder, name, check, &miss);
+  PatchGlobalProxy(object);
   CompileHandlerBackend(function);
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(function);
@@ -2725,19 +2538,9 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
                                                       Handle<JSObject> holder,
                                                       Handle<Name> name) {
-  // ----------- S t a t e -------------
-  // rcx                 : function name
-  // rsp[0]              : return address
-  // rsp[8]              : argument argc
-  // rsp[16]             : argument argc - 1
-  // ...
-  // rsp[argc * 8]       : argument 1
-  // rsp[(argc + 1) * 8] : argument 0 = receiver
-  // -----------------------------------
   Label miss;
   GenerateNameCheck(name, &miss);
 
-
   LookupResult lookup(isolate());
   LookupPostInterceptor(holder, name, &lookup);
 
@@ -2787,16 +2590,6 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
     Handle<PropertyCell> cell,
     Handle<JSFunction> function,
     Handle<Name> name) {
-  // ----------- S t a t e -------------
-  // rcx                 : function name
-  // rsp[0]              : return address
-  // rsp[8]              : argument argc
-  // rsp[16]             : argument argc - 1
-  // ...
-  // rsp[argc * 8]       : argument 1
-  // rsp[(argc + 1) * 8] : argument 0 = receiver
-  // -----------------------------------
-
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(
         object, holder, cell, function, Handle<String>::cast(name),
@@ -2806,17 +2599,9 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-
-  StackArgumentsAccessor args(rsp, arguments());
-  GenerateGlobalReceiverCheck(object, holder, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
   GenerateLoadFunctionFromCell(cell, function, &miss);
-
-  // Patch the receiver on the stack with the global proxy.
-  if (object->IsGlobalObject()) {
-    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
-    __ movq(args.GetReceiverOperand(), rdx);
-  }
+  PatchGlobalProxy(object);
 
   // Set up the context (function already in rdi).
   __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
@@ -2835,10 +2620,7 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
   __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION,
                 NullCallWrapper(), call_kind);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  __ IncrementCounter(counters->call_global_inline_miss(), 1);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::NORMAL, name);