v8/test/mjsunit/regress/regress-v8-13190.js
Leszek Swirski 6013fdbac9 [runtime] Cache template objects as JSArray lists keyed on Script
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}
2022-10-13 15:34:51 +00:00

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");