Chromium Code Reviews| 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 4996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5007 } while (hash_value == 0 && attempts < 30); | 5007 } while (hash_value == 0 && attempts < 30); |
| 5008 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 | 5008 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 |
| 5009 | 5009 |
| 5010 return Smi::FromInt(hash_value); | 5010 return Smi::FromInt(hash_value); |
| 5011 } | 5011 } |
| 5012 | 5012 |
| 5013 | 5013 |
| 5014 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) { | 5014 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) { |
| 5015 DCHECK(!object->IsJSGlobalProxy()); | 5015 DCHECK(!object->IsJSGlobalProxy()); |
| 5016 Isolate* isolate = object->GetIsolate(); | 5016 Isolate* isolate = object->GetIsolate(); |
| 5017 SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash); | 5017 Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol()); |
| 5018 JSObject::AddProperty(object, hash_code_symbol, hash, NONE); | |
| 5018 } | 5019 } |
| 5019 | 5020 |
| 5020 | 5021 |
| 5021 template<typename ProxyType> | 5022 template<typename ProxyType> |
| 5022 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) { | 5023 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) { |
| 5023 Isolate* isolate = proxy->GetIsolate(); | 5024 Isolate* isolate = proxy->GetIsolate(); |
| 5024 | 5025 |
| 5025 Handle<Object> maybe_hash(proxy->hash(), isolate); | 5026 Handle<Object> maybe_hash(proxy->hash(), isolate); |
| 5026 if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash); | 5027 if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash); |
| 5027 | 5028 |
| 5028 Handle<Smi> hash(GenerateIdentityHash(isolate), isolate); | 5029 Handle<Smi> hash(GenerateIdentityHash(isolate), isolate); |
| 5029 proxy->set_hash(*hash); | 5030 proxy->set_hash(*hash); |
| 5030 return hash; | 5031 return hash; |
| 5031 } | 5032 } |
| 5032 | 5033 |
| 5033 | 5034 |
| 5034 Object* JSObject::GetIdentityHash() { | 5035 Object* JSObject::GetIdentityHash() { |
| 5035 DisallowHeapAllocation no_gc; | 5036 DisallowHeapAllocation no_gc; |
| 5036 Isolate* isolate = GetIsolate(); | 5037 Isolate* isolate = GetIsolate(); |
| 5037 if (IsJSGlobalProxy()) { | 5038 if (IsJSGlobalProxy()) { |
| 5038 return JSGlobalProxy::cast(this)->hash(); | 5039 return JSGlobalProxy::cast(this)->hash(); |
|
adamk
2015/05/19 17:39:38
To expand slightly on Toon's explanation, here's t
| |
| 5039 } | 5040 } |
| 5040 Object* stored_value = | 5041 Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol()); |
| 5041 GetHiddenProperty(isolate->factory()->identity_hash_string()); | 5042 Handle<Object> stored_value = |
| 5042 return stored_value->IsSmi() | 5043 Object::GetPropertyOrElement(Handle<Object>(this, isolate), |
| 5043 ? stored_value | 5044 hash_code_symbol).ToHandleChecked(); |
| 5044 : isolate->heap()->undefined_value(); | 5045 return stored_value->IsSmi() ? *stored_value |
| 5046 : isolate->heap()->undefined_value(); | |
| 5045 } | 5047 } |
| 5046 | 5048 |
| 5047 | 5049 |
| 5048 Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) { | 5050 Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) { |
| 5049 if (object->IsJSGlobalProxy()) { | 5051 if (object->IsJSGlobalProxy()) { |
| 5050 return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object)); | 5052 return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object)); |
| 5051 } | 5053 } |
| 5052 | 5054 |
| 5053 Isolate* isolate = object->GetIsolate(); | 5055 Isolate* isolate = object->GetIsolate(); |
| 5054 | 5056 |
| 5055 Handle<Object> maybe_hash(object->GetIdentityHash(), isolate); | 5057 Handle<Object> maybe_hash(object->GetIdentityHash(), isolate); |
| 5056 if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash); | 5058 if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash); |
| 5057 | 5059 |
| 5058 Handle<Smi> hash(GenerateIdentityHash(isolate), isolate); | 5060 Handle<Smi> hash(GenerateIdentityHash(isolate), isolate); |
| 5059 SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash); | 5061 Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol()); |
| 5062 JSObject::AddProperty(object, hash_code_symbol, hash, NONE); | |
| 5060 return hash; | 5063 return hash; |
| 5061 } | 5064 } |
| 5062 | 5065 |
| 5063 | 5066 |
| 5064 Object* JSProxy::GetIdentityHash() { | 5067 Object* JSProxy::GetIdentityHash() { |
| 5065 return this->hash(); | 5068 return this->hash(); |
| 5066 } | 5069 } |
| 5067 | 5070 |
| 5068 | 5071 |
| 5069 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) { | 5072 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) { |
| 5070 return GetOrCreateIdentityHashHelper(proxy); | 5073 return GetOrCreateIdentityHashHelper(proxy); |
| 5071 } | 5074 } |
| 5072 | 5075 |
| 5073 | 5076 |
| 5074 Object* JSObject::GetHiddenProperty(Handle<Name> key) { | 5077 Object* JSObject::GetHiddenProperty(Handle<Name> key) { |
| 5075 DisallowHeapAllocation no_gc; | 5078 DisallowHeapAllocation no_gc; |
| 5076 DCHECK(key->IsUniqueName()); | 5079 DCHECK(key->IsUniqueName()); |
| 5077 if (IsJSGlobalProxy()) { | 5080 if (IsJSGlobalProxy()) { |
| 5078 // JSGlobalProxies store their hash internally. | |
| 5079 DCHECK(*key != GetHeap()->identity_hash_string()); | |
| 5080 // For a proxy, use the prototype as target object. | 5081 // For a proxy, use the prototype as target object. |
| 5081 PrototypeIterator iter(GetIsolate(), this); | 5082 PrototypeIterator iter(GetIsolate(), this); |
| 5082 // If the proxy is detached, return undefined. | 5083 // If the proxy is detached, return undefined. |
| 5083 if (iter.IsAtEnd()) return GetHeap()->the_hole_value(); | 5084 if (iter.IsAtEnd()) return GetHeap()->the_hole_value(); |
| 5084 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); | 5085 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); |
| 5085 return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key); | 5086 return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key); |
| 5086 } | 5087 } |
| 5087 DCHECK(!IsJSGlobalProxy()); | 5088 DCHECK(!IsJSGlobalProxy()); |
| 5088 Object* inline_value = GetHiddenPropertiesHashTable(); | 5089 Object* inline_value = GetHiddenPropertiesHashTable(); |
| 5089 | 5090 |
| 5090 if (inline_value->IsSmi()) { | 5091 DCHECK(!inline_value->IsSmi()); |
| 5091 // Handle inline-stored identity hash. | |
| 5092 if (*key == GetHeap()->identity_hash_string()) { | |
| 5093 return inline_value; | |
| 5094 } else { | |
| 5095 return GetHeap()->the_hole_value(); | |
| 5096 } | |
| 5097 } | |
| 5098 | |
| 5099 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); | 5092 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); |
| 5100 | 5093 |
| 5101 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); | 5094 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); |
| 5102 Object* entry = hashtable->Lookup(key); | 5095 Object* entry = hashtable->Lookup(key); |
| 5103 return entry; | 5096 return entry; |
| 5104 } | 5097 } |
| 5105 | 5098 |
| 5106 | 5099 |
| 5107 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, | 5100 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, |
| 5108 Handle<Name> key, | 5101 Handle<Name> key, |
| 5109 Handle<Object> value) { | 5102 Handle<Object> value) { |
| 5110 Isolate* isolate = object->GetIsolate(); | 5103 Isolate* isolate = object->GetIsolate(); |
| 5111 | 5104 |
| 5112 DCHECK(key->IsUniqueName()); | 5105 DCHECK(key->IsUniqueName()); |
| 5113 if (object->IsJSGlobalProxy()) { | 5106 if (object->IsJSGlobalProxy()) { |
| 5114 // JSGlobalProxies store their hash internally. | |
| 5115 DCHECK(*key != *isolate->factory()->identity_hash_string()); | |
| 5116 // For a proxy, use the prototype as target object. | 5107 // For a proxy, use the prototype as target object. |
| 5117 PrototypeIterator iter(isolate, object); | 5108 PrototypeIterator iter(isolate, object); |
| 5118 // If the proxy is detached, return undefined. | 5109 // If the proxy is detached, return undefined. |
| 5119 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); | 5110 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); |
| 5120 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5111 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 5121 return SetHiddenProperty( | 5112 return SetHiddenProperty( |
| 5122 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key, | 5113 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key, |
| 5123 value); | 5114 value); |
| 5124 } | 5115 } |
| 5125 DCHECK(!object->IsJSGlobalProxy()); | 5116 DCHECK(!object->IsJSGlobalProxy()); |
| 5126 | 5117 |
| 5127 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); | 5118 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); |
| 5128 | 5119 |
| 5129 // If there is no backing store yet, store the identity hash inline. | |
| 5130 if (value->IsSmi() && | |
| 5131 *key == *isolate->factory()->identity_hash_string() && | |
| 5132 (inline_value->IsUndefined() || inline_value->IsSmi())) { | |
| 5133 return JSObject::SetHiddenPropertiesHashTable(object, value); | |
| 5134 } | |
| 5135 | |
| 5136 Handle<ObjectHashTable> hashtable = | 5120 Handle<ObjectHashTable> hashtable = |
| 5137 GetOrCreateHiddenPropertiesHashtable(object); | 5121 GetOrCreateHiddenPropertiesHashtable(object); |
| 5138 | 5122 |
| 5139 // If it was found, check if the key is already in the dictionary. | 5123 // If it was found, check if the key is already in the dictionary. |
| 5140 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key, | 5124 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key, |
| 5141 value); | 5125 value); |
| 5142 if (*new_table != *hashtable) { | 5126 if (*new_table != *hashtable) { |
| 5143 // If adding the key expanded the dictionary (i.e., Add returned a new | 5127 // If adding the key expanded the dictionary (i.e., Add returned a new |
| 5144 // dictionary), store it back to the object. | 5128 // dictionary), store it back to the object. |
| 5145 SetHiddenPropertiesHashTable(object, new_table); | 5129 SetHiddenPropertiesHashTable(object, new_table); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 5157 if (object->IsJSGlobalProxy()) { | 5141 if (object->IsJSGlobalProxy()) { |
| 5158 PrototypeIterator iter(isolate, object); | 5142 PrototypeIterator iter(isolate, object); |
| 5159 if (iter.IsAtEnd()) return; | 5143 if (iter.IsAtEnd()) return; |
| 5160 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5144 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 5161 return DeleteHiddenProperty( | 5145 return DeleteHiddenProperty( |
| 5162 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key); | 5146 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key); |
| 5163 } | 5147 } |
| 5164 | 5148 |
| 5165 Object* inline_value = object->GetHiddenPropertiesHashTable(); | 5149 Object* inline_value = object->GetHiddenPropertiesHashTable(); |
| 5166 | 5150 |
| 5167 // We never delete (inline-stored) identity hashes. | 5151 DCHECK(!inline_value->IsSmi()); |
| 5168 DCHECK(*key != *isolate->factory()->identity_hash_string()); | 5152 if (inline_value->IsUndefined()) return; |
| 5169 if (inline_value->IsUndefined() || inline_value->IsSmi()) return; | |
| 5170 | 5153 |
| 5171 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); | 5154 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); |
| 5172 bool was_present = false; | 5155 bool was_present = false; |
| 5173 ObjectHashTable::Remove(hashtable, key, &was_present); | 5156 ObjectHashTable::Remove(hashtable, key, &was_present); |
| 5174 } | 5157 } |
| 5175 | 5158 |
| 5176 | 5159 |
| 5177 bool JSObject::HasHiddenProperties(Handle<JSObject> object) { | 5160 bool JSObject::HasHiddenProperties(Handle<JSObject> object) { |
| 5178 Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string(); | 5161 Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string(); |
| 5179 LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR); | 5162 LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5223 | 5206 |
| 5224 static const int kInitialCapacity = 4; | 5207 static const int kInitialCapacity = 4; |
| 5225 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); | 5208 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); |
| 5226 if (inline_value->IsHashTable()) { | 5209 if (inline_value->IsHashTable()) { |
| 5227 return Handle<ObjectHashTable>::cast(inline_value); | 5210 return Handle<ObjectHashTable>::cast(inline_value); |
| 5228 } | 5211 } |
| 5229 | 5212 |
| 5230 Handle<ObjectHashTable> hashtable = ObjectHashTable::New( | 5213 Handle<ObjectHashTable> hashtable = ObjectHashTable::New( |
| 5231 isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY); | 5214 isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY); |
| 5232 | 5215 |
| 5233 if (inline_value->IsSmi()) { | 5216 DCHECK(inline_value->IsUndefined()); |
| 5234 // We were storing the identity hash inline and now allocated an actual | |
| 5235 // dictionary. Put the identity hash into the new dictionary. | |
| 5236 hashtable = ObjectHashTable::Put(hashtable, | |
| 5237 isolate->factory()->identity_hash_string(), | |
| 5238 inline_value); | |
| 5239 } | |
| 5240 | |
| 5241 SetHiddenPropertiesHashTable(object, hashtable); | 5217 SetHiddenPropertiesHashTable(object, hashtable); |
| 5242 return hashtable; | 5218 return hashtable; |
| 5243 } | 5219 } |
| 5244 | 5220 |
| 5245 | 5221 |
| 5246 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, | 5222 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, |
| 5247 Handle<Object> value) { | 5223 Handle<Object> value) { |
| 5248 DCHECK(!object->IsJSGlobalProxy()); | 5224 DCHECK(!object->IsJSGlobalProxy()); |
| 5249 Isolate* isolate = object->GetIsolate(); | 5225 Isolate* isolate = object->GetIsolate(); |
| 5250 Handle<Name> name = isolate->factory()->hidden_string(); | 5226 Handle<Name> name = isolate->factory()->hidden_string(); |
| (...skipping 11995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 17246 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, | 17222 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, |
| 17247 Handle<Object> new_value) { | 17223 Handle<Object> new_value) { |
| 17248 if (cell->value() != *new_value) { | 17224 if (cell->value() != *new_value) { |
| 17249 cell->set_value(*new_value); | 17225 cell->set_value(*new_value); |
| 17250 Isolate* isolate = cell->GetIsolate(); | 17226 Isolate* isolate = cell->GetIsolate(); |
| 17251 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17227 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17252 isolate, DependentCode::kPropertyCellChangedGroup); | 17228 isolate, DependentCode::kPropertyCellChangedGroup); |
| 17253 } | 17229 } |
| 17254 } | 17230 } |
| 17255 } } // namespace v8::internal | 17231 } } // namespace v8::internal |
| OLD | NEW |