OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 double the amount of elements if only a quarter of the | |
10048 // capacity is filled with elements and the new capacity is more | |
10049 // than 16 elements. | |
10050 if (nof > (capacity >> 2)) return this; | |
10051 int new_capacity = capacity >> 2; | |
10052 if (new_capacity < 16) return this; | |
Vyacheslav Egorov (Chromium)
2011/06/22 14:39:36
This is a bit strange.
I would ensure that (new_
Mads Ager (chromium)
2011/06/22 14:55:20
Ah, I actually mean this. However, I did not mean
| |
10053 | |
10054 const int kMinCapacityForPretenure = 256; | |
10055 bool pretenure = | |
10056 (new_capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this); | |
10057 Object* obj; | |
10058 { MaybeObject* maybe_obj = | |
10059 Allocate(new_capacity, pretenure ? TENURED : NOT_TENURED); | |
10060 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
10061 } | |
10062 | |
10063 return Rehash(HashTable::cast(obj), key); | |
10064 } | |
10065 | |
10066 | |
10007 template<typename Shape, typename Key> | 10067 template<typename Shape, typename Key> |
10008 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) { | 10068 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) { |
10009 uint32_t capacity = Capacity(); | 10069 uint32_t capacity = Capacity(); |
10010 uint32_t entry = FirstProbe(hash, capacity); | 10070 uint32_t entry = FirstProbe(hash, capacity); |
10011 uint32_t count = 1; | 10071 uint32_t count = 1; |
10012 // EnsureCapacity will guarantee the hash table is never full. | 10072 // EnsureCapacity will guarantee the hash table is never full. |
10013 while (true) { | 10073 while (true) { |
10014 Object* element = KeyAt(entry); | 10074 Object* element = KeyAt(entry); |
10015 if (element->IsUndefined() || element->IsNull()) break; | 10075 if (element->IsUndefined() || element->IsNull()) break; |
10016 entry = NextProbe(entry, count++, capacity); | 10076 entry = NextProbe(entry, count++, capacity); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10048 | 10108 |
10049 template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo( | 10109 template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo( |
10050 FixedArray*, PropertyAttributes); | 10110 FixedArray*, PropertyAttributes); |
10051 | 10111 |
10052 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty( | 10112 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty( |
10053 int, JSObject::DeleteMode); | 10113 int, JSObject::DeleteMode); |
10054 | 10114 |
10055 template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty( | 10115 template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty( |
10056 int, JSObject::DeleteMode); | 10116 int, JSObject::DeleteMode); |
10057 | 10117 |
10118 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Shrink( | |
10119 String*); | |
10120 | |
10121 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Shrink( | |
10122 uint32_t); | |
10123 | |
10058 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo( | 10124 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo( |
10059 FixedArray*); | 10125 FixedArray*); |
10060 | 10126 |
10061 template int | 10127 template int |
10062 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes( | 10128 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes( |
10063 PropertyAttributes); | 10129 PropertyAttributes); |
10064 | 10130 |
10065 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add( | 10131 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add( |
10066 String*, Object*, PropertyDetails); | 10132 String*, Object*, PropertyDetails); |
10067 | 10133 |
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10947 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) { | 11013 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) { |
10948 return heap->false_value(); | 11014 return heap->false_value(); |
10949 } | 11015 } |
10950 SetEntry(entry, heap->null_value(), heap->null_value()); | 11016 SetEntry(entry, heap->null_value(), heap->null_value()); |
10951 HashTable<Shape, Key>::ElementRemoved(); | 11017 HashTable<Shape, Key>::ElementRemoved(); |
10952 return heap->true_value(); | 11018 return heap->true_value(); |
10953 } | 11019 } |
10954 | 11020 |
10955 | 11021 |
10956 template<typename Shape, typename Key> | 11022 template<typename Shape, typename Key> |
11023 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) { | |
11024 return HashTable<Shape, Key>::Shrink(key); | |
11025 } | |
11026 | |
11027 | |
11028 template<typename Shape, typename Key> | |
10957 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { | 11029 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { |
10958 int entry = this->FindEntry(key); | 11030 int entry = this->FindEntry(key); |
10959 | 11031 |
10960 // If the entry is present set the value; | 11032 // If the entry is present set the value; |
10961 if (entry != Dictionary<Shape, Key>::kNotFound) { | 11033 if (entry != Dictionary<Shape, Key>::kNotFound) { |
10962 ValueAtPut(entry, value); | 11034 ValueAtPut(entry, value); |
10963 return this; | 11035 return this; |
10964 } | 11036 } |
10965 | 11037 |
10966 // Check whether the dictionary should be extended. | 11038 // Check whether the dictionary should be extended. |
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11561 if (break_point_objects()->IsUndefined()) return 0; | 11633 if (break_point_objects()->IsUndefined()) return 0; |
11562 // Single beak point. | 11634 // Single beak point. |
11563 if (!break_point_objects()->IsFixedArray()) return 1; | 11635 if (!break_point_objects()->IsFixedArray()) return 1; |
11564 // Multiple break points. | 11636 // Multiple break points. |
11565 return FixedArray::cast(break_point_objects())->length(); | 11637 return FixedArray::cast(break_point_objects())->length(); |
11566 } | 11638 } |
11567 #endif | 11639 #endif |
11568 | 11640 |
11569 | 11641 |
11570 } } // namespace v8::internal | 11642 } } // namespace v8::internal |
OLD | NEW |