Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index e7cdc518981f300942f57edcace5c65eabf6e0dc..8e36ae5337a8da2f0aea27b5b9ae1d1af2698899 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -4689,7 +4689,7 @@ MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { |
case JSObject::FAST_ELEMENTS: |
return UnionOfKeys(FixedArray::cast(array->elements())); |
case JSObject::FAST_DOUBLE_ELEMENTS: |
- UNIMPLEMENTED(); |
+ return UnionOfDoubleKeys(FixedDoubleArray::cast(array->elements())); |
break; |
case JSObject::DICTIONARY_ELEMENTS: { |
NumberDictionary* dict = array->element_dictionary(); |
@@ -4786,6 +4786,69 @@ MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { |
} |
+MaybeObject* FixedArray::UnionOfDoubleKeys(FixedDoubleArray* other) { |
+ int len0 = length(); |
+#ifdef DEBUG |
+ if (FLAG_enable_slow_asserts) { |
+ for (int i = 0; i < len0; i++) { |
+ ASSERT(get(i)->IsString() || get(i)->IsNumber()); |
+ } |
+ } |
+#endif |
+ int len1 = other->length(); |
+ // Optimize if 'other' is empty. |
+ // We cannot optimize if 'this' is empty, as other may have holes |
+ // or non keys. |
+ if (len1 == 0) return this; |
+ |
+ // Compute how many elements are not in this. |
+ int extra = 0; |
+ Heap* heap = GetHeap(); |
+ Object* obj; |
+ for (int y = 0; y < len1; y++) { |
+ if (!other->is_the_hole(y)) { |
+ MaybeObject* maybe_obj = heap->NumberFromDouble(other->get(y)); |
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
+ if (!HasKey(this, obj)) extra++; |
+ } |
+ } |
+ |
+ if (extra == 0) return this; |
+ |
+ // Allocate the result |
+ { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(len0 + extra); |
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
+ } |
+ // Fill in the content |
+ FixedArray* result = FixedArray::cast(obj); |
+ { |
+ // Limit the scope of the AssertNoAllocation |
+ AssertNoAllocation no_gc; |
+ WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
+ for (int i = 0; i < len0; i++) { |
+ Object* e = get(i); |
+ ASSERT(e->IsString() || e->IsNumber()); |
+ result->set(i, e, mode); |
+ } |
+ } |
+ |
+ // Fill in the extra keys. |
+ int index = 0; |
+ for (int y = 0; y < len1; y++) { |
+ if (!other->is_the_hole(y)) { |
+ MaybeObject* maybe_obj = heap->NumberFromDouble(other->get(y)); |
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
+ if (!HasKey(this, obj)) { |
+ result->set(len0 + index, obj); |
+ index++; |
+ } |
+ } |
+ } |
+ ASSERT(extra == index); |
+ return result; |
+} |
+ |
+ |
MaybeObject* FixedArray::CopySize(int new_length) { |
Heap* heap = GetHeap(); |
if (new_length == 0) return heap->empty_fixed_array(); |
@@ -7542,9 +7605,10 @@ MaybeObject* JSObject::SetSlowElements(Object* len) { |
switch (GetElementsKind()) { |
case FAST_ELEMENTS: { |
+ case FAST_DOUBLE_ELEMENTS: |
// Make sure we never try to shrink dense arrays into sparse arrays. |
- ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <= |
- new_length); |
+ ASSERT(static_cast<uint32_t>( |
+ FixedArrayBase::cast(elements())->length()) <= new_length); |
MaybeObject* result = NormalizeElements(); |
if (result->IsFailure()) return result; |
@@ -7573,7 +7637,6 @@ MaybeObject* JSObject::SetSlowElements(Object* len) { |
case EXTERNAL_FLOAT_ELEMENTS: |
case EXTERNAL_DOUBLE_ELEMENTS: |
case EXTERNAL_PIXEL_ELEMENTS: |
- case FAST_DOUBLE_ELEMENTS: |
UNREACHABLE(); |
break; |
} |
@@ -7914,6 +7977,17 @@ bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { |
} |
break; |
} |
+ case FAST_DOUBLE_ELEMENTS: { |
+ uint32_t length = IsJSArray() ? |
+ static_cast<uint32_t> |
+ (Smi::cast(JSArray::cast(this)->length())->value()) : |
+ static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
+ if ((index < length) && |
+ !FixedDoubleArray::cast(elements())->is_the_hole(index)) { |
+ return true; |
+ } |
+ break; |
+ } |
case EXTERNAL_PIXEL_ELEMENTS: { |
ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
if (index < static_cast<uint32_t>(pixels->length())) { |
@@ -7928,8 +8002,7 @@ bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { |
case EXTERNAL_INT_ELEMENTS: |
case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
case EXTERNAL_FLOAT_ELEMENTS: |
- case EXTERNAL_DOUBLE_ELEMENTS: |
- case FAST_DOUBLE_ELEMENTS: { |
+ case EXTERNAL_DOUBLE_ELEMENTS: { |
ExternalArray* array = ExternalArray::cast(elements()); |
if (index < static_cast<uint32_t>(array->length())) { |
return true; |
@@ -9380,6 +9453,15 @@ bool JSObject::HasRealElementProperty(uint32_t index) { |
return (index < length) && |
!FixedArray::cast(elements())->get(index)->IsTheHole(); |
} |
+ case FAST_DOUBLE_ELEMENTS: { |
+ uint32_t length = IsJSArray() ? |
+ static_cast<uint32_t>( |
+ Smi::cast(JSArray::cast(this)->length())->value()) : |
+ static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
+ return (index < length) && |
+ !FixedDoubleArray::cast(elements())->is_the_hole(index); |
+ break; |
+ } |
case EXTERNAL_PIXEL_ELEMENTS: { |
ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
return index < static_cast<uint32_t>(pixels->length()); |
@@ -9395,9 +9477,6 @@ bool JSObject::HasRealElementProperty(uint32_t index) { |
ExternalArray* array = ExternalArray::cast(elements()); |
return index < static_cast<uint32_t>(array->length()); |
} |
- case FAST_DOUBLE_ELEMENTS: |
- UNREACHABLE(); |
- break; |
case DICTIONARY_ELEMENTS: { |
return element_dictionary()->FindEntry(index) |
!= NumberDictionary::kNotFound; |