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

Side by Side Diff: src/objects.cc

Issue 7190032: Shrink dictionaries on deletion if number of elements are less than a (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address comments. Created 9 years, 6 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') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); 486 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
487 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; 487 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
488 } 488 }
489 set_map(Map::cast(new_map)); 489 set_map(Map::cast(new_map));
490 } 490 }
491 JSGlobalPropertyCell* cell = 491 JSGlobalPropertyCell* cell =
492 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); 492 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
493 cell->set_value(cell->heap()->the_hole_value()); 493 cell->set_value(cell->heap()->the_hole_value());
494 dictionary->DetailsAtPut(entry, details.AsDeleted()); 494 dictionary->DetailsAtPut(entry, details.AsDeleted());
495 } else { 495 } else {
496 return dictionary->DeleteProperty(entry, mode); 496 Object* deleted = dictionary->DeleteProperty(entry, mode);
497 if (deleted == GetHeap()->true_value()) {
498 FixedArray* new_properties = NULL;
499 MaybeObject* maybe_properties = dictionary->Shrink(name);
500 if (!maybe_properties->To(&new_properties)) {
501 return maybe_properties;
502 }
503 set_properties(new_properties);
504 }
505 return deleted;
497 } 506 }
498 } 507 }
499 return GetHeap()->true_value(); 508 return GetHeap()->true_value();
500 } 509 }
501 510
502 511
503 bool JSObject::IsDirty() { 512 bool JSObject::IsDirty() {
504 Object* cons_obj = map()->constructor(); 513 Object* cons_obj = map()->constructor();
505 if (!cons_obj->IsJSFunction()) 514 if (!cons_obj->IsJSFunction())
506 return true; 515 return true;
(...skipping 2441 matching lines...) Expand 10 before | Expand all | Expand 10 after
2948 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 2957 static_cast<uint32_t>(FixedArray::cast(elements())->length());
2949 if (index < length) { 2958 if (index < length) {
2950 FixedArray::cast(elements())->set_the_hole(index); 2959 FixedArray::cast(elements())->set_the_hole(index);
2951 } 2960 }
2952 break; 2961 break;
2953 } 2962 }
2954 case DICTIONARY_ELEMENTS: { 2963 case DICTIONARY_ELEMENTS: {
2955 NumberDictionary* dictionary = element_dictionary(); 2964 NumberDictionary* dictionary = element_dictionary();
2956 int entry = dictionary->FindEntry(index); 2965 int entry = dictionary->FindEntry(index);
2957 if (entry != NumberDictionary::kNotFound) { 2966 if (entry != NumberDictionary::kNotFound) {
2958 return dictionary->DeleteProperty(entry, mode); 2967 Object* deleted = dictionary->DeleteProperty(entry, mode);
2968 if (deleted == GetHeap()->true_value()) {
2969 MaybeObject* maybe_elements = dictionary->Shrink(index);
2970 FixedArray* new_elements = NULL;
2971 if (!maybe_elements->To(&new_elements)) {
2972 return maybe_elements;
2973 }
2974 set_elements(new_elements);
2975 }
2976 return deleted;
2959 } 2977 }
2960 break; 2978 break;
2961 } 2979 }
2962 default: 2980 default:
2963 UNREACHABLE(); 2981 UNREACHABLE();
2964 break; 2982 break;
2965 } 2983 }
2966 return GetHeap()->true_value(); 2984 return GetHeap()->true_value();
2967 } 2985 }
2968 2986
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3028 Isolate* isolate = GetIsolate(); 3046 Isolate* isolate = GetIsolate();
3029 Heap* heap = isolate->heap(); 3047 Heap* heap = isolate->heap();
3030 FixedArray* backing_store = FixedArray::cast(elements()); 3048 FixedArray* backing_store = FixedArray::cast(elements());
3031 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { 3049 if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
3032 backing_store = FixedArray::cast(backing_store->get(1)); 3050 backing_store = FixedArray::cast(backing_store->get(1));
3033 } 3051 }
3034 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); 3052 NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
3035 int entry = dictionary->FindEntry(index); 3053 int entry = dictionary->FindEntry(index);
3036 if (entry != NumberDictionary::kNotFound) { 3054 if (entry != NumberDictionary::kNotFound) {
3037 Object* result = dictionary->DeleteProperty(entry, mode); 3055 Object* result = dictionary->DeleteProperty(entry, mode);
3056 if (result == heap->true_value()) {
3057 MaybeObject* maybe_elements = dictionary->Shrink(index);
3058 FixedArray* new_elements = NULL;
3059 if (!maybe_elements->To(&new_elements)) {
3060 return maybe_elements;
3061 }
3062 set_elements(new_elements);
3063 }
3038 if (mode == STRICT_DELETION && result == heap->false_value()) { 3064 if (mode == STRICT_DELETION && result == heap->false_value()) {
3039 // In strict mode, attempting to delete a non-configurable property 3065 // In strict mode, attempting to delete a non-configurable property
3040 // throws an exception. 3066 // throws an exception.
3041 HandleScope scope(isolate); 3067 HandleScope scope(isolate);
3042 Handle<Object> name = isolate->factory()->NewNumberFromUint(index); 3068 Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
3043 Handle<Object> args[2] = { name, Handle<Object>(this) }; 3069 Handle<Object> args[2] = { name, Handle<Object>(this) };
3044 Handle<Object> error = 3070 Handle<Object> error =
3045 isolate->factory()->NewTypeError("strict_delete_property", 3071 isolate->factory()->NewTypeError("strict_delete_property",
3046 HandleVector(args, 2)); 3072 HandleVector(args, 2));
3047 return isolate->Throw(*error); 3073 return isolate->Throw(*error);
(...skipping 5175 matching lines...) Expand 10 before | Expand all | Expand 10 after
8223 if (check_prototype && 8249 if (check_prototype &&
8224 (index >= length || backing_store->get(index)->IsTheHole())) { 8250 (index >= length || backing_store->get(index)->IsTheHole())) {
8225 bool found; 8251 bool found;
8226 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 8252 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
8227 value, 8253 value,
8228 &found, 8254 &found,
8229 strict_mode); 8255 strict_mode);
8230 if (found) return result; 8256 if (found) return result;
8231 } 8257 }
8232 8258
8233 // Check whether there is extra space in fixed array.. 8259 // Check whether there is extra space in fixed array.
8234 if (index < length) { 8260 if (index < length) {
8235 backing_store->set(index, value); 8261 backing_store->set(index, value);
8236 if (IsJSArray()) { 8262 if (IsJSArray()) {
8237 // Update the length of the array if needed. 8263 // Update the length of the array if needed.
8238 uint32_t array_length = 0; 8264 uint32_t array_length = 0;
8239 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 8265 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
8240 if (index >= array_length) { 8266 if (index >= array_length) {
8241 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); 8267 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
8242 } 8268 }
8243 } 8269 }
(...skipping 1703 matching lines...) Expand 10 before | Expand all | Expand 10 after
9947 return entry; 9973 return entry;
9948 } 9974 }
9949 ASSERT(element->IsNull() || !String::cast(element)->Equals(key)); 9975 ASSERT(element->IsNull() || !String::cast(element)->Equals(key));
9950 entry = NextProbe(entry, count++, capacity); 9976 entry = NextProbe(entry, count++, capacity);
9951 } 9977 }
9952 return kNotFound; 9978 return kNotFound;
9953 } 9979 }
9954 9980
9955 9981
9956 template<typename Shape, typename Key> 9982 template<typename Shape, typename Key>
9983 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) {
9984 ASSERT(NumberOfElements() < new_table->Capacity());
9985
9986 AssertNoAllocation no_gc;
9987 WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
9988
9989 // Copy prefix to new array.
9990 for (int i = kPrefixStartIndex;
9991 i < kPrefixStartIndex + Shape::kPrefixSize;
9992 i++) {
9993 new_table->set(i, get(i), mode);
9994 }
9995
9996 // Rehash the elements.
9997 int capacity = Capacity();
9998 for (int i = 0; i < capacity; i++) {
9999 uint32_t from_index = EntryToIndex(i);
10000 Object* k = get(from_index);
10001 if (IsKey(k)) {
10002 uint32_t hash = Shape::HashForObject(key, k);
10003 uint32_t insertion_index =
10004 EntryToIndex(new_table->FindInsertionEntry(hash));
10005 for (int j = 0; j < Shape::kEntrySize; j++) {
10006 new_table->set(insertion_index + j, get(from_index + j), mode);
10007 }
10008 }
10009 }
10010 new_table->SetNumberOfElements(NumberOfElements());
10011 new_table->SetNumberOfDeletedElements(0);
10012 return new_table;
10013 }
10014
10015
10016 template<typename Shape, typename Key>
9957 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { 10017 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
9958 int capacity = Capacity(); 10018 int capacity = Capacity();
9959 int nof = NumberOfElements() + n; 10019 int nof = NumberOfElements() + n;
9960 int nod = NumberOfDeletedElements(); 10020 int nod = NumberOfDeletedElements();
9961 // Return if: 10021 // Return if:
9962 // 50% is still free after adding n elements and 10022 // 50% is still free after adding n elements and
9963 // at most 50% of the free elements are deleted elements. 10023 // at most 50% of the free elements are deleted elements.
9964 if (nod <= (capacity - nof) >> 1) { 10024 if (nod <= (capacity - nof) >> 1) {
9965 int needed_free = nof >> 1; 10025 int needed_free = nof >> 1;
9966 if (nof + needed_free <= capacity) return this; 10026 if (nof + needed_free <= capacity) return this;
9967 } 10027 }
9968 10028
9969 const int kMinCapacityForPretenure = 256; 10029 const int kMinCapacityForPretenure = 256;
9970 bool pretenure = 10030 bool pretenure =
9971 (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this); 10031 (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this);
9972 Object* obj; 10032 Object* obj;
9973 { MaybeObject* maybe_obj = 10033 { MaybeObject* maybe_obj =
9974 Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED); 10034 Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED);
9975 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 10035 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9976 } 10036 }
9977 10037
9978 AssertNoAllocation no_gc; 10038 return Rehash(HashTable::cast(obj), key);
9979 HashTable* table = HashTable::cast(obj);
9980 WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc);
9981
9982 // Copy prefix to new array.
9983 for (int i = kPrefixStartIndex;
9984 i < kPrefixStartIndex + Shape::kPrefixSize;
9985 i++) {
9986 table->set(i, get(i), mode);
9987 }
9988 // Rehash the elements.
9989 for (int i = 0; i < capacity; i++) {
9990 uint32_t from_index = EntryToIndex(i);
9991 Object* k = get(from_index);
9992 if (IsKey(k)) {
9993 uint32_t hash = Shape::HashForObject(key, k);
9994 uint32_t insertion_index =
9995 EntryToIndex(table->FindInsertionEntry(hash));
9996 for (int j = 0; j < Shape::kEntrySize; j++) {
9997 table->set(insertion_index + j, get(from_index + j), mode);
9998 }
9999 }
10000 }
10001 table->SetNumberOfElements(NumberOfElements());
10002 table->SetNumberOfDeletedElements(0);
10003 return table;
10004 } 10039 }
10005 10040
10006 10041
10042 template<typename Shape, typename Key>
10043 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) {
10044 int capacity = Capacity();
10045 int nof = NumberOfElements();
10046
10047 // Shrink to fit the number of elements if only a quarter of the
10048 // capacity is filled with elements.
10049 if (nof > (capacity >> 2)) return this;
10050 // Allocate a new dictionary with room for at least the current
10051 // number of elements. The allocation method will make sure that
10052 // there is extra room in the dictionary for additions. Don't go
10053 // lower than room for 16 elements.
10054 int at_least_room_for = nof;
10055 if (at_least_room_for < 16) return this;
10056
10057 const int kMinCapacityForPretenure = 256;
10058 bool pretenure =
10059 (at_least_room_for > kMinCapacityForPretenure) &&
10060 !GetHeap()->InNewSpace(this);
10061 Object* obj;
10062 { MaybeObject* maybe_obj =
10063 Allocate(at_least_room_for, pretenure ? TENURED : NOT_TENURED);
10064 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10065 }
10066
10067 return Rehash(HashTable::cast(obj), key);
10068 }
10069
10070
10007 template<typename Shape, typename Key> 10071 template<typename Shape, typename Key>
10008 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) { 10072 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
10009 uint32_t capacity = Capacity(); 10073 uint32_t capacity = Capacity();
10010 uint32_t entry = FirstProbe(hash, capacity); 10074 uint32_t entry = FirstProbe(hash, capacity);
10011 uint32_t count = 1; 10075 uint32_t count = 1;
10012 // EnsureCapacity will guarantee the hash table is never full. 10076 // EnsureCapacity will guarantee the hash table is never full.
10013 while (true) { 10077 while (true) {
10014 Object* element = KeyAt(entry); 10078 Object* element = KeyAt(entry);
10015 if (element->IsUndefined() || element->IsNull()) break; 10079 if (element->IsUndefined() || element->IsNull()) break;
10016 entry = NextProbe(entry, count++, capacity); 10080 entry = NextProbe(entry, count++, capacity);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
10048 10112
10049 template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo( 10113 template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo(
10050 FixedArray*, PropertyAttributes); 10114 FixedArray*, PropertyAttributes);
10051 10115
10052 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty( 10116 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
10053 int, JSObject::DeleteMode); 10117 int, JSObject::DeleteMode);
10054 10118
10055 template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty( 10119 template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty(
10056 int, JSObject::DeleteMode); 10120 int, JSObject::DeleteMode);
10057 10121
10122 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Shrink(
10123 String*);
10124
10125 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Shrink(
10126 uint32_t);
10127
10058 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo( 10128 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
10059 FixedArray*); 10129 FixedArray*);
10060 10130
10061 template int 10131 template int
10062 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes( 10132 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
10063 PropertyAttributes); 10133 PropertyAttributes);
10064 10134
10065 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add( 10135 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add(
10066 String*, Object*, PropertyDetails); 10136 String*, Object*, PropertyDetails);
10067 10137
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after
10947 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) { 11017 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) {
10948 return heap->false_value(); 11018 return heap->false_value();
10949 } 11019 }
10950 SetEntry(entry, heap->null_value(), heap->null_value()); 11020 SetEntry(entry, heap->null_value(), heap->null_value());
10951 HashTable<Shape, Key>::ElementRemoved(); 11021 HashTable<Shape, Key>::ElementRemoved();
10952 return heap->true_value(); 11022 return heap->true_value();
10953 } 11023 }
10954 11024
10955 11025
10956 template<typename Shape, typename Key> 11026 template<typename Shape, typename Key>
11027 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) {
11028 return HashTable<Shape, Key>::Shrink(key);
11029 }
11030
11031
11032 template<typename Shape, typename Key>
10957 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { 11033 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
10958 int entry = this->FindEntry(key); 11034 int entry = this->FindEntry(key);
10959 11035
10960 // If the entry is present set the value; 11036 // If the entry is present set the value;
10961 if (entry != Dictionary<Shape, Key>::kNotFound) { 11037 if (entry != Dictionary<Shape, Key>::kNotFound) {
10962 ValueAtPut(entry, value); 11038 ValueAtPut(entry, value);
10963 return this; 11039 return this;
10964 } 11040 }
10965 11041
10966 // Check whether the dictionary should be extended. 11042 // Check whether the dictionary should be extended.
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after
11561 if (break_point_objects()->IsUndefined()) return 0; 11637 if (break_point_objects()->IsUndefined()) return 0;
11562 // Single beak point. 11638 // Single beak point.
11563 if (!break_point_objects()->IsFixedArray()) return 1; 11639 if (!break_point_objects()->IsFixedArray()) return 1;
11564 // Multiple break points. 11640 // Multiple break points.
11565 return FixedArray::cast(break_point_objects())->length(); 11641 return FixedArray::cast(break_point_objects())->length();
11566 } 11642 }
11567 #endif 11643 #endif
11568 11644
11569 11645
11570 } } // namespace v8::internal 11646 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698