summaryrefslogtreecommitdiff
path: root/chromium/v8/src/elements.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/elements.cc')
-rw-r--r--chromium/v8/src/elements.cc145
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[] = {