Index: src/elements.cc |
diff --git a/src/elements.cc b/src/elements.cc |
index e2127c4638201f5d7f8f46df2db960fd4b17fc95..abb046725c8a0923e2ccd45aaf9826ebb9eb0453 100644 |
--- a/src/elements.cc |
+++ b/src/elements.cc |
@@ -247,15 +247,18 @@ static void CopyDictionaryToObjectElements( |
} |
-static void CopyDoubleToObjectElements(Handle<FixedArrayBase> from_base, |
+// NOTE: this method violates the handlified function signature convention: |
+// raw pointer parameters in the function that allocates. |
+// See ElementsAccessorBase::CopyElements() for details. |
+static void CopyDoubleToObjectElements(FixedArrayBase* from_base, |
uint32_t from_start, |
- Handle<FixedArrayBase> to_base, |
- ElementsKind to_kind, |
- uint32_t to_start, |
+ FixedArrayBase* to_base, |
+ ElementsKind to_kind, uint32_t to_start, |
int raw_copy_size) { |
DCHECK(IsFastSmiOrObjectElementsKind(to_kind)); |
int copy_size = raw_copy_size; |
if (raw_copy_size < 0) { |
+ DisallowHeapAllocation no_allocation; |
DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd || |
raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
copy_size = Min(from_base->length() - from_start, |
@@ -268,7 +271,7 @@ static void CopyDoubleToObjectElements(Handle<FixedArrayBase> from_base, |
int length = to_base->length() - start; |
if (length > 0) { |
Heap* heap = from_base->GetHeap(); |
- MemsetPointer(FixedArray::cast(*to_base)->data_start() + start, |
+ MemsetPointer(FixedArray::cast(to_base)->data_start() + start, |
heap->the_hole_value(), length); |
} |
} |
@@ -276,9 +279,12 @@ static void CopyDoubleToObjectElements(Handle<FixedArrayBase> from_base, |
DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
(copy_size + static_cast<int>(from_start)) <= from_base->length()); |
if (copy_size == 0) return; |
+ |
+ // From here on, the code below could actually allocate. Therefore the raw |
+ // values are wrapped into handles. |
Isolate* isolate = from_base->GetIsolate(); |
- Handle<FixedDoubleArray> from = Handle<FixedDoubleArray>::cast(from_base); |
- Handle<FixedArray> to = Handle<FixedArray>::cast(to_base); |
+ Handle<FixedDoubleArray> from(FixedDoubleArray::cast(from_base), isolate); |
+ Handle<FixedArray> to(FixedArray::cast(to_base), isolate); |
for (int i = 0; i < copy_size; ++i) { |
HandleScope scope(isolate); |
if (IsFastSmiElementsKind(to_kind)) { |
@@ -702,12 +708,9 @@ class ElementsAccessorBase : public ElementsAccessor { |
uint32_t key, |
JSReceiver::DeleteMode mode) OVERRIDE = 0; |
- static void CopyElementsImpl(Handle<FixedArrayBase> from, |
- uint32_t from_start, |
- Handle<FixedArrayBase> to, |
- ElementsKind from_kind, |
- uint32_t to_start, |
- int packed_size, |
+ static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
+ FixedArrayBase* to, ElementsKind from_kind, |
+ uint32_t to_start, int packed_size, |
int copy_size) { |
UNREACHABLE(); |
} |
@@ -720,9 +723,15 @@ class ElementsAccessorBase : public ElementsAccessor { |
uint32_t to_start, |
int copy_size) FINAL OVERRIDE { |
DCHECK(!from.is_null()); |
- ElementsAccessorSubclass::CopyElementsImpl( |
- from, from_start, to, from_kind, to_start, kPackedSizeNotKnown, |
- copy_size); |
+ // NOTE: the ElementsAccessorSubclass::CopyElementsImpl() methods |
+ // violate the handlified function signature convention: |
+ // raw pointer parameters in the function that allocates. This is done |
+ // intentionally to avoid ArrayConcat() builtin performance degradation. |
+ // See the comment in another ElementsAccessorBase::CopyElements() for |
+ // details. |
+ ElementsAccessorSubclass::CopyElementsImpl(*from, from_start, *to, |
+ from_kind, to_start, |
+ kPackedSizeNotKnown, copy_size); |
} |
virtual void CopyElements( |
@@ -742,9 +751,18 @@ class ElementsAccessorBase : public ElementsAccessor { |
packed_size = copy_size; |
} |
} |
- Handle<FixedArrayBase> from(from_holder->elements()); |
+ FixedArrayBase* from = from_holder->elements(); |
+ // NOTE: the ElementsAccessorSubclass::CopyElementsImpl() methods |
+ // violate the handlified function signature convention: |
+ // raw pointer parameters in the function that allocates. This is done |
+ // intentionally to avoid ArrayConcat() builtin performance degradation. |
+ // |
+ // Details: The idea is that allocations actually happen only in case of |
+ // copying from object with fast double elements to object with object |
+ // elements. In all the other cases there are no allocations performed and |
+ // handle creation causes noticeable performance degradation of the builtin. |
ElementsAccessorSubclass::CopyElementsImpl( |
- from, from_start, to, from_kind, to_start, packed_size, copy_size); |
+ from, from_start, *to, from_kind, to_start, packed_size, copy_size); |
} |
virtual MaybeHandle<FixedArray> AddElementsToFixedArray( |
@@ -1018,7 +1036,7 @@ class FastElementsAccessor |
}; |
-static inline ElementsKind ElementsKindForArray(Handle<FixedArrayBase> array) { |
+static inline ElementsKind ElementsKindForArray(FixedArrayBase* array) { |
switch (array->map()->instance_type()) { |
case FIXED_ARRAY_TYPE: |
if (array->IsDictionary()) { |
@@ -1054,38 +1072,42 @@ class FastSmiOrObjectElementsAccessor |
: FastElementsAccessor<FastElementsAccessorSubclass, |
KindTraits>(name) {} |
- static void CopyElementsImpl(Handle<FixedArrayBase> from, |
- uint32_t from_start, |
- Handle<FixedArrayBase> to, |
- ElementsKind from_kind, |
- uint32_t to_start, |
- int packed_size, |
+ // NOTE: this method violates the handlified function signature convention: |
+ // raw pointer parameters in the function that allocates. |
+ // See ElementsAccessor::CopyElements() for details. |
+ // This method could actually allocate if copying from double elements to |
+ // object elements. |
+ static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
+ FixedArrayBase* to, ElementsKind from_kind, |
+ uint32_t to_start, int packed_size, |
int copy_size) { |
+ DisallowHeapAllocation no_gc; |
ElementsKind to_kind = KindTraits::Kind; |
switch (from_kind) { |
case FAST_SMI_ELEMENTS: |
case FAST_HOLEY_SMI_ELEMENTS: |
case FAST_ELEMENTS: |
case FAST_HOLEY_ELEMENTS: |
- CopyObjectToObjectElements(*from, from_kind, from_start, *to, to_kind, |
+ CopyObjectToObjectElements(from, from_kind, from_start, to, to_kind, |
to_start, copy_size); |
break; |
case FAST_DOUBLE_ELEMENTS: |
- case FAST_HOLEY_DOUBLE_ELEMENTS: |
+ case FAST_HOLEY_DOUBLE_ELEMENTS: { |
+ AllowHeapAllocation allow_allocation; |
CopyDoubleToObjectElements( |
from, from_start, to, to_kind, to_start, copy_size); |
break; |
+ } |
case DICTIONARY_ELEMENTS: |
- CopyDictionaryToObjectElements(*from, from_start, *to, to_kind, |
- to_start, copy_size); |
+ CopyDictionaryToObjectElements(from, from_start, to, to_kind, to_start, |
+ copy_size); |
break; |
case SLOPPY_ARGUMENTS_ELEMENTS: { |
// TODO(verwaest): This is a temporary hack to support extending |
// SLOPPY_ARGUMENTS_ELEMENTS in SetFastElementsCapacityAndLength. |
// This case should be UNREACHABLE(). |
- Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(from); |
- Handle<FixedArrayBase> arguments( |
- FixedArrayBase::cast(parameter_map->get(1))); |
+ FixedArray* parameter_map = FixedArray::cast(from); |
+ FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
ElementsKind from_kind = ElementsKindForArray(arguments); |
CopyElementsImpl(arguments, from_start, to, from_kind, |
to_start, packed_size, copy_size); |
@@ -1179,31 +1201,29 @@ class FastDoubleElementsAccessor |
} |
protected: |
- static void CopyElementsImpl(Handle<FixedArrayBase> from, |
- uint32_t from_start, |
- Handle<FixedArrayBase> to, |
- ElementsKind from_kind, |
- uint32_t to_start, |
- int packed_size, |
+ static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
+ FixedArrayBase* to, ElementsKind from_kind, |
+ uint32_t to_start, int packed_size, |
int copy_size) { |
+ DisallowHeapAllocation no_allocation; |
switch (from_kind) { |
case FAST_SMI_ELEMENTS: |
- CopyPackedSmiToDoubleElements(*from, from_start, *to, to_start, |
+ CopyPackedSmiToDoubleElements(from, from_start, to, to_start, |
packed_size, copy_size); |
break; |
case FAST_HOLEY_SMI_ELEMENTS: |
- CopySmiToDoubleElements(*from, from_start, *to, to_start, copy_size); |
+ CopySmiToDoubleElements(from, from_start, to, to_start, copy_size); |
break; |
case FAST_DOUBLE_ELEMENTS: |
case FAST_HOLEY_DOUBLE_ELEMENTS: |
- CopyDoubleToDoubleElements(*from, from_start, *to, to_start, copy_size); |
+ CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size); |
break; |
case FAST_ELEMENTS: |
case FAST_HOLEY_ELEMENTS: |
- CopyObjectToDoubleElements(*from, from_start, *to, to_start, copy_size); |
+ CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size); |
break; |
case DICTIONARY_ELEMENTS: |
- CopyDictionaryToDoubleElements(*from, from_start, *to, to_start, |
+ CopyDictionaryToDoubleElements(from, from_start, to, to_start, |
copy_size); |
break; |
case SLOPPY_ARGUMENTS_ELEMENTS: |
@@ -1439,12 +1459,9 @@ class DictionaryElementsAccessor |
return isolate->factory()->true_value(); |
} |
- static void CopyElementsImpl(Handle<FixedArrayBase> from, |
- uint32_t from_start, |
- Handle<FixedArrayBase> to, |
- ElementsKind from_kind, |
- uint32_t to_start, |
- int packed_size, |
+ static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
+ FixedArrayBase* to, ElementsKind from_kind, |
+ uint32_t to_start, int packed_size, |
int copy_size) { |
UNREACHABLE(); |
} |
@@ -1654,12 +1671,9 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase< |
return isolate->factory()->true_value(); |
} |
- static void CopyElementsImpl(Handle<FixedArrayBase> from, |
- uint32_t from_start, |
- Handle<FixedArrayBase> to, |
- ElementsKind from_kind, |
- uint32_t to_start, |
- int packed_size, |
+ static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
+ FixedArrayBase* to, ElementsKind from_kind, |
+ uint32_t to_start, int packed_size, |
int copy_size) { |
UNREACHABLE(); |
} |
@@ -1715,7 +1729,7 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase< |
ElementsAccessor* ElementsAccessor::ForArray(Handle<FixedArrayBase> array) { |
- return elements_accessors_[ElementsKindForArray(array)]; |
+ return elements_accessors_[ElementsKindForArray(*array)]; |
} |