| Index: src/ic/ic.cc | 
| diff --git a/src/ic/ic.cc b/src/ic/ic.cc | 
| index 98d86b5e39f41e97b45bc301e92e5768ba4a2616..f45d04cc795a72b26979cb07a47c597caf08d9b6 100644 | 
| --- a/src/ic/ic.cc | 
| +++ b/src/ic/ic.cc | 
| @@ -89,8 +89,8 @@ const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) { | 
|  | 
| void IC::TraceIC(const char* type, Handle<Object> name) { | 
| if (FLAG_trace_ic) { | 
| -    Code* new_target = raw_target(); | 
| -    State new_state = new_target->ic_state(); | 
| +    State new_state = | 
| +        UseVector() ? nexus()->StateFromFeedback() : raw_target()->ic_state(); | 
| TraceIC(type, name, state(), new_state); | 
| } | 
| } | 
| @@ -134,12 +134,16 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state, | 
| } | 
| } | 
|  | 
| + | 
| #define TRACE_IC(type, name) TraceIC(type, name) | 
| -#define TRACE_VECTOR_IC(type, name, old_state, new_state) \ | 
| -  TraceIC(type, name, old_state, new_state) | 
|  | 
| -IC::IC(FrameDepth depth, Isolate* isolate) | 
| -    : isolate_(isolate), target_set_(false), target_maps_set_(false) { | 
| + | 
| +IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus, | 
| +       bool for_queries_only) | 
| +    : isolate_(isolate), | 
| +      target_set_(false), | 
| +      target_maps_set_(false), | 
| +      nexus_(nexus) { | 
| // To improve the performance of the (much used) IC code, we unfold a few | 
| // levels of the stack frame iteration code. This yields a ~35% speedup when | 
| // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. | 
| @@ -178,8 +182,10 @@ IC::IC(FrameDepth depth, Isolate* isolate) | 
| } | 
| pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); | 
| target_ = handle(raw_target(), isolate); | 
| -  state_ = target_->ic_state(); | 
| kind_ = target_->kind(); | 
| +  state_ = (!for_queries_only && UseVector()) ? nexus->StateFromFeedback() | 
| +                                              : target_->ic_state(); | 
| +  old_state_ = state_; | 
| extra_ic_state_ = target_->extra_ic_state(); | 
| } | 
|  | 
| @@ -419,6 +425,30 @@ void IC::OnTypeFeedbackChanged(Isolate* isolate, Address address, | 
| } | 
|  | 
|  | 
| +// static | 
| +void IC::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. | 
| +} | 
| + | 
| + | 
| void IC::PostPatching(Address address, Code* target, Code* old_target) { | 
| // Type vector based ICs update these statistics at a different time because | 
| // they don't always patch on state change. | 
| @@ -507,17 +537,21 @@ void IC::Clear(Isolate* isolate, Address address, | 
| } | 
|  | 
|  | 
| -void IC::Clear(Isolate* isolate, Code::Kind kind, Code* host, | 
| -               TypeFeedbackVector* vector, FeedbackVectorICSlot slot) { | 
| +template <class Nexus> | 
| +void IC::Clear(Isolate* isolate, Code::Kind kind, Code* host, Nexus* nexus) { | 
| switch (kind) { | 
| case Code::CALL_IC: | 
| -      return CallIC::Clear(isolate, host, vector, slot); | 
| +      return CallIC::Clear(isolate, host, nexus); | 
| default: | 
| UNREACHABLE(); | 
| } | 
| } | 
|  | 
|  | 
| +// Force instantiation of template instances for vector-based IC clearing. | 
| +template void IC::Clear(Isolate*, Code::Kind, Code*, CallICNexus*); | 
| + | 
| + | 
| void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, | 
| ConstantPoolArray* constant_pool) { | 
| if (IsCleared(target)) return; | 
| @@ -529,18 +563,15 @@ void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, | 
| } | 
|  | 
|  | 
| -void CallIC::Clear(Isolate* isolate, Code* host, TypeFeedbackVector* vector, | 
| -                   FeedbackVectorICSlot slot) { | 
| -  DCHECK(vector != NULL && !slot.IsInvalid()); | 
| -  Object* feedback = vector->Get(slot); | 
| +void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { | 
| // Determine our state. | 
| -  State state = FeedbackToState(isolate, vector, slot); | 
| +  Object* feedback = nexus->vector()->Get(nexus->slot()); | 
| +  State state = nexus->StateFromFeedback(); | 
|  | 
| if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { | 
| -    vector->Set(slot, isolate->heap()->uninitialized_symbol(), | 
| -                SKIP_WRITE_BARRIER); | 
| +    nexus->ConfigureUninitialized(); | 
| // The change in state must be processed. | 
| -    OnTypeFeedbackChanged(isolate, host, vector, state, UNINITIALIZED); | 
| +    OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED); | 
| } | 
| } | 
|  | 
| @@ -1940,34 +1971,8 @@ 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, | 
| -                             FeedbackVectorICSlot slot, | 
| -                             const CallICState& state) { | 
| +                             const CallICState& callic_state) { | 
| DCHECK(FLAG_use_ic && function->IsJSFunction()); | 
|  | 
| // Are we the array function? | 
| @@ -1975,42 +1980,33 @@ 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(isolate(), *vector, slot); | 
| -    Object* feedback = vector->Get(slot); | 
| -    if (!feedback->IsAllocationSite()) { | 
| -      Handle<AllocationSite> new_site = | 
| -          isolate()->factory()->NewAllocationSite(); | 
| -      vector->Set(slot, *new_site); | 
| -    } | 
| +    CallICNexus* nexus = casted_nexus<CallICNexus>(); | 
| +    nexus->ConfigureMonomorphicArray(); | 
|  | 
| -    CallIC_ArrayStub stub(isolate(), state); | 
| +    CallIC_ArrayStub stub(isolate(), callic_state); | 
| set_target(*stub.GetCode()); | 
| Handle<String> name; | 
| if (array_function->shared()->name()->IsString()) { | 
| name = Handle<String>(String::cast(array_function->shared()->name()), | 
| isolate()); | 
| } | 
| - | 
| -    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); | 
| +    TRACE_IC("CallIC", name); | 
| +    OnTypeFeedbackChanged(isolate(), get_host(), nexus->vector(), state(), | 
| +                          MONOMORPHIC); | 
| return true; | 
| } | 
| return false; | 
| } | 
|  | 
|  | 
| -void CallIC::PatchMegamorphic(Handle<Object> function, | 
| -                              Handle<TypeFeedbackVector> vector, | 
| -                              FeedbackVectorICSlot slot) { | 
| -  CallICState state(target()->extra_ic_state()); | 
| -  IC::State old_state = FeedbackToState(isolate(), *vector, slot); | 
| +void CallIC::PatchMegamorphic(Handle<Object> function) { | 
| +  CallICState callic_state(target()->extra_ic_state()); | 
|  | 
| // We are going generic. | 
| -  vector->Set(slot, *TypeFeedbackVector::MegamorphicSentinel(isolate()), | 
| -              SKIP_WRITE_BARRIER); | 
| +  CallICNexus* nexus = casted_nexus<CallICNexus>(); | 
| +  nexus->ConfigureGeneric(); | 
|  | 
| -  CallICStub stub(isolate(), state); | 
| +  CallICStub stub(isolate(), callic_state); | 
| Handle<Code> code = stub.GetCode(); | 
| set_target(*code); | 
|  | 
| @@ -2020,27 +2016,24 @@ void CallIC::PatchMegamorphic(Handle<Object> function, | 
| name = handle(js_function->shared()->name(), isolate()); | 
| } | 
|  | 
| -  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); | 
| +  TRACE_IC("CallIC", name); | 
| +  OnTypeFeedbackChanged(isolate(), get_host(), nexus->vector(), state(), | 
| +                        GENERIC); | 
| } | 
|  | 
|  | 
| -void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function, | 
| -                        Handle<TypeFeedbackVector> vector, | 
| -                        FeedbackVectorICSlot slot) { | 
| -  CallICState state(target()->extra_ic_state()); | 
| -  IC::State old_state = FeedbackToState(isolate(), *vector, slot); | 
| +void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function) { | 
| +  CallICState callic_state(target()->extra_ic_state()); | 
| Handle<Object> name = isolate()->factory()->empty_string(); | 
| -  Object* feedback = vector->Get(slot); | 
| +  CallICNexus* nexus = casted_nexus<CallICNexus>(); | 
| +  Object* feedback = nexus->GetFeedback(); | 
|  | 
| // 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, *TypeFeedbackVector::MegamorphicSentinel(isolate()), | 
| -                SKIP_WRITE_BARRIER); | 
| +    nexus->ConfigureGeneric(); | 
| } else { | 
| // The feedback is either uninitialized or an allocation site. | 
| // It might be an allocation site because if we re-compile the full code | 
| @@ -2052,12 +2045,11 @@ void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function, | 
| feedback->IsAllocationSite()); | 
|  | 
| // Do we want to install a custom handler? | 
| -    if (FLAG_use_ic && | 
| -        DoCustomHandler(receiver, function, vector, slot, state)) { | 
| +    if (FLAG_use_ic && DoCustomHandler(receiver, function, callic_state)) { | 
| return; | 
| } | 
|  | 
| -    vector->Set(slot, *function); | 
| +    nexus->ConfigureMonomorphic(Handle<JSFunction>::cast(function)); | 
| } | 
|  | 
| if (function->IsJSFunction()) { | 
| @@ -2065,9 +2057,9 @@ void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function, | 
| name = handle(js_function->shared()->name(), isolate()); | 
| } | 
|  | 
| -  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); | 
| +  IC::State new_state = nexus->StateFromFeedback(); | 
| +  OnTypeFeedbackChanged(isolate(), get_host(), *vector(), state(), new_state); | 
| +  TRACE_IC("CallIC", name); | 
| } | 
|  | 
|  | 
| @@ -2083,13 +2075,14 @@ RUNTIME_FUNCTION(CallIC_Miss) { | 
| TimerEventScope<TimerEventIcMiss> timer(isolate); | 
| HandleScope scope(isolate); | 
| DCHECK(args.length() == 4); | 
| -  CallIC ic(isolate); | 
| Handle<Object> receiver = args.at<Object>(0); | 
| Handle<Object> function = args.at<Object>(1); | 
| Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); | 
| Handle<Smi> slot = args.at<Smi>(3); | 
| FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 
| -  ic.HandleMiss(receiver, function, vector, vector_slot); | 
| +  CallICNexus nexus(vector, vector_slot); | 
| +  CallIC ic(isolate, &nexus); | 
| +  ic.HandleMiss(receiver, function); | 
| return *function; | 
| } | 
|  | 
| @@ -2098,13 +2091,14 @@ RUNTIME_FUNCTION(CallIC_Customization_Miss) { | 
| TimerEventScope<TimerEventIcMiss> timer(isolate); | 
| HandleScope scope(isolate); | 
| DCHECK(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<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); | 
| Handle<Smi> slot = args.at<Smi>(3); | 
| FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 
| -  ic.PatchMegamorphic(function, vector, vector_slot); | 
| +  CallICNexus nexus(vector, vector_slot); | 
| +  // A miss on a custom call ic always results in going megamorphic. | 
| +  CallIC ic(isolate, &nexus); | 
| +  ic.PatchMegamorphic(function); | 
| return *function; | 
| } | 
|  | 
|  |