Commit 902759b8 authored by Shu-yu Guo's avatar Shu-yu Guo Committed by V8 LUCI CQ

[change-array-by-copy] Initialize elements in Array.prototype.toSpliced

The fast path of Array#toSpliced currently does not correctly initialize
the elements range in the copy's FixedArray elements that will hold the
inserted items. A GC can occur between the initial allocation of the
elements before the inserted items are copied into it, which will fail
heap verification.

This CL also refactors CSA's FillFixedArrayWithSmiZero method to support
only zeroing a portion of a FixedArray instead of the entire thing.

Bug: v8:13035
Change-Id: I1bdb77d3b27f682620b45caa5a9c10ea0072a6ad
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3750321Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81665}
parent f1eb47dc
......@@ -20,8 +20,18 @@ macro CopyFastPackedArrayForToSpliced(implicit context: Context)(
// Copy the part before the inserted items.
CopyElements(kind, copy, 0, array.elements, 0, actualStart);
// Leave the items to be inserted for later since it could transition the
// ElementsKind.
// Initialize elements that will hold the inserted items because the
// NewJSArray below may allocate. Leave the actual insertion for later since
// it could transition the ElementsKind.
if (insertCount > 0) {
if constexpr (kind == ElementsKind::PACKED_DOUBLE_ELEMENTS) {
FillFixedDoubleArrayWithZero(
UnsafeCast<FixedDoubleArray>(copy), actualStart, insertCount);
} else {
FillFixedArrayWithSmiZero(
kind, UnsafeCast<FixedArray>(copy), actualStart, insertCount);
}
}
// Copy the part after the inserted items.
const secondPartStart: intptr = actualStart + insertCount;
......
......@@ -4040,9 +4040,9 @@ CodeStubAssembler::AllocateUninitializedJSArrayWithElements(
elements = AllocateFixedArray(kind, capacity, allocation_flags);
if (IsDoubleElementsKind(kind)) {
FillFixedDoubleArrayWithZero(CAST(elements.value()), capacity);
FillEntireFixedDoubleArrayWithZero(CAST(elements.value()), capacity);
} else {
FillFixedArrayWithSmiZero(CAST(elements.value()), capacity);
FillEntireFixedArrayWithSmiZero(kind, CAST(elements.value()), capacity);
}
// The JSArray and possibly allocation memento next. Note that
......@@ -4710,17 +4710,23 @@ void CodeStubAssembler::StoreFixedDoubleArrayHole(TNode<FixedDoubleArray> array,
StoreDoubleHole(array, offset);
}
void CodeStubAssembler::FillFixedArrayWithSmiZero(TNode<FixedArray> array,
void CodeStubAssembler::FillFixedArrayWithSmiZero(ElementsKind kind,
TNode<FixedArray> array,
TNode<IntPtrT> start,
TNode<IntPtrT> length) {
CSA_DCHECK(this, WordEqual(length, LoadAndUntagFixedArrayBaseLength(array)));
DCHECK(IsSmiOrObjectElementsKind(kind));
CSA_DCHECK(this,
IntPtrLessThanOrEqual(IntPtrAdd(start, length),
LoadAndUntagFixedArrayBaseLength(array)));
TNode<IntPtrT> byte_length = TimesTaggedSize(length);
CSA_DCHECK(this, UintPtrLessThan(length, byte_length));
static const int32_t fa_base_data_offset =
FixedArray::kHeaderSize - kHeapObjectTag;
TNode<IntPtrT> backing_store = IntPtrAdd(BitcastTaggedToWord(array),
IntPtrConstant(fa_base_data_offset));
TNode<IntPtrT> offset =
ElementOffsetFromIndex(start, kind, fa_base_data_offset);
TNode<IntPtrT> backing_store = IntPtrAdd(BitcastTaggedToWord(array), offset);
// Call out to memset to perform initialization.
TNode<ExternalReference> memset =
......@@ -4733,16 +4739,20 @@ void CodeStubAssembler::FillFixedArrayWithSmiZero(TNode<FixedArray> array,
}
void CodeStubAssembler::FillFixedDoubleArrayWithZero(
TNode<FixedDoubleArray> array, TNode<IntPtrT> length) {
CSA_DCHECK(this, WordEqual(length, LoadAndUntagFixedArrayBaseLength(array)));
TNode<FixedDoubleArray> array, TNode<IntPtrT> start,
TNode<IntPtrT> length) {
CSA_DCHECK(this,
IntPtrLessThanOrEqual(IntPtrAdd(start, length),
LoadAndUntagFixedArrayBaseLength(array)));
TNode<IntPtrT> byte_length = TimesDoubleSize(length);
CSA_DCHECK(this, UintPtrLessThan(length, byte_length));
static const int32_t fa_base_data_offset =
FixedDoubleArray::kHeaderSize - kHeapObjectTag;
TNode<IntPtrT> backing_store = IntPtrAdd(BitcastTaggedToWord(array),
IntPtrConstant(fa_base_data_offset));
TNode<IntPtrT> offset = ElementOffsetFromIndex(start, PACKED_DOUBLE_ELEMENTS,
fa_base_data_offset);
TNode<IntPtrT> backing_store = IntPtrAdd(BitcastTaggedToWord(array), offset);
// Call out to memset to perform initialization.
TNode<ExternalReference> memset =
......
......@@ -2032,7 +2032,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<FixedArray> result = UncheckedCast<FixedArray>(
AllocateFixedArray(PACKED_ELEMENTS, capacity,
AllocationFlag::kAllowLargeObjectAllocation));
FillFixedArrayWithSmiZero(result, capacity);
FillEntireFixedArrayWithSmiZero(PACKED_ELEMENTS, result, capacity);
return result;
}
......@@ -2041,7 +2041,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<FixedDoubleArray> result = UncheckedCast<FixedDoubleArray>(
AllocateFixedArray(PACKED_DOUBLE_ELEMENTS, capacity,
AllocationFlag::kAllowLargeObjectAllocation));
FillFixedDoubleArrayWithZero(result, capacity);
FillEntireFixedDoubleArrayWithZero(result, capacity);
return result;
}
......@@ -2085,10 +2085,25 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
RootIndex value_root_index);
// Uses memset to effectively initialize the given FixedArray with zeroes.
void FillFixedArrayWithSmiZero(TNode<FixedArray> array,
TNode<IntPtrT> length);
void FillFixedArrayWithSmiZero(ElementsKind kind, TNode<FixedArray> array,
TNode<IntPtrT> start, TNode<IntPtrT> length);
void FillEntireFixedArrayWithSmiZero(ElementsKind kind,
TNode<FixedArray> array,
TNode<IntPtrT> length) {
CSA_DCHECK(this,
WordEqual(length, LoadAndUntagFixedArrayBaseLength(array)));
FillFixedArrayWithSmiZero(kind, array, IntPtrConstant(0), length);
}
void FillFixedDoubleArrayWithZero(TNode<FixedDoubleArray> array,
TNode<IntPtrT> start,
TNode<IntPtrT> length);
void FillEntireFixedDoubleArrayWithZero(TNode<FixedDoubleArray> array,
TNode<IntPtrT> length) {
CSA_DCHECK(this,
WordEqual(length, LoadAndUntagFixedArrayBaseLength(array)));
FillFixedDoubleArrayWithZero(array, IntPtrConstant(0), length);
}
void FillPropertyArrayWithUndefined(TNode<PropertyArray> array,
TNode<IntPtrT> from_index,
......
......@@ -104,6 +104,11 @@ extern macro AllocateZeroedFixedDoubleArray(intptr): FixedDoubleArray;
extern macro CalculateNewElementsCapacity(Smi): Smi;
extern macro CalculateNewElementsCapacity(intptr): intptr;
extern macro FillFixedArrayWithSmiZero(
constexpr ElementsKind, FixedArray, intptr, intptr): void;
extern macro FillFixedDoubleArrayWithZero(
FixedDoubleArray, intptr, intptr): void;
extern macro AllocateFixedArrayWithHoles(
intptr, constexpr AllocationFlag): FixedArray;
extern macro AllocateFixedDoubleArrayWithHoles(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment