Commit e75a173f authored by ager@chromium.org's avatar ager@chromium.org

Revert r2324 until we can fix build and test errors.

TBR=bak@chromium.org

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2325 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5cbb2094
......@@ -1434,8 +1434,8 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
}
}
} else {
Handle<StringDictionary> properties =
Handle<StringDictionary>(from->property_dictionary());
Handle<Dictionary> properties =
Handle<Dictionary>(from->property_dictionary());
int capacity = properties->Capacity();
for (int i = 0; i < capacity; i++) {
Object* raw_key(properties->KeyAt(i));
......
......@@ -37,8 +37,8 @@ namespace internal {
Handle<Code> CodeStub::GetCode() {
uint32_t key = GetKey();
int index = Heap::code_stubs()->FindEntry(key);
if (index == NumberDictionary::kNotFound) {
int index = Heap::code_stubs()->FindNumberEntry(key);
if (index == -1) {
HandleScope scope;
// Update the static counter each time a new code stub is generated.
......@@ -80,15 +80,14 @@ Handle<Code> CodeStub::GetCode() {
#endif
// Update the dictionary and the root in Heap.
Handle<NumberDictionary> dict =
Factory::DictionaryAtNumberPut(
Handle<NumberDictionary>(Heap::code_stubs()),
key,
code);
Handle<Dictionary> dict =
Factory::DictionaryAtNumberPut(Handle<Dictionary>(Heap::code_stubs()),
key,
code);
Heap::set_code_stubs(*dict);
index = Heap::code_stubs()->FindEntry(key);
index = Heap::code_stubs()->FindNumberEntry(key);
}
ASSERT(index != NumberDictionary::kNotFound);
ASSERT(index != -1);
return Handle<Code>(Code::cast(Heap::code_stubs()->ValueAt(index)));
}
......
......@@ -49,17 +49,9 @@ Handle<FixedArray> Factory::NewFixedArrayWithHoles(int size) {
}
Handle<StringDictionary> Factory::NewStringDictionary(int at_least_space_for) {
Handle<Dictionary> Factory::NewDictionary(int at_least_space_for) {
ASSERT(0 <= at_least_space_for);
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);
CALL_HEAP_FUNCTION(Dictionary::Allocate(at_least_space_for), Dictionary);
}
......@@ -663,11 +655,10 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
}
Handle<NumberDictionary> Factory::DictionaryAtNumberPut(
Handle<NumberDictionary> dictionary,
uint32_t key,
Handle<Object> value) {
CALL_HEAP_FUNCTION(dictionary->AtNumberPut(key, *value), NumberDictionary);
Handle<Dictionary> Factory::DictionaryAtNumberPut(Handle<Dictionary> dictionary,
uint32_t key,
Handle<Object> value) {
CALL_HEAP_FUNCTION(dictionary->AtNumberPut(key, *value), Dictionary);
}
......
......@@ -47,9 +47,7 @@ class Factory : public AllStatic {
// Allocate a new fixed array with non-existing entries (the hole).
static Handle<FixedArray> NewFixedArrayWithHoles(int size);
static Handle<NumberDictionary> NewNumberDictionary(int at_least_space_for);
static Handle<StringDictionary> NewStringDictionary(int at_least_space_for);
static Handle<Dictionary> NewDictionary(int at_least_space_for);
static Handle<DescriptorArray> NewDescriptorArray(int number_of_descriptors);
......@@ -315,10 +313,9 @@ class Factory : public AllStatic {
static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
static Handle<NumberDictionary> DictionaryAtNumberPut(
Handle<NumberDictionary>,
uint32_t key,
Handle<Object> value);
static Handle<Dictionary> DictionaryAtNumberPut(Handle<Dictionary>,
uint32_t key,
Handle<Object> value);
#ifdef ENABLE_DEBUGGER_SUPPORT
static Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared);
......
......@@ -198,8 +198,7 @@ class FixedArray;
class FunctionEntry;
class FunctionLiteral;
class FunctionTemplateInfo;
class NumberDictionary;
class StringDictionary;
class Dictionary;
class FreeStoreAllocationPolicy;
template <typename T> class Handle;
class Heap;
......
......@@ -1392,14 +1392,14 @@ bool Heap::CreateInitialObjects() {
prototype_accessors_ = Proxy::cast(obj);
// Allocate the code_stubs dictionary.
obj = NumberDictionary::Allocate(4);
obj = Dictionary::Allocate(4);
if (obj->IsFailure()) return false;
code_stubs_ = NumberDictionary::cast(obj);
code_stubs_ = Dictionary::cast(obj);
// Allocate the non_monomorphic_cache used in stub-cache.cc
obj = NumberDictionary::Allocate(4);
obj = Dictionary::Allocate(4);
if (obj->IsFailure()) return false;
non_monomorphic_cache_ = NumberDictionary::cast(obj);
non_monomorphic_cache_ = Dictionary::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->IsHashTable());
ASSERT(result->IsDictionary());
return result;
}
......
......@@ -118,8 +118,8 @@ namespace internal {
V(Map, neander_map) \
V(JSObject, message_listeners) \
V(Proxy, prototype_accessors) \
V(NumberDictionary, code_stubs) \
V(NumberDictionary, non_monomorphic_cache) \
V(Dictionary, code_stubs) \
V(Dictionary, 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(NumberDictionary* value) { code_stubs_ = value; }
static void set_code_stubs(Dictionary* value) { code_stubs_ = value; }
// Sets the non_monomorphic_cache_ (only used when expanding the dictionary).
static void set_non_monomorphic_cache(NumberDictionary* value) {
static void set_non_monomorphic_cache(Dictionary* value) {
non_monomorphic_cache_ = value;
}
......
......@@ -83,7 +83,7 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
// Compute the capacity mask.
const int kCapacityOffset =
Array::kHeaderSize + StringDictionary::kCapacityIndex * kPointerSize;
Array::kHeaderSize + Dictionary::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 + StringDictionary::kElementsStartIndex * kPointerSize;
Array::kHeaderSize + Dictionary::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(StringDictionary::GetProbeOffset(i)));
__ add(Operand(r1), Immediate(Dictionary::GetProbeOffset(i)));
}
__ and_(r1, Operand(r2));
// Scale the index by multiplying by the entry size.
ASSERT(StringDictionary::kEntrySize == 3);
// Scale the index by multiplying by the element size.
ASSERT(Dictionary::kElementSize == 3);
__ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3
// Check if the key is identical to the name.
......
......@@ -744,12 +744,12 @@ void Proxy::ProxyVerify() {
ASSERT(IsProxy());
}
template<typename Shape, typename Key>
void Dictionary<Shape, Key>::Print() {
int capacity = HashTable<Shape, Key>::Capacity();
void Dictionary::Print() {
int capacity = Capacity();
for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) {
Object* k = KeyAt(i);
if (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 {
StringDictionary* dict = property_dictionary();
Dictionary* 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 {
NumberDictionary* dict = element_dictionary();
Dictionary* dict = element_dictionary();
info->number_of_slow_used_elements_ += dict->NumberOfElements();
info->number_of_slow_unused_elements_ +=
dict->Capacity() - dict->NumberOfElements();
......
......@@ -1370,14 +1370,15 @@ void DescriptorArray::Swap(int first, int second) {
}
bool NumberDictionary::requires_slow_elements() {
bool Dictionary::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 NumberDictionary::max_number_key() {
uint32_t Dictionary::max_number_key() {
ASSERT(!requires_slow_elements());
Object* max_index_object = get(kMaxNumberKeyIndex);
if (!max_index_object->IsSmi()) return 0;
......@@ -1385,7 +1386,8 @@ uint32_t NumberDictionary::max_number_key() {
return value >> kRequiresSlowElementsTagSize;
}
void NumberDictionary::set_requires_slow_elements() {
void Dictionary::set_requires_slow_elements() {
set(kMaxNumberKeyIndex,
Smi::FromInt(kRequiresSlowElementsMask),
SKIP_WRITE_BARRIER);
......@@ -1398,6 +1400,7 @@ void NumberDictionary::set_requires_slow_elements() {
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(DescriptorArray)
CAST_ACCESSOR(Dictionary)
CAST_ACCESSOR(SymbolTable)
CAST_ACCESSOR(CompilationCacheTable)
CAST_ACCESSOR(MapCache)
......@@ -1436,9 +1439,9 @@ CAST_ACCESSOR(Struct)
STRUCT_LIST(MAKE_STRUCT_CAST)
#undef MAKE_STRUCT_CAST
template <typename Shape, typename Key>
HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
template <int prefix_size, int elem_size>
HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
Object* obj) {
ASSERT(obj->IsHashTable());
return reinterpret_cast<HashTable*>(obj);
}
......@@ -2465,15 +2468,15 @@ bool JSObject::HasIndexedInterceptor() {
}
StringDictionary* JSObject::property_dictionary() {
Dictionary* JSObject::property_dictionary() {
ASSERT(!HasFastProperties());
return StringDictionary::cast(properties());
return Dictionary::cast(properties());
}
NumberDictionary* JSObject::element_dictionary() {
Dictionary* JSObject::element_dictionary() {
ASSERT(!HasFastElements());
return NumberDictionary::cast(elements());
return Dictionary::cast(elements());
}
......@@ -2637,17 +2640,16 @@ void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
}
template<typename Shape, typename Key>
void Dictionary<Shape, Key>::SetEntry(int entry,
Object* key,
Object* value,
PropertyDetails details) {
void Dictionary::SetEntry(int entry,
Object* key,
Object* value,
PropertyDetails details) {
ASSERT(!key->IsString() || details.index() > 0);
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());
int index = EntryToIndex(entry);
WriteBarrierMode mode = GetWriteBarrierMode();
set(index, key, mode);
set(index+1, value, mode);
fast_set(this, index+2, details.AsSmi());
}
......
......@@ -41,7 +41,6 @@
#include "disassembler.h"
#endif
namespace v8 {
namespace internal {
......@@ -429,17 +428,17 @@ Object* JSObject::SetNormalizedProperty(String* name,
Object* value,
PropertyDetails details) {
ASSERT(!HasFastProperties());
int entry = property_dictionary()->FindEntry(name);
if (entry == StringDictionary::kNotFound) {
int entry = property_dictionary()->FindStringEntry(name);
if (entry == Dictionary::kNotFound) {
Object* store_value = value;
if (IsGlobalObject()) {
store_value = Heap::AllocateJSGlobalPropertyCell(value);
if (store_value->IsFailure()) return store_value;
}
Object* dict =
property_dictionary()->Add(name, store_value, details);
property_dictionary()->AddStringEntry(name, store_value, details);
if (dict->IsFailure()) return dict;
set_properties(StringDictionary::cast(dict));
set_properties(Dictionary::cast(dict));
return value;
}
// Preserve enumeration index.
......@@ -453,7 +452,7 @@ Object* JSObject::SetNormalizedProperty(String* name,
// Please note we have to update the property details.
property_dictionary()->DetailsAtPut(entry, details);
} else {
property_dictionary()->SetEntry(entry, name, value, details);
property_dictionary()->SetStringEntry(entry, name, value, details);
}
return value;
}
......@@ -461,9 +460,9 @@ Object* JSObject::SetNormalizedProperty(String* name,
Object* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) {
ASSERT(!HasFastProperties());
StringDictionary* dictionary = property_dictionary();
int entry = dictionary->FindEntry(name);
if (entry != StringDictionary::kNotFound) {
Dictionary* dictionary = property_dictionary();
int entry = dictionary->FindStringEntry(name);
if (entry != Dictionary::kNotFound) {
// If we have a global object set the cell to the hole.
if (IsGlobalObject()) {
PropertyDetails details = dictionary->DetailsAt(entry);
......@@ -1341,16 +1340,16 @@ Object* JSObject::AddSlowProperty(String* name,
Object* value,
PropertyAttributes attributes) {
ASSERT(!HasFastProperties());
StringDictionary* dict = property_dictionary();
Dictionary* dict = property_dictionary();
Object* store_value = value;
if (IsGlobalObject()) {
// In case name is an orphaned property reuse the cell.
int entry = dict->FindEntry(name);
if (entry != StringDictionary::kNotFound) {
int entry = dict->FindStringEntry(name);
if (entry != Dictionary::kNotFound) {
store_value = dict->ValueAt(entry);
JSGlobalPropertyCell::cast(store_value)->set_value(value);
PropertyDetails details = PropertyDetails(attributes, NORMAL);
dict->SetEntry(entry, name, store_value, details);
dict->SetStringEntry(entry, name, store_value, details);
return value;
}
store_value = Heap::AllocateJSGlobalPropertyCell(value);
......@@ -1358,9 +1357,9 @@ Object* JSObject::AddSlowProperty(String* name,
JSGlobalPropertyCell::cast(store_value)->set_value(value);
}
PropertyDetails details = PropertyDetails(attributes, NORMAL);
Object* result = dict->Add(name, store_value, details);
Object* result = dict->AddStringEntry(name, store_value, details);
if (result->IsFailure()) return result;
if (dict != result) set_properties(StringDictionary::cast(result));
if (dict != result) set_properties(Dictionary::cast(result));
return value;
}
......@@ -1406,8 +1405,8 @@ Object* JSObject::SetPropertyPostInterceptor(String* name,
Object* JSObject::ReplaceSlowProperty(String* name,
Object* value,
PropertyAttributes attributes) {
StringDictionary* dictionary = property_dictionary();
int old_index = dictionary->FindEntry(name);
Dictionary* dictionary = property_dictionary();
int old_index = dictionary->FindStringEntry(name);
int new_enumeration_index = 0; // 0 means "Use the next available index."
if (old_index != -1) {
// All calls to ReplaceSlowProperty have had all transitions removed.
......@@ -1647,9 +1646,9 @@ Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) {
pt != Heap::null_value();
pt = pt->GetPrototype()) {
if (JSObject::cast(pt)->HasFastElements()) continue;
NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary();
int entry = dictionary->FindEntry(index);
if (entry != StringDictionary::kNotFound) {
Dictionary* dictionary = JSObject::cast(pt)->element_dictionary();
int entry = dictionary->FindNumberEntry(index);
if (entry != Dictionary::kNotFound) {
Object* element = dictionary->ValueAt(entry);
PropertyDetails details = dictionary->DetailsAt(entry);
if (details.type() == CALLBACKS) {
......@@ -1699,8 +1698,8 @@ void JSObject::LocalLookupRealNamedProperty(String* name,
return;
}
} else {
int entry = property_dictionary()->FindEntry(name);
if (entry != StringDictionary::kNotFound) {
int entry = property_dictionary()->FindStringEntry(name);
if (entry != Dictionary::kNotFound) {
// Make sure to disallow caching for uninitialized constants
// found in the dictionary-mode objects.
Object* value = property_dictionary()->ValueAt(entry);
......@@ -2102,9 +2101,9 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
// Allocate new content
Object* obj =
StringDictionary::Allocate(map()->NumberOfDescribedProperties() * 2 + 4);
Dictionary::Allocate(map()->NumberOfDescribedProperties() * 2 + 4);
if (obj->IsFailure()) return obj;
StringDictionary* dictionary = StringDictionary::cast(obj);
Dictionary* dictionary = Dictionary::cast(obj);
for (DescriptorReader r(map()->instance_descriptors());
!r.eos();
......@@ -2119,9 +2118,9 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
value = Heap::AllocateJSGlobalPropertyCell(value);
if (value->IsFailure()) return value;
}
Object* result = dictionary->Add(r.GetKey(), value, d);
Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
if (result->IsFailure()) return result;
dictionary = StringDictionary::cast(result);
dictionary = Dictionary::cast(result);
break;
}
case FIELD: {
......@@ -2132,9 +2131,9 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
value = Heap::AllocateJSGlobalPropertyCell(value);
if (value->IsFailure()) return value;
}
Object* result = dictionary->Add(r.GetKey(), value, d);
Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
if (result->IsFailure()) return result;
dictionary = StringDictionary::cast(result);
dictionary = Dictionary::cast(result);
break;
}
case CALLBACKS: {
......@@ -2145,9 +2144,9 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
value = Heap::AllocateJSGlobalPropertyCell(value);
if (value->IsFailure()) return value;
}
Object* result = dictionary->Add(r.GetKey(), value, d);
Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
if (result->IsFailure()) return result;
dictionary = StringDictionary::cast(result);
dictionary = Dictionary::cast(result);
break;
}
case MAP_TRANSITION:
......@@ -2220,9 +2219,9 @@ Object* JSObject::NormalizeElements() {
int length = IsJSArray() ?
Smi::cast(JSArray::cast(this)->length())->value() :
array->length();
Object* obj = NumberDictionary::Allocate(length);
Object* obj = Dictionary::Allocate(length);
if (obj->IsFailure()) return obj;
NumberDictionary* dictionary = NumberDictionary::cast(obj);
Dictionary* dictionary = Dictionary::cast(obj);
// Copy entries.
for (int i = 0; i < length; i++) {
Object* value = array->get(i);
......@@ -2230,7 +2229,7 @@ Object* JSObject::NormalizeElements() {
PropertyDetails details = PropertyDetails(NONE, NORMAL);
Object* result = dictionary->AddNumberEntry(i, array->get(i), details);
if (result->IsFailure()) return result;
dictionary = NumberDictionary::cast(result);
dictionary = Dictionary::cast(result);
}
}
// Switch to using the dictionary as the backing storage for elements.
......@@ -2307,9 +2306,9 @@ Object* JSObject::DeleteElementPostInterceptor(uint32_t index,
return Heap::true_value();
}
ASSERT(!HasFastElements());
NumberDictionary* dictionary = element_dictionary();
int entry = dictionary->FindEntry(index);
if (entry != NumberDictionary::kNotFound) {
Dictionary* dictionary = element_dictionary();
int entry = dictionary->FindNumberEntry(index);
if (entry != Dictionary::kNotFound) {
return dictionary->DeleteProperty(entry, mode);
}
return Heap::true_value();
......@@ -2381,9 +2380,9 @@ Object* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
}
return Heap::true_value();
} else {
NumberDictionary* dictionary = element_dictionary();
int entry = dictionary->FindEntry(index);
if (entry != NumberDictionary::kNotFound) {
Dictionary* dictionary = element_dictionary();
int entry = dictionary->FindNumberEntry(index);
if (entry != Dictionary::kNotFound) {
return dictionary->DeleteProperty(entry, mode);
}
}
......@@ -2688,9 +2687,9 @@ Object* JSObject::DefineGetterSetter(String* name,
if (is_element) {
// Lookup the index.
if (!HasFastElements()) {
NumberDictionary* dictionary = element_dictionary();
int entry = dictionary->FindEntry(index);
if (entry != NumberDictionary::kNotFound) {
Dictionary* dictionary = element_dictionary();
int entry = dictionary->FindNumberEntry(index);
if (entry != Dictionary::kNotFound) {
Object* result = dictionary->ValueAt(entry);
PropertyDetails details = dictionary->DetailsAt(entry);
if (details.IsReadOnly()) return Heap::undefined_value();
......@@ -2726,14 +2725,14 @@ Object* JSObject::DefineGetterSetter(String* name,
// Update the dictionary with the new CALLBACKS property.
Object* dict =
element_dictionary()->Set(index, structure, details);
element_dictionary()->SetOrAddNumberEntry(index, structure, details);
if (dict->IsFailure()) return dict;
// If name is an index we need to stay in slow case.
NumberDictionary* elements = NumberDictionary::cast(dict);
Dictionary* elements = Dictionary::cast(dict);
elements->set_requires_slow_elements();
// Set the potential new dictionary on the object.
set_elements(NumberDictionary::cast(dict));
set_elements(Dictionary::cast(dict));
} else {
// Normalize object to make this operation simple.
Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
......@@ -2800,9 +2799,9 @@ Object* JSObject::LookupAccessor(String* name, bool is_getter) {
obj = JSObject::cast(obj)->GetPrototype()) {
JSObject* jsObject = JSObject::cast(obj);
if (!jsObject->HasFastElements()) {
NumberDictionary* dictionary = jsObject->element_dictionary();
int entry = dictionary->FindEntry(index);
if (entry != NumberDictionary::kNotFound) {
Dictionary* dictionary = jsObject->element_dictionary();
int entry = dictionary->FindNumberEntry(index);
if (entry != Dictionary::kNotFound) {
Object* element = dictionary->ValueAt(entry);
PropertyDetails details = dictionary->DetailsAt(entry);
if (details.type() == CALLBACKS) {
......@@ -3005,7 +3004,7 @@ Object* FixedArray::AddKeysFromJSArray(JSArray* array) {
return UnionOfKeys(array->elements());
}
ASSERT(!array->HasFastElements());
NumberDictionary* dict = array->element_dictionary();
Dictionary* dict = array->element_dictionary();
int size = dict->NumberOfElements();
// Allocate a temporary fixed array.
......@@ -5076,7 +5075,7 @@ void JSObject::SetFastElements(FixedArray* elems) {
elems->set(i, old_elements->get(i), mode);
}
} else {
NumberDictionary* dictionary = NumberDictionary::cast(elements());
Dictionary* dictionary = Dictionary::cast(elements());
for (int i = 0; i < dictionary->Capacity(); i++) {
Object* key = dictionary->KeyAt(i);
if (key->IsNumber()) {
......@@ -5241,8 +5240,7 @@ bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) {
return true;
}
} else {
if (element_dictionary()->FindEntry(index)
!= NumberDictionary::kNotFound) {
if (element_dictionary()->FindNumberEntry(index) != Dictionary::kNotFound) {
return true;
}
}
......@@ -5319,8 +5317,8 @@ bool JSObject::HasLocalElement(uint32_t index) {
return (index < length) &&
!FixedArray::cast(elements())->get(index)->IsTheHole();
} else {
return element_dictionary()->FindEntry(index)
!= NumberDictionary::kNotFound;
return element_dictionary()->FindNumberEntry(index)
!= Dictionary::kNotFound;
}
}
......@@ -5346,8 +5344,7 @@ bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
if ((index < length) &&
!FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
} else {
if (element_dictionary()->FindEntry(index)
!= NumberDictionary::kNotFound) {
if (element_dictionary()->FindNumberEntry(index) != Dictionary::kNotFound) {
return true;
}
}
......@@ -5482,10 +5479,10 @@ Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) {
// Insert element in the dictionary.
FixedArray* elms = FixedArray::cast(elements());
NumberDictionary* dictionary = NumberDictionary::cast(elms);
Dictionary* dictionary = Dictionary::cast(elms);
int entry = dictionary->FindEntry(index);
if (entry != NumberDictionary::kNotFound) {
int entry = dictionary->FindNumberEntry(index);
if (entry != Dictionary::kNotFound) {
Object* element = dictionary->ValueAt(entry);
PropertyDetails details = dictionary->DetailsAt(entry);
if (details.type() == CALLBACKS) {
......@@ -5534,7 +5531,7 @@ Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) {
CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &new_length));
JSArray::cast(this)->set_length(Smi::FromInt(new_length));
} else {
new_length = NumberDictionary::cast(elements())->max_number_key() + 1;
new_length = Dictionary::cast(elements())->max_number_key() + 1;
}
Object* obj = Heap::AllocateFixedArrayWithHoles(new_length);
if (obj->IsFailure()) return obj;
......@@ -5577,9 +5574,9 @@ Object* JSObject::GetElementPostInterceptor(JSObject* receiver,
if (!value->IsTheHole()) return value;
}
} else {
NumberDictionary* dictionary = element_dictionary();
int entry = dictionary->FindEntry(index);
if (entry != NumberDictionary::kNotFound) {
Dictionary* dictionary = element_dictionary();
int entry = dictionary->FindNumberEntry(index);
if (entry != Dictionary::kNotFound) {
Object* element = dictionary->ValueAt(entry);
PropertyDetails details = dictionary->DetailsAt(entry);
if (details.type() == CALLBACKS) {
......@@ -5661,9 +5658,9 @@ Object* JSObject::GetElementWithReceiver(JSObject* receiver, uint32_t index) {
if (!value->IsTheHole()) return value;
}
} else {
NumberDictionary* dictionary = element_dictionary();
int entry = dictionary->FindEntry(index);
if (entry != NumberDictionary::kNotFound) {
Dictionary* dictionary = element_dictionary();
int entry = dictionary->FindNumberEntry(index);
if (entry != Dictionary::kNotFound) {
Object* element = dictionary->ValueAt(entry);
PropertyDetails details = dictionary->DetailsAt(entry);
if (details.type() == CALLBACKS) {
......@@ -5699,7 +5696,7 @@ bool JSObject::HasDenseElements() {
if (!elms->get(i)->IsTheHole()) number_of_elements++;
}
} else {
NumberDictionary* dictionary = NumberDictionary::cast(elements());
Dictionary* dictionary = Dictionary::cast(elements());
capacity = dictionary->Capacity();
number_of_elements = dictionary->NumberOfElements();
}
......@@ -5721,7 +5718,7 @@ bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
bool JSObject::ShouldConvertToFastElements() {
ASSERT(!HasFastElements());
NumberDictionary* dictionary = NumberDictionary::cast(elements());
Dictionary* dictionary = Dictionary::cast(elements());
// If the elements are sparse, we should not go back to fast case.
if (!HasDenseElements()) return false;
// If an element has been added at a very high index in the elements
......@@ -5740,19 +5737,17 @@ bool JSObject::ShouldConvertToFastElements() {
length = dictionary->max_number_key();
}
return static_cast<uint32_t>(dictionary->Capacity()) >=
(length / (2 * NumberDictionary::kEntrySize));
(length / (2 * Dictionary::kElementSize));
}
template<typename Shape, typename Key>
void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
void Dictionary::CopyValuesTo(FixedArray* elements) {
int pos = 0;
int capacity = HashTable<Shape, Key>::Capacity();
int capacity = Capacity();
WriteBarrierMode mode = elements->GetWriteBarrierMode();
for (int i = 0; i < capacity; i++) {
Object* k = Dictionary<Shape, Key>::KeyAt(i);
if (Dictionary<Shape, Key>::IsKey(k)) {
elements->set(pos++, ValueAt(i), mode);
}
Object* k = KeyAt(i);
if (IsKey(k)) elements->set(pos++, ValueAt(i), mode);
}
ASSERT(pos == elements->length());
}
......@@ -5958,8 +5953,8 @@ bool JSObject::HasRealElementProperty(uint32_t index) {
return (index < length) &&
!FixedArray::cast(elements())->get(index)->IsTheHole();
}
return element_dictionary()->FindEntry(index)
!= NumberDictionary::kNotFound;
return element_dictionary()->FindNumberEntry(index)
!= Dictionary::kNotFound;
}
......@@ -6192,49 +6187,38 @@ int JSObject::GetEnumElementKeys(FixedArray* storage) {
}
bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
ASSERT(other->IsNumber());
return key == static_cast<uint32_t>(other->Number());
}
uint32_t NumberDictionaryShape::Hash(uint32_t key) {
return ComputeIntegerHash(key);
}
uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) {
ASSERT(other->IsNumber());
return ComputeIntegerHash(static_cast<uint32_t>(other->Number()));
}
Object* NumberDictionaryShape::AsObject(uint32_t key) {
return Heap::NumberFromUint32(key);
}
// The NumberKey uses carries the uint32_t as key.
// This avoids allocation in HasProperty.
class NumberKey : public HashTableKey {
public:
explicit NumberKey(uint32_t number) : number_(number) { }
bool IsMatch(Object* number) {
return number_ == ToUint32(number);
}
bool StringDictionaryShape::IsMatch(String* key, Object* other) {
// We know that all entries in a hash table had their hash keys created.
// Use that knowledge to have fast failure.
if (key->Hash() != String::cast(other)->Hash()) return false;
return key->Equals(String::cast(other));
}
uint32_t Hash() { return ComputeIntegerHash(number_); }
HashFunction GetHashFunction() { return NumberHash; }
uint32_t StringDictionaryShape::Hash(String* key) {
return key->Hash();
}
Object* GetObject() {
return Heap::NumberFromDouble(number_);
}
bool IsStringKey() { return false; }
uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
return String::cast(other)->Hash();
}
private:
static uint32_t NumberHash(Object* obj) {
return ComputeIntegerHash(ToUint32(obj));
}
static uint32_t ToUint32(Object* obj) {
ASSERT(obj->IsNumber());
return static_cast<uint32_t>(obj->Number());
}
Object* StringDictionaryShape::AsObject(String* key) {
return key;
}
uint32_t number_;
};
// StringKey simply carries a string object as key.
......@@ -6242,12 +6226,12 @@ class StringKey : public HashTableKey {
public:
explicit StringKey(String* string) :
string_(string),
hash_(HashForObject(string)) { }
hash_(StringHash(string)) { }
bool IsMatch(Object* string) {
// We know that all entries in a hash table had their hash keys created.
// Use that knowledge to have fast failure.
if (hash_ != HashForObject(string)) {
if (hash_ != StringHash(string)) {
return false;
}
return string_->Equals(String::cast(string));
......@@ -6255,9 +6239,15 @@ class StringKey : public HashTableKey {
uint32_t Hash() { return hash_; }
uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
HashFunction GetHashFunction() { return StringHash; }
Object* GetObject() { return string_; }
Object* AsObject() { return string_; }
static uint32_t StringHash(Object* obj) {
return String::cast(obj)->Hash();
}
bool IsStringKey() { return true; }
String* string_;
uint32_t hash_;
......@@ -6279,6 +6269,10 @@ class StringSharedKey : public HashTableKey {
return source->Equals(source_);
}
typedef uint32_t (*HashFunction)(Object* obj);
virtual HashFunction GetHashFunction() { return StringSharedHash; }
static uint32_t StringSharedHashHelper(String* source,
SharedFunctionInfo* shared) {
uint32_t hash = source->Hash();
......@@ -6295,18 +6289,18 @@ class StringSharedKey : public HashTableKey {
return hash;
}
uint32_t Hash() {
return StringSharedHashHelper(source_, shared_);
}
uint32_t HashForObject(Object* obj) {
static uint32_t StringSharedHash(Object* obj) {
FixedArray* pair = FixedArray::cast(obj);
SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
String* source = String::cast(pair->get(1));
return StringSharedHashHelper(source, shared);
}
Object* AsObject() {
virtual uint32_t Hash() {
return StringSharedHashHelper(source_, shared_);
}
virtual Object* GetObject() {
Object* obj = Heap::AllocateFixedArray(2);
if (obj->IsFailure()) return obj;
FixedArray* pair = FixedArray::cast(obj);
......@@ -6315,6 +6309,8 @@ class StringSharedKey : public HashTableKey {
return pair;
}
virtual bool IsStringKey() { return false; }
private:
String* source_;
SharedFunctionInfo* shared_;
......@@ -6336,14 +6332,16 @@ class RegExpKey : public HashTableKey {
uint32_t Hash() { return RegExpHash(string_, flags_); }
Object* AsObject() {
HashFunction GetHashFunction() { return RegExpObjectHash; }
Object* GetObject() {
// Plain hash maps, which is where regexp keys are used, don't
// use this function.
UNREACHABLE();
return NULL;
}
uint32_t HashForObject(Object* obj) {
static uint32_t RegExpObjectHash(Object* obj) {
FixedArray* val = FixedArray::cast(obj);
return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
Smi::cast(val->get(JSRegExp::kFlagsIndex)));
......@@ -6353,6 +6351,8 @@ class RegExpKey : public HashTableKey {
return string->Hash() + flags->value();
}
bool IsStringKey() { return false; }
String* string_;
Smi* flags_;
};
......@@ -6367,6 +6367,10 @@ class Utf8SymbolKey : public HashTableKey {
return String::cast(string)->IsEqualTo(string_);
}
HashFunction GetHashFunction() {
return StringHash;
}
uint32_t Hash() {
if (length_field_ != 0) return length_field_ >> String::kHashShift;
unibrow::Utf8InputBuffer<> buffer(string_.start(),
......@@ -6378,15 +6382,17 @@ class Utf8SymbolKey : public HashTableKey {
return result;
}
uint32_t HashForObject(Object* other) {
return String::cast(other)->Hash();
}
Object* AsObject() {
Object* GetObject() {
if (length_field_ == 0) Hash();
return Heap::AllocateSymbol(string_, chars_, length_field_);
}
static uint32_t StringHash(Object* obj) {
return String::cast(obj)->Hash();
}
bool IsStringKey() { return true; }
Vector<const char> string_;
uint32_t length_field_;
int chars_; // Caches the number of characters when computing the hash code.
......@@ -6398,17 +6404,17 @@ class SymbolKey : public HashTableKey {
public:
explicit SymbolKey(String* string) : string_(string) { }
HashFunction GetHashFunction() {
return StringHash;
}
bool IsMatch(Object* string) {
return String::cast(string)->Equals(string_);
}
uint32_t Hash() { return string_->Hash(); }
uint32_t HashForObject(Object* other) {
return String::cast(other)->Hash();
}
Object* AsObject() {
Object* GetObject() {
// If the string is a cons string, attempt to flatten it so that
// symbols will most often be flat strings.
if (StringShape(string_).IsCons()) {
......@@ -6436,27 +6442,28 @@ class SymbolKey : public HashTableKey {
return String::cast(obj)->Hash();
}
bool IsStringKey() { return true; }
String* string_;
};
template<typename Shape, typename Key>
void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) {
template<int prefix_size, int element_size>
void HashTable<prefix_size, element_size>::IteratePrefix(ObjectVisitor* v) {
IteratePointers(v, 0, kElementsStartOffset);
}
template<typename Shape, typename Key>
void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) {
template<int prefix_size, int element_size>
void HashTable<prefix_size, element_size>::IterateElements(ObjectVisitor* v) {
IteratePointers(v,
kElementsStartOffset,
kHeaderSize + length() * kPointerSize);
}
template<typename Shape, typename Key>
Object* HashTable<Shape, Key>::Allocate(
int at_least_space_for) {
template<int prefix_size, int element_size>
Object* HashTable<prefix_size, element_size>::Allocate(int at_least_space_for) {
int capacity = RoundUpToPowerOf2(at_least_space_for);
if (capacity < 4) capacity = 4; // Guarantee min capacity.
Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity));
......@@ -6468,28 +6475,27 @@ Object* HashTable<Shape, Key>::Allocate(
}
// Find entry for key otherwise return -1.
template<typename Shape, typename Key>
int HashTable<Shape, Key>::FindEntry(Key key) {
template <int prefix_size, int element_size>
int HashTable<prefix_size, element_size>::FindEntry(HashTableKey* key) {
uint32_t nof = NumberOfElements();
if (nof == 0) return kNotFound; // Bail out if empty.
uint32_t capacity = Capacity();
uint32_t hash = Shape::Hash(key);
uint32_t hash = key->Hash();
uint32_t entry = GetProbe(hash, 0, capacity);
Object* element = KeyAt(entry);
uint32_t passed_elements = 0;
if (!element->IsNull()) {
if (!element->IsUndefined() && Shape::IsMatch(key, element)) return entry;
if (!element->IsUndefined() && key->IsMatch(element)) return entry;
if (++passed_elements == nof) return kNotFound;
}
for (uint32_t i = 1; !element->IsUndefined(); i++) {
entry = GetProbe(hash, i, capacity);
element = KeyAt(entry);
if (!element->IsNull()) {
if (!element->IsUndefined() && Shape::IsMatch(key, element)) return entry;
if (!element->IsUndefined() && key->IsMatch(element)) return entry;
if (++passed_elements == nof) return kNotFound;
}
}
......@@ -6497,8 +6503,9 @@ int HashTable<Shape, Key>::FindEntry(Key key) {
}
template<typename Shape, typename Key>
Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
template<int prefix_size, int element_size>
Object* HashTable<prefix_size, element_size>::EnsureCapacity(
int n, HashTableKey* key) {
int capacity = Capacity();
int nof = NumberOfElements() + n;
// Make sure 50% is free
......@@ -6510,20 +6517,18 @@ Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
WriteBarrierMode mode = table->GetWriteBarrierMode();
// Copy prefix to new array.
for (int i = kPrefixStartIndex;
i < kPrefixStartIndex + Shape::kPrefixSize;
i++) {
for (int i = kPrefixStartIndex; i < kPrefixStartIndex + prefix_size; i++) {
table->set(i, get(i), mode);
}
// Rehash the elements.
uint32_t (*Hash)(Object* key) = key->GetHashFunction();
for (int i = 0; i < capacity; i++) {
uint32_t from_index = EntryToIndex(i);
Object* k = get(from_index);
if (IsKey(k)) {
uint32_t hash = Shape::HashForObject(key, k);
Object* key = get(from_index);
if (IsKey(key)) {
uint32_t insertion_index =
EntryToIndex(table->FindInsertionEntry(hash));
for (int j = 0; j < Shape::kEntrySize; j++) {
EntryToIndex(table->FindInsertionEntry(key, Hash(key)));
for (int j = 0; j < element_size; j++) {
table->set(insertion_index + j, get(from_index + j), mode);
}
}
......@@ -6533,8 +6538,10 @@ Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
}
template<typename Shape, typename Key>
uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
template<int prefix_size, int element_size>
uint32_t HashTable<prefix_size, element_size>::FindInsertionEntry(
Object* key,
uint32_t hash) {
uint32_t capacity = Capacity();
uint32_t entry = GetProbe(hash, 0, capacity);
Object* element = KeyAt(entry);
......@@ -6547,23 +6554,18 @@ uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
return entry;
}
// Force instantiation of template instances class
template class HashTable<SymbolTableShape, HashTableKey*>;
template class HashTable<CompilationCacheShape, HashTableKey*>;
template class HashTable<MapCacheShape, HashTableKey*>;
// Force instantiation of SymbolTable's base class
template class HashTable<0, 1>;
template class Dictionary<StringDictionaryShape, String*>;
template class Dictionary<NumberDictionaryShape, uint32_t>;
// Force instantiation of Dictionary's base class
template class HashTable<2, 3>;
template Object* Dictionary<NumberDictionaryShape, uint32_t>::Allocate(
int at_least_space_for);
// Force instantiation of EvalCache's base class
template class HashTable<0, 2>;
template Object* Dictionary<StringDictionaryShape, String*>::Allocate(
int at_least_space_for);
// Collates undefined and unexisting elements below limit from position
// zero of the elements. The object stays in Dictionary mode.
......@@ -6572,7 +6574,7 @@ Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
// Must stay in dictionary mode, either because of requires_slow_elements,
// or because we are not going to sort (and therefore compact) all of the
// elements.
NumberDictionary* dict = element_dictionary();
Dictionary* dict = element_dictionary();
HeapNumber* result_double = NULL;
if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
// Allocate space for result before we start mutating the object.
......@@ -6582,9 +6584,9 @@ Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
}
int capacity = dict->Capacity();
Object* obj = NumberDictionary::Allocate(dict->Capacity());
Object* obj = Dictionary::Allocate(dict->Capacity());
if (obj->IsFailure()) return obj;
NumberDictionary* new_dict = NumberDictionary::cast(obj);
Dictionary* new_dict = Dictionary::cast(obj);
AssertNoAllocation no_alloc;
......@@ -6645,7 +6647,7 @@ Object* JSObject::PrepareElementsForSort(uint32_t limit) {
if (!HasFastElements()) {
// Convert to fast elements containing only the existing properties.
// Ordering is irrelevant, since we are going to sort anyway.
NumberDictionary* dict = element_dictionary();
Dictionary* dict = element_dictionary();
if (IsJSArray() || dict->requires_slow_elements() ||
dict->max_number_key() >= limit) {
return PrepareSlowElementsForSort(limit);
......@@ -6785,7 +6787,7 @@ Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
if (obj->IsFailure()) return obj;
// Create symbol object.
Object* symbol = key->AsObject();
Object* symbol = key->GetObject();
if (symbol->IsFailure()) return symbol;
// If the symbol table grew as part of EnsureCapacity, obj is not
......@@ -6794,7 +6796,7 @@ Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
SymbolTable* table = reinterpret_cast<SymbolTable*>(obj);
// Add the new symbol and return it along with the symbol table.
entry = table->FindInsertionEntry(key->Hash());
entry = table->FindInsertionEntry(symbol, key->Hash());
table->set(EntryToIndex(entry), symbol);
table->ElementAdded();
*s = symbol;
......@@ -6834,7 +6836,7 @@ Object* CompilationCacheTable::Put(String* src, Object* value) {
CompilationCacheTable* cache =
reinterpret_cast<CompilationCacheTable*>(obj);
int entry = cache->FindInsertionEntry(key.Hash());
int entry = cache->FindInsertionEntry(src, key.Hash());
cache->set(EntryToIndex(entry), src);
cache->set(EntryToIndex(entry) + 1, value);
cache->ElementAdded();
......@@ -6851,9 +6853,9 @@ Object* CompilationCacheTable::PutEval(String* src,
CompilationCacheTable* cache =
reinterpret_cast<CompilationCacheTable*>(obj);
int entry = cache->FindInsertionEntry(key.Hash());
int entry = cache->FindInsertionEntry(src, key.Hash());
Object* k = key.AsObject();
Object* k = key.GetObject();
if (k->IsFailure()) return k;
cache->set(EntryToIndex(entry), k);
......@@ -6872,7 +6874,7 @@ Object* CompilationCacheTable::PutRegExp(String* src,
CompilationCacheTable* cache =
reinterpret_cast<CompilationCacheTable*>(obj);
int entry = cache->FindInsertionEntry(key.Hash());
int entry = cache->FindInsertionEntry(value, key.Hash());
cache->set(EntryToIndex(entry), value);
cache->set(EntryToIndex(entry) + 1, value);
cache->ElementAdded();
......@@ -6895,9 +6897,13 @@ class SymbolsKey : public HashTableKey {
return true;
}
uint32_t Hash() { return HashForObject(symbols_); }
uint32_t Hash() { return SymbolsHash(symbols_); }
HashFunction GetHashFunction() { return SymbolsHash; }
uint32_t HashForObject(Object* obj) {
Object* GetObject() { return symbols_; }
static uint32_t SymbolsHash(Object* obj) {
FixedArray* symbols = FixedArray::cast(obj);
int len = symbols->length();
uint32_t hash = 0;
......@@ -6907,7 +6913,7 @@ class SymbolsKey : public HashTableKey {
return hash;
}
Object* AsObject() { return symbols_; }
bool IsStringKey() { return false; }
private:
FixedArray* symbols_;
......@@ -6928,7 +6934,7 @@ Object* MapCache::Put(FixedArray* array, Map* value) {
if (obj->IsFailure()) return obj;
MapCache* cache = reinterpret_cast<MapCache*>(obj);
int entry = cache->FindInsertionEntry(key.Hash());
int entry = cache->FindInsertionEntry(array, key.Hash());
cache->set(EntryToIndex(entry), array);
cache->set(EntryToIndex(entry) + 1, value);
cache->ElementAdded();
......@@ -6936,21 +6942,19 @@ Object* MapCache::Put(FixedArray* array, Map* value) {
}
template<typename Shape, typename Key>
Object* Dictionary<Shape, Key>::Allocate(int at_least_space_for) {
Object* obj = HashTable<Shape, Key>::Allocate(at_least_space_for);
Object* Dictionary::Allocate(int at_least_space_for) {
Object* obj = DictionaryBase::Allocate(at_least_space_for);
// Initialize the next enumeration index.
if (!obj->IsFailure()) {
Dictionary<Shape, Key>::cast(obj)->
Dictionary::cast(obj)->
SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
}
return obj;
}
template<typename Shape, typename Key>
Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
int length = HashTable<Shape, Key>::NumberOfElements();
Object* Dictionary::GenerateNewEnumerationIndices() {
int length = NumberOfElements();
// Allocate and initialize iteration order array.
Object* obj = Heap::AllocateFixedArray(length);
......@@ -6966,10 +6970,10 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
FixedArray* enumeration_order = FixedArray::cast(obj);
// Fill the enumeration order array with property details.
int capacity = HashTable<Shape, Key>::Capacity();
int capacity = Capacity();
int pos = 0;
for (int i = 0; i < capacity; i++) {
if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
if (IsKey(KeyAt(i))) {
enumeration_order->set(pos++,
Smi::FromInt(DetailsAt(i).index()),
SKIP_WRITE_BARRIER);
......@@ -6989,10 +6993,10 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
}
// Update the dictionary with new indices.
capacity = HashTable<Shape, Key>::Capacity();
capacity = Capacity();
pos = 0;
for (int i = 0; i < capacity; i++) {
if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
if (IsKey(KeyAt(i))) {
int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
PropertyDetails details = DetailsAt(i);
PropertyDetails new_details =
......@@ -7006,20 +7010,20 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
return this;
}
template<typename Shape, typename Key>
Object* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
Object* Dictionary::EnsureCapacity(int n, HashTableKey* key) {
// Check whether there are enough enumeration indices to add n elements.
if (Shape::kIsEnumerable &&
if (key->IsStringKey() &&
!PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
// If not, we generate new indices for the properties.
Object* result = GenerateNewEnumerationIndices();
if (result->IsFailure()) return result;
}
return HashTable<Shape, Key>::EnsureCapacity(n, key);
return DictionaryBase::EnsureCapacity(n, key);
}
void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
void Dictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
// Do nothing if the interval [from, to) is empty.
if (from >= to) return;
......@@ -7041,26 +7045,36 @@ void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
SetNumberOfElements(NumberOfElements() - removed_entries);
}
template<typename Shape, typename Key>
Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
JSObject::DeleteMode mode) {
Object* Dictionary::DeleteProperty(int entry, JSObject::DeleteMode mode) {
PropertyDetails details = DetailsAt(entry);
// Ignore attributes if forcing a deletion.
if (details.IsDontDelete() && mode == JSObject::NORMAL_DELETION) {
return Heap::false_value();
}
SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0));
HashTable<Shape, Key>::ElementRemoved();
ElementRemoved();
return Heap::true_value();
}
template<typename Shape, typename Key>
Object* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
int Dictionary::FindStringEntry(String* key) {
StringKey k(key);
return FindEntry(&k);
}
int Dictionary::FindNumberEntry(uint32_t index) {
NumberKey k(index);
return FindEntry(&k);
}
Object* Dictionary::AtPut(HashTableKey* key, Object* value) {
int entry = FindEntry(key);
// If the entry is present set the value;
if (entry != Dictionary<Shape, Key>::kNotFound) {
if (entry != kNotFound) {
ValueAtPut(entry, value);
return this;
}
......@@ -7068,57 +7082,48 @@ Object* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
// Check whether the dictionary should be extended.
Object* obj = EnsureCapacity(1, key);
if (obj->IsFailure()) return obj;
Object* k = Shape::AsObject(key);
Object* k = key->GetObject();
if (k->IsFailure()) return k;
PropertyDetails details = PropertyDetails(NONE, NORMAL);
return Dictionary<Shape, Key>::cast(obj)->
AddEntry(key, value, details, Shape::Hash(key));
Dictionary::cast(obj)->AddEntry(k, value, details, key->Hash());
return obj;
}
template<typename Shape, typename Key>
Object* Dictionary<Shape, Key>::Add(Key key,
Object* value,
PropertyDetails details) {
// Valdate key is absent.
SLOW_ASSERT((FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
Object* Dictionary::Add(HashTableKey* key, Object* value,
PropertyDetails details) {
// Check whether the dictionary should be extended.
Object* obj = EnsureCapacity(1, key);
if (obj->IsFailure()) return obj;
return Dictionary<Shape, Key>::cast(obj)->
AddEntry(key, value, details, Shape::Hash(key));
// Compute the key object.
Object* k = key->GetObject();
if (k->IsFailure()) return k;
Dictionary::cast(obj)->AddEntry(k, value, details, key->Hash());
return obj;
}
// Add a key, value pair to the dictionary.
template<typename Shape, typename Key>
Object* Dictionary<Shape, Key>::AddEntry(Key key,
Object* value,
PropertyDetails details,
uint32_t hash) {
// Compute the key object.
Object* k = Shape::AsObject(key);
if (k->IsFailure()) return k;
uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
void Dictionary::AddEntry(Object* key,
Object* value,
PropertyDetails details,
uint32_t hash) {
uint32_t entry = FindInsertionEntry(key, hash);
// Insert element at empty or deleted entry
if (details.index() == 0 && Shape::kIsEnumerable) {
if (details.index() == 0 && key->IsString()) {
// Assign an enumeration index to the property and update
// SetNextEnumerationIndex.
int index = NextEnumerationIndex();
details = PropertyDetails(details.attributes(), details.type(), index);
SetNextEnumerationIndex(index + 1);
}
SetEntry(entry, k, value, details);
ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
|| Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
HashTable<Shape, Key>::ElementAdded();
return this;
SetEntry(entry, key, value, details);
ASSERT(KeyAt(entry)->IsNumber() || KeyAt(entry)->IsString());
ElementAdded();
}
void NumberDictionary::UpdateMaxNumberKey(uint32_t key) {
void Dictionary::UpdateMaxNumberKey(uint32_t key) {
// If the dictionary requires slow elements an element has already
// been added at a high index.
if (requires_slow_elements()) return;
......@@ -7131,51 +7136,73 @@ void NumberDictionary::UpdateMaxNumberKey(uint32_t key) {
// Update max key value.
Object* max_index_object = get(kMaxNumberKeyIndex);
if (!max_index_object->IsSmi() || max_number_key() < key) {
FixedArray::set(kMaxNumberKeyIndex,
Smi::FromInt(key << kRequiresSlowElementsTagSize),
SKIP_WRITE_BARRIER);
set(kMaxNumberKeyIndex,
Smi::FromInt(key << kRequiresSlowElementsTagSize),
SKIP_WRITE_BARRIER);
}
}
Object* NumberDictionary::AddNumberEntry(uint32_t key,
Object* value,
PropertyDetails details) {
Object* Dictionary::AddStringEntry(String* key,
Object* value,
PropertyDetails details) {
StringKey k(key);
SLOW_ASSERT(FindEntry(&k) == kNotFound);
return Add(&k, value, details);
}
Object* Dictionary::AddNumberEntry(uint32_t key,
Object* value,
PropertyDetails details) {
NumberKey k(key);
UpdateMaxNumberKey(key);
SLOW_ASSERT(FindEntry(key) == kNotFound);
return Add(key, value, details);
SLOW_ASSERT(FindEntry(&k) == kNotFound);
return Add(&k, value, details);
}
Object* NumberDictionary::AtNumberPut(uint32_t key, Object* value) {
Object* Dictionary::AtNumberPut(uint32_t key, Object* value) {
NumberKey k(key);
UpdateMaxNumberKey(key);
return AtPut(key, value);
return AtPut(&k, value);
}
Object* NumberDictionary::Set(uint32_t key,
Object* value,
PropertyDetails details) {
int entry = FindEntry(key);
if (entry == kNotFound) return AddNumberEntry(key, value, details);
Object* Dictionary::SetStringEntry(int entry,
String* key,
Object* value,
PropertyDetails details) {
// Preserve enumeration index.
details = PropertyDetails(details.attributes(),
details.type(),
DetailsAt(entry).index());
SetEntry(entry, NumberDictionaryShape::AsObject(key), value, details);
SetEntry(entry, key, value, details);
return this;
}
Object* Dictionary::SetOrAddNumberEntry(uint32_t key,
Object* value,
PropertyDetails details) {
NumberKey k(key);
int entry = FindEntry(&k);
if (entry == -1) return AddNumberEntry(key, value, details);
// Preserve enumeration index.
details = PropertyDetails(details.attributes(),
details.type(),
DetailsAt(entry).index());
SetEntry(entry, k.GetObject(), value, details);
return this;
}
template<typename Shape, typename Key>
int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
PropertyAttributes filter) {
int capacity = HashTable<Shape, Key>::Capacity();
int Dictionary::NumberOfElementsFilterAttributes(PropertyAttributes filter) {
int capacity = Capacity();
int result = 0;
for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) {
Object* k = KeyAt(i);
if (IsKey(k)) {
PropertyAttributes attr = DetailsAt(i).attributes();
if ((attr & filter) == 0) result++;
}
......@@ -7184,22 +7211,19 @@ int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
}
template<typename Shape, typename Key>
int Dictionary<Shape, Key>::NumberOfEnumElements() {
int Dictionary::NumberOfEnumElements() {
return NumberOfElementsFilterAttributes(
static_cast<PropertyAttributes>(DONT_ENUM));
}
template<typename Shape, typename Key>
void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage,
PropertyAttributes filter) {
void Dictionary::CopyKeysTo(FixedArray* storage, PropertyAttributes filter) {
ASSERT(storage->length() >= NumberOfEnumElements());
int capacity = HashTable<Shape, Key>::Capacity();
int capacity = Capacity();
int index = 0;
for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) {
Object* k = KeyAt(i);
if (IsKey(k)) {
PropertyAttributes attr = DetailsAt(i).attributes();
if ((attr & filter) == 0) storage->set(index++, k);
}
......@@ -7209,8 +7233,7 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage,
}
void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
FixedArray* sort_array) {
void Dictionary::CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array) {
ASSERT(storage->length() >= NumberOfEnumElements());
int capacity = Capacity();
int index = 0;
......@@ -7232,15 +7255,14 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
}
template<typename Shape, typename Key>
void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) {
void Dictionary::CopyKeysTo(FixedArray* storage) {
ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
static_cast<PropertyAttributes>(NONE)));
int capacity = HashTable<Shape, Key>::Capacity();
int capacity = Capacity();
int index = 0;
for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) {
Object* k = KeyAt(i);
if (IsKey(k)) {
storage->set(index++, k);
}
}
......@@ -7249,12 +7271,11 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) {
// Backwards lookup (slow).
template<typename Shape, typename Key>
Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
int capacity = HashTable<Shape, Key>::Capacity();
Object* Dictionary::SlowReverseLookup(Object* value) {
int capacity = Capacity();
for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i);
if (Dictionary<Shape, Key>::IsKey(k)) {
Object* k = KeyAt(i);
if (IsKey(k)) {
Object* e = ValueAt(i);
if (e->IsJSGlobalPropertyCell()) {
e = JSGlobalPropertyCell::cast(e)->value();
......@@ -7266,8 +7287,8 @@ Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
}
Object* StringDictionary::TransformPropertiesToFastFor(
JSObject* obj, int unused_property_fields) {
Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
int unused_property_fields) {
// Make sure we preserve dictionary representation if there are too many
// descriptors.
if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj;
......@@ -7275,8 +7296,7 @@ Object* StringDictionary::TransformPropertiesToFastFor(
// Figure out if it is necessary to generate new enumeration indices.
int max_enumeration_index =
NextEnumerationIndex() +
(DescriptorArray::kMaxNumberOfDescriptors -
NumberOfElements());
(DescriptorArray::kMaxNumberOfDescriptors - NumberOfElements());
if (!PropertyDetails::IsValidIndex(max_enumeration_index)) {
Object* result = GenerateNewEnumerationIndices();
if (result->IsFailure()) return result;
......@@ -7625,5 +7645,4 @@ int BreakPointInfo::GetBreakPointCount() {
}
#endif
} } // namespace v8::internal
......@@ -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 StringDictionary* property_dictionary(); // Gets slow properties.
inline Dictionary* 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 NumberDictionary* element_dictionary(); // Gets slow elements.
inline Dictionary* element_dictionary(); // Gets slow elements.
// Collects elements starting at index 0.
// Undefined values are placed after non-undefined values.
......@@ -1875,29 +1875,32 @@ 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 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 = ..;
// };
// 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
// 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.
template<typename Shape, typename Key>
// 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>
class HashTable: public FixedArray {
public:
// Returns the number of elements in the dictionary.
......@@ -1946,27 +1949,25 @@ class HashTable: public FixedArray {
static const int kNumberOfElementsIndex = 0;
static const int kCapacityIndex = 1;
static const int kPrefixStartIndex = 2;
static const int kElementsStartIndex =
kPrefixStartIndex + Shape::kPrefixSize;
static const int kEntrySize = Shape::kEntrySize;
static const int kElementsStartIndex = kPrefixStartIndex + prefix_size;
static const int kElementSize = element_size;
static const int kElementsStartOffset =
kHeaderSize + kElementsStartIndex * kPointerSize;
// Constant used for denoting a absent entry.
static const int kNotFound = -1;
// Find entry for key otherwise return -1.
int FindEntry(Key key);
protected:
// Find entry for key otherwise return -1.
int FindEntry(HashTableKey* key);
// Find the entry at which to insert element with the given key that
// has the given hash value.
uint32_t FindInsertionEntry(uint32_t hash);
uint32_t FindInsertionEntry(Object* key, uint32_t hash);
// Returns the index for an entry (of the key)
static inline int EntryToIndex(int entry) {
return (entry * kEntrySize) + kElementsStartIndex;
return (entry * kElementSize) + kElementsStartIndex;
}
// Update the number of elements in the dictionary.
......@@ -1991,51 +1992,15 @@ class HashTable: public FixedArray {
}
// Ensure enough space for n additional elements.
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() {}
Object* EnsureCapacity(int n, HashTableKey* key);
};
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<SymbolTableShape, HashTableKey*> {
class SymbolTable: public HashTable<0, 1> {
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
......@@ -2059,33 +2024,11 @@ class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
};
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<MapCacheShape, HashTableKey*> {
class MapCache: public HashTable<0, 2> {
public:
// Find cached value for a string key, otherwise return null.
Object* Lookup(FixedArray* key);
......@@ -2097,42 +2040,74 @@ class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
};
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);
}
// 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 {
public:
// Returns the value at entry.
Object* ValueAt(int entry) {
return get(HashTable<Shape, Key>::EntryToIndex(entry)+1);
return get(EntryToIndex(entry)+1);
}
// Set the value for entry.
void ValueAtPut(int entry, Object* value) {
set(HashTable<Shape, Key>::EntryToIndex(entry)+1, value);
set(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(HashTable<Shape, Key>::EntryToIndex(entry) + 2)));
return PropertyDetails(Smi::cast(get(EntryToIndex(entry) + 2)));
}
// Set the details for entry.
void DetailsAtPut(int entry, PropertyDetails value) {
set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi());
set(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);
......@@ -2142,23 +2117,42 @@ class Dictionary: public HashTable<Shape, Key> {
// 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);
// For transforming properties of a JSObject.
Object* TransformPropertiesToFastFor(JSObject* obj,
int unused_property_fields);
// If slow elements are required we will never go back to fast-case
// for the elements kept in this dictionary. We require slow
// elements if an element has been added at an index larger than
// kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
// when defining a getter or setter with a number key.
inline bool requires_slow_elements();
inline void set_requires_slow_elements();
// Get the value of the max number key that has been added to this
// dictionary. max_number_key can only be called if
// 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(FixedArray::get(kNextEnumerationIndexIndex))->value();
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, Key key);
Object* EnsureCapacity(int n, HashTableKey* key);
#ifdef DEBUG
void Print();
......@@ -2166,110 +2160,38 @@ class Dictionary: public HashTable<Shape, Key> {
// 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);
// Bit masks.
static const int kRequiresSlowElementsMask = 1;
static const int kRequiresSlowElementsTagSize = 1;
static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
Object* Add(Key key, Object* value, PropertyDetails details);
void UpdateMaxNumberKey(uint32_t key);
protected:
private:
// Generic at put operation.
Object* AtPut(Key key, Object* value);
Object* AtPut(HashTableKey* key, Object* value);
Object* Add(HashTableKey* key, Object* value, PropertyDetails details);
// Add entry to dictionary.
Object* AddEntry(Key key,
Object* value,
PropertyDetails details,
uint32_t hash);
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 =
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
// elements if an element has been added at an index larger than
// kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
// when defining a getter or setter with a number key.
inline bool requires_slow_elements();
inline void set_requires_slow_elements();
// Get the value of the max number key that has been added to this
// dictionary. max_number_key can only be called if
// requires_slow_elements returns false.
inline uint32_t max_number_key();
// Remove all entries were key is a number and (from <= key && key < to).
void RemoveNumberEntries(uint32_t from, uint32_t to);
static const int kMaxNumberKeyIndex = kPrefixStartIndex;
static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
// Bit masks.
static const int kRequiresSlowElementsMask = 1;
static const int kRequiresSlowElementsTagSize = 1;
static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary);
};
......@@ -3309,30 +3231,7 @@ class JSRegExp: public JSObject {
};
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*> {
class CompilationCacheTable: public HashTable<0, 2> {
public:
// Find cached value for a string key, otherwise return null.
Object* Lookup(String* src);
......
......@@ -168,7 +168,7 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
}
}
} else {
NumberDictionary* element_dictionary = copy->element_dictionary();
Dictionary* 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.
StringDictionary* dictionary = receiver->property_dictionary();
int entry = dictionary->FindEntry(key);
if ((entry != StringDictionary::kNotFound) &&
Dictionary* dictionary = receiver->property_dictionary();
int entry = dictionary->FindStringEntry(key);
if ((entry != Dictionary::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<NumberDictionary> dict = Handle<NumberDictionary>::cast(storage_);
Handle<NumberDictionary> result =
Handle<Dictionary> dict = Handle<Dictionary>::cast(storage_);
Handle<Dictionary> 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<NumberDictionary> dict(receiver->element_dictionary());
Handle<Dictionary> 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::NewNumberDictionary(at_least_space_for));
Factory::NewDictionary(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(NumberDictionary::cast(elements)->NumberOfElements());
return Smi::FromInt(Dictionary::cast(elements)->NumberOfElements());
} else {
return array->length();
}
......
......@@ -562,8 +562,8 @@ Object* StubCache::ComputeCallGlobal(int argc,
static Object* GetProbeValue(Code::Flags flags) {
NumberDictionary* dictionary = Heap::non_monomorphic_cache();
int entry = dictionary->FindEntry(flags);
Dictionary* dictionary = Heap::non_monomorphic_cache();
int entry = dictionary->FindNumberEntry(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(NumberDictionary::cast(result));
Heap::set_non_monomorphic_cache(Dictionary::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()->FindEntry(
Heap::non_monomorphic_cache()->FindNumberEntry(
Code::cast(code)->flags());
// The entry must be present see comment in ProbeCache.
ASSERT(entry != -1);
......
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