Changeset 37631 in webkit


Ignore:
Timestamp:
Oct 16, 2008 1:00:53 AM (16 years ago)
Author:
ap@webkit.org
Message:

Reviewed by Darin Adler.

https://bugs.webkit.org/show_bug.cgi?id=21609
Make MessagePorts protect their peers across heaps

JavaScriptCore:

  • JavaScriptCore.exp:
  • kjs/JSGlobalObject.cpp: (JSC::JSGlobalObject::markCrossHeapDependentObjects):
  • kjs/JSGlobalObject.h:
  • kjs/collector.cpp: (JSC::Heap::collect): Before GC sweep phase, a function supplied by global object is now called for all global objects in the heap, making it possible to implement cross-heap dependencies.

WebCore:

  • dom/MessagePort.cpp: (WebCore::MessagePort::MessagePort):
  • dom/MessagePort.h: (WebCore::MessagePort::setJSWrapperIsKnownToBeInaccessible): (WebCore::MessagePort::jsWrapperIsKnownToBeInaccessible): Track objects whose JS wrappers are no longer reachable in MessagePort. Unfortunately, this means that the implementation object knows about JS bindings - but it is not possible to access JS wrappers from another heap/thread.
  • bindings/js/JSDOMBinding.cpp: (WebCore::markCrossHeapDependentObjectsForDocument):
  • bindings/js/JSDOMBinding.h:
  • bindings/js/JSDOMWindowBase.cpp: (WebCore::JSDOMWindowBase::markCrossHeapDependentObjects):
  • bindings/js/JSDOMWindowBase.h: Implement cross-heap dependency tracking for entangled MessagePorts. If a wrapper object hasn't been marked normally, it is marked as inaccessible. It is then marked manually, as long as its entangled port is accessible itself.
Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r37630 r37631  
     12008-10-15  Alexey Proskuryakov  <ap@webkit.org>
     2
     3        Reviewed by Darin Adler.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=21609
     6        Make MessagePorts protect their peers across heaps
     7
     8        * JavaScriptCore.exp:
     9        * kjs/JSGlobalObject.cpp:
     10        (JSC::JSGlobalObject::markCrossHeapDependentObjects):
     11        * kjs/JSGlobalObject.h:
     12        * kjs/collector.cpp:
     13        (JSC::Heap::collect):
     14        Before GC sweep phase, a function supplied by global object is now called for all global
     15        objects in the heap, making it possible to implement cross-heap dependencies.
     16
    1172008-10-15  Alexey Proskuryakov  <ap@webkit.org>
    218
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r37622 r37631  
    148148__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEj
    149149__ZN3JSC14JSGlobalObject17startTimeoutCheckEv
     150__ZN3JSC14JSGlobalObject29markCrossHeapDependentObjectsEv
    150151__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueERNS_15PutPropertySlotE
    151152__ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
  • trunk/JavaScriptCore/kjs/JSGlobalObject.cpp

    r37433 r37631  
    400400}
    401401
     402void JSGlobalObject::markCrossHeapDependentObjects()
     403{
     404    // Overridden by subclasses.
     405}
     406
    402407JSGlobalObject* JSGlobalObject::toGlobalObject(ExecState*) const
    403408{
  • trunk/JavaScriptCore/kjs/JSGlobalObject.h

    r37323 r37631  
    159159
    160160        virtual void mark();
     161        virtual void markCrossHeapDependentObjects();
    161162
    162163        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
  • trunk/JavaScriptCore/kjs/collector.cpp

    r37622 r37631  
    970970    m_globalData->smallStrings.mark();
    971971
     972    JSGlobalObject* globalObject = m_globalData->head;
     973    do {
     974        globalObject->markCrossHeapDependentObjects();
     975        globalObject = globalObject->next();
     976    } while (globalObject != m_globalData->head);
     977
    972978    JAVASCRIPTCORE_GC_MARKED();
    973979
  • trunk/WebCore/ChangeLog

    r37628 r37631  
     12008-10-15  Alexey Proskuryakov  <ap@webkit.org>
     2
     3        Reviewed by Darin Adler.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=21609
     6        Make MessagePorts protect their peers across heaps
     7
     8        * dom/MessagePort.cpp:
     9        (WebCore::MessagePort::MessagePort):
     10        * dom/MessagePort.h:
     11        (WebCore::MessagePort::setJSWrapperIsKnownToBeInaccessible):
     12        (WebCore::MessagePort::jsWrapperIsKnownToBeInaccessible):
     13        Track objects whose JS wrappers are no longer reachable in MessagePort. Unfortunately, this
     14        means that the implementation object knows about JS bindings - but it is not possible to
     15        access JS wrappers from another heap/thread.
     16
     17        * bindings/js/JSDOMBinding.cpp:
     18        (WebCore::markCrossHeapDependentObjectsForDocument):
     19        * bindings/js/JSDOMBinding.h:
     20        * bindings/js/JSDOMWindowBase.cpp:
     21        (WebCore::JSDOMWindowBase::markCrossHeapDependentObjects):
     22        * bindings/js/JSDOMWindowBase.h:
     23        Implement cross-heap dependency tracking for entangled MessagePorts. If a wrapper object
     24        hasn't been marked normally, it is marked as inaccessible. It is then marked manually,
     25        as long as its entangled port is accessible itself.
     26
    1272008-10-15  Jon Honeycutt  <jhoneycutt@apple.com>
    228
  • trunk/WebCore/bindings/js/JSDOMBinding.cpp

    r37199 r37631  
    269269}
    270270
     271void markCrossHeapDependentObjectsForDocument(JSGlobalData& globalData, Document* document)
     272{
     273    const HashSet<MessagePort*>& messagePorts = document->messagePorts();
     274    HashSet<MessagePort*>::const_iterator portsEnd = messagePorts.end();
     275    for (HashSet<MessagePort*>::const_iterator iter = messagePorts.begin(); iter != portsEnd; ++iter) {
     276        MessagePort* port = *iter;
     277        RefPtr<MessagePort> entangledPort = port->entangledPort();
     278        if (entangledPort) {
     279            // No wrapper, or wrapper is already marked - no need to examine cross-heap dependencies.
     280            DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, port);
     281            if (!wrapper || wrapper->marked())
     282                continue;
     283
     284            // If the wrapper hasn't been marked during the mark phase of GC, then the port shouldn't protect its entangled one.
     285            // It's important not to call this when there is no wrapper. E.g., if GC is triggered after a MessageChannel is created, but before its ports are used from JS,
     286            // irreversibly telling the object that its (not yet existing) wrapper is inaccessible would be wrong. Similarly, ports posted via postMessage() may not
     287            // have wrappers until delivered.
     288            port->setJSWrapperIsInaccessible();
     289
     290            // If the port is protected by its entangled one, mark it.
     291            // This is an atomic read of a boolean value, no synchronization between threads is required (at least on platforms that guarantee cache coherency).
     292            if (!entangledPort->jsWrapperIsInaccessible())
     293                wrapper->mark();
     294        }
     295    }
     296}
     297
    271298void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocument)
    272299{
  • trunk/WebCore/bindings/js/JSDOMBinding.h

    r37190 r37631  
    7070    void markDOMNodesForDocument(Document*);
    7171    void markActiveObjectsForDocument(JSC::JSGlobalData&, Document*);
     72    void markCrossHeapDependentObjectsForDocument(JSC::JSGlobalData&, Document*);
    7273
    7374    JSC::StructureID* getCachedDOMStructure(JSC::ExecState*, const JSC::ClassInfo*);
  • trunk/WebCore/bindings/js/JSDOMWindowBase.cpp

    r37563 r37631  
    508508}
    509509
     510void JSDOMWindowBase::markCrossHeapDependentObjects()
     511{
     512    Document* document = impl()->document();
     513    if (!document)
     514        return;
     515
     516    markCrossHeapDependentObjectsForDocument(*globalData(), document);
     517}
     518
    510519bool JSDOMWindowBase::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    511520{
  • trunk/WebCore/bindings/js/JSDOMWindowBase.h

    r37257 r37631  
    6464
    6565        void disconnectFrame();
     66
     67        virtual void markCrossHeapDependentObjects();
    6668
    6769        virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);
  • trunk/WebCore/dom/MessagePort.cpp

    r37190 r37631  
    6969    , m_document(document)
    7070    , m_pendingActivity(0)
     71    , m_jsWrapperIsInaccessible(false)
    7172{
    7273    document->createdMessagePort(this);
  • trunk/WebCore/dom/MessagePort.h

    r37190 r37631  
    3434#include <wtf/MessageQueue.h>
    3535#include <wtf/PassRefPtr.h>
    36 #include <wtf/RefCounted.h>
    3736#include <wtf/RefPtr.h>
     37#include <wtf/Threading.h>
    3838#include <wtf/Vector.h>
    3939
     
    4646    class String;
    4747
    48     class MessagePort : public RefCounted<MessagePort>, public EventTarget {
     48    class MessagePort : public ThreadSafeShared<MessagePort>, public EventTarget {
    4949    public:
    5050        static PassRefPtr<MessagePort> create(Document* document) { return adoptRef(new MessagePort(document)); }
     
    8484        EventListenersMap& eventListeners() { return m_eventListeners; }
    8585
    86         using RefCounted<MessagePort>::ref;
    87         using RefCounted<MessagePort>::deref;
     86        using ThreadSafeShared<MessagePort>::ref;
     87        using ThreadSafeShared<MessagePort>::deref;
    8888
    8989        bool hasPendingActivity() { return m_pendingActivity; }
     
    9494        void setOnclose(PassRefPtr<EventListener> eventListener) { m_onCloseListener = eventListener; }
    9595        EventListener* onclose() const { return m_onCloseListener.get(); }
     96
     97        void setJSWrapperIsInaccessible() { m_jsWrapperIsInaccessible = true; }
     98        bool jsWrapperIsInaccessible() const { return m_jsWrapperIsInaccessible; }
    9699
    97100    private:
     
    120123
    121124        unsigned m_pendingActivity;
     125        bool m_jsWrapperIsInaccessible;
    122126    };
    123127
Note: See TracChangeset for help on using the changeset viewer.