[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:
Frank Emrich 2021-03-05 14:16:00 +01:00 committed by Commit Bot
parent 98919e51b2
commit 1b67ab4d3f
9 changed files with 72 additions and 61 deletions

View File

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

View File

@ -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();

View File

@ -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());
}

View File

@ -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);

View File

@ -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);

View File

@ -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())

View File

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

View File

@ -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_);

View File

@ -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());
}