Commit 5d19e724 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[runtime] Hold cached template objects weakly

Cached template objects only need to be cached for reference identity
comparisons. If there is no strong reference to the cached template
object, then there's nothing to compare it against if it were to be
loaded from the cache, so we can hold it in the cache weakly.

Bug: v8:13190
Change-Id: I4a787eb33eab734fe9df6c424ff915d775fce70f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3898692
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83220}
parent e4c32b49
......@@ -73,6 +73,22 @@ Handle<AccessorPair> FactoryBase<Impl>::NewAccessorPair() {
return handle(accessors, isolate());
}
template <typename Impl>
Handle<CachedTemplateObject> FactoryBase<Impl>::NewCachedTemplateObject(
int function_literal_id, int slot_id, Handle<HeapObject> next,
Handle<JSArray> template_object, AllocationType allocation) {
DCHECK(next->IsCachedTemplateObject() || next->IsTheHole());
Map map = read_only_roots().cached_template_object_map();
CachedTemplateObject result = CachedTemplateObject::cast(
AllocateRawWithImmortalMap(CachedTemplateObject::kSize, allocation, map));
DisallowGarbageCollection no_gc;
result.set_function_literal_id(function_literal_id);
result.set_slot_id(slot_id);
result.set_template_object(HeapObjectReference::Weak(*template_object));
result.set_next(*next);
return handle(result, isolate());
}
template <typename Impl>
Handle<CodeDataContainer> FactoryBase<Impl>::NewCodeDataContainer(
int flags, AllocationType allocation) {
......
......@@ -102,6 +102,11 @@ class FactoryBase : public TorqueGeneratedFactory<Impl> {
Handle<CodeDataContainer> NewCodeDataContainer(int flags,
AllocationType allocation);
Handle<CachedTemplateObject> NewCachedTemplateObject(
int function_literal_id, int slot_id, Handle<HeapObject> next,
Handle<JSArray> template_object,
AllocationType allocation_type = AllocationType::kYoung);
// Allocates a fixed array initialized with undefined values.
Handle<FixedArray> NewFixedArray(
int length, AllocationType allocation = AllocationType::kYoung);
......
......@@ -315,8 +315,6 @@ IS_TYPE_FUNCTION_DECL(CodeT)
V(_, BreakPointMap, break_point_map, BreakPoint) \
V(_, BreakPointInfoMap, break_point_info_map, BreakPointInfo) \
V(_, BytecodeArrayMap, bytecode_array_map, BytecodeArray) \
V(_, CachedTemplateObjectMap, cached_template_object_map, \
CachedTemplateObject) \
V(_, CellMap, cell_map, Cell) \
V(_, WeakCellMap, weak_cell_map, WeakCell) \
V(_, CodeMap, code_map, Code) \
......
......@@ -91,6 +91,7 @@ class ZoneForwardList;
V(CallHandlerInfo) \
V(Callable) \
V(Cell) \
V(CachedTemplateObject) \
V(ClassBoilerplate) \
V(Code) \
V(CodeDataContainer) \
......
......@@ -32,7 +32,7 @@
#include "src/objects/source-text-module.h"
#include "src/objects/swiss-name-dictionary-inl.h"
#include "src/objects/synthetic-module.h"
#include "src/objects/template-objects.h"
#include "src/objects/template-objects-inl.h"
#include "src/objects/torque-defined-classes-inl.h"
#include "src/objects/transitions.h"
#include "src/objects/turbofan-types-inl.h"
......
......@@ -152,8 +152,6 @@ namespace internal {
async_generator_request) \
V(_, BREAK_POINT_TYPE, BreakPoint, break_point) \
V(_, BREAK_POINT_INFO_TYPE, BreakPointInfo, break_point_info) \
V(_, CACHED_TEMPLATE_OBJECT_TYPE, CachedTemplateObject, \
cached_template_object) \
V(_, CALL_SITE_INFO_TYPE, CallSiteInfo, call_site_info) \
V(_, CLASS_POSITIONS_TYPE, ClassPositions, class_positions) \
V(_, DEBUG_INFO_TYPE, DebugInfo, debug_info) \
......
......@@ -20,10 +20,12 @@ Handle<JSArray> TemplateObjectDescription::GetTemplateObject(
Handle<TemplateObjectDescription> description,
Handle<SharedFunctionInfo> shared_info, int slot_id) {
uint32_t hash = shared_info->Hash();
int function_literal_id = shared_info->function_literal_id();
// Check the template weakmap to see if the template object already exists.
Handle<EphemeronHashTable> template_weakmap;
Handle<Script> script(Script::cast(shared_info->script(isolate)), isolate);
MaybeHandle<CachedTemplateObject> existing_cached_template;
if (native_context->template_weakmap().IsUndefined(isolate)) {
template_weakmap = EphemeronHashTable::New(isolate, 1);
......@@ -34,14 +36,22 @@ Handle<JSArray> TemplateObjectDescription::GetTemplateObject(
EphemeronHashTable::cast(native_context->template_weakmap()), isolate);
Object maybe_cached_template =
template_weakmap->Lookup(isolate, script, hash);
int function_literal_id = shared_info->function_literal_id();
while (!maybe_cached_template.IsTheHole(roots)) {
CachedTemplateObject cached_template =
CachedTemplateObject::cast(maybe_cached_template);
if (cached_template.function_literal_id() == function_literal_id &&
cached_template.slot_id() == slot_id) {
return handle(cached_template.template_object(), isolate);
HeapObject template_object;
if (!cached_template.template_object(isolate).GetHeapObject(
&template_object)) {
// If the existing cached template is a cleared ref, update it
// in-place.
existing_cached_template = handle(cached_template, isolate);
break;
}
return handle(JSArray::cast(template_object), isolate);
}
// TODO(leszeks): Clean up entries with cleared object refs.
maybe_cached_template = cached_template.next();
}
}
......@@ -79,9 +89,15 @@ Handle<JSArray> TemplateObjectDescription::GetTemplateObject(
// Insert the template object into the template weakmap.
Handle<HeapObject> previous_cached_templates =
handle(HeapObject::cast(template_weakmap->Lookup(script, hash)), isolate);
Handle<CachedTemplateObject> cached_template = CachedTemplateObject::New(
isolate, shared_info->function_literal_id(), slot_id, template_object,
previous_cached_templates);
Handle<CachedTemplateObject> cached_template;
if (existing_cached_template.ToHandle(&cached_template)) {
cached_template->set_template_object(
HeapObjectReference::Weak(*template_object));
} else {
cached_template = isolate->factory()->NewCachedTemplateObject(
function_literal_id, slot_id, previous_cached_templates,
template_object);
}
template_weakmap = EphemeronHashTable::Put(isolate, template_weakmap, script,
cached_template, hash);
native_context->set_template_weakmap(*template_weakmap);
......@@ -89,23 +105,5 @@ Handle<JSArray> TemplateObjectDescription::GetTemplateObject(
return template_object;
}
Handle<CachedTemplateObject> CachedTemplateObject::New(
Isolate* isolate, int function_literal_id, int slot_id,
Handle<JSArray> template_object, Handle<HeapObject> next) {
DCHECK(next->IsCachedTemplateObject() || next->IsTheHole());
Handle<CachedTemplateObject> result_handle =
Handle<CachedTemplateObject>::cast(isolate->factory()->NewStruct(
CACHED_TEMPLATE_OBJECT_TYPE, AllocationType::kOld));
{
DisallowGarbageCollection no_gc;
auto result = *result_handle;
result.set_function_literal_id(function_literal_id);
result.set_slot_id(slot_id);
result.set_template_object(*template_object);
result.set_next(*next);
}
return result_handle;
}
} // namespace internal
} // namespace v8
......@@ -23,14 +23,10 @@ class StructBodyDescriptor;
// created. All the CachedTemplateObject's for a given SharedFunctionInfo form a
// linked list via the next fields.
class CachedTemplateObject final
: public TorqueGeneratedCachedTemplateObject<CachedTemplateObject, Struct> {
: public TorqueGeneratedCachedTemplateObject<CachedTemplateObject,
HeapObject> {
public:
static Handle<CachedTemplateObject> New(Isolate* isolate,
int function_literal_id, int slot_id,
Handle<JSArray> template_object,
Handle<HeapObject> next);
using BodyDescriptor = StructBodyDescriptor;
class BodyDescriptor;
TQ_OBJECT_CONSTRUCTORS(CachedTemplateObject)
};
......
......@@ -2,11 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
extern class CachedTemplateObject extends Struct {
@generateBodyDescriptor
@generateUniqueMap
extern class CachedTemplateObject extends HeapObject {
function_literal_id: Smi;
slot_id: Smi;
template_object: JSArray;
next: CachedTemplateObject|TheHole;
template_object: Weak<JSArray>;
}
extern class TemplateObjectDescription extends Struct {
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment