JSEventListener::replaceJSFunctionForAttributeListener() should not replace m_wrapper unconditionally
https://bugs.webkit.org/show_bug.cgi?id=235658

Patch by Alexey Shvayka <ashvayka@apple.com> on 2022-01-26
Reviewed by Yusuke Suzuki.

This is a follow-up to r287293, which aligns JSEventListener::replaceJSFunctionForAttributeListener()
with JSEventListener::ensureJSFunction() in terms of handling uninitilized lazy event listeners.

Without this change, the microbenchmark in <https://webkit.org/b/234441> consumes 16 GB of memory in
30 seconds and crashes, which even isn't a regression: the same issue was observed before r287293.

According to new microbenchmark samples, I'm hopeful that with this patch, Speedometer2/Inferno-TodoMVC
will progress as promised in r287293.

No new tests, no behavior change.

* bindings/js/JSEventListener.cpp:
(WebCore::JSEventListener::replaceJSFunctionForAttributeListener):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@288648 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index c408d8b..ae32a71 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,24 @@
+2022-01-26  Alexey Shvayka  <ashvayka@apple.com>
+
+        JSEventListener::replaceJSFunctionForAttributeListener() should not replace m_wrapper unconditionally
+        https://bugs.webkit.org/show_bug.cgi?id=235658
+
+        Reviewed by Yusuke Suzuki.
+
+        This is a follow-up to r287293, which aligns JSEventListener::replaceJSFunctionForAttributeListener()
+        with JSEventListener::ensureJSFunction() in terms of handling uninitilized lazy event listeners.
+
+        Without this change, the microbenchmark in <https://webkit.org/b/234441> consumes 16 GB of memory in
+        30 seconds and crashes, which even isn't a regression: the same issue was observed before r287293.
+
+        According to new microbenchmark samples, I'm hopeful that with this patch, Speedometer2/Inferno-TodoMVC
+        will progress as promised in r287293.
+
+        No new tests, no behavior change.
+
+        * bindings/js/JSEventListener.cpp:
+        (WebCore::JSEventListener::replaceJSFunctionForAttributeListener):
+
 2022-01-26  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         REGRESSION(r288623) MSVC reports "InspectorDOMAgent.cpp(558,40): error C2059: syntax error: ':'"
diff --git a/Source/WebCore/bindings/js/JSEventListener.cpp b/Source/WebCore/bindings/js/JSEventListener.cpp
index 059dfea..0e392ca 100644
--- a/Source/WebCore/bindings/js/JSEventListener.cpp
+++ b/Source/WebCore/bindings/js/JSEventListener.cpp
@@ -86,8 +86,12 @@
     ASSERT(wrapper);
 
     m_jsFunction = Weak { function };
-    m_wrapper = wrapper;
-    m_isInitialized = true;
+    if (UNLIKELY(!m_isInitialized)) {
+        m_wrapper = Weak { wrapper };
+        auto& vm = m_isolatedWorld->vm();
+        vm.writeBarrier(wrapper, function);
+        m_isInitialized = true;
+    }
 }
 
 JSValue eventHandlerAttribute(EventTarget& eventTarget, const AtomString& eventType, DOMWrapperWorld& isolatedWorld)