| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 3147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3158 PrintF("Object elements have been normalized:\n"); | 3158 PrintF("Object elements have been normalized:\n"); |
| 3159 Print(); | 3159 Print(); |
| 3160 } | 3160 } |
| 3161 #endif | 3161 #endif |
| 3162 | 3162 |
| 3163 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 3163 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
| 3164 return dictionary; | 3164 return dictionary; |
| 3165 } | 3165 } |
| 3166 | 3166 |
| 3167 | 3167 |
| 3168 MaybeObject* JSObject::GetHiddenProperties(HiddenPropertiesFlag flag) { | 3168 MaybeObject* JSObject::GetHiddenProperties(CreationFlag flag) { |
| 3169 Isolate* isolate = GetIsolate(); | 3169 Isolate* isolate = GetIsolate(); |
| 3170 Heap* heap = isolate->heap(); | 3170 Heap* heap = isolate->heap(); |
| 3171 Object* holder = BypassGlobalProxy(); | 3171 Object* holder = BypassGlobalProxy(); |
| 3172 if (holder->IsUndefined()) return heap->undefined_value(); | 3172 if (holder->IsUndefined()) return heap->undefined_value(); |
| 3173 JSObject* obj = JSObject::cast(holder); | 3173 JSObject* obj = JSObject::cast(holder); |
| 3174 if (obj->HasFastProperties()) { | 3174 if (obj->HasFastProperties()) { |
| 3175 // If the object has fast properties, check whether the first slot | 3175 // If the object has fast properties, check whether the first slot |
| 3176 // in the descriptor array matches the hidden symbol. Since the | 3176 // in the descriptor array matches the hidden symbol. Since the |
| 3177 // hidden symbols hash code is zero (and no other string has hash | 3177 // hidden symbols hash code is zero (and no other string has hash |
| 3178 // code zero) it will always occupy the first entry if present. | 3178 // code zero) it will always occupy the first entry if present. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3198 } | 3198 } |
| 3199 return obj->SetHiddenPropertiesObject(hidden_obj); | 3199 return obj->SetHiddenPropertiesObject(hidden_obj); |
| 3200 } else { | 3200 } else { |
| 3201 return heap->undefined_value(); | 3201 return heap->undefined_value(); |
| 3202 } | 3202 } |
| 3203 } | 3203 } |
| 3204 return obj->GetHiddenPropertiesObject(); | 3204 return obj->GetHiddenPropertiesObject(); |
| 3205 } | 3205 } |
| 3206 | 3206 |
| 3207 | 3207 |
| 3208 MaybeObject* JSObject::GetIdentityHash(HiddenPropertiesFlag flag) { | 3208 Smi* JSReceiver::GenerateIdentityHash() { |
| 3209 Isolate* isolate = GetIsolate(); |
| 3210 |
| 3211 int hash_value; |
| 3212 int attempts = 0; |
| 3213 do { |
| 3214 // Generate a random 32-bit hash value but limit range to fit |
| 3215 // within a smi. |
| 3216 hash_value = V8::Random(isolate) & Smi::kMaxValue; |
| 3217 attempts++; |
| 3218 } while (hash_value == 0 && attempts < 30); |
| 3219 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 |
| 3220 |
| 3221 return Smi::FromInt(hash_value); |
| 3222 } |
| 3223 |
| 3224 |
| 3225 MaybeObject* JSObject::SetIdentityHash(Object* hash, CreationFlag flag) { |
| 3226 JSObject* hidden_props; |
| 3227 MaybeObject* maybe = GetHiddenProperties(flag); |
| 3228 if (!maybe->To<JSObject>(&hidden_props)) return maybe; |
| 3229 maybe = hidden_props->SetLocalPropertyIgnoreAttributes( |
| 3230 GetHeap()->identity_hash_symbol(), hash, NONE); |
| 3231 if (maybe->IsFailure()) return maybe; |
| 3232 return this; |
| 3233 } |
| 3234 |
| 3235 |
| 3236 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) { |
| 3209 Isolate* isolate = GetIsolate(); | 3237 Isolate* isolate = GetIsolate(); |
| 3210 Object* hidden_props_obj; | 3238 Object* hidden_props_obj; |
| 3211 { MaybeObject* maybe_obj = GetHiddenProperties(flag); | 3239 { MaybeObject* maybe_obj = GetHiddenProperties(flag); |
| 3212 if (!maybe_obj->ToObject(&hidden_props_obj)) return maybe_obj; | 3240 if (!maybe_obj->ToObject(&hidden_props_obj)) return maybe_obj; |
| 3213 } | 3241 } |
| 3214 if (!hidden_props_obj->IsJSObject()) { | 3242 if (!hidden_props_obj->IsJSObject()) { |
| 3215 // We failed to create hidden properties. That's a detached | 3243 // We failed to create hidden properties. That's a detached |
| 3216 // global proxy. | 3244 // global proxy. |
| 3217 ASSERT(hidden_props_obj->IsUndefined()); | 3245 ASSERT(hidden_props_obj->IsUndefined()); |
| 3218 return Smi::FromInt(0); | 3246 return Smi::FromInt(0); |
| 3219 } | 3247 } |
| 3220 JSObject* hidden_props = JSObject::cast(hidden_props_obj); | 3248 JSObject* hidden_props = JSObject::cast(hidden_props_obj); |
| 3221 String* hash_symbol = isolate->heap()->identity_hash_symbol(); | 3249 String* hash_symbol = isolate->heap()->identity_hash_symbol(); |
| 3222 { | 3250 { |
| 3223 // Note that HasLocalProperty() can cause a GC in the general case in the | 3251 // Note that HasLocalProperty() can cause a GC in the general case in the |
| 3224 // presence of interceptors. | 3252 // presence of interceptors. |
| 3225 AssertNoAllocation no_alloc; | 3253 AssertNoAllocation no_alloc; |
| 3226 if (hidden_props->HasLocalProperty(hash_symbol)) { | 3254 if (hidden_props->HasLocalProperty(hash_symbol)) { |
| 3227 MaybeObject* hash = hidden_props->GetProperty(hash_symbol); | 3255 MaybeObject* hash = hidden_props->GetProperty(hash_symbol); |
| 3228 return Smi::cast(hash->ToObjectChecked()); | 3256 return Smi::cast(hash->ToObjectChecked()); |
| 3229 } | 3257 } |
| 3230 } | 3258 } |
| 3231 | 3259 |
| 3232 int hash_value; | 3260 Smi* hash = GenerateIdentityHash(); |
| 3233 int attempts = 0; | |
| 3234 do { | |
| 3235 // Generate a random 32-bit hash value but limit range to fit | |
| 3236 // within a smi. | |
| 3237 hash_value = V8::Random(isolate) & Smi::kMaxValue; | |
| 3238 attempts++; | |
| 3239 } while (hash_value == 0 && attempts < 30); | |
| 3240 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 | |
| 3241 | |
| 3242 Smi* hash = Smi::FromInt(hash_value); | |
| 3243 { MaybeObject* result = hidden_props->SetLocalPropertyIgnoreAttributes( | 3261 { MaybeObject* result = hidden_props->SetLocalPropertyIgnoreAttributes( |
| 3244 hash_symbol, | 3262 hash_symbol, |
| 3245 hash, | 3263 hash, |
| 3246 static_cast<PropertyAttributes>(None)); | 3264 static_cast<PropertyAttributes>(None)); |
| 3247 if (result->IsFailure()) return result; | 3265 if (result->IsFailure()) return result; |
| 3248 } | 3266 } |
| 3249 return hash; | 3267 return hash; |
| 3250 } | 3268 } |
| 3251 | 3269 |
| 3252 | 3270 |
| 3271 MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) { |
| 3272 Object* hash = this->hash(); |
| 3273 if (!hash->IsSmi() && flag == ALLOW_CREATION) { |
| 3274 hash = GenerateIdentityHash(); |
| 3275 set_hash(hash); |
| 3276 } |
| 3277 return hash; |
| 3278 } |
| 3279 |
| 3280 |
| 3253 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, | 3281 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, |
| 3254 DeleteMode mode) { | 3282 DeleteMode mode) { |
| 3255 // Check local property, ignore interceptor. | 3283 // Check local property, ignore interceptor. |
| 3256 LookupResult result; | 3284 LookupResult result; |
| 3257 LocalLookupRealNamedProperty(name, &result); | 3285 LocalLookupRealNamedProperty(name, &result); |
| 3258 if (!result.IsProperty()) return GetHeap()->true_value(); | 3286 if (!result.IsProperty()) return GetHeap()->true_value(); |
| 3259 | 3287 |
| 3260 // Normalize object if needed. | 3288 // Normalize object if needed. |
| 3261 Object* obj; | 3289 Object* obj; |
| 3262 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 3290 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| (...skipping 8192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11455 ASSERT(obj->IsJSObject()); | 11483 ASSERT(obj->IsJSObject()); |
| 11456 | 11484 |
| 11457 descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); | 11485 descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); |
| 11458 // Check that it really works. | 11486 // Check that it really works. |
| 11459 ASSERT(obj->HasFastProperties()); | 11487 ASSERT(obj->HasFastProperties()); |
| 11460 | 11488 |
| 11461 return obj; | 11489 return obj; |
| 11462 } | 11490 } |
| 11463 | 11491 |
| 11464 | 11492 |
| 11465 Object* ObjectHashTable::Lookup(JSObject* key) { | 11493 Object* ObjectHashTable::Lookup(JSReceiver* key) { |
| 11466 // If the object does not have an identity hash, it was never used as a key. | 11494 // If the object does not have an identity hash, it was never used as a key. |
| 11467 MaybeObject* maybe_hash = key->GetIdentityHash(JSObject::OMIT_CREATION); | 11495 MaybeObject* maybe_hash = key->GetIdentityHash(OMIT_CREATION); |
| 11468 if (maybe_hash->IsFailure()) return GetHeap()->undefined_value(); | 11496 if (maybe_hash->IsFailure()) return GetHeap()->undefined_value(); |
| 11469 int entry = FindEntry(key); | 11497 int entry = FindEntry(key); |
| 11470 if (entry == kNotFound) return GetHeap()->undefined_value(); | 11498 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 11471 return get(EntryToIndex(entry) + 1); | 11499 return get(EntryToIndex(entry) + 1); |
| 11472 } | 11500 } |
| 11473 | 11501 |
| 11474 | 11502 |
| 11475 MaybeObject* ObjectHashTable::Put(JSObject* key, Object* value) { | 11503 MaybeObject* ObjectHashTable::Put(JSReceiver* key, Object* value) { |
| 11476 // Make sure the key object has an identity hash code. | 11504 // Make sure the key object has an identity hash code. |
| 11477 int hash; | 11505 int hash; |
| 11478 { MaybeObject* maybe_hash = key->GetIdentityHash(JSObject::ALLOW_CREATION); | 11506 { MaybeObject* maybe_hash = key->GetIdentityHash(ALLOW_CREATION); |
| 11479 if (maybe_hash->IsFailure()) return maybe_hash; | 11507 if (maybe_hash->IsFailure()) return maybe_hash; |
| 11480 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); | 11508 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); |
| 11481 } | 11509 } |
| 11482 int entry = FindEntry(key); | 11510 int entry = FindEntry(key); |
| 11483 | 11511 |
| 11484 // Check whether to perform removal operation. | 11512 // Check whether to perform removal operation. |
| 11485 if (value->IsUndefined()) { | 11513 if (value->IsUndefined()) { |
| 11486 if (entry == kNotFound) return this; | 11514 if (entry == kNotFound) return this; |
| 11487 RemoveEntry(entry); | 11515 RemoveEntry(entry); |
| 11488 return Shrink(key); | 11516 return Shrink(key); |
| 11489 } | 11517 } |
| 11490 | 11518 |
| 11491 // Key is already in table, just overwrite value. | 11519 // Key is already in table, just overwrite value. |
| 11492 if (entry != kNotFound) { | 11520 if (entry != kNotFound) { |
| 11493 set(EntryToIndex(entry) + 1, value); | 11521 set(EntryToIndex(entry) + 1, value); |
| 11494 return this; | 11522 return this; |
| 11495 } | 11523 } |
| 11496 | 11524 |
| 11497 // Check whether the hash table should be extended. | 11525 // Check whether the hash table should be extended. |
| 11498 Object* obj; | 11526 Object* obj; |
| 11499 { MaybeObject* maybe_obj = EnsureCapacity(1, key); | 11527 { MaybeObject* maybe_obj = EnsureCapacity(1, key); |
| 11500 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11528 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 11501 } | 11529 } |
| 11502 ObjectHashTable* table = ObjectHashTable::cast(obj); | 11530 ObjectHashTable* table = ObjectHashTable::cast(obj); |
| 11503 table->AddEntry(table->FindInsertionEntry(hash), key, value); | 11531 table->AddEntry(table->FindInsertionEntry(hash), key, value); |
| 11504 return table; | 11532 return table; |
| 11505 } | 11533 } |
| 11506 | 11534 |
| 11507 | 11535 |
| 11508 void ObjectHashTable::AddEntry(int entry, JSObject* key, Object* value) { | 11536 void ObjectHashTable::AddEntry(int entry, JSReceiver* key, Object* value) { |
| 11509 set(EntryToIndex(entry), key); | 11537 set(EntryToIndex(entry), key); |
| 11510 set(EntryToIndex(entry) + 1, value); | 11538 set(EntryToIndex(entry) + 1, value); |
| 11511 ElementAdded(); | 11539 ElementAdded(); |
| 11512 } | 11540 } |
| 11513 | 11541 |
| 11514 | 11542 |
| 11515 void ObjectHashTable::RemoveEntry(int entry, Heap* heap) { | 11543 void ObjectHashTable::RemoveEntry(int entry, Heap* heap) { |
| 11516 set_null(heap, EntryToIndex(entry)); | 11544 set_null(heap, EntryToIndex(entry)); |
| 11517 set_null(heap, EntryToIndex(entry) + 1); | 11545 set_null(heap, EntryToIndex(entry) + 1); |
| 11518 ElementRemoved(); | 11546 ElementRemoved(); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11766 if (break_point_objects()->IsUndefined()) return 0; | 11794 if (break_point_objects()->IsUndefined()) return 0; |
| 11767 // Single break point. | 11795 // Single break point. |
| 11768 if (!break_point_objects()->IsFixedArray()) return 1; | 11796 if (!break_point_objects()->IsFixedArray()) return 1; |
| 11769 // Multiple break points. | 11797 // Multiple break points. |
| 11770 return FixedArray::cast(break_point_objects())->length(); | 11798 return FixedArray::cast(break_point_objects())->length(); |
| 11771 } | 11799 } |
| 11772 #endif | 11800 #endif |
| 11773 | 11801 |
| 11774 | 11802 |
| 11775 } } // namespace v8::internal | 11803 } } // namespace v8::internal |
| OLD | NEW |