aea3ce3df3
TypeFeedbackVectors are strongly rooted by a closure. However, in modern JavaScript closures are created and abandoned more freely. An important closure may not be present in the root-set at time of garbage collection, even though we've cached optimized code and use it regularly. For example, consider leaf functions in an event dispatching system. They may well be "hot," but tragically non-present when we collect the heap. Until now, we've relied on a weak root to cache the feedback vector in this case. Since there is no way to signal intent or relative importance, this weak root is as susceptible to clearing as any other weak root at garbage collection time. Meanwhile, the feedback vector has become more important. All of our ICs store their data there. Literal and regex boilerplates are stored there. If we lose the vector, then we not only lose optimized code built from it, we also lose the very feedback which allowed us to create that optimized code. Therefore it's vital to express that dependency through the root set. This CL does this by creating a strong link to a feedback vector at the instantiation site of the function closure. This instantiation site is in the code and feedback vector of the outer closure. BUG=v8:5456 Review-Url: https://codereview.chromium.org/2674593003 Cr-Commit-Position: refs/heads/master@{#42953}
56 lines
1.3 KiB
JavaScript
56 lines
1.3 KiB
JavaScript
// Copyright 2016 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 --turbo
|
|
|
|
// Make sure literals are strongly rooted and safe from weak-code deopts.
|
|
|
|
(function() {
|
|
function foo() {
|
|
var a = {y: 0};
|
|
a.y = 1;
|
|
return a;
|
|
}
|
|
|
|
foo();
|
|
foo();
|
|
% OptimizeFunctionOnNextCall(foo);
|
|
foo();
|
|
gc();
|
|
assertOptimized(foo);
|
|
})();
|
|
|
|
(function() {
|
|
function hot(o) {
|
|
return o.x + o.y;
|
|
}
|
|
function mapPlus(a, y) {
|
|
return a.map(x => hot({x, y}));
|
|
}
|
|
|
|
var a = [1, 2, 3];
|
|
print(mapPlus(a, 1));
|
|
print(mapPlus(a, 2));
|
|
% OptimizeFunctionOnNextCall(hot);
|
|
print(mapPlus(a, 3));
|
|
gc(); // BOOOM!
|
|
assertOptimized(hot);
|
|
print(mapPlus(a, 4));
|
|
})();
|
|
|
|
// Verify that we can handle the creation of a new script, where the
|
|
// code is cached and the feedback vector has to be re-created.
|
|
(function() {
|
|
var sopen = 'function wrapper() { ';
|
|
var s1 = 'function foo() { return bar(5); } ';
|
|
var s2 = 'foo(); foo(); %OptimizeFunctionOnNextCall(foo); foo(); ';
|
|
var sclose = '} wrapper(); ';
|
|
var s = sopen + s1 + s2 + sclose;
|
|
function bar(i){return i + 3};
|
|
|
|
for (var i = 0; i < 4; i++) {
|
|
eval(s);
|
|
}
|
|
})();
|