LibWeb: Cache UniversalGlobalScopeMixin pointer on ESO

Avoid expensive cross-hierarchy dynamic_cast from JS::Object to
UniversalGlobalScopeMixin on every microtask checkpoint.

Since UniversalGlobalScopeMixin is not in the JS::Object
inheritance chain, as<UniversalGlobalScopeMixin>(JS::Object&)
falls through to dynamic_cast, which is very costly. Profiling
showed this taking ~14% of total CPU time.

Add EnvironmentSettingsObject::universal_global_scope() backed
by a pointer cached eagerly during initialization.
This commit is contained in:
Andreas Kling
2026-03-23 20:30:19 +01:00
committed by Andreas Kling
parent e49ab8a1f2
commit b5babda288
Notes: github-actions[bot] 2026-03-24 07:29:35 +00:00
4 changed files with 14 additions and 3 deletions

View File

@@ -22,6 +22,8 @@
namespace Web::HTML {
class UniversalGlobalScopeMixin;
// https://html.spec.whatwg.org/multipage/webappapis.html#environment
struct WEB_API Environment : public JS::Cell {
GC_CELL(Environment, JS::Cell);
@@ -120,6 +122,8 @@ public:
JS::Realm& realm();
JS::Object& global_object();
JS::Object const& global_object() const { return const_cast<EnvironmentSettingsObject*>(this)->global_object(); }
UniversalGlobalScopeMixin& universal_global_scope();
UniversalGlobalScopeMixin const& universal_global_scope() const { return const_cast<EnvironmentSettingsObject*>(this)->universal_global_scope(); }
EventLoop& responsible_event_loop();
// https://fetch.spec.whatwg.org/#concept-fetch-group
@@ -166,6 +170,7 @@ protected:
private:
NonnullOwnPtr<JS::ExecutionContext> m_realm_execution_context;
GC::Ptr<ModuleMap> m_module_map;
UniversalGlobalScopeMixin* m_universal_global_scope { nullptr };
GC::Ptr<EventLoop> m_responsible_event_loop;