| 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
|
|
|