Changeset 34271 in webkit


Ignore:
Timestamp:
May 30, 2008 10:37:03 PM (16 years ago)
Author:
mjs@apple.com
Message:

2008-05-30 Maciej Stachowiak <mjs@apple.com>

Reviewed by Oliver (earlier version reviewed by Alexey).


("This Time for Sure" Edition)

I'm pretty sure this fixes it but I have not been able to
reproduce and am unsure if my theory of the bug is right.

I belive the bug was because JSDOMWindowBase accessed
JSDOMWindowShell in its destructor to remove itself from a
hashtable, but GC destructor order is not guaranteed, so the
hashtable may have been freed already. This patch changes things
so that a non-GC object (the KJSProxy) does the tracking of live
window objects for a frame. JSDOMWindowBase can null check the frame
pointer to verify if it is still good.


In addition, we must create a similar setup between DOMWindow and
Frame; since the DOMWindow of a given frame can now change over
time, we must ensure that the Frame disconnects every live
DOMWindow when destroyed, not just the last.

  • bindings/js/JSDOMWindowBase.cpp: (WebCore::JSDOMWindowBase::~JSDOMWindowBase):
  • bindings/js/JSDOMWindowShell.cpp: (WebCore::JSDOMWindowShell::JSDOMWindowShell):
  • bindings/js/JSDOMWindowShell.h: (WebCore::JSDOMWindowShell::setWindow):
  • bindings/js/kjs_proxy.cpp: (WebCore::KJSProxy::clear): (WebCore::KJSProxy::initScript): (WebCore::KJSProxy::updateDocument):
  • bindings/js/kjs_proxy.h: (WebCore::KJSProxy::clearFormerWindow):
  • page/DOMWindow.cpp: (WebCore::DOMWindow::~DOMWindow):
  • page/Frame.cpp: (WebCore::Frame::~Frame): (WebCore::Frame::setDocument): (WebCore::Frame::clearDOMWindow): (WebCore::Frame::clearFormerDOMWindow):
  • page/Frame.h:
  • page/FramePrivate.h:
Location:
trunk/WebCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r34267 r34271  
     12008-05-30  Maciej Stachowiak  <mjs@apple.com>
     2
     3        Reviewed by Oliver (earlier version reviewed by Alexey).
     4
     5        - speculative fix for "REGRESSION(r34143?): Frequent crash while browsing"
     6        https://bugs.webkit.org/show_bug.cgi?id=19285
     7       
     8        ("This Time for Sure" Edition)
     9
     10        I'm pretty sure this fixes it but I have not been able to
     11        reproduce and am unsure if my theory of the bug is right.
     12
     13        I belive the bug was because JSDOMWindowBase accessed
     14        JSDOMWindowShell in its destructor to remove itself from a
     15        hashtable, but GC destructor order is not guaranteed, so the
     16        hashtable may have been freed already. This patch changes things
     17        so that a non-GC object (the KJSProxy) does the tracking of live
     18        window objects for a frame. JSDOMWindowBase can null check the frame
     19        pointer to verify if it is still good.
     20       
     21        In addition, we must create a similar setup between DOMWindow and
     22        Frame; since the DOMWindow of a given frame can now change over
     23        time, we must ensure that the Frame disconnects every live
     24        DOMWindow when destroyed, not just the last.
     25
     26        * bindings/js/JSDOMWindowBase.cpp:
     27        (WebCore::JSDOMWindowBase::~JSDOMWindowBase):
     28        * bindings/js/JSDOMWindowShell.cpp:
     29        (WebCore::JSDOMWindowShell::JSDOMWindowShell):
     30        * bindings/js/JSDOMWindowShell.h:
     31        (WebCore::JSDOMWindowShell::setWindow):
     32        * bindings/js/kjs_proxy.cpp:
     33        (WebCore::KJSProxy::clear):
     34        (WebCore::KJSProxy::initScript):
     35        (WebCore::KJSProxy::updateDocument):
     36        * bindings/js/kjs_proxy.h:
     37        (WebCore::KJSProxy::clearFormerWindow):
     38        * page/DOMWindow.cpp:
     39        (WebCore::DOMWindow::~DOMWindow):
     40        * page/Frame.cpp:
     41        (WebCore::Frame::~Frame):
     42        (WebCore::Frame::setDocument):
     43        (WebCore::Frame::clearDOMWindow):
     44        (WebCore::Frame::clearFormerDOMWindow):
     45        * page/Frame.h:
     46        * page/FramePrivate.h:
     47
    1482008-05-30  Dan Bernstein  <mitz@apple.com>
    249
  • trunk/WebCore/bindings/js/JSDOMWindowBase.cpp

    r34261 r34271  
    203203JSDOMWindowBase::~JSDOMWindowBase()
    204204{
    205     d->m_shell->clearFormerWindow(asJSDOMWindow(this));
     205    if (m_impl->frame())
     206        m_impl->frame()->scriptProxy()->clearFormerWindow(asJSDOMWindow(this));
    206207
    207208    clearAllTimeouts();
  • trunk/WebCore/bindings/js/JSDOMWindowShell.cpp

    r34261 r34271  
    4545    : Base(jsNull())
    4646    , m_window(0)
    47     , m_liveFormerWindows(new HashSet<JSDOMWindow*>)
    4847{
    4948    m_window = new JSDOMWindow(domWindow, this);
     
    146145
    147146
    148 void JSDOMWindowShell::updateDocument()
    149 {
    150     m_window->updateDocument();
    151     HashSet<JSDOMWindow*>::iterator end = m_liveFormerWindows->end();
    152     for (HashSet<JSDOMWindow*>::iterator it = m_liveFormerWindows->begin(); it != end; ++it)
    153         (*it)->updateDocument();
    154 }
    155 
    156147// ----
    157148// Conversion methods
  • trunk/WebCore/bindings/js/JSDOMWindowShell.h

    r34261 r34271  
    4848        {
    4949            ASSERT_ARG(window, window);
    50             m_liveFormerWindows->add(m_window);
    5150            m_window = window;
    5251            setPrototype(window->prototype());
     
    7776        void disconnectFrame();
    7877        void clear();
    79         void updateDocument();
    80 
    81         void clearFormerWindow(JSDOMWindow* window) { m_liveFormerWindows->remove(window); }
    8278
    8379    private:
    8480        JSDOMWindow* m_window;
    85         HashSet<JSDOMWindow*>* m_liveFormerWindows;
    8681    };
    8782
  • trunk/WebCore/bindings/js/kjs_proxy.cpp

    r34261 r34271  
    113113    JSLock lock;
    114114    m_windowShell->window()->clear();
     115    m_liveFormerWindows.add(m_windowShell->window());
    115116    m_windowShell->setWindow(new JSDOMWindow(m_frame->domWindow(), m_windowShell));
    116117    if (Page* page = m_frame->page()) {
     
    156157
    157158    m_windowShell = new JSDOMWindowShell(m_frame->domWindow());
    158     m_windowShell->updateDocument();
     159    updateDocument();
    159160
    160161    if (Page* page = m_frame->page()) {
     
    211212}
    212213
     214void KJSProxy::updateDocument()
     215{
     216    JSLock lock;
     217    if (m_windowShell)
     218        m_windowShell->window()->updateDocument();
     219    HashSet<JSDOMWindow*>::iterator end = m_liveFormerWindows.end();
     220    for (HashSet<JSDOMWindow*>::iterator it = m_liveFormerWindows.begin(); it != end; ++it)
     221        (*it)->updateDocument();
     222}
     223
     224
    213225} // namespace WebCore
  • trunk/WebCore/bindings/js/kjs_proxy.h

    r34261 r34271  
    7878    bool isPaused() const { return m_paused; }
    7979
     80    void clearFormerWindow(JSDOMWindow* window) { m_liveFormerWindows.remove(window); }
     81    void updateDocument();
     82
    8083private:
    8184    void initScriptIfNeeded()
     
    8790
    8891    KJS::ProtectedPtr<JSDOMWindowShell> m_windowShell;
     92    HashSet<JSDOMWindow*> m_liveFormerWindows;
    8993    Frame* m_frame;
    9094    int m_handlerLineno;
  • trunk/WebCore/page/DOMWindow.cpp

    r34179 r34271  
    147147DOMWindow::~DOMWindow()
    148148{
     149    if (m_frame)
     150        m_frame->clearFormerDOMWindow(this);
    149151}
    150152
  • trunk/WebCore/page/Frame.cpp

    r34261 r34271  
    182182    if (d->m_domWindow)
    183183        d->m_domWindow->disconnectFrame();
     184
     185    HashSet<DOMWindow*>::iterator end = d->m_liveFormerWindows.end();
     186    for (HashSet<DOMWindow*>::iterator it = d->m_liveFormerWindows.begin(); it != end; ++it)
     187        (*it)->disconnectFrame();
    184188           
    185189    if (d->m_view) {
     
    261265
    262266    // Update the cached 'document' property, which is now stale.
    263     if (d->m_doc && d->m_jscript.haveWindowShell()) {
    264         JSLock lock;
    265         d->m_jscript.windowShell()->updateDocument();
    266     }
     267    d->m_jscript.updateDocument();
    267268}
    268269
     
    11291130void Frame::clearDOMWindow()
    11301131{
    1131     if (d->m_domWindow)
     1132    if (d->m_domWindow) {
     1133        d->m_liveFormerWindows.add(d->m_domWindow.get());
    11321134        d->m_domWindow->clear();
     1135    }
    11331136    d->m_domWindow = 0;
    11341137}
     
    17091712
    17101713    return d->m_domWindow.get();
     1714}
     1715
     1716void Frame::clearFormerDOMWindow(DOMWindow* window)
     1717{
     1718    d->m_liveFormerWindows.remove(window);   
    17111719}
    17121720
  • trunk/WebCore/page/Frame.h

    r32700 r34271  
    9797
    9898    DOMWindow* domWindow() const;
     99    void clearFormerDOMWindow(DOMWindow*);
    99100    Editor* editor() const;
    100101    EventHandler* eventHandler() const;
  • trunk/WebCore/page/FramePrivate.h

    r32422 r34271  
    7575        FrameLoader m_loader;
    7676        RefPtr<DOMWindow> m_domWindow;
     77        HashSet<DOMWindow*> m_liveFormerWindows;
    7778
    7879        HTMLFrameOwnerElement* m_ownerElement;
Note: See TracChangeset for help on using the changeset viewer.