Reviewed by Oliver

        Resolve an outstanding FIXME in Loader::numRequests()

        Before, numRequests() would iterate through the list of requests pending load and the list of currently
        loading requests and tally up a count matching the current DocLoader.

        I noticed while studying and cleaning up the loader code that numRequests() is potentially very hot!
        Indeed load a complex site with many resources and multiple frames, and this method gets called very often,
        tallying up this number every time.

        The FIXME was to keep a collection of Requests mapped to each DocLoader.  In reality, since this map would
        simply be used for retrieving a count, that was overkill.  Keeping a request count in the DocLoader itself
        along with maintaining that count in Loader as requests come and go is a much better way to do this.

        * loader/DocLoader.cpp:
        (WebCore::DocLoader::DocLoader):
        (WebCore::DocLoader::incrementRequestCount):
        (WebCore::DocLoader::decrementRequestCount):
        (WebCore::DocLoader::requestCount): Emulate the defunct Loader::numRequests()
        * loader/DocLoader.h:

        * loader/FrameLoader.cpp:
        (WebCore::numRequests): Call DocLoader::requestCount() directly
        (WebCore::FrameLoader::checkCompleted): Use numRequests()

        * loader/loader.cpp:
        (WebCore::Loader::load): Increment the DocLoader's request count
        (WebCore::Loader::servePendingRequests): If the SubresourceLoader failed to create, decrement the count
        (WebCore::Loader::didFinishLoading): If the Request is not Multipart, decrement the count
        (WebCore::Loader::didFail): If the Request is not Multipart, decrement the count
        (WebCore::Loader::didReceiveResponse): If the Request becomes Multipart, decrement the count
        (WebCore::Loader::cancelRequests): Decrement the count for the pending requests being tossed, and ASSERT the
          count is zero after all requests have been cancelled
        * loader/loader.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@21245 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 646f214..2cc1468 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,4 +1,41 @@
-<<<<<<< .mine
+2007-05-03  Brady Eidson  <beidson@apple.com>
+
+        Reviewed by Oliver
+
+        Resolve an outstanding FIXME in Loader::numRequests()
+
+        Before, numRequests() would iterate through the list of requests pending load and the list of currently
+        loading requests and tally up a count matching the current DocLoader.
+
+        I noticed while studying and cleaning up the loader code that numRequests() is potentially very hot!
+        Indeed load a complex site with many resources and multiple frames, and this method gets called very often,
+        tallying up this number every time.
+
+        The FIXME was to keep a collection of Requests mapped to each DocLoader.  In reality, since this map would
+        simply be used for retrieving a count, that was overkill.  Keeping a request count in the DocLoader itself
+        along with maintaining that count in Loader as requests come and go is a much better way to do this.
+
+        * loader/DocLoader.cpp:
+        (WebCore::DocLoader::DocLoader):
+        (WebCore::DocLoader::incrementRequestCount):
+        (WebCore::DocLoader::decrementRequestCount):
+        (WebCore::DocLoader::requestCount): Emulate the defunct Loader::numRequests()
+        * loader/DocLoader.h:
+
+        * loader/FrameLoader.cpp:
+        (WebCore::numRequests): Call DocLoader::requestCount() directly
+        (WebCore::FrameLoader::checkCompleted): Use numRequests()
+
+        * loader/loader.cpp:
+        (WebCore::Loader::load): Increment the DocLoader's request count
+        (WebCore::Loader::servePendingRequests): If the SubresourceLoader failed to create, decrement the count
+        (WebCore::Loader::didFinishLoading): If the Request is not Multipart, decrement the count
+        (WebCore::Loader::didFail): If the Request is not Multipart, decrement the count
+        (WebCore::Loader::didReceiveResponse): If the Request becomes Multipart, decrement the count
+        (WebCore::Loader::cancelRequests): Decrement the count for the pending requests being tossed, and ASSERT the
+          count is zero after all requests have been cancelled
+        * loader/loader.h:
+
 2007-05-03  Geoffrey Garen  <ggaren@apple.com>
 
         Reviewed by Brady Eidson.
@@ -18,7 +55,6 @@
         the function name.
         * loader/FrameLoader.h:
 
-=======
 2007-05-03  Justin Garcia  <justin.garcia@apple.com>
 
         Reviewed by harrison.
@@ -31,7 +67,6 @@
         (WebCore::createMarkup):
         Nil-check checkAncestor and lastClosed.
 
->>>>>>> .r21243
 2007-05-03  Timothy Hatcher  <timothy@apple.com>
 
         Reviewed by Kevin.
diff --git a/WebCore/loader/DocLoader.cpp b/WebCore/loader/DocLoader.cpp
index bd8bedc..b94cd44 100644
--- a/WebCore/loader/DocLoader.cpp
+++ b/WebCore/loader/DocLoader.cpp
@@ -45,6 +45,7 @@
     , m_cachePolicy(CachePolicyVerify)
     , m_frame(frame)
     , m_doc(doc)
+    , m_requestCount(0)
     , m_autoLoadImages(true)
     , m_loadInProgress(false)
     , m_allowStaleResources(false)
@@ -205,4 +206,22 @@
     m_frame->loader()->didTellBridgeAboutLoad(resource->url());
 }
 
+void DocLoader::incrementRequestCount()
+{
+    ++m_requestCount;
+}
+
+void DocLoader::decrementRequestCount()
+{
+    --m_requestCount;
+    ASSERT(m_requestCount > -1);
+}
+
+int DocLoader::requestCount()
+{
+    if (loadInProgress())
+         return m_requestCount + 1;
+    return m_requestCount;
+}
+
 }
diff --git a/WebCore/loader/DocLoader.h b/WebCore/loader/DocLoader.h
index 1e4a0ab..e62bfaf 100644
--- a/WebCore/loader/DocLoader.h
+++ b/WebCore/loader/DocLoader.h
@@ -88,6 +88,9 @@
     void replaceDocument(Document* doc) { m_doc = doc; }
 #endif
 
+    void incrementRequestCount();
+    void decrementRequestCount();
+    int requestCount();
 private:
     CachedResource* requestResource(CachedResource::Type, const String& url, const String* charset = 0, bool skipCanLoadCheck = false);
 
@@ -101,6 +104,8 @@
     Frame* m_frame;
     Document *m_doc;
     
+    int m_requestCount;
+    
     //29 bits left
     bool m_autoLoadImages : 1;
     bool m_loadInProgress : 1;
diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp
index 0bf11a0..5acbbcc 100644
--- a/WebCore/loader/FrameLoader.cpp
+++ b/WebCore/loader/FrameLoader.cpp
@@ -195,9 +195,10 @@
 
 static int numRequests(Document* document)
 {
-    if (document)
-        return cache()->loader()->numRequests(document->docLoader());
-    return 0;
+    if (!document)
+        return 0;
+    
+    return document->docLoader()->requestCount();
 }
 
 FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
@@ -1126,8 +1127,8 @@
         return;
 
     // Still waiting for images/scripts?
-    if (m_frame->document() && m_frame->document()->docLoader())
-        if (cache()->loader()->numRequests(m_frame->document()->docLoader()))
+    if (m_frame->document())
+        if (numRequests(m_frame->document()))
             return;
 
 #if USE(LOW_BANDWIDTH_DISPLAY)
diff --git a/WebCore/loader/loader.cpp b/WebCore/loader/loader.cpp
index 7fe515e..9c5642b 100644
--- a/WebCore/loader/loader.cpp
+++ b/WebCore/loader/loader.cpp
@@ -58,8 +58,10 @@
 
 void Loader::load(DocLoader* dl, CachedResource* object, bool incremental, bool skipCanLoadCheck)
 {
+    ASSERT(dl);
     Request* req = new Request(dl, object, incremental);
     m_requestsPending.append(req);
+    dl->incrementRequestCount();
     servePendingRequests(skipCanLoadCheck);
 }
 
@@ -70,25 +72,28 @@
 
     // get the first pending request
     Request* req = m_requestsPending.take(0);
+    DocLoader* dl = req->docLoader();
+    dl->decrementRequestCount();
 
     ResourceRequest request(req->cachedResource()->url());
 
     if (!req->cachedResource()->accept().isEmpty())
         request.setHTTPAccept(req->cachedResource()->accept());
-    if (req->docLoader())  {
-        KURL r = req->docLoader()->doc()->URL();
-        if (r.protocol().startsWith("http") && r.path().isEmpty())
-            r.setPath("/");
-        request.setHTTPReferrer(r.url());
-        DeprecatedString domain = r.host();
-        if (req->docLoader()->doc()->isHTMLDocument())
-            domain = static_cast<HTMLDocument*>(req->docLoader()->doc())->domain().deprecatedString();
-    }
-    
-    RefPtr<SubresourceLoader> loader = SubresourceLoader::create(req->docLoader()->doc()->frame(), this, request, skipCanLoadCheck);
 
-    if (loader)
+    KURL r = dl->doc()->URL();
+    if (r.protocol().startsWith("http") && r.path().isEmpty())
+        r.setPath("/");
+    request.setHTTPReferrer(r.url());
+    DeprecatedString domain = r.host();
+    if (dl->doc()->isHTMLDocument())
+        domain = static_cast<HTMLDocument*>(dl->doc())->domain().deprecatedString();
+    
+    RefPtr<SubresourceLoader> loader = SubresourceLoader::create(dl->doc()->frame(), this, request, skipCanLoadCheck);
+
+    if (loader) {
         m_requestsLoading.add(loader.release(), req);
+        dl->incrementRequestCount();
+    }
 }
 
 void Loader::didFinishLoading(SubresourceLoader* loader)
@@ -99,9 +104,11 @@
 
     Request* req = i->second;
     m_requestsLoading.remove(i);
+    DocLoader* docLoader = req->docLoader();
+    if (!req->isMultipart())
+        docLoader->decrementRequestCount();
 
     CachedResource* object = req->cachedResource();
-    DocLoader* docLoader = req->docLoader();
 
     docLoader->setLoadInProgress(true);
     object->data(loader->resourceData(), true);
@@ -126,9 +133,11 @@
 
     Request* req = i->second;
     m_requestsLoading.remove(i);
+    DocLoader* docLoader = req->docLoader();
+    if (!req->isMultipart())
+        docLoader->decrementRequestCount();
 
     CachedResource* object = req->cachedResource();
-    DocLoader* docLoader = req->docLoader();
 
     if (!cancelled) {
         docLoader->setLoadInProgress(true);
@@ -160,6 +169,10 @@
             req->docLoader()->frame()->loader()->checkCompleted();
     } else if (response.isMultipart()) {
         req->setIsMultipart(true);
+        
+        // We don't count multiParts in a DocLoader's request count
+        req->docLoader()->decrementRequestCount();
+            
         // If we get a multipart response, we must have a handle
         ASSERT(loader->handle());
         if (!req->cachedResource()->isImage())
@@ -183,30 +196,6 @@
         object->data(loader->resourceData(), false);
 }
 
-int Loader::numRequests(DocLoader* dl) const
-{
-    // FIXME: Maybe we should keep a collection of requests by DocLoader, so we can do this instantly.
-
-    int res = 0;
-
-    DeprecatedPtrListIterator<Request> pIt(m_requestsPending);
-    for (; pIt.current(); ++pIt) {
-        if (pIt.current()->docLoader() == dl)
-            res++;
-    }
-
-    RequestMap::const_iterator end = m_requestsLoading.end();
-    for (RequestMap::const_iterator i = m_requestsLoading.begin(); !(i == end); ++i) {
-        Request* r = i->second;
-        res += (r->docLoader() == dl && !r->isMultipart());
-    }
-
-    if (dl->loadInProgress())
-        res++;
-
-    return res;
-}
-
 void Loader::cancelRequests(DocLoader* dl)
 {
     DeprecatedPtrListIterator<Request> pIt(m_requestsPending);
@@ -214,6 +203,7 @@
         if (pIt.current()->docLoader() == dl) {
             cache()->remove(pIt.current()->cachedResource());
             m_requestsPending.remove(pIt);
+            dl->decrementRequestCount();
         } else
             ++pIt;
     }
@@ -231,6 +221,11 @@
         SubresourceLoader* loader = loadersToCancel[i];
         didFail(loader, true);
     }
+    
+    if (dl->loadInProgress())
+        ASSERT(dl->requestCount() == 1);
+    else
+        ASSERT(dl->requestCount() == 0);
 }
 
 } //namespace WebCore
diff --git a/WebCore/loader/loader.h b/WebCore/loader/loader.h
index 3f8ae35..c02dc29 100644
--- a/WebCore/loader/loader.h
+++ b/WebCore/loader/loader.h
@@ -51,9 +51,7 @@
 
         void load(DocLoader*, CachedResource*, bool incremental = true, bool skipCanLoadCheck = false);
 
-        int numRequests(DocLoader*) const;
         void cancelRequests(DocLoader*);
-
     private:
         virtual void didReceiveResponse(SubresourceLoader*, const ResourceResponse&);
         virtual void didReceiveData(SubresourceLoader*, const char*, int);