Fixed arm/mac errors and presubmitting 2324.
authorbak@chromium.org <bak@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 2 Jul 2009 06:50:43 +0000 (06:50 +0000)
committerbak@chromium.org <bak@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 2 Jul 2009 06:50:43 +0000 (06:50 +0000)
Review URL: http://codereview.chromium.org/151193

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2328 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

15 files changed:
src/arm/ic-arm.cc
src/bootstrapper.cc
src/code-stubs.cc
src/factory.cc
src/factory.h
src/globals.h
src/heap.cc
src/heap.h
src/ia32/ic-ia32.cc
src/objects-debug.cc
src/objects-inl.h
src/objects.cc
src/objects.h
src/runtime.cc
src/stub-cache.cc

index 5519771..3b4f5a5 100644 (file)
@@ -85,13 +85,13 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
 
   // Compute the capacity mask.
   const int kCapacityOffset =
-      Array::kHeaderSize + Dictionary::kCapacityIndex * kPointerSize;
+      Array::kHeaderSize + StringDictionary::kCapacityIndex * kPointerSize;
   __ ldr(r3, FieldMemOperand(t0, kCapacityOffset));
   __ mov(r3, Operand(r3, ASR, kSmiTagSize));  // convert smi to int
   __ sub(r3, r3, Operand(1));
 
   const int kElementsStartOffset =
-      Array::kHeaderSize + Dictionary::kElementsStartIndex * kPointerSize;
+      Array::kHeaderSize + StringDictionary::kElementsStartIndex * kPointerSize;
 
   // Generate an unrolled loop that performs a few probes before
   // giving up. Measurements done on Gmail indicate that 2 probes
@@ -102,12 +102,12 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
     __ ldr(t1, FieldMemOperand(r2, String::kLengthOffset));
     __ mov(t1, Operand(t1, LSR, String::kHashShift));
     if (i > 0) {
-      __ add(t1, t1, Operand(Dictionary::GetProbeOffset(i)));
+      __ add(t1, t1, Operand(StringDictionary::GetProbeOffset(i)));
     }
     __ and_(t1, t1, Operand(r3));
 
     // Scale the index by multiplying by the element size.
-    ASSERT(Dictionary::kElementSize == 3);
+    ASSERT(StringDictionary::kEntrySize == 3);
     __ add(t1, t1, Operand(t1, LSL, 1));  // t1 = t1 * 3
 
     // Check if the key is identical to the name.
index f3c7c5f..3adc051 100644 (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));
index ee60332..37bc707 100644 (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)));
 }
index 216a07e..4d7a957 100644 (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);
 }
 
 
index 1ec9f1b..90fb29c 100644 (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);
index bf83d0d..8088331 100644 (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;
index 4a317e3..749013a 100644 (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;
 }
 
index 77cea1b..0f00ccd 100644 (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;
   }
 
index 004dad2..fa76dff 100644 (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.
index 85b975b..652a0e9 100644 (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();
index c360fd7..c0f3174 100644 (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) {
-  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());
+template<typename Shape, typename Key>
+void Dictionary<Shape, Key>::SetEntry(int entry,
+                                      Object* key,
+                                      Object* value,
+                                      PropertyDetails details) {
+  ASSERT(!Shape::kIsEnumerable || 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());
 }
 
 
index a967e7b..496fb35 100644 (file)
@@ -41,6 +41,7 @@
 #include "disassembler.h"
 #endif
 
+
 namespace v8 {
 namespace internal {
 
@@ -428,17 +429,17 @@ Object* JSObject::SetNormalizedProperty(String* name,
                                         Object* value,
                                         PropertyDetails details) {
   ASSERT(!HasFastProperties());
-  int entry = property_dictionary()->FindStringEntry(name);
-  if (entry == Dictionary::kNotFound) {
+  int entry = property_dictionary()->FindEntry(name);
+  if (entry == StringDictionary::kNotFound) {
     Object* store_value = value;
     if (IsGlobalObject()) {
       store_value = Heap::AllocateJSGlobalPropertyCell(value);
       if (store_value->IsFailure()) return store_value;
     }
     Object* dict =
-        property_dictionary()->AddStringEntry(name, store_value, details);
+        property_dictionary()->Add(name, store_value, details);
     if (dict->IsFailure()) return dict;
-    set_properties(Dictionary::cast(dict));
+    set_properties(StringDictionary::cast(dict));
     return value;
   }
   // Preserve enumeration index.
@@ -452,7 +453,7 @@ Object* JSObject::SetNormalizedProperty(String* name,
     // Please note we have to update the property details.
     property_dictionary()->DetailsAtPut(entry, details);
   } else {
-    property_dictionary()->SetStringEntry(entry, name, value, details);
+    property_dictionary()->SetEntry(entry, name, value, details);
   }
   return value;
 }
@@ -460,9 +461,9 @@ Object* JSObject::SetNormalizedProperty(String* name,
 
 Object* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) {
   ASSERT(!HasFastProperties());
-  Dictionary* dictionary = property_dictionary();
-  int entry = dictionary->FindStringEntry(name);
-  if (entry != Dictionary::kNotFound) {
+  StringDictionary* dictionary = property_dictionary();
+  int entry = dictionary->FindEntry(name);
+  if (entry != StringDictionary::kNotFound) {
     // If we have a global object set the cell to the hole.
     if (IsGlobalObject()) {
       PropertyDetails details = dictionary->DetailsAt(entry);
@@ -1340,16 +1341,20 @@ Object* JSObject::AddSlowProperty(String* name,
                                   Object* value,
                                   PropertyAttributes attributes) {
   ASSERT(!HasFastProperties());
-  Dictionary* dict = property_dictionary();
+  StringDictionary* dict = property_dictionary();
   Object* store_value = value;
   if (IsGlobalObject()) {
     // In case name is an orphaned property reuse the cell.
-    int entry = dict->FindStringEntry(name);
-    if (entry != Dictionary::kNotFound) {
+    int entry = dict->FindEntry(name);
+    if (entry != StringDictionary::kNotFound) {
       store_value = dict->ValueAt(entry);
       JSGlobalPropertyCell::cast(store_value)->set_value(value);
-      PropertyDetails details = PropertyDetails(attributes, NORMAL);
-      dict->SetStringEntry(entry, name, store_value, details);
+      // Assign an enumeration index to the property and update
+      // SetNextEnumerationIndex.
+      int index = dict->NextEnumerationIndex();
+      PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
+      dict->SetNextEnumerationIndex(index + 1);
+      dict->SetEntry(entry, name, store_value, details);
       return value;
     }
     store_value = Heap::AllocateJSGlobalPropertyCell(value);
@@ -1357,9 +1362,9 @@ Object* JSObject::AddSlowProperty(String* name,
     JSGlobalPropertyCell::cast(store_value)->set_value(value);
   }
   PropertyDetails details = PropertyDetails(attributes, NORMAL);
-  Object* result = dict->AddStringEntry(name, store_value, details);
+  Object* result = dict->Add(name, store_value, details);
   if (result->IsFailure()) return result;
-  if (dict != result) set_properties(Dictionary::cast(result));
+  if (dict != result) set_properties(StringDictionary::cast(result));
   return value;
 }
 
@@ -1405,8 +1410,8 @@ Object* JSObject::SetPropertyPostInterceptor(String* name,
 Object* JSObject::ReplaceSlowProperty(String* name,
                                        Object* value,
                                        PropertyAttributes attributes) {
-  Dictionary* dictionary = property_dictionary();
-  int old_index = dictionary->FindStringEntry(name);
+  StringDictionary* dictionary = property_dictionary();
+  int old_index = dictionary->FindEntry(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.
@@ -1646,9 +1651,9 @@ Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) {
        pt != Heap::null_value();
        pt = pt->GetPrototype()) {
     if (JSObject::cast(pt)->HasFastElements()) continue;
-    Dictionary* dictionary = JSObject::cast(pt)->element_dictionary();
-    int entry = dictionary->FindNumberEntry(index);
-    if (entry != Dictionary::kNotFound) {
+    NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary();
+    int entry = dictionary->FindEntry(index);
+    if (entry != StringDictionary::kNotFound) {
       Object* element = dictionary->ValueAt(entry);
       PropertyDetails details = dictionary->DetailsAt(entry);
       if (details.type() == CALLBACKS) {
@@ -1698,8 +1703,8 @@ void JSObject::LocalLookupRealNamedProperty(String* name,
       return;
     }
   } else {
-    int entry = property_dictionary()->FindStringEntry(name);
-    if (entry != Dictionary::kNotFound) {
+    int entry = property_dictionary()->FindEntry(name);
+    if (entry != StringDictionary::kNotFound) {
       // Make sure to disallow caching for uninitialized constants
       // found in the dictionary-mode objects.
       Object* value = property_dictionary()->ValueAt(entry);
@@ -2101,9 +2106,9 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
 
   // Allocate new content
   Object* obj =
-      Dictionary::Allocate(map()->NumberOfDescribedProperties() * 2 + 4);
+      StringDictionary::Allocate(map()->NumberOfDescribedProperties() * 2 + 4);
   if (obj->IsFailure()) return obj;
-  Dictionary* dictionary = Dictionary::cast(obj);
+  StringDictionary* dictionary = StringDictionary::cast(obj);
 
   for (DescriptorReader r(map()->instance_descriptors());
        !r.eos();
@@ -2118,9 +2123,9 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
           value = Heap::AllocateJSGlobalPropertyCell(value);
           if (value->IsFailure()) return value;
         }
-        Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
+        Object* result = dictionary->Add(r.GetKey(), value, d);
         if (result->IsFailure()) return result;
-        dictionary = Dictionary::cast(result);
+        dictionary = StringDictionary::cast(result);
         break;
       }
       case FIELD: {
@@ -2131,9 +2136,9 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
           value = Heap::AllocateJSGlobalPropertyCell(value);
           if (value->IsFailure()) return value;
         }
-        Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
+        Object* result = dictionary->Add(r.GetKey(), value, d);
         if (result->IsFailure()) return result;
-        dictionary = Dictionary::cast(result);
+        dictionary = StringDictionary::cast(result);
         break;
       }
       case CALLBACKS: {
@@ -2144,9 +2149,9 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
           value = Heap::AllocateJSGlobalPropertyCell(value);
           if (value->IsFailure()) return value;
         }
-        Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
+        Object* result = dictionary->Add(r.GetKey(), value, d);
         if (result->IsFailure()) return result;
-        dictionary = Dictionary::cast(result);
+        dictionary = StringDictionary::cast(result);
         break;
       }
       case MAP_TRANSITION:
@@ -2219,9 +2224,9 @@ Object* JSObject::NormalizeElements() {
   int length = IsJSArray() ?
                Smi::cast(JSArray::cast(this)->length())->value() :
                array->length();
-  Object* obj = Dictionary::Allocate(length);
+  Object* obj = NumberDictionary::Allocate(length);
   if (obj->IsFailure()) return obj;
-  Dictionary* dictionary = Dictionary::cast(obj);
+  NumberDictionary* dictionary = NumberDictionary::cast(obj);
   // Copy entries.
   for (int i = 0; i < length; i++) {
     Object* value = array->get(i);
@@ -2229,7 +2234,7 @@ Object* JSObject::NormalizeElements() {
       PropertyDetails details = PropertyDetails(NONE, NORMAL);
       Object* result = dictionary->AddNumberEntry(i, array->get(i), details);
       if (result->IsFailure()) return result;
-      dictionary = Dictionary::cast(result);
+      dictionary = NumberDictionary::cast(result);
     }
   }
   // Switch to using the dictionary as the backing storage for elements.
@@ -2306,9 +2311,9 @@ Object* JSObject::DeleteElementPostInterceptor(uint32_t index,
     return Heap::true_value();
   }
   ASSERT(!HasFastElements());
-  Dictionary* dictionary = element_dictionary();
-  int entry = dictionary->FindNumberEntry(index);
-  if (entry != Dictionary::kNotFound) {
+  NumberDictionary* dictionary = element_dictionary();
+  int entry = dictionary->FindEntry(index);
+  if (entry != NumberDictionary::kNotFound) {
     return dictionary->DeleteProperty(entry, mode);
   }
   return Heap::true_value();
@@ -2380,9 +2385,9 @@ Object* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
     }
     return Heap::true_value();
   } else {
-    Dictionary* dictionary = element_dictionary();
-    int entry = dictionary->FindNumberEntry(index);
-    if (entry != Dictionary::kNotFound) {
+    NumberDictionary* dictionary = element_dictionary();
+    int entry = dictionary->FindEntry(index);
+    if (entry != NumberDictionary::kNotFound) {
       return dictionary->DeleteProperty(entry, mode);
     }
   }
@@ -2687,9 +2692,9 @@ Object* JSObject::DefineGetterSetter(String* name,
   if (is_element) {
     // Lookup the index.
     if (!HasFastElements()) {
-      Dictionary* dictionary = element_dictionary();
-      int entry = dictionary->FindNumberEntry(index);
-      if (entry != Dictionary::kNotFound) {
+      NumberDictionary* dictionary = element_dictionary();
+      int entry = dictionary->FindEntry(index);
+      if (entry != NumberDictionary::kNotFound) {
         Object* result = dictionary->ValueAt(entry);
         PropertyDetails details = dictionary->DetailsAt(entry);
         if (details.IsReadOnly()) return Heap::undefined_value();
@@ -2725,14 +2730,14 @@ Object* JSObject::DefineGetterSetter(String* name,
 
     // Update the dictionary with the new CALLBACKS property.
     Object* dict =
-        element_dictionary()->SetOrAddNumberEntry(index, structure, details);
+        element_dictionary()->Set(index, structure, details);
     if (dict->IsFailure()) return dict;
 
     // If name is an index we need to stay in slow case.
-    Dictionary* elements = Dictionary::cast(dict);
+    NumberDictionary* elements = NumberDictionary::cast(dict);
     elements->set_requires_slow_elements();
     // Set the potential new dictionary on the object.
-    set_elements(Dictionary::cast(dict));
+    set_elements(NumberDictionary::cast(dict));
   } else {
     // Normalize object to make this operation simple.
     Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
@@ -2799,9 +2804,9 @@ Object* JSObject::LookupAccessor(String* name, bool is_getter) {
          obj = JSObject::cast(obj)->GetPrototype()) {
       JSObject* jsObject = JSObject::cast(obj);
       if (!jsObject->HasFastElements()) {
-        Dictionary* dictionary = jsObject->element_dictionary();
-        int entry = dictionary->FindNumberEntry(index);
-        if (entry != Dictionary::kNotFound) {
+        NumberDictionary* dictionary = jsObject->element_dictionary();
+        int entry = dictionary->FindEntry(index);
+        if (entry != NumberDictionary::kNotFound) {
           Object* element = dictionary->ValueAt(entry);
           PropertyDetails details = dictionary->DetailsAt(entry);
           if (details.type() == CALLBACKS) {
@@ -3004,7 +3009,7 @@ Object* FixedArray::AddKeysFromJSArray(JSArray* array) {
     return UnionOfKeys(array->elements());
   }
   ASSERT(!array->HasFastElements());
-  Dictionary* dict = array->element_dictionary();
+  NumberDictionary* dict = array->element_dictionary();
   int size = dict->NumberOfElements();
 
   // Allocate a temporary fixed array.
@@ -5075,7 +5080,7 @@ void JSObject::SetFastElements(FixedArray* elems) {
       elems->set(i, old_elements->get(i), mode);
     }
   } else {
-    Dictionary* dictionary = Dictionary::cast(elements());
+    NumberDictionary* dictionary = NumberDictionary::cast(elements());
     for (int i = 0; i < dictionary->Capacity(); i++) {
       Object* key = dictionary->KeyAt(i);
       if (key->IsNumber()) {
@@ -5240,7 +5245,8 @@ bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) {
       return true;
     }
   } else {
-    if (element_dictionary()->FindNumberEntry(index) != Dictionary::kNotFound) {
+    if (element_dictionary()->FindEntry(index)
+        != NumberDictionary::kNotFound) {
       return true;
     }
   }
@@ -5317,8 +5323,8 @@ bool JSObject::HasLocalElement(uint32_t index) {
     return (index < length) &&
            !FixedArray::cast(elements())->get(index)->IsTheHole();
   } else {
-    return element_dictionary()->FindNumberEntry(index)
-        != Dictionary::kNotFound;
+    return element_dictionary()->FindEntry(index)
+        != NumberDictionary::kNotFound;
   }
 }
 
@@ -5344,7 +5350,8 @@ bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
     if ((index < length) &&
         !FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
   } else {
-    if (element_dictionary()->FindNumberEntry(index) != Dictionary::kNotFound) {
+    if (element_dictionary()->FindEntry(index)
+        != NumberDictionary::kNotFound) {
       return true;
     }
   }
@@ -5479,10 +5486,10 @@ Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) {
 
   // Insert element in the dictionary.
   FixedArray* elms = FixedArray::cast(elements());
-  Dictionary* dictionary = Dictionary::cast(elms);
+  NumberDictionary* dictionary = NumberDictionary::cast(elms);
 
-  int entry = dictionary->FindNumberEntry(index);
-  if (entry != Dictionary::kNotFound) {
+  int entry = dictionary->FindEntry(index);
+  if (entry != NumberDictionary::kNotFound) {
     Object* element = dictionary->ValueAt(entry);
     PropertyDetails details = dictionary->DetailsAt(entry);
     if (details.type() == CALLBACKS) {
@@ -5531,7 +5538,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 = Dictionary::cast(elements())->max_number_key() + 1;
+      new_length = NumberDictionary::cast(elements())->max_number_key() + 1;
     }
     Object* obj = Heap::AllocateFixedArrayWithHoles(new_length);
     if (obj->IsFailure()) return obj;
@@ -5574,9 +5581,9 @@ Object* JSObject::GetElementPostInterceptor(JSObject* receiver,
       if (!value->IsTheHole()) return value;
     }
   } else {
-    Dictionary* dictionary = element_dictionary();
-    int entry = dictionary->FindNumberEntry(index);
-    if (entry != Dictionary::kNotFound) {
+    NumberDictionary* dictionary = element_dictionary();
+    int entry = dictionary->FindEntry(index);
+    if (entry != NumberDictionary::kNotFound) {
       Object* element = dictionary->ValueAt(entry);
       PropertyDetails details = dictionary->DetailsAt(entry);
       if (details.type() == CALLBACKS) {
@@ -5658,9 +5665,9 @@ Object* JSObject::GetElementWithReceiver(JSObject* receiver, uint32_t index) {
       if (!value->IsTheHole()) return value;
     }
   } else {
-    Dictionary* dictionary = element_dictionary();
-    int entry = dictionary->FindNumberEntry(index);
-    if (entry != Dictionary::kNotFound) {
+    NumberDictionary* dictionary = element_dictionary();
+    int entry = dictionary->FindEntry(index);
+    if (entry != NumberDictionary::kNotFound) {
       Object* element = dictionary->ValueAt(entry);
       PropertyDetails details = dictionary->DetailsAt(entry);
       if (details.type() == CALLBACKS) {
@@ -5696,7 +5703,7 @@ bool JSObject::HasDenseElements() {
       if (!elms->get(i)->IsTheHole()) number_of_elements++;
     }
   } else {
-    Dictionary* dictionary = Dictionary::cast(elements());
+    NumberDictionary* dictionary = NumberDictionary::cast(elements());
     capacity = dictionary->Capacity();
     number_of_elements = dictionary->NumberOfElements();
   }
@@ -5718,7 +5725,7 @@ bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
 
 bool JSObject::ShouldConvertToFastElements() {
   ASSERT(!HasFastElements());
-  Dictionary* dictionary = Dictionary::cast(elements());
+  NumberDictionary* dictionary = NumberDictionary::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
@@ -5737,17 +5744,19 @@ bool JSObject::ShouldConvertToFastElements() {
     length = dictionary->max_number_key();
   }
   return static_cast<uint32_t>(dictionary->Capacity()) >=
-      (length / (2 * Dictionary::kElementSize));
+      (length / (2 * NumberDictionary::kEntrySize));
 }
 
-
-void Dictionary::CopyValuesTo(FixedArray* elements) {
+template<typename Shape, typename Key>
+void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
   int pos = 0;
-  int capacity = Capacity();
+  int capacity = HashTable<Shape, Key>::Capacity();
   WriteBarrierMode mode = elements->GetWriteBarrierMode();
   for (int i = 0; i < capacity; i++) {
-    Object* k = KeyAt(i);
-    if (IsKey(k)) elements->set(pos++, ValueAt(i), mode);
+    Object* k =  Dictionary<Shape, Key>::KeyAt(i);
+    if (Dictionary<Shape, Key>::IsKey(k)) {
+      elements->set(pos++, ValueAt(i), mode);
+    }
   }
   ASSERT(pos == elements->length());
 }
@@ -5953,8 +5962,8 @@ bool JSObject::HasRealElementProperty(uint32_t index) {
     return (index < length) &&
         !FixedArray::cast(elements())->get(index)->IsTheHole();
   }
-  return element_dictionary()->FindNumberEntry(index)
-      != Dictionary::kNotFound;
+  return element_dictionary()->FindEntry(index)
+      != NumberDictionary::kNotFound;
 }
 
 
@@ -6187,38 +6196,49 @@ int JSObject::GetEnumElementKeys(FixedArray* storage) {
 }
 
 
-// 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 NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
+  ASSERT(other->IsNumber());
+  return key == static_cast<uint32_t>(other->Number());
+}
 
-  bool IsMatch(Object* number) {
-    return number_ == ToUint32(number);
-  }
 
-  uint32_t Hash() { return ComputeIntegerHash(number_); }
+uint32_t NumberDictionaryShape::Hash(uint32_t key) {
+  return ComputeIntegerHash(key);
+}
 
-  HashFunction GetHashFunction() { return NumberHash; }
 
-  Object* GetObject() {
-    return Heap::NumberFromDouble(number_);
-  }
+uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) {
+  ASSERT(other->IsNumber());
+  return ComputeIntegerHash(static_cast<uint32_t>(other->Number()));
+}
 
-  bool IsStringKey() { return false; }
 
- private:
-  static uint32_t NumberHash(Object* obj) {
-    return ComputeIntegerHash(ToUint32(obj));
-  }
+Object* NumberDictionaryShape::AsObject(uint32_t key) {
+  return Heap::NumberFromUint32(key);
+}
 
-  static uint32_t ToUint32(Object* obj) {
-    ASSERT(obj->IsNumber());
-    return static_cast<uint32_t>(obj->Number());
-  }
 
-  uint32_t 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 StringDictionaryShape::Hash(String* key) {
+  return key->Hash();
+}
+
+
+uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
+  return String::cast(other)->Hash();
+}
+
+
+Object* StringDictionaryShape::AsObject(String* key) {
+  return key;
+}
 
 
 // StringKey simply carries a string object as key.
@@ -6226,12 +6246,12 @@ class StringKey : public HashTableKey {
  public:
   explicit StringKey(String* string) :
       string_(string),
-      hash_(StringHash(string)) { }
+      hash_(HashForObject(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_ != StringHash(string)) {
+    if (hash_ != HashForObject(string)) {
       return false;
     }
     return string_->Equals(String::cast(string));
@@ -6239,15 +6259,9 @@ class StringKey : public HashTableKey {
 
   uint32_t Hash() { return hash_; }
 
-  HashFunction GetHashFunction() { return StringHash; }
-
-  Object* GetObject() { return string_; }
-
-  static uint32_t StringHash(Object* obj) {
-    return String::cast(obj)->Hash();
-  }
+  uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
 
-  bool IsStringKey() { return true; }
+  Object* AsObject() { return string_; }
 
   String* string_;
   uint32_t hash_;
@@ -6269,10 +6283,6 @@ 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();
@@ -6289,18 +6299,18 @@ class StringSharedKey : public HashTableKey {
     return hash;
   }
 
-  static uint32_t StringSharedHash(Object* obj) {
+  uint32_t Hash() {
+    return StringSharedHashHelper(source_, shared_);
+  }
+
+  uint32_t HashForObject(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);
   }
 
-  virtual uint32_t Hash() {
-    return StringSharedHashHelper(source_, shared_);
-  }
-
-  virtual Object* GetObject() {
+  Object* AsObject() {
     Object* obj = Heap::AllocateFixedArray(2);
     if (obj->IsFailure()) return obj;
     FixedArray* pair = FixedArray::cast(obj);
@@ -6309,8 +6319,6 @@ class StringSharedKey : public HashTableKey {
     return pair;
   }
 
-  virtual bool IsStringKey() { return false; }
-
  private:
   String* source_;
   SharedFunctionInfo* shared_;
@@ -6332,16 +6340,14 @@ class RegExpKey : public HashTableKey {
 
   uint32_t Hash() { return RegExpHash(string_, flags_); }
 
-  HashFunction GetHashFunction() { return RegExpObjectHash; }
-
-  Object* GetObject() {
+  Object* AsObject() {
     // Plain hash maps, which is where regexp keys are used, don't
     // use this function.
     UNREACHABLE();
     return NULL;
   }
 
-  static uint32_t RegExpObjectHash(Object* obj) {
+  uint32_t HashForObject(Object* obj) {
     FixedArray* val = FixedArray::cast(obj);
     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
@@ -6351,8 +6357,6 @@ class RegExpKey : public HashTableKey {
     return string->Hash() + flags->value();
   }
 
-  bool IsStringKey() { return false; }
-
   String* string_;
   Smi* flags_;
 };
@@ -6367,10 +6371,6 @@ 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(),
@@ -6382,17 +6382,15 @@ class Utf8SymbolKey : public HashTableKey {
     return result;
   }
 
-  Object* GetObject() {
-    if (length_field_ == 0) Hash();
-    return Heap::AllocateSymbol(string_, chars_, length_field_);
+  uint32_t HashForObject(Object* other) {
+    return String::cast(other)->Hash();
   }
 
-  static uint32_t StringHash(Object* obj) {
-    return String::cast(obj)->Hash();
+  Object* AsObject() {
+    if (length_field_ == 0) Hash();
+    return Heap::AllocateSymbol(string_, chars_, length_field_);
   }
 
-  bool IsStringKey() { return true; }
-
   Vector<const char> string_;
   uint32_t length_field_;
   int chars_;  // Caches the number of characters when computing the hash code.
@@ -6404,17 +6402,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(); }
 
-  Object* GetObject() {
+  uint32_t HashForObject(Object* other) {
+    return String::cast(other)->Hash();
+  }
+
+  Object* AsObject() {
     // If the string is a cons string, attempt to flatten it so that
     // symbols will most often be flat strings.
     if (StringShape(string_).IsCons()) {
@@ -6442,28 +6440,27 @@ class SymbolKey : public HashTableKey {
     return String::cast(obj)->Hash();
   }
 
-  bool IsStringKey() { return true; }
-
   String* string_;
 };
 
 
-template<int prefix_size, int element_size>
-void HashTable<prefix_size, element_size>::IteratePrefix(ObjectVisitor* v) {
+template<typename Shape, typename Key>
+void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) {
   IteratePointers(v, 0, kElementsStartOffset);
 }
 
 
-template<int prefix_size, int element_size>
-void HashTable<prefix_size, element_size>::IterateElements(ObjectVisitor* v) {
+template<typename Shape, typename Key>
+void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) {
   IteratePointers(v,
                   kElementsStartOffset,
                   kHeaderSize + length() * kPointerSize);
 }
 
 
-template<int prefix_size, int element_size>
-Object* HashTable<prefix_size, element_size>::Allocate(int at_least_space_for) {
+template<typename Shape, typename Key>
+Object* HashTable<Shape, Key>::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));
@@ -6475,27 +6472,28 @@ Object* HashTable<prefix_size, element_size>::Allocate(int at_least_space_for) {
 }
 
 
+
 // Find entry for key otherwise return -1.
-template <int prefix_size, int element_size>
-int HashTable<prefix_size, element_size>::FindEntry(HashTableKey* key) {
+template<typename Shape, typename Key>
+int HashTable<Shape, Key>::FindEntry(Key key) {
   uint32_t nof = NumberOfElements();
   if (nof == 0) return kNotFound;  // Bail out if empty.
 
   uint32_t capacity = Capacity();
-  uint32_t hash = key->Hash();
+  uint32_t hash = Shape::Hash(key);
   uint32_t entry = GetProbe(hash, 0, capacity);
 
   Object* element = KeyAt(entry);
   uint32_t passed_elements = 0;
   if (!element->IsNull()) {
-    if (!element->IsUndefined() && key->IsMatch(element)) return entry;
+    if (!element->IsUndefined() && Shape::IsMatch(key, 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() && key->IsMatch(element)) return entry;
+      if (!element->IsUndefined() && Shape::IsMatch(key, element)) return entry;
       if (++passed_elements == nof) return kNotFound;
     }
   }
@@ -6503,9 +6501,8 @@ int HashTable<prefix_size, element_size>::FindEntry(HashTableKey* key) {
 }
 
 
-template<int prefix_size, int element_size>
-Object* HashTable<prefix_size, element_size>::EnsureCapacity(
-    int n, HashTableKey* key) {
+template<typename Shape, typename Key>
+Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
   int capacity = Capacity();
   int nof = NumberOfElements() + n;
   // Make sure 50% is free
@@ -6517,18 +6514,20 @@ Object* HashTable<prefix_size, element_size>::EnsureCapacity(
   WriteBarrierMode mode = table->GetWriteBarrierMode();
 
   // Copy prefix to new array.
-  for (int i = kPrefixStartIndex; i < kPrefixStartIndex + prefix_size; i++) {
+  for (int i = kPrefixStartIndex;
+       i < kPrefixStartIndex + Shape::kPrefixSize;
+       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* key = get(from_index);
-    if (IsKey(key)) {
+    Object* k = get(from_index);
+    if (IsKey(k)) {
+      uint32_t hash = Shape::HashForObject(key, k);
       uint32_t insertion_index =
-          EntryToIndex(table->FindInsertionEntry(key, Hash(key)));
-      for (int j = 0; j < element_size; j++) {
+          EntryToIndex(table->FindInsertionEntry(hash));
+      for (int j = 0; j < Shape::kEntrySize; j++) {
         table->set(insertion_index + j, get(from_index + j), mode);
       }
     }
@@ -6538,10 +6537,8 @@ Object* HashTable<prefix_size, element_size>::EnsureCapacity(
 }
 
 
-template<int prefix_size, int element_size>
-uint32_t HashTable<prefix_size, element_size>::FindInsertionEntry(
-      Object* key,
-      uint32_t hash) {
+template<typename Shape, typename Key>
+uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
   uint32_t capacity = Capacity();
   uint32_t entry = GetProbe(hash, 0, capacity);
   Object* element = KeyAt(entry);
@@ -6554,18 +6551,80 @@ uint32_t HashTable<prefix_size, element_size>::FindInsertionEntry(
   return entry;
 }
 
+// Force instantiation of template instances class.
+// Please note this list is compiler dependent.
+
+template class HashTable<SymbolTableShape, HashTableKey*>;
+
+template class HashTable<CompilationCacheShape, HashTableKey*>;
+
+template class HashTable<MapCacheShape, HashTableKey*>;
+
+template class Dictionary<StringDictionaryShape, String*>;
 
-// Force instantiation of SymbolTable's base class
-template class HashTable<0, 1>;
+template class Dictionary<NumberDictionaryShape, uint32_t>;
 
+template Object* Dictionary<NumberDictionaryShape, uint32_t>::Allocate(
+    int);
 
-// Force instantiation of Dictionary's base class
-template class HashTable<2, 3>;
+template Object* Dictionary<StringDictionaryShape, String*>::Allocate(
+    int);
 
+template Object* Dictionary<NumberDictionaryShape, uint32_t>::AtPut(
+    uint32_t, Object*);
 
-// Force instantiation of EvalCache's base class
-template class HashTable<0, 2>;
+template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup(
+    Object*);
 
+template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
+    Object*);
+
+template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo(
+    FixedArray*, PropertyAttributes);
+
+template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
+    int, JSObject::DeleteMode);
+
+template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty(
+    int, JSObject::DeleteMode);
+
+template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
+    FixedArray*);
+
+template int
+Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
+    PropertyAttributes);
+
+template Object* Dictionary<StringDictionaryShape, String*>::Add(
+    String*, Object*, PropertyDetails);
+
+template Object*
+Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices();
+
+template int
+Dictionary<NumberDictionaryShape, uint32_t>::NumberOfElementsFilterAttributes(
+    PropertyAttributes);
+
+template Object* Dictionary<NumberDictionaryShape, uint32_t>::Add(
+    uint32_t, Object*, PropertyDetails);
+
+template Object* Dictionary<NumberDictionaryShape, uint32_t>::EnsureCapacity(
+    int, uint32_t);
+
+template Object* Dictionary<StringDictionaryShape, String*>::EnsureCapacity(
+    int, String*);
+
+template Object* Dictionary<NumberDictionaryShape, uint32_t>::AddEntry(
+    uint32_t, Object*, PropertyDetails, uint32_t);
+
+template Object* Dictionary<StringDictionaryShape, String*>::AddEntry(
+    String*, Object*, PropertyDetails, uint32_t);
+
+template
+int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements();
+
+template
+int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
 
 // Collates undefined and unexisting elements below limit from position
 // zero of the elements. The object stays in Dictionary mode.
@@ -6574,7 +6633,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.
-  Dictionary* dict = element_dictionary();
+  NumberDictionary* 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.
@@ -6584,9 +6643,9 @@ Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
   }
 
   int capacity = dict->Capacity();
-  Object* obj = Dictionary::Allocate(dict->Capacity());
+  Object* obj = NumberDictionary::Allocate(dict->Capacity());
   if (obj->IsFailure()) return obj;
-  Dictionary* new_dict = Dictionary::cast(obj);
+  NumberDictionary* new_dict = NumberDictionary::cast(obj);
 
   AssertNoAllocation no_alloc;
 
@@ -6647,7 +6706,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.
-    Dictionary* dict = element_dictionary();
+    NumberDictionary* dict = element_dictionary();
     if (IsJSArray() || dict->requires_slow_elements() ||
         dict->max_number_key() >= limit) {
       return PrepareSlowElementsForSort(limit);
@@ -6787,7 +6846,7 @@ Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
   if (obj->IsFailure()) return obj;
 
   // Create symbol object.
-  Object* symbol = key->GetObject();
+  Object* symbol = key->AsObject();
   if (symbol->IsFailure()) return symbol;
 
   // If the symbol table grew as part of EnsureCapacity, obj is not
@@ -6796,7 +6855,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(symbol, key->Hash());
+  entry = table->FindInsertionEntry(key->Hash());
   table->set(EntryToIndex(entry), symbol);
   table->ElementAdded();
   *s = symbol;
@@ -6836,7 +6895,7 @@ Object* CompilationCacheTable::Put(String* src, Object* value) {
 
   CompilationCacheTable* cache =
       reinterpret_cast<CompilationCacheTable*>(obj);
-  int entry = cache->FindInsertionEntry(src, key.Hash());
+  int entry = cache->FindInsertionEntry(key.Hash());
   cache->set(EntryToIndex(entry), src);
   cache->set(EntryToIndex(entry) + 1, value);
   cache->ElementAdded();
@@ -6853,9 +6912,9 @@ Object* CompilationCacheTable::PutEval(String* src,
 
   CompilationCacheTable* cache =
       reinterpret_cast<CompilationCacheTable*>(obj);
-  int entry = cache->FindInsertionEntry(src, key.Hash());
+  int entry = cache->FindInsertionEntry(key.Hash());
 
-  Object* k = key.GetObject();
+  Object* k = key.AsObject();
   if (k->IsFailure()) return k;
 
   cache->set(EntryToIndex(entry), k);
@@ -6874,7 +6933,7 @@ Object* CompilationCacheTable::PutRegExp(String* src,
 
   CompilationCacheTable* cache =
       reinterpret_cast<CompilationCacheTable*>(obj);
-  int entry = cache->FindInsertionEntry(value, key.Hash());
+  int entry = cache->FindInsertionEntry(key.Hash());
   cache->set(EntryToIndex(entry), value);
   cache->set(EntryToIndex(entry) + 1, value);
   cache->ElementAdded();
@@ -6897,13 +6956,9 @@ class SymbolsKey : public HashTableKey {
     return true;
   }
 
-  uint32_t Hash() { return SymbolsHash(symbols_); }
-
-  HashFunction GetHashFunction() { return SymbolsHash; }
+  uint32_t Hash() { return HashForObject(symbols_); }
 
-  Object* GetObject() { return symbols_; }
-
-  static uint32_t SymbolsHash(Object* obj) {
+  uint32_t HashForObject(Object* obj) {
     FixedArray* symbols = FixedArray::cast(obj);
     int len = symbols->length();
     uint32_t hash = 0;
@@ -6913,7 +6968,7 @@ class SymbolsKey : public HashTableKey {
     return hash;
   }
 
-  bool IsStringKey() { return false; }
+  Object* AsObject() { return symbols_; }
 
  private:
   FixedArray* symbols_;
@@ -6934,7 +6989,7 @@ Object* MapCache::Put(FixedArray* array, Map* value) {
   if (obj->IsFailure()) return obj;
 
   MapCache* cache = reinterpret_cast<MapCache*>(obj);
-  int entry = cache->FindInsertionEntry(array, key.Hash());
+  int entry = cache->FindInsertionEntry(key.Hash());
   cache->set(EntryToIndex(entry), array);
   cache->set(EntryToIndex(entry) + 1, value);
   cache->ElementAdded();
@@ -6942,19 +6997,21 @@ Object* MapCache::Put(FixedArray* array, Map* value) {
 }
 
 
-Object* Dictionary::Allocate(int at_least_space_for) {
-  Object* obj = DictionaryBase::Allocate(at_least_space_for);
+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);
   // Initialize the next enumeration index.
   if (!obj->IsFailure()) {
-    Dictionary::cast(obj)->
+    Dictionary<Shape, Key>::cast(obj)->
         SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
   }
   return obj;
 }
 
 
-Object* Dictionary::GenerateNewEnumerationIndices() {
-  int length = NumberOfElements();
+template<typename Shape, typename Key>
+Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
+  int length = HashTable<Shape, Key>::NumberOfElements();
 
   // Allocate and initialize iteration order array.
   Object* obj = Heap::AllocateFixedArray(length);
@@ -6970,10 +7027,10 @@ Object* Dictionary::GenerateNewEnumerationIndices() {
   FixedArray* enumeration_order = FixedArray::cast(obj);
 
   // Fill the enumeration order array with property details.
-  int capacity = Capacity();
+  int capacity = HashTable<Shape, Key>::Capacity();
   int pos = 0;
   for (int i = 0; i < capacity; i++) {
-    if (IsKey(KeyAt(i))) {
+    if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
       enumeration_order->set(pos++,
                              Smi::FromInt(DetailsAt(i).index()),
                              SKIP_WRITE_BARRIER);
@@ -6993,10 +7050,10 @@ Object* Dictionary::GenerateNewEnumerationIndices() {
   }
 
   // Update the dictionary with new indices.
-  capacity = Capacity();
+  capacity = HashTable<Shape, Key>::Capacity();
   pos = 0;
   for (int i = 0; i < capacity; i++) {
-    if (IsKey(KeyAt(i))) {
+    if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
       int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
       PropertyDetails details = DetailsAt(i);
       PropertyDetails new_details =
@@ -7010,20 +7067,20 @@ Object* Dictionary::GenerateNewEnumerationIndices() {
   return this;
 }
 
-
-Object* Dictionary::EnsureCapacity(int n, HashTableKey* key) {
+template<typename Shape, typename Key>
+Object* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
   // Check whether there are enough enumeration indices to add n elements.
-  if (key->IsStringKey() &&
+  if (Shape::kIsEnumerable &&
       !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
     // If not, we generate new indices for the properties.
     Object* result = GenerateNewEnumerationIndices();
     if (result->IsFailure()) return result;
   }
-  return DictionaryBase::EnsureCapacity(n, key);
+  return HashTable<Shape, Key>::EnsureCapacity(n, key);
 }
 
 
-void Dictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
+void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
   // Do nothing if the interval [from, to) is empty.
   if (from >= to) return;
 
@@ -7046,35 +7103,26 @@ void Dictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
 }
 
 
-Object* Dictionary::DeleteProperty(int entry, JSObject::DeleteMode mode) {
+template<typename Shape, typename Key>
+Object* Dictionary<Shape, Key>::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));
-  ElementRemoved();
+  HashTable<Shape, Key>::ElementRemoved();
   return Heap::true_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) {
+template<typename Shape, typename Key>
+Object* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
   int entry = FindEntry(key);
 
   // If the entry is present set the value;
-  if (entry != kNotFound) {
+  if (entry != Dictionary<Shape, Key>::kNotFound) {
     ValueAtPut(entry, value);
     return this;
   }
@@ -7082,48 +7130,57 @@ Object* Dictionary::AtPut(HashTableKey* key, Object* value) {
   // Check whether the dictionary should be extended.
   Object* obj = EnsureCapacity(1, key);
   if (obj->IsFailure()) return obj;
-  Object* k = key->GetObject();
+
+  Object* k = Shape::AsObject(key);
   if (k->IsFailure()) return k;
   PropertyDetails details = PropertyDetails(NONE, NORMAL);
-  Dictionary::cast(obj)->AddEntry(k, value, details, key->Hash());
-  return obj;
+  return Dictionary<Shape, Key>::cast(obj)->
+      AddEntry(key, value, details, Shape::Hash(key));
 }
 
 
-Object* Dictionary::Add(HashTableKey* key, Object* value,
-                        PropertyDetails details) {
+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));
   // Check whether the dictionary should be extended.
   Object* obj = EnsureCapacity(1, key);
   if (obj->IsFailure()) return obj;
-  // Compute the key object.
-  Object* k = key->GetObject();
-  if (k->IsFailure()) return k;
-  Dictionary::cast(obj)->AddEntry(k, value, details, key->Hash());
-  return obj;
+  return Dictionary<Shape, Key>::cast(obj)->
+      AddEntry(key, value, details, Shape::Hash(key));
 }
 
 
 // Add a key, value pair to the dictionary.
-void Dictionary::AddEntry(Object* key,
-                          Object* value,
-                          PropertyDetails details,
-                          uint32_t hash) {
-  uint32_t entry = FindInsertionEntry(key, hash);
+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);
   // Insert element at empty or deleted entry
-  if (details.index() == 0 && key->IsString()) {
+  if (details.index() == 0 && Shape::kIsEnumerable) {
     // 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, key, value, details);
-  ASSERT(KeyAt(entry)->IsNumber() || KeyAt(entry)->IsString());
-  ElementAdded();
+  SetEntry(entry, k, value, details);
+  ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
+          || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
+  HashTable<Shape, Key>::ElementAdded();
+  return this;
 }
 
 
-void Dictionary::UpdateMaxNumberKey(uint32_t key) {
+void NumberDictionary::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;
@@ -7136,73 +7193,51 @@ void Dictionary::UpdateMaxNumberKey(uint32_t key) {
   // Update max key value.
   Object* max_index_object = get(kMaxNumberKeyIndex);
   if (!max_index_object->IsSmi() || max_number_key() < key) {
-    set(kMaxNumberKeyIndex,
-        Smi::FromInt(key << kRequiresSlowElementsTagSize),
-        SKIP_WRITE_BARRIER);
+    FixedArray::set(kMaxNumberKeyIndex,
+                    Smi::FromInt(key << kRequiresSlowElementsTagSize),
+                    SKIP_WRITE_BARRIER);
   }
 }
 
 
-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);
+Object* NumberDictionary::AddNumberEntry(uint32_t key,
+                                         Object* value,
+                                         PropertyDetails details) {
   UpdateMaxNumberKey(key);
-  SLOW_ASSERT(FindEntry(&k) == kNotFound);
-  return Add(&k, value, details);
+  SLOW_ASSERT(FindEntry(key) == kNotFound);
+  return Add(key, value, details);
 }
 
 
-Object* Dictionary::AtNumberPut(uint32_t key, Object* value) {
-  NumberKey k(key);
+Object* NumberDictionary::AtNumberPut(uint32_t key, Object* value) {
   UpdateMaxNumberKey(key);
-  return AtPut(&k, value);
+  return AtPut(key, value);
 }
 
 
-Object* Dictionary::SetStringEntry(int entry,
-                                   String* key,
-                                   Object* value,
-                                   PropertyDetails details) {
+Object* NumberDictionary::Set(uint32_t key,
+                              Object* value,
+                              PropertyDetails details) {
+  int entry = FindEntry(key);
+  if (entry == kNotFound) return AddNumberEntry(key, value, details);
   // Preserve enumeration index.
   details = PropertyDetails(details.attributes(),
                             details.type(),
                             DetailsAt(entry).index());
-  SetEntry(entry, key, value, details);
+  SetEntry(entry, NumberDictionaryShape::AsObject(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;
-}
-
 
-int Dictionary::NumberOfElementsFilterAttributes(PropertyAttributes filter) {
-  int capacity = Capacity();
+template<typename Shape, typename Key>
+int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
+    PropertyAttributes filter) {
+  int capacity = HashTable<Shape, Key>::Capacity();
   int result = 0;
   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)) {
       PropertyAttributes attr = DetailsAt(i).attributes();
       if ((attr & filter) == 0) result++;
     }
@@ -7211,19 +7246,22 @@ int Dictionary::NumberOfElementsFilterAttributes(PropertyAttributes filter) {
 }
 
 
-int Dictionary::NumberOfEnumElements() {
+template<typename Shape, typename Key>
+int Dictionary<Shape, Key>::NumberOfEnumElements() {
   return NumberOfElementsFilterAttributes(
       static_cast<PropertyAttributes>(DONT_ENUM));
 }
 
 
-void Dictionary::CopyKeysTo(FixedArray* storage, PropertyAttributes filter) {
+template<typename Shape, typename Key>
+void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage,
+                                        PropertyAttributes filter) {
   ASSERT(storage->length() >= NumberOfEnumElements());
-  int capacity = Capacity();
+  int capacity = HashTable<Shape, Key>::Capacity();
   int index = 0;
   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)) {
        PropertyAttributes attr = DetailsAt(i).attributes();
        if ((attr & filter) == 0) storage->set(index++, k);
      }
@@ -7233,7 +7271,8 @@ void Dictionary::CopyKeysTo(FixedArray* storage, PropertyAttributes filter) {
 }
 
 
-void Dictionary::CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array) {
+void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
+                                      FixedArray* sort_array) {
   ASSERT(storage->length() >= NumberOfEnumElements());
   int capacity = Capacity();
   int index = 0;
@@ -7255,14 +7294,15 @@ void Dictionary::CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array) {
 }
 
 
-void Dictionary::CopyKeysTo(FixedArray* storage) {
+template<typename Shape, typename Key>
+void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) {
   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
       static_cast<PropertyAttributes>(NONE)));
-  int capacity = Capacity();
+  int capacity = HashTable<Shape, Key>::Capacity();
   int index = 0;
   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)) {
       storage->set(index++, k);
     }
   }
@@ -7271,11 +7311,12 @@ void Dictionary::CopyKeysTo(FixedArray* storage) {
 
 
 // Backwards lookup (slow).
-Object* Dictionary::SlowReverseLookup(Object* value) {
-  int capacity = Capacity();
+template<typename Shape, typename Key>
+Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
+  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 (Dictionary<Shape, Key>::IsKey(k)) {
       Object* e = ValueAt(i);
       if (e->IsJSGlobalPropertyCell()) {
         e = JSGlobalPropertyCell::cast(e)->value();
@@ -7287,8 +7328,8 @@ Object* Dictionary::SlowReverseLookup(Object* value) {
 }
 
 
-Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
-                                                 int unused_property_fields) {
+Object* StringDictionary::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;
@@ -7296,7 +7337,8 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
   // 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;
@@ -7645,4 +7687,5 @@ int BreakPointInfo::GetBreakPointCount() {
 }
 #endif
 
+
 } }  // namespace v8::internal
index 4ebe6a1..ebd0bb4 100644 (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,42 +2142,23 @@ 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);
 
-  // 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(get(kNextEnumerationIndexIndex))->value();
+    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, HashTableKey* key);
+  Object* EnsureCapacity(int n, Key key);
 
 #ifdef DEBUG
   void Print();
@@ -2160,38 +2166,110 @@ class Dictionary: public DictionaryBase {
   // Returns the key (slow).
   Object* SlowReverseLookup(Object* value);
 
-  // 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);
 
+  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 = kPrefixStartIndex;
+  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);
 
-  DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary);
+  // 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);
+
+  // Bit masks.
+  static const int kRequiresSlowElementsMask = 1;
+  static const int kRequiresSlowElementsTagSize = 1;
+  static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
 };
 
 
@@ -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);
index e0eab74..ac0c173 100644 (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);
@@ -2610,9 +2610,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()) {
@@ -5136,8 +5136,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;
@@ -5185,7 +5185,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));
@@ -5339,7 +5339,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));
@@ -5402,7 +5402,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();
   }
index f7ba9f3..49b20e2 100644 (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);