OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <iomanip> | 5 #include <iomanip> |
6 #include <sstream> | 6 #include <sstream> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
803 return context->symbol_function()->initial_map(); | 803 return context->symbol_function()->initial_map(); |
804 } | 804 } |
805 if (heap_object->IsBoolean()) { | 805 if (heap_object->IsBoolean()) { |
806 return context->boolean_function()->initial_map(); | 806 return context->boolean_function()->initial_map(); |
807 } | 807 } |
808 return isolate->heap()->null_value()->map(); | 808 return isolate->heap()->null_value()->map(); |
809 } | 809 } |
810 | 810 |
811 | 811 |
812 Object* Object::GetHash() { | 812 Object* Object::GetHash() { |
813 Object* hash = GetSimpleHash(); | |
814 if (hash->IsSmi()) return hash; | |
815 | |
816 DCHECK(IsJSReceiver()); | |
817 return JSReceiver::cast(this)->GetIdentityHash(); | |
818 } | |
819 | |
820 | |
821 Object* Object::GetSimpleHash() { | |
813 // The object is either a Smi, a HeapNumber, a name, an odd-ball, | 822 // The object is either a Smi, a HeapNumber, a name, an odd-ball, |
814 // a real JS object, or a Harmony proxy. | 823 // a real JS object, or a Harmony proxy. |
815 if (IsSmi()) { | 824 if (IsSmi()) { |
816 uint32_t hash = ComputeIntegerHash(Smi::cast(this)->value(), kZeroHashSeed); | 825 uint32_t hash = ComputeIntegerHash(Smi::cast(this)->value(), kZeroHashSeed); |
817 return Smi::FromInt(hash & Smi::kMaxValue); | 826 return Smi::FromInt(hash & Smi::kMaxValue); |
818 } | 827 } |
819 if (IsHeapNumber()) { | 828 if (IsHeapNumber()) { |
820 double num = HeapNumber::cast(this)->value(); | 829 double num = HeapNumber::cast(this)->value(); |
821 if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue); | 830 if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue); |
822 if (i::IsMinusZero(num)) num = 0; | 831 if (i::IsMinusZero(num)) num = 0; |
823 if (IsSmiDouble(num)) { | 832 if (IsSmiDouble(num)) { |
824 return Smi::FromInt(FastD2I(num))->GetHash(); | 833 return Smi::FromInt(FastD2I(num))->GetHash(); |
825 } | 834 } |
826 uint32_t hash = ComputeLongHash(double_to_uint64(num)); | 835 uint32_t hash = ComputeLongHash(double_to_uint64(num)); |
827 return Smi::FromInt(hash & Smi::kMaxValue); | 836 return Smi::FromInt(hash & Smi::kMaxValue); |
828 } | 837 } |
829 if (IsName()) { | 838 if (IsName()) { |
830 uint32_t hash = Name::cast(this)->Hash(); | 839 uint32_t hash = Name::cast(this)->Hash(); |
831 return Smi::FromInt(hash); | 840 return Smi::FromInt(hash); |
832 } | 841 } |
833 if (IsOddball()) { | 842 if (IsOddball()) { |
834 uint32_t hash = Oddball::cast(this)->to_string()->Hash(); | 843 uint32_t hash = Oddball::cast(this)->to_string()->Hash(); |
835 return Smi::FromInt(hash); | 844 return Smi::FromInt(hash); |
836 } | 845 } |
837 | |
838 DCHECK(IsJSReceiver()); | 846 DCHECK(IsJSReceiver()); |
839 return JSReceiver::cast(this)->GetIdentityHash(); | 847 JSReceiver* receiver = JSReceiver::cast(this); |
848 return receiver->GetHeap()->undefined_value(); | |
840 } | 849 } |
841 | 850 |
842 | 851 |
843 Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) { | 852 Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) { |
844 Handle<Object> hash(object->GetHash(), isolate); | 853 Handle<Object> hash(object->GetSimpleHash(), isolate); |
845 if (hash->IsSmi()) return Handle<Smi>::cast(hash); | 854 if (hash->IsSmi()) return Handle<Smi>::cast(hash); |
846 | 855 |
847 DCHECK(object->IsJSReceiver()); | 856 DCHECK(object->IsJSReceiver()); |
848 return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object)); | 857 return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object)); |
849 } | 858 } |
850 | 859 |
851 | 860 |
852 bool Object::SameValue(Object* other) { | 861 bool Object::SameValue(Object* other) { |
853 if (other == this) return true; | 862 if (other == this) return true; |
854 | 863 |
(...skipping 4170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5025 // within a smi. | 5034 // within a smi. |
5026 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue; | 5035 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue; |
5027 attempts++; | 5036 attempts++; |
5028 } while (hash_value == 0 && attempts < 30); | 5037 } while (hash_value == 0 && attempts < 30); |
5029 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 | 5038 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 |
5030 | 5039 |
5031 return Smi::FromInt(hash_value); | 5040 return Smi::FromInt(hash_value); |
5032 } | 5041 } |
5033 | 5042 |
5034 | 5043 |
5035 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) { | 5044 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) { |
Toon Verwaest
2015/05/26 09:06:26
Perhaps you should rename this to AddIdentityHash
| |
5036 DCHECK(!object->IsJSGlobalProxy()); | 5045 DCHECK(!object->IsJSGlobalProxy()); |
5037 Isolate* isolate = object->GetIsolate(); | 5046 Isolate* isolate = object->GetIsolate(); |
5038 SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash); | 5047 Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol()); |
5048 JSObject::AddProperty(object, hash_code_symbol, hash, NONE); | |
5039 } | 5049 } |
5040 | 5050 |
5041 | 5051 |
5042 template<typename ProxyType> | 5052 template<typename ProxyType> |
5043 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) { | 5053 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) { |
5044 Isolate* isolate = proxy->GetIsolate(); | 5054 Isolate* isolate = proxy->GetIsolate(); |
5045 | 5055 |
5046 Handle<Object> maybe_hash(proxy->hash(), isolate); | 5056 Handle<Object> maybe_hash(proxy->hash(), isolate); |
5047 if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash); | 5057 if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash); |
5048 | 5058 |
5049 Handle<Smi> hash(GenerateIdentityHash(isolate), isolate); | 5059 Handle<Smi> hash(GenerateIdentityHash(isolate), isolate); |
5050 proxy->set_hash(*hash); | 5060 proxy->set_hash(*hash); |
5051 return hash; | 5061 return hash; |
5052 } | 5062 } |
5053 | 5063 |
5054 | 5064 |
5055 Object* JSObject::GetIdentityHash() { | 5065 Object* JSObject::GetIdentityHash() { |
5056 DisallowHeapAllocation no_gc; | 5066 DisallowHeapAllocation no_gc; |
5057 Isolate* isolate = GetIsolate(); | 5067 Isolate* isolate = GetIsolate(); |
5058 if (IsJSGlobalProxy()) { | 5068 if (IsJSGlobalProxy()) { |
5059 return JSGlobalProxy::cast(this)->hash(); | 5069 return JSGlobalProxy::cast(this)->hash(); |
5060 } | 5070 } |
5061 Object* stored_value = | 5071 Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol()); |
5062 GetHiddenProperty(isolate->factory()->identity_hash_string()); | 5072 Handle<Object> stored_value = |
5063 return stored_value->IsSmi() | 5073 Object::GetPropertyOrElement(Handle<Object>(this, isolate), |
5064 ? stored_value | 5074 hash_code_symbol).ToHandleChecked(); |
5065 : isolate->heap()->undefined_value(); | 5075 return stored_value->IsSmi() ? *stored_value |
5076 : isolate->heap()->undefined_value(); | |
5066 } | 5077 } |
5067 | 5078 |
5068 | 5079 |
5069 Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) { | 5080 Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) { |
5070 if (object->IsJSGlobalProxy()) { | 5081 if (object->IsJSGlobalProxy()) { |
5071 return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object)); | 5082 return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object)); |
5072 } | 5083 } |
5073 | 5084 |
5074 Isolate* isolate = object->GetIsolate(); | 5085 Isolate* isolate = object->GetIsolate(); |
5075 | 5086 |
5076 Handle<Object> maybe_hash(object->GetIdentityHash(), isolate); | 5087 Handle<Object> maybe_hash(object->GetIdentityHash(), isolate); |
5077 if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash); | 5088 if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash); |
5078 | 5089 |
5079 Handle<Smi> hash(GenerateIdentityHash(isolate), isolate); | 5090 Handle<Smi> hash(GenerateIdentityHash(isolate), isolate); |
5080 SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash); | 5091 Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol()); |
5092 JSObject::AddProperty(object, hash_code_symbol, hash, NONE); | |
5081 return hash; | 5093 return hash; |
5082 } | 5094 } |
5083 | 5095 |
5084 | 5096 |
5085 Object* JSProxy::GetIdentityHash() { | 5097 Object* JSProxy::GetIdentityHash() { |
5086 return this->hash(); | 5098 return this->hash(); |
5087 } | 5099 } |
5088 | 5100 |
5089 | 5101 |
5090 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) { | 5102 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) { |
5091 return GetOrCreateIdentityHashHelper(proxy); | 5103 return GetOrCreateIdentityHashHelper(proxy); |
5092 } | 5104 } |
5093 | 5105 |
5094 | 5106 |
5095 Object* JSObject::GetHiddenProperty(Handle<Name> key) { | 5107 Object* JSObject::GetHiddenProperty(Handle<Name> key) { |
5096 DisallowHeapAllocation no_gc; | 5108 DisallowHeapAllocation no_gc; |
5097 DCHECK(key->IsUniqueName()); | 5109 DCHECK(key->IsUniqueName()); |
5098 if (IsJSGlobalProxy()) { | 5110 if (IsJSGlobalProxy()) { |
5099 // JSGlobalProxies store their hash internally. | |
5100 DCHECK(*key != GetHeap()->identity_hash_string()); | |
5101 // For a proxy, use the prototype as target object. | 5111 // For a proxy, use the prototype as target object. |
5102 PrototypeIterator iter(GetIsolate(), this); | 5112 PrototypeIterator iter(GetIsolate(), this); |
5103 // If the proxy is detached, return undefined. | 5113 // If the proxy is detached, return undefined. |
5104 if (iter.IsAtEnd()) return GetHeap()->the_hole_value(); | 5114 if (iter.IsAtEnd()) return GetHeap()->the_hole_value(); |
5105 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); | 5115 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); |
5106 return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key); | 5116 return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key); |
5107 } | 5117 } |
5108 DCHECK(!IsJSGlobalProxy()); | 5118 DCHECK(!IsJSGlobalProxy()); |
5109 Object* inline_value = GetHiddenPropertiesHashTable(); | 5119 Object* inline_value = GetHiddenPropertiesHashTable(); |
5110 | 5120 |
5111 if (inline_value->IsSmi()) { | |
5112 // Handle inline-stored identity hash. | |
5113 if (*key == GetHeap()->identity_hash_string()) { | |
5114 return inline_value; | |
5115 } else { | |
5116 return GetHeap()->the_hole_value(); | |
5117 } | |
5118 } | |
5119 | |
5120 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); | 5121 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); |
5121 | 5122 |
5122 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); | 5123 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); |
5123 Object* entry = hashtable->Lookup(key); | 5124 Object* entry = hashtable->Lookup(key); |
5124 return entry; | 5125 return entry; |
5125 } | 5126 } |
5126 | 5127 |
5127 | 5128 |
5128 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, | 5129 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, |
5129 Handle<Name> key, | 5130 Handle<Name> key, |
5130 Handle<Object> value) { | 5131 Handle<Object> value) { |
5131 Isolate* isolate = object->GetIsolate(); | 5132 Isolate* isolate = object->GetIsolate(); |
5132 | 5133 |
5133 DCHECK(key->IsUniqueName()); | 5134 DCHECK(key->IsUniqueName()); |
5134 if (object->IsJSGlobalProxy()) { | 5135 if (object->IsJSGlobalProxy()) { |
5135 // JSGlobalProxies store their hash internally. | |
5136 DCHECK(*key != *isolate->factory()->identity_hash_string()); | |
5137 // For a proxy, use the prototype as target object. | 5136 // For a proxy, use the prototype as target object. |
5138 PrototypeIterator iter(isolate, object); | 5137 PrototypeIterator iter(isolate, object); |
5139 // If the proxy is detached, return undefined. | 5138 // If the proxy is detached, return undefined. |
5140 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); | 5139 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); |
5141 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5140 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
5142 return SetHiddenProperty( | 5141 return SetHiddenProperty( |
5143 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key, | 5142 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key, |
5144 value); | 5143 value); |
5145 } | 5144 } |
5146 DCHECK(!object->IsJSGlobalProxy()); | 5145 DCHECK(!object->IsJSGlobalProxy()); |
5147 | 5146 |
5148 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); | 5147 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); |
5149 | 5148 |
5150 // If there is no backing store yet, store the identity hash inline. | |
5151 if (value->IsSmi() && | |
5152 *key == *isolate->factory()->identity_hash_string() && | |
5153 (inline_value->IsUndefined() || inline_value->IsSmi())) { | |
5154 return JSObject::SetHiddenPropertiesHashTable(object, value); | |
5155 } | |
5156 | |
5157 Handle<ObjectHashTable> hashtable = | 5149 Handle<ObjectHashTable> hashtable = |
5158 GetOrCreateHiddenPropertiesHashtable(object); | 5150 GetOrCreateHiddenPropertiesHashtable(object); |
5159 | 5151 |
5160 // If it was found, check if the key is already in the dictionary. | 5152 // If it was found, check if the key is already in the dictionary. |
5161 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key, | 5153 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key, |
5162 value); | 5154 value); |
5163 if (*new_table != *hashtable) { | 5155 if (*new_table != *hashtable) { |
5164 // If adding the key expanded the dictionary (i.e., Add returned a new | 5156 // If adding the key expanded the dictionary (i.e., Add returned a new |
5165 // dictionary), store it back to the object. | 5157 // dictionary), store it back to the object. |
5166 SetHiddenPropertiesHashTable(object, new_table); | 5158 SetHiddenPropertiesHashTable(object, new_table); |
(...skipping 11 matching lines...) Expand all Loading... | |
5178 if (object->IsJSGlobalProxy()) { | 5170 if (object->IsJSGlobalProxy()) { |
5179 PrototypeIterator iter(isolate, object); | 5171 PrototypeIterator iter(isolate, object); |
5180 if (iter.IsAtEnd()) return; | 5172 if (iter.IsAtEnd()) return; |
5181 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5173 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
5182 return DeleteHiddenProperty( | 5174 return DeleteHiddenProperty( |
5183 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key); | 5175 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key); |
5184 } | 5176 } |
5185 | 5177 |
5186 Object* inline_value = object->GetHiddenPropertiesHashTable(); | 5178 Object* inline_value = object->GetHiddenPropertiesHashTable(); |
5187 | 5179 |
5188 // We never delete (inline-stored) identity hashes. | 5180 if (inline_value->IsUndefined()) return; |
5189 DCHECK(*key != *isolate->factory()->identity_hash_string()); | |
5190 if (inline_value->IsUndefined() || inline_value->IsSmi()) return; | |
5191 | 5181 |
5192 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); | 5182 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); |
5193 bool was_present = false; | 5183 bool was_present = false; |
5194 ObjectHashTable::Remove(hashtable, key, &was_present); | 5184 ObjectHashTable::Remove(hashtable, key, &was_present); |
5195 } | 5185 } |
5196 | 5186 |
5197 | 5187 |
5198 bool JSObject::HasHiddenProperties(Handle<JSObject> object) { | 5188 bool JSObject::HasHiddenProperties(Handle<JSObject> object) { |
5199 Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string(); | 5189 Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string(); |
5200 LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR); | 5190 LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5244 | 5234 |
5245 static const int kInitialCapacity = 4; | 5235 static const int kInitialCapacity = 4; |
5246 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); | 5236 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); |
5247 if (inline_value->IsHashTable()) { | 5237 if (inline_value->IsHashTable()) { |
5248 return Handle<ObjectHashTable>::cast(inline_value); | 5238 return Handle<ObjectHashTable>::cast(inline_value); |
5249 } | 5239 } |
5250 | 5240 |
5251 Handle<ObjectHashTable> hashtable = ObjectHashTable::New( | 5241 Handle<ObjectHashTable> hashtable = ObjectHashTable::New( |
5252 isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY); | 5242 isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY); |
5253 | 5243 |
5254 if (inline_value->IsSmi()) { | 5244 DCHECK(inline_value->IsUndefined()); |
5255 // We were storing the identity hash inline and now allocated an actual | |
5256 // dictionary. Put the identity hash into the new dictionary. | |
5257 hashtable = ObjectHashTable::Put(hashtable, | |
5258 isolate->factory()->identity_hash_string(), | |
5259 inline_value); | |
5260 } | |
5261 | |
5262 SetHiddenPropertiesHashTable(object, hashtable); | 5245 SetHiddenPropertiesHashTable(object, hashtable); |
5263 return hashtable; | 5246 return hashtable; |
5264 } | 5247 } |
5265 | 5248 |
5266 | 5249 |
5267 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, | 5250 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, |
5268 Handle<Object> value) { | 5251 Handle<Object> value) { |
5269 DCHECK(!object->IsJSGlobalProxy()); | 5252 DCHECK(!object->IsJSGlobalProxy()); |
5270 Isolate* isolate = object->GetIsolate(); | 5253 Isolate* isolate = object->GetIsolate(); |
5271 Handle<Name> name = isolate->factory()->hidden_string(); | 5254 Handle<Name> name = isolate->factory()->hidden_string(); |
(...skipping 11042 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16314 e = PropertyCell::cast(e)->value(); | 16297 e = PropertyCell::cast(e)->value(); |
16315 } | 16298 } |
16316 if (e == value) return k; | 16299 if (e == value) return k; |
16317 } | 16300 } |
16318 } | 16301 } |
16319 Heap* heap = Dictionary::GetHeap(); | 16302 Heap* heap = Dictionary::GetHeap(); |
16320 return heap->undefined_value(); | 16303 return heap->undefined_value(); |
16321 } | 16304 } |
16322 | 16305 |
16323 | 16306 |
16307 Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key, | |
16308 int32_t hash) { | |
16309 DisallowHeapAllocation no_gc; | |
16310 DCHECK(IsKey(*key)); | |
16311 | |
16312 int entry = FindEntry(isolate, key, hash); | |
16313 if (entry == kNotFound) return isolate->heap()->the_hole_value(); | |
16314 return get(EntryToIndex(entry) + 1); | |
16315 } | |
16316 | |
16317 | |
16324 Object* ObjectHashTable::Lookup(Handle<Object> key) { | 16318 Object* ObjectHashTable::Lookup(Handle<Object> key) { |
16325 DisallowHeapAllocation no_gc; | 16319 DisallowHeapAllocation no_gc; |
16326 DCHECK(IsKey(*key)); | 16320 DCHECK(IsKey(*key)); |
16327 | 16321 |
16322 Isolate* isolate = GetIsolate(); | |
16323 | |
16328 // If the object does not have an identity hash, it was never used as a key. | 16324 // If the object does not have an identity hash, it was never used as a key. |
16329 Object* hash = key->GetHash(); | 16325 Object* hash = key->GetHash(); |
16330 if (hash->IsUndefined()) { | 16326 if (hash->IsUndefined()) { |
16331 return GetHeap()->the_hole_value(); | 16327 return isolate->heap()->the_hole_value(); |
16332 } | 16328 } |
16333 int entry = FindEntry(key); | 16329 return Lookup(isolate, key, Smi::cast(hash)->value()); |
16334 if (entry == kNotFound) return GetHeap()->the_hole_value(); | |
16335 return get(EntryToIndex(entry) + 1); | |
16336 } | 16330 } |
16337 | 16331 |
16338 | 16332 |
16333 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) { | |
16334 return Lookup(GetIsolate(), key, hash); | |
16335 } | |
16336 | |
16337 | |
16339 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, | 16338 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, |
16340 Handle<Object> key, | 16339 Handle<Object> key, |
16341 Handle<Object> value) { | 16340 Handle<Object> value) { |
16342 DCHECK(table->IsKey(*key)); | 16341 DCHECK(table->IsKey(*key)); |
16343 DCHECK(!value->IsTheHole()); | 16342 DCHECK(!value->IsTheHole()); |
16344 | 16343 |
16345 Isolate* isolate = table->GetIsolate(); | 16344 Isolate* isolate = table->GetIsolate(); |
16345 // Make sure the key object has an identity hash code. | |
16346 int32_t hash = Object::GetOrCreateHash(isolate, key)->value(); | |
16347 | |
16348 return Put(table, key, value, hash); | |
16349 } | |
16350 | |
16351 | |
16352 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, | |
16353 Handle<Object> key, | |
16354 Handle<Object> value, | |
16355 int32_t hash) { | |
16356 DCHECK(table->IsKey(*key)); | |
16357 DCHECK(!value->IsTheHole()); | |
16358 | |
16359 Isolate* isolate = table->GetIsolate(); | |
16346 | 16360 |
16347 // Make sure the key object has an identity hash code. | 16361 int entry = table->FindEntry(isolate, key, hash); |
16348 Handle<Smi> hash = Object::GetOrCreateHash(isolate, key); | |
16349 | |
16350 int entry = table->FindEntry(key); | |
16351 | 16362 |
16352 // Key is already in table, just overwrite value. | 16363 // Key is already in table, just overwrite value. |
16353 if (entry != kNotFound) { | 16364 if (entry != kNotFound) { |
16354 table->set(EntryToIndex(entry) + 1, *value); | 16365 table->set(EntryToIndex(entry) + 1, *value); |
16355 return table; | 16366 return table; |
16356 } | 16367 } |
16357 | 16368 |
16358 // Check whether the hash table should be extended. | 16369 // Check whether the hash table should be extended. |
16359 table = EnsureCapacity(table, 1, key); | 16370 table = EnsureCapacity(table, 1, key); |
16360 table->AddEntry(table->FindInsertionEntry(hash->value()), | 16371 table->AddEntry(table->FindInsertionEntry(hash), *key, *value); |
16361 *key, | |
16362 *value); | |
16363 return table; | 16372 return table; |
16364 } | 16373 } |
16365 | 16374 |
16366 | 16375 |
16367 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table, | 16376 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table, |
16368 Handle<Object> key, | 16377 Handle<Object> key, |
16369 bool* was_present) { | 16378 bool* was_present) { |
16370 DCHECK(table->IsKey(*key)); | 16379 DCHECK(table->IsKey(*key)); |
16371 | 16380 |
16372 Object* hash = key->GetHash(); | 16381 Object* hash = key->GetHash(); |
16373 if (hash->IsUndefined()) { | 16382 if (hash->IsUndefined()) { |
16374 *was_present = false; | 16383 *was_present = false; |
16375 return table; | 16384 return table; |
16376 } | 16385 } |
16377 | 16386 |
16378 int entry = table->FindEntry(key); | 16387 return Remove(table, key, was_present, Smi::cast(hash)->value()); |
16388 } | |
16389 | |
16390 | |
16391 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table, | |
16392 Handle<Object> key, | |
16393 bool* was_present, | |
16394 int32_t hash) { | |
16395 DCHECK(table->IsKey(*key)); | |
16396 | |
16397 int entry = table->FindEntry(table->GetIsolate(), key, hash); | |
16379 if (entry == kNotFound) { | 16398 if (entry == kNotFound) { |
16380 *was_present = false; | 16399 *was_present = false; |
16381 return table; | 16400 return table; |
16382 } | 16401 } |
16383 | 16402 |
16384 *was_present = true; | 16403 *was_present = true; |
16385 table->RemoveEntry(entry); | 16404 table->RemoveEntry(entry); |
16386 return Shrink(table, key); | 16405 return Shrink(table, key); |
16387 } | 16406 } |
16388 | 16407 |
(...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17325 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, | 17344 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, |
17326 Handle<Object> new_value) { | 17345 Handle<Object> new_value) { |
17327 if (cell->value() != *new_value) { | 17346 if (cell->value() != *new_value) { |
17328 cell->set_value(*new_value); | 17347 cell->set_value(*new_value); |
17329 Isolate* isolate = cell->GetIsolate(); | 17348 Isolate* isolate = cell->GetIsolate(); |
17330 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17349 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17331 isolate, DependentCode::kPropertyCellChangedGroup); | 17350 isolate, DependentCode::kPropertyCellChangedGroup); |
17332 } | 17351 } |
17333 } | 17352 } |
17334 } } // namespace v8::internal | 17353 } } // namespace v8::internal |
OLD | NEW |