Index: src/type-feedback-vector.cc |
diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc |
index 676290c83d021fff88102a40c4d65c478fb56c31..0e78358d949df687b688bc1e9edb37883c9826f9 100644 |
--- a/src/type-feedback-vector.cc |
+++ b/src/type-feedback-vector.cc |
@@ -76,12 +76,14 @@ void TypeFeedbackVector::SetKind(FeedbackVectorICSlot slot, Code::Kind kind) { |
// static |
-Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate, |
- int slot_count, |
- int ic_slot_count) { |
- int index_count = |
+Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate( |
+ Isolate* isolate, const FeedbackVectorSpec& spec) { |
+ const int slot_count = spec.slots(); |
+ const int ic_slot_count = spec.ic_slots(); |
+ const int index_count = |
FLAG_vector_ics ? VectorICComputer::word_count(ic_slot_count) : 0; |
- int length = slot_count + ic_slot_count + index_count + kReservedIndexCount; |
+ const int length = |
+ slot_count + ic_slot_count + index_count + kReservedIndexCount; |
if (length == kReservedIndexCount) { |
return Handle<TypeFeedbackVector>::cast( |
isolate->factory()->empty_fixed_array()); |
@@ -96,10 +98,6 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate, |
} |
array->set(kWithTypesIndex, Smi::FromInt(0)); |
array->set(kGenericCountIndex, Smi::FromInt(0)); |
- // Fill the indexes with zeros. |
- for (int i = 0; i < index_count; i++) { |
- array->set(kReservedIndexCount + i, Smi::FromInt(0)); |
- } |
// Ensure we can skip the write barrier |
Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate); |
@@ -107,7 +105,14 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate, |
for (int i = kReservedIndexCount + index_count; i < length; i++) { |
array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER); |
} |
- return Handle<TypeFeedbackVector>::cast(array); |
+ |
+ Handle<TypeFeedbackVector> vector = Handle<TypeFeedbackVector>::cast(array); |
+ if (FLAG_vector_ics) { |
+ for (int i = 0; i < ic_slot_count; i++) { |
+ vector->SetKind(FeedbackVectorICSlot(i), spec.GetKind(i)); |
+ } |
+ } |
+ return vector; |
} |
@@ -121,6 +126,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(); |
@@ -145,19 +172,33 @@ void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) { |
slots = ICSlots(); |
if (slots == 0) return; |
- // Now clear vector-based ICs. They are all CallICs. |
+ // Now clear vector-based ICs. |
// 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); |
+ Code::Kind kind = GetKind(slot); |
+ if (kind == Code::CALL_IC) { |
+ CallICNexus nexus(this, slot); |
+ 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,23 +231,66 @@ void FeedbackNexus::InstallHandlers(int start_index, TypeHandleList* types, |
} |
+InlineCacheState LoadICNexus::StateFromFeedback() const { |
+ Isolate* isolate = GetIsolate(); |
+ Object* feedback = GetFeedback(); |
+ if (feedback == *vector()->UninitializedSentinel(isolate)) { |
+ return UNINITIALIZED; |
+ } else if (feedback == *vector()->MegamorphicSentinel(isolate)) { |
+ return MEGAMORPHIC; |
+ } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) { |
+ return PREMONOMORPHIC; |
+ } else if (feedback->IsFixedArray()) { |
+ FixedArray* array = FixedArray::cast(feedback); |
+ int length = array->length(); |
+ DCHECK(length >= 2); |
+ return length == 2 ? MONOMORPHIC : POLYMORPHIC; |
+ } |
+ |
+ return UNINITIALIZED; |
+} |
+ |
+ |
+InlineCacheState KeyedLoadICNexus::StateFromFeedback() const { |
+ Isolate* isolate = GetIsolate(); |
+ Object* feedback = GetFeedback(); |
+ if (feedback == *vector()->UninitializedSentinel(isolate)) { |
+ return UNINITIALIZED; |
+ } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) { |
+ return PREMONOMORPHIC; |
+ } else if (feedback == *vector()->MegamorphicSentinel(isolate)) { |
+ return MEGAMORPHIC; |
+ } else if (feedback == *vector()->GenericSentinel(isolate)) { |
+ return GENERIC; |
+ } else if (feedback->IsFixedArray()) { |
+ FixedArray* array = FixedArray::cast(feedback); |
+ int length = array->length(); |
+ DCHECK(length >= 3); |
+ return length == 3 ? MONOMORPHIC : POLYMORPHIC; |
+ } |
+ |
+ return UNINITIALIZED; |
+} |
+ |
+ |
InlineCacheState CallICNexus::StateFromFeedback() const { |
Isolate* isolate = GetIsolate(); |
- InlineCacheState state = UNINITIALIZED; |
Object* feedback = GetFeedback(); |
if (feedback == *vector()->MegamorphicSentinel(isolate)) { |
- state = GENERIC; |
+ return GENERIC; |
} else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) { |
- state = MONOMORPHIC; |
- } else { |
- CHECK(feedback == *vector()->UninitializedSentinel(isolate)); |
+ return MONOMORPHIC; |
} |
- return state; |
+ CHECK(feedback == *vector()->UninitializedSentinel(isolate)); |
+ return UNINITIALIZED; |
} |
+void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); } |
+ |
+ |
void CallICNexus::ConfigureGeneric() { |
SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); |
} |
@@ -233,6 +317,79 @@ void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { |
} |
+void KeyedLoadICNexus::ConfigureGeneric() { |
+ SetFeedback(*vector()->GenericSentinel(GetIsolate()), SKIP_WRITE_BARRIER); |
+} |
+ |
+ |
+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 +446,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 |