Chromium Code Reviews| 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; |
| } |