PR-URL: https://github.com/nodejs/node/pull/58070 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
68 lines
2.2 KiB
JavaScript
68 lines
2.2 KiB
JavaScript
// Copyright 2024 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 --turboshaft-string-concat-escape-analysis
|
|
// Flags: --turbofan --no-always-turbofan
|
|
|
|
// This test ensures that string concat escape analysis does not try to create a
|
|
// FrameState with more inputs that the maximum number of inputs allowed in
|
|
// Turboshaft (2**16-1).
|
|
|
|
// The FrameState for `return s12 + a` will contain:
|
|
// * The Closure => 1 input
|
|
// * Parameters:
|
|
// * this => 1 input
|
|
// * "should_return" and "a" => 2 inputs
|
|
// * and other parameters
|
|
// * Context => 1 input
|
|
// * Local:
|
|
// * s12 => 1 input
|
|
// * Accumulator: a => 1 input
|
|
//
|
|
// So, that's 7 "fixed" input + all of the additional parameters. Then, string
|
|
// concat escape analysis should add 12 parameters (s1, s2, ..., s12). The
|
|
// maximum input count for a Turboshaft node is 2**16-1. So, we need to add n
|
|
// additional parameters such that n+12+7 is greater than 2**16-1, so we need at
|
|
// least 2**16-1-12 additional parameters. And we'll add a "-3" to this number,
|
|
// just to have a small buffer, to make the code instruction selector and
|
|
// generator happy (details, details, details, don't ask).
|
|
let additional_input_count = 2**16-1-12-3;
|
|
let fun_str = 'function foo(should_return, a';
|
|
for (let i = 0; i < additional_input_count; i++) {
|
|
fun_str += `, v${i}`;
|
|
}
|
|
fun_str += `) {
|
|
let s1 = a + a;
|
|
let s2 = s1 + a;
|
|
let s3 = s2 + a;
|
|
let s4 = s3 + a;
|
|
let s5 = s4 + a;
|
|
let s6 = s5 + a;
|
|
let s7 = s6 + a;
|
|
let s8 = s7 + a;
|
|
let s9 = s8 + a;
|
|
let s10 = s9 + a;
|
|
let s11 = s10 + a;
|
|
let s12 = s11 + a;
|
|
if (should_return) {
|
|
// We won't record feedback for this, which means that
|
|
// we'll have an unconditional deopt here.
|
|
return s12 + a;
|
|
}
|
|
}`;
|
|
|
|
eval(fun_str);
|
|
|
|
%PrepareFunctionForOptimization(foo);
|
|
foo(false, "a");
|
|
foo(false, "a");
|
|
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
foo(false, "a");
|
|
assertOptimized(foo);
|
|
|
|
// Passing `true` to `foo`, which will cause it to return the string (and,
|
|
// deopt, since we didn't record feedback for this.
|
|
assertEquals("aaaaaaaaaaaaaa", foo(true, "a"));
|