Prune decoded image resources retained by active documents once they grow beyond a recent working set. Route-heavy applications can load many unique images through one Document, and the shared resource and available-image caches would otherwise keep decoded image data alive after the DOM stopped using those images. Track cache touches and evict least recently used decoded images from both caches. This keeps active documents from accumulating unbounded decoded image resources while preserving a small hot cache for repeat loads.
79 lines
2.1 KiB
C++
79 lines
2.1 KiB
C++
/*
|
|
* Copyright (c) 2023, Andreas Kling <andreas@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/HashMap.h>
|
|
#include <LibJS/Heap/Cell.h>
|
|
#include <LibURL/Origin.h>
|
|
#include <LibURL/URL.h>
|
|
#include <LibWeb/Forward.h>
|
|
#include <LibWeb/HTML/CORSSettingAttribute.h>
|
|
|
|
namespace Web::HTML {
|
|
|
|
// https://html.spec.whatwg.org/multipage/images.html#list-of-available-images
|
|
class ListOfAvailableImages : public JS::Cell {
|
|
GC_CELL(ListOfAvailableImages, JS::Cell);
|
|
GC_DECLARE_ALLOCATOR(ListOfAvailableImages);
|
|
|
|
public:
|
|
struct Key {
|
|
String url;
|
|
HTML::CORSSettingAttribute mode;
|
|
Optional<URL::Origin> origin;
|
|
|
|
[[nodiscard]] bool operator==(Key const& other) const;
|
|
[[nodiscard]] u32 hash() const;
|
|
|
|
private:
|
|
mutable Optional<u32> cached_hash;
|
|
};
|
|
|
|
struct Entry {
|
|
Entry(GC::Ref<DecodedImageData> image_data, bool ignore_higher_layer_caching, u64 cache_touch_serial)
|
|
: image_data(move(image_data))
|
|
, ignore_higher_layer_caching(ignore_higher_layer_caching)
|
|
, cache_touch_serial(cache_touch_serial)
|
|
{
|
|
}
|
|
|
|
GC::Ref<DecodedImageData> image_data;
|
|
bool ignore_higher_layer_caching { false };
|
|
u64 cache_touch_serial { 0 };
|
|
};
|
|
|
|
ListOfAvailableImages();
|
|
~ListOfAvailableImages();
|
|
|
|
void add(Key const&, GC::Ref<DecodedImageData>, bool ignore_higher_layer_caching);
|
|
void remove(Key const&);
|
|
void prune_to_limits(size_t external_memory_limit, size_t count_limit);
|
|
[[nodiscard]] Entry* get(Key const&);
|
|
|
|
void visit_edges(JS::Cell::Visitor& visitor) override;
|
|
|
|
private:
|
|
HashMap<Key, NonnullOwnPtr<Entry>> m_images;
|
|
};
|
|
|
|
}
|
|
|
|
namespace AK {
|
|
|
|
template<>
|
|
struct Traits<Web::HTML::ListOfAvailableImages::Key> : public DefaultTraits<Web::HTML::ListOfAvailableImages::Key> {
|
|
static unsigned hash(Web::HTML::ListOfAvailableImages::Key const& key)
|
|
{
|
|
return key.hash();
|
|
}
|
|
static bool equals(Web::HTML::ListOfAvailableImages::Key const& a, Web::HTML::ListOfAvailableImages::Key const& b)
|
|
{
|
|
return a == b;
|
|
}
|
|
};
|
|
|
|
}
|