| Index: src/ic/ic.cc
 | 
| diff --git a/src/ic/ic.cc b/src/ic/ic.cc
 | 
| index 1c621fe4822afd89b284ba6b8a2cf2dc41731eb1..9fb89c69eae4912c17cdbdf4a4e939f57fbb8894 100644
 | 
| --- a/src/ic/ic.cc
 | 
| +++ b/src/ic/ic.cc
 | 
| @@ -491,12 +491,11 @@ void IC::Clear(Isolate* isolate, Address address,
 | 
|        return StoreIC::Clear(isolate, address, target, constant_pool);
 | 
|      case Code::KEYED_STORE_IC:
 | 
|        return KeyedStoreIC::Clear(isolate, address, target, constant_pool);
 | 
| -    case Code::CALL_IC:
 | 
| -      return CallIC::Clear(isolate, address, target, constant_pool);
 | 
|      case Code::COMPARE_IC:
 | 
|        return CompareIC::Clear(isolate, address, target, constant_pool);
 | 
|      case Code::COMPARE_NIL_IC:
 | 
|        return CompareNilIC::Clear(address, target, constant_pool);
 | 
| +    case Code::CALL_IC:  // CallICs are vector-based and cleared differently.
 | 
|      case Code::BINARY_OP_IC:
 | 
|      case Code::TO_BOOLEAN_IC:
 | 
|        // Clearing these is tricky and does not
 | 
| @@ -508,6 +507,17 @@ void IC::Clear(Isolate* isolate, Address address,
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void IC::Clear(Isolate* isolate, Code::Kind kind, Code* host,
 | 
| +               TypeFeedbackVector* vector, FeedbackVectorICSlot slot) {
 | 
| +  switch (kind) {
 | 
| +    case Code::CALL_IC:
 | 
| +      return CallIC::Clear(isolate, host, vector, slot);
 | 
| +    default:
 | 
| +      UNREACHABLE();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target,
 | 
|                          ConstantPoolArray* constant_pool) {
 | 
|    if (IsCleared(target)) return;
 | 
| @@ -524,9 +534,19 @@ void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target,
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void CallIC::Clear(Isolate* isolate, Address address, Code* target,
 | 
| -                   ConstantPoolArray* constant_pool) {
 | 
| -  // Currently, CallIC doesn't have state changes.
 | 
| +void CallIC::Clear(Isolate* isolate, Code* host, TypeFeedbackVector* vector,
 | 
| +                   FeedbackVectorICSlot slot) {
 | 
| +  DCHECK(vector != NULL && !slot.IsInvalid());
 | 
| +  Object* feedback = vector->Get(slot);
 | 
| +  // Determine our state.
 | 
| +  State state = FeedbackToState(isolate, vector, slot);
 | 
| +
 | 
| +  if (state != UNINITIALIZED && !feedback->IsAllocationSite()) {
 | 
| +    vector->Set(slot, isolate->heap()->uninitialized_symbol(),
 | 
| +                SKIP_WRITE_BARRIER);
 | 
| +    // The change in state must be processed.
 | 
| +    OnTypeFeedbackChanged(isolate, host, vector, state, UNINITIALIZED);
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1929,9 +1949,34 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
 | 
|  }
 | 
|  
 | 
|  
 | 
| +// static
 | 
| +void CallIC::OnTypeFeedbackChanged(Isolate* isolate, Code* host,
 | 
| +                                   TypeFeedbackVector* vector, State old_state,
 | 
| +                                   State new_state) {
 | 
| +  if (host->kind() != Code::FUNCTION) return;
 | 
| +
 | 
| +  if (FLAG_type_info_threshold > 0) {
 | 
| +    int polymorphic_delta = 0;  // "Polymorphic" here includes monomorphic.
 | 
| +    int generic_delta = 0;      // "Generic" here includes megamorphic.
 | 
| +    ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
 | 
| +                              &generic_delta);
 | 
| +    vector->change_ic_with_type_info_count(polymorphic_delta);
 | 
| +    vector->change_ic_generic_count(generic_delta);
 | 
| +  }
 | 
| +  TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
 | 
| +  info->change_own_type_change_checksum();
 | 
| +  host->set_profiler_ticks(0);
 | 
| +  isolate->runtime_profiler()->NotifyICChanged();
 | 
| +  // TODO(2029): When an optimized function is patched, it would
 | 
| +  // be nice to propagate the corresponding type information to its
 | 
| +  // unoptimized version for the benefit of later inlining.
 | 
| +}
 | 
| +
 | 
| +
 | 
|  bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function,
 | 
|                               Handle<TypeFeedbackVector> vector,
 | 
| -                             Handle<Smi> slot, const CallICState& state) {
 | 
| +                             FeedbackVectorICSlot slot,
 | 
| +                             const CallICState& state) {
 | 
|    DCHECK(FLAG_use_ic && function->IsJSFunction());
 | 
|  
 | 
|    // Are we the array function?
 | 
| @@ -1939,12 +1984,12 @@ bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function,
 | 
|        Handle<JSFunction>(isolate()->native_context()->array_function());
 | 
|    if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) {
 | 
|      // Alter the slot.
 | 
| -    IC::State old_state = FeedbackToState(vector, slot);
 | 
| -    Object* feedback = vector->get(slot->value());
 | 
| +    IC::State old_state = FeedbackToState(isolate(), *vector, slot);
 | 
| +    Object* feedback = vector->Get(slot);
 | 
|      if (!feedback->IsAllocationSite()) {
 | 
|        Handle<AllocationSite> new_site =
 | 
|            isolate()->factory()->NewAllocationSite();
 | 
| -      vector->set(slot->value(), *new_site);
 | 
| +      vector->Set(slot, *new_site);
 | 
|      }
 | 
|  
 | 
|      CallIC_ArrayStub stub(isolate(), state);
 | 
| @@ -1955,8 +2000,8 @@ bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function,
 | 
|                              isolate());
 | 
|      }
 | 
|  
 | 
| -    IC::State new_state = FeedbackToState(vector, slot);
 | 
| -    OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
 | 
| +    IC::State new_state = FeedbackToState(isolate(), *vector, slot);
 | 
| +    OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state);
 | 
|      TRACE_VECTOR_IC("CallIC (custom handler)", name, old_state, new_state);
 | 
|      return true;
 | 
|    }
 | 
| @@ -1966,13 +2011,12 @@ bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function,
 | 
|  
 | 
|  void CallIC::PatchMegamorphic(Handle<Object> function,
 | 
|                                Handle<TypeFeedbackVector> vector,
 | 
| -                              Handle<Smi> slot) {
 | 
| +                              FeedbackVectorICSlot slot) {
 | 
|    CallICState state(target()->extra_ic_state());
 | 
| -  IC::State old_state = FeedbackToState(vector, slot);
 | 
| +  IC::State old_state = FeedbackToState(isolate(), *vector, slot);
 | 
|  
 | 
|    // We are going generic.
 | 
| -  vector->set(slot->value(),
 | 
| -              *TypeFeedbackVector::MegamorphicSentinel(isolate()),
 | 
| +  vector->Set(slot, *TypeFeedbackVector::MegamorphicSentinel(isolate()),
 | 
|                SKIP_WRITE_BARRIER);
 | 
|  
 | 
|    CallICStub stub(isolate(), state);
 | 
| @@ -1985,26 +2029,26 @@ void CallIC::PatchMegamorphic(Handle<Object> function,
 | 
|      name = handle(js_function->shared()->name(), isolate());
 | 
|    }
 | 
|  
 | 
| -  IC::State new_state = FeedbackToState(vector, slot);
 | 
| -  OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
 | 
| +  IC::State new_state = FeedbackToState(isolate(), *vector, slot);
 | 
| +  OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state);
 | 
|    TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function,
 | 
| -                        Handle<TypeFeedbackVector> vector, Handle<Smi> slot) {
 | 
| +                        Handle<TypeFeedbackVector> vector,
 | 
| +                        FeedbackVectorICSlot slot) {
 | 
|    CallICState state(target()->extra_ic_state());
 | 
| -  IC::State old_state = FeedbackToState(vector, slot);
 | 
| +  IC::State old_state = FeedbackToState(isolate(), *vector, slot);
 | 
|    Handle<Object> name = isolate()->factory()->empty_string();
 | 
| -  Object* feedback = vector->get(slot->value());
 | 
| +  Object* feedback = vector->Get(slot);
 | 
|  
 | 
|    // Hand-coded MISS handling is easier if CallIC slots don't contain smis.
 | 
|    DCHECK(!feedback->IsSmi());
 | 
|  
 | 
|    if (feedback->IsJSFunction() || !function->IsJSFunction()) {
 | 
|      // We are going generic.
 | 
| -    vector->set(slot->value(),
 | 
| -                *TypeFeedbackVector::MegamorphicSentinel(isolate()),
 | 
| +    vector->Set(slot, *TypeFeedbackVector::MegamorphicSentinel(isolate()),
 | 
|                  SKIP_WRITE_BARRIER);
 | 
|    } else {
 | 
|      // The feedback is either uninitialized or an allocation site.
 | 
| @@ -2022,7 +2066,7 @@ void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function,
 | 
|        return;
 | 
|      }
 | 
|  
 | 
| -    vector->set(slot->value(), *function);
 | 
| +    vector->Set(slot, *function);
 | 
|    }
 | 
|  
 | 
|    if (function->IsJSFunction()) {
 | 
| @@ -2030,8 +2074,8 @@ void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function,
 | 
|      name = handle(js_function->shared()->name(), isolate());
 | 
|    }
 | 
|  
 | 
| -  IC::State new_state = FeedbackToState(vector, slot);
 | 
| -  OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
 | 
| +  IC::State new_state = FeedbackToState(isolate(), *vector, slot);
 | 
| +  OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state);
 | 
|    TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
 | 
|  }
 | 
|  
 | 
| @@ -2053,7 +2097,8 @@ RUNTIME_FUNCTION(CallIC_Miss) {
 | 
|    Handle<Object> function = args.at<Object>(1);
 | 
|    Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2);
 | 
|    Handle<Smi> slot = args.at<Smi>(3);
 | 
| -  ic.HandleMiss(receiver, function, vector, slot);
 | 
| +  FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
 | 
| +  ic.HandleMiss(receiver, function, vector, vector_slot);
 | 
|    return *function;
 | 
|  }
 | 
|  
 | 
| @@ -2067,7 +2112,8 @@ RUNTIME_FUNCTION(CallIC_Customization_Miss) {
 | 
|    Handle<Object> function = args.at<Object>(1);
 | 
|    Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2);
 | 
|    Handle<Smi> slot = args.at<Smi>(3);
 | 
| -  ic.PatchMegamorphic(function, vector, slot);
 | 
| +  FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
 | 
| +  ic.PatchMegamorphic(function, vector, vector_slot);
 | 
|    return *function;
 | 
|  }
 | 
|  
 | 
| 
 |