Changeset 55816 in webkit


Ignore:
Timestamp:
Mar 10, 2010 4:08:18 PM (14 years ago)
Author:
dimich@chromium.org
Message:

Make Document::postTask to use a single queue of tasks, to fire them in order
https://bugs.webkit.org/show_bug.cgi?id=35943

Reviewed by Darin Adler.

JavaScriptCore:

The patch uses CFRunLoopTimer to schedule execution of tasks instead of performSelectorOnMainThread which apparently can starve other event sources.
The timer is used when the schedule request is coming on the main thread itself. This happens when the task is posted on the main thread or
when too many tasks are posted and the queue does 'stop and re-schedule' to make sure run loop has a chance to execute other events.

  • wtf/mac/MainThreadMac.mm:

(WTF::timerFired):
(WTF::postTimer):
(WTF::scheduleDispatchFunctionsOnMainThread): Use timer posted to the current RunLoop if scheduling the task execution while on the main thread.

WebCore:

Test: existing worker-cloneport.html which was broken by initial patch in http://trac.webkit.org/changeset/55593.
Additional test which indirectly verifies the order of execution will come as part of https://bugs.webkit.org/show_bug.cgi?id=34726

  • dom/Document.cpp:

(WebCore::Document::postTask): Always use the same task queue, independent of what thread is posting the task.

LayoutTests:

Updated the test since the order of events coming from independent task sources has changed.
This is a behavior change, but is consistent with the spec (which specifically says these events may be fired
in any order) and the last version of FF (3.5.8) which was completing the test successfully.

  • http/tests/appcache/top-frame-2-expected.txt:
  • http/tests/appcache/top-frame-2.html:
Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r55815 r55816  
     12010-03-10  Dmitry Titov  <dimich@chromium.org>
     2
     3        Reviewed by Darin Adler.
     4
     5        Make Document::postTask to use a single queue of tasks, to fire them in order
     6        https://bugs.webkit.org/show_bug.cgi?id=35943
     7
     8        The patch uses CFRunLoopTimer to schedule execution of tasks instead of performSelectorOnMainThread which apparently can starve other event sources.
     9        The timer is used when the schedule request is coming on the main thread itself. This happens when the task is posted on the main thread or
     10        when too many tasks are posted and the queue does 'stop and re-schedule' to make sure run loop has a chance to execute other events.
     11
     12        * wtf/mac/MainThreadMac.mm:
     13        (WTF::timerFired):
     14        (WTF::postTimer):
     15        (WTF::scheduleDispatchFunctionsOnMainThread): Use timer posted to the current RunLoop if scheduling the task execution while on the main thread.
     16
    1172010-03-10  Geoffrey Garen  <ggaren@apple.com>
    218
  • trunk/JavaScriptCore/wtf/mac/MainThreadMac.mm

    r52046 r55816  
    3030#import "MainThread.h"
    3131
     32#import <CoreFoundation/CoreFoundation.h>
    3233#import <Foundation/NSThread.h>
    3334#import <wtf/Assertions.h>
     35#import <wtf/Threading.h>
    3436
    3537@interface WTFMainThreadCaller : NSObject {
     
    6466}
    6567
     68static bool isTimerPosted; // This is only accessed on the 'main' thread.
     69
     70static void timerFired(CFRunLoopTimerRef timer, void*)
     71{
     72    CFRelease(timer);
     73    isTimerPosted = false;
     74    WTF::dispatchFunctionsFromMainThread();
     75}
     76
     77void postTimer()
     78{
     79    ASSERT(isMainThread());
     80
     81    if (isTimerPosted)
     82        return;
     83
     84    isTimerPosted = true;
     85    CFRunLoopAddTimer(CFRunLoopGetCurrent(), CFRunLoopTimerCreate(0, 0, 0, 0, 0, timerFired, 0), kCFRunLoopCommonModes);
     86}
     87
     88
    6689void scheduleDispatchFunctionsOnMainThread()
    6790{
    6891    ASSERT(staticMainThreadCaller);
     92
     93    if (isMainThread()) {
     94        postTimer();
     95        return;
     96    }
     97
    6998#if USE(WEB_THREAD)
    7099    [staticMainThreadCaller performSelector:@selector(call) onThread:webThread withObject:nil waitUntilDone:NO];
  • trunk/LayoutTests/ChangeLog

    r55804 r55816  
     12010-03-10  Dmitry Titov  <dimich@chromium.org>
     2
     3        Reviewed by Darin Adler.
     4
     5        Make Document::postTask to use a single queue of tasks, to fire them in order
     6        https://bugs.webkit.org/show_bug.cgi?id=35943
     7
     8        Updated the test since the order of events coming from independent task sources has changed.
     9        This is a behavior change, but is consistent with the spec (which specifically says these events may be fired
     10        in any order) and the last version of FF (3.5.8) which was completing the test successfully.
     11
     12        * http/tests/appcache/top-frame-2-expected.txt:
     13        * http/tests/appcache/top-frame-2.html:
     14
    1152010-03-10  Antonio Gomes  <tonikitoo@webkit.org>
    216
  • trunk/LayoutTests/http/tests/appcache/top-frame-2-expected.txt

    r39477 r55816  
    33Should say SUCCESS:
    44
    5 checking
    65SUCCESS
    76
  • trunk/LayoutTests/http/tests/appcache/top-frame-2.html

    r39477 r55816  
    1717}
    1818
     19function debug(message)
     20{
     21    // If running manually in the browser, print the sequence of events.
     22    if (!window.layoutTestController)
     23        log(message);
     24}
     25
     26var receivedExpectedMessage = false;
     27var receivedCheckingEvent = false;
     28var receivedNoupdateEvent = false;
     29
    1930function test()
    2031{
     
    2334
    2435    // When a new main resource is associated with the cache, an update should be started.
    25     applicationCache.onchecking = function() { log("checking") }
     36    applicationCache.onchecking = function() { debug("checking"); receivedCheckingEvent = true; checkDone();  }
     37    applicationCache.onnoupdate = function() { debug("noupdate"); receivedNoupdateEvent = true; checkDone();  }
    2638
    2739    var ifr = document.createElement("iframe");
    2840    ifr.setAttribute("src", "resources/subframe-2.html");
    2941    document.body.appendChild(ifr);
     42}
     43
     44function checkDone()
     45{
     46    if (receivedExpectedMessage && receivedCheckingEvent && receivedNoupdateEvent) {
     47        log("SUCCESS");
     48        if (window.layoutTestController)
     49            layoutTestController.notifyDone();
     50    }
    3051}
    3152
     
    3657applicationCache.onerror = function() { log("FAIL: received unexpected error event") }
    3758
    38 window.addEventListener("message", function() { log("SUCCESS"); if (window.layoutTestController) layoutTestController.notifyDone() }, false);
     59window.addEventListener("message", function() { debug("message"); receivedExpectedMessage = true; checkDone(); }, false);
    3960
    4061</script>
  • trunk/WebCore/ChangeLog

    r55814 r55816  
     12010-03-10  Dmitry Titov  <dimich@chromium.org>
     2
     3        Reviewed by Darin Adler.
     4
     5        Make Document::postTask to use a single queue of tasks, to fire them in order
     6        https://bugs.webkit.org/show_bug.cgi?id=35943
     7
     8        Test: existing worker-cloneport.html which was broken by initial patch in http://trac.webkit.org/changeset/55593.
     9        Additional test which indirectly verifies the order of execution will come as part of https://bugs.webkit.org/show_bug.cgi?id=34726
     10
     11        * dom/Document.cpp:
     12        (WebCore::Document::postTask): Always use the same task queue, independent of what thread is posting the task.
     13
    1142010-03-10  Sanjeev Radhakrishnan  <sanjeevr@chromium.org>
    215
  • trunk/WebCore/dom/Document.cpp

    r55802 r55816  
    46864686}
    46874687
    4688 class ScriptExecutionContextTaskTimer : public TimerBase {
    4689 public:
    4690     ScriptExecutionContextTaskTimer(PassRefPtr<Document> context, PassOwnPtr<ScriptExecutionContext::Task> task)
    4691         : m_context(context)
    4692         , m_task(task)
    4693     {
    4694     }
    4695 
    4696 private:
    4697     virtual void fired()
    4698     {
    4699         m_task->performTask(m_context.get());
    4700         delete this;
    4701     }
    4702 
    4703     RefPtr<Document> m_context;
    4704     OwnPtr<ScriptExecutionContext::Task> m_task;
    4705 };
    4706 
    47074688struct PerformTaskContext : Noncopyable {
    47084689    PerformTaskContext(PassRefPtr<DocumentWeakReference> documentReference, PassOwnPtr<ScriptExecutionContext::Task> task)
     
    47314712void Document::postTask(PassOwnPtr<Task> task)
    47324713{
    4733     if (isMainThread()) {
    4734         ScriptExecutionContextTaskTimer* timer = new ScriptExecutionContextTaskTimer(static_cast<Document*>(this), task);
    4735         timer->startOneShot(0);
    4736     } else {
    4737         callOnMainThread(performTask, new PerformTaskContext(m_weakReference, task));
    4738     }
     4714    callOnMainThread(performTask, new PerformTaskContext(m_weakReference, task));
    47394715}
    47404716
Note: See TracChangeset for help on using the changeset viewer.