Files
v8/test/mjsunit/array-destructuring-expression.js
Leszek Swirski ca4fd87385 [arrdstrct] Make ArrayDestructure write registers directly
Drop the FixedArray allocation in ArrayDestructure, and write registers
directly when performing the ArrayDestructure.

This is needed not (just) for performance, but for correctness. The
two-phase approach of reading the iterator into a FixedArray and then
setting registers meant that throwing an exception in `next()` would
cause either all or none of the target registers to be set, rather
than setting them one-by-one as they are returned by the iterator.

This is done differently depending on the tier:

  * In Ignition and Sparkplug, the ArrayDestructure builtin now writes
    directly to the register frame, receiving its address as an
    argument.
  * In Maglev, the ArrayDestructure builtin is effectively eagerly
    inlined, desugared into the appropriate iteration protocol
    execution, where the abstract interpreter register values are
    updated one-by one to be exception safe, and lazy continuations
    handle finishing the writes to the remaining register in case
    there's a deopt
  * In Turbofan, I ain't doin' all that, so it's UNREACHABLE. Please
    write your local Turbolev representative to get the Maglev
    implementation working in the 4th tier.

TAG=agy
Conversation-Id: 7fc7c031-68c6-4ddc-bdff-6ce4e63adc59

Change-Id: Ie1d21dc20f845e8d04aea8a177cd632b155dbd32
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8035120
Reviewed-by: Marja Hölttä <marja@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#108498}
2026-07-07 08:27:13 -07:00

75 lines
1.8 KiB
JavaScript

// Copyright 2026 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.
// Flags: --allow-natives-syntax --maglev --turbolev --array-destructure-bytecode
(function TestDestructuringAsValueExpression() {
let a, b;
let arr = [10, 20];
let res = ([a, b] = arr);
assertEquals(arr, res);
assertEquals(10, a);
assertEquals(20, b);
})();
(function TestDestructuringInReturnStatement() {
function f(arr) {
let x, y;
return ([x, y] = arr);
}
%PrepareFunctionForOptimization(f);
let arr = [30, 40];
assertEquals(arr, f(arr));
assertEquals(arr, f(arr));
%OptimizeFunctionOnNextCall(f);
assertEquals(arr, f(arr));
assertOptimized(f);
})();
(function TestChainedDestructuringAssignments() {
function f(arr) {
let a, b, c, d;
let res = ([a, b] = ([c, d] = arr));
assertEquals(arr, res);
return a + b + c + d;
}
%PrepareFunctionForOptimization(f);
assertEquals(220, f([50, 60]));
assertEquals(220, f([50, 60]));
%OptimizeFunctionOnNextCall(f);
assertEquals(220, f([50, 60]));
assertOptimized(f);
})();
(function TestDestructuringWithDefaultValuesInExpression() {
function f(arr) {
let x, y;
return ([x = 100, y = 200] = arr);
}
%PrepareFunctionForOptimization(f);
let arr1 = [5, undefined];
assertEquals(arr1, f(arr1));
%OptimizeFunctionOnNextCall(f);
assertEquals(arr1, f(arr1));
assertOptimized(f);
})();
(function TestDestructuringWithHoles() {
function f(arr) {
let x, z;
return ([x, , z] = arr);
}
%PrepareFunctionForOptimization(f);
let arr = [10, 20, 30];
assertEquals(arr, f(arr));
assertEquals(arr, f(arr));
%OptimizeFunctionOnNextCall(f);
assertEquals(arr, f(arr));
assertOptimized(f);
})();