Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 4301775086c73827cc58d9dfdb86102de244baa8..2f8aec5631e6c21f4814dda2e5b0503670738c80 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -810,6 +810,15 @@ Map* Object::GetRootMap(Isolate* isolate) { |
Object* Object::GetHash() { |
+ Object* hash = GetSimpleHash(); |
+ if (hash->IsSmi()) return hash; |
+ |
+ DCHECK(IsJSReceiver()); |
+ return JSReceiver::cast(this)->GetIdentityHash(); |
+} |
+ |
+ |
+Object* Object::GetSimpleHash() { |
// The object is either a Smi, a HeapNumber, a name, an odd-ball, |
// a real JS object, or a Harmony proxy. |
if (IsSmi()) { |
@@ -834,14 +843,14 @@ Object* Object::GetHash() { |
uint32_t hash = Oddball::cast(this)->to_string()->Hash(); |
return Smi::FromInt(hash); |
} |
- |
DCHECK(IsJSReceiver()); |
- return JSReceiver::cast(this)->GetIdentityHash(); |
+ JSReceiver* receiver = JSReceiver::cast(this); |
+ return receiver->GetHeap()->undefined_value(); |
} |
Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) { |
- Handle<Object> hash(object->GetHash(), isolate); |
+ Handle<Object> hash(object->GetSimpleHash(), isolate); |
if (hash->IsSmi()) return Handle<Smi>::cast(hash); |
DCHECK(object->IsJSReceiver()); |
@@ -5035,7 +5044,8 @@ static Smi* GenerateIdentityHash(Isolate* isolate) { |
void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) { |
DCHECK(!object->IsJSGlobalProxy()); |
Isolate* isolate = object->GetIsolate(); |
- SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash); |
+ Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol()); |
+ JSObject::AddProperty(object, hash_code_symbol, hash, NONE); |
} |
@@ -5058,11 +5068,12 @@ Object* JSObject::GetIdentityHash() { |
if (IsJSGlobalProxy()) { |
return JSGlobalProxy::cast(this)->hash(); |
} |
- Object* stored_value = |
- GetHiddenProperty(isolate->factory()->identity_hash_string()); |
- return stored_value->IsSmi() |
- ? stored_value |
- : isolate->heap()->undefined_value(); |
+ Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol()); |
+ Handle<Object> stored_value = |
+ Object::GetPropertyOrElement(Handle<Object>(this, isolate), |
+ hash_code_symbol).ToHandleChecked(); |
+ return stored_value->IsSmi() ? *stored_value |
+ : isolate->heap()->undefined_value(); |
} |
@@ -5077,7 +5088,8 @@ Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) { |
if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash); |
Handle<Smi> hash(GenerateIdentityHash(isolate), isolate); |
- SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash); |
+ Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol()); |
+ JSObject::AddProperty(object, hash_code_symbol, hash, NONE); |
return hash; |
} |
@@ -5096,8 +5108,6 @@ Object* JSObject::GetHiddenProperty(Handle<Name> key) { |
DisallowHeapAllocation no_gc; |
DCHECK(key->IsUniqueName()); |
if (IsJSGlobalProxy()) { |
- // JSGlobalProxies store their hash internally. |
- DCHECK(*key != GetHeap()->identity_hash_string()); |
// For a proxy, use the prototype as target object. |
PrototypeIterator iter(GetIsolate(), this); |
// If the proxy is detached, return undefined. |
@@ -5108,15 +5118,6 @@ Object* JSObject::GetHiddenProperty(Handle<Name> key) { |
DCHECK(!IsJSGlobalProxy()); |
Object* inline_value = GetHiddenPropertiesHashTable(); |
- if (inline_value->IsSmi()) { |
- // Handle inline-stored identity hash. |
- if (*key == GetHeap()->identity_hash_string()) { |
- return inline_value; |
- } else { |
- return GetHeap()->the_hole_value(); |
- } |
- } |
- |
if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); |
ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); |
@@ -5132,8 +5133,6 @@ Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, |
DCHECK(key->IsUniqueName()); |
if (object->IsJSGlobalProxy()) { |
- // JSGlobalProxies store their hash internally. |
- DCHECK(*key != *isolate->factory()->identity_hash_string()); |
// For a proxy, use the prototype as target object. |
PrototypeIterator iter(isolate, object); |
// If the proxy is detached, return undefined. |
@@ -5147,13 +5146,6 @@ Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, |
Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); |
- // If there is no backing store yet, store the identity hash inline. |
- if (value->IsSmi() && |
- *key == *isolate->factory()->identity_hash_string() && |
- (inline_value->IsUndefined() || inline_value->IsSmi())) { |
- return JSObject::SetHiddenPropertiesHashTable(object, value); |
- } |
- |
Handle<ObjectHashTable> hashtable = |
GetOrCreateHiddenPropertiesHashtable(object); |
@@ -5185,9 +5177,7 @@ void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) { |
Object* inline_value = object->GetHiddenPropertiesHashTable(); |
- // We never delete (inline-stored) identity hashes. |
- DCHECK(*key != *isolate->factory()->identity_hash_string()); |
- if (inline_value->IsUndefined() || inline_value->IsSmi()) return; |
+ if (inline_value->IsUndefined()) return; |
Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); |
bool was_present = false; |
@@ -5251,14 +5241,7 @@ Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable( |
Handle<ObjectHashTable> hashtable = ObjectHashTable::New( |
isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY); |
- if (inline_value->IsSmi()) { |
- // We were storing the identity hash inline and now allocated an actual |
- // dictionary. Put the identity hash into the new dictionary. |
- hashtable = ObjectHashTable::Put(hashtable, |
- isolate->factory()->identity_hash_string(), |
- inline_value); |
- } |
- |
+ DCHECK(inline_value->IsUndefined()); |
SetHiddenPropertiesHashTable(object, hashtable); |
return hashtable; |
} |
@@ -16324,18 +16307,34 @@ Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { |
} |
+Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key, |
+ int32_t hash) { |
+ DisallowHeapAllocation no_gc; |
+ DCHECK(IsKey(*key)); |
+ |
+ int entry = FindEntry(isolate, key, hash); |
+ if (entry == kNotFound) return isolate->heap()->the_hole_value(); |
+ return get(EntryToIndex(entry) + 1); |
+} |
+ |
+ |
Object* ObjectHashTable::Lookup(Handle<Object> key) { |
DisallowHeapAllocation no_gc; |
DCHECK(IsKey(*key)); |
+ Isolate* isolate = GetIsolate(); |
+ |
// If the object does not have an identity hash, it was never used as a key. |
Object* hash = key->GetHash(); |
if (hash->IsUndefined()) { |
- return GetHeap()->the_hole_value(); |
+ return isolate->heap()->the_hole_value(); |
} |
- int entry = FindEntry(key); |
- if (entry == kNotFound) return GetHeap()->the_hole_value(); |
- return get(EntryToIndex(entry) + 1); |
+ return Lookup(isolate, key, Smi::cast(hash)->value()); |
+} |
+ |
+ |
+Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) { |
+ return Lookup(GetIsolate(), key, hash); |
} |
@@ -16346,11 +16345,23 @@ Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, |
DCHECK(!value->IsTheHole()); |
Isolate* isolate = table->GetIsolate(); |
- |
// Make sure the key object has an identity hash code. |
- Handle<Smi> hash = Object::GetOrCreateHash(isolate, key); |
+ int32_t hash = Object::GetOrCreateHash(isolate, key)->value(); |
- int entry = table->FindEntry(key); |
+ return Put(table, key, value, hash); |
+} |
+ |
+ |
+Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, |
+ Handle<Object> key, |
+ Handle<Object> value, |
+ int32_t hash) { |
+ DCHECK(table->IsKey(*key)); |
+ DCHECK(!value->IsTheHole()); |
+ |
+ Isolate* isolate = table->GetIsolate(); |
+ |
+ int entry = table->FindEntry(isolate, key, hash); |
// Key is already in table, just overwrite value. |
if (entry != kNotFound) { |
@@ -16360,9 +16371,7 @@ Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, |
// Check whether the hash table should be extended. |
table = EnsureCapacity(table, 1, key); |
- table->AddEntry(table->FindInsertionEntry(hash->value()), |
- *key, |
- *value); |
+ table->AddEntry(table->FindInsertionEntry(hash), *key, *value); |
return table; |
} |
@@ -16378,7 +16387,17 @@ Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table, |
return table; |
} |
- int entry = table->FindEntry(key); |
+ return Remove(table, key, was_present, Smi::cast(hash)->value()); |
+} |
+ |
+ |
+Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table, |
+ Handle<Object> key, |
+ bool* was_present, |
+ int32_t hash) { |
+ DCHECK(table->IsKey(*key)); |
+ |
+ int entry = table->FindEntry(table->GetIsolate(), key, hash); |
if (entry == kNotFound) { |
*was_present = false; |
return table; |