Index: src/ic/ic.cc |
diff --git a/src/ic/ic.cc b/src/ic/ic.cc |
index 15626cd954f01cd35d863e02af6f0796854bb086..cfc2a81feee0f1d6119e3da25f3551bbe659321a 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,7 @@ 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 (ICUseVector(target->kind())) return; |
Isolate* isolate = target->GetHeap()->isolate(); |
State old_state = UNINITIALIZED; |
@@ -514,8 +519,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 +544,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 +556,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 +582,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 +590,14 @@ void LoadIC::Clear(Isolate* isolate, Address address, Code* target, |
} |
+void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { |
+ if (IsCleared(nexus)) return; |
+ State state = nexus->StateFromFeedback(); |
+ nexus->ConfigurePremonomorphic(); |
+ 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 +648,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 +726,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 +835,22 @@ 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()) { |
+ 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 +861,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 +919,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 +970,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 +997,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 +1044,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 +1074,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; |
} |
@@ -1228,11 +1341,19 @@ static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { |
Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { |
+ Handle<Code> null_handle; |
Handle<Map> receiver_map(receiver->map(), isolate()); |
MapHandleList target_receiver_maps; |
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 null_handle; |
+ } |
return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); |
} |
@@ -1247,6 +1368,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 null_handle; |
+ } |
return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); |
} |
@@ -1258,6 +1385,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 null_handle; |
+ } |
return generic_stub(); |
} |
@@ -1265,9 +1396,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 null_handle; |
+ } |
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 null_handle; |
+ } |
+ |
return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); |
} |
@@ -1303,11 +1450,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 +2308,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 (FLAG_vector_ics) { |
+ DCHECK(args.length() == 4); |
+ 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 +2335,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 (FLAG_vector_ics) { |
+ DCHECK(args.length() == 4); |
+ 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 +2362,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 (FLAG_vector_ics) { |
+ DCHECK(args.length() == 4); |
+ 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; |
} |
@@ -2683,7 +2871,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(); |
} |
@@ -2765,13 +2953,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 (FLAG_vector_ics) { |
+ DCHECK(args.length() == 4); |
+ 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; |
} |