 Chromium Code Reviews
 Chromium Code Reviews Issue 754303003:
  Flesh out vector ic state query and set mechanisms.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 754303003:
  Flesh out vector ic state query and set mechanisms.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| Index: src/ic/ic.cc | 
| diff --git a/src/ic/ic.cc b/src/ic/ic.cc | 
| index 0c38c2b74112b24eb3893147cf0abaf931f554af..cde608ac9c059dbf74c3131618499351597276e8 100644 | 
| --- a/src/ic/ic.cc | 
| +++ b/src/ic/ic.cc | 
| @@ -258,7 +258,11 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, | 
| Handle<String> name) { | 
| if (!IsNameCompatibleWithPrototypeFailure(name)) return false; | 
| Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate()); | 
| - maybe_handler_ = target()->FindHandlerForMap(*receiver_map); | 
| + if (UseVector()) { | 
| + maybe_handler_ = nexus()->FindHandlerForMap(receiver_map); | 
| + } else { | 
| + maybe_handler_ = target()->FindHandlerForMap(*receiver_map); | 
| + } | 
| // The current map wasn't handled yet. There's no reason to stay monomorphic, | 
| // *unless* we're moving from a deprecated map to its replacement, or | 
| @@ -310,7 +314,8 @@ bool IC::IsNameCompatibleWithPrototypeFailure(Handle<Object> name) { | 
| if (target()->is_keyed_stub()) { | 
| // Determine whether the failure is due to a name failure. | 
| if (!name->IsName()) return false; | 
| - Name* stub_name = target()->FindFirstName(); | 
| + Name* stub_name = | 
| + UseVector() ? nexus()->FindFirstName() : target()->FindFirstName(); | 
| if (*name != stub_name) return false; | 
| } | 
| @@ -452,7 +457,11 @@ void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host, | 
| 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. | 
| - if (target->kind() == Code::CALL_IC) return; | 
| + if (target->kind() == Code::CALL_IC || | 
| + (FLAG_vector_ics && (target->kind() == Code::LOAD_IC || | 
| 
Jakob Kummerow
2014/11/26 15:14:14
Can you re-use UseVector() here instead of duplica
 
mvstanton
2014/11/27 13:09:26
Done.
 | 
| + target->kind() == Code::KEYED_LOAD_IC))) { | 
| + return; | 
| + } | 
| Isolate* isolate = target->GetHeap()->isolate(); | 
| State old_state = UNINITIALIZED; | 
| @@ -514,8 +523,10 @@ void IC::Clear(Isolate* isolate, Address address, | 
| switch (target->kind()) { | 
| case Code::LOAD_IC: | 
| + if (FLAG_vector_ics) return; | 
| return LoadIC::Clear(isolate, address, target, constant_pool); | 
| case Code::KEYED_LOAD_IC: | 
| + if (FLAG_vector_ics) return; | 
| return KeyedLoadIC::Clear(isolate, address, target, constant_pool); | 
| case Code::STORE_IC: | 
| return StoreIC::Clear(isolate, address, target, constant_pool); | 
| @@ -537,23 +548,9 @@ void IC::Clear(Isolate* isolate, Address address, | 
| } | 
| -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, 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) { | 
| + DCHECK(!FLAG_vector_ics); | 
| if (IsCleared(target)) return; | 
| // Make sure to also clear the map used in inline fast cases. If we | 
| @@ -563,6 +560,17 @@ void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, | 
| } | 
| +void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) { | 
| + if (IsCleared(nexus)) return; | 
| + // Make sure to also clear the map used in inline fast cases. If we | 
| + // do not clear these maps, cached code can keep objects alive | 
| + // through the embedded maps. | 
| + State state = nexus->StateFromFeedback(); | 
| + nexus->ConfigurePremonomorphic(); | 
| + OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 
| +} | 
| + | 
| + | 
| void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { | 
| // Determine our state. | 
| Object* feedback = nexus->vector()->Get(nexus->slot()); | 
| @@ -578,6 +586,7 @@ void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { | 
| void LoadIC::Clear(Isolate* isolate, Address address, Code* target, | 
| ConstantPoolArray* constant_pool) { | 
| + DCHECK(!FLAG_vector_ics); | 
| if (IsCleared(target)) return; | 
| Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, | 
| target->extra_ic_state()); | 
| @@ -585,6 +594,15 @@ void LoadIC::Clear(Isolate* isolate, Address address, Code* target, | 
| } | 
| +void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { | 
| + if (IsCleared(nexus)) return; | 
| + // Determine our state. | 
| 
Jakob Kummerow
2014/11/26 15:14:15
nit: I don't think this comment adds much value.
 
mvstanton
2014/11/27 13:09:26
Done.
 | 
| + nexus->ConfigurePremonomorphic(); | 
| + State state = nexus->StateFromFeedback(); | 
| 
Jakob Kummerow
2014/11/26 15:14:14
Save the previous state before calling ConfigurePr
 
mvstanton
2014/11/27 13:09:26
doh! good catch, thanks!
 | 
| + OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 
| +} | 
| + | 
| + | 
| void StoreIC::Clear(Isolate* isolate, Address address, Code* target, | 
| ConstantPoolArray* constant_pool) { | 
| if (IsCleared(target)) return; | 
| @@ -635,6 +653,71 @@ static bool MigrateDeprecated(Handle<Object> object) { | 
| } | 
| +void IC::ConfigureVectorState(IC::State new_state) { | 
| + DCHECK(UseVector()); | 
| + if (kind() == Code::LOAD_IC) { | 
| + LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 
| + if (new_state == PREMONOMORPHIC) { | 
| + nexus->ConfigurePremonomorphic(); | 
| + } else if (new_state == MEGAMORPHIC) { | 
| + nexus->ConfigureMegamorphic(); | 
| + } else { | 
| + UNREACHABLE(); | 
| + } | 
| + } else if (kind() == Code::KEYED_LOAD_IC) { | 
| + KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 
| + if (new_state == GENERIC) { | 
| + nexus->ConfigureGeneric(); | 
| + } else if (new_state == PREMONOMORPHIC) { | 
| + nexus->ConfigurePremonomorphic(); | 
| + } else if (new_state == MEGAMORPHIC) { | 
| + nexus->ConfigureMegamorphic(); | 
| + } else { | 
| + UNREACHABLE(); | 
| + } | 
| + } else { | 
| + UNREACHABLE(); | 
| + } | 
| + | 
| + OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 
| + new_state); | 
| +} | 
| + | 
| + | 
| +void IC::ConfigureVectorState(Handle<Name> name, Handle<HeapType> type, | 
| + Handle<Code> handler) { | 
| + DCHECK(UseVector()); | 
| + if (kind() == Code::LOAD_IC) { | 
| + LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 
| + nexus->ConfigureMonomorphic(type, handler); | 
| + } else { | 
| + DCHECK(kind() == Code::KEYED_LOAD_IC); | 
| + KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 
| + nexus->ConfigureMonomorphic(name, type, handler); | 
| + } | 
| + | 
| + OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 
| + MONOMORPHIC); | 
| +} | 
| + | 
| + | 
| +void IC::ConfigureVectorState(Handle<Name> name, TypeHandleList* types, | 
| + CodeHandleList* handlers) { | 
| + DCHECK(UseVector()); | 
| + if (kind() == Code::LOAD_IC) { | 
| + LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 
| + nexus->ConfigurePolymorphic(types, handlers); | 
| + } else { | 
| + DCHECK(kind() == Code::KEYED_LOAD_IC); | 
| + KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 
| + nexus->ConfigurePolymorphic(name, types, handlers); | 
| + } | 
| + | 
| + OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 
| + POLYMORPHIC); | 
| +} | 
| + | 
| + | 
| MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { | 
| // If the object is undefined or null it's illegal to try to get any | 
| // of its properties; throw a TypeError in that case. | 
| @@ -648,7 +731,11 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { | 
| if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 
| // Rewrite to the generic keyed load stub. | 
| if (FLAG_use_ic) { | 
| - set_target(*KeyedLoadIC::generic_stub(isolate())); | 
| + if (UseVector()) { | 
| + ConfigureVectorState(GENERIC); | 
| + } else { | 
| + set_target(*KeyedLoadIC::generic_stub(isolate())); | 
| + } | 
| TRACE_IC("LoadIC", name); | 
| TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); | 
| } | 
| @@ -753,14 +840,23 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) { | 
| if (number_of_valid_types >= 4) return false; | 
| if (number_of_types == 0) return false; | 
| - if (!target()->FindHandlers(&handlers, types.length())) return false; | 
| + if (UseVector()) { | 
| + if (!nexus()->FindHandlers(&handlers, types.length())) return false; | 
| + } else { | 
| + if (!target()->FindHandlers(&handlers, types.length())) return false; | 
| + } | 
| number_of_valid_types++; | 
| if (number_of_valid_types > 1 && target()->is_keyed_stub()) return false; | 
| Handle<Code> ic; | 
| if (number_of_valid_types == 1) { | 
| - ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, type, code, | 
| - extra_ic_state()); | 
| + if (UseVector()) { | 
| + DCHECK(kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC); | 
| 
Jakob Kummerow
2014/11/26 15:14:15
You can drop this DCHECK; ConfigureVectorState() c
 
mvstanton
2014/11/27 13:09:26
Done.
 | 
| + ConfigureVectorState(name, receiver_type(), code); | 
| + } else { | 
| + ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, type, code, | 
| + extra_ic_state()); | 
| + } | 
| } else { | 
| if (handler_to_overwrite >= 0) { | 
| handlers.Set(handler_to_overwrite, code); | 
| @@ -771,11 +867,17 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) { | 
| types.Add(type); | 
| handlers.Add(code); | 
| } | 
| - ic = PropertyICCompiler::ComputePolymorphic(kind(), &types, &handlers, | 
| - number_of_valid_types, name, | 
| - extra_ic_state()); | 
| + | 
| + if (UseVector()) { | 
| + ConfigureVectorState(name, &types, &handlers); | 
| + } else { | 
| + ic = PropertyICCompiler::ComputePolymorphic(kind(), &types, &handlers, | 
| + number_of_valid_types, name, | 
| + extra_ic_state()); | 
| + } | 
| } | 
| - set_target(*ic); | 
| + | 
| + if (!UseVector()) set_target(*ic); | 
| return true; | 
| } | 
| @@ -823,9 +925,13 @@ template Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, | 
| void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { | 
| DCHECK(handler->is_handler()); | 
| - Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( | 
| - kind(), name, receiver_type(), handler, extra_ic_state()); | 
| - set_target(*ic); | 
| + if (UseVector()) { | 
| + ConfigureVectorState(name, receiver_type(), handler); | 
| + } else { | 
| + Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( | 
| + kind(), name, receiver_type(), handler, extra_ic_state()); | 
| + set_target(*ic); | 
| + } | 
| } | 
| @@ -870,7 +976,11 @@ void IC::PatchCache(Handle<Name> name, Handle<Code> code) { | 
| // same key. | 
| CopyICToMegamorphicCache(name); | 
| } | 
| - set_target(*megamorphic_stub()); | 
| + if (UseVector()) { | 
| + ConfigureVectorState(MEGAMORPHIC); | 
| + } else { | 
| + set_target(*megamorphic_stub()); | 
| + } | 
| // Fall through. | 
| case MEGAMORPHIC: | 
| UpdateMegamorphicCache(*receiver_type(), *name, *code); | 
| @@ -893,6 +1003,10 @@ void IC::PatchCache(Handle<Name> name, Handle<Code> code) { | 
| Handle<Code> LoadIC::initialize_stub(Isolate* isolate, | 
| ExtraICState extra_state) { | 
| + if (FLAG_vector_ics) { | 
| + return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); | 
| + } | 
| + | 
| return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); | 
| } | 
| @@ -936,6 +1050,7 @@ Handle<Code> LoadIC::megamorphic_stub() { | 
| Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | 
| ExtraICState extra_state) { | 
| + DCHECK(!FLAG_vector_ics); | 
| return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); | 
| } | 
| @@ -965,7 +1080,11 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) { | 
| if (state() == UNINITIALIZED) { | 
| // This is the first time we execute this inline cache. Set the target to | 
| // the pre monomorphic stub to delay setting the monomorphic state. | 
| - set_target(*pre_monomorphic_stub()); | 
| + if (UseVector()) { | 
| + ConfigureVectorState(PREMONOMORPHIC); | 
| + } else { | 
| + set_target(*pre_monomorphic_stub()); | 
| + } | 
| TRACE_IC("LoadIC", lookup->name()); | 
| return; | 
| } | 
| @@ -1233,6 +1352,12 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { | 
| TargetMaps(&target_receiver_maps); | 
| if (target_receiver_maps.length() == 0) { | 
| + if (FLAG_vector_ics) { | 
| + Handle<Code> handler = | 
| + PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); | 
| + ConfigureVectorState(Handle<Name>::null(), receiver_type(), handler); | 
| + return target(); | 
| 
Jakob Kummerow
2014/11/26 15:14:15
Consider "return Handle<Code>::null();" to make it
 
mvstanton
2014/11/27 13:09:26
I think this use of target() solved a problem for
 | 
| + } | 
| return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | 
| } | 
| @@ -1247,6 +1372,12 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { | 
| IsMoreGeneralElementsKindTransition( | 
| target_receiver_maps.at(0)->elements_kind(), | 
| Handle<JSObject>::cast(receiver)->GetElementsKind())) { | 
| + if (FLAG_vector_ics) { | 
| + Handle<Code> handler = | 
| + PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); | 
| + ConfigureVectorState(Handle<Name>::null(), receiver_type(), handler); | 
| + return target(); | 
| + } | 
| return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | 
| } | 
| @@ -1258,6 +1389,10 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { | 
| // If the miss wasn't due to an unseen map, a polymorphic stub | 
| // won't help, use the generic stub. | 
| TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); | 
| + if (FLAG_vector_ics) { | 
| + ConfigureVectorState(GENERIC); | 
| + return target(); | 
| + } | 
| return generic_stub(); | 
| } | 
| @@ -1265,9 +1400,25 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { | 
| // version of the IC. | 
| if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 
| TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 
| + if (FLAG_vector_ics) { | 
| + ConfigureVectorState(GENERIC); | 
| + return target(); | 
| + } | 
| return generic_stub(); | 
| } | 
| + if (FLAG_vector_ics) { | 
| + CodeHandleList handlers(target_receiver_maps.length()); | 
| + ElementHandlerCompiler compiler(isolate()); | 
| + compiler.CompileElementHandlers(&target_receiver_maps, &handlers); | 
| + TypeHandleList types(target_receiver_maps.length()); | 
| + for (int i = 0; i < target_receiver_maps.length(); i++) { | 
| + types.Add(HeapType::Class(target_receiver_maps.at(i), isolate())); | 
| + } | 
| + ConfigureVectorState(Handle<Name>::null(), &types, &handlers); | 
| + return target(); | 
| + } | 
| + | 
| return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); | 
| } | 
| @@ -1303,11 +1454,14 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 
| } | 
| if (!is_target_set()) { | 
| - Code* generic = *generic_stub(); | 
| - if (*stub == generic) { | 
| - TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 
| + if (!FLAG_vector_ics) { | 
| + Code* generic = *generic_stub(); | 
| + if (*stub == generic) { | 
| + TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 
| + } | 
| + | 
| + set_target(*stub); | 
| } | 
| - set_target(*stub); | 
| TRACE_IC("LoadIC", key); | 
| } | 
| @@ -2158,13 +2312,25 @@ RUNTIME_FUNCTION(CallIC_Customization_Miss) { | 
| RUNTIME_FUNCTION(LoadIC_Miss) { | 
| TimerEventScope<TimerEventIcMiss> timer(isolate); | 
| HandleScope scope(isolate); | 
| - DCHECK(args.length() == 2); | 
| - LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 
| Handle<Object> receiver = args.at<Object>(0); | 
| Handle<Name> key = args.at<Name>(1); | 
| - ic.UpdateState(receiver, key); | 
| Handle<Object> result; | 
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + | 
| + if (args.length() == 4) { | 
| + DCHECK(FLAG_vector_ics); | 
| 
Jakob Kummerow
2014/11/26 15:14:14
I think I'd swap this around:
if (FLAG_vector_ics
 
mvstanton
2014/11/27 13:09:26
Cool. This is a relic of a time in the work when b
 | 
| + Handle<Smi> slot = args.at<Smi>(2); | 
| + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | 
| + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 
| + LoadICNexus nexus(vector, vector_slot); | 
| + LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 
| + ic.UpdateState(receiver, key); | 
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + } else { | 
| + DCHECK(args.length() == 2); | 
| + LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 
| + ic.UpdateState(receiver, key); | 
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + } | 
| return *result; | 
| } | 
| @@ -2173,13 +2339,26 @@ RUNTIME_FUNCTION(LoadIC_Miss) { | 
| RUNTIME_FUNCTION(KeyedLoadIC_Miss) { | 
| TimerEventScope<TimerEventIcMiss> timer(isolate); | 
| HandleScope scope(isolate); | 
| - DCHECK(args.length() == 2); | 
| - KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 
| Handle<Object> receiver = args.at<Object>(0); | 
| Handle<Object> key = args.at<Object>(1); | 
| - ic.UpdateState(receiver, key); | 
| Handle<Object> result; | 
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + | 
| + if (args.length() == 4) { | 
| + DCHECK(FLAG_vector_ics); | 
| 
Jakob Kummerow
2014/11/26 15:14:15
again
 
mvstanton
2014/11/27 13:09:26
Done.
 | 
| + Handle<Smi> slot = args.at<Smi>(2); | 
| + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | 
| + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 
| + KeyedLoadICNexus nexus(vector, vector_slot); | 
| + KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 
| + ic.UpdateState(receiver, key); | 
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + } else { | 
| + DCHECK(args.length() == 2); | 
| + KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 
| + ic.UpdateState(receiver, key); | 
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + } | 
| + | 
| return *result; | 
| } | 
| @@ -2187,13 +2366,26 @@ RUNTIME_FUNCTION(KeyedLoadIC_Miss) { | 
| RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) { | 
| TimerEventScope<TimerEventIcMiss> timer(isolate); | 
| HandleScope scope(isolate); | 
| - DCHECK(args.length() == 2); | 
| - KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | 
| Handle<Object> receiver = args.at<Object>(0); | 
| Handle<Object> key = args.at<Object>(1); | 
| - ic.UpdateState(receiver, key); | 
| Handle<Object> result; | 
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + | 
| + if (args.length() == 4) { | 
| + DCHECK(FLAG_vector_ics); | 
| 
Jakob Kummerow
2014/11/26 15:14:14
again
 
mvstanton
2014/11/27 13:09:26
Done.
 | 
| + Handle<Smi> slot = args.at<Smi>(2); | 
| + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | 
| + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 
| + KeyedLoadICNexus nexus(vector, vector_slot); | 
| + KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 
| + ic.UpdateState(receiver, key); | 
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + } else { | 
| + DCHECK(args.length() == 2); | 
| + KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | 
| + ic.UpdateState(receiver, key); | 
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + } | 
| + | 
| return *result; | 
| } | 
| @@ -2685,7 +2877,7 @@ static Object* ThrowReferenceError(Isolate* isolate, Name* name) { | 
| // If the load is non-contextual, just return the undefined result. | 
| // Note that both keyed and non-keyed loads may end up here. | 
| HandleScope scope(isolate); | 
| - LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 
| + LoadIC ic(IC::NO_EXTRA_FRAME, isolate, true); | 
| if (ic.contextual_mode() != CONTEXTUAL) { | 
| return isolate->heap()->undefined_value(); | 
| } | 
| @@ -2767,13 +2959,26 @@ RUNTIME_FUNCTION(LoadElementWithInterceptor) { | 
| RUNTIME_FUNCTION(LoadIC_MissFromStubFailure) { | 
| TimerEventScope<TimerEventIcMiss> timer(isolate); | 
| HandleScope scope(isolate); | 
| - DCHECK(args.length() == 2); | 
| - LoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | 
| Handle<Object> receiver = args.at<Object>(0); | 
| Handle<Name> key = args.at<Name>(1); | 
| - ic.UpdateState(receiver, key); | 
| Handle<Object> result; | 
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + | 
| + if (args.length() == 4) { | 
| + DCHECK(FLAG_vector_ics); | 
| 
Jakob Kummerow
2014/11/26 15:14:14
again
 
mvstanton
2014/11/27 13:09:26
Done.
 | 
| + Handle<Smi> slot = args.at<Smi>(2); | 
| + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | 
| + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 
| + LoadICNexus nexus(vector, vector_slot); | 
| + LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 
| + ic.UpdateState(receiver, key); | 
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + } else { | 
| + DCHECK(args.length() == 2); | 
| + LoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | 
| + ic.UpdateState(receiver, key); | 
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 
| + } | 
| + | 
| return *result; | 
| } |