[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},