[csa] Fix an old spec violation in Array.length writes
We used to apply an invalid optimization which skips `length` writes if the JSArray is 'fast' and the old value equals the new value. This optimization is not valid if e.g. `length` is non-writable. Fixed: chromium:1262478 Change-Id: I49ef50de293dae5c3a62c64b303ec34b9c0f6cbc Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3236720 Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Commit-Queue: Tobias Tebbi <tebbi@chromium.org> Auto-Submit: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/main@{#77552}
This commit is contained in:
parent
8678fc629d
commit
a6a113c6d5
@ -14726,42 +14726,8 @@ TNode<JSArray> CodeStubAssembler::ArrayCreate(TNode<Context> context,
|
|||||||
void CodeStubAssembler::SetPropertyLength(TNode<Context> context,
|
void CodeStubAssembler::SetPropertyLength(TNode<Context> context,
|
||||||
TNode<Object> array,
|
TNode<Object> array,
|
||||||
TNode<Number> length) {
|
TNode<Number> length) {
|
||||||
Label fast(this), runtime(this), done(this);
|
SetPropertyStrict(context, array, CodeStubAssembler::LengthStringConstant(),
|
||||||
// There's no need to set the length, if
|
length);
|
||||||
// 1) the array is a fast JS array and
|
|
||||||
// 2) the new length is equal to the old length.
|
|
||||||
// as the set is not observable. Otherwise fall back to the run-time.
|
|
||||||
|
|
||||||
// 1) Check that the array has fast elements.
|
|
||||||
// TODO(delphick): Consider changing this since it does an an unnecessary
|
|
||||||
// check for SMIs.
|
|
||||||
// TODO(delphick): Also we could hoist this to after the array construction
|
|
||||||
// and copy the args into array in the same way as the Array constructor.
|
|
||||||
BranchIfFastJSArray(array, context, &fast, &runtime);
|
|
||||||
|
|
||||||
BIND(&fast);
|
|
||||||
{
|
|
||||||
TNode<JSArray> fast_array = CAST(array);
|
|
||||||
|
|
||||||
TNode<Smi> length_smi = CAST(length);
|
|
||||||
TNode<Smi> old_length = LoadFastJSArrayLength(fast_array);
|
|
||||||
CSA_DCHECK(this, TaggedIsPositiveSmi(old_length));
|
|
||||||
|
|
||||||
// 2) If the created array's length matches the required length, then
|
|
||||||
// there's nothing else to do. Otherwise use the runtime to set the
|
|
||||||
// property as that will insert holes into excess elements or shrink
|
|
||||||
// the backing store as appropriate.
|
|
||||||
Branch(SmiNotEqual(length_smi, old_length), &runtime, &done);
|
|
||||||
}
|
|
||||||
|
|
||||||
BIND(&runtime);
|
|
||||||
{
|
|
||||||
SetPropertyStrict(context, array, CodeStubAssembler::LengthStringConstant(),
|
|
||||||
length);
|
|
||||||
Goto(&done);
|
|
||||||
}
|
|
||||||
|
|
||||||
BIND(&done);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TNode<Smi> CodeStubAssembler::RefillMathRandom(
|
TNode<Smi> CodeStubAssembler::RefillMathRandom(
|
||||||
|
8
test/mjsunit/regress/regress-1262478.js
Normal file
8
test/mjsunit/regress/regress-1262478.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Copyright 2021 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
let __v_0 = [];
|
||||||
|
Object.defineProperty(__v_0, 'length', { writable: false });
|
||||||
|
function __f_5() { return __v_0; }
|
||||||
|
assertThrows(() => Array.of.call(__f_5), TypeError);
|
Loading…
Reference in New Issue
Block a user