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

Side by Side Diff: src/objects.cc

Issue 10827040: Limit initial size of hidden properties and store identity hashes inline. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: addressed comments Created 8 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | test/cctest/test-dictionary.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | test/cctest/test-dictionary.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698