[dict-proto] SwissNameDictionary rollout in runtime code, pt. 2
This CL is part of a series that makes SwissNameDictionary available as a new property backing store. Currently, the flag v8_dict_mode_prototypes allows selecting between NameDictionary and OrderedNameDictionary as the backing store used for all dictionary mode objects. This series of CLs changes this such that enabling the flag causes SwissNameDictionary being used instead of OrderedNameDictionary. The behavior for when the flag is not set remains unchanged (= use NameDictionary). This particular CL just collects many small changes. Note that the changes this CL makes to literal-objects.cc do not fix the problems with the enumeration order of computed property names in classes that currently exist when using OrderedNameDictionary. This will be fixed separately. Bug: v8:11388 Change-Id: I6b98f61c395b4f2788407d6a34363ef8863cce9a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2735834 Commit-Queue: Frank Emrich <emrich@google.com> Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Marja Hölttä <marja@chromium.org> Cr-Commit-Position: refs/heads/master@{#73224}
This commit is contained in:
parent
98919e51b2
commit
1b67ab4d3f
@ -6676,9 +6676,8 @@ Local<v8::Object> v8::Object::New(Isolate* isolate,
|
||||
// large enough to hold all of them, while we start with no elements
|
||||
// (see http://bit.ly/v8-fast-object-create-cpp for the motivation).
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
i::Handle<i::OrderedNameDictionary> properties =
|
||||
i::OrderedNameDictionary::Allocate(i_isolate, static_cast<int>(length))
|
||||
.ToHandleChecked();
|
||||
i::Handle<i::SwissNameDictionary> properties =
|
||||
i_isolate->factory()->NewSwissNameDictionary(static_cast<int>(length));
|
||||
AddPropertiesAndElementsToObject(i_isolate, properties, elements, names,
|
||||
values, length);
|
||||
i::Handle<i::JSObject> obj =
|
||||
|
@ -1762,7 +1762,7 @@ void JSObject::IncrementSpillStatistics(Isolate* isolate,
|
||||
info->number_of_slow_unused_properties_ +=
|
||||
dict.Capacity() - dict.NumberOfElements();
|
||||
} else if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
OrderedNameDictionary dict = property_dictionary_ordered();
|
||||
SwissNameDictionary dict = property_dictionary_swiss();
|
||||
info->number_of_slow_used_properties_ += dict.NumberOfElements();
|
||||
info->number_of_slow_unused_properties_ +=
|
||||
dict.Capacity() - dict.NumberOfElements();
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "src/common/globals.h"
|
||||
#include "src/diagnostics/disasm.h"
|
||||
#include "src/diagnostics/disassembler.h"
|
||||
#include "src/execution/isolate-utils-inl.h"
|
||||
#include "src/heap/heap-inl.h" // For InOldSpace.
|
||||
#include "src/heap/heap-write-barrier-inl.h" // For GetIsolateFromWritableObj.
|
||||
#include "src/init/bootstrapper.h"
|
||||
@ -73,6 +74,13 @@ void PrintDictionaryContents(std::ostream& os, T dict) {
|
||||
DisallowGarbageCollection no_gc;
|
||||
ReadOnlyRoots roots = dict.GetReadOnlyRoots();
|
||||
|
||||
if (dict.Capacity() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Isolate* isolate = GetIsolateFromWritableObject(dict);
|
||||
// IterateEntries for SwissNameDictionary needs to create a handle.
|
||||
HandleScope scope(isolate);
|
||||
for (InternalIndex i : dict.IterateEntries()) {
|
||||
Object k;
|
||||
if (!dict.ToKey(roots, i, &k)) continue;
|
||||
@ -308,7 +316,7 @@ bool JSObject::PrintProperties(std::ostream& os) { // NOLINT
|
||||
PrintDictionaryContents(
|
||||
os, JSGlobalObject::cast(*this).global_dictionary(kAcquireLoad));
|
||||
} else if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
PrintDictionaryContents(os, property_dictionary_ordered());
|
||||
PrintDictionaryContents(os, property_dictionary_swiss());
|
||||
} else {
|
||||
PrintDictionaryContents(os, property_dictionary());
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ LoadHandler::Kind LoadHandler::GetHandlerKind(Smi smi_handler) {
|
||||
}
|
||||
|
||||
Handle<Smi> LoadHandler::LoadNormal(Isolate* isolate) {
|
||||
// TODO(v8:11167) remove DCHECK once OrderedNameDictionary supported.
|
||||
// TODO(v8:11167) remove DCHECK once SwissNameDictionary supported.
|
||||
DCHECK(!V8_DICT_MODE_PROTOTYPES_BOOL);
|
||||
int config = KindBits::encode(kNormal);
|
||||
return handle(Smi::FromInt(config), isolate);
|
||||
@ -130,7 +130,7 @@ Handle<Smi> StoreHandler::StoreGlobalProxy(Isolate* isolate) {
|
||||
}
|
||||
|
||||
Handle<Smi> StoreHandler::StoreNormal(Isolate* isolate) {
|
||||
// TODO(v8:11167) remove DCHECK once OrderedNameDictionary supported.
|
||||
// TODO(v8:11167) remove DCHECK once SwissNameDictionary supported.
|
||||
DCHECK(!V8_DICT_MODE_PROTOTYPES_BOOL);
|
||||
int config = KindBits::encode(kNormal);
|
||||
return handle(Smi::FromInt(config), isolate);
|
||||
|
@ -116,7 +116,7 @@ Handle<Object> LoadHandler::LoadFromPrototype(
|
||||
Isolate* isolate, Handle<Map> lookup_start_object_map,
|
||||
Handle<JSReceiver> holder, Handle<Smi> smi_handler,
|
||||
MaybeObjectHandle maybe_data1, MaybeObjectHandle maybe_data2) {
|
||||
// TODO(v8:11167) remove DCHECK once OrderedNameDictionary supported.
|
||||
// TODO(v8:11167) remove DCHECK once SwissNameDictionary supported.
|
||||
DCHECK_IMPLIES(V8_DICT_MODE_PROTOTYPES_BOOL,
|
||||
GetHandlerKind(*smi_handler) != Kind::kNormal);
|
||||
MaybeObjectHandle data1;
|
||||
@ -274,7 +274,7 @@ Handle<Object> StoreHandler::StoreThroughPrototype(
|
||||
Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
|
||||
Handle<Smi> smi_handler, MaybeObjectHandle maybe_data1,
|
||||
MaybeObjectHandle maybe_data2) {
|
||||
// TODO(v8:11167) remove DCHECK once OrderedNameDictionary supported.
|
||||
// TODO(v8:11167) remove DCHECK once SwissNameDictionary supported.
|
||||
DCHECK_IMPLIES(V8_DICT_MODE_PROTOTYPES_BOOL,
|
||||
KindBits::decode(smi_handler->value()) != Kind::kNormal);
|
||||
|
||||
|
@ -927,7 +927,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
|
||||
MaybeObjectHandle::Weak(lookup->GetPropertyCell()));
|
||||
} else {
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
// TODO(v8:11167) remove once OrderedNameDictionary supported.
|
||||
// TODO(v8:11167) remove once SwissNameDictionary supported.
|
||||
smi_handler = LoadHandler::LoadSlow(isolate());
|
||||
} else {
|
||||
smi_handler = LoadHandler::LoadNormal(isolate());
|
||||
@ -1814,7 +1814,8 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
|
||||
DCHECK(holder.is_identical_to(receiver));
|
||||
DCHECK_IMPLIES(!V8_DICT_PROPERTY_CONST_TRACKING_BOOL,
|
||||
lookup->constness() == PropertyConstness::kMutable);
|
||||
// TODO(v8:11167) don't create slow hanlder once OrderedNameDictionary
|
||||
|
||||
// TODO(v8:11167) don't create slow hanlder once SwissNameDictionary
|
||||
// supported.
|
||||
Handle<Smi> handler = V8_DICT_MODE_PROTOTYPES_BOOL
|
||||
? StoreHandler::StoreSlow(isolate())
|
||||
|
@ -25,7 +25,7 @@ namespace internal {
|
||||
namespace {
|
||||
|
||||
// The enumeration order index in the property details is unused if they are
|
||||
// stored in a OrderedNameDictionary or NumberDictionary (because they handle
|
||||
// stored in a SwissNameDictionary or NumberDictionary (because they handle
|
||||
// propery ordering differently). We then use this dummy value instead.
|
||||
constexpr int kDummyEnumerationIndex = 0;
|
||||
|
||||
@ -100,14 +100,13 @@ Handle<NameDictionary> DictionaryAddNoUpdateNextEnumerationIndex(
|
||||
}
|
||||
|
||||
template <typename LocalIsolate>
|
||||
Handle<OrderedNameDictionary> DictionaryAddNoUpdateNextEnumerationIndex(
|
||||
LocalIsolate* isolate, Handle<OrderedNameDictionary> dictionary,
|
||||
Handle<SwissNameDictionary> DictionaryAddNoUpdateNextEnumerationIndex(
|
||||
LocalIsolate* isolate, Handle<SwissNameDictionary> dictionary,
|
||||
Handle<Name> name, Handle<Object> value, PropertyDetails details,
|
||||
InternalIndex* entry_out = nullptr) {
|
||||
// OrderedNameDictionary does not maintain the enumeration order in property
|
||||
// SwissNameDictionary does not maintain the enumeration order in property
|
||||
// details, so it's a normal Add().
|
||||
return OrderedNameDictionary::Add(isolate, dictionary, name, value, details)
|
||||
.ToHandleChecked();
|
||||
return SwissNameDictionary::Add(isolate, dictionary, name, value, details);
|
||||
}
|
||||
|
||||
template <typename LocalIsolate>
|
||||
@ -124,7 +123,7 @@ Handle<NumberDictionary> DictionaryAddNoUpdateNextEnumerationIndex(
|
||||
template <typename Dictionary>
|
||||
void DictionaryUpdateMaxNumberKey(Handle<Dictionary> dictionary,
|
||||
Handle<Name> name) {
|
||||
STATIC_ASSERT((std::is_same<Dictionary, OrderedNameDictionary>::value ||
|
||||
STATIC_ASSERT((std::is_same<Dictionary, SwissNameDictionary>::value ||
|
||||
std::is_same<Dictionary, NameDictionary>::value));
|
||||
// No-op for (ordered) name dictionaries.
|
||||
}
|
||||
@ -162,7 +161,7 @@ void AddToDictionaryTemplate(LocalIsolate* isolate,
|
||||
std::is_same<Dictionary, NumberDictionary>::value;
|
||||
STATIC_ASSERT(is_elements_dictionary !=
|
||||
(std::is_same<Dictionary, NameDictionary>::value ||
|
||||
std::is_same<Dictionary, OrderedNameDictionary>::value));
|
||||
std::is_same<Dictionary, SwissNameDictionary>::value));
|
||||
|
||||
if (entry.is_not_found()) {
|
||||
// Entry not found, add new one.
|
||||
@ -407,7 +406,7 @@ class ObjectDescriptor {
|
||||
descriptor_array_template_ = factory->empty_descriptor_array();
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
properties_dictionary_template_ =
|
||||
factory->empty_ordered_property_dictionary();
|
||||
factory->empty_swiss_property_dictionary();
|
||||
} else {
|
||||
properties_dictionary_template_ = factory->empty_property_dictionary();
|
||||
}
|
||||
@ -417,9 +416,9 @@ class ObjectDescriptor {
|
||||
property_count_ + computed_count_ + property_slack_;
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
properties_dictionary_template_ =
|
||||
OrderedNameDictionary::Allocate(isolate, need_space_for,
|
||||
AllocationType::kOld)
|
||||
.ToHandleChecked();
|
||||
isolate->factory()->NewSwissNameDictionary(need_space_for,
|
||||
AllocationType::kOld);
|
||||
|
||||
} else {
|
||||
properties_dictionary_template_ = NameDictionary::New(
|
||||
isolate, need_space_for, AllocationType::kOld);
|
||||
@ -533,8 +532,8 @@ class ObjectDescriptor {
|
||||
return Handle<NameDictionary>::cast(properties_dictionary_template_);
|
||||
}
|
||||
|
||||
Handle<OrderedNameDictionary> properties_ordered_dictionary_template() const {
|
||||
return Handle<OrderedNameDictionary>::cast(properties_dictionary_template_);
|
||||
Handle<SwissNameDictionary> properties_ordered_dictionary_template() const {
|
||||
return Handle<SwissNameDictionary>::cast(properties_dictionary_template_);
|
||||
}
|
||||
|
||||
const int property_slack_;
|
||||
@ -546,7 +545,7 @@ class ObjectDescriptor {
|
||||
|
||||
Handle<DescriptorArray> descriptor_array_template_;
|
||||
|
||||
// Is either a NameDictionary or OrderedNameDictionary.
|
||||
// Is either a NameDictionary or SwissNameDictionary.
|
||||
Handle<HeapObject> properties_dictionary_template_;
|
||||
|
||||
Handle<NumberDictionary> elements_dictionary_template_;
|
||||
@ -569,16 +568,8 @@ template void ClassBoilerplate::AddToPropertiesTemplate(
|
||||
LocalIsolate* isolate, Handle<NameDictionary> dictionary, Handle<Name> name,
|
||||
int key_index, ClassBoilerplate::ValueKind value_kind, Smi value);
|
||||
template void ClassBoilerplate::AddToPropertiesTemplate(
|
||||
Isolate* isolate, Handle<OrderedNameDictionary> dictionary,
|
||||
Handle<Name> name, int key_index, ClassBoilerplate::ValueKind value_kind,
|
||||
Smi value);
|
||||
template <>
|
||||
void ClassBoilerplate::AddToPropertiesTemplate(
|
||||
Isolate* isolate, Handle<SwissNameDictionary> dictionary, Handle<Name> name,
|
||||
int key_index, ClassBoilerplate::ValueKind value_kind, Smi value) {
|
||||
// TODO(v8:11388) Temporary dummy to make MSVC happy, removed in next CL.
|
||||
UNREACHABLE();
|
||||
}
|
||||
int key_index, ClassBoilerplate::ValueKind value_kind, Smi value);
|
||||
|
||||
template <typename LocalIsolate>
|
||||
void ClassBoilerplate::AddToElementsTemplate(
|
||||
|
@ -381,8 +381,13 @@ void LookupIterator::PrepareForDataProperty(Handle<Object> value) {
|
||||
// that's only for the case that the existing map is a fast mode map.
|
||||
// Therefore, we need to perform the necessary updates to the property
|
||||
// details and the prototype validity cell directly.
|
||||
NameDictionary dict = holder->property_dictionary();
|
||||
dict.DetailsAtPut(dictionary_entry(), property_details_);
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
SwissNameDictionary dict = holder->property_dictionary_swiss();
|
||||
dict.DetailsAtPut(dictionary_entry(), property_details_);
|
||||
} else {
|
||||
NameDictionary dict = holder->property_dictionary();
|
||||
dict.DetailsAtPut(dictionary_entry(), property_details_);
|
||||
}
|
||||
|
||||
Map old_map = holder->map(isolate_);
|
||||
if (old_map.is_prototype_map()) {
|
||||
@ -429,8 +434,13 @@ void LookupIterator::PrepareForDataProperty(Handle<Object> value) {
|
||||
property_details_ =
|
||||
property_details_.CopyWithConstness(PropertyConstness::kMutable);
|
||||
|
||||
NameDictionary dict = holder_obj->property_dictionary();
|
||||
dict.DetailsAtPut(dictionary_entry(), property_details_);
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
SwissNameDictionary dict = holder_obj->property_dictionary_swiss();
|
||||
dict.DetailsAtPut(dictionary_entry(), property_details_);
|
||||
} else {
|
||||
NameDictionary dict = holder_obj->property_dictionary();
|
||||
dict.DetailsAtPut(dictionary_entry(), property_details_);
|
||||
}
|
||||
|
||||
DCHECK_IMPLIES(new_map->is_prototype_map(),
|
||||
!new_map->IsPrototypeValidityCellValid());
|
||||
@ -499,9 +509,10 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
|
||||
} else {
|
||||
PropertyDetails details(kData, attributes, PropertyConstness::kMutable);
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
Handle<OrderedNameDictionary> dictionary(
|
||||
holder_obj->property_dictionary_ordered(isolate_), isolate());
|
||||
dictionary->SetEntry(dictionary_entry(), *name(), *value, details);
|
||||
Handle<SwissNameDictionary> dictionary(
|
||||
holder_obj->property_dictionary_swiss(isolate_), isolate());
|
||||
dictionary->ValueAtPut(dictionary_entry(), *value);
|
||||
dictionary->DetailsAtPut(dictionary_entry(), details);
|
||||
DCHECK_EQ(details.AsSmi(),
|
||||
dictionary->DetailsAt(dictionary_entry()).AsSmi());
|
||||
property_details_ = details;
|
||||
@ -641,17 +652,13 @@ void LookupIterator::ApplyTransitionToDataProperty(
|
||||
JSObject::InvalidatePrototypeChains(receiver->map(isolate_));
|
||||
}
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
Handle<OrderedNameDictionary> dictionary(
|
||||
receiver->property_dictionary_ordered(isolate_), isolate_);
|
||||
Handle<SwissNameDictionary> dictionary(
|
||||
receiver->property_dictionary_swiss(isolate_), isolate_);
|
||||
|
||||
dictionary =
|
||||
OrderedNameDictionary::Add(isolate(), dictionary, name(),
|
||||
isolate_->factory()->uninitialized_value(),
|
||||
property_details_)
|
||||
.ToHandleChecked();
|
||||
|
||||
// set to last used entry
|
||||
number_ = InternalIndex(dictionary->UsedCapacity() - 1);
|
||||
SwissNameDictionary::Add(isolate(), dictionary, name(),
|
||||
isolate_->factory()->uninitialized_value(),
|
||||
property_details_, &number_);
|
||||
receiver->SetProperties(*dictionary);
|
||||
} else {
|
||||
Handle<NameDictionary> dictionary(receiver->property_dictionary(isolate_),
|
||||
@ -850,7 +857,7 @@ Handle<Object> LookupIterator::FetchValue(
|
||||
.ValueAt(isolate_, dictionary_entry());
|
||||
} else if (!holder_->HasFastProperties(isolate_)) {
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
result = holder_->property_dictionary_ordered(isolate_).ValueAt(
|
||||
result = holder_->property_dictionary_swiss(isolate_).ValueAt(
|
||||
dictionary_entry());
|
||||
} else {
|
||||
result = holder_->property_dictionary(isolate_).ValueAt(
|
||||
@ -931,9 +938,14 @@ bool LookupIterator::IsConstDictValueEqualTo(Object value) const {
|
||||
return true;
|
||||
}
|
||||
Handle<JSReceiver> holder = GetHolder<JSReceiver>();
|
||||
NameDictionary dict = holder->property_dictionary();
|
||||
|
||||
Object current_value = dict.ValueAt(dictionary_entry());
|
||||
Object current_value;
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
SwissNameDictionary dict = holder->property_dictionary_swiss();
|
||||
current_value = dict.ValueAt(dictionary_entry());
|
||||
} else {
|
||||
NameDictionary dict = holder->property_dictionary();
|
||||
current_value = dict.ValueAt(dictionary_entry());
|
||||
}
|
||||
|
||||
if (current_value.IsUninitialized(isolate()) || current_value == value) {
|
||||
return true;
|
||||
@ -1046,8 +1058,8 @@ void LookupIterator::WriteDataValue(Handle<Object> value,
|
||||
holder->IsJSProxy(isolate_) || IsConstDictValueEqualTo(*value));
|
||||
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
OrderedNameDictionary dictionary =
|
||||
holder->property_dictionary_ordered(isolate_);
|
||||
SwissNameDictionary dictionary =
|
||||
holder->property_dictionary_swiss(isolate_);
|
||||
dictionary.ValueAtPut(dictionary_entry(), *value);
|
||||
} else {
|
||||
NameDictionary dictionary = holder->property_dictionary(isolate_);
|
||||
@ -1198,7 +1210,7 @@ LookupIterator::State LookupIterator::LookupInRegularHolder(
|
||||
} else {
|
||||
DCHECK_IMPLIES(holder.IsJSProxy(isolate_), name()->IsPrivate(isolate_));
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
OrderedNameDictionary dict = holder.property_dictionary_ordered(isolate_);
|
||||
SwissNameDictionary dict = holder.property_dictionary_swiss(isolate_);
|
||||
number_ = dict.FindEntry(isolate(), *name_);
|
||||
if (number_.is_not_found()) return NotFound(holder);
|
||||
property_details_ = dict.DetailsAt(number_);
|
||||
|
@ -30,7 +30,7 @@ int AddToSetAndGetHash(Isolate* isolate, Handle<JSObject> obj,
|
||||
|
||||
int GetPropertyDictionaryHash(Handle<JSObject> obj) {
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
return obj->property_dictionary_ordered().Hash();
|
||||
return obj->property_dictionary_swiss().Hash();
|
||||
} else {
|
||||
return obj->property_dictionary().Hash();
|
||||
}
|
||||
@ -38,7 +38,7 @@ int GetPropertyDictionaryHash(Handle<JSObject> obj) {
|
||||
|
||||
int GetPropertyDictionaryLength(Handle<JSObject> obj) {
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
return obj->property_dictionary_ordered().length();
|
||||
return obj->property_dictionary_swiss().Capacity();
|
||||
} else {
|
||||
return obj->property_dictionary().length();
|
||||
}
|
||||
@ -46,7 +46,7 @@ int GetPropertyDictionaryLength(Handle<JSObject> obj) {
|
||||
|
||||
void CheckIsDictionaryModeObject(Handle<JSObject> obj) {
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
CHECK(obj->raw_properties_or_hash().IsOrderedNameDictionary());
|
||||
CHECK(obj->raw_properties_or_hash().IsSwissNameDictionary());
|
||||
} else {
|
||||
CHECK(obj->raw_properties_or_hash().IsNameDictionary());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user