From 0302e63e7f467a677466653378449d00ea096c56 Mon Sep 17 00:00:00 2001 From: mvstanton Date: Fri, 28 Aug 2015 02:01:22 -0700 Subject: [PATCH] Vector ICs: Make the Oracle gather feedback for vector stores. Also, polymorphic element stores have a slightly different shape for the array attached to a vector slot. It's of the form [map, map, handler], where the 2nd map is either a transition map or undefined (the maps are actually in WeakCells). Review URL: https://codereview.chromium.org/1316953003 Cr-Commit-Position: refs/heads/master@{#30432} --- src/type-feedback-vector.cc | 86 +++++++++++++++++++++++++++++++++---- src/type-feedback-vector.h | 6 +++ src/type-info.cc | 70 +++++++++++++++++++++++++----- src/type-info.h | 13 ++++++ src/typing.cc | 21 +++++++-- 5 files changed, 173 insertions(+), 23 deletions(-) diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc index fd49513026..fa9c50c8f1 100644 --- a/src/type-feedback-vector.cc +++ b/src/type-feedback-vector.cc @@ -584,6 +584,32 @@ void KeyedStoreICNexus::ConfigurePolymorphic(Handle name, } +void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps, + MapHandleList* transitioned_maps, + CodeHandleList* handlers) { + int receiver_count = maps->length(); + DCHECK(receiver_count > 1); + Handle array = EnsureArrayOfSize(receiver_count * 3); + SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), + SKIP_WRITE_BARRIER); + + Handle undefined_value = GetIsolate()->factory()->undefined_value(); + for (int i = 0; i < receiver_count; ++i) { + Handle map = maps->at(i); + Handle cell = Map::WeakCellForMap(map); + array->set(i * 3, *cell); + if (!transitioned_maps->at(i).is_null()) { + Handle transitioned_map = transitioned_maps->at(i); + cell = Map::WeakCellForMap(transitioned_map); + array->set((i * 3) + 1, *cell); + } else { + array->set((i * 3) + 1, *undefined_value); + } + array->set((i * 3) + 2, *handlers->at(i)); + } +} + + int FeedbackNexus::ExtractMaps(MapHandleList* maps) const { Isolate* isolate = GetIsolate(); Object* feedback = GetFeedback(); @@ -593,10 +619,13 @@ int FeedbackNexus::ExtractMaps(MapHandleList* maps) const { feedback = GetFeedbackExtra(); } FixedArray* array = FixedArray::cast(feedback); - // The array should be of the form [], then - // [map, handler, map, handler, ... ] + // The array should be of the form + // [map, handler, map, handler, ...] + // or + // [map, map, handler, map, map, handler, ...] DCHECK(array->length() >= 2); - for (int i = 0; i < array->length(); i += 2) { + int increment = array->get(1)->IsCode() ? 2 : 3; + for (int i = 0; i < array->length(); i += increment) { DCHECK(array->get(i)->IsWeakCell()); WeakCell* cell = WeakCell::cast(array->get(i)); if (!cell->cleared()) { @@ -626,13 +655,15 @@ MaybeHandle FeedbackNexus::FindHandlerForMap(Handle map) const { feedback = GetFeedbackExtra(); } FixedArray* array = FixedArray::cast(feedback); - for (int i = 0; i < array->length(); i += 2) { + DCHECK(array->length() >= 2); + int increment = array->get(1)->IsCode() ? 2 : 3; + for (int i = 0; i < array->length(); i += increment) { DCHECK(array->get(i)->IsWeakCell()); WeakCell* cell = WeakCell::cast(array->get(i)); if (!cell->cleared()) { Map* array_map = Map::cast(cell->value()); if (array_map == *map) { - Code* code = Code::cast(array->get(i + 1)); + Code* code = Code::cast(array->get(i + increment - 1)); DCHECK(code->kind() == Code::HANDLER); return handle(code); } @@ -662,14 +693,18 @@ bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const { feedback = GetFeedbackExtra(); } FixedArray* array = FixedArray::cast(feedback); - // The array should be of the form [map, handler, map, handler, ... ]. + // The array should be of the form + // [map, handler, map, handler, ...] + // or + // [map, map, handler, map, map, handler, ...] // Be sure to skip handlers whose maps have been cleared. DCHECK(array->length() >= 2); - for (int i = 0; i < array->length(); i += 2) { + int increment = array->get(1)->IsCode() ? 2 : 3; + for (int i = 0; i < array->length(); i += increment) { DCHECK(array->get(i)->IsWeakCell()); WeakCell* cell = WeakCell::cast(array->get(i)); if (!cell->cleared()) { - Code* code = Code::cast(array->get(i + 1)); + Code* code = Code::cast(array->get(i + increment - 1)); DCHECK(code->kind() == Code::HANDLER); code_list->Add(handle(code)); count++; @@ -722,5 +757,40 @@ void StoreICNexus::Clear(Code* host) { void KeyedStoreICNexus::Clear(Code* host) { KeyedStoreIC::Clear(GetIsolate(), host, this); } + + +KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const { + KeyedAccessStoreMode mode = STANDARD_STORE; + MapHandleList maps; + CodeHandleList handlers; + + if (GetKeyType() == PROPERTY) return mode; + + ExtractMaps(&maps); + FindHandlers(&handlers, maps.length()); + for (int i = 0; i < handlers.length(); i++) { + // The first handler that isn't the slow handler will have the bits we need. + Handle handler = handlers.at(i); + CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key()); + uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key()); + CHECK(major_key == CodeStub::KeyedStoreSloppyArguments || + major_key == CodeStub::StoreFastElement || + major_key == CodeStub::StoreElement || + major_key == CodeStub::ElementsTransitionAndStore || + major_key == CodeStub::NoCache); + if (major_key != CodeStub::NoCache) { + mode = CommonStoreModeBits::decode(minor_key); + break; + } + } + + return mode; +} + + +IcCheckType KeyedStoreICNexus::GetKeyType() const { + // The structure of the vector slots tells us the type. + return GetFeedback()->IsName() ? PROPERTY : ELEMENT; +} } // namespace internal } // namespace v8 diff --git a/src/type-feedback-vector.h b/src/type-feedback-vector.h index 86292a2ab0..29e4402d7d 100644 --- a/src/type-feedback-vector.h +++ b/src/type-feedback-vector.h @@ -490,6 +490,12 @@ class KeyedStoreICNexus : public FeedbackNexus { // name can be null. void ConfigurePolymorphic(Handle name, MapHandleList* maps, CodeHandleList* handlers); + void ConfigurePolymorphic(MapHandleList* maps, + MapHandleList* transitioned_maps, + CodeHandleList* handlers); + + KeyedAccessStoreMode GetKeyedAccessStoreMode() const; + IcCheckType GetKeyType() const; InlineCacheState StateFromFeedback() const override; Name* FindFirstName() const override; diff --git a/src/type-info.cc b/src/type-info.cc index bffeccfbc1..15a64ef845 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -131,6 +131,21 @@ bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) { } +bool TypeFeedbackOracle::StoreIsUninitialized(FeedbackVectorICSlot slot) { + if (!slot.IsInvalid()) { + Code::Kind kind = feedback_vector_->GetKind(slot); + if (kind == Code::STORE_IC) { + StoreICNexus nexus(feedback_vector_, slot); + return nexus.StateFromFeedback(); + } else if (kind == Code::KEYED_STORE_IC) { + KeyedStoreICNexus nexus(feedback_vector_, slot); + return nexus.StateFromFeedback(); + } + } + return true; +} + + bool TypeFeedbackOracle::CallIsUninitialized(FeedbackVectorICSlot slot) { Handle value = GetInfo(slot); return value->IsUndefined() || @@ -180,18 +195,17 @@ void TypeFeedbackOracle::GetStoreModeAndKeyType( } -void TypeFeedbackOracle::GetLoadKeyType( - TypeFeedbackId ast_id, IcCheckType* key_type) { - Handle maybe_code = GetInfo(ast_id); - if (maybe_code->IsCode()) { - Handle code = Handle::cast(maybe_code); - if (code->kind() == Code::KEYED_LOAD_IC) { - ExtraICState extra_ic_state = code->extra_ic_state(); - *key_type = KeyedLoadIC::GetKeyType(extra_ic_state); - return; - } +void TypeFeedbackOracle::GetStoreModeAndKeyType( + FeedbackVectorICSlot slot, KeyedAccessStoreMode* store_mode, + IcCheckType* key_type) { + if (!slot.IsInvalid()) { + KeyedStoreICNexus nexus(feedback_vector_, slot); + *store_mode = nexus.GetKeyedAccessStoreMode(); + *key_type = nexus.GetKeyType(); + } else { + *store_mode = STANDARD_STORE; + *key_type = ELEMENT; } - *key_type = ELEMENT; } @@ -366,6 +380,15 @@ void TypeFeedbackOracle::AssignmentReceiverTypes(TypeFeedbackId id, } +void TypeFeedbackOracle::AssignmentReceiverTypes(FeedbackVectorICSlot slot, + Handle name, + SmallMapList* receiver_types) { + receiver_types->Clear(); + Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); + CollectReceiverTypes(slot, name, flags, receiver_types); +} + + void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( TypeFeedbackId id, SmallMapList* receiver_types, KeyedAccessStoreMode* store_mode, IcCheckType* key_type) { @@ -375,6 +398,15 @@ void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( } +void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( + FeedbackVectorICSlot slot, SmallMapList* receiver_types, + KeyedAccessStoreMode* store_mode, IcCheckType* key_type) { + receiver_types->Clear(); + CollectReceiverTypes(slot, receiver_types); + GetStoreModeAndKeyType(slot, store_mode, key_type); +} + + void TypeFeedbackOracle::CountReceiverTypes(TypeFeedbackId id, SmallMapList* receiver_types) { receiver_types->Clear(); @@ -382,6 +414,15 @@ void TypeFeedbackOracle::CountReceiverTypes(TypeFeedbackId id, } +void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorICSlot slot, + Handle name, + Code::Flags flags, + SmallMapList* types) { + StoreICNexus nexus(feedback_vector_, slot); + CollectReceiverTypes(&nexus, name, flags, types); +} + + void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, Handle name, Code::Flags flags, @@ -419,6 +460,13 @@ void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, } +void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorICSlot slot, + SmallMapList* types) { + KeyedStoreICNexus nexus(feedback_vector_, slot); + CollectReceiverTypes(&nexus, types); +} + + template void TypeFeedbackOracle::CollectReceiverTypes(T* obj, SmallMapList* types) { MapHandleList maps; diff --git a/src/type-info.h b/src/type-info.h index 7143458a35..96539c923b 100644 --- a/src/type-info.h +++ b/src/type-info.h @@ -28,6 +28,7 @@ class TypeFeedbackOracle: public ZoneObject { InlineCacheState LoadInlineCacheState(TypeFeedbackId id); InlineCacheState LoadInlineCacheState(FeedbackVectorICSlot slot); bool StoreIsUninitialized(TypeFeedbackId id); + bool StoreIsUninitialized(FeedbackVectorICSlot slot); bool CallIsUninitialized(FeedbackVectorICSlot slot); bool CallIsMonomorphic(FeedbackVectorICSlot slot); bool KeyedArrayCallIsHoley(TypeFeedbackId id); @@ -42,6 +43,9 @@ class TypeFeedbackOracle: public ZoneObject { void GetStoreModeAndKeyType(TypeFeedbackId id, KeyedAccessStoreMode* store_mode, IcCheckType* key_type); + void GetStoreModeAndKeyType(FeedbackVectorICSlot slot, + KeyedAccessStoreMode* store_mode, + IcCheckType* key_type); void GetLoadKeyType(TypeFeedbackId id, IcCheckType* key_type); void PropertyReceiverTypes(FeedbackVectorICSlot slot, Handle name, @@ -51,13 +55,20 @@ class TypeFeedbackOracle: public ZoneObject { IcCheckType* key_type); void AssignmentReceiverTypes(TypeFeedbackId id, Handle name, SmallMapList* receiver_types); + void AssignmentReceiverTypes(FeedbackVectorICSlot slot, Handle name, + SmallMapList* receiver_types); void KeyedAssignmentReceiverTypes(TypeFeedbackId id, SmallMapList* receiver_types, KeyedAccessStoreMode* store_mode, IcCheckType* key_type); + void KeyedAssignmentReceiverTypes(FeedbackVectorICSlot slot, + SmallMapList* receiver_types, + KeyedAccessStoreMode* store_mode, + IcCheckType* key_type); void CountReceiverTypes(TypeFeedbackId id, SmallMapList* receiver_types); + void CollectReceiverTypes(FeedbackVectorICSlot slot, SmallMapList* types); void CollectReceiverTypes(TypeFeedbackId id, SmallMapList* types); template @@ -102,6 +113,8 @@ class TypeFeedbackOracle: public ZoneObject { Isolate* isolate() const { return isolate_; } private: + void CollectReceiverTypes(FeedbackVectorICSlot slot, Handle name, + Code::Flags flags, SmallMapList* types); void CollectReceiverTypes(TypeFeedbackId id, Handle name, Code::Flags flags, SmallMapList* types); template diff --git a/src/typing.cc b/src/typing.cc index 1cb7577775..b2b60bde2c 100644 --- a/src/typing.cc +++ b/src/typing.cc @@ -427,18 +427,31 @@ void AstTyper::VisitAssignment(Assignment* expr) { Property* prop = expr->target()->AsProperty(); if (prop != NULL) { TypeFeedbackId id = expr->AssignmentFeedbackId(); - expr->set_is_uninitialized(oracle()->StoreIsUninitialized(id)); + FeedbackVectorICSlot slot = expr->AssignmentSlot(); + expr->set_is_uninitialized(FLAG_vector_stores + ? oracle()->StoreIsUninitialized(slot) + : oracle()->StoreIsUninitialized(id)); if (!expr->IsUninitialized()) { + SmallMapList* receiver_types = expr->GetReceiverTypes(); if (prop->key()->IsPropertyName()) { Literal* lit_key = prop->key()->AsLiteral(); DCHECK(lit_key != NULL && lit_key->value()->IsString()); Handle name = Handle::cast(lit_key->value()); - oracle()->AssignmentReceiverTypes(id, name, expr->GetReceiverTypes()); + if (FLAG_vector_stores) { + oracle()->AssignmentReceiverTypes(slot, name, receiver_types); + } else { + oracle()->AssignmentReceiverTypes(id, name, receiver_types); + } } else { KeyedAccessStoreMode store_mode; IcCheckType key_type; - oracle()->KeyedAssignmentReceiverTypes(id, expr->GetReceiverTypes(), - &store_mode, &key_type); + if (FLAG_vector_stores) { + oracle()->KeyedAssignmentReceiverTypes(slot, receiver_types, + &store_mode, &key_type); + } else { + oracle()->KeyedAssignmentReceiverTypes(id, receiver_types, + &store_mode, &key_type); + } expr->set_store_mode(store_mode); expr->set_key_type(key_type); }