Refactor CallICStub to use a different stub for each customization.
authormvstanton@chromium.org <mvstanton@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 28 May 2014 11:29:55 +0000 (11:29 +0000)
committermvstanton@chromium.org <mvstanton@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 28 May 2014 11:29:55 +0000 (11:29 +0000)
This gives us much more room to customize on different functions, by
using MajorKey to differentiate them.

R=verwaest@chromium.org

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

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

src/arm/code-stubs-arm.cc
src/arm64/code-stubs-arm64.cc
src/code-stubs.cc
src/code-stubs.h
src/ia32/code-stubs-ia32.cc
src/ic.cc
src/ic.h
src/mips/code-stubs-mips.cc
src/x64/code-stubs-x64.cc

index 3721253..599e4be 100644 (file)
@@ -3066,13 +3066,18 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
 }
 
 
-void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
+void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
   // r1 - function
-  // r2 - feedback vector
   // r3 - slot id
+  Label miss;
+  int argc = state_.arg_count();
+  ParameterCount actual(argc);
+
+  EmitLoadTypeFeedbackVector(masm, r2);
+
   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4);
   __ cmp(r1, r4);
-  __ b(ne, miss);
+  __ b(ne, &miss);
 
   __ mov(r0, Operand(arg_count()));
   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
@@ -3081,24 +3086,9 @@ void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
   __ AssertUndefinedOrAllocationSite(r2, r4);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);
-}
-
-
-void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) {
-  // r1 - function
-  // r2 - feedback vector
-  // r3 - slot id
-  Label miss;
-
-  if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) {
-    Generate_MonomorphicArray(masm, &miss);
-  } else {
-    // So far there is only one customer for our custom feedback scheme.
-    UNREACHABLE();
-  }
 
   __ bind(&miss);
-  GenerateMiss(masm);
+  GenerateMiss(masm, IC::kCallIC_Customization_Miss);
 
   // The slow case, we need this no matter what to complete a call after a miss.
   CallFunctionNoFeedback(masm,
@@ -3122,11 +3112,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
 
   EmitLoadTypeFeedbackVector(masm, r2);
 
-  if (state_.stub_type() != CallIC::DEFAULT) {
-    Generate_CustomFeedbackCall(masm);
-    return;
-  }
-
   // The checks. First, does r1 match the recorded monomorphic target?
   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
   __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize));
@@ -3174,7 +3159,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
 
   // We are here because tracing is on or we are going monomorphic.
   __ bind(&miss);
-  GenerateMiss(masm);
+  GenerateMiss(masm, IC::kCallIC_Miss);
 
   // the slow case
   __ bind(&slow_start);
@@ -3189,7 +3174,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
 }
 
 
-void CallICStub::GenerateMiss(MacroAssembler* masm) {
+void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) {
   // Get the receiver of the function from the stack; 1 ~ return address.
   __ ldr(r4, MemOperand(sp, (state_.arg_count() + 1) * kPointerSize));
 
@@ -3200,7 +3185,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
     __ Push(r4, r1, r2, r3);
 
     // Call the entry.
-    ExternalReference miss = ExternalReference(IC_Utility(IC::kCallIC_Miss),
+    ExternalReference miss = ExternalReference(IC_Utility(id),
                                                masm->isolate());
     __ CallExternalReference(miss, 4);
 
index 1b939af..bbcbdd3 100644 (file)
@@ -3360,18 +3360,20 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
 }
 
 
-void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
+void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
   // x1 - function
-  // x2 - feedback vector
   // x3 - slot id
+  Label miss;
   Register function = x1;
   Register feedback_vector = x2;
   Register index = x3;
   Register scratch = x4;
 
+  EmitLoadTypeFeedbackVector(masm, feedback_vector);
+
   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch);
   __ Cmp(function, scratch);
-  __ B(ne, miss);
+  __ B(ne, &miss);
 
   Register allocation_site = feedback_vector;
   __ Mov(x0, Operand(arg_count()));
@@ -3384,24 +3386,9 @@ void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
   __ AssertUndefinedOrAllocationSite(allocation_site, scratch);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);
-}
-
-
-void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) {
-  // x1 - function
-  // x2 - feedback vector
-  // x3 - slot id
-  Label miss;
-
-  if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) {
-    Generate_MonomorphicArray(masm, &miss);
-  } else {
-    // So far there is only one customer for our custom feedback scheme.
-    UNREACHABLE();
-  }
 
   __ bind(&miss);
-  GenerateMiss(masm);
+  GenerateMiss(masm, IC::kCallIC_Customization_Miss);
 
   // The slow case, we need this no matter what to complete a call after a miss.
   CallFunctionNoFeedback(masm,
@@ -3431,11 +3418,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
 
   EmitLoadTypeFeedbackVector(masm, feedback_vector);
 
-  if (state_.stub_type() != CallIC::DEFAULT) {
-    Generate_CustomFeedbackCall(masm);
-    return;
-  }
-
   // The checks. First, does x1 match the recorded monomorphic target?
   __ Add(x4, feedback_vector,
          Operand::UntagSmiAndScale(index, kPointerSizeLog2));
@@ -3487,7 +3469,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
 
   // We are here because tracing is on or we are going monomorphic.
   __ bind(&miss);
-  GenerateMiss(masm);
+  GenerateMiss(masm, IC::kCallIC_Miss);
 
   // the slow case
   __ bind(&slow_start);
@@ -3501,7 +3483,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
 }
 
 
-void CallICStub::GenerateMiss(MacroAssembler* masm) {
+void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) {
   ASM_LOCATION("CallICStub[Miss]");
 
   // Get the receiver of the function from the stack; 1 ~ return address.
@@ -3514,7 +3496,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
     __ Push(x4, x1, x2, x3);
 
     // Call the entry.
-    ExternalReference miss = ExternalReference(IC_Utility(IC::kCallIC_Miss),
+    ExternalReference miss = ExternalReference(IC_Utility(id),
                                                masm->isolate());
     __ CallExternalReference(miss, 4);
 
index 02cb930..aaad108 100644 (file)
@@ -470,6 +470,12 @@ Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
 }
 
 
+void CallIC_ArrayStub::PrintState(StringStream* stream) {
+  state_.Print(stream);
+  stream->Add(" (Array)");
+}
+
+
 void CallICStub::PrintState(StringStream* stream) {
   state_.Print(stream);
 }
index 454029a..5fba1cf 100644 (file)
@@ -30,6 +30,7 @@ namespace internal {
   V(CompareNilIC)                        \
   V(MathPow)                             \
   V(CallIC)                              \
+  V(CallIC_Array)                        \
   V(FunctionPrototype)                   \
   V(RecordWrite)                         \
   V(StoreBufferOverflow)                 \
@@ -819,15 +820,26 @@ class CallICStub: public PlatformCodeStub {
   virtual int MinorKey() { return GetExtraICState(); }
   virtual void PrintState(StringStream* stream) V8_FINAL V8_OVERRIDE;
 
- private:
   virtual CodeStub::Major MajorKey() { return CallIC; }
 
   // Code generation helpers.
-  void GenerateMiss(MacroAssembler* masm);
-  void Generate_CustomFeedbackCall(MacroAssembler* masm);
-  void Generate_MonomorphicArray(MacroAssembler* masm, Label* miss);
+  void GenerateMiss(MacroAssembler* masm, IC::UtilityId id);
+
+  const CallIC::State state_;
+};
+
+
+class CallIC_ArrayStub: public CallICStub {
+ public:
+  CallIC_ArrayStub(Isolate* isolate, const CallIC::State& state_in)
+      : CallICStub(isolate, state_in) {}
+
+  virtual void Generate(MacroAssembler* masm);
+
+ protected:
+  virtual void PrintState(StringStream* stream) V8_FINAL V8_OVERRIDE;
 
-  CallIC::State state_;
+  virtual CodeStub::Major MajorKey() { return CallIC_Array; }
 };
 
 
index 9c12520..abf2a63 100644 (file)
@@ -2470,13 +2470,18 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
 }
 
 
-void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
+void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
   // edi - function
-  // ebx - feedback vector
   // edx - slot id
+  Label miss;
+  int argc = state_.arg_count();
+  ParameterCount actual(argc);
+
+  EmitLoadTypeFeedbackVector(masm, ebx);
+
   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
   __ cmp(edi, ecx);
-  __ j(not_equal, miss);
+  __ j(not_equal, &miss);
 
   __ mov(eax, arg_count());
   __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size,
@@ -2485,24 +2490,9 @@ void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
   __ AssertUndefinedOrAllocationSite(ebx);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);
-}
-
-
-void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) {
-  // edi - function
-  // ebx - feedback vector
-  // edx - slot id
-  Label miss;
-
-  if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) {
-    Generate_MonomorphicArray(masm, &miss);
-  } else {
-    // So far there is only one customer for our custom feedback scheme.
-    UNREACHABLE();
-  }
 
   __ bind(&miss);
-  GenerateMiss(masm);
+  GenerateMiss(masm, IC::kCallIC_Customization_Miss);
 
   // The slow case, we need this no matter what to complete a call after a miss.
   CallFunctionNoFeedback(masm,
@@ -2527,11 +2517,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
 
   EmitLoadTypeFeedbackVector(masm, ebx);
 
-  if (state_.stub_type() != CallIC::DEFAULT) {
-    Generate_CustomFeedbackCall(masm);
-    return;
-  }
-
   // The checks. First, does edi match the recorded monomorphic target?
   __ cmp(edi, FieldOperand(ebx, edx, times_half_pointer_size,
                            FixedArray::kHeaderSize));
@@ -2582,7 +2567,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
 
   // We are here because tracing is on or we are going monomorphic.
   __ bind(&miss);
-  GenerateMiss(masm);
+  GenerateMiss(masm, IC::kCallIC_Miss);
 
   // the slow case
   __ bind(&slow_start);
@@ -2600,7 +2585,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
 }
 
 
-void CallICStub::GenerateMiss(MacroAssembler* masm) {
+void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) {
   // Get the receiver of the function from the stack; 1 ~ return address.
   __ mov(ecx, Operand(esp, (state_.arg_count() + 1) * kPointerSize));
 
@@ -2614,7 +2599,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
     __ push(edx);
 
     // Call the entry.
-    ExternalReference miss = ExternalReference(IC_Utility(IC::kCallIC_Miss),
+    ExternalReference miss = ExternalReference(IC_Utility(id),
                                                masm->isolate());
     __ CallExternalReference(miss, 4);
 
index 0f1c3b4..b40885b 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -501,14 +501,6 @@ void CallIC::Clear(Isolate* isolate,
                    Code* target,
                    ConstantPoolArray* constant_pool) {
   // Currently, CallIC doesn't have state changes.
-  if (target->ic_state() != v8::internal::MONOMORPHIC) return;
-  CallIC::State existing_state(target->extra_ic_state());
-
-  // Monomorphic array stubs don't need to be cleared because
-  // 1) the stub doesn't store information that should be cleared, and
-  // 2) the AllocationSite stored in the type feedback vector is immune
-  //    from gc type feedback clearing.
-  ASSERT(existing_state.stub_type() == MONOMORPHIC_ARRAY);
 }
 
 
@@ -1351,7 +1343,7 @@ void CallIC::State::Print(StringStream* stream) const {
 Handle<Code> CallIC::initialize_stub(Isolate* isolate,
                                      int argc,
                                      CallType call_type) {
-  CallICStub stub(isolate, State::DefaultCallState(argc, call_type));
+  CallICStub stub(isolate, State(argc, call_type));
   Handle<Code> code = stub.GetCode();
   return code;
 }
@@ -1825,16 +1817,14 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
 
 CallIC::State::State(ExtraICState extra_ic_state)
     : argc_(ArgcBits::decode(extra_ic_state)),
-      call_type_(CallTypeBits::decode(extra_ic_state)),
-      stub_type_(StubTypeBits::decode(extra_ic_state)) {
+      call_type_(CallTypeBits::decode(extra_ic_state)) {
 }
 
 
 ExtraICState CallIC::State::GetExtraICState() const {
   ExtraICState extra_ic_state =
       ArgcBits::encode(argc_) |
-      CallTypeBits::encode(call_type_) |
-      StubTypeBits::encode(stub_type_);
+      CallTypeBits::encode(call_type_);
   return extra_ic_state;
 }
 
@@ -1853,8 +1843,7 @@ bool CallIC::DoCustomHandler(Handle<Object> receiver,
     // Alter the slot.
     Handle<AllocationSite> new_site = isolate()->factory()->NewAllocationSite();
     vector->set(slot->value(), *new_site);
-    State new_state = state.ToMonomorphicArrayCallState();
-    CallICStub stub(isolate(), new_state);
+    CallIC_ArrayStub stub(isolate(), state);
     set_target(*stub.GetCode());
     Handle<String> name;
     if (array_function->shared()->name()->IsString()) {
@@ -1869,6 +1858,23 @@ bool CallIC::DoCustomHandler(Handle<Object> receiver,
 }
 
 
+void CallIC::PatchMegamorphic(Handle<FixedArray> vector,
+                              Handle<Smi> slot) {
+  State state(target()->extra_ic_state());
+
+  // We are going generic.
+  vector->set(slot->value(),
+              *TypeFeedbackInfo::MegamorphicSentinel(isolate()),
+              SKIP_WRITE_BARRIER);
+
+  CallICStub stub(isolate(), state);
+  Handle<Code> code = stub.GetCode();
+  set_target(*code);
+
+  TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic");
+}
+
+
 void CallIC::HandleMiss(Handle<Object> receiver,
                         Handle<Object> function,
                         Handle<FixedArray> vector,
@@ -1876,23 +1882,12 @@ void CallIC::HandleMiss(Handle<Object> receiver,
   State state(target()->extra_ic_state());
   Object* feedback = vector->get(slot->value());
 
-  if (feedback->IsJSFunction() || !function->IsJSFunction() ||
-      state.stub_type() != DEFAULT) {
+  if (feedback->IsJSFunction() || !function->IsJSFunction()) {
     // We are going generic.
     vector->set(slot->value(),
                 *TypeFeedbackInfo::MegamorphicSentinel(isolate()),
                 SKIP_WRITE_BARRIER);
 
-    State new_state = state.ToGenericState();
-    if (new_state != state) {
-      // Only happens when the array ic goes generic.
-      ASSERT(state.stub_type() == MONOMORPHIC_ARRAY &&
-             FLAG_use_ic);
-      CallICStub stub(isolate(), new_state);
-      Handle<Code> code = stub.GetCode();
-      set_target(*code);
-    }
-
     TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic");
   } else {
     // If we came here feedback must be the uninitialized sentinel,
@@ -1934,6 +1929,19 @@ RUNTIME_FUNCTION(CallIC_Miss) {
 }
 
 
+RUNTIME_FUNCTION(CallIC_Customization_Miss) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 4);
+  // A miss on a custom call ic always results in going megamorphic.
+  CallIC ic(isolate);
+  Handle<Object> function = args.at<Object>(1);
+  Handle<FixedArray> vector = args.at<FixedArray>(2);
+  Handle<Smi> slot = args.at<Smi>(3);
+  ic.PatchMegamorphic(vector, slot);
+  return *function;
+}
+
+
 // Used from ic-<arch>.cc.
 RUNTIME_FUNCTION(LoadIC_Miss) {
   HandleScope scope(isolate);
index cb60bcb..92dd773 100644 (file)
--- a/src/ic.h
+++ b/src/ic.h
@@ -20,6 +20,7 @@ const int kMaxKeyedPolymorphism = 4;
   ICU(LoadIC_Miss)                                    \
   ICU(KeyedLoadIC_Miss)                               \
   ICU(CallIC_Miss)                                    \
+  ICU(CallIC_Customization_Miss)                      \
   ICU(StoreIC_Miss)                                   \
   ICU(StoreIC_ArrayLength)                            \
   ICU(StoreIC_Slow)                                   \
@@ -333,34 +334,16 @@ class IC_Utility {
 class CallIC: public IC {
  public:
   enum CallType { METHOD, FUNCTION };
-  enum StubType { DEFAULT, MONOMORPHIC_ARRAY };
 
   class State V8_FINAL BASE_EMBEDDED {
    public:
     explicit State(ExtraICState extra_ic_state);
 
-    static State MonomorphicArrayCallState(int argc, CallType call_type) {
-      return State(argc, call_type, MONOMORPHIC_ARRAY);
+    State(int argc, CallType call_type)
+        : argc_(argc), call_type_(call_type) {
     }
 
-    static State DefaultCallState(int argc, CallType call_type) {
-      return State(argc, call_type, DEFAULT);
-    }
-
-    // Transition from the current state to another.
-    State ToGenericState() const {
-      return DefaultCallState(arg_count(), call_type());
-    }
-
-    State ToMonomorphicArrayCallState() const {
-      return MonomorphicArrayCallState(arg_count(), call_type());
-    }
-
-    InlineCacheState GetICState() const {
-      return stub_type_ == CallIC::DEFAULT
-          ? ::v8::internal::GENERIC
-          : ::v8::internal::MONOMORPHIC;
-    }
+    InlineCacheState GetICState() const { return ::v8::internal::GENERIC; }
 
     ExtraICState GetExtraICState() const;
 
@@ -369,43 +352,25 @@ class CallIC: public IC {
 
     int arg_count() const { return argc_; }
     CallType call_type() const { return call_type_; }
-    StubType stub_type() const { return stub_type_; }
 
     bool CallAsMethod() const { return call_type_ == METHOD; }
 
     void Print(StringStream* stream) const;
 
-    bool operator==(const State& other_state) const {
-      return (argc_ == other_state.argc_ &&
-              call_type_ == other_state.call_type_ &&
-              stub_type_ == other_state.stub_type_);
-    }
-
-    bool operator!=(const State& other_state) const {
-      return !(*this == other_state);
-    }
-
    private:
-    State(int argc, CallType call_type, StubType stub_type)
-        : argc_(argc),
-        call_type_(call_type),
-        stub_type_(stub_type) {
-    }
-
     class ArgcBits: public BitField<int, 0, Code::kArgumentsBits> {};
     class CallTypeBits: public BitField<CallType, Code::kArgumentsBits, 1> {};
-    class StubTypeBits:
-        public BitField<StubType, Code::kArgumentsBits + 1, 1> {};  // NOLINT
 
     const int argc_;
     const CallType call_type_;
-    const StubType stub_type_;
   };
 
   explicit CallIC(Isolate* isolate)
       : IC(EXTRA_CALL_FRAME, isolate) {
   }
 
+  void PatchMegamorphic(Handle<FixedArray> vector, Handle<Smi> slot);
+
   void HandleMiss(Handle<Object> receiver,
                   Handle<Object> function,
                   Handle<FixedArray> vector,
@@ -416,7 +381,7 @@ class CallIC: public IC {
                        Handle<Object> function,
                        Handle<FixedArray> vector,
                        Handle<Smi> slot,
-                       const State& new_state);
+                       const State& state);
 
   // Code generator routines.
   static Handle<Code> initialize_stub(Isolate* isolate,
index 118b284..962c2f0 100644 (file)
@@ -3227,12 +3227,15 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
 }
 
 
-void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
+void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
   // a1 - function
-  // a2 - feedback vector
   // a3 - slot id
+  Label miss;
+
+  EmitLoadTypeFeedbackVector(masm, a2);
+
   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, at);
-  __ Branch(miss, ne, a1, Operand(at));
+  __ Branch(&miss, ne, a1, Operand(at));
 
   __ li(a0, Operand(arg_count()));
   __ sll(at, a3, kPointerSizeLog2 - kSmiTagSize);
@@ -3242,24 +3245,9 @@ void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
   __ AssertUndefinedOrAllocationSite(a2, at);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);
-}
-
-
-void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) {
-  // a1 - function
-  // a2 - feedback vector
-  // a3 - slot id
-  Label miss;
-
-  if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) {
-    Generate_MonomorphicArray(masm, &miss);
-  } else {
-    // So far there is only one customer for our custom feedback scheme.
-    UNREACHABLE();
-  }
 
   __ bind(&miss);
-  GenerateMiss(masm);
+  GenerateMiss(masm, IC::kCallIC_Customization_Miss);
 
   // The slow case, we need this no matter what to complete a call after a miss.
   CallFunctionNoFeedback(masm,
@@ -3283,11 +3271,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
 
   EmitLoadTypeFeedbackVector(masm, a2);
 
-  if (state_.stub_type() != CallIC::DEFAULT) {
-    Generate_CustomFeedbackCall(masm);
-    return;
-  }
-
   // The checks. First, does r1 match the recorded monomorphic target?
   __ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize);
   __ Addu(t0, a2, Operand(t0));
@@ -3336,7 +3319,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
 
   // We are here because tracing is on or we are going monomorphic.
   __ bind(&miss);
-  GenerateMiss(masm);
+  GenerateMiss(masm, IC::kCallIC_Miss);
 
   // the slow case
   __ bind(&slow_start);
@@ -3351,7 +3334,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
 }
 
 
-void CallICStub::GenerateMiss(MacroAssembler* masm) {
+void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) {
   // Get the receiver of the function from the stack; 1 ~ return address.
   __ lw(t0, MemOperand(sp, (state_.arg_count() + 1) * kPointerSize));
 
@@ -3362,7 +3345,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
     __ Push(t0, a1, a2, a3);
 
     // Call the entry.
-    ExternalReference miss = ExternalReference(IC_Utility(IC::kCallIC_Miss),
+    ExternalReference miss = ExternalReference(IC_Utility(id),
                                                masm->isolate());
     __ CallExternalReference(miss, 4);
 
index 31ef347..20d722c 100644 (file)
@@ -2364,13 +2364,19 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
 }
 
 
-void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
+void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
   // rdi - function
-  // rbx - feedback vector
   // rdx - slot id (as integer)
+  Label miss;
+  int argc = state_.arg_count();
+  ParameterCount actual(argc);
+
+  EmitLoadTypeFeedbackVector(masm, rbx);
+  __ SmiToInteger32(rdx, rdx);
+
   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx);
   __ cmpq(rdi, rcx);
-  __ j(not_equal, miss);
+  __ j(not_equal, &miss);
 
   __ movq(rax, Immediate(arg_count()));
   __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size,
@@ -2380,26 +2386,9 @@ void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
   __ AssertUndefinedOrAllocationSite(rbx);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);
-}
-
-
-void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) {
-  // rdi - function
-  // rbx - feedback vector
-  // rdx - slot id
-  Label miss;
-
-  __ SmiToInteger32(rdx, rdx);
-
-  if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) {
-    Generate_MonomorphicArray(masm, &miss);
-  } else {
-    // So far there is only one customer for our custom feedback scheme.
-    UNREACHABLE();
-  }
 
   __ bind(&miss);
-  GenerateMiss(masm);
+  GenerateMiss(masm, IC::kCallIC_Customization_Miss);
 
   // The slow case, we need this no matter what to complete a call after a miss.
   CallFunctionNoFeedback(masm,
@@ -2426,11 +2415,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
 
   EmitLoadTypeFeedbackVector(masm, rbx);
 
-  if (state_.stub_type() != CallIC::DEFAULT) {
-    Generate_CustomFeedbackCall(masm);
-    return;
-  }
-
   // The checks. First, does rdi match the recorded monomorphic target?
   __ SmiToInteger32(rdx, rdx);
   __ cmpq(rdi, FieldOperand(rbx, rdx, times_pointer_size,
@@ -2482,7 +2466,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
 
   // We are here because tracing is on or we are going monomorphic.
   __ bind(&miss);
-  GenerateMiss(masm);
+  GenerateMiss(masm, IC::kCallIC_Miss);
 
   // the slow case
   __ bind(&slow_start);
@@ -2498,7 +2482,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
 }
 
 
-void CallICStub::GenerateMiss(MacroAssembler* masm) {
+void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) {
   // Get the receiver of the function from the stack; 1 ~ return address.
   __ movp(rcx, Operand(rsp, (state_.arg_count() + 1) * kPointerSize));
 
@@ -2513,7 +2497,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
     __ Push(rdx);
 
     // Call the entry.
-    ExternalReference miss = ExternalReference(IC_Utility(IC::kCallIC_Miss),
+    ExternalReference miss = ExternalReference(IC_Utility(id),
                                                masm->isolate());
     __ CallExternalReference(miss, 4);