LibWeb: Account text and image storage as external memory
Report DOM character data, decoded image frames, ImageBitmap pixel buffers, and 2D canvas surfaces through the GC external memory hook. This lets image and text-heavy pages participate in GC threshold calculations through their retained backing storage.
This commit is contained in:
parent
68fa684f76
commit
a414136d7c
10 changed files with 67 additions and 0 deletions
|
|
@ -5,6 +5,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/ExternalMemory.h>
|
||||
#include <LibUnicode/Segmenter.h>
|
||||
#include <LibWeb/Bindings/CharacterData.h>
|
||||
#include <LibWeb/CSS/Invalidation/LanguageInvalidator.h>
|
||||
|
|
@ -32,6 +33,11 @@ void CharacterData::initialize(JS::Realm& realm)
|
|||
Base::initialize(realm);
|
||||
}
|
||||
|
||||
size_t CharacterData::external_memory_size() const
|
||||
{
|
||||
return Node::external_memory_size() + JS::utf16_string_external_memory_size(m_data);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-characterdata-data
|
||||
void CharacterData::set_data(Utf16String const& data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ protected:
|
|||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
private:
|
||||
virtual size_t external_memory_size() const override;
|
||||
|
||||
Utf16String m_data;
|
||||
|
||||
mutable OwnPtr<Unicode::Segmenter> m_grapheme_segmenter;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <LibGC/Heap.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibJS/Runtime/ExternalMemory.h>
|
||||
#include <LibJS/Runtime/Realm.h>
|
||||
#include <LibWeb/HTML/AnimatedDecodedImageData.h>
|
||||
#include <LibWeb/Painting/DisplayListRecorder.h>
|
||||
|
|
@ -100,6 +101,16 @@ AnimatedDecodedImageData::AnimatedDecodedImageData(
|
|||
|
||||
AnimatedDecodedImageData::~AnimatedDecodedImageData() = default;
|
||||
|
||||
size_t AnimatedDecodedImageData::external_memory_size() const
|
||||
{
|
||||
size_t size = JS::vector_external_memory_size(m_durations);
|
||||
for (auto const& slot : m_buffer_slots) {
|
||||
if (slot.frame)
|
||||
size = JS::saturating_add_external_memory_size(size, slot.frame->bitmap().data_size());
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void AnimatedDecodedImageData::finalize()
|
||||
{
|
||||
Base::finalize();
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ private:
|
|||
Gfx::ColorSpace,
|
||||
Vector<u32> durations);
|
||||
|
||||
virtual size_t external_memory_size() const override;
|
||||
|
||||
BufferSlot const* find_slot(u32 frame_index) const;
|
||||
BufferSlot& evict_oldest_slot();
|
||||
void maybe_request_more_frames(size_t current_frame_index);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
*/
|
||||
|
||||
#include <LibGC/Heap.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibJS/Runtime/ExternalMemory.h>
|
||||
#include <LibJS/Runtime/Realm.h>
|
||||
#include <LibWeb/HTML/BitmapDecodedImageData.h>
|
||||
#include <LibWeb/Painting/DisplayListRecorder.h>
|
||||
|
|
@ -28,6 +30,16 @@ BitmapDecodedImageData::BitmapDecodedImageData(Vector<Frame>&& frames, size_t lo
|
|||
|
||||
BitmapDecodedImageData::~BitmapDecodedImageData() = default;
|
||||
|
||||
size_t BitmapDecodedImageData::external_memory_size() const
|
||||
{
|
||||
size_t size = JS::vector_external_memory_size(m_frames);
|
||||
for (auto const& frame : m_frames) {
|
||||
if (frame.frame)
|
||||
size = JS::saturating_add_external_memory_size(size, frame.frame->bitmap().data_size());
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
RefPtr<Gfx::DecodedImageFrame> BitmapDecodedImageData::frame(size_t frame_index, Gfx::IntSize) const
|
||||
{
|
||||
if (frame_index >= m_frames.size())
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ public:
|
|||
private:
|
||||
BitmapDecodedImageData(Vector<Frame>&&, size_t loop_count, bool animated);
|
||||
|
||||
virtual size_t external_memory_size() const override;
|
||||
|
||||
Vector<Frame> m_frames;
|
||||
size_t m_loop_count { 0 };
|
||||
bool m_animated { false };
|
||||
|
|
|
|||
|
|
@ -9,12 +9,15 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Checked.h>
|
||||
#include <AK/NumericLimits.h>
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/CompositingAndBlendingOperator.h>
|
||||
#include <LibGfx/DecodedImageFrame.h>
|
||||
#include <LibGfx/PainterSkia.h>
|
||||
#include <LibGfx/Rect.h>
|
||||
#include <LibJS/Runtime/ExternalMemory.h>
|
||||
#include <LibJS/Runtime/TypedArray.h>
|
||||
#include <LibJS/Runtime/ValueInlines.h>
|
||||
#include <LibUnicode/Segmenter.h>
|
||||
|
|
@ -74,6 +77,24 @@ void CanvasRenderingContext2D::visit_edges(Cell::Visitor& visitor)
|
|||
visitor.visit(m_element);
|
||||
}
|
||||
|
||||
size_t CanvasRenderingContext2D::external_memory_size() const
|
||||
{
|
||||
auto size = Base::external_memory_size();
|
||||
if (!m_surface)
|
||||
return size;
|
||||
|
||||
auto surface_size = m_surface->size();
|
||||
if (surface_size.is_empty())
|
||||
return size;
|
||||
|
||||
Checked<size_t> pixel_size = static_cast<size_t>(surface_size.width());
|
||||
pixel_size *= static_cast<size_t>(surface_size.height());
|
||||
pixel_size *= sizeof(u32);
|
||||
if (pixel_size.has_overflow())
|
||||
return NumericLimits<size_t>::max();
|
||||
return JS::saturating_add_external_memory_size(size, pixel_size.value());
|
||||
}
|
||||
|
||||
HTMLCanvasElement& CanvasRenderingContext2D::canvas_element()
|
||||
{
|
||||
return *m_element;
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ private:
|
|||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
virtual size_t external_memory_size() const override;
|
||||
|
||||
virtual Gfx::Painter* painter_for_canvas_state() override { return painter(); }
|
||||
virtual Gfx::Path& path_for_canvas_state() override { return path(); }
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibJS/Runtime/ExternalMemory.h>
|
||||
#include <LibWeb/Bindings/ImageBitmap.h>
|
||||
#include <LibWeb/HTML/ImageBitmap.h>
|
||||
#include <LibWeb/HTML/StructuredSerialize.h>
|
||||
|
|
@ -72,6 +73,14 @@ void ImageBitmap::visit_edges(Cell::Visitor& visitor)
|
|||
Base::visit_edges(visitor);
|
||||
}
|
||||
|
||||
size_t ImageBitmap::external_memory_size() const
|
||||
{
|
||||
auto size = Base::external_memory_size();
|
||||
if (m_bitmap)
|
||||
size = JS::saturating_add_external_memory_size(size, m_bitmap->data_size());
|
||||
return size;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#the-imagebitmap-interface:serialization-steps
|
||||
WebIDL::ExceptionOr<void> ImageBitmap::serialization_steps(HTML::TransferDataEncoder& serialized, bool, HTML::SerializationMemory&)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ private:
|
|||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
virtual size_t external_memory_size() const override;
|
||||
|
||||
WebIDL::UnsignedLong m_width = 0;
|
||||
WebIDL::UnsignedLong m_height = 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue