Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(398)

Side by Side Diff: src/objects.cc

Issue 1142493002: Use a private own symbol instead of a hidden property for hash codes (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW
« src/isolate.cc ('K') | « src/math.js ('k') | src/runtime/runtime-symbol.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698