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:
ishell 2015-06-01 08:43:24 -07:00 committed by Commit bot
parent 673c0516ab
commit 6c6b425dea
4 changed files with 116 additions and 73 deletions

View File

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

View File

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

View File

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

View File

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