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 |