| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2754 // Code will be set on the JavaScript side. | 2754 // Code will be set on the JavaScript side. |
| 2755 } else { | 2755 } else { |
| 2756 isolate->factory()->BecomeJSObject(self); | 2756 isolate->factory()->BecomeJSObject(self); |
| 2757 } | 2757 } |
| 2758 ASSERT(self->IsJSObject()); | 2758 ASSERT(self->IsJSObject()); |
| 2759 | 2759 |
| 2760 // Inherit identity, if it was present. | 2760 // Inherit identity, if it was present. |
| 2761 Object* hash; | 2761 Object* hash; |
| 2762 if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) { | 2762 if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) { |
| 2763 Handle<JSObject> new_self(JSObject::cast(*self)); | 2763 Handle<JSObject> new_self(JSObject::cast(*self)); |
| 2764 isolate->factory()->SetIdentityHash(new_self, hash); | 2764 isolate->factory()->SetIdentityHash(new_self, Smi::cast(hash)); |
| 2765 } | 2765 } |
| 2766 } | 2766 } |
| 2767 | 2767 |
| 2768 | 2768 |
| 2769 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name, | 2769 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name, |
| 2770 Handle<Object> derived, | 2770 Handle<Object> derived, |
| 2771 int argc, | 2771 int argc, |
| 2772 Handle<Object> argv[]) { | 2772 Handle<Object> argv[]) { |
| 2773 Isolate* isolate = GetIsolate(); | 2773 Isolate* isolate = GetIsolate(); |
| 2774 Handle<Object> handler(this->handler()); | 2774 Handle<Object> handler(this->handler()); |
| (...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3498 // within a smi. | 3498 // within a smi. |
| 3499 hash_value = V8::RandomPrivate(isolate) & Smi::kMaxValue; | 3499 hash_value = V8::RandomPrivate(isolate) & Smi::kMaxValue; |
| 3500 attempts++; | 3500 attempts++; |
| 3501 } while (hash_value == 0 && attempts < 30); | 3501 } while (hash_value == 0 && attempts < 30); |
| 3502 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 | 3502 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 |
| 3503 | 3503 |
| 3504 return Smi::FromInt(hash_value); | 3504 return Smi::FromInt(hash_value); |
| 3505 } | 3505 } |
| 3506 | 3506 |
| 3507 | 3507 |
| 3508 MaybeObject* JSObject::SetIdentityHash(Object* hash, CreationFlag flag) { | 3508 MaybeObject* JSObject::SetIdentityHash(Smi* hash, CreationFlag flag) { |
| 3509 MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(), | 3509 MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(), |
| 3510 hash); | 3510 hash); |
| 3511 if (maybe->IsFailure()) return maybe; | 3511 if (maybe->IsFailure()) return maybe; |
| 3512 return this; | 3512 return this; |
| 3513 } | 3513 } |
| 3514 | 3514 |
| 3515 | 3515 |
| 3516 int JSObject::GetIdentityHash(Handle<JSObject> obj) { | 3516 int JSObject::GetIdentityHash(Handle<JSObject> obj) { |
| 3517 CALL_AND_RETRY(obj->GetIsolate(), | 3517 CALL_AND_RETRY(obj->GetIsolate(), |
| 3518 obj->GetIdentityHash(ALLOW_CREATION), | 3518 obj->GetIdentityHash(ALLOW_CREATION), |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3544 Object* hash = this->hash(); | 3544 Object* hash = this->hash(); |
| 3545 if (!hash->IsSmi() && flag == ALLOW_CREATION) { | 3545 if (!hash->IsSmi() && flag == ALLOW_CREATION) { |
| 3546 hash = GenerateIdentityHash(); | 3546 hash = GenerateIdentityHash(); |
| 3547 set_hash(hash); | 3547 set_hash(hash); |
| 3548 } | 3548 } |
| 3549 return hash; | 3549 return hash; |
| 3550 } | 3550 } |
| 3551 | 3551 |
| 3552 | 3552 |
| 3553 Object* JSObject::GetHiddenProperty(String* key) { | 3553 Object* JSObject::GetHiddenProperty(String* key) { |
| 3554 ASSERT(key->IsSymbol()); |
| 3554 if (IsJSGlobalProxy()) { | 3555 if (IsJSGlobalProxy()) { |
| 3555 // For a proxy, use the prototype as target object. | 3556 // For a proxy, use the prototype as target object. |
| 3556 Object* proxy_parent = GetPrototype(); | 3557 Object* proxy_parent = GetPrototype(); |
| 3557 // If the proxy is detached, return undefined. | 3558 // If the proxy is detached, return undefined. |
| 3558 if (proxy_parent->IsNull()) return GetHeap()->undefined_value(); | 3559 if (proxy_parent->IsNull()) return GetHeap()->undefined_value(); |
| 3559 ASSERT(proxy_parent->IsJSGlobalObject()); | 3560 ASSERT(proxy_parent->IsJSGlobalObject()); |
| 3560 return JSObject::cast(proxy_parent)->GetHiddenProperty(key); | 3561 return JSObject::cast(proxy_parent)->GetHiddenProperty(key); |
| 3561 } | 3562 } |
| 3562 ASSERT(!IsJSGlobalProxy()); | 3563 ASSERT(!IsJSGlobalProxy()); |
| 3563 MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false); | 3564 MaybeObject* hidden_lookup = |
| 3565 GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE); |
| 3564 ASSERT(!hidden_lookup->IsFailure()); // No failure when passing false as arg. | 3566 ASSERT(!hidden_lookup->IsFailure()); // No failure when passing false as arg. |
| 3565 if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) { | 3567 Object* inline_value = hidden_lookup->ToObjectUnchecked(); |
| 3566 return GetHeap()->undefined_value(); | 3568 |
| 3569 if (inline_value->IsSmi()) { |
| 3570 // Handle inline-stored identity hash. |
| 3571 if (key == GetHeap()->identity_hash_symbol()) { |
| 3572 return inline_value; |
| 3573 } else { |
| 3574 return GetHeap()->undefined_value(); |
| 3575 } |
| 3567 } | 3576 } |
| 3568 StringDictionary* dictionary = | 3577 |
| 3569 StringDictionary::cast(hidden_lookup->ToObjectUnchecked()); | 3578 if (inline_value->IsUndefined()) return GetHeap()->undefined_value(); |
| 3570 int entry = dictionary->FindEntry(key); | 3579 |
| 3571 if (entry == StringDictionary::kNotFound) return GetHeap()->undefined_value(); | 3580 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); |
| 3572 return dictionary->ValueAt(entry); | 3581 Object* entry = hashtable->Lookup(key); |
| 3582 if (entry->IsTheHole()) return GetHeap()->undefined_value(); |
| 3583 return entry; |
| 3573 } | 3584 } |
| 3574 | 3585 |
| 3575 | 3586 |
| 3576 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj, | 3587 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj, |
| 3577 Handle<String> key, | 3588 Handle<String> key, |
| 3578 Handle<Object> value) { | 3589 Handle<Object> value) { |
| 3579 CALL_HEAP_FUNCTION(obj->GetIsolate(), | 3590 CALL_HEAP_FUNCTION(obj->GetIsolate(), |
| 3580 obj->SetHiddenProperty(*key, *value), | 3591 obj->SetHiddenProperty(*key, *value), |
| 3581 Object); | 3592 Object); |
| 3582 } | 3593 } |
| 3583 | 3594 |
| 3584 | 3595 |
| 3585 MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) { | 3596 MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) { |
| 3597 ASSERT(key->IsSymbol()); |
| 3586 if (IsJSGlobalProxy()) { | 3598 if (IsJSGlobalProxy()) { |
| 3587 // For a proxy, use the prototype as target object. | 3599 // For a proxy, use the prototype as target object. |
| 3588 Object* proxy_parent = GetPrototype(); | 3600 Object* proxy_parent = GetPrototype(); |
| 3589 // If the proxy is detached, return undefined. | 3601 // If the proxy is detached, return undefined. |
| 3590 if (proxy_parent->IsNull()) return GetHeap()->undefined_value(); | 3602 if (proxy_parent->IsNull()) return GetHeap()->undefined_value(); |
| 3591 ASSERT(proxy_parent->IsJSGlobalObject()); | 3603 ASSERT(proxy_parent->IsJSGlobalObject()); |
| 3592 return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value); | 3604 return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value); |
| 3593 } | 3605 } |
| 3594 ASSERT(!IsJSGlobalProxy()); | 3606 ASSERT(!IsJSGlobalProxy()); |
| 3595 MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(true); | 3607 |
| 3596 StringDictionary* dictionary; | 3608 // If there is no backing store yet, store the identity hash inline. |
| 3597 if (!hidden_lookup->To<StringDictionary>(&dictionary)) return hidden_lookup; | 3609 MaybeObject* hidden_lookup = |
| 3610 GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE); |
| 3611 ASSERT(!hidden_lookup->IsFailure()); |
| 3612 Object* inline_value = hidden_lookup->ToObjectUnchecked(); |
| 3613 |
| 3614 if (value->IsSmi() && |
| 3615 key == GetHeap()->identity_hash_symbol() && |
| 3616 (inline_value->IsUndefined() || inline_value->IsSmi())) { |
| 3617 return SetHiddenPropertiesHashTable(value); |
| 3618 } |
| 3619 |
| 3620 hidden_lookup = GetHiddenPropertiesHashTable(CREATE_NEW_IF_ABSENT); |
| 3621 ObjectHashTable* hashtable; |
| 3622 if (!hidden_lookup->To(&hashtable)) return hidden_lookup; |
| 3598 | 3623 |
| 3599 // If it was found, check if the key is already in the dictionary. | 3624 // If it was found, check if the key is already in the dictionary. |
| 3600 int entry = dictionary->FindEntry(key); | 3625 MaybeObject* insert_result = hashtable->Put(key, value); |
| 3601 if (entry != StringDictionary::kNotFound) { | 3626 ObjectHashTable* new_table; |
| 3602 // If key was found, just update the value. | 3627 if (!insert_result->To(&new_table)) return insert_result; |
| 3603 dictionary->ValueAtPut(entry, value); | 3628 if (new_table != hashtable) { |
| 3604 return this; | |
| 3605 } | |
| 3606 // Key was not already in the dictionary, so add the entry. | |
| 3607 MaybeObject* insert_result = dictionary->Add(key, | |
| 3608 value, | |
| 3609 PropertyDetails(NONE, NORMAL)); | |
| 3610 StringDictionary* new_dict; | |
| 3611 if (!insert_result->To<StringDictionary>(&new_dict)) return insert_result; | |
| 3612 if (new_dict != dictionary) { | |
| 3613 // If adding the key expanded the dictionary (i.e., Add returned a new | 3629 // If adding the key expanded the dictionary (i.e., Add returned a new |
| 3614 // dictionary), store it back to the object. | 3630 // dictionary), store it back to the object. |
| 3615 MaybeObject* store_result = SetHiddenPropertiesDictionary(new_dict); | 3631 MaybeObject* store_result = SetHiddenPropertiesHashTable(new_table); |
| 3616 if (store_result->IsFailure()) return store_result; | 3632 if (store_result->IsFailure()) return store_result; |
| 3617 } | 3633 } |
| 3618 // Return this to mark success. | 3634 // Return this to mark success. |
| 3619 return this; | 3635 return this; |
| 3620 } | 3636 } |
| 3621 | 3637 |
| 3622 | 3638 |
| 3623 void JSObject::DeleteHiddenProperty(String* key) { | 3639 void JSObject::DeleteHiddenProperty(String* key) { |
| 3640 ASSERT(key->IsSymbol()); |
| 3624 if (IsJSGlobalProxy()) { | 3641 if (IsJSGlobalProxy()) { |
| 3625 // For a proxy, use the prototype as target object. | 3642 // For a proxy, use the prototype as target object. |
| 3626 Object* proxy_parent = GetPrototype(); | 3643 Object* proxy_parent = GetPrototype(); |
| 3627 // If the proxy is detached, return immediately. | 3644 // If the proxy is detached, return immediately. |
| 3628 if (proxy_parent->IsNull()) return; | 3645 if (proxy_parent->IsNull()) return; |
| 3629 ASSERT(proxy_parent->IsJSGlobalObject()); | 3646 ASSERT(proxy_parent->IsJSGlobalObject()); |
| 3630 JSObject::cast(proxy_parent)->DeleteHiddenProperty(key); | 3647 JSObject::cast(proxy_parent)->DeleteHiddenProperty(key); |
| 3631 return; | 3648 return; |
| 3632 } | 3649 } |
| 3633 MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false); | 3650 MaybeObject* hidden_lookup = |
| 3651 GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE); |
| 3634 ASSERT(!hidden_lookup->IsFailure()); // No failure when passing false as arg. | 3652 ASSERT(!hidden_lookup->IsFailure()); // No failure when passing false as arg. |
| 3635 if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) return; | 3653 if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) return; |
| 3636 StringDictionary* dictionary = | 3654 // We never delete (inline-stored) identity hashes. |
| 3637 StringDictionary::cast(hidden_lookup->ToObjectUnchecked()); | 3655 ASSERT(!hidden_lookup->ToObjectUnchecked()->IsSmi()); |
| 3638 int entry = dictionary->FindEntry(key); | 3656 |
| 3639 if (entry == StringDictionary::kNotFound) { | 3657 ObjectHashTable* hashtable = |
| 3640 // Key wasn't in dictionary. Deletion is a success. | 3658 ObjectHashTable::cast(hidden_lookup->ToObjectUnchecked()); |
| 3641 return; | 3659 MaybeObject* delete_result = hashtable->Put(key, GetHeap()->the_hole_value()); |
| 3642 } | 3660 USE(delete_result); |
| 3643 // Key was in the dictionary. Remove it. | 3661 ASSERT(!delete_result->IsFailure()); // Delete does not cause GC. |
| 3644 dictionary->DeleteProperty(entry, JSReceiver::FORCE_DELETION); | |
| 3645 } | 3662 } |
| 3646 | 3663 |
| 3647 | 3664 |
| 3648 bool JSObject::HasHiddenProperties() { | 3665 bool JSObject::HasHiddenProperties() { |
| 3649 return GetPropertyAttributePostInterceptor(this, | 3666 return GetPropertyAttributePostInterceptor(this, |
| 3650 GetHeap()->hidden_symbol(), | 3667 GetHeap()->hidden_symbol(), |
| 3651 false) != ABSENT; | 3668 false) != ABSENT; |
| 3652 } | 3669 } |
| 3653 | 3670 |
| 3654 | 3671 |
| 3655 MaybeObject* JSObject::GetHiddenPropertiesDictionary(bool create_if_absent) { | 3672 MaybeObject* JSObject::GetHiddenPropertiesHashTable( |
| 3673 InitializeHiddenProperties init_option) { |
| 3656 ASSERT(!IsJSGlobalProxy()); | 3674 ASSERT(!IsJSGlobalProxy()); |
| 3675 Object* inline_value; |
| 3657 if (HasFastProperties()) { | 3676 if (HasFastProperties()) { |
| 3658 // If the object has fast properties, check whether the first slot | 3677 // If the object has fast properties, check whether the first slot |
| 3659 // in the descriptor array matches the hidden symbol. Since the | 3678 // in the descriptor array matches the hidden symbol. Since the |
| 3660 // hidden symbols hash code is zero (and no other string has hash | 3679 // hidden symbols hash code is zero (and no other string has hash |
| 3661 // code zero) it will always occupy the first entry if present. | 3680 // code zero) it will always occupy the first entry if present. |
| 3662 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 3681 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
| 3663 if ((descriptors->number_of_descriptors() > 0) && | 3682 if ((descriptors->number_of_descriptors() > 0) && |
| 3664 (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) { | 3683 (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) { |
| 3665 ASSERT(descriptors->GetType(0) == FIELD); | 3684 ASSERT(descriptors->GetType(0) == FIELD); |
| 3666 Object* hidden_store = | 3685 inline_value = this->FastPropertyAt(descriptors->GetFieldIndex(0)); |
| 3667 this->FastPropertyAt(descriptors->GetFieldIndex(0)); | 3686 } else { |
| 3668 return StringDictionary::cast(hidden_store); | 3687 inline_value = GetHeap()->undefined_value(); |
| 3669 } | 3688 } |
| 3670 } else { | 3689 } else { |
| 3671 PropertyAttributes attributes; | 3690 PropertyAttributes attributes; |
| 3672 // You can't install a getter on a property indexed by the hidden symbol, | 3691 // You can't install a getter on a property indexed by the hidden symbol, |
| 3673 // so we can be sure that GetLocalPropertyPostInterceptor returns a real | 3692 // so we can be sure that GetLocalPropertyPostInterceptor returns a real |
| 3674 // object. | 3693 // object. |
| 3675 Object* lookup = | 3694 inline_value = |
| 3676 GetLocalPropertyPostInterceptor(this, | 3695 GetLocalPropertyPostInterceptor(this, |
| 3677 GetHeap()->hidden_symbol(), | 3696 GetHeap()->hidden_symbol(), |
| 3678 &attributes)->ToObjectUnchecked(); | 3697 &attributes)->ToObjectUnchecked(); |
| 3679 if (!lookup->IsUndefined()) { | |
| 3680 return StringDictionary::cast(lookup); | |
| 3681 } | |
| 3682 } | 3698 } |
| 3683 if (!create_if_absent) return GetHeap()->undefined_value(); | 3699 |
| 3684 const int kInitialSize = 5; | 3700 if (init_option == ONLY_RETURN_INLINE_VALUE || |
| 3685 MaybeObject* dict_alloc = StringDictionary::Allocate(kInitialSize); | 3701 inline_value->IsHashTable()) { |
| 3686 StringDictionary* dictionary; | 3702 return inline_value; |
| 3687 if (!dict_alloc->To<StringDictionary>(&dictionary)) return dict_alloc; | 3703 } |
| 3704 |
| 3705 ObjectHashTable* hashtable; |
| 3706 static const int kInitialCapacity = 4; |
| 3707 MaybeObject* maybe_obj = |
| 3708 ObjectHashTable::Allocate(kInitialCapacity, |
| 3709 ObjectHashTable::USE_CUSTOM_MINIMUM_CAPACITY); |
| 3710 if (!maybe_obj->To<ObjectHashTable>(&hashtable)) return maybe_obj; |
| 3711 |
| 3712 if (inline_value->IsSmi()) { |
| 3713 // We were storing the identity hash inline and now allocated an actual |
| 3714 // dictionary. Put the identity hash into the new dictionary. |
| 3715 MaybeObject* insert_result = |
| 3716 hashtable->Put(GetHeap()->identity_hash_symbol(), inline_value); |
| 3717 ObjectHashTable* new_table; |
| 3718 if (!insert_result->To(&new_table)) return insert_result; |
| 3719 // We expect no resizing for the first insert. |
| 3720 ASSERT_EQ(hashtable, new_table); |
| 3721 } |
| 3722 |
| 3688 MaybeObject* store_result = | 3723 MaybeObject* store_result = |
| 3689 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), | 3724 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), |
| 3690 dictionary, | 3725 hashtable, |
| 3691 DONT_ENUM, | 3726 DONT_ENUM, |
| 3692 kNonStrictMode, | 3727 kNonStrictMode, |
| 3693 OMIT_EXTENSIBILITY_CHECK); | 3728 OMIT_EXTENSIBILITY_CHECK); |
| 3694 if (store_result->IsFailure()) return store_result; | 3729 if (store_result->IsFailure()) return store_result; |
| 3695 return dictionary; | 3730 return hashtable; |
| 3696 } | 3731 } |
| 3697 | 3732 |
| 3698 | 3733 |
| 3699 MaybeObject* JSObject::SetHiddenPropertiesDictionary( | 3734 MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) { |
| 3700 StringDictionary* dictionary) { | |
| 3701 ASSERT(!IsJSGlobalProxy()); | 3735 ASSERT(!IsJSGlobalProxy()); |
| 3702 ASSERT(HasHiddenProperties()); | 3736 // We can store the identity hash inline iff there is no backing store |
| 3737 // for hidden properties yet. |
| 3738 ASSERT(HasHiddenProperties() != value->IsSmi()); |
| 3703 if (HasFastProperties()) { | 3739 if (HasFastProperties()) { |
| 3704 // If the object has fast properties, check whether the first slot | 3740 // If the object has fast properties, check whether the first slot |
| 3705 // in the descriptor array matches the hidden symbol. Since the | 3741 // in the descriptor array matches the hidden symbol. Since the |
| 3706 // hidden symbols hash code is zero (and no other string has hash | 3742 // hidden symbols hash code is zero (and no other string has hash |
| 3707 // code zero) it will always occupy the first entry if present. | 3743 // code zero) it will always occupy the first entry if present. |
| 3708 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 3744 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
| 3709 if ((descriptors->number_of_descriptors() > 0) && | 3745 if ((descriptors->number_of_descriptors() > 0) && |
| 3710 (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) { | 3746 (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) { |
| 3711 ASSERT(descriptors->GetType(0) == FIELD); | 3747 ASSERT(descriptors->GetType(0) == FIELD); |
| 3712 this->FastPropertyAtPut(descriptors->GetFieldIndex(0), dictionary); | 3748 this->FastPropertyAtPut(descriptors->GetFieldIndex(0), value); |
| 3713 return this; | 3749 return this; |
| 3714 } | 3750 } |
| 3715 } | 3751 } |
| 3716 MaybeObject* store_result = | 3752 MaybeObject* store_result = |
| 3717 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), | 3753 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), |
| 3718 dictionary, | 3754 value, |
| 3719 DONT_ENUM, | 3755 DONT_ENUM, |
| 3720 kNonStrictMode, | 3756 kNonStrictMode, |
| 3721 OMIT_EXTENSIBILITY_CHECK); | 3757 OMIT_EXTENSIBILITY_CHECK); |
| 3722 if (store_result->IsFailure()) return store_result; | 3758 if (store_result->IsFailure()) return store_result; |
| 3723 return this; | 3759 return this; |
| 3724 } | 3760 } |
| 3725 | 3761 |
| 3726 | 3762 |
| 3727 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, | 3763 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, |
| 3728 DeleteMode mode) { | 3764 DeleteMode mode) { |
| (...skipping 7310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11039 template<typename Shape, typename Key> | 11075 template<typename Shape, typename Key> |
| 11040 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) { | 11076 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) { |
| 11041 IteratePointers(v, | 11077 IteratePointers(v, |
| 11042 kElementsStartOffset, | 11078 kElementsStartOffset, |
| 11043 kHeaderSize + length() * kPointerSize); | 11079 kHeaderSize + length() * kPointerSize); |
| 11044 } | 11080 } |
| 11045 | 11081 |
| 11046 | 11082 |
| 11047 template<typename Shape, typename Key> | 11083 template<typename Shape, typename Key> |
| 11048 MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for, | 11084 MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for, |
| 11085 MinimumCapacity capacity_option, |
| 11049 PretenureFlag pretenure) { | 11086 PretenureFlag pretenure) { |
| 11050 int capacity = ComputeCapacity(at_least_space_for); | 11087 ASSERT(!capacity_option || IS_POWER_OF_TWO(at_least_space_for)); |
| 11088 int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY) |
| 11089 ? at_least_space_for |
| 11090 : ComputeCapacity(at_least_space_for); |
| 11051 if (capacity > HashTable::kMaxCapacity) { | 11091 if (capacity > HashTable::kMaxCapacity) { |
| 11052 return Failure::OutOfMemoryException(); | 11092 return Failure::OutOfMemoryException(); |
| 11053 } | 11093 } |
| 11054 | 11094 |
| 11055 Object* obj; | 11095 Object* obj; |
| 11056 { MaybeObject* maybe_obj = Isolate::Current()->heap()-> | 11096 { MaybeObject* maybe_obj = Isolate::Current()->heap()-> |
| 11057 AllocateHashTable(EntryToIndex(capacity), pretenure); | 11097 AllocateHashTable(EntryToIndex(capacity), pretenure); |
| 11058 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11098 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 11059 } | 11099 } |
| 11060 HashTable::cast(obj)->SetNumberOfElements(0); | 11100 HashTable::cast(obj)->SetNumberOfElements(0); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11149 if (nod <= (capacity - nof) >> 1) { | 11189 if (nod <= (capacity - nof) >> 1) { |
| 11150 int needed_free = nof >> 1; | 11190 int needed_free = nof >> 1; |
| 11151 if (nof + needed_free <= capacity) return this; | 11191 if (nof + needed_free <= capacity) return this; |
| 11152 } | 11192 } |
| 11153 | 11193 |
| 11154 const int kMinCapacityForPretenure = 256; | 11194 const int kMinCapacityForPretenure = 256; |
| 11155 bool pretenure = | 11195 bool pretenure = |
| 11156 (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this); | 11196 (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this); |
| 11157 Object* obj; | 11197 Object* obj; |
| 11158 { MaybeObject* maybe_obj = | 11198 { MaybeObject* maybe_obj = |
| 11159 Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED); | 11199 Allocate(nof * 2, |
| 11200 USE_DEFAULT_MINIMUM_CAPACITY, |
| 11201 pretenure ? TENURED : NOT_TENURED); |
| 11160 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11202 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 11161 } | 11203 } |
| 11162 | 11204 |
| 11163 return Rehash(HashTable::cast(obj), key); | 11205 return Rehash(HashTable::cast(obj), key); |
| 11164 } | 11206 } |
| 11165 | 11207 |
| 11166 | 11208 |
| 11167 template<typename Shape, typename Key> | 11209 template<typename Shape, typename Key> |
| 11168 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) { | 11210 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) { |
| 11169 int capacity = Capacity(); | 11211 int capacity = Capacity(); |
| 11170 int nof = NumberOfElements(); | 11212 int nof = NumberOfElements(); |
| 11171 | 11213 |
| 11172 // Shrink to fit the number of elements if only a quarter of the | 11214 // Shrink to fit the number of elements if only a quarter of the |
| 11173 // capacity is filled with elements. | 11215 // capacity is filled with elements. |
| 11174 if (nof > (capacity >> 2)) return this; | 11216 if (nof > (capacity >> 2)) return this; |
| 11175 // Allocate a new dictionary with room for at least the current | 11217 // Allocate a new dictionary with room for at least the current |
| 11176 // number of elements. The allocation method will make sure that | 11218 // number of elements. The allocation method will make sure that |
| 11177 // there is extra room in the dictionary for additions. Don't go | 11219 // there is extra room in the dictionary for additions. Don't go |
| 11178 // lower than room for 16 elements. | 11220 // lower than room for 16 elements. |
| 11179 int at_least_room_for = nof; | 11221 int at_least_room_for = nof; |
| 11180 if (at_least_room_for < 16) return this; | 11222 if (at_least_room_for < 16) return this; |
| 11181 | 11223 |
| 11182 const int kMinCapacityForPretenure = 256; | 11224 const int kMinCapacityForPretenure = 256; |
| 11183 bool pretenure = | 11225 bool pretenure = |
| 11184 (at_least_room_for > kMinCapacityForPretenure) && | 11226 (at_least_room_for > kMinCapacityForPretenure) && |
| 11185 !GetHeap()->InNewSpace(this); | 11227 !GetHeap()->InNewSpace(this); |
| 11186 Object* obj; | 11228 Object* obj; |
| 11187 { MaybeObject* maybe_obj = | 11229 { MaybeObject* maybe_obj = |
| 11188 Allocate(at_least_room_for, pretenure ? TENURED : NOT_TENURED); | 11230 Allocate(at_least_room_for, |
| 11231 USE_DEFAULT_MINIMUM_CAPACITY, |
| 11232 pretenure ? TENURED : NOT_TENURED); |
| 11189 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11233 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 11190 } | 11234 } |
| 11191 | 11235 |
| 11192 return Rehash(HashTable::cast(obj), key); | 11236 return Rehash(HashTable::cast(obj), key); |
| 11193 } | 11237 } |
| 11194 | 11238 |
| 11195 | 11239 |
| 11196 template<typename Shape, typename Key> | 11240 template<typename Shape, typename Key> |
| 11197 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) { | 11241 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) { |
| 11198 uint32_t capacity = Capacity(); | 11242 uint32_t capacity = Capacity(); |
| (...skipping 1929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13128 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13172 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
| 13129 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13173 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
| 13130 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13174 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
| 13131 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13175 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
| 13132 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13176 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
| 13133 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13177 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
| 13134 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13178 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
| 13135 } | 13179 } |
| 13136 | 13180 |
| 13137 } } // namespace v8::internal | 13181 } } // namespace v8::internal |
| OLD | NEW |