Title: [289513] branches/safari-613-branch/Source/WebCore
Revision
289513
Author
alanc...@apple.com
Date
2022-02-09 17:27:00 -0800 (Wed, 09 Feb 2022)

Log Message

Cherry-pick r289383. rdar://problem/88366849

    [WebCore] JSValueInWrappedObject is not correct for concurrent GC
    https://bugs.webkit.org/show_bug.cgi?id=236277
    rdar://88366849

    Reviewed by Saam Barati.

    JSValueInWrappedObject is broken for concurrent GC's marking. It is using std::variant<> to store Weak / JSValue,
    which is not safe if concurrent GC reads it while changing that std::variant. This patch fixes several problems
    in JSValueInWrappedObject.

    1. We must not use std::variant here since concurrent access can happen. We have both JSValue and Weak, and change
       Weak after fully initialize WeakImpl's content in Weak. To ensure that, we emit storeStoreBarrier before setting
       Weak to the JSValueInWrappedObject's field.
    2. Assignment operator & copy constructor are basically wrong for this class as we need a write-barrier to set a value
       to the field. We remove them and make it explicit that we do not have write-barrier, which reveals that IDBRequest
       has a semantic bug.
    3. We also add clear() instead of assigning empty JSValueInWrappedObject. And we ensure that this new clear() works
       well with concurrent GC threads: we clear the underlying WeakImpl* pointer to nullptr. But since WeakImpl* is kept
       alive until GC clears weak-related things in its end phase, concurrent GC thread can access the old WeakImpl*.

    * Modules/indexeddb/IDBCursor.cpp:
    (WebCore::IDBCursor::setGetResult):
    * Modules/indexeddb/IDBRequest.cpp:
    (WebCore::IDBRequest::setResult):
    (WebCore::IDBRequest::setResultToStructuredClone):
    (WebCore::IDBRequest::setResultToUndefined):
    (WebCore::IDBRequest::willIterateCursor):
    (WebCore::IDBRequest::didOpenOrIterateCursor):
    * Modules/paymentrequest/PaymentMethodChangeEvent.cpp:
    * Modules/paymentrequest/PaymentResponse.cpp:
    (WebCore::PaymentResponse::setDetailsFunction):
    * Modules/webaudio/AudioBuffer.cpp:
    (WebCore::AudioBuffer::getChannelData):
    (WebCore::AudioBuffer::visitChannelWrappers):
    * bindings/js/JSValueInWrappedObject.h:
    (WebCore::JSValueInWrappedObject::JSValueInWrappedObject):
    (WebCore::JSValueInWrappedObject::operator JSC::JSValue const):
    (WebCore::JSValueInWrappedObject::visit const):
    (WebCore::JSValueInWrappedObject::setWeakly):
    (WebCore::JSValueInWrappedObject::set):
    (WebCore::JSValueInWrappedObject::clear):
    (WebCore::JSValueInWrappedObject::setWithoutBarrier):
    (WebCore::cachedPropertyValue):
    (WebCore::JSValueInWrappedObject::makeValue): Deleted.
    (WebCore::JSValueInWrappedObject::operator=): Deleted.

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@289383 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Modified Paths

Diff

Modified: branches/safari-613-branch/Source/WebCore/ChangeLog (289512 => 289513)


--- branches/safari-613-branch/Source/WebCore/ChangeLog	2022-02-10 01:26:56 UTC (rev 289512)
+++ branches/safari-613-branch/Source/WebCore/ChangeLog	2022-02-10 01:27:00 UTC (rev 289513)
@@ -1,3 +1,103 @@
+2022-02-09  Alan Coon  <alanc...@apple.com>
+
+        Cherry-pick r289383. rdar://problem/88366849
+
+    [WebCore] JSValueInWrappedObject is not correct for concurrent GC
+    https://bugs.webkit.org/show_bug.cgi?id=236277
+    rdar://88366849
+    
+    Reviewed by Saam Barati.
+    
+    JSValueInWrappedObject is broken for concurrent GC's marking. It is using std::variant<> to store Weak / JSValue,
+    which is not safe if concurrent GC reads it while changing that std::variant. This patch fixes several problems
+    in JSValueInWrappedObject.
+    
+    1. We must not use std::variant here since concurrent access can happen. We have both JSValue and Weak, and change
+       Weak after fully initialize WeakImpl's content in Weak. To ensure that, we emit storeStoreBarrier before setting
+       Weak to the JSValueInWrappedObject's field.
+    2. Assignment operator & copy constructor are basically wrong for this class as we need a write-barrier to set a value
+       to the field. We remove them and make it explicit that we do not have write-barrier, which reveals that IDBRequest
+       has a semantic bug.
+    3. We also add clear() instead of assigning empty JSValueInWrappedObject. And we ensure that this new clear() works
+       well with concurrent GC threads: we clear the underlying WeakImpl* pointer to nullptr. But since WeakImpl* is kept
+       alive until GC clears weak-related things in its end phase, concurrent GC thread can access the old WeakImpl*.
+    
+    * Modules/indexeddb/IDBCursor.cpp:
+    (WebCore::IDBCursor::setGetResult):
+    * Modules/indexeddb/IDBRequest.cpp:
+    (WebCore::IDBRequest::setResult):
+    (WebCore::IDBRequest::setResultToStructuredClone):
+    (WebCore::IDBRequest::setResultToUndefined):
+    (WebCore::IDBRequest::willIterateCursor):
+    (WebCore::IDBRequest::didOpenOrIterateCursor):
+    * Modules/paymentrequest/PaymentMethodChangeEvent.cpp:
+    * Modules/paymentrequest/PaymentResponse.cpp:
+    (WebCore::PaymentResponse::setDetailsFunction):
+    * Modules/webaudio/AudioBuffer.cpp:
+    (WebCore::AudioBuffer::getChannelData):
+    (WebCore::AudioBuffer::visitChannelWrappers):
+    * bindings/js/JSValueInWrappedObject.h:
+    (WebCore::JSValueInWrappedObject::JSValueInWrappedObject):
+    (WebCore::JSValueInWrappedObject::operator JSC::JSValue const):
+    (WebCore::JSValueInWrappedObject::visit const):
+    (WebCore::JSValueInWrappedObject::setWeakly):
+    (WebCore::JSValueInWrappedObject::set):
+    (WebCore::JSValueInWrappedObject::clear):
+    (WebCore::JSValueInWrappedObject::setWithoutBarrier):
+    (WebCore::cachedPropertyValue):
+    (WebCore::JSValueInWrappedObject::makeValue): Deleted.
+    (WebCore::JSValueInWrappedObject::operator=): Deleted.
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@289383 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2022-02-07  Yusuke Suzuki  <ysuz...@apple.com>
+
+            [WebCore] JSValueInWrappedObject is not correct for concurrent GC
+            https://bugs.webkit.org/show_bug.cgi?id=236277
+            rdar://88366849
+
+            Reviewed by Saam Barati.
+
+            JSValueInWrappedObject is broken for concurrent GC's marking. It is using std::variant<> to store Weak / JSValue,
+            which is not safe if concurrent GC reads it while changing that std::variant. This patch fixes several problems
+            in JSValueInWrappedObject.
+
+            1. We must not use std::variant here since concurrent access can happen. We have both JSValue and Weak, and change
+               Weak after fully initialize WeakImpl's content in Weak. To ensure that, we emit storeStoreBarrier before setting
+               Weak to the JSValueInWrappedObject's field.
+            2. Assignment operator & copy constructor are basically wrong for this class as we need a write-barrier to set a value
+               to the field. We remove them and make it explicit that we do not have write-barrier, which reveals that IDBRequest
+               has a semantic bug.
+            3. We also add clear() instead of assigning empty JSValueInWrappedObject. And we ensure that this new clear() works
+               well with concurrent GC threads: we clear the underlying WeakImpl* pointer to nullptr. But since WeakImpl* is kept
+               alive until GC clears weak-related things in its end phase, concurrent GC thread can access the old WeakImpl*.
+
+            * Modules/indexeddb/IDBCursor.cpp:
+            (WebCore::IDBCursor::setGetResult):
+            * Modules/indexeddb/IDBRequest.cpp:
+            (WebCore::IDBRequest::setResult):
+            (WebCore::IDBRequest::setResultToStructuredClone):
+            (WebCore::IDBRequest::setResultToUndefined):
+            (WebCore::IDBRequest::willIterateCursor):
+            (WebCore::IDBRequest::didOpenOrIterateCursor):
+            * Modules/paymentrequest/PaymentMethodChangeEvent.cpp:
+            * Modules/paymentrequest/PaymentResponse.cpp:
+            (WebCore::PaymentResponse::setDetailsFunction):
+            * Modules/webaudio/AudioBuffer.cpp:
+            (WebCore::AudioBuffer::getChannelData):
+            (WebCore::AudioBuffer::visitChannelWrappers):
+            * bindings/js/JSValueInWrappedObject.h:
+            (WebCore::JSValueInWrappedObject::JSValueInWrappedObject):
+            (WebCore::JSValueInWrappedObject::operator JSC::JSValue const):
+            (WebCore::JSValueInWrappedObject::visit const):
+            (WebCore::JSValueInWrappedObject::setWeakly):
+            (WebCore::JSValueInWrappedObject::set):
+            (WebCore::JSValueInWrappedObject::clear):
+            (WebCore::JSValueInWrappedObject::setWithoutBarrier):
+            (WebCore::cachedPropertyValue):
+            (WebCore::JSValueInWrappedObject::makeValue): Deleted.
+            (WebCore::JSValueInWrappedObject::operator=): Deleted.
+
 2022-02-08  Russell Epstein  <repst...@apple.com>
 
         Cherry-pick r288435. rdar://problem/83668578

Modified: branches/safari-613-branch/Source/WebCore/Modules/indexeddb/IDBCursor.cpp (289512 => 289513)


--- branches/safari-613-branch/Source/WebCore/Modules/indexeddb/IDBCursor.cpp	2022-02-10 01:26:56 UTC (rev 289512)
+++ branches/safari-613-branch/Source/WebCore/Modules/indexeddb/IDBCursor.cpp	2022-02-10 01:27:00 UTC (rev 289513)
@@ -336,9 +336,7 @@
     VM& vm = context->vm();
     JSLockHolder lock(vm);
 
-    m_keyWrapper = { };
-    m_primaryKeyWrapper = { };
-    m_valueWrapper = { };
+    clearWrappers();
 
     if (!getResult.isDefined()) {
         m_keyData = { };

Modified: branches/safari-613-branch/Source/WebCore/Modules/indexeddb/IDBRequest.cpp (289512 => 289513)


--- branches/safari-613-branch/Source/WebCore/Modules/indexeddb/IDBRequest.cpp	2022-02-10 01:26:56 UTC (rev 289512)
+++ branches/safari-613-branch/Source/WebCore/Modules/indexeddb/IDBRequest.cpp	2022-02-10 01:27:00 UTC (rev 289513)
@@ -369,7 +369,7 @@
     VM& vm = context->vm();
     JSLockHolder lock(vm);
     m_result = keyData;
-    m_resultWrapper = { };
+    m_resultWrapper.clear();
 }
 
 void IDBRequest::setResult(const Vector<IDBKeyData>& keyDatas)
@@ -383,7 +383,7 @@
     VM& vm = context->vm();
     JSLockHolder lock(vm);
     m_result = keyDatas;
-    m_resultWrapper = { };
+    m_resultWrapper.clear();
 }
 
 void IDBRequest::setResult(const IDBGetAllResult& result)
@@ -397,7 +397,7 @@
     VM& vm = context->vm();
     JSLockHolder lock(vm);
     m_result = result;
-    m_resultWrapper = { };
+    m_resultWrapper.clear();
 }
 
 void IDBRequest::setResult(uint64_t number)
@@ -411,7 +411,7 @@
     VM& vm = context->vm();
     JSLockHolder lock(vm);
     m_result = number;
-    m_resultWrapper = { };
+    m_resultWrapper.clear();
 }
 
 void IDBRequest::setResultToStructuredClone(const IDBGetResult& result)
@@ -427,7 +427,7 @@
     VM& vm = context->vm();
     JSLockHolder lock(vm);
     m_result = result;
-    m_resultWrapper = { };
+    m_resultWrapper.clear();
 }
 
 void IDBRequest::setResultToUndefined()
@@ -441,7 +441,7 @@
     VM& vm = context->vm();
     JSLockHolder lock(vm);
     m_result = NullResultType::Undefined;
-    m_resultWrapper = { };
+    m_resultWrapper.clear();
 }
 
 IDBCursor* IDBRequest::resultCursor()
@@ -474,9 +474,14 @@
     VM& vm = context->vm();
     JSLockHolder lock(vm);
 
+    // FIXME: This code is wrong: let's consider that these fields' access are reordered in the concurrent GC thread.
+    // And we just scanned cleared m_resultWrapper and then, we missed scanning m_cursorWrapper with a new value.
+    // Then we could make both collected. Whenever changing JSValueInWrappedObject fields, we should emit a write barrier
+    // if we would like to keep them alive.
+    // https://bugs.webkit.org/show_bug.cgi?id=236278
     if (m_resultWrapper)
-        m_cursorWrapper = m_resultWrapper;
-    m_resultWrapper = { };
+        m_cursorWrapper.setWithoutBarrier(m_resultWrapper);
+    m_resultWrapper.clear();
     m_readyState = ReadyState::Pending;
     m_domError = nullptr;
     m_idbError = IDBError { };
@@ -495,11 +500,16 @@
     JSLockHolder lock(vm);
 
     m_result = NullResultType::Empty;
-    m_resultWrapper = { };
+    m_resultWrapper.clear();
 
+    // FIXME: This code is wrong: let's consider that these fields' access are reordered in the concurrent GC thread.
+    // And we just scanned cleared m_resultWrapper and then, we missed scanning m_cursorWrapper with a new value.
+    // Then we could make both collected. Whenever changing JSValueInWrappedObject fields, we should emit a write barrier
+    // if we would like to keep them alive.
+    // https://bugs.webkit.org/show_bug.cgi?id=236278
     if (resultData.type() == IDBResultType::IterateCursorSuccess || resultData.type() == IDBResultType::OpenCursorSuccess) {
         if (m_pendingCursor->setGetResult(*this, resultData.getResult(), m_currentTransactionOperationID) && m_cursorWrapper)
-            m_resultWrapper = m_cursorWrapper;
+            m_resultWrapper.setWithoutBarrier(m_cursorWrapper);
         if (resultData.getResult().isDefined())
             m_result = m_pendingCursor;
     }
@@ -552,7 +562,7 @@
     JSLockHolder lock(vm);
 
     m_result = RefPtr<IDBDatabase> { WTFMove(database) };
-    m_resultWrapper = { };
+    m_resultWrapper.clear();
 }
 
 void IDBRequest::clearWrappers()

Modified: branches/safari-613-branch/Source/WebCore/Modules/paymentrequest/PaymentMethodChangeEvent.cpp (289512 => 289513)


--- branches/safari-613-branch/Source/WebCore/Modules/paymentrequest/PaymentMethodChangeEvent.cpp	2022-02-10 01:26:56 UTC (rev 289512)
+++ branches/safari-613-branch/Source/WebCore/Modules/paymentrequest/PaymentMethodChangeEvent.cpp	2022-02-10 01:27:00 UTC (rev 289513)
@@ -42,7 +42,7 @@
 PaymentMethodChangeEvent::PaymentMethodChangeEvent(const AtomString& type, Init&& eventInit)
     : PaymentRequestUpdateEvent { type, eventInit }
     , m_methodName { WTFMove(eventInit.methodName) }
-    , m_methodDetails { JSValueInWrappedObject { eventInit.methodDetails.get() } }
+    , m_methodDetails { std::in_place_type_t<JSValueInWrappedObject>(), eventInit.methodDetails.get() }
 {
 }
 
@@ -49,7 +49,7 @@
 PaymentMethodChangeEvent::PaymentMethodChangeEvent(const AtomString& type, const String& methodName, MethodDetailsFunction&& methodDetailsFunction)
     : PaymentRequestUpdateEvent { type }
     , m_methodName { methodName }
-    , m_methodDetails { WTFMove(methodDetailsFunction) }
+    , m_methodDetails { std::in_place_type_t<MethodDetailsFunction>(), WTFMove(methodDetailsFunction) }
 {
 }
 

Modified: branches/safari-613-branch/Source/WebCore/Modules/paymentrequest/PaymentResponse.cpp (289512 => 289513)


--- branches/safari-613-branch/Source/WebCore/Modules/paymentrequest/PaymentResponse.cpp	2022-02-10 01:26:56 UTC (rev 289512)
+++ branches/safari-613-branch/Source/WebCore/Modules/paymentrequest/PaymentResponse.cpp	2022-02-10 01:27:00 UTC (rev 289513)
@@ -60,7 +60,7 @@
 void PaymentResponse::setDetailsFunction(DetailsFunction&& detailsFunction)
 {
     m_detailsFunction = WTFMove(detailsFunction);
-    m_cachedDetails = { };
+    m_cachedDetails.clear();
 }
 
 void PaymentResponse::complete(std::optional<PaymentComplete>&& result, DOMPromiseDeferred<void>&& promise)

Modified: branches/safari-613-branch/Source/WebCore/Modules/webaudio/AudioBuffer.cpp (289512 => 289513)


--- branches/safari-613-branch/Source/WebCore/Modules/webaudio/AudioBuffer.cpp	2022-02-10 01:26:56 UTC (rev 289512)
+++ branches/safari-613-branch/Source/WebCore/Modules/webaudio/AudioBuffer.cpp	2022-02-10 01:27:00 UTC (rev 289513)
@@ -159,7 +159,7 @@
 
     if (globalObject.worldIsNormal()) {
         if (!m_channelWrappers[channelIndex])
-            m_channelWrappers[channelIndex] = { constructJSArray() };
+            m_channelWrappers[channelIndex].setWeakly(constructJSArray());
         return static_cast<JSC::JSValue>(m_channelWrappers[channelIndex]);
     }
     return constructJSArray();
@@ -168,6 +168,8 @@
 template<typename Visitor>
 void AudioBuffer::visitChannelWrappers(Visitor& visitor)
 {
+    // FIXME: AudioBuffer::releaseMemory can clear this buffer while visiting it from concurrent GC thread.
+    // https://bugs.webkit.org/show_bug.cgi?id=236279
     for (auto& channelWrapper : m_channelWrappers)
         channelWrapper.visit(visitor);
 }

Modified: branches/safari-613-branch/Source/WebCore/bindings/js/JSValueInWrappedObject.h (289512 => 289513)


--- branches/safari-613-branch/Source/WebCore/bindings/js/JSValueInWrappedObject.h	2022-02-10 01:26:56 UTC (rev 289512)
+++ branches/safari-613-branch/Source/WebCore/bindings/js/JSValueInWrappedObject.h	2022-02-10 01:27:00 UTC (rev 289513)
@@ -34,57 +34,46 @@
 namespace WebCore {
 
 class JSValueInWrappedObject {
+    // It must not be copyable. Changing this will break concurrent GC.
+    WTF_MAKE_NONCOPYABLE(JSValueInWrappedObject);
 public:
     JSValueInWrappedObject(JSC::JSValue = { });
-    JSValueInWrappedObject(const JSValueInWrappedObject&);
+
+    // FIXME: Remove them once AudioBuffer's m_channelWrappers bug is fixed.
+    // https://bugs.webkit.org/show_bug.cgi?id=236279
+    JSValueInWrappedObject(JSValueInWrappedObject&&) = default;
+    JSValueInWrappedObject& operator=(JSValueInWrappedObject&&) = default;
+
     operator JSC::JSValue() const;
     explicit operator bool() const;
-    JSValueInWrappedObject& operator=(const JSValueInWrappedObject& other);
     template<typename Visitor> void visit(Visitor&) const;
     void clear();
 
+    void set(JSC::VM&, const JSC::JSCell* owner, JSC::JSValue);
+    void setWeakly(JSC::JSValue);
+
+    // FIXME: Remove this once IDBRequest semantic bug is fixed.
+    // https://bugs.webkit.org/show_bug.cgi?id=236278
+    void setWithoutBarrier(JSValueInWrappedObject&);
+
 private:
-    // Use a weak pointer here so that if this code or client code has a visiting mistake,
-    // we get null rather than a dangling pointer to a deleted object.
-    using Weak = JSC::Weak<JSC::JSCell>;
-    // FIXME: Would storing a separate JSValue alongside a Weak be better than using a Variant?
-    using Value = std::variant<JSC::JSValue, Weak>;
-    static Value makeValue(JSC::JSValue);
-    Value m_value;
+    // Keep in mind that all of these fields are accessed concurrently without lock from concurrent GC thread.
+    JSC::JSValue m_nonCell { };
+    JSC::Weak<JSC::JSCell> m_cell { };
 };
 
 JSC::JSValue cachedPropertyValue(JSC::JSGlobalObject&, const JSDOMObject& owner, JSValueInWrappedObject& cacheSlot, const Function<JSC::JSValue()>&);
 
-inline auto JSValueInWrappedObject::makeValue(JSC::JSValue value) -> Value
-{
-    if (!value.isCell())
-        return value;
-    // FIXME: This is not quite right. It is possible that this value is being
-    // stored in a wrapped object that does not yet have a wrapper. If garbage
-    // collection occurs before the wrapped object gets a wrapper, it's possible
-    // the value object could be collected, and this will become null. A future
-    // version of this class should prevent the value from being collected in
-    // that case. Unclear if this can actually happen in practice.
-    return Weak { value.asCell() };
-}
-
 inline JSValueInWrappedObject::JSValueInWrappedObject(JSC::JSValue value)
-    : m_value(makeValue(JSC::JSValue(value)))
 {
+    setWeakly(value);
 }
 
-inline JSValueInWrappedObject::JSValueInWrappedObject(const JSValueInWrappedObject& value)
-    : m_value(makeValue(value))
-{
-}
-
 inline JSValueInWrappedObject::operator JSC::JSValue() const
 {
-    return WTF::switchOn(m_value, [] (JSC::JSValue value) {
-        return value;
-    }, [] (const Weak& value) -> JSC::JSValue {
-        return value.get();
-    });
+    if (m_nonCell)
+        return m_nonCell;
+    return m_cell.get();
 }
 
 inline JSValueInWrappedObject::operator bool() const
@@ -92,39 +81,54 @@
     return JSC::JSValue { *this }.operator bool();
 }
 
-inline JSValueInWrappedObject& JSValueInWrappedObject::operator=(const JSValueInWrappedObject& other)
-{
-    m_value = makeValue(JSC::JSValue(other));
-    return *this;
-}
-
 template<typename Visitor>
 inline void JSValueInWrappedObject::visit(Visitor& visitor) const
 {
-    return WTF::switchOn(m_value, [] (JSC::JSValue) {
-        // Nothing to visit.
-    }, [&visitor] (const Weak& value) {
-        visitor.append(value);
-    });
+    visitor.append(m_cell);
 }
 
 template void JSValueInWrappedObject::visit(JSC::AbstractSlotVisitor&) const;
 template void JSValueInWrappedObject::visit(JSC::SlotVisitor&) const;
 
+inline void JSValueInWrappedObject::setWeakly(JSC::JSValue value)
+{
+    if (!value.isCell()) {
+        m_nonCell = value;
+        m_cell.clear();
+        return;
+    }
+    m_nonCell = { };
+    JSC::Weak weak { value.asCell() };
+    WTF::storeStoreFence();
+    m_cell = WTFMove(weak);
+}
+
+inline void JSValueInWrappedObject::set(JSC::VM& vm, const JSC::JSCell* owner, JSC::JSValue value)
+{
+    setWeakly(value);
+    vm.writeBarrier(owner, value);
+}
+
 inline void JSValueInWrappedObject::clear()
 {
-    WTF::switchOn(m_value, [] (Weak& value) {
-        value.clear();
-    }, [] (auto&) { });
+    m_nonCell = { };
+    m_cell.clear();
 }
 
+inline void JSValueInWrappedObject::setWithoutBarrier(JSValueInWrappedObject& other)
+{
+    JSC::Weak weak { other.m_cell.get() };
+    WTF::storeStoreFence(); // Ensure Weak is fully initialized for concurrent access.
+    m_nonCell = other.m_nonCell;
+    m_cell = WTFMove(weak);
+}
+
 inline JSC::JSValue cachedPropertyValue(JSC::JSGlobalObject& lexicalGlobalObject, const JSDOMObject& owner, JSValueInWrappedObject& cachedValue, const Function<JSC::JSValue()>& function)
 {
     if (cachedValue && isWorldCompatible(lexicalGlobalObject, cachedValue))
         return cachedValue;
     auto value = function();
-    cachedValue = cloneAcrossWorlds(lexicalGlobalObject, owner, value);
-    lexicalGlobalObject.vm().writeBarrier(&owner, value);
+    cachedValue.set(lexicalGlobalObject.vm(), &owner, cloneAcrossWorlds(lexicalGlobalObject, owner, value));
     ASSERT(isWorldCompatible(lexicalGlobalObject, cachedValue));
     return cachedValue;
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to