Commit fc7ca518 authored by Frank Emrich's avatar Frank Emrich Committed by Commit Bot

[dict-proto] SwissNameDictionary rollout in runtime code, pt. 1

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
a) moves two operations from ordered-hash-table.cc to
swiss-name-dictionary.cc (which were itself just copies of existing
functions, see the existing TODOs about cleaning this up).

b) adds a new getter for the SwissNameDictionary backing store,
called JSReceiver::property_dictionary_swiss.

c) contains a first wave of replacing usages of
OrderedNameDictionary with SwissNameDictionary.

Bug: v8:11388
Change-Id: Ie6b45571aee3646c0c0d3937b3c25f0f033810dd
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2732676Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Frank Emrich <emrich@google.com>
Cr-Commit-Position: refs/heads/master@{#73213}
parent d4f31caa
......@@ -1602,13 +1602,15 @@ Handle<JSObject> Factory::CopyJSObjectWithAllocationSite(
clone->set_raw_properties_or_hash(*prop);
}
} else {
Handle<FixedArray> properties =
handle(V8_DICT_MODE_PROTOTYPES_BOOL
? FixedArray::cast(source->property_dictionary_ordered())
: FixedArray::cast(source->property_dictionary()),
isolate());
Handle<FixedArray> prop = CopyFixedArray(properties);
clone->set_raw_properties_or_hash(*prop);
Handle<Object> copied_properties;
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
copied_properties = SwissNameDictionary::ShallowCopy(
isolate(), handle(source->property_dictionary_swiss(), isolate()));
} else {
copied_properties =
CopyFixedArray(handle(source->property_dictionary(), isolate()));
}
clone->set_raw_properties_or_hash(*copied_properties);
}
return clone;
}
......@@ -2190,8 +2192,7 @@ Handle<JSObject> Factory::NewSlowJSObjectFromMap(
DCHECK(map->is_dictionary_map());
Handle<HeapObject> object_properties;
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
object_properties =
OrderedNameDictionary::Allocate(isolate(), capacity).ToHandleChecked();
object_properties = NewSwissNameDictionary(capacity, allocation);
} else {
object_properties = NameDictionary::New(isolate(), capacity);
}
......@@ -2205,7 +2206,7 @@ Handle<JSObject> Factory::NewSlowJSObjectWithPropertiesAndElements(
Handle<HeapObject> prototype, Handle<HeapObject> properties,
Handle<FixedArrayBase> elements) {
DCHECK_IMPLIES(V8_DICT_MODE_PROTOTYPES_BOOL,
properties->IsOrderedNameDictionary());
properties->IsSwissNameDictionary());
DCHECK_IMPLIES(!V8_DICT_MODE_PROTOTYPES_BOOL, properties->IsNameDictionary());
Handle<Map> object_map = isolate()->slow_object_with_object_prototype_map();
......
......@@ -60,6 +60,7 @@
#include "src/objects/ordered-hash-table.h"
#include "src/objects/property-cell.h"
#include "src/objects/slots-inl.h"
#include "src/objects/swiss-name-dictionary-inl.h"
#include "src/objects/templates.h"
#include "src/snapshot/snapshot.h"
#include "src/wasm/wasm-js.h"
......@@ -5202,10 +5203,10 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
} else if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// Copy all keys and values in enumeration order.
Handle<OrderedNameDictionary> properties = Handle<OrderedNameDictionary>(
from->property_dictionary_ordered(), isolate());
Handle<SwissNameDictionary> properties = Handle<SwissNameDictionary>(
from->property_dictionary_swiss(), isolate());
ReadOnlyRoots roots(isolate());
for (InternalIndex entry : properties->IterateEntries()) {
for (InternalIndex entry : properties->IterateEntriesOrdered()) {
Object raw_key;
if (!properties->ToKey(roots, entry, &raw_key)) continue;
......
......@@ -75,6 +75,9 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) Dictionary
Handle<Object> value, PropertyDetails details,
InternalIndex* entry_out = nullptr);
static Handle<Derived> ShallowCopy(Isolate* isolate,
Handle<Derived> dictionary);
protected:
// Generic at put operation.
V8_WARN_UNUSED_RESULT static Handle<Derived> AtPut(Isolate* isolate,
......
......@@ -21,6 +21,7 @@
#include "src/objects/shared-function-info.h"
#include "src/objects/slots.h"
#include "src/objects/smi-inl.h"
#include "src/objects/swiss-name-dictionary-inl.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......@@ -605,7 +606,7 @@ void JSReceiver::initialize_properties(Isolate* isolate) {
if (map(isolate).is_dictionary_map()) {
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
WRITE_FIELD(*this, kPropertiesOrHashOffset,
roots.empty_ordered_property_dictionary());
roots.empty_swiss_property_dictionary());
} else {
WRITE_FIELD(*this, kPropertiesOrHashOffset,
roots.empty_property_dictionary());
......@@ -619,7 +620,7 @@ DEF_GETTER(JSReceiver, HasFastProperties, bool) {
DCHECK(raw_properties_or_hash(isolate).IsSmi() ||
((raw_properties_or_hash(isolate).IsGlobalDictionary(isolate) ||
raw_properties_or_hash(isolate).IsNameDictionary(isolate) ||
raw_properties_or_hash(isolate).IsOrderedNameDictionary(isolate)) ==
raw_properties_or_hash(isolate).IsSwissNameDictionary(isolate)) ==
map(isolate).is_dictionary_map()));
return !map(isolate).is_dictionary_map();
}
......@@ -652,6 +653,20 @@ DEF_GETTER(JSReceiver, property_dictionary_ordered, OrderedNameDictionary) {
return OrderedNameDictionary::cast(prop);
}
DEF_GETTER(JSReceiver, property_dictionary_swiss, SwissNameDictionary) {
DCHECK(!IsJSGlobalObject(isolate));
DCHECK(!HasFastProperties(isolate));
DCHECK(V8_DICT_MODE_PROTOTYPES_BOOL);
// Can't use ReadOnlyRoots(isolate) as this isolate could be produced by
// i::GetIsolateForPtrCompr(HeapObject).
Object prop = raw_properties_or_hash(isolate);
if (prop.IsSmi()) {
return GetReadOnlyRoots(isolate).empty_swiss_property_dictionary();
}
return SwissNameDictionary::cast(prop);
}
// TODO(gsathya): Pass isolate directly to this function and access
// the heap from this.
DEF_GETTER(JSReceiver, property_array, PropertyArray) {
......
......@@ -65,6 +65,7 @@
#include "src/objects/prototype-info.h"
#include "src/objects/prototype.h"
#include "src/objects/shared-function-info.h"
#include "src/objects/swiss-name-dictionary-inl.h"
#include "src/objects/transitions.h"
#include "src/strings/string-builder-inl.h"
#include "src/strings/string-stream.h"
......@@ -360,7 +361,7 @@ Maybe<bool> JSReceiver::SetOrCopyDataProperties(
.NumberOfEnumerableProperties();
} else if (V8_DICT_MODE_PROTOTYPES_BOOL) {
source_length =
from->property_dictionary_ordered().NumberOfEnumerableProperties();
from->property_dictionary_swiss().NumberOfEnumerableProperties();
} else {
source_length =
from->property_dictionary().NumberOfEnumerableProperties();
......@@ -646,7 +647,7 @@ Object SetHashAndUpdateProperties(HeapObject properties, int hash) {
if (properties == roots.empty_fixed_array() ||
properties == roots.empty_property_array() ||
properties == roots.empty_property_dictionary() ||
properties == roots.empty_ordered_property_dictionary()) {
properties == roots.empty_swiss_property_dictionary()) {
return Smi::FromInt(hash);
}
......@@ -662,8 +663,8 @@ Object SetHashAndUpdateProperties(HeapObject properties, int hash) {
}
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
DCHECK(properties.IsOrderedNameDictionary());
OrderedNameDictionary::cast(properties).SetHash(hash);
DCHECK(properties.IsSwissNameDictionary());
SwissNameDictionary::cast(properties).SetHash(hash);
} else {
DCHECK(properties.IsNameDictionary());
NameDictionary::cast(properties).SetHash(hash);
......@@ -681,8 +682,8 @@ int GetIdentityHashHelper(JSReceiver object) {
if (properties.IsPropertyArray()) {
return PropertyArray::cast(properties).Hash();
}
if (V8_DICT_MODE_PROTOTYPES_BOOL && properties.IsOrderedNameDictionary()) {
return OrderedNameDictionary::cast(properties).Hash();
if (V8_DICT_MODE_PROTOTYPES_BOOL && properties.IsSwissNameDictionary()) {
return SwissNameDictionary::cast(properties).Hash();
}
if (properties.IsNameDictionary()) {
......@@ -698,7 +699,7 @@ int GetIdentityHashHelper(JSReceiver object) {
ReadOnlyRoots roots = object.GetReadOnlyRoots();
DCHECK(properties == roots.empty_fixed_array() ||
properties == roots.empty_property_dictionary() ||
properties == roots.empty_ordered_property_dictionary());
properties == roots.empty_swiss_property_dictionary());
#endif
return PropertyArray::kNoHashSentinel;
......@@ -786,11 +787,10 @@ void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object,
cell->ClearAndInvalidate(ReadOnlyRoots(isolate));
} else {
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
Handle<OrderedNameDictionary> dictionary(
object->property_dictionary_ordered(), isolate);
Handle<SwissNameDictionary> dictionary(
object->property_dictionary_swiss(), isolate);
dictionary =
OrderedNameDictionary::DeleteEntry(isolate, dictionary, entry);
dictionary = SwissNameDictionary::DeleteEntry(isolate, dictionary, entry);
object->SetProperties(*dictionary);
} else {
Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
......@@ -2137,7 +2137,7 @@ MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
isolate, initial_map,
JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject);
int initial_capacity = V8_DICT_MODE_PROTOTYPES_BOOL
? OrderedNameDictionary::kInitialCapacity
? SwissNameDictionary::kInitialCapacity
: NameDictionary::kInitialCapacity;
Handle<JSObject> result = isolate->factory()->NewFastOrSlowJSObjectFromMap(
initial_map, initial_capacity, AllocationType::kYoung, site);
......@@ -2469,18 +2469,18 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object, Handle<Name> name,
}
} else {
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
Handle<OrderedNameDictionary> dictionary(
object->property_dictionary_ordered(), isolate);
Handle<SwissNameDictionary> dictionary(
object->property_dictionary_swiss(), isolate);
InternalIndex entry = dictionary->FindEntry(isolate, *name);
if (entry.is_not_found()) {
DCHECK_IMPLIES(object->map().is_prototype_map(),
Map::IsPrototypeChainInvalidated(object->map()));
dictionary = OrderedNameDictionary::Add(isolate, dictionary, name,
value, details)
.ToHandleChecked();
dictionary =
SwissNameDictionary::Add(isolate, dictionary, name, value, details);
object->SetProperties(*dictionary);
} else {
dictionary->SetEntry(entry, *name, *value, details);
dictionary->ValueAtPut(entry, *value);
dictionary->DetailsAtPut(entry, details);
}
} else {
Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
......@@ -2968,16 +2968,15 @@ void MigrateFastToSlow(Isolate* isolate, Handle<JSObject> object,
} else {
// Make space for two more properties.
int initial_capacity = V8_DICT_MODE_PROTOTYPES_BOOL
? OrderedNameDictionary::kInitialCapacity
? SwissNameDictionary::kInitialCapacity
: NameDictionary::kInitialCapacity;
property_count += initial_capacity;
}
Handle<NameDictionary> dictionary;
Handle<OrderedNameDictionary> ord_dictionary;
Handle<SwissNameDictionary> ord_dictionary;
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
ord_dictionary =
isolate->factory()->NewOrderedNameDictionary(property_count);
ord_dictionary = isolate->factory()->NewSwissNameDictionary(property_count);
} else {
dictionary = isolate->factory()->NewNameDictionary(property_count);
}
......@@ -3014,8 +3013,7 @@ void MigrateFastToSlow(Isolate* isolate, Handle<JSObject> object,
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
ord_dictionary =
OrderedNameDictionary::Add(isolate, ord_dictionary, key, value, d)
.ToHandleChecked();
SwissNameDictionary::Add(isolate, ord_dictionary, key, value, d);
} else {
dictionary = NameDictionary::Add(isolate, dictionary, key, value, d);
}
......@@ -3424,11 +3422,11 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
Factory* factory = isolate->factory();
Handle<NameDictionary> dictionary;
Handle<OrderedNameDictionary> ord_dictionary;
Handle<SwissNameDictionary> swiss_dictionary;
int number_of_elements;
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
ord_dictionary = handle(object->property_dictionary_ordered(), isolate);
number_of_elements = ord_dictionary->NumberOfElements();
swiss_dictionary = handle(object->property_dictionary_swiss(), isolate);
number_of_elements = swiss_dictionary->NumberOfElements();
} else {
dictionary = handle(object->property_dictionary(), isolate);
number_of_elements = dictionary->NumberOfElements();
......@@ -3442,7 +3440,7 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
int iteration_length;
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// |iteration_order| remains empty handle, we don't need it.
iteration_length = ord_dictionary->UsedCapacity();
iteration_length = swiss_dictionary->UsedCapacity();
} else {
iteration_order = NameDictionary::IterationIndices(isolate, dictionary);
iteration_length = dictionary->NumberOfElements();
......@@ -3455,13 +3453,13 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
for (int i = 0; i < iteration_length; i++) {
PropertyKind kind;
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
InternalIndex index(i);
Object key = ord_dictionary->KeyAt(index);
if (!OrderedNameDictionary::IsKey(roots, key)) {
InternalIndex index(swiss_dictionary->EntryForEnumerationIndex(i));
Object key = swiss_dictionary->KeyAt(index);
if (!SwissNameDictionary::IsKey(roots, key)) {
// Ignore deleted entries.
continue;
}
kind = ord_dictionary->DetailsAt(index).kind();
kind = swiss_dictionary->DetailsAt(index).kind();
} else {
InternalIndex index(Smi::ToInt(iteration_order->get(i)));
DCHECK(dictionary->IsKey(roots, dictionary->KeyAt(isolate, index)));
......@@ -3530,15 +3528,15 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
PropertyDetails details = PropertyDetails::Empty();
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
InternalIndex index(i);
Object key_obj = ord_dictionary->KeyAt(index);
if (!OrderedNameDictionary::IsKey(roots, key_obj)) {
InternalIndex index(swiss_dictionary->EntryForEnumerationIndex(i));
Object key_obj = swiss_dictionary->KeyAt(index);
if (!SwissNameDictionary::IsKey(roots, key_obj)) {
continue;
}
k = Name::cast(key_obj);
value = ord_dictionary->ValueAt(index);
details = ord_dictionary->DetailsAt(index);
value = swiss_dictionary->ValueAt(index);
details = swiss_dictionary->DetailsAt(index);
} else {
InternalIndex index(Smi::ToInt(iteration_order->get(i)));
k = dictionary->NameAt(index);
......@@ -3804,7 +3802,7 @@ bool TestPropertiesIntegrityLevel(JSObject object, PropertyAttributes level) {
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
return TestDictionaryPropertiesIntegrityLevel(
object.property_dictionary_ordered(), object.GetReadOnlyRoots(), level);
object.property_dictionary_swiss(), object.GetReadOnlyRoots(), level);
} else {
return TestDictionaryPropertiesIntegrityLevel(
object.property_dictionary(), object.GetReadOnlyRoots(), level);
......@@ -4108,8 +4106,8 @@ Maybe<bool> JSObject::PreventExtensionsWithTransition(
JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary,
attrs);
} else if (V8_DICT_MODE_PROTOTYPES_BOOL) {
Handle<OrderedNameDictionary> dictionary(
object->property_dictionary_ordered(), isolate);
Handle<SwissNameDictionary> dictionary(
object->property_dictionary_swiss(), isolate);
JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary,
attrs);
} else {
......@@ -4355,7 +4353,7 @@ Object JSObject::SlowReverseLookup(Object value) {
.global_dictionary(kAcquireLoad)
.SlowReverseLookup(value);
} else if (V8_DICT_MODE_PROTOTYPES_BOOL) {
return property_dictionary_ordered().SlowReverseLookup(GetIsolate(), value);
return property_dictionary_swiss().SlowReverseLookup(GetIsolate(), value);
} else {
return property_dictionary().SlowReverseLookup(value);
}
......@@ -4429,16 +4427,23 @@ void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
JSObject::MigrateToMap(isolate, object, new_map);
if (V8_DICT_PROPERTY_CONST_TRACKING_BOOL && !object->HasFastProperties()) {
Handle<NameDictionary> dict =
handle(object->property_dictionary(), isolate);
ReadOnlyRoots roots(isolate);
for (InternalIndex index : dict->IterateEntries()) {
DisallowHeapAllocation no_gc;
auto make_constant = [&](auto dict) {
for (InternalIndex index : dict.IterateEntries()) {
Object k;
if (!dict->ToKey(roots, index, &k)) continue;
if (!dict.ToKey(roots, index, &k)) continue;
PropertyDetails details = dict->DetailsAt(index);
PropertyDetails details = dict.DetailsAt(index);
details = details.CopyWithConstness(PropertyConstness::kConst);
dict->DetailsAtPut(index, details);
dict.DetailsAtPut(index, details);
}
};
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
make_constant(object->property_dictionary_swiss());
} else {
make_constant(object->property_dictionary());
}
}
......
......@@ -50,7 +50,11 @@ class JSReceiver : public HeapObject {
// Gets slow properties for non-global objects (if v8_dict_mode_prototypes is
// set).
// TODO(v8:11388) Keeping both versions around while transition to
// SwissNameDictionary is in progress, will then delete
// property_dictionary_ordered.
DECL_GETTER(property_dictionary_ordered, OrderedNameDictionary)
DECL_GETTER(property_dictionary_swiss, SwissNameDictionary)
// Sets the properties backing store and makes sure any existing hash is moved
// to the new properties store. To clear out the properties store, pass in the
......
......@@ -66,7 +66,7 @@ Handle<JSRegExpResultIndices> JSRegExpResultIndices::BuildIndices(
int num_names = names->length() >> 1;
Handle<HeapObject> group_names;
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
group_names = isolate->factory()->NewOrderedNameDictionary(num_names);
group_names = isolate->factory()->NewSwissNameDictionary(num_names);
} else {
group_names = isolate->factory()->NewNameDictionary(num_names);
}
......@@ -82,11 +82,9 @@ Handle<JSRegExpResultIndices> JSRegExpResultIndices::BuildIndices(
capture_indices = Handle<JSArray>::cast(capture_indices);
}
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
group_names =
OrderedNameDictionary::Add(
isolate, Handle<OrderedNameDictionary>::cast(group_names), name,
capture_indices, PropertyDetails::Empty())
.ToHandleChecked();
group_names = SwissNameDictionary::Add(
isolate, Handle<SwissNameDictionary>::cast(group_names), name,
capture_indices, PropertyDetails::Empty());
} else {
group_names = NameDictionary::Add(
isolate, Handle<NameDictionary>::cast(group_names), name,
......
......@@ -830,7 +830,7 @@ void CommonCopyEnumKeysTo(Isolate* isolate, Handle<Dictionary> dictionary,
continue;
} else {
if (Dictionary::kIsOrderedDictionaryType) {
storage->set(properties, dictionary->NameAt(i));
storage->set(properties, Name::cast(key));
} else {
// If the dictionary does not store elements in enumeration order,
// we need to sort it afterwards in CopyEnumKeysTo. To enable this we
......@@ -875,11 +875,11 @@ void CopyEnumKeysTo(Isolate* isolate, Handle<Dictionary> dictionary,
}
template <>
void CopyEnumKeysTo(Isolate* isolate, Handle<OrderedNameDictionary> dictionary,
void CopyEnumKeysTo(Isolate* isolate, Handle<SwissNameDictionary> dictionary,
Handle<FixedArray> storage, KeyCollectionMode mode,
KeyAccumulator* accumulator) {
CommonCopyEnumKeysTo<OrderedNameDictionary>(isolate, dictionary, storage,
mode, accumulator);
CommonCopyEnumKeysTo<SwissNameDictionary>(isolate, dictionary, storage, mode,
accumulator);
// No need to sort, as CommonCopyEnumKeysTo on OrderedNameDictionary
// adds entries to |storage| in the dict's insertion order
......@@ -1006,7 +1006,7 @@ Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver,
JSGlobalObject::cast(*object).global_dictionary(kAcquireLoad));
} else if (V8_DICT_MODE_PROTOTYPES_BOOL) {
enum_keys = GetOwnEnumPropertyDictionaryKeys(
isolate_, mode_, this, object, object->property_dictionary_ordered());
isolate_, mode_, this, object, object->property_dictionary_swiss());
} else {
enum_keys = GetOwnEnumPropertyDictionaryKeys(
isolate_, mode_, this, object, object->property_dictionary());
......@@ -1045,7 +1045,7 @@ Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver,
this));
} else if (V8_DICT_MODE_PROTOTYPES_BOOL) {
RETURN_NOTHING_IF_NOT_SUCCESSFUL(CollectKeysFromDictionary(
handle(object->property_dictionary_ordered(), isolate_), this));
handle(object->property_dictionary_swiss(), isolate_), this));
} else {
RETURN_NOTHING_IF_NOT_SUCCESSFUL(CollectKeysFromDictionary(
handle(object->property_dictionary(), isolate_), this));
......@@ -1070,7 +1070,7 @@ ExceptionStatus KeyAccumulator::CollectPrivateNames(Handle<JSReceiver> receiver,
this));
} else if (V8_DICT_MODE_PROTOTYPES_BOOL) {
RETURN_FAILURE_IF_NOT_SUCCESSFUL(CollectKeysFromDictionary(
handle(object->property_dictionary_ordered(), isolate_), this));
handle(object->property_dictionary_swiss(), isolate_), this));
} else {
RETURN_FAILURE_IF_NOT_SUCCESSFUL(CollectKeysFromDictionary(
handle(object->property_dictionary(), isolate_), this));
......@@ -1156,7 +1156,7 @@ Handle<FixedArray> KeyAccumulator::GetOwnEnumPropertyKeys(
} else if (V8_DICT_MODE_PROTOTYPES_BOOL) {
return GetOwnEnumPropertyDictionaryKeys(
isolate, KeyCollectionMode::kOwnOnly, nullptr, object,
object->property_dictionary_ordered());
object->property_dictionary_swiss());
} else {
return GetOwnEnumPropertyDictionaryKeys(
isolate, KeyCollectionMode::kOwnOnly, nullptr, object,
......@@ -1189,7 +1189,7 @@ Maybe<bool> KeyAccumulator::CollectOwnJSProxyKeys(Handle<JSReceiver> receiver,
if (filter_ == PRIVATE_NAMES_ONLY) {
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
RETURN_NOTHING_IF_NOT_SUCCESSFUL(CollectKeysFromDictionary(
handle(proxy->property_dictionary_ordered(), isolate_), this));
handle(proxy->property_dictionary_swiss(), isolate_), this));
} else {
RETURN_NOTHING_IF_NOT_SUCCESSFUL(CollectKeysFromDictionary(
handle(proxy->property_dictionary(), isolate_), this));
......
......@@ -572,6 +572,13 @@ 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();
}
template <typename LocalIsolate>
void ClassBoilerplate::AddToElementsTemplate(
......
......@@ -3561,11 +3561,10 @@ Maybe<bool> JSProxy::SetPrivateSymbol(Isolate* isolate, Handle<JSProxy> proxy,
PropertyDetails details(kData, DONT_ENUM, PropertyConstness::kMutable);
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
Handle<OrderedNameDictionary> dict(proxy->property_dictionary_ordered(),
Handle<SwissNameDictionary> dict(proxy->property_dictionary_swiss(),
isolate);
Handle<OrderedNameDictionary> result =
OrderedNameDictionary::Add(isolate, dict, private_name, value, details)
.ToHandleChecked();
Handle<SwissNameDictionary> result =
SwissNameDictionary::Add(isolate, dict, private_name, value, details);
if (!dict.is_identical_to(result)) proxy->SetProperties(*result);
} else {
Handle<NameDictionary> dict(proxy->property_dictionary(), isolate);
......@@ -5922,6 +5921,13 @@ Handle<Derived> Dictionary<Derived, Shape>::Add(LocalIsolate* isolate,
return dictionary;
}
template <typename Derived, typename Shape>
Handle<Derived> Dictionary<Derived, Shape>::ShallowCopy(
Isolate* isolate, Handle<Derived> dictionary) {
return Handle<Derived>::cast(isolate->factory()->CopyFixedArrayWithMap(
dictionary, Derived::GetMap(ReadOnlyRoots(isolate))));
}
// static
Handle<SimpleNumberDictionary> SimpleNumberDictionary::Set(
Isolate* isolate, Handle<SimpleNumberDictionary> dictionary, uint32_t key,
......
......@@ -438,38 +438,6 @@ InternalIndex OrderedNameDictionary::FindEntry(LocalIsolate* isolate,
return InternalIndex::NotFound();
}
// TODO(emrich): This is almost an identical copy of
// Dictionary<..>::SlowReverseLookup.
// Consolidate both versions elsewhere (e.g., hash-table-utils)?
Object OrderedNameDictionary::SlowReverseLookup(Isolate* isolate,
Object value) {
ReadOnlyRoots roots(isolate);
for (InternalIndex i : IterateEntries()) {
Object k;
if (!ToKey(roots, i, &k)) continue;
Object e = this->ValueAt(i);
if (e == value) return k;
}
return roots.undefined_value();
}
// TODO(emrich): This is almost an identical copy of
// HashTable<..>::NumberOfEnumerableProperties.
// Consolidate both versions elsewhere (e.g., hash-table-utils)?
int OrderedNameDictionary::NumberOfEnumerableProperties() {
ReadOnlyRoots roots = this->GetReadOnlyRoots();
int result = 0;
for (InternalIndex i : this->IterateEntries()) {
Object k;
if (!this->ToKey(roots, i, &k)) continue;
if (k.FilterKey(ENUMERABLE_STRINGS)) continue;
PropertyDetails details = this->DetailsAt(i);
PropertyAttributes attr = details.attributes();
if ((attr & ONLY_ENUMERABLE) == 0) result++;
}
return result;
}
template <typename LocalIsolate>
MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::Add(
LocalIsolate* isolate, Handle<OrderedNameDictionary> table,
......
......@@ -92,8 +92,6 @@ class OrderedHashTable : public FixedArray {
InternalIndex FindEntry(Isolate* isolate, Object key);
Object SlowReverseLookup(Isolate* isolate, Object value);
int NumberOfElements() const {
return Smi::ToInt(get(NumberOfElementsIndex()));
}
......@@ -784,10 +782,6 @@ class V8_EXPORT_PRIVATE OrderedNameDictionary
return FindEntry(isolate, *key);
}
int NumberOfEnumerableProperties();
Object SlowReverseLookup(Isolate* isolate, Object value);
static Handle<OrderedNameDictionary> DeleteEntry(
Isolate* isolate, Handle<OrderedNameDictionary> table,
InternalIndex entry);
......
......@@ -107,8 +107,13 @@ bool SwissNameDictionary::EqualsForTesting(SwissNameDictionary other) {
}
// static
Handle<SwissNameDictionary> SwissNameDictionary::CopyForTesting(
Handle<SwissNameDictionary> SwissNameDictionary::ShallowCopy(
Isolate* isolate, Handle<SwissNameDictionary> table) {
// TODO(v8:11388) Consider doing some cleanup during copying: For example, we
// could turn kDeleted into kEmpty in certain situations. But this would
// require tidying up the enumeration table in a similar fashion as would be
// required when trying to re-use deleted entries.
if (table->Capacity() == 0) {
return table;
}
......@@ -242,6 +247,37 @@ void SwissNameDictionary::Rehash(Isolate* isolate) {
}
}
// TODO(emrich,v8:11388): This is almost an identical copy of
// HashTable<..>::NumberOfEnumerableProperties. Consolidate both versions
// elsewhere (e.g., hash-table-utils)?
int SwissNameDictionary::NumberOfEnumerableProperties() {
ReadOnlyRoots roots = this->GetReadOnlyRoots();
int result = 0;
for (InternalIndex i : this->IterateEntries()) {
Object k;
if (!this->ToKey(roots, i, &k)) continue;
if (k.FilterKey(ENUMERABLE_STRINGS)) continue;
PropertyDetails details = this->DetailsAt(i);
PropertyAttributes attr = details.attributes();
if ((attr & ONLY_ENUMERABLE) == 0) result++;
}
return result;
}
// TODO(emrich, v8:11388): This is almost an identical copy of
// Dictionary<..>::SlowReverseLookup. Consolidate both versions elsewhere (e.g.,
// hash-table-utils)?
Object SwissNameDictionary::SlowReverseLookup(Isolate* isolate, Object value) {
ReadOnlyRoots roots(isolate);
for (InternalIndex i : IterateEntries()) {
Object k;
if (!ToKey(roots, i, &k)) continue;
Object e = this->ValueAt(i);
if (e == value) return k;
}
return roots.undefined_value();
}
// The largest value we ever have to store in the enumeration table is
// Capacity() - 1. The largest value we ever have to store for the present or
// deleted element count is MaxUsableCapacity(Capacity()). All data in the
......
......@@ -112,18 +112,17 @@ class V8_EXPORT_PRIVATE SwissNameDictionary : public HeapObject {
inline int Capacity();
inline int UsedCapacity();
int NumberOfEnumerableProperties();
static Handle<SwissNameDictionary> ShallowCopy(
Isolate* isolate, Handle<SwissNameDictionary> table);
// Strict in the sense that it checks that all used/initialized memory in
// |this| and |other| is the same. The only exceptions are the meta table
// pointer (which must differ between the two tables) and PropertyDetails of
// deleted entries (which reside in initialized memory, but are not compared).
bool EqualsForTesting(SwissNameDictionary other);
// Copy operation for testing purposes. Guarantees that DebugEquals holds for
// the old table and its copy. In particular, no kind of tidying up is
// performed.
static Handle<SwissNameDictionary> CopyForTesting(
Isolate* isolate, Handle<SwissNameDictionary> table);
template <typename LocalIsolate>
void Initialize(LocalIsolate* isolate, ByteArray meta_table, int capacity);
......@@ -136,6 +135,8 @@ class V8_EXPORT_PRIVATE SwissNameDictionary : public HeapObject {
inline void SetHash(int hash);
inline int Hash();
Object SlowReverseLookup(Isolate* isolate, Object value);
class IndexIterator {
public:
inline IndexIterator(Handle<SwissNameDictionary> dict, int start);
......
......@@ -1371,7 +1371,7 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject js_obj,
SetDataOrAccessorPropertyReference(details.kind(), entry, name, value);
}
} else if (V8_DICT_MODE_PROTOTYPES_BOOL) {
OrderedNameDictionary dictionary = js_obj.property_dictionary_ordered();
SwissNameDictionary dictionary = js_obj.property_dictionary_swiss();
ReadOnlyRoots roots(isolate);
for (InternalIndex i : dictionary.IterateEntries()) {
Object k = dictionary.KeyAt(i);
......
......@@ -117,7 +117,7 @@ namespace {
template <typename Dictionary>
Handle<Name> KeyToName(Isolate* isolate, Handle<Object> key) {
STATIC_ASSERT((std::is_same<Dictionary, OrderedNameDictionary>::value ||
STATIC_ASSERT((std::is_same<Dictionary, SwissNameDictionary>::value ||
std::is_same<Dictionary, NameDictionary>::value));
DCHECK(key->IsName());
return Handle<Name>::cast(key);
......@@ -190,8 +190,7 @@ Handle<Dictionary> ShallowCopyDictionaryTemplate(
Isolate* isolate, Handle<Dictionary> dictionary_template) {
Handle<Map> dictionary_map(dictionary_template->map(), isolate);
Handle<Dictionary> dictionary =
Handle<Dictionary>::cast(isolate->factory()->CopyFixedArrayWithMap(
dictionary_template, dictionary_map));
Dictionary::ShallowCopy(isolate, dictionary_template);
// Clone all AccessorPairs in the dictionary.
for (InternalIndex i : dictionary->IterateEntries()) {
Object value = dictionary->ValueAt(i);
......@@ -530,8 +529,8 @@ bool InitClassPrototype(Isolate* isolate,
const bool install_name_accessor = false;
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
Handle<OrderedNameDictionary> properties_dictionary_template =
Handle<OrderedNameDictionary>::cast(properties_template);
Handle<SwissNameDictionary> properties_dictionary_template =
Handle<SwissNameDictionary>::cast(properties_template);
return AddDescriptorsByTemplate(
isolate, map, properties_dictionary_template,
elements_dictionary_template, computed_properties, prototype,
......@@ -591,8 +590,8 @@ bool InitClassConstructor(
const bool install_name_accessor = true;
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
Handle<OrderedNameDictionary> properties_dictionary_template =
Handle<OrderedNameDictionary>::cast(properties_template);
Handle<SwissNameDictionary> properties_dictionary_template =
Handle<SwissNameDictionary>::cast(properties_template);
return AddDescriptorsByTemplate(
isolate, map, properties_dictionary_template,
......
......@@ -134,8 +134,8 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
}
} else {
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
Handle<OrderedNameDictionary> dict(
copy->property_dictionary_ordered(isolate), isolate);
Handle<SwissNameDictionary> dict(
copy->property_dictionary_swiss(isolate), isolate);
for (InternalIndex i : dict->IterateEntries()) {
Object raw = dict->ValueAt(i);
if (!raw.IsJSObject(isolate)) continue;
......
......@@ -402,11 +402,10 @@ RUNTIME_FUNCTION(Runtime_AddDictionaryProperty) {
PropertyDetails property_details(
kData, NONE, PropertyDetails::kConstIfDictConstnessTracking);
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
Handle<OrderedNameDictionary> dictionary(
receiver->property_dictionary_ordered(), isolate);
dictionary = OrderedNameDictionary::Add(isolate, dictionary, name, value,
property_details)
.ToHandleChecked();
Handle<SwissNameDictionary> dictionary(
receiver->property_dictionary_swiss(), isolate);
dictionary = SwissNameDictionary::Add(isolate, dictionary, name, value,
property_details);
receiver->SetProperties(*dictionary);
} else {
Handle<NameDictionary> dictionary(receiver->property_dictionary(), isolate);
......@@ -682,8 +681,7 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
} else if (!holder->HasFastProperties()) {
// Attempt dictionary lookup.
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
OrderedNameDictionary dictionary =
holder->property_dictionary_ordered();
SwissNameDictionary dictionary = holder->property_dictionary_swiss();
InternalIndex entry = dictionary.FindEntry(isolate, *key);
if (entry.is_found() &&
(dictionary.DetailsAt(entry).kind() == kData)) {
......@@ -816,10 +814,10 @@ RUNTIME_FUNCTION(Runtime_ShrinkPropertyDictionary) {
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
Handle<OrderedNameDictionary> dictionary(
receiver->property_dictionary_ordered(), isolate);
Handle<OrderedNameDictionary> new_properties =
OrderedNameDictionary::Shrink(isolate, dictionary);
Handle<SwissNameDictionary> dictionary(
receiver->property_dictionary_swiss(), isolate);
Handle<SwissNameDictionary> new_properties =
SwissNameDictionary::Shrink(isolate, dictionary);
receiver->SetProperties(*new_properties);
} else {
Handle<NameDictionary> dictionary(receiver->property_dictionary(), isolate);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment