Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 7495d6e7099fcb7e6c8c02a36fc7249fd7e707d8..8479402e4a850a9db55bdb07e054332ad31d0ff3 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -2896,9 +2896,12 @@ MaybeObject* JSObject::NormalizeElements() { |
int length = IsJSArray() |
? Smi::cast(JSArray::cast(this)->length())->value() |
: array->length(); |
+ int old_capacity = 0; |
+ int used_elements = 0; |
+ GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
NumberDictionary* dictionary = NULL; |
{ Object* object; |
- MaybeObject* maybe = NumberDictionary::Allocate(length); |
+ MaybeObject* maybe = NumberDictionary::Allocate(used_elements); |
if (!maybe->ToObject(&object)) return maybe; |
dictionary = NumberDictionary::cast(object); |
} |
@@ -9083,62 +9086,69 @@ MaybeObject* JSObject::GetExternalElement(uint32_t index) { |
bool JSObject::HasDenseElements() { |
int capacity = 0; |
- int number_of_elements = 0; |
+ int used = 0; |
+ GetElementsCapacityAndUsage(&capacity, &used); |
+ return (capacity == 0) || (used > (capacity / 2)); |
+} |
+ |
+ |
+void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { |
+ *capacity = 0; |
+ *used = 0; |
FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements()); |
FixedArray* backing_store = NULL; |
- switch (GetElementsKind()) { |
+ ElementsKind kind = GetElementsKind(); |
+ switch (kind) { |
case NON_STRICT_ARGUMENTS_ELEMENTS: |
backing_store_base = |
FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
backing_store = FixedArray::cast(backing_store_base); |
if (backing_store->IsDictionary()) { |
NumberDictionary* dictionary = NumberDictionary::cast(backing_store); |
- capacity = dictionary->Capacity(); |
- number_of_elements = dictionary->NumberOfElements(); |
+ *capacity = dictionary->Capacity(); |
+ *used = dictionary->NumberOfElements(); |
break; |
} |
// Fall through. |
case FAST_ELEMENTS: |
backing_store = FixedArray::cast(backing_store_base); |
- capacity = backing_store->length(); |
- for (int i = 0; i < capacity; ++i) { |
- if (!backing_store->get(i)->IsTheHole()) ++number_of_elements; |
+ *capacity = backing_store->length(); |
+ for (int i = 0; i < *capacity; ++i) { |
+ if (!backing_store->get(i)->IsTheHole()) ++(*used); |
} |
break; |
case DICTIONARY_ELEMENTS: { |
NumberDictionary* dictionary = |
NumberDictionary::cast(FixedArray::cast(elements())); |
- capacity = dictionary->Capacity(); |
- number_of_elements = dictionary->NumberOfElements(); |
+ *capacity = dictionary->Capacity(); |
+ *used = dictionary->NumberOfElements(); |
break; |
} |
case FAST_DOUBLE_ELEMENTS: { |
FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
- capacity = elms->length(); |
- for (int i = 0; i < capacity; i++) { |
- if (!elms->is_the_hole(i)) number_of_elements++; |
+ *capacity = elms->length(); |
+ for (int i = 0; i < *capacity; i++) { |
+ if (!elms->is_the_hole(i)) ++(*used); |
} |
break; |
} |
- case EXTERNAL_PIXEL_ELEMENTS: |
- case EXTERNAL_BYTE_ELEMENTS: |
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
- case EXTERNAL_SHORT_ELEMENTS: |
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
- case EXTERNAL_INT_ELEMENTS: |
- case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
- case EXTERNAL_FLOAT_ELEMENTS: |
- case EXTERNAL_DOUBLE_ELEMENTS: { |
- return true; |
- } |
+ default: |
+ ASSERT(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND <= kind && |
+ kind <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
danno
2011/07/22 09:21:25
Please leave this explicitly enumerated and remove
Vitaly Repeshko
2011/07/25 15:50:55
Agreed. I added the external array cases back. The
|
+ break; |
} |
- return (capacity == 0) || (number_of_elements > (capacity / 2)); |
} |
bool JSObject::ShouldConvertToSlowElements(int new_capacity) { |
- if (new_capacity <= kMaxFastElementsLength) return false; |
+ STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <= |
+ kMaxUncheckedFastElementsLength); |
+ if (new_capacity <= kMaxUncheckedOldFastElementsLength || |
+ (new_capacity <= kMaxUncheckedFastElementsLength && |
+ GetHeap()->InNewSpace(this))) { |
+ return false; |
+ } |
// Keep the array in fast case if the current backing storage is |
// almost filled and if the new capacity is no more than twice the |
// old capacity. |