Chromium Code Reviews| Index: src/type-feedback-vector.cc |
| diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc |
| index 676290c83d021fff88102a40c4d65c478fb56c31..951ba76f4c9ca47a094be0f295ded156fd7bff22 100644 |
| --- a/src/type-feedback-vector.cc |
| +++ b/src/type-feedback-vector.cc |
| @@ -121,6 +121,28 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( |
| } |
| +// This logic is copied from |
| +// StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget. |
| +// TODO(mvstanton): with weak handling of all vector ics, this logic should |
| +// actually be completely eliminated and we no longer need to clear the |
| +// vector ICs. |
| +static bool ClearLogic(Heap* heap, int ic_age, Code::Kind kind, |
| + InlineCacheState state) { |
| + if (FLAG_cleanup_code_caches_at_gc && |
| + (kind == Code::CALL_IC || state == MEGAMORPHIC || state == GENERIC || |
| + state == POLYMORPHIC || heap->flush_monomorphic_ics() || |
| + // TODO(mvstanton): is this ic_age granular enough? it comes from |
| + // the SharedFunctionInfo which may change on a different schedule |
| + // than ic targets. |
| + // ic_age != heap->global_ic_age() || |
| + // is_invalidated_weak_stub || |
| + heap->isolate()->serializer_enabled())) { |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| + |
| void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) { |
| int slots = Slots(); |
| Isolate* isolate = GetIsolate(); |
| @@ -147,17 +169,33 @@ void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) { |
| // Now clear vector-based ICs. They are all CallICs. |
|
Jakob Kummerow
2014/11/26 15:14:15
nit: s/They are all CallICs.//
mvstanton
2014/11/27 13:09:26
Done.
|
| // Try and pass the containing code (the "host"). |
| + Heap* heap = isolate->heap(); |
| Code* host = shared->code(); |
| + // I'm not sure yet if this ic age is the correct one. |
| + int ic_age = shared->ic_age(); |
| for (int i = 0; i < slots; i++) { |
| FeedbackVectorICSlot slot(i); |
| Object* obj = Get(slot); |
| if (obj != uninitialized_sentinel) { |
| - // TODO(mvstanton): To make this code work with --vector-ics, |
| - // additional Nexus types must be created. |
| - DCHECK(!FLAG_vector_ics); |
| - DCHECK(GetKind(slot) == Code::CALL_IC); |
| - CallICNexus nexus(this, slot); |
| - ICUtility::Clear(isolate, Code::CALL_IC, host, &nexus); |
| + // Discover the correct Code::Kind. |
|
Jakob Kummerow
2014/11/26 15:14:15
nit: this comment doesn't add value
mvstanton
2014/11/27 13:09:26
Done.
|
| + Code::Kind kind = GetKind(slot); |
| + if (kind == Code::CALL_IC) { |
| + CallICNexus nexus(this, slot); |
| + // bool is_invalidated = nexus.IsInvalidatedWeakIC(); |
|
Jakob Kummerow
2014/11/26 15:14:15
leftover?
mvstanton
2014/11/27 13:09:26
Yes, I think so, removed.
|
| + if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) { |
| + nexus.Clear(host); |
| + } |
| + } else if (kind == Code::LOAD_IC) { |
| + LoadICNexus nexus(this, slot); |
| + if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) { |
| + nexus.Clear(host); |
| + } |
| + } else if (kind == Code::KEYED_LOAD_IC) { |
| + KeyedLoadICNexus nexus(this, slot); |
| + if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) { |
| + nexus.Clear(host); |
| + } |
| + } |
| } |
| } |
| } |
| @@ -190,6 +228,59 @@ void FeedbackNexus::InstallHandlers(int start_index, TypeHandleList* types, |
| } |
| +InlineCacheState LoadICNexus::StateFromFeedback() const { |
| + Isolate* isolate = GetIsolate(); |
| + InlineCacheState state = UNINITIALIZED; |
| + Object* feedback = GetFeedback(); |
| + if (feedback == *vector()->UninitializedSentinel(isolate)) { |
| + state = UNINITIALIZED; |
|
Jakob Kummerow
2014/11/26 15:14:15
consider to directly "return UNINITIALIZED;" (and
mvstanton
2014/11/27 13:09:26
Done.
|
| + } else if (feedback == *vector()->MegamorphicSentinel(isolate)) { |
| + state = MEGAMORPHIC; |
| + } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) { |
| + state = PREMONOMORPHIC; |
| + } else if (feedback->IsFixedArray()) { |
| + FixedArray* array = FixedArray::cast(feedback); |
| + int length = array->length(); |
| + DCHECK(length >= 2); |
| + if (length == 2) { |
| + state = MONOMORPHIC; |
| + } else if (length > 2) { |
|
Jakob Kummerow
2014/11/26 15:14:15
s/if (length > 2)//, it's guaranteed anyway.
mvstanton
2014/11/27 13:09:26
Done.
|
| + state = POLYMORPHIC; |
| + } |
| + } |
| + |
| + return state; |
| +} |
| + |
| + |
| +InlineCacheState KeyedLoadICNexus::StateFromFeedback() const { |
| + Isolate* isolate = GetIsolate(); |
| + InlineCacheState state = UNINITIALIZED; |
| + Object* feedback = GetFeedback(); |
| + if (feedback == *vector()->UninitializedSentinel(isolate)) { |
| + state = UNINITIALIZED; |
| + } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) { |
| + state = PREMONOMORPHIC; |
| + } else if (feedback == *vector()->MegamorphicSentinel(isolate)) { |
| + state = MEGAMORPHIC; |
| + } else if (feedback == *vector()->GenericSentinel(isolate)) { |
| + state = GENERIC; |
| + } else if (feedback->IsFixedArray()) { |
| + FixedArray* array = FixedArray::cast(feedback); |
| + int length = array->length(); |
| + DCHECK(length >= 3); |
| + |
| + if (length == 3) { |
| + state = MONOMORPHIC; |
| + } else if (length > 3) { |
|
Jakob Kummerow
2014/11/26 15:14:15
s/if (length > 3)//, it's guaranteed anyway.
mvstanton
2014/11/27 13:09:26
Done.
|
| + state = POLYMORPHIC; |
| + } |
| + } |
| + |
| + return state; |
| +} |
| + |
| + |
| InlineCacheState CallICNexus::StateFromFeedback() const { |
| Isolate* isolate = GetIsolate(); |
| InlineCacheState state = UNINITIALIZED; |
| @@ -207,6 +298,9 @@ InlineCacheState CallICNexus::StateFromFeedback() const { |
| } |
| +void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); } |
| + |
| + |
| void CallICNexus::ConfigureGeneric() { |
| SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); |
| } |
| @@ -233,6 +327,79 @@ void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { |
| } |
| +void KeyedLoadICNexus::ConfigureGeneric() { |
| + SetFeedback(*vector()->GenericSentinel(GetIsolate()), SKIP_WRITE_BARRIER); |
|
Jakob Kummerow
2014/11/26 15:14:15
Looks like return raw pointers in the various vect
mvstanton
2014/11/27 13:09:26
Yes, I'll come back for that later. I think I want
|
| +} |
| + |
| + |
| +void KeyedLoadICNexus::ConfigureMegamorphic() { |
| + SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); |
| +} |
| + |
| + |
| +void LoadICNexus::ConfigureMegamorphic() { |
| + SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); |
| +} |
| + |
| + |
| +void LoadICNexus::ConfigurePremonomorphic() { |
| + SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()), |
| + SKIP_WRITE_BARRIER); |
| +} |
| + |
| + |
| +void KeyedLoadICNexus::ConfigurePremonomorphic() { |
| + SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()), |
| + SKIP_WRITE_BARRIER); |
| +} |
| + |
| + |
| +void LoadICNexus::ConfigureMonomorphic(Handle<HeapType> type, |
| + Handle<Code> handler) { |
| + Handle<FixedArray> array = EnsureArrayOfSize(2); |
| + Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate()); |
| + array->set(0, *receiver_map); |
| + array->set(1, *handler); |
| +} |
| + |
| + |
| +void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name, |
| + Handle<HeapType> type, |
| + Handle<Code> handler) { |
| + Handle<FixedArray> array = EnsureArrayOfSize(3); |
| + Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate()); |
| + if (name.is_null()) { |
| + array->set(0, Smi::FromInt(0)); |
| + } else { |
| + array->set(0, *name); |
| + } |
| + array->set(1, *receiver_map); |
| + array->set(2, *handler); |
| +} |
| + |
| + |
| +void LoadICNexus::ConfigurePolymorphic(TypeHandleList* types, |
| + CodeHandleList* handlers) { |
| + int receiver_count = types->length(); |
| + EnsureArrayOfSize(receiver_count * 2); |
| + InstallHandlers(0, types, handlers); |
| +} |
| + |
| + |
| +void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name, |
| + TypeHandleList* types, |
| + CodeHandleList* handlers) { |
| + int receiver_count = types->length(); |
| + Handle<FixedArray> array = EnsureArrayOfSize(1 + receiver_count * 2); |
| + if (name.is_null()) { |
| + array->set(0, Smi::FromInt(0)); |
| + } else { |
| + array->set(0, *name); |
| + } |
| + InstallHandlers(1, types, handlers); |
| +} |
| + |
| + |
| int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const { |
| Isolate* isolate = GetIsolate(); |
| Object* feedback = GetFeedback(); |
| @@ -289,5 +456,56 @@ bool FeedbackNexus::FindHandlers(int start_index, CodeHandleList* code_list, |
| } |
| return count == length; |
| } |
| + |
| + |
| +int LoadICNexus::ExtractMaps(MapHandleList* maps) const { |
| + return FeedbackNexus::ExtractMaps(0, maps); |
| +} |
| + |
| + |
| +void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); } |
| + |
| + |
| +void KeyedLoadICNexus::Clear(Code* host) { |
| + KeyedLoadIC::Clear(GetIsolate(), host, this); |
| +} |
| + |
| + |
| +int KeyedLoadICNexus::ExtractMaps(MapHandleList* maps) const { |
| + return FeedbackNexus::ExtractMaps(1, maps); |
| +} |
| + |
| + |
| +MaybeHandle<Code> LoadICNexus::FindHandlerForMap(Handle<Map> map) const { |
| + return FeedbackNexus::FindHandlerForMap(0, map); |
| +} |
| + |
| + |
| +MaybeHandle<Code> KeyedLoadICNexus::FindHandlerForMap(Handle<Map> map) const { |
| + return FeedbackNexus::FindHandlerForMap(1, map); |
| +} |
| + |
| + |
| +bool LoadICNexus::FindHandlers(CodeHandleList* code_list, int length) const { |
| + return FeedbackNexus::FindHandlers(0, code_list, length); |
| +} |
| + |
| + |
| +bool KeyedLoadICNexus::FindHandlers(CodeHandleList* code_list, |
| + int length) const { |
| + return FeedbackNexus::FindHandlers(1, code_list, length); |
| +} |
| + |
| + |
| +Name* KeyedLoadICNexus::FindFirstName() const { |
| + Object* feedback = GetFeedback(); |
| + if (feedback->IsFixedArray()) { |
| + FixedArray* array = FixedArray::cast(feedback); |
| + DCHECK(array->length() >= 3); |
| + Object* name = array->get(0); |
| + if (name->IsName()) return Name::cast(name); |
| + } |
| + return NULL; |
| +} |
| } |
| } // namespace v8::internal |