Introducing GlobalDictionary, a backing store for global objects.
This updates Dictionary classes hierarchy and introduces GlobalDictionary class but it is not used yet. Review URL: https://codereview.chromium.org/1163673003 Cr-Commit-Position: refs/heads/master@{#28732}
This commit is contained in:
parent
673c0516ab
commit
6c6b425dea
@ -377,6 +377,7 @@ class MemoryChunk;
|
||||
class SeededNumberDictionary;
|
||||
class UnseededNumberDictionary;
|
||||
class NameDictionary;
|
||||
class GlobalDictionary;
|
||||
template <typename T> class MaybeHandle;
|
||||
template <typename T> class Handle;
|
||||
class Heap;
|
||||
|
@ -905,6 +905,9 @@ bool Object::IsNameDictionary() const {
|
||||
}
|
||||
|
||||
|
||||
bool Object::IsGlobalDictionary() const { return IsDictionary(); }
|
||||
|
||||
|
||||
bool Object::IsSeededNumberDictionary() const {
|
||||
return IsDictionary();
|
||||
}
|
||||
@ -3384,6 +3387,7 @@ CAST_ACCESSOR(FixedArrayBase)
|
||||
CAST_ACCESSOR(FixedDoubleArray)
|
||||
CAST_ACCESSOR(FixedTypedArrayBase)
|
||||
CAST_ACCESSOR(Foreign)
|
||||
CAST_ACCESSOR(GlobalDictionary)
|
||||
CAST_ACCESSOR(GlobalObject)
|
||||
CAST_ACCESSOR(HandlerTable)
|
||||
CAST_ACCESSOR(HeapObject)
|
||||
@ -6733,10 +6737,20 @@ bool JSObject::HasIndexedInterceptor() {
|
||||
|
||||
NameDictionary* JSObject::property_dictionary() {
|
||||
DCHECK(!HasFastProperties());
|
||||
// TODO(ishell): Uncomment, once all property_dictionary() usages for global
|
||||
// objects are replaced with global_dictionary().
|
||||
// DCHECK(!IsGlobalObject());
|
||||
return NameDictionary::cast(properties());
|
||||
}
|
||||
|
||||
|
||||
GlobalDictionary* JSObject::global_dictionary() {
|
||||
DCHECK(!HasFastProperties());
|
||||
DCHECK(IsGlobalObject());
|
||||
return GlobalDictionary::cast(properties());
|
||||
}
|
||||
|
||||
|
||||
SeededNumberDictionary* JSObject::element_dictionary() {
|
||||
DCHECK(HasDictionaryElements());
|
||||
return SeededNumberDictionary::cast(elements());
|
||||
|
102
src/objects.cc
102
src/objects.cc
@ -14021,10 +14021,10 @@ bool JSObject::ShouldConvertToFastDoubleElements(
|
||||
#ifdef OBJECT_PRINT
|
||||
template <typename Derived, typename Shape, typename Key>
|
||||
void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) { // NOLINT
|
||||
int capacity = DerivedHashTable::Capacity();
|
||||
int capacity = this->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = DerivedHashTable::KeyAt(i);
|
||||
if (DerivedHashTable::IsKey(k)) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k)) {
|
||||
os << " ";
|
||||
if (k->IsString()) {
|
||||
String::cast(k)->StringPrint(os);
|
||||
@ -14041,12 +14041,12 @@ void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) { // NOLINT
|
||||
template<typename Derived, typename Shape, typename Key>
|
||||
void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
|
||||
int pos = 0;
|
||||
int capacity = DerivedHashTable::Capacity();
|
||||
int capacity = this->Capacity();
|
||||
DisallowHeapAllocation no_gc;
|
||||
WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = Dictionary::KeyAt(i);
|
||||
if (Dictionary::IsKey(k)) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k)) {
|
||||
elements->set(pos++, ValueAt(i), mode);
|
||||
}
|
||||
}
|
||||
@ -14780,9 +14780,10 @@ Handle<Derived> HashTable<Derived, Shape, Key>::New(
|
||||
|
||||
|
||||
// Find entry for key otherwise return kNotFound.
|
||||
int NameDictionary::FindEntry(Handle<Name> key) {
|
||||
template <typename Derived, typename Shape>
|
||||
int NameDictionaryBase<Derived, Shape>::FindEntry(Handle<Name> key) {
|
||||
if (!key->IsUniqueName()) {
|
||||
return DerivedHashTable::FindEntry(key);
|
||||
return DerivedDictionary::FindEntry(key);
|
||||
}
|
||||
|
||||
// Optimized for unique names. Knowledge of the key type allows:
|
||||
@ -14795,13 +14796,13 @@ int NameDictionary::FindEntry(Handle<Name> key) {
|
||||
// boost a certain style of code).
|
||||
|
||||
// EnsureCapacity will guarantee the hash table is never full.
|
||||
uint32_t capacity = Capacity();
|
||||
uint32_t entry = FirstProbe(key->Hash(), capacity);
|
||||
uint32_t capacity = this->Capacity();
|
||||
uint32_t entry = Derived::FirstProbe(key->Hash(), capacity);
|
||||
uint32_t count = 1;
|
||||
|
||||
while (true) {
|
||||
int index = EntryToIndex(entry);
|
||||
Object* element = get(index);
|
||||
int index = Derived::EntryToIndex(entry);
|
||||
Object* element = this->get(index);
|
||||
if (element->IsUndefined()) break; // Empty entry.
|
||||
if (*key == element) return entry;
|
||||
if (!element->IsUniqueName() &&
|
||||
@ -14809,13 +14810,13 @@ int NameDictionary::FindEntry(Handle<Name> key) {
|
||||
Name::cast(element)->Equals(*key)) {
|
||||
// Replace a key that is a non-internalized string by the equivalent
|
||||
// internalized string for faster further lookups.
|
||||
set(index, *key);
|
||||
this->set(index, *key);
|
||||
return entry;
|
||||
}
|
||||
DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key));
|
||||
entry = NextProbe(entry, count++, capacity);
|
||||
entry = Derived::NextProbe(entry, count++, capacity);
|
||||
}
|
||||
return kNotFound;
|
||||
return Derived::kNotFound;
|
||||
}
|
||||
|
||||
|
||||
@ -14836,12 +14837,12 @@ void HashTable<Derived, Shape, Key>::Rehash(
|
||||
}
|
||||
|
||||
// Rehash the elements.
|
||||
int capacity = Capacity();
|
||||
int capacity = this->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
uint32_t from_index = EntryToIndex(i);
|
||||
Object* k = get(from_index);
|
||||
Object* k = this->get(from_index);
|
||||
if (IsKey(k)) {
|
||||
uint32_t hash = HashTable::HashForObject(key, k);
|
||||
uint32_t hash = this->HashForObject(key, k);
|
||||
uint32_t insertion_index =
|
||||
EntryToIndex(new_table->FindInsertionEntry(hash));
|
||||
for (int j = 0; j < Shape::kEntrySize; j++) {
|
||||
@ -14860,8 +14861,8 @@ uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
|
||||
Object* k,
|
||||
int probe,
|
||||
uint32_t expected) {
|
||||
uint32_t hash = HashTable::HashForObject(key, k);
|
||||
uint32_t capacity = Capacity();
|
||||
uint32_t hash = this->HashForObject(key, k);
|
||||
uint32_t capacity = this->Capacity();
|
||||
uint32_t entry = FirstProbe(hash, capacity);
|
||||
for (int i = 1; i < probe; i++) {
|
||||
if (entry == expected) return expected;
|
||||
@ -15125,6 +15126,9 @@ Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
|
||||
template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape,
|
||||
uint32_t>::FindEntry(uint32_t);
|
||||
|
||||
template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry(
|
||||
Handle<Name>);
|
||||
|
||||
|
||||
Handle<Object> JSObject::PrepareSlowElementsForSort(
|
||||
Handle<JSObject> object, uint32_t limit) {
|
||||
@ -16215,11 +16219,11 @@ template <typename Derived, typename Shape, typename Key>
|
||||
template <DictionaryEntryType type>
|
||||
int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
|
||||
PropertyAttributes filter) {
|
||||
int capacity = DerivedHashTable::Capacity();
|
||||
int capacity = this->Capacity();
|
||||
int result = 0;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = DerivedHashTable::KeyAt(i);
|
||||
if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k) && !FilterKey(k, filter)) {
|
||||
if (IsDeleted<type>(this, i)) continue;
|
||||
PropertyDetails details = DetailsAt(i);
|
||||
PropertyAttributes attr = details.attributes();
|
||||
@ -16233,10 +16237,10 @@ int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
|
||||
template <typename Derived, typename Shape, typename Key>
|
||||
template <DictionaryEntryType type>
|
||||
bool Dictionary<Derived, Shape, Key>::HasComplexElements() {
|
||||
int capacity = DerivedHashTable::Capacity();
|
||||
int capacity = this->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = DerivedHashTable::KeyAt(i);
|
||||
if (DerivedHashTable::IsKey(k) && !FilterKey(k, NONE)) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k) && !FilterKey(k, NONE)) {
|
||||
if (IsDeleted<type>(this, i)) continue;
|
||||
PropertyDetails details = DetailsAt(i);
|
||||
if (details.type() == ACCESSOR_CONSTANT) return true;
|
||||
@ -16254,16 +16258,16 @@ void Dictionary<Derived, Shape, Key>::CopyKeysTo(
|
||||
FixedArray* storage, PropertyAttributes filter,
|
||||
typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
|
||||
DCHECK(storage->length() >= NumberOfElementsFilterAttributes<type>(filter));
|
||||
int capacity = DerivedHashTable::Capacity();
|
||||
int capacity = this->Capacity();
|
||||
int index = 0;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = DerivedHashTable::KeyAt(i);
|
||||
if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
|
||||
if (IsDeleted<type>(this, i)) continue;
|
||||
PropertyDetails details = DetailsAt(i);
|
||||
PropertyAttributes attr = details.attributes();
|
||||
if ((attr & filter) == 0) storage->set(index++, k);
|
||||
}
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k) && !FilterKey(k, filter)) {
|
||||
if (IsDeleted<type>(this, i)) continue;
|
||||
PropertyDetails details = DetailsAt(i);
|
||||
PropertyAttributes attr = details.attributes();
|
||||
if ((attr & filter) == 0) storage->set(index++, k);
|
||||
}
|
||||
}
|
||||
if (sort_mode == Dictionary::SORTED) {
|
||||
storage->SortPairs(storage, index);
|
||||
@ -16272,25 +16276,27 @@ void Dictionary<Derived, Shape, Key>::CopyKeysTo(
|
||||
}
|
||||
|
||||
|
||||
template <typename Dictionary>
|
||||
struct EnumIndexComparator {
|
||||
explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { }
|
||||
explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {}
|
||||
bool operator() (Smi* a, Smi* b) {
|
||||
PropertyDetails da(dict->DetailsAt(a->value()));
|
||||
PropertyDetails db(dict->DetailsAt(b->value()));
|
||||
return da.dictionary_index() < db.dictionary_index();
|
||||
}
|
||||
NameDictionary* dict;
|
||||
Dictionary* dict;
|
||||
};
|
||||
|
||||
|
||||
template <typename Derived, typename Shape, typename Key>
|
||||
template <DictionaryEntryType type>
|
||||
void NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
|
||||
void Dictionary<Derived, Shape, Key>::CopyEnumKeysTo(FixedArray* storage) {
|
||||
int length = storage->length();
|
||||
int capacity = Capacity();
|
||||
int capacity = this->Capacity();
|
||||
int properties = 0;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = KeyAt(i);
|
||||
if (IsKey(k) && !k->IsSymbol()) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k) && !k->IsSymbol()) {
|
||||
PropertyDetails details = DetailsAt(i);
|
||||
if (details.IsDontEnum() || IsDeleted<type>(this, i)) continue;
|
||||
storage->set(properties, Smi::FromInt(i));
|
||||
@ -16299,12 +16305,12 @@ void NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
|
||||
}
|
||||
}
|
||||
CHECK_EQ(length, properties);
|
||||
EnumIndexComparator cmp(this);
|
||||
EnumIndexComparator<Derived> cmp(static_cast<Derived*>(this));
|
||||
Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
|
||||
std::sort(start, start + length, cmp);
|
||||
for (int i = 0; i < length; i++) {
|
||||
int index = Smi::cast(storage->get(i))->value();
|
||||
storage->set(i, KeyAt(index));
|
||||
storage->set(i, this->KeyAt(index));
|
||||
}
|
||||
}
|
||||
|
||||
@ -16315,10 +16321,10 @@ void Dictionary<Derived, Shape, Key>::CopyKeysTo(
|
||||
FixedArray* storage, int index, PropertyAttributes filter,
|
||||
typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
|
||||
DCHECK(storage->length() >= NumberOfElementsFilterAttributes<type>(filter));
|
||||
int capacity = DerivedHashTable::Capacity();
|
||||
int capacity = this->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = DerivedHashTable::KeyAt(i);
|
||||
if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k) && !FilterKey(k, filter)) {
|
||||
if (IsDeleted<type>(this, i)) continue;
|
||||
PropertyDetails details = DetailsAt(i);
|
||||
PropertyAttributes attr = details.attributes();
|
||||
@ -16335,10 +16341,10 @@ void Dictionary<Derived, Shape, Key>::CopyKeysTo(
|
||||
// Backwards lookup (slow).
|
||||
template<typename Derived, typename Shape, typename Key>
|
||||
Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
|
||||
int capacity = DerivedHashTable::Capacity();
|
||||
int capacity = this->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = DerivedHashTable::KeyAt(i);
|
||||
if (Dictionary::IsKey(k)) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k)) {
|
||||
Object* e = ValueAt(i);
|
||||
// TODO(dcarney): this should be templatized.
|
||||
if (e->IsPropertyCell()) {
|
||||
|
@ -1059,6 +1059,7 @@ class Object {
|
||||
INLINE(bool IsSpecFunction()) const;
|
||||
INLINE(bool IsTemplateInfo()) const;
|
||||
INLINE(bool IsNameDictionary() const);
|
||||
INLINE(bool IsGlobalDictionary() const);
|
||||
INLINE(bool IsSeededNumberDictionary() const);
|
||||
INLINE(bool IsUnseededNumberDictionary() const);
|
||||
INLINE(bool IsOrderedHashSet() const);
|
||||
@ -1728,7 +1729,10 @@ class JSObject: public JSReceiver {
|
||||
DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
|
||||
inline void initialize_properties();
|
||||
inline bool HasFastProperties();
|
||||
inline NameDictionary* property_dictionary(); // Gets slow properties.
|
||||
// Gets slow properties for non-global objects.
|
||||
inline NameDictionary* property_dictionary();
|
||||
// Gets global object properties.
|
||||
inline GlobalDictionary* global_dictionary();
|
||||
|
||||
// [elements]: The elements (properties with names that are integers).
|
||||
//
|
||||
@ -3599,30 +3603,29 @@ enum class DictionaryEntryType { kObjects, kCells };
|
||||
|
||||
template <typename Derived, typename Shape, typename Key>
|
||||
class Dictionary: public HashTable<Derived, Shape, Key> {
|
||||
protected:
|
||||
typedef HashTable<Derived, Shape, Key> DerivedHashTable;
|
||||
|
||||
public:
|
||||
// Returns the value at entry.
|
||||
Object* ValueAt(int entry) {
|
||||
return this->get(DerivedHashTable::EntryToIndex(entry) + 1);
|
||||
return this->get(Derived::EntryToIndex(entry) + 1);
|
||||
}
|
||||
|
||||
// Set the value for entry.
|
||||
void ValueAtPut(int entry, Object* value) {
|
||||
this->set(DerivedHashTable::EntryToIndex(entry) + 1, value);
|
||||
this->set(Derived::EntryToIndex(entry) + 1, value);
|
||||
}
|
||||
|
||||
// Returns the property details for the property at entry.
|
||||
PropertyDetails DetailsAt(int entry) {
|
||||
DCHECK(entry >= 0); // Not found is -1, which is not caught by get().
|
||||
return PropertyDetails(
|
||||
Smi::cast(this->get(DerivedHashTable::EntryToIndex(entry) + 2)));
|
||||
Smi::cast(this->get(Derived::EntryToIndex(entry) + 2)));
|
||||
}
|
||||
|
||||
// Set the details for entry.
|
||||
void DetailsAtPut(int entry, PropertyDetails value) {
|
||||
this->set(DerivedHashTable::EntryToIndex(entry) + 2, value.AsSmi());
|
||||
this->set(Derived::EntryToIndex(entry) + 2, value.AsSmi());
|
||||
}
|
||||
|
||||
// Delete a property from the dictionary.
|
||||
@ -3712,6 +3715,17 @@ class Dictionary: public HashTable<Derived, Shape, Key> {
|
||||
}
|
||||
}
|
||||
|
||||
// Copies enumerable keys to preallocated fixed array.
|
||||
template <DictionaryEntryType type>
|
||||
void CopyEnumKeysTo(FixedArray* storage);
|
||||
void CopyEnumKeysTo(Object* holder, FixedArray* storage) {
|
||||
if (holder->IsGlobalObject()) {
|
||||
return CopyEnumKeysTo<DictionaryEntryType::kCells>(storage);
|
||||
} else {
|
||||
return CopyEnumKeysTo<DictionaryEntryType::kObjects>(storage);
|
||||
}
|
||||
}
|
||||
|
||||
// Accessors for next enumeration index.
|
||||
void SetNextEnumerationIndex(int index) {
|
||||
DCHECK(index != 0);
|
||||
@ -3781,6 +3795,17 @@ class Dictionary: public HashTable<Derived, Shape, Key> {
|
||||
};
|
||||
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
class NameDictionaryBase : public Dictionary<Derived, Shape, Handle<Name> > {
|
||||
typedef Dictionary<Derived, Shape, Handle<Name> > DerivedDictionary;
|
||||
|
||||
public:
|
||||
// Find entry for key, otherwise return kNotFound. Optimized version of
|
||||
// HashTable::FindEntry.
|
||||
int FindEntry(Handle<Name> key);
|
||||
};
|
||||
|
||||
|
||||
class NameDictionaryShape : public BaseShape<Handle<Name> > {
|
||||
public:
|
||||
static inline bool IsMatch(Handle<Name> key, Object* other);
|
||||
@ -3793,32 +3818,29 @@ class NameDictionaryShape : public BaseShape<Handle<Name> > {
|
||||
};
|
||||
|
||||
|
||||
class NameDictionary: public Dictionary<NameDictionary,
|
||||
NameDictionaryShape,
|
||||
Handle<Name> > {
|
||||
typedef Dictionary<
|
||||
NameDictionary, NameDictionaryShape, Handle<Name> > DerivedDictionary;
|
||||
class NameDictionary
|
||||
: public NameDictionaryBase<NameDictionary, NameDictionaryShape> {
|
||||
typedef NameDictionaryBase<NameDictionary, NameDictionaryShape>
|
||||
DerivedDictionary;
|
||||
|
||||
public:
|
||||
DECLARE_CAST(NameDictionary)
|
||||
|
||||
// Copies enumerable keys to preallocated fixed array.
|
||||
template <DictionaryEntryType type>
|
||||
void CopyEnumKeysTo(FixedArray* storage);
|
||||
void CopyEnumKeysTo(Object* holder, FixedArray* storage) {
|
||||
if (holder->IsGlobalObject()) {
|
||||
return CopyEnumKeysTo<DictionaryEntryType::kCells>(storage);
|
||||
} else {
|
||||
return CopyEnumKeysTo<DictionaryEntryType::kObjects>(storage);
|
||||
}
|
||||
}
|
||||
|
||||
inline static Handle<FixedArray> DoGenerateNewEnumerationIndices(
|
||||
Handle<NameDictionary> dictionary);
|
||||
};
|
||||
|
||||
// Find entry for key, otherwise return kNotFound. Optimized version of
|
||||
// HashTable::FindEntry.
|
||||
int FindEntry(Handle<Name> key);
|
||||
|
||||
class GlobalDictionaryShape : public NameDictionaryShape {
|
||||
public:
|
||||
static const int kEntrySize = 3; // Overrides NameDictionaryShape::kEntrySize
|
||||
};
|
||||
|
||||
|
||||
class GlobalDictionary
|
||||
: public NameDictionaryBase<GlobalDictionary, GlobalDictionaryShape> {
|
||||
public:
|
||||
DECLARE_CAST(GlobalDictionary)
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user