}
+void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
+ MapHandleList* transitioned_maps,
+ CodeHandleList* handlers) {
+ int receiver_count = maps->length();
+ DCHECK(receiver_count > 1);
+ Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3);
+ SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+ SKIP_WRITE_BARRIER);
+
+ Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value();
+ for (int i = 0; i < receiver_count; ++i) {
+ Handle<Map> map = maps->at(i);
+ Handle<WeakCell> cell = Map::WeakCellForMap(map);
+ array->set(i * 3, *cell);
+ if (!transitioned_maps->at(i).is_null()) {
+ Handle<Map> 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();
feedback = GetFeedbackExtra();
}
FixedArray* array = FixedArray::cast(feedback);
- // The array should be of the form [<optional name>], 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()) {
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);
}
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++;
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<Code> 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
// name can be null.
void ConfigurePolymorphic(Handle<Name> 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;
}
+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<Object> value = GetInfo(slot);
return value->IsUndefined() ||
}
-void TypeFeedbackOracle::GetLoadKeyType(
- TypeFeedbackId ast_id, IcCheckType* key_type) {
- Handle<Object> maybe_code = GetInfo(ast_id);
- if (maybe_code->IsCode()) {
- Handle<Code> code = Handle<Code>::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;
}
}
+void TypeFeedbackOracle::AssignmentReceiverTypes(FeedbackVectorICSlot slot,
+ Handle<Name> 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) {
}
+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();
}
+void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorICSlot slot,
+ Handle<Name> name,
+ Code::Flags flags,
+ SmallMapList* types) {
+ StoreICNexus nexus(feedback_vector_, slot);
+ CollectReceiverTypes<FeedbackNexus>(&nexus, name, flags, types);
+}
+
+
void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id,
Handle<Name> name,
Code::Flags flags,
}
+void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorICSlot slot,
+ SmallMapList* types) {
+ KeyedStoreICNexus nexus(feedback_vector_, slot);
+ CollectReceiverTypes<FeedbackNexus>(&nexus, types);
+}
+
+
template <class T>
void TypeFeedbackOracle::CollectReceiverTypes(T* obj, SmallMapList* types) {
MapHandleList maps;
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);
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> name,
IcCheckType* key_type);
void AssignmentReceiverTypes(TypeFeedbackId id, Handle<Name> name,
SmallMapList* receiver_types);
+ void AssignmentReceiverTypes(FeedbackVectorICSlot slot, Handle<Name> 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 <class T>
Isolate* isolate() const { return isolate_; }
private:
+ void CollectReceiverTypes(FeedbackVectorICSlot slot, Handle<Name> name,
+ Code::Flags flags, SmallMapList* types);
void CollectReceiverTypes(TypeFeedbackId id, Handle<Name> name,
Code::Flags flags, SmallMapList* types);
template <class T>
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<String> name = Handle<String>::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);
}