Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 7616c9f62c7ad16e5f95380221b2d6bb0a450fcf..ff7a48aeec1e25166444ff8ef127086ec77eb952 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -723,6 +723,49 @@ Object* Object::GetPrototype() { |
} |
+MaybeObject* Object::GetHash(CreationFlag flag) { |
+ // The object is either a number, a string, an odd-ball, |
+ // a real JS object, or a Harmony proxy. |
+ if (IsNumber()) { |
+ uint32_t hash = ComputeLongHash(double_to_uint64(Number())); |
+ return Smi::FromInt(hash & Smi::kMaxValue); |
+ } |
+ if (IsString()) { |
+ uint32_t hash = String::cast(this)->Hash(); |
+ return Smi::FromInt(hash); |
+ } |
+ if (IsOddball()) { |
+ uint32_t hash = Oddball::cast(this)->to_string()->Hash(); |
+ return Smi::FromInt(hash); |
+ } |
+ if (IsJSReceiver()) { |
+ return JSReceiver::cast(this)->GetIdentityHash(flag); |
+ } |
+ |
+ UNREACHABLE(); |
+ return Smi::FromInt(0); |
+} |
+ |
+ |
+bool Object::SameValue(Object* other) { |
+ if (other == this) return true; |
+ if (!IsHeapObject() || !other->IsHeapObject()) return false; |
+ |
+ // The object is either a number, a string, an odd-ball, |
+ // a real JS object, or a Harmony proxy. |
+ if (IsNumber() && other->IsNumber()) { |
+ double this_value = Number(); |
+ double other_value = other->Number(); |
+ return (this_value == other_value) || |
+ (isnan(this_value) && isnan(other_value)); |
+ } |
+ if (IsString() && other->IsString()) { |
+ return String::cast(this)->Equals(String::cast(other)); |
+ } |
+ return false; |
+} |
+ |
+ |
void Object::ShortPrint(FILE* out) { |
HeapStringAllocator allocator; |
StringStream accumulator(&allocator); |
@@ -1270,6 +1313,8 @@ void HeapObject::IterateBody(InstanceType type, int object_size, |
case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
case JS_VALUE_TYPE: |
case JS_ARRAY_TYPE: |
+ case JS_SET_TYPE: |
+ case JS_MAP_TYPE: |
case JS_WEAK_MAP_TYPE: |
case JS_REGEXP_TYPE: |
case JS_GLOBAL_PROXY_TYPE: |
@@ -10827,7 +10872,9 @@ template class HashTable<CompilationCacheShape, HashTableKey*>; |
template class HashTable<MapCacheShape, HashTableKey*>; |
-template class HashTable<ObjectHashTableShape, JSReceiver*>; |
+template class HashTable<ObjectHashTableShape<1>, Object*>; |
+ |
+template class HashTable<ObjectHashTableShape<2>, Object*>; |
template class Dictionary<StringDictionaryShape, String*>; |
@@ -12173,20 +12220,72 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( |
} |
-Object* ObjectHashTable::Lookup(JSReceiver* key) { |
+bool ObjectHashSet::Contains(Object* key) { |
+ // If the object does not have an identity hash, it was never used as a key. |
+ { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); |
+ if (maybe_hash->IsFailure()) return false; |
+ } |
+ return (FindEntry(key) != kNotFound); |
+} |
+ |
+ |
+MaybeObject* ObjectHashSet::Add(Object* key) { |
+ // Make sure the key object has an identity hash code. |
+ int hash; |
+ { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); |
+ if (maybe_hash->IsFailure()) return maybe_hash; |
+ hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); |
+ } |
+ int entry = FindEntry(key); |
+ |
+ // Check whether key is already present. |
+ if (entry != kNotFound) return this; |
+ |
+ // Check whether the hash set should be extended and add entry. |
+ Object* obj; |
+ { MaybeObject* maybe_obj = EnsureCapacity(1, key); |
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
+ } |
+ ObjectHashSet* table = ObjectHashSet::cast(obj); |
+ entry = table->FindInsertionEntry(hash); |
+ table->set(EntryToIndex(entry), key); |
+ table->ElementAdded(); |
+ return table; |
+} |
+ |
+ |
+MaybeObject* ObjectHashSet::Remove(Object* key) { |
// If the object does not have an identity hash, it was never used as a key. |
- MaybeObject* maybe_hash = key->GetIdentityHash(OMIT_CREATION); |
- if (maybe_hash->IsFailure()) return GetHeap()->undefined_value(); |
+ { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); |
+ if (maybe_hash->IsFailure()) return this; |
+ } |
+ int entry = FindEntry(key); |
+ |
+ // Check whether key is actually present. |
+ if (entry == kNotFound) return this; |
+ |
+ // Remove entry and try to shrink this hash set. |
+ set_null(EntryToIndex(entry)); |
+ ElementRemoved(); |
+ return Shrink(key); |
+} |
+ |
+ |
+Object* ObjectHashTable::Lookup(Object* key) { |
+ // If the object does not have an identity hash, it was never used as a key. |
+ { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); |
+ if (maybe_hash->IsFailure()) GetHeap()->undefined_value(); |
+ } |
int entry = FindEntry(key); |
if (entry == kNotFound) return GetHeap()->undefined_value(); |
return get(EntryToIndex(entry) + 1); |
} |
-MaybeObject* ObjectHashTable::Put(JSReceiver* key, Object* value) { |
+MaybeObject* ObjectHashTable::Put(Object* key, Object* value) { |
// Make sure the key object has an identity hash code. |
int hash; |
- { MaybeObject* maybe_hash = key->GetIdentityHash(ALLOW_CREATION); |
+ { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); |
if (maybe_hash->IsFailure()) return maybe_hash; |
hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); |
} |
@@ -12216,7 +12315,7 @@ MaybeObject* ObjectHashTable::Put(JSReceiver* key, Object* value) { |
} |
-void ObjectHashTable::AddEntry(int entry, JSReceiver* key, Object* value) { |
+void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) { |
set(EntryToIndex(entry), key); |
set(EntryToIndex(entry) + 1, value); |
ElementAdded(); |