Removed virtual behavior from Dictionaries.

Review URL: http://codereview.chromium.org/150168

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2324 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
bak@chromium.org 2009-07-01 15:38:25 +00:00
parent 9518261f2b
commit 5cbb209425
14 changed files with 604 additions and 510 deletions

View File

@ -1434,8 +1434,8 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
}
}
} else {
Handle<Dictionary> properties =
Handle<Dictionary>(from->property_dictionary());
Handle<StringDictionary> properties =
Handle<StringDictionary>(from->property_dictionary());
int capacity = properties->Capacity();
for (int i = 0; i < capacity; i++) {
Object* raw_key(properties->KeyAt(i));

View File

@ -37,8 +37,8 @@ namespace internal {
Handle<Code> CodeStub::GetCode() {
uint32_t key = GetKey();
int index = Heap::code_stubs()->FindNumberEntry(key);
if (index == -1) {
int index = Heap::code_stubs()->FindEntry(key);
if (index == NumberDictionary::kNotFound) {
HandleScope scope;
// Update the static counter each time a new code stub is generated.
@ -80,14 +80,15 @@ Handle<Code> CodeStub::GetCode() {
#endif
// Update the dictionary and the root in Heap.
Handle<Dictionary> dict =
Factory::DictionaryAtNumberPut(Handle<Dictionary>(Heap::code_stubs()),
key,
code);
Handle<NumberDictionary> dict =
Factory::DictionaryAtNumberPut(
Handle<NumberDictionary>(Heap::code_stubs()),
key,
code);
Heap::set_code_stubs(*dict);
index = Heap::code_stubs()->FindNumberEntry(key);
index = Heap::code_stubs()->FindEntry(key);
}
ASSERT(index != -1);
ASSERT(index != NumberDictionary::kNotFound);
return Handle<Code>(Code::cast(Heap::code_stubs()->ValueAt(index)));
}

View File

@ -49,9 +49,17 @@ Handle<FixedArray> Factory::NewFixedArrayWithHoles(int size) {
}
Handle<Dictionary> Factory::NewDictionary(int at_least_space_for) {
Handle<StringDictionary> Factory::NewStringDictionary(int at_least_space_for) {
ASSERT(0 <= at_least_space_for);
CALL_HEAP_FUNCTION(Dictionary::Allocate(at_least_space_for), Dictionary);
CALL_HEAP_FUNCTION(StringDictionary::Allocate(at_least_space_for),
StringDictionary);
}
Handle<NumberDictionary> Factory::NewNumberDictionary(int at_least_space_for) {
ASSERT(0 <= at_least_space_for);
CALL_HEAP_FUNCTION(NumberDictionary::Allocate(at_least_space_for),
NumberDictionary);
}
@ -655,10 +663,11 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
}
Handle<Dictionary> Factory::DictionaryAtNumberPut(Handle<Dictionary> dictionary,
uint32_t key,
Handle<Object> value) {
CALL_HEAP_FUNCTION(dictionary->AtNumberPut(key, *value), Dictionary);
Handle<NumberDictionary> Factory::DictionaryAtNumberPut(
Handle<NumberDictionary> dictionary,
uint32_t key,
Handle<Object> value) {
CALL_HEAP_FUNCTION(dictionary->AtNumberPut(key, *value), NumberDictionary);
}

View File

@ -47,7 +47,9 @@ class Factory : public AllStatic {
// Allocate a new fixed array with non-existing entries (the hole).
static Handle<FixedArray> NewFixedArrayWithHoles(int size);
static Handle<Dictionary> NewDictionary(int at_least_space_for);
static Handle<NumberDictionary> NewNumberDictionary(int at_least_space_for);
static Handle<StringDictionary> NewStringDictionary(int at_least_space_for);
static Handle<DescriptorArray> NewDescriptorArray(int number_of_descriptors);
@ -313,9 +315,10 @@ class Factory : public AllStatic {
static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
static Handle<Dictionary> DictionaryAtNumberPut(Handle<Dictionary>,
uint32_t key,
Handle<Object> value);
static Handle<NumberDictionary> DictionaryAtNumberPut(
Handle<NumberDictionary>,
uint32_t key,
Handle<Object> value);
#ifdef ENABLE_DEBUGGER_SUPPORT
static Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared);

View File

@ -198,7 +198,8 @@ class FixedArray;
class FunctionEntry;
class FunctionLiteral;
class FunctionTemplateInfo;
class Dictionary;
class NumberDictionary;
class StringDictionary;
class FreeStoreAllocationPolicy;
template <typename T> class Handle;
class Heap;

View File

@ -1392,14 +1392,14 @@ bool Heap::CreateInitialObjects() {
prototype_accessors_ = Proxy::cast(obj);
// Allocate the code_stubs dictionary.
obj = Dictionary::Allocate(4);
obj = NumberDictionary::Allocate(4);
if (obj->IsFailure()) return false;
code_stubs_ = Dictionary::cast(obj);
code_stubs_ = NumberDictionary::cast(obj);
// Allocate the non_monomorphic_cache used in stub-cache.cc
obj = Dictionary::Allocate(4);
obj = NumberDictionary::Allocate(4);
if (obj->IsFailure()) return false;
non_monomorphic_cache_ = Dictionary::cast(obj);
non_monomorphic_cache_ = NumberDictionary::cast(obj);
CreateFixedStubs();
@ -2563,7 +2563,7 @@ Object* Heap::AllocateHashTable(int length) {
Object* result = Heap::AllocateFixedArray(length);
if (result->IsFailure()) return result;
reinterpret_cast<Array*>(result)->set_map(hash_table_map());
ASSERT(result->IsDictionary());
ASSERT(result->IsHashTable());
return result;
}

View File

@ -118,8 +118,8 @@ namespace internal {
V(Map, neander_map) \
V(JSObject, message_listeners) \
V(Proxy, prototype_accessors) \
V(Dictionary, code_stubs) \
V(Dictionary, non_monomorphic_cache) \
V(NumberDictionary, code_stubs) \
V(NumberDictionary, non_monomorphic_cache) \
V(Code, js_entry_code) \
V(Code, js_construct_entry_code) \
V(Code, c_entry_code) \
@ -692,10 +692,10 @@ class Heap : public AllStatic {
static inline AllocationSpace TargetSpaceId(InstanceType type);
// Sets the stub_cache_ (only used when expanding the dictionary).
static void set_code_stubs(Dictionary* value) { code_stubs_ = value; }
static void set_code_stubs(NumberDictionary* value) { code_stubs_ = value; }
// Sets the non_monomorphic_cache_ (only used when expanding the dictionary).
static void set_non_monomorphic_cache(Dictionary* value) {
static void set_non_monomorphic_cache(NumberDictionary* value) {
non_monomorphic_cache_ = value;
}

View File

@ -83,7 +83,7 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
// Compute the capacity mask.
const int kCapacityOffset =
Array::kHeaderSize + Dictionary::kCapacityIndex * kPointerSize;
Array::kHeaderSize + StringDictionary::kCapacityIndex * kPointerSize;
__ mov(r2, FieldOperand(r0, kCapacityOffset));
__ shr(r2, kSmiTagSize); // convert smi to int
__ dec(r2);
@ -93,18 +93,18 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
// cover ~93% of loads from dictionaries.
static const int kProbes = 4;
const int kElementsStartOffset =
Array::kHeaderSize + Dictionary::kElementsStartIndex * kPointerSize;
Array::kHeaderSize + StringDictionary::kElementsStartIndex * kPointerSize;
for (int i = 0; i < kProbes; i++) {
// Compute the masked index: (hash + i + i * i) & mask.
__ mov(r1, FieldOperand(name, String::kLengthOffset));
__ shr(r1, String::kHashShift);
if (i > 0) {
__ add(Operand(r1), Immediate(Dictionary::GetProbeOffset(i)));
__ add(Operand(r1), Immediate(StringDictionary::GetProbeOffset(i)));
}
__ and_(r1, Operand(r2));
// Scale the index by multiplying by the element size.
ASSERT(Dictionary::kElementSize == 3);
// Scale the index by multiplying by the entry size.
ASSERT(StringDictionary::kEntrySize == 3);
__ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3
// Check if the key is identical to the name.

View File

@ -744,12 +744,12 @@ void Proxy::ProxyVerify() {
ASSERT(IsProxy());
}
void Dictionary::Print() {
int capacity = Capacity();
template<typename Shape, typename Key>
void Dictionary<Shape, Key>::Print() {
int capacity = HashTable<Shape, Key>::Capacity();
for (int i = 0; i < capacity; i++) {
Object* k = KeyAt(i);
if (IsKey(k)) {
Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) {
PrintF(" ");
if (k->IsString()) {
String::cast(k)->StringPrint();
@ -1017,7 +1017,7 @@ void JSObject::IncrementSpillStatistics(SpillInformation* info) {
info->number_of_fast_used_fields_ += map()->NextFreePropertyIndex();
info->number_of_fast_unused_fields_ += map()->unused_property_fields();
} else {
Dictionary* dict = property_dictionary();
StringDictionary* dict = property_dictionary();
info->number_of_slow_used_properties_ += dict->NumberOfElements();
info->number_of_slow_unused_properties_ +=
dict->Capacity() - dict->NumberOfElements();
@ -1034,7 +1034,7 @@ void JSObject::IncrementSpillStatistics(SpillInformation* info) {
info->number_of_fast_used_elements_ += len - holes;
info->number_of_fast_unused_elements_ += holes;
} else {
Dictionary* dict = element_dictionary();
NumberDictionary* dict = element_dictionary();
info->number_of_slow_used_elements_ += dict->NumberOfElements();
info->number_of_slow_unused_elements_ +=
dict->Capacity() - dict->NumberOfElements();

View File

@ -1370,15 +1370,14 @@ void DescriptorArray::Swap(int first, int second) {
}
bool Dictionary::requires_slow_elements() {
bool NumberDictionary::requires_slow_elements() {
Object* max_index_object = get(kMaxNumberKeyIndex);
if (!max_index_object->IsSmi()) return false;
return 0 !=
(Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
}
uint32_t Dictionary::max_number_key() {
uint32_t NumberDictionary::max_number_key() {
ASSERT(!requires_slow_elements());
Object* max_index_object = get(kMaxNumberKeyIndex);
if (!max_index_object->IsSmi()) return 0;
@ -1386,8 +1385,7 @@ uint32_t Dictionary::max_number_key() {
return value >> kRequiresSlowElementsTagSize;
}
void Dictionary::set_requires_slow_elements() {
void NumberDictionary::set_requires_slow_elements() {
set(kMaxNumberKeyIndex,
Smi::FromInt(kRequiresSlowElementsMask),
SKIP_WRITE_BARRIER);
@ -1400,7 +1398,6 @@ void Dictionary::set_requires_slow_elements() {
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(DescriptorArray)
CAST_ACCESSOR(Dictionary)
CAST_ACCESSOR(SymbolTable)
CAST_ACCESSOR(CompilationCacheTable)
CAST_ACCESSOR(MapCache)
@ -1439,9 +1436,9 @@ CAST_ACCESSOR(Struct)
STRUCT_LIST(MAKE_STRUCT_CAST)
#undef MAKE_STRUCT_CAST
template <int prefix_size, int elem_size>
HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
Object* obj) {
template <typename Shape, typename Key>
HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
ASSERT(obj->IsHashTable());
return reinterpret_cast<HashTable*>(obj);
}
@ -2468,15 +2465,15 @@ bool JSObject::HasIndexedInterceptor() {
}
Dictionary* JSObject::property_dictionary() {
StringDictionary* JSObject::property_dictionary() {
ASSERT(!HasFastProperties());
return Dictionary::cast(properties());
return StringDictionary::cast(properties());
}
Dictionary* JSObject::element_dictionary() {
NumberDictionary* JSObject::element_dictionary() {
ASSERT(!HasFastElements());
return Dictionary::cast(elements());
return NumberDictionary::cast(elements());
}
@ -2640,16 +2637,17 @@ void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
}
void Dictionary::SetEntry(int entry,
Object* key,
Object* value,
PropertyDetails details) {
template<typename Shape, typename Key>
void Dictionary<Shape, Key>::SetEntry(int entry,
Object* key,
Object* value,
PropertyDetails details) {
ASSERT(!key->IsString() || details.index() > 0);
int index = EntryToIndex(entry);
WriteBarrierMode mode = GetWriteBarrierMode();
set(index, key, mode);
set(index+1, value, mode);
fast_set(this, index+2, details.AsSmi());
int index = HashTable<Shape, Key>::EntryToIndex(entry);
WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
FixedArray::set(index, key, mode);
FixedArray::set(index+1, value, mode);
FixedArray::fast_set(this, index+2, details.AsSmi());
}

File diff suppressed because it is too large Load Diff

View File

@ -1207,7 +1207,7 @@ class JSObject: public HeapObject {
DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
inline void initialize_properties();
inline bool HasFastProperties();
inline Dictionary* property_dictionary(); // Gets slow properties.
inline StringDictionary* property_dictionary(); // Gets slow properties.
// [elements]: The elements (properties with names that are integers).
// elements is a FixedArray in the fast case, and a Dictionary in the slow
@ -1215,7 +1215,7 @@ class JSObject: public HeapObject {
DECL_ACCESSORS(elements, FixedArray) // Get and set fast elements.
inline void initialize_elements();
inline bool HasFastElements();
inline Dictionary* element_dictionary(); // Gets slow elements.
inline NumberDictionary* element_dictionary(); // Gets slow elements.
// Collects elements starting at index 0.
// Undefined values are placed after non-undefined values.
@ -1875,32 +1875,29 @@ class DescriptorArray: public FixedArray {
// - Elements with key == undefined have not been used yet.
// - Elements with key == null have been deleted.
//
// The hash table class is parameterized with a prefix size and with
// the size, including the key size, of the elements held in the hash
// The hash table class is parameterized with a Shape and a Key.
// Shape must be a class with the following interface:
// class ExampleShape {
// public:
// // Tells whether key matches other.
// static bool IsMatch(Key key, Object* other);
// // Returns the hash value for key.
// static uint32_t Hash(Key key);
// // Returns the hash value for object.
// static uint32_t HashForObject(Key key, Object* object);
// // Convert key to an object.
// static inline Object* AsObject(Key key);
// // The prefix size indicates number of elements in the beginning
// // of the backing storage.
// static const int kPrefixSize = ..;
// // The Element size indicates number of elements per entry.
// static const int kEntrySize = ..;
// };
// table. The prefix size indicates an amount of memory in the
// beginning of the backing storage that can be used for non-element
// information by subclasses.
// HashTableKey is an abstract superclass keys.
class HashTableKey {
public:
// Returns whether the other object matches this key.
virtual bool IsMatch(Object* other) = 0;
typedef uint32_t (*HashFunction)(Object* obj);
// Returns the hash function used for this key.
virtual HashFunction GetHashFunction() = 0;
// Returns the hash value for this key.
virtual uint32_t Hash() = 0;
// Returns the key object for storing into the dictionary.
// If allocations fails a failure object is returned.
virtual Object* GetObject() = 0;
virtual bool IsStringKey() = 0;
// Required.
virtual ~HashTableKey() {}
};
template<int prefix_size, int element_size>
template<typename Shape, typename Key>
class HashTable: public FixedArray {
public:
// Returns the number of elements in the dictionary.
@ -1949,25 +1946,27 @@ class HashTable: public FixedArray {
static const int kNumberOfElementsIndex = 0;
static const int kCapacityIndex = 1;
static const int kPrefixStartIndex = 2;
static const int kElementsStartIndex = kPrefixStartIndex + prefix_size;
static const int kElementSize = element_size;
static const int kElementsStartIndex =
kPrefixStartIndex + Shape::kPrefixSize;
static const int kEntrySize = Shape::kEntrySize;
static const int kElementsStartOffset =
kHeaderSize + kElementsStartIndex * kPointerSize;
// Constant used for denoting a absent entry.
static const int kNotFound = -1;
protected:
// Find entry for key otherwise return -1.
int FindEntry(HashTableKey* key);
int FindEntry(Key key);
protected:
// Find the entry at which to insert element with the given key that
// has the given hash value.
uint32_t FindInsertionEntry(Object* key, uint32_t hash);
uint32_t FindInsertionEntry(uint32_t hash);
// Returns the index for an entry (of the key)
static inline int EntryToIndex(int entry) {
return (entry * kElementSize) + kElementsStartIndex;
return (entry * kEntrySize) + kElementsStartIndex;
}
// Update the number of elements in the dictionary.
@ -1992,15 +1991,51 @@ class HashTable: public FixedArray {
}
// Ensure enough space for n additional elements.
Object* EnsureCapacity(int n, HashTableKey* key);
Object* EnsureCapacity(int n, Key key);
};
// HashTableKey is an abstract superclass for virtual key behavior.
class HashTableKey {
public:
// Returns whether the other object matches this key.
virtual bool IsMatch(Object* other) = 0;
// Returns the hash value for this key.
virtual uint32_t Hash() = 0;
// Returns the hash value for object.
virtual uint32_t HashForObject(Object* key) = 0;
// Returns the key object for storing into the dictionary.
// If allocations fails a failure object is returned.
virtual Object* AsObject() = 0;
// Required.
virtual ~HashTableKey() {}
};
class SymbolTableShape {
public:
static bool IsMatch(HashTableKey* key, Object* value) {
return key->IsMatch(value);
}
static uint32_t Hash(HashTableKey* key) {
return key->Hash();
}
static uint32_t HashForObject(HashTableKey* key, Object* object) {
return key->HashForObject(object);
}
static Object* AsObject(HashTableKey* key) {
return key->AsObject();
}
static const int kPrefixSize = 0;
static const int kEntrySize = 1;
};
// SymbolTable.
//
// No special elements in the prefix and the element size is 1
// because only the symbol itself (the key) needs to be stored.
class SymbolTable: public HashTable<0, 1> {
class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
public:
// Find symbol in the symbol table. If it is not there yet, it is
// added. The return value is the symbol table which might have
@ -2024,11 +2059,33 @@ class SymbolTable: public HashTable<0, 1> {
};
class MapCacheShape {
public:
static bool IsMatch(HashTableKey* key, Object* value) {
return key->IsMatch(value);
}
static uint32_t Hash(HashTableKey* key) {
return key->Hash();
}
static uint32_t HashForObject(HashTableKey* key, Object* object) {
return key->HashForObject(object);
}
static Object* AsObject(HashTableKey* key) {
return key->AsObject();
}
static const int kPrefixSize = 0;
static const int kEntrySize = 2;
};
// MapCache.
//
// Maps keys that are a fixed array of symbols to a map.
// Used for canonicalize maps for object literals.
class MapCache: public HashTable<0, 2> {
class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
public:
// Find cached value for a string key, otherwise return null.
Object* Lookup(FixedArray* key);
@ -2040,74 +2097,42 @@ class MapCache: public HashTable<0, 2> {
};
// Dictionary for keeping properties and elements in slow case.
//
// One element in the prefix is used for storing non-element
// information about the dictionary.
//
// The rest of the array embeds triples of (key, value, details).
// if key == undefined the triple is empty.
// if key == null the triple has been deleted.
// otherwise key contains the name of a property.
class DictionaryBase: public HashTable<2, 3> {};
class Dictionary: public DictionaryBase {
template <typename Shape, typename Key>
class Dictionary: public HashTable<Shape, Key> {
public:
static inline Dictionary<Shape, Key>* cast(Object* obj) {
return reinterpret_cast<Dictionary<Shape, Key>*>(obj);
}
// Returns the value at entry.
Object* ValueAt(int entry) {
return get(EntryToIndex(entry)+1);
return get(HashTable<Shape, Key>::EntryToIndex(entry)+1);
}
// Set the value for entry.
void ValueAtPut(int entry, Object* value) {
set(EntryToIndex(entry)+1, value);
set(HashTable<Shape, Key>::EntryToIndex(entry)+1, value);
}
// Returns the property details for the property at entry.
PropertyDetails DetailsAt(int entry) {
ASSERT(entry >= 0); // Not found is -1, which is not caught by get().
return PropertyDetails(Smi::cast(get(EntryToIndex(entry) + 2)));
return PropertyDetails(
Smi::cast(get(HashTable<Shape, Key>::EntryToIndex(entry) + 2)));
}
// Set the details for entry.
void DetailsAtPut(int entry, PropertyDetails value) {
set(EntryToIndex(entry) + 2, value.AsSmi());
set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi());
}
// Remove all entries were key is a number and (from <= key && key < to).
void RemoveNumberEntries(uint32_t from, uint32_t to);
// Sorting support
void CopyValuesTo(FixedArray* elements);
// Casting.
static inline Dictionary* cast(Object* obj);
// Find entry for string key otherwise return -1.
int FindStringEntry(String* key);
// Find entry for number key otherwise return -1.
int FindNumberEntry(uint32_t index);
// Delete a property from the dictionary.
Object* DeleteProperty(int entry, JSObject::DeleteMode mode);
// Type specific at put (default NONE attributes is used when adding).
Object* AtNumberPut(uint32_t key, Object* value);
Object* AddStringEntry(String* key, Object* value, PropertyDetails details);
Object* AddNumberEntry(uint32_t key, Object* value, PropertyDetails details);
// Set an existing entry or add a new one if needed.
Object* SetStringEntry(int entry,
String* key,
Object* value,
PropertyDetails details);
Object* SetOrAddNumberEntry(uint32_t key,
Object* value,
PropertyDetails details);
// Returns the number of elements in the dictionary filtering out properties
// with the specified attributes.
int NumberOfElementsFilterAttributes(PropertyAttributes filter);
@ -2117,14 +2142,113 @@ class Dictionary: public DictionaryBase {
// Copies keys to preallocated fixed array.
void CopyKeysTo(FixedArray* storage, PropertyAttributes filter);
// Copies enumerable keys to preallocated fixed array.
void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array);
// Fill in details for properties into storage.
void CopyKeysTo(FixedArray* storage);
// Accessors for next enumeration index.
void SetNextEnumerationIndex(int index) {
fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index));
}
int NextEnumerationIndex() {
return Smi::cast(FixedArray::get(kNextEnumerationIndexIndex))->value();
}
// Returns a new array for dictionary usage. Might return Failure.
static Object* Allocate(int at_least_space_for);
// Ensure enough space for n additional elements.
Object* EnsureCapacity(int n, Key key);
#ifdef DEBUG
void Print();
#endif
// Returns the key (slow).
Object* SlowReverseLookup(Object* value);
// Sets the entry to (key, value) pair.
inline void SetEntry(int entry,
Object* key,
Object* value,
PropertyDetails details);
Object* Add(Key key, Object* value, PropertyDetails details);
protected:
// Generic at put operation.
Object* AtPut(Key key, Object* value);
// Add entry to dictionary.
Object* AddEntry(Key key,
Object* value,
PropertyDetails details,
uint32_t hash);
// Generate new enumeration indices to avoid enumeration index overflow.
Object* GenerateNewEnumerationIndices();
static const int kMaxNumberKeyIndex =
HashTable<Shape, Key>::kPrefixStartIndex;
static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
};
class StringDictionaryShape {
public:
static inline bool IsMatch(String* key, Object* other);
static inline uint32_t Hash(String* key);
static inline uint32_t HashForObject(String* key, Object* object);
static inline Object* AsObject(String* key);
static const int kPrefixSize = 2;
static const int kEntrySize = 3;
static const bool kIsEnumerable = true;
};
class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
public:
static inline StringDictionary* cast(Object* obj) {
ASSERT(obj->IsDictionary());
return reinterpret_cast<StringDictionary*>(obj);
}
// Copies enumerable keys to preallocated fixed array.
void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array);
// For transforming properties of a JSObject.
Object* TransformPropertiesToFastFor(JSObject* obj,
int unused_property_fields);
};
class NumberDictionaryShape {
public:
static inline bool IsMatch(uint32_t key, Object* other);
static inline uint32_t Hash(uint32_t key);
static inline uint32_t HashForObject(uint32_t key, Object* object);
static inline Object* AsObject(uint32_t key);
static const int kPrefixSize = 2;
static const int kEntrySize = 3;
static const bool kIsEnumerable = false;
};
class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> {
public:
static NumberDictionary* cast(Object* obj) {
ASSERT(obj->IsDictionary());
return reinterpret_cast<NumberDictionary*>(obj);
}
// Type specific at put (default NONE attributes is used when adding).
Object* AtNumberPut(uint32_t key, Object* value);
Object* AddNumberEntry(uint32_t key,
Object* value,
PropertyDetails details);
// Set an existing entry or add a new one if needed.
Object* Set(uint32_t key, Object* value, PropertyDetails details);
void UpdateMaxNumberKey(uint32_t key);
// If slow elements are required we will never go back to fast-case
// for the elements kept in this dictionary. We require slow
@ -2139,59 +2263,13 @@ class Dictionary: public DictionaryBase {
// requires_slow_elements returns false.
inline uint32_t max_number_key();
// Accessors for next enumeration index.
void SetNextEnumerationIndex(int index) {
fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index));
}
int NextEnumerationIndex() {
return Smi::cast(get(kNextEnumerationIndexIndex))->value();
}
// Returns a new array for dictionary usage. Might return Failure.
static Object* Allocate(int at_least_space_for);
// Ensure enough space for n additional elements.
Object* EnsureCapacity(int n, HashTableKey* key);
#ifdef DEBUG
void Print();
#endif
// Returns the key (slow).
Object* SlowReverseLookup(Object* value);
// Remove all entries were key is a number and (from <= key && key < to).
void RemoveNumberEntries(uint32_t from, uint32_t to);
// Bit masks.
static const int kRequiresSlowElementsMask = 1;
static const int kRequiresSlowElementsTagSize = 1;
static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
void UpdateMaxNumberKey(uint32_t key);
private:
// Generic at put operation.
Object* AtPut(HashTableKey* key, Object* value);
Object* Add(HashTableKey* key, Object* value, PropertyDetails details);
// Add entry to dictionary.
void AddEntry(Object* key,
Object* value,
PropertyDetails details,
uint32_t hash);
// Sets the entry to (key, value) pair.
inline void SetEntry(int entry,
Object* key,
Object* value,
PropertyDetails details);
// Generate new enumeration indices to avoid enumeration index overflow.
Object* GenerateNewEnumerationIndices();
static const int kMaxNumberKeyIndex = kPrefixStartIndex;
static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary);
};
@ -3231,7 +3309,30 @@ class JSRegExp: public JSObject {
};
class CompilationCacheTable: public HashTable<0, 2> {
class CompilationCacheShape {
public:
static inline bool IsMatch(HashTableKey* key, Object* value) {
return key->IsMatch(value);
}
static inline uint32_t Hash(HashTableKey* key) {
return key->Hash();
}
static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
return key->HashForObject(object);
}
static Object* AsObject(HashTableKey* key) {
return key->AsObject();
}
static const int kPrefixSize = 0;
static const int kEntrySize = 2;
};
class CompilationCacheTable: public HashTable<CompilationCacheShape,
HashTableKey*> {
public:
// Find cached value for a string key, otherwise return null.
Object* Lookup(String* src);

View File

@ -168,7 +168,7 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
}
}
} else {
Dictionary* element_dictionary = copy->element_dictionary();
NumberDictionary* element_dictionary = copy->element_dictionary();
int capacity = element_dictionary->Capacity();
for (int i = 0; i < capacity; i++) {
Object* k = element_dictionary->KeyAt(i);
@ -2604,9 +2604,9 @@ static Object* Runtime_KeyedGetProperty(Arguments args) {
}
} else {
// Attempt dictionary lookup.
Dictionary* dictionary = receiver->property_dictionary();
int entry = dictionary->FindStringEntry(key);
if ((entry != Dictionary::kNotFound) &&
StringDictionary* dictionary = receiver->property_dictionary();
int entry = dictionary->FindEntry(key);
if ((entry != StringDictionary::kNotFound) &&
(dictionary->DetailsAt(entry).type() == NORMAL)) {
Object* value = dictionary->ValueAt(entry);
if (receiver->IsGlobalObject()) {
@ -5130,8 +5130,8 @@ class ArrayConcatVisitor {
storage_->set(index, *elm);
} else {
Handle<Dictionary> dict = Handle<Dictionary>::cast(storage_);
Handle<Dictionary> result =
Handle<NumberDictionary> dict = Handle<NumberDictionary>::cast(storage_);
Handle<NumberDictionary> result =
Factory::DictionaryAtNumberPut(dict, index, elm);
if (!result.is_identical_to(dict))
storage_ = result;
@ -5179,7 +5179,7 @@ static uint32_t IterateElements(Handle<JSObject> receiver,
}
} else {
Handle<Dictionary> dict(receiver->element_dictionary());
Handle<NumberDictionary> dict(receiver->element_dictionary());
uint32_t capacity = dict->Capacity();
for (uint32_t j = 0; j < capacity; j++) {
Handle<Object> k(dict->KeyAt(j));
@ -5333,7 +5333,7 @@ static Object* Runtime_ArrayConcat(Arguments args) {
uint32_t at_least_space_for = estimate_nof_elements +
(estimate_nof_elements >> 2);
storage = Handle<FixedArray>::cast(
Factory::NewDictionary(at_least_space_for));
Factory::NewNumberDictionary(at_least_space_for));
}
Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length));
@ -5396,7 +5396,7 @@ static Object* Runtime_EstimateNumberOfElements(Arguments args) {
CONVERT_CHECKED(JSArray, array, args[0]);
HeapObject* elements = array->elements();
if (elements->IsDictionary()) {
return Smi::FromInt(Dictionary::cast(elements)->NumberOfElements());
return Smi::FromInt(NumberDictionary::cast(elements)->NumberOfElements());
} else {
return array->length();
}

View File

@ -562,8 +562,8 @@ Object* StubCache::ComputeCallGlobal(int argc,
static Object* GetProbeValue(Code::Flags flags) {
Dictionary* dictionary = Heap::non_monomorphic_cache();
int entry = dictionary->FindNumberEntry(flags);
NumberDictionary* dictionary = Heap::non_monomorphic_cache();
int entry = dictionary->FindEntry(flags);
if (entry != -1) return dictionary->ValueAt(entry);
return Heap::undefined_value();
}
@ -579,7 +579,7 @@ static Object* ProbeCache(Code::Flags flags) {
Heap::non_monomorphic_cache()->AtNumberPut(flags,
Heap::undefined_value());
if (result->IsFailure()) return result;
Heap::set_non_monomorphic_cache(Dictionary::cast(result));
Heap::set_non_monomorphic_cache(NumberDictionary::cast(result));
return probe;
}
@ -587,7 +587,7 @@ static Object* ProbeCache(Code::Flags flags) {
static Object* FillCache(Object* code) {
if (code->IsCode()) {
int entry =
Heap::non_monomorphic_cache()->FindNumberEntry(
Heap::non_monomorphic_cache()->FindEntry(
Code::cast(code)->flags());
// The entry must be present see comment in ProbeCache.
ASSERT(entry != -1);