forked from LeenkxTeam/Kmake
98 lines
3.3 KiB
JavaScript
98 lines
3.3 KiB
JavaScript
// Copyright 2023 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
|
|
|
|
function maybe_throw() {}
|
|
%NeverOptimizeFunction(maybe_throw);
|
|
|
|
function with_merge_after_try_catch() {
|
|
var x;
|
|
var inner = function () {
|
|
// This modifies the statically-known parent context.
|
|
x = "foo";
|
|
};
|
|
%PrepareFunctionForOptimization(inner);
|
|
|
|
try {
|
|
// Call a function so that we don't eliminate the try-catch.
|
|
maybe_throw();
|
|
} catch (e) {}
|
|
|
|
// After this try-catch, we should not have a Phi for the context, else
|
|
// context load-after-store elimination will incorrectly miss the store inside
|
|
// `inner`.
|
|
|
|
x = "bar"; // store context[x] = "bar"
|
|
inner(); // store context[x] = "foo" via inner
|
|
return x; // load context[x]
|
|
};
|
|
%PrepareFunctionForOptimization(with_merge_after_try_catch);
|
|
assertEquals("foo", with_merge_after_try_catch());
|
|
assertEquals("foo", with_merge_after_try_catch());
|
|
%OptimizeFunctionOnNextCall(with_merge_after_try_catch);
|
|
assertEquals("foo", with_merge_after_try_catch());
|
|
|
|
async function with_merge_after_try_catch_that_has_await() {
|
|
var x;
|
|
var inner = function () {
|
|
// This modifies the statically-known parent context.
|
|
x = "foo";
|
|
};
|
|
%PrepareFunctionForOptimization(inner);
|
|
|
|
try {
|
|
// Call a function so that we don't eliminate the try-catch.
|
|
maybe_throw();
|
|
} catch (e) {
|
|
// This will suspend+resume, which switches back to using the on-stack
|
|
// context on resume.
|
|
await 0;
|
|
}
|
|
|
|
// After this try-catch, we will have a Phi for the context, between the
|
|
// created function context (if there was no suspend) and the on-stack context
|
|
// (if there was one). Context load-after-store elimination should still not
|
|
// miss the store inside `inner`.
|
|
|
|
x = "bar"; // store context[x] = "bar"
|
|
inner(); // store context[x] = "foo" via inner
|
|
return x; // load context[x]
|
|
};
|
|
|
|
(async function () {
|
|
%PrepareFunctionForOptimization(with_merge_after_try_catch_that_has_await);
|
|
assertEquals("foo", await with_merge_after_try_catch_that_has_await());
|
|
assertEquals("foo", await with_merge_after_try_catch_that_has_await());
|
|
%OptimizeFunctionOnNextCall(with_merge_after_try_catch_that_has_await);
|
|
assertEquals("foo", await with_merge_after_try_catch_that_has_await());
|
|
})()
|
|
|
|
|
|
function with_inner_mixed_context_return(return_inside_block) {
|
|
function inner() {
|
|
{
|
|
// Create a block context.
|
|
let x = 5;
|
|
let inner = function () { x; };
|
|
// Return from inside the block context.
|
|
if (return_inside_block) return 1;
|
|
}
|
|
// Return outside the block context.
|
|
return 2;
|
|
}
|
|
%PrepareFunctionForOptimization(inner);
|
|
|
|
// There should be no DCHECK failures about context phis from inlining the
|
|
// inner function call, despite that having returns both inside and outside
|
|
// the block context.
|
|
return inner();
|
|
};
|
|
%PrepareFunctionForOptimization(with_inner_mixed_context_return);
|
|
assertEquals(1, with_inner_mixed_context_return(true));
|
|
assertEquals(2, with_inner_mixed_context_return(false));
|
|
%OptimizeFunctionOnNextCall(with_inner_mixed_context_return);
|
|
assertEquals(1, with_inner_mixed_context_return(true));
|
|
assertEquals(2, with_inner_mixed_context_return(false));
|