v8/test/mjsunit/regress/regress-4578.js
Camillo Bruni e3e8ea5d65 [flags] Rename --opt to --turbofan
To be consistent with the all the other tiers and avoid confusion, we
rename --opt to ---turbofan, and --always-opt to --always-turbofan.

Change-Id: Ie23dc8282b3fb4cf2fbf73b6c3d5264de5d09718
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610431
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Jakob Linke <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80336}
2022-05-03 12:10:30 +00:00

96 lines
2.9 KiB
JavaScript

// 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.
// Flags: --allow-natives-syntax --expose-gc --turbofan --no-concurrent-recompilation
// Flags: --no-stress-opt --no-always-turbofan --no-assert-types
// This weak ref is for checking whether the closure-allocated object o got
// collected as it should.
var weak;
// Return a function which refers to a variable from its enclosing function.
function makeFn() {
var o = {};
weak = new WeakRef(o);
o.num = 0;
return () => { return ++o.num; };
}
// Simple wrapper function which will cause inlining.
function g(f) {
f();
}
// Optimize g so that it inlines a specific function instance created by makeFn,
// and then drop all user-visible references to that function instance.
(function () {
var fn = makeFn();
%PrepareFunctionForOptimization(g);
%PrepareFunctionForOptimization(fn);
g(fn);
%OptimizeFunctionOnNextCall(g);
g(fn);
})();
// WeakRefs created during the current microtask are strong, so defer the rest.
setTimeout(() => {
// Since the function inlined by g no longer exists, it should deopt and
// release the inner function.
gc();
// Check that the memory leak described in v8:4578 no longer happens.
assertEquals(undefined, weak.deref());
// Next, let's check the opposite case: if an optimized function's Code is
// currently running at the time of gc, then it must keep its deoptimization
// data alive.
// Another simple wrapper function, but this one causes a GC internally.
function h(f) {
gcAndCheckState(); // Non-inlined call
f(); // Inlined call
}
var doCheck = false;
function gcAndCheckState() {
if (!doCheck) return;
// It's possible that h has already deoptimized by this point if
// --stress-incremental-marking caused additional gc cycles.
var optimized = isOptimized(h);
gc();
// If the optimized code for h is still on the stack, then it must not clear
// out its own deoptimization data. Eventually h will deopt due to the wrong
// function being passed, but only after this function has returned.
if (optimized) {
assertNotEquals(undefined, weak.deref());
} else {
assertEquals(undefined, weak.deref());
}
}
// Don't inline gcAndCheckState, to avoid the possibility that its content
// could cause h to deoptimize.
%NeverOptimizeFunction(gcAndCheckState);
// Optimize h to inline a specific function instance, and then drop all
// user-visible references to that inlined function.
(function () {
var fn = makeFn();
%PrepareFunctionForOptimization(h);
%PrepareFunctionForOptimization(fn);
h(fn);
%OptimizeFunctionOnNextCall(h);
h(fn);
})();
// Defer again so the WeakRef can expire.
setTimeout(() => {
doCheck = true;
h(() => {});
}, 0);
}, 0);