diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-12-08 13:24:59 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-12-08 13:24:59 +0100 |
commit | cd7832ee326b0c424d4ad1538efd074c86a68f9b (patch) | |
tree | 158872ea92d5df96b1290b578cbe574aaa2acfd5 /chromium/v8/src/elements.cc | |
parent | 93cdb9906305e23304d9ff55350b7557fc1850cb (diff) | |
parent | 69b8f9169ffd66fdeca1ac60a4bc06b91d106186 (diff) | |
download | qtwebengine-chromium-cd7832ee326b0c424d4ad1538efd074c86a68f9b.tar.gz |
Merge remote-tracking branch 'origin/upstream-master' into 63-based
Change-Id: I4d88054034fccbb7409fa65c37d4498b74ec0578
Diffstat (limited to 'chromium/v8/src/elements.cc')
-rw-r--r-- | chromium/v8/src/elements.cc | 145 |
1 files changed, 101 insertions, 44 deletions
diff --git a/chromium/v8/src/elements.cc b/chromium/v8/src/elements.cc index 577f77ddc84..8c692ecab82 100644 --- a/chromium/v8/src/elements.cc +++ b/chromium/v8/src/elements.cc @@ -1020,13 +1020,14 @@ class ElementsAccessorBase : public ElementsAccessor { } Object* CopyElements(Handle<JSReceiver> source, Handle<JSObject> destination, - size_t length) final { - return Subclass::CopyElementsHandleImpl(source, destination, length); + size_t length, uint32_t offset) final { + return Subclass::CopyElementsHandleImpl(source, destination, length, + offset); } static Object* CopyElementsHandleImpl(Handle<JSReceiver> source, Handle<JSObject> destination, - size_t length) { + size_t length, uint32_t offset) { UNREACHABLE(); } @@ -3168,28 +3169,30 @@ class TypedElementsAccessor template <typename SourceTraits> static void CopyBetweenBackingStores(FixedTypedArrayBase* source, - BackingStore* dest, size_t length) { + BackingStore* dest, size_t length, + uint32_t offset) { FixedTypedArray<SourceTraits>* source_fta = FixedTypedArray<SourceTraits>::cast(source); for (uint32_t i = 0; i < length; i++) { typename SourceTraits::ElementType elem = source_fta->get_scalar(i); - dest->set(i, dest->from(elem)); + dest->set(offset + i, dest->from(elem)); } } - static void CopyElementsHandleFromTypedArray(Handle<JSTypedArray> source, - Handle<JSTypedArray> destination, - size_t length) { + static void CopyElementsFromTypedArray(JSTypedArray* source, + JSTypedArray* destination, + size_t length, uint32_t offset) { // The source is a typed array, so we know we don't need to do ToNumber // side-effects, as the source elements will always be a number or // undefined. DisallowHeapAllocation no_gc; - Handle<FixedTypedArrayBase> source_elements( - FixedTypedArrayBase::cast(source->elements())); - Handle<BackingStore> destination_elements( - BackingStore::cast(destination->elements())); + FixedTypedArrayBase* source_elements = + FixedTypedArrayBase::cast(source->elements()); + BackingStore* destination_elements = + BackingStore::cast(destination->elements()); + DCHECK_LE(offset + source->length(), destination->length()); DCHECK_GE(destination->length(), source->length()); DCHECK(source->length()->IsSmi()); DCHECK_EQ(Smi::FromInt(static_cast<int>(length)), source->length()); @@ -3219,15 +3222,16 @@ class TypedElementsAccessor // which have special conversion operations. if (same_type || (same_size && both_are_simple)) { size_t element_size = source->element_size(); - std::memcpy(dest_data, source_data, length * element_size); + std::memcpy(dest_data + offset * element_size, source_data, + length * element_size); } else { // We use scalar accessors below to avoid boxing/unboxing, so there are // no allocations. switch (source->GetElementsKind()) { -#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ - case TYPE##_ELEMENTS: \ - CopyBetweenBackingStores<Type##ArrayTraits>( \ - *source_elements, *destination_elements, length); \ +#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ + case TYPE##_ELEMENTS: \ + CopyBetweenBackingStores<Type##ArrayTraits>( \ + source_elements, destination_elements, length, offset); \ break; TYPED_ARRAYS(TYPED_ARRAY_CASE) default: @@ -3238,23 +3242,27 @@ class TypedElementsAccessor } } - static bool HoleyPrototypeLookupRequired(Isolate* isolate, - Handle<JSArray> source) { + static bool HoleyPrototypeLookupRequired(Isolate* isolate, Context* context, + JSArray* source) { + DisallowHeapAllocation no_gc; + DisallowJavascriptExecution no_js(isolate); + Object* source_proto = source->map()->prototype(); + // Null prototypes are OK - we don't need to do prototype chain lookups on // them. if (source_proto->IsNull(isolate)) return false; if (source_proto->IsJSProxy()) return true; - DCHECK(source_proto->IsJSObject()); - if (!isolate->is_initial_array_prototype(JSObject::cast(source_proto))) { + if (!context->is_initial_array_prototype(JSObject::cast(source_proto))) { return true; } - return !isolate->IsFastArrayConstructorPrototypeChainIntact(); + + return !isolate->IsFastArrayConstructorPrototypeChainIntact(context); } - static bool TryCopyElementsHandleFastNumber(Handle<JSArray> source, - Handle<JSTypedArray> destination, - size_t length) { + static bool TryCopyElementsFastNumber(Context* context, JSArray* source, + JSTypedArray* destination, + size_t length, uint32_t offset) { Isolate* isolate = source->GetIsolate(); DisallowHeapAllocation no_gc; DisallowJavascriptExecution no_js(isolate); @@ -3267,7 +3275,7 @@ class TypedElementsAccessor // When the array has the original array prototype, and that prototype has // not been changed in a way that would affect lookups, we can just convert // the hole into undefined. - if (HoleyPrototypeLookupRequired(isolate, source)) return false; + if (HoleyPrototypeLookupRequired(isolate, context, source)) return false; Object* undefined = isolate->heap()->undefined_value(); @@ -3279,19 +3287,19 @@ class TypedElementsAccessor Object* elem = source_store->get(i); DCHECK(elem->IsSmi()); int int_value = Smi::ToInt(elem); - dest->set(i, dest->from(int_value)); + dest->set(offset + i, dest->from(int_value)); } return true; } else if (kind == HOLEY_SMI_ELEMENTS) { FixedArray* source_store = FixedArray::cast(source->elements()); for (uint32_t i = 0; i < length; i++) { if (source_store->is_the_hole(isolate, i)) { - dest->SetValue(i, undefined); + dest->SetValue(offset + i, undefined); } else { Object* elem = source_store->get(i); DCHECK(elem->IsSmi()); int int_value = Smi::ToInt(elem); - dest->set(i, dest->from(int_value)); + dest->set(offset + i, dest->from(int_value)); } } return true; @@ -3305,7 +3313,7 @@ class TypedElementsAccessor // Use the from_double conversion for this specific TypedArray type, // rather than relying on C++ to convert elem. double elem = source_store->get_scalar(i); - dest->set(i, dest->from(elem)); + dest->set(offset + i, dest->from(elem)); } return true; } else if (kind == HOLEY_DOUBLE_ELEMENTS) { @@ -3313,10 +3321,10 @@ class TypedElementsAccessor FixedDoubleArray::cast(source->elements()); for (uint32_t i = 0; i < length; i++) { if (source_store->is_the_hole(i)) { - dest->SetValue(i, undefined); + dest->SetValue(offset + i, undefined); } else { double elem = source_store->get_scalar(i); - dest->set(i, dest->from(elem)); + dest->set(offset + i, dest->from(elem)); } } return true; @@ -3326,7 +3334,7 @@ class TypedElementsAccessor static Object* CopyElementsHandleSlow(Handle<JSReceiver> source, Handle<JSTypedArray> destination, - size_t length) { + size_t length, uint32_t offset) { Isolate* isolate = source->GetIsolate(); Handle<BackingStore> destination_elements( BackingStore::cast(destination->elements())); @@ -3336,13 +3344,21 @@ class TypedElementsAccessor ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, elem, Object::GetProperty(&it)); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, elem, Object::ToNumber(elem)); - // We don't need to check for buffer neutering here, because the - // source cannot be a TypedArray. + + if (V8_UNLIKELY(destination->WasNeutered())) { + const char* op = "set"; + const MessageTemplate::Template message = + MessageTemplate::kDetachedOperation; + Handle<String> operation = + isolate->factory()->NewStringFromAsciiChecked(op); + THROW_NEW_ERROR_RETURN_FAILURE(isolate, + NewTypeError(message, operation)); + } // The spec says we store the length, then get each element, so we don't // need to check changes to length. - destination_elements->SetValue(i, *elem); + destination_elements->SetValue(offset + i, *elem); } - return Smi::kZero; + return *isolate->factory()->undefined_value(); } // This doesn't guarantee that the destination array will be completely @@ -3350,28 +3366,32 @@ class TypedElementsAccessor // that is required. static Object* CopyElementsHandleImpl(Handle<JSReceiver> source, Handle<JSObject> destination, - size_t length) { + size_t length, uint32_t offset) { + Isolate* isolate = destination->GetIsolate(); Handle<JSTypedArray> destination_ta = Handle<JSTypedArray>::cast(destination); + DCHECK_LE(offset + length, destination_ta->length_value()); + + if (length == 0) return *isolate->factory()->undefined_value(); // All conversions from TypedArrays can be done without allocation. if (source->IsJSTypedArray()) { Handle<JSTypedArray> source_ta = Handle<JSTypedArray>::cast(source); - CopyElementsHandleFromTypedArray(source_ta, destination_ta, length); - return Smi::kZero; + CopyElementsFromTypedArray(*source_ta, *destination_ta, length, offset); + return *isolate->factory()->undefined_value(); } // Fast cases for packed numbers kinds where we don't need to allocate. if (source->IsJSArray()) { Handle<JSArray> source_array = Handle<JSArray>::cast(source); - if (TryCopyElementsHandleFastNumber(source_array, destination_ta, - length)) { - return Smi::kZero; + if (TryCopyElementsFastNumber(isolate->context(), *source_array, + *destination_ta, length, offset)) { + return *isolate->factory()->undefined_value(); } } // Final generic case that handles prototype chain lookups, getters, proxies // and observable side effects via valueOf, etc. - return CopyElementsHandleSlow(source, destination_ta, length); + return CopyElementsHandleSlow(source, destination_ta, length, offset); } }; @@ -4307,6 +4327,43 @@ MaybeHandle<Object> ArrayConstructInitializeElements(Handle<JSArray> array, return array; } +void CopyFastNumberJSArrayElementsToTypedArray(Context* context, + JSArray* source, + JSTypedArray* destination, + uintptr_t length, + uintptr_t offset) { + DCHECK(context->IsContext()); + DCHECK(source->IsJSArray()); + DCHECK(destination->IsJSTypedArray()); + + switch (destination->GetElementsKind()) { +#define TYPED_ARRAYS_CASE(Type, type, TYPE, ctype, size) \ + case TYPE##_ELEMENTS: \ + CHECK(Fixed##Type##ElementsAccessor::TryCopyElementsFastNumber( \ + context, source, destination, length, static_cast<uint32_t>(offset))); \ + break; + TYPED_ARRAYS(TYPED_ARRAYS_CASE) +#undef TYPED_ARRAYS_CASE + default: + UNREACHABLE(); + } +} + +void CopyTypedArrayElementsToTypedArray(JSTypedArray* source, + JSTypedArray* destination, + uintptr_t length, uintptr_t offset) { + switch (destination->GetElementsKind()) { +#define TYPED_ARRAYS_CASE(Type, type, TYPE, ctype, size) \ + case TYPE##_ELEMENTS: \ + Fixed##Type##ElementsAccessor::CopyElementsFromTypedArray( \ + source, destination, length, static_cast<uint32_t>(offset)); \ + break; + TYPED_ARRAYS(TYPED_ARRAYS_CASE) +#undef TYPED_ARRAYS_CASE + default: + UNREACHABLE(); + } +} void ElementsAccessor::InitializeOncePerProcess() { static ElementsAccessor* accessor_array[] = { |