[runtime] Object.create(null) creates a slow object

Object.create(null) is most likely to be used for dictionary-like objects.
Hence it would be beneficial to directly create a slow-mode object and avoid
additional overhead later-on.

BUG=

Review-Url: https://codereview.chromium.org/2430273007
Cr-Commit-Position: refs/heads/master@{#40551}
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 4c34c0f..6ebc5b5 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -3528,12 +3528,13 @@
       HeapObject::cast(object_function->initial_map()->prototype())->map());
 
   // Set up the map for Object.create(null) instances.
-  Handle<Map> object_with_null_prototype_map =
+  Handle<Map> slow_object_with_null_prototype_map =
       Map::CopyInitialMap(handle(object_function->initial_map(), isolate()));
-  Map::SetPrototype(object_with_null_prototype_map,
+  slow_object_with_null_prototype_map->set_dictionary_map(true);
+  Map::SetPrototype(slow_object_with_null_prototype_map,
                     isolate()->factory()->null_value());
-  native_context()->set_object_with_null_prototype_map(
-      *object_with_null_prototype_map);
+  native_context()->set_slow_object_with_null_prototype_map(
+      *slow_object_with_null_prototype_map);
 
   // Store the map for the %StringPrototype% after the natives has been compiled
   // and the String function has been set up.
diff --git a/src/builtins/builtins-object.cc b/src/builtins/builtins-object.cc
index 4536fc9..01f5ad4 100644
--- a/src/builtins/builtins-object.cc
+++ b/src/builtins/builtins-object.cc
@@ -494,6 +494,7 @@
   a->Bind(&no_properties);
   {
     Variable map(a, MachineRepresentation::kTagged);
+    Variable properties(a, MachineRepresentation::kTagged);
     Label non_null_proto(a), instantiate_map(a), good(a);
 
     a->Branch(a->WordEqual(prototype, a->NullConstant()), &good,
@@ -501,13 +502,16 @@
 
     a->Bind(&good);
     {
-      map.Bind(a->LoadContextElement(context,
-                                     Context::OBJECT_WITH_NULL_PROTOTYPE_MAP));
+      map.Bind(a->LoadContextElement(
+          context, Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP));
+      properties.Bind(
+          a->AllocateNameDictionary(NameDictionary::kInitialCapacity));
       a->Goto(&instantiate_map);
     }
 
     a->Bind(&non_null_proto);
     {
+      properties.Bind(a->EmptyFixedArrayConstant());
       Node* object_function =
           a->LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX);
       Node* object_function_map = a->LoadObjectField(
@@ -528,7 +532,8 @@
 
     a->Bind(&instantiate_map);
     {
-      Node* instance = a->AllocateJSObjectFromMap(map.value());
+      Node* instance =
+          a->AllocateJSObjectFromMap(map.value(), properties.value());
       a->Return(instance);
     }
   }
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
index 58db510..d0c8911 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -127,6 +127,24 @@
   return IntPtrSub(left, right);
 }
 
+Node* CodeStubAssembler::IntPtrRoundUpToPowerOfTwo32(Node* value) {
+  Comment("IntPtrRoundUpToPowerOfTwo32");
+  CSA_ASSERT(UintPtrLessThanOrEqual(value, IntPtrConstant(0x80000000u)));
+  value = IntPtrSub(value, IntPtrConstant(1));
+  for (int i = 1; i <= 16; i *= 2) {
+    value = WordOr(value, WordShr(value, IntPtrConstant(i)));
+  }
+  return IntPtrAdd(value, IntPtrConstant(1));
+}
+
+Node* CodeStubAssembler::WordIsPowerOfTwo(Node* value) {
+  // value && !(value & (value - 1))
+  return WordEqual(
+      Select(WordEqual(value, IntPtrConstant(0)), IntPtrConstant(1),
+             WordAnd(value, IntPtrSub(value, IntPtrConstant(1)))),
+      IntPtrConstant(0));
+}
+
 Node* CodeStubAssembler::Float64Round(Node* x) {
   Node* one = Float64Constant(1.0);
   Node* one_half = Float64Constant(0.5);
@@ -775,6 +793,7 @@
 }
 
 Node* CodeStubAssembler::Allocate(Node* size_in_bytes, AllocationFlags flags) {
+  Comment("Allocate");
   bool const new_space = !(flags & kPretenured);
   Node* top_address = ExternalConstant(
       new_space
@@ -1105,6 +1124,12 @@
                               Int32Constant(LAST_SPECIAL_RECEIVER_TYPE));
 }
 
+Node* CodeStubAssembler::IsDictionaryMap(Node* map) {
+  Node* bit_field3 = LoadMapBitField3(map);
+  return Word32NotEqual(IsSetWord32<Map::DictionaryMap>(bit_field3),
+                        Int32Constant(0));
+}
+
 Node* CodeStubAssembler::LoadNameHashField(Node* name) {
   return LoadObjectField(name, Name::kHashFieldOffset, MachineType::Uint32());
 }
@@ -1659,6 +1684,57 @@
   return result;
 }
 
+Node* CodeStubAssembler::AllocateNameDictionary(int at_least_space_for) {
+  return AllocateNameDictionary(IntPtrConstant(at_least_space_for));
+}
+
+Node* CodeStubAssembler::AllocateNameDictionary(Node* at_least_space_for) {
+  CSA_ASSERT(UintPtrLessThanOrEqual(
+      at_least_space_for, IntPtrConstant(NameDictionary::kMaxCapacity)));
+
+  Node* capacity = HashTableComputeCapacity(at_least_space_for);
+  CSA_ASSERT(WordIsPowerOfTwo(capacity));
+
+  Node* length = EntryToIndex<NameDictionary>(capacity);
+  Node* store_size =
+      IntPtrAddFoldConstants(WordShl(length, IntPtrConstant(kPointerSizeLog2)),
+                             IntPtrConstant(NameDictionary::kHeaderSize));
+
+  Node* result = Allocate(store_size);
+  Comment("Initialize NameDictionary");
+  // Initialize FixedArray fields.
+  StoreObjectFieldRoot(result, FixedArray::kMapOffset,
+                       Heap::kHashTableMapRootIndex);
+  StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset,
+                                 SmiFromWord(length));
+  // Initialized HashTable fields.
+  Node* zero = SmiConstant(0);
+  StoreFixedArrayElement(result, NameDictionary::kNumberOfElementsIndex, zero,
+                         SKIP_WRITE_BARRIER);
+  StoreFixedArrayElement(result, NameDictionary::kNumberOfDeletedElementsIndex,
+                         zero, SKIP_WRITE_BARRIER);
+  StoreFixedArrayElement(result, NameDictionary::kCapacityIndex,
+                         SmiTag(capacity), SKIP_WRITE_BARRIER);
+  // Initialize Dictionary fields.
+  Node* filler = LoadRoot(Heap::kUndefinedValueRootIndex);
+  StoreFixedArrayElement(result, NameDictionary::kMaxNumberKeyIndex, filler,
+                         SKIP_WRITE_BARRIER);
+  StoreFixedArrayElement(result, NameDictionary::kNextEnumerationIndexIndex,
+                         SmiConstant(PropertyDetails::kInitialIndex),
+                         SKIP_WRITE_BARRIER);
+
+  // Initialize NameDictionary elements.
+  Node* start_address = IntPtrAdd(
+      result, IntPtrConstant(NameDictionary::OffsetOfElementAt(
+                                 NameDictionary::kElementsStartIndex) -
+                             kHeapObjectTag));
+  Node* end_address = IntPtrAdd(
+      result,
+      IntPtrSubFoldConstants(store_size, IntPtrConstant(kHeapObjectTag)));
+  StoreFieldsNoWriteBarrier(start_address, end_address, filler);
+  return result;
+}
+
 Node* CodeStubAssembler::AllocateJSObjectFromMap(Node* map, Node* properties,
                                                  Node* elements) {
   Node* size =
@@ -1676,6 +1752,7 @@
   // This helper assumes that the object is in new-space, as guarded by the
   // check in AllocatedJSObjectFromMap.
   if (properties == nullptr) {
+    CSA_ASSERT(Word32BinaryNot(IsDictionaryMap((map))));
     StoreObjectFieldRoot(object, JSObject::kPropertiesOffset,
                          Heap::kEmptyFixedArrayRootIndex);
   } else {
@@ -3835,6 +3912,19 @@
                                                field_index));
 }
 
+template Node* CodeStubAssembler::EntryToIndex<NameDictionary>(Node*, int);
+template Node* CodeStubAssembler::EntryToIndex<GlobalDictionary>(Node*, int);
+
+Node* CodeStubAssembler::HashTableComputeCapacity(Node* at_least_space_for) {
+  Node* capacity = IntPtrRoundUpToPowerOfTwo32(
+      WordShl(at_least_space_for, IntPtrConstant(1)));
+  return IntPtrMax(capacity, IntPtrConstant(HashTableBase::kMinCapacity));
+}
+
+Node* CodeStubAssembler::IntPtrMax(Node* left, Node* right) {
+  return Select(IntPtrGreaterThanOrEqual(left, right), left, right);
+}
+
 template <typename Dictionary>
 void CodeStubAssembler::NameDictionaryLookup(Node* dictionary,
                                              Node* unique_name, Label* if_found,
diff --git a/src/code-stub-assembler.h b/src/code-stub-assembler.h
index 8cbf3d6..e391278 100644
--- a/src/code-stub-assembler.h
+++ b/src/code-stub-assembler.h
@@ -108,6 +108,9 @@
                                          compiler::Node* right);
   compiler::Node* IntPtrSubFoldConstants(compiler::Node* left,
                                          compiler::Node* right);
+  // Round the 32bits payload of the provided word up to the next power of two.
+  compiler::Node* IntPtrRoundUpToPowerOfTwo32(compiler::Node* value);
+  compiler::Node* IntPtrMax(compiler::Node* left, compiler::Node* right);
 
   // Float64 operations.
   compiler::Node* Float64Ceil(compiler::Node* x);
@@ -167,6 +170,7 @@
   compiler::Node* WordIsPositiveSmi(compiler::Node* a);
   // Check that a word has a word-aligned address.
   compiler::Node* WordIsWordAligned(compiler::Node* word);
+  compiler::Node* WordIsPowerOfTwo(compiler::Node* value);
 
   void BranchIfSmiEqual(compiler::Node* a, compiler::Node* b, Label* if_true,
                         Label* if_false) {
@@ -286,6 +290,8 @@
   // JSProxy or an object with interceptors.
   compiler::Node* IsSpecialReceiverMap(compiler::Node* map);
   compiler::Node* IsSpecialReceiverInstanceType(compiler::Node* instance_type);
+  // Check if the map is set for slow properties.
+  compiler::Node* IsDictionaryMap(compiler::Node* map);
 
   // Load the hash field of a name as an uint32 value.
   compiler::Node* LoadNameHashField(compiler::Node* name);
@@ -360,6 +366,14 @@
                                        Heap::RootListIndex root);
   // Store an array element to a FixedArray.
   compiler::Node* StoreFixedArrayElement(
+      compiler::Node* object, int index, compiler::Node* value,
+      WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
+      ParameterMode parameter_mode = INTEGER_PARAMETERS) {
+    return StoreFixedArrayElement(object, Int32Constant(index), value,
+                                  barrier_mode, parameter_mode);
+  }
+
+  compiler::Node* StoreFixedArrayElement(
       compiler::Node* object, compiler::Node* index, compiler::Node* value,
       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
       ParameterMode parameter_mode = INTEGER_PARAMETERS);
@@ -431,6 +445,9 @@
                                        compiler::Node* index,
                                        compiler::Node* input);
 
+  compiler::Node* AllocateNameDictionary(int capacity);
+  compiler::Node* AllocateNameDictionary(compiler::Node* capacity);
+
   compiler::Node* AllocateJSObjectFromMap(compiler::Node* map,
                                           compiler::Node* properties = nullptr,
                                           compiler::Node* elements = nullptr);
@@ -722,6 +739,8 @@
   compiler::Node* EntryToIndex(compiler::Node* entry) {
     return EntryToIndex<Dictionary>(entry, Dictionary::kEntryKeyIndex);
   }
+  // Calculate a valid size for the a hash table.
+  compiler::Node* HashTableComputeCapacity(compiler::Node* at_least_space_for);
 
   // Looks up an entry in a NameDictionaryBase successor. If the entry is found
   // control goes to {if_found} and {var_name_index} contains an index of the
diff --git a/src/compiler/code-assembler.cc b/src/compiler/code-assembler.cc
index f911755..513225d 100644
--- a/src/compiler/code-assembler.cc
+++ b/src/compiler/code-assembler.cc
@@ -110,6 +110,10 @@
   return BitcastWordToTaggedSigned(IntPtrConstant(bit_cast<intptr_t>(value)));
 }
 
+Node* CodeAssembler::SmiConstant(int value) {
+  return SmiConstant(Smi::FromInt(value));
+}
+
 Node* CodeAssembler::HeapConstant(Handle<HeapObject> object) {
   return raw_assembler_->HeapConstant(object);
 }
diff --git a/src/compiler/code-assembler.h b/src/compiler/code-assembler.h
index 24d9df8..946b241 100644
--- a/src/compiler/code-assembler.h
+++ b/src/compiler/code-assembler.h
@@ -222,6 +222,7 @@
   Node* IntPtrConstant(intptr_t value);
   Node* NumberConstant(double value);
   Node* SmiConstant(Smi* value);
+  Node* SmiConstant(int value);
   Node* HeapConstant(Handle<HeapObject> object);
   Node* BooleanConstant(bool value);
   Node* ExternalConstant(ExternalReference address);
diff --git a/src/contexts.h b/src/contexts.h
index 8e6d2e5..7cedb82 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -263,7 +263,8 @@
   V(NORMALIZED_MAP_CACHE_INDEX, Object, normalized_map_cache)                  \
   V(NUMBER_FUNCTION_INDEX, JSFunction, number_function)                        \
   V(OBJECT_FUNCTION_INDEX, JSFunction, object_function)                        \
-  V(OBJECT_WITH_NULL_PROTOTYPE_MAP, Map, object_with_null_prototype_map)       \
+  V(SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP, Map,                                  \
+    slow_object_with_null_prototype_map)                                       \
   V(OBJECT_FUNCTION_PROTOTYPE_MAP_INDEX, Map, object_function_prototype_map)   \
   V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function)    \
   V(PROXY_CALLABLE_MAP_INDEX, Map, proxy_callable_map)                         \
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 2372c2e..6e55449 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -3173,7 +3173,6 @@
 
 // static
 int HashTableBase::ComputeCapacity(int at_least_space_for) {
-  const int kMinCapacity = 4;
   int capacity = base::bits::RoundUpToPowerOfTwo32(at_least_space_for * 2);
   return Max(capacity, kMinCapacity);
 }
@@ -7577,7 +7576,7 @@
 
 
 bool JSReceiver::HasFastProperties() {
-  DCHECK(properties()->IsDictionary() == map()->is_dictionary_map());
+  DCHECK_EQ(properties()->IsDictionary(), map()->is_dictionary_map());
   return !properties()->IsDictionary();
 }
 
diff --git a/src/objects.cc b/src/objects.cc
index 9e8b06c..dc403d9 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -3432,7 +3432,8 @@
   if (expected_additional_properties > 0) {
     property_count += expected_additional_properties;
   } else {
-    property_count += 2;  // Make space for two more properties.
+    // Make space for two more properties.
+    property_count += NameDictionary::kInitialCapacity;
   }
   Handle<NameDictionary> dictionary =
       NameDictionary::New(isolate, property_count);
@@ -16774,7 +16775,8 @@
     MinimumCapacity capacity_option,
     PretenureFlag pretenure) {
   DCHECK(0 <= at_least_space_for);
-  DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
+  DCHECK_IMPLIES(capacity_option == USE_CUSTOM_MINIMUM_CAPACITY,
+                 base::bits::IsPowerOfTwo32(at_least_space_for));
 
   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
                      ? at_least_space_for
diff --git a/src/objects.h b/src/objects.h
index f1bc09b..c6434e0 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -3489,6 +3489,9 @@
   // Constant used for denoting a absent entry.
   static const int kNotFound = -1;
 
+  // Minimum capacity for newly created hash tables.
+  static const int kMinCapacity = 4;
+
  protected:
   // Update the number of elements in the hash table.
   inline void SetNumberOfElements(int nof);
@@ -3566,8 +3569,11 @@
   static const int kEntryKeyIndex = 0;
   static const int kElementsStartOffset =
       kHeaderSize + kElementsStartIndex * kPointerSize;
-  static const int kCapacityOffset =
-      kHeaderSize + kCapacityIndex * kPointerSize;
+  // Maximal capacity of HashTable. Based on maximal length of underlying
+  // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
+  // cannot overflow.
+  static const int kMaxCapacity =
+      (FixedArray::kMaxLength - kElementsStartIndex) / kEntrySize;
 
   // Returns the index for an entry (of the key)
   static inline int EntryToIndex(int entry) {
@@ -3604,12 +3610,6 @@
     set(kCapacityIndex, Smi::FromInt(capacity));
   }
 
-  // Maximal capacity of HashTable. Based on maximal length of underlying
-  // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
-  // cannot overflow.
-  static const int kMaxCapacity =
-      (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
-
  private:
   // Returns _expected_ if one of entries given by the first _probe_ probes is
   // equal to  _expected_. Otherwise, returns the entry given by the probe
@@ -3838,23 +3838,22 @@
   static Handle<FixedArray> BuildIterationIndicesArray(
       Handle<Derived> dictionary);
 
+  static const int kMaxNumberKeyIndex = DerivedHashTable::kPrefixStartIndex;
+  static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
+
  protected:
   // Generic at put operation.
   MUST_USE_RESULT static Handle<Derived> AtPut(
       Handle<Derived> dictionary,
       Key key,
       Handle<Object> value);
-
   // Add entry to dictionary. Returns entry value.
   static int AddEntry(Handle<Derived> dictionary, Key key, Handle<Object> value,
                       PropertyDetails details, uint32_t hash);
-
   // Generate new enumeration indices to avoid enumeration index overflow.
   // Returns iteration indices array for the |dictionary|.
   static Handle<FixedArray> GenerateNewEnumerationIndices(
       Handle<Derived> dictionary);
-  static const int kMaxNumberKeyIndex = DerivedHashTable::kPrefixStartIndex;
-  static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
 };
 
 
@@ -3926,6 +3925,7 @@
 
   static const int kEntryValueIndex = 1;
   static const int kEntryDetailsIndex = 2;
+  static const int kInitialCapacity = 2;
 };
 
 
diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc
index cbb1665..7be70bf 100644
--- a/src/runtime/runtime-object.cc
+++ b/src/runtime/runtime-object.cc
@@ -226,7 +226,7 @@
                   isolate);
   if (map->prototype() != *prototype) {
     if (prototype->IsNull(isolate)) {
-      map = isolate->object_with_null_prototype_map();
+      map = isolate->slow_object_with_null_prototype_map();
     } else if (prototype->IsJSObject()) {
       Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
       if (!js_prototype->map()->is_prototype_map()) {
@@ -250,6 +250,12 @@
   // Actually allocate the object.
   Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
 
+  if (map->is_dictionary_map()) {
+    Handle<NameDictionary> properties =
+        NameDictionary::New(isolate, NameDictionary::kInitialCapacity);
+    object->set_properties(*properties);
+  }
+
   // Define the properties if properties was specified and is not undefined.
   Handle<Object> properties = args.at<Object>(1);
   if (!properties->IsUndefined(isolate)) {
diff --git a/test/cctest/test-code-stub-assembler.cc b/test/cctest/test-code-stub-assembler.cc
index 6178499..d25f057 100644
--- a/test/cctest/test-code-stub-assembler.cc
+++ b/test/cctest/test-code-stub-assembler.cc
@@ -348,6 +348,37 @@
 namespace {
 
 template <typename Dictionary>
+void TestEntryToIndex() {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+
+  const int kNumParams = 1;
+  CodeStubAssemblerTester m(isolate, kNumParams);
+  {
+    Node* entry = m.SmiUntag(m.Parameter(0));
+    Node* result = m.EntryToIndex<Dictionary>(entry);
+    m.Return(m.SmiTag(result));
+  }
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  // Test a wide range of entries but staying linear in the first 100 entries.
+  for (int entry = 0; entry < Dictionary::kMaxCapacity;
+       entry = entry * 1.01 + 1) {
+    Handle<Object> result =
+        ft.Call(handle(Smi::FromInt(entry), isolate)).ToHandleChecked();
+    CHECK_EQ(Dictionary::EntryToIndex(entry), Smi::cast(*result)->value());
+  }
+}
+
+TEST(NameDictionaryEntryToIndex) { TestEntryToIndex<NameDictionary>(); }
+TEST(GlobalDictionaryEntryToIndex) { TestEntryToIndex<GlobalDictionary>(); }
+
+}  // namespace
+
+namespace {
+
+template <typename Dictionary>
 void TestNameDictionaryLookup() {
   typedef CodeStubAssembler::Label Label;
   typedef CodeStubAssembler::Variable Variable;
@@ -1627,7 +1658,6 @@
   FunctionTester ft(code, kNumParams);
 
   Handle<Map> maps[] = {
-      isolate->object_with_null_prototype_map(),
       handle(isolate->object_function()->initial_map(), isolate),
       handle(isolate->array_function()->initial_map(), isolate),
   };
@@ -1644,6 +1674,7 @@
       Handle<JSObject> result = Handle<JSObject>::cast(
           ft.Call(map, empty_fixed_array, empty_fixed_array).ToHandleChecked());
       VERIFY(result, *map, *empty_fixed_array, *empty_fixed_array);
+      CHECK(result->HasFastProperties());
 #ifdef VERIFY_HEAP
       isolate->heap()->Verify();
 #endif
@@ -1662,10 +1693,40 @@
                 handle(object->elements()))
             .ToHandleChecked());
     VERIFY(result, object->map(), object->properties(), object->elements());
+    CHECK(!result->HasFastProperties());
 #ifdef VERIFY_HEAP
     isolate->heap()->Verify();
 #endif
   }
+#undef VERIFY
+}
+
+TEST(AllocateNameDictionary) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+
+  const int kNumParams = 1;
+  CodeStubAssemblerTester m(isolate, kNumParams);
+
+  {
+    Node* capacity = m.Parameter(0);
+    Node* result = m.AllocateNameDictionary(m.SmiUntag(capacity));
+    m.Return(result);
+  }
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  {
+    for (int i = 0; i < 256; i = i * 1.1 + 1) {
+      Handle<Object> result =
+          ft.Call(handle(Smi::FromInt(i), isolate)).ToHandleChecked();
+      Handle<NameDictionary> dict = NameDictionary::New(isolate, i);
+      // Both dictionaries should be memory equal.
+      int size =
+          FixedArrayBase::kHeaderSize + (dict->length() - 1) * kPointerSize;
+      CHECK_EQ(0, memcmp(*dict, *result, size));
+    }
+  }
 }
 
 }  // namespace internal
diff --git a/test/mjsunit/es6/symbols.js b/test/mjsunit/es6/symbols.js
index a21afb3..d83e217 100644
--- a/test/mjsunit/es6/symbols.js
+++ b/test/mjsunit/es6/symbols.js
@@ -353,7 +353,7 @@
 }
 
 
-var objs = [{}, [], Object.create(null), Object(1), new Map, function(){}]
+var objs = [{}, [], Object.create({}), Object(1), new Map, function(){}]
 
 for (var i in objs) {
   var obj = objs[i]
diff --git a/test/mjsunit/harmony/private.js b/test/mjsunit/harmony/private.js
index d44ff33..71b4377 100644
--- a/test/mjsunit/harmony/private.js
+++ b/test/mjsunit/harmony/private.js
@@ -295,7 +295,7 @@
 }
 
 
-var objs = [{}, [], Object.create(null), Object(1), new Map, function(){}]
+var objs = [{}, [], Object.create({}), Object(1), new Map, function(){}]
 
 for (var i in objs) {
   var obj = objs[i]
diff --git a/test/mjsunit/regress/regress-252797.js b/test/mjsunit/regress/regress-252797.js
index 379205f..ac776a1 100644
--- a/test/mjsunit/regress/regress-252797.js
+++ b/test/mjsunit/regress/regress-252797.js
@@ -31,11 +31,17 @@
 // starting with a negative lookup.
 
 // Create a holder in fast mode.
-var holder = Object.create(null, {
+var holder = Object.create({}, {
   holderMethod: {value: function() {}}
 });
 assertTrue(%HasFastProperties(holder));
 
+// We assume dict usage for null prototype.
+var holder = Object.create(null, {
+  holderMethod: {value: function() {}}
+});
+assertFalse(%HasFastProperties(holder));
+
 // Create a receiver into dictionary mode.
 var receiver = Object.create(holder, {
   killMe: {value: 0, configurable: true},