6013fdbac9
Make several changes to template object caching: * Key the cache on Script rather than SFI, so that entries stay alive even if the SFI dies (e.g. because its parent is code flushed) but can be resurrected (because other functions from the same script can recreate it) * With the above change, identify the required template object by comparing both function literal id and feedback slot id. * Change the cache from a linked list of CachedTemplateObjects into an ArrayList pointing directly to the template object JSArrays. * With CachedTemplateObjects being gone, store the function literal id and slot id directly on the JSArray behind private symbols. Fast path access to them in the case where the template object has the expected map, and look them up in a slow path if the map changed (e.g. because the template object was used as a prototype and transitioned to a dictionary map). Change-Id: Id715cb2fd38b9605b8e6ddf5e35336bb4f0300d2 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3900376 Commit-Queue: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/main@{#83693}
49 lines
1.5 KiB
JavaScript
49 lines
1.5 KiB
JavaScript
// Copyright 2022 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
|
|
// Flags: --no-sparkplug --no-maglev --no-turbofan
|
|
// Flags: --lazy --flush-bytecode
|
|
|
|
// Helper that, given a template object, simply returns it.
|
|
function get_template_object(obj) {
|
|
return obj;
|
|
}
|
|
|
|
function foo_factory() {
|
|
// The SFI for foo is held by the bytecode array of foo_factory, so will be
|
|
// collected if foo_factory's bytecode is flushed.
|
|
return function foo() {
|
|
return get_template_object``
|
|
}
|
|
}
|
|
|
|
// Create foo in another function to avoid it leaking on the global object or
|
|
// top-level script locals, and accidentally being kept alive.
|
|
function get_foo_template_object() {
|
|
let foo = foo_factory();
|
|
return foo();
|
|
}
|
|
|
|
assertTrue(isLazy(foo_factory));
|
|
|
|
let inital_template_object = get_foo_template_object();
|
|
assertEquals(inital_template_object, get_foo_template_object(),
|
|
"Template object identity should be preserved");
|
|
|
|
// Force a flush of foo_factory, so that the SharedFunctionInfo of foo can be
|
|
// collected.
|
|
%ForceFlush(foo_factory);
|
|
assertTrue(isLazy(foo_factory));
|
|
|
|
// Do a few more GCs to allow weak maps to be cleared.
|
|
gc();
|
|
gc();
|
|
gc();
|
|
|
|
// Flushing foo_factory and GCing foo should not affect the persisted reference
|
|
// identity of the template object inside foo.
|
|
assertSame(inital_template_object, get_foo_template_object(),
|
|
"Template object identity should be preserved");
|