Backed out changeset 961d90be2ba8 from bug 364315 due to random crashes in
authorDave Townsend <dtownsend@oxymoronical.com>
Tue, 30 Sep 2008 13:08:20 +0100
changeset 19915 996d2802d3f2762122f9cb25a4b2302d2facbb8f
parent 19898 961d90be2ba80d1ecafb00edc027908beca1e733
child 19916 d00d64c5b4d9702accf1b09855ceefe3ccfb2f4b
push id2543
push userdtownsend@mozilla.com
push dateTue, 30 Sep 2008 12:09:36 +0000
treeherdermozilla-central@d00d64c5b4d9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs364315
milestone1.9.1b1pre
backs out961d90be2ba80d1ecafb00edc027908beca1e733
Backed out changeset 961d90be2ba8 from bug 364315 due to random crashes in tests.
content/base/src/nsScriptLoader.cpp
content/base/src/nsScriptLoader.h
parser/htmlparser/src/CParserContext.cpp
parser/htmlparser/src/CParserContext.h
parser/htmlparser/src/nsParser.cpp
parser/htmlparser/src/nsParser.h
parser/htmlparser/src/nsScanner.cpp
parser/htmlparser/src/nsScanner.h
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -91,21 +91,16 @@ public:
   {
     mElement->ScriptAvailable(aResult, mElement, mIsInline, mURI, mLineNo);
   }
   void FireScriptEvaluated(nsresult aResult)
   {
     mElement->ScriptEvaluated(aResult, mElement, mIsInline);
   }
 
-  PRBool IsPreload()
-  {
-    return mElement == nsnull;
-  }
-
   nsCOMPtr<nsIScriptElement> mElement;
   PRPackedBool mLoading;             // Are we still waiting for a load to complete?
   PRPackedBool mDefer;               // Is execution defered?
   PRPackedBool mIsInline;            // Is the script inline or loaded?
   nsString mScriptText;              // Holds script for loaded scripts
   PRUint32 mJSVersion;
   nsCOMPtr<nsIURI> mURI;
   PRInt32 mLineNo;
@@ -190,82 +185,16 @@ IsScriptEventHandler(nsIScriptElement *a
 
     return PR_TRUE;
   }
 
   return PR_FALSE;
 }
 
 nsresult
-nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
-{
-  // Check that the containing page is allowed to load this URI.
-  nsresult rv = nsContentUtils::GetSecurityManager()->
-    CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), aRequest->mURI,
-                              nsIScriptSecurityManager::ALLOW_CHROME);
-
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // After the security manager, the content-policy stuff gets a veto
-  PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
-  rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT,
-                                 aRequest->mURI,
-                                 mDocument->NodePrincipal(),
-                                 aRequest->mElement,
-                                 NS_LossyConvertUTF16toASCII(aType),
-                                 nsnull,    //extra
-                                 &shouldLoad,
-                                 nsContentUtils::GetContentPolicy(),
-                                 nsContentUtils::GetSecurityManager());
-  if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
-    if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
-      return NS_ERROR_CONTENT_BLOCKED;
-    }
-    return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
-  }
-
-  nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup();
-  nsCOMPtr<nsIStreamLoader> loader;
-
-  nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mDocument->GetScriptGlobalObject()));
-  nsIDocShell *docshell = window->GetDocShell();
-
-  nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));
-
-  nsCOMPtr<nsIChannel> channel;
-  rv = NS_NewChannel(getter_AddRefs(channel),
-                     aRequest->mURI, nsnull, loadGroup,
-                     prompter, nsIRequest::LOAD_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
-  if (httpChannel) {
-    // HTTP content negotation has little value in this context.
-    httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
-                                  NS_LITERAL_CSTRING("*/*"),
-                                  PR_FALSE);
-    httpChannel->SetReferrer(mDocument->GetDocumentURI());
-  }
-
-  rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return channel->AsyncOpen(loader, aRequest);
-}
-
-PRBool
-nsScriptLoader::PreloadURIComparator::Equals(const PreloadInfo &aPi,
-                                             nsIURI * const &aURI) const
-{
-  PRBool same;
-  return NS_SUCCEEDED(aPi.mRequest->mURI->Equals(aURI, &same)) &&
-         same;
-}
-
-nsresult
 nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
 {
   // We need a document to evaluate scripts.
   NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
 
   // Check to see if scripts has been turned off.
   if (!mEnabled || !mDocument->IsScriptEnabled()) {
     return NS_ERROR_NOT_AVAILABLE;
@@ -442,65 +371,84 @@ nsScriptLoader::ProcessScriptElement(nsI
       !nsContentUtils::IsChromeDoc(mDocument)) {
     NS_WARNING("Untrusted language called from non-chrome - ignored");
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsCOMPtr<nsIContent> eltContent(do_QueryInterface(aElement));
   eltContent->SetScriptTypeID(typeID);
 
-  PRBool hadPendingRequests = !!GetFirstPendingRequest();
-
-  // Did we preload this request?
-  nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
-  nsRefPtr<nsScriptLoadRequest> request;
-  if (scriptURI) {
-    nsTArray<PreloadInfo>::index_type i =
-      mPreloads.IndexOf(scriptURI.get(), 0, PreloadURIComparator());
-    if (i != nsTArray<PreloadInfo>::NoIndex) {
-      request = mPreloads[i].mRequest;
-      request->mElement = aElement;
-      request->mJSVersion = version;
-      request->mDefer = mDeferEnabled && aElement->GetScriptDeferred();
-      mPreloads.RemoveElementAt(i);
-
-      if (!request->mLoading && !request->mDefer && !hadPendingRequests &&
-            ReadyToExecuteScripts() && nsContentUtils::IsSafeToRunScript()) {
-        return ProcessRequest(request);
-      }
-
-      // Not done loading yet. Move into the real requests queue and wait.
-      mRequests.AppendObject(request);
-
-      if (!request->mLoading && !hadPendingRequests && ReadyToExecuteScripts() &&
-          !request->mDefer) {
-        nsContentUtils::AddScriptRunner(new nsRunnableMethod<nsScriptLoader>(this,
-          &nsScriptLoader::ProcessPendingRequests));
-      }
-
-      return request->mDefer ? NS_OK : NS_ERROR_HTMLPARSER_BLOCK;
-    }
-  }
-
   // Create a request object for this script
-  request = new nsScriptLoadRequest(aElement, version);
+  nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(aElement, version);
   NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY);
 
   request->mDefer = mDeferEnabled && aElement->GetScriptDeferred();
 
+  PRBool hadPendingRequests = !!GetFirstPendingRequest();
+
   // First check to see if this is an external script
+  nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
   if (scriptURI) {
+    // Check that the containing page is allowed to load this URI.
+    rv = nsContentUtils::GetSecurityManager()->
+      CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), scriptURI,
+                                nsIScriptSecurityManager::ALLOW_CHROME);
+
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    // After the security manager, the content-policy stuff gets a veto
+    PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
+    rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT,
+                                   scriptURI,
+                                   mDocument->NodePrincipal(),
+                                   aElement,
+                                   NS_LossyConvertUTF16toASCII(type),
+                                   nsnull,    //extra
+                                   &shouldLoad,
+                                   nsContentUtils::GetContentPolicy(),
+                                   nsContentUtils::GetSecurityManager());
+    if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
+      if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
+        return NS_ERROR_CONTENT_BLOCKED;
+      }
+      return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
+    }
+
     request->mURI = scriptURI;
     request->mIsInline = PR_FALSE;
     request->mLoading = PR_TRUE;
 
-    rv = StartLoad(request, type);
-    if (NS_FAILED(rv)) {
-      return rv;
+    nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup();
+    nsCOMPtr<nsIStreamLoader> loader;
+
+    nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(globalObject));
+    nsIDocShell *docshell = window->GetDocShell();
+
+    nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));
+
+    nsCOMPtr<nsIChannel> channel;
+    rv = NS_NewChannel(getter_AddRefs(channel),
+                       scriptURI, nsnull, loadGroup,
+                       prompter, nsIRequest::LOAD_NORMAL);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
+    if (httpChannel) {
+      // HTTP content negotation has little value in this context.
+      httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
+                                    NS_LITERAL_CSTRING("*/*"),
+                                    PR_FALSE);
+      httpChannel->SetReferrer(mDocument->GetDocumentURI());
     }
+
+    rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = channel->AsyncOpen(loader, request);
+    NS_ENSURE_SUCCESS(rv, rv);
   } else {
     request->mLoading = PR_FALSE;
     request->mIsInline = PR_TRUE;
     request->mURI = mDocument->GetDocumentURI();
 
     request->mLineNo = aElement->GetScriptLineNumber();
 
     // If we've got existing pending requests, add ourselves
@@ -861,21 +809,18 @@ nsScriptLoader::OnStreamComplete(nsIStre
 {
   nsScriptLoadRequest* request = static_cast<nsScriptLoadRequest*>(aContext);
   NS_ASSERTION(request, "null request in stream complete handler");
   NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
 
   nsresult rv = PrepareLoadedRequest(request, aLoader, aStatus, aStringLen,
                                      aString);
   if (NS_FAILED(rv)) {
-    if (!mRequests.RemoveObject(request)) {
-      mPreloads.RemoveElement(request, PreloadRequestComparator());
-    } else {
-      FireScriptAvailable(rv, request);
-    }
+    mRequests.RemoveObject(request);
+    FireScriptAvailable(rv, request);
   }
 
   // Process our request and/or any pending ones
   ProcessPendingRequests();
 
   return NS_OK;
 }
 
@@ -910,40 +855,32 @@ nsScriptLoader::PrepareLoadedRequest(nsS
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(req);
   if (aStringLen) {
     // Check the charset attribute to determine script charset.
     nsAutoString hintCharset;
-    if (!aRequest->IsPreload()) {
-      aRequest->mElement->GetScriptCharset(hintCharset);
-    } else {
-      nsTArray<PreloadInfo>::index_type i =
-        mPreloads.IndexOf(aRequest, 0, PreloadRequestComparator());
-      NS_ASSERTION(i != mPreloads.NoIndex, "Incorrect preload bookkeeping");
-      hintCharset = mPreloads[i].mCharset;
-    }
+    aRequest->mElement->GetScriptCharset(hintCharset);
     rv = ConvertToUTF16(channel, aString, aStringLen, hintCharset, mDocument,
                         aRequest->mScriptText);
 
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (!ShouldExecuteScript(mDocument, channel)) {
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
   // This assertion could fire errorously if we ran out of memory when
   // inserting the request in the array. However it's an unlikely case
   // so if you see this assertion it is likely something else that is
   // wrong, especially if you see it more than once.
-  NS_ASSERTION(mRequests.IndexOf(aRequest) >= 0 ||
-               mPreloads.Contains(aRequest, PreloadRequestComparator()),
+  NS_ASSERTION(mRequests.IndexOf(aRequest) >= 0,
                "aRequest should be pending!");
 
   // Mark this as loaded
   aRequest->mLoading = PR_FALSE;
 
   return NS_OK;
 }
 
@@ -976,38 +913,14 @@ nsScriptLoader::ShouldExecuteScript(nsID
   rv = channelPrincipal->Subsumes(docPrincipal, &subsumes);
   return NS_SUCCEEDED(rv) && subsumes;
 }
 
 void
 nsScriptLoader::EndDeferringScripts()
 {
   mDeferEnabled = PR_FALSE;
-  for (PRUint32 i = 0; i < (PRUint32)mRequests.Count(); ++i) {
+  for (PRUint32 i = 0; i < mRequests.Count(); ++i) {
     mRequests[i]->mDefer = PR_FALSE;
   }
 
   ProcessPendingRequests();
 }
-
-void
-nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
-                           const nsAString &aType)
-{
-  nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(nsnull, 0);
-  if (!request) {
-    return;
-  }
-
-  request->mURI = aURI;
-  request->mIsInline = PR_FALSE;
-  request->mLoading = PR_TRUE;
-  request->mDefer = PR_FALSE; // This is computed later when we go to execute the
-                              // script.
-  nsresult rv = StartLoad(request, aType);
-  if (NS_FAILED(rv)) {
-    return;
-  }
-
-  PreloadInfo *pi = mPreloads.AppendElement();
-  pi->mRequest = request;
-  pi->mCharset = aCharset;
-}
--- a/content/base/src/nsScriptLoader.h
+++ b/content/base/src/nsScriptLoader.h
@@ -200,33 +200,18 @@ public:
    * Stops defering scripts and immediately processes the mDeferredRequests
    * queue.
    *
    * WARNING: This function will syncronously execute content scripts, so be
    * prepared that the world might change around you.
    */
   void EndDeferringScripts();
 
-  /**
-   * Adds aURI to the preload list and starts loading it.
-   *
-   * @param aURI The URI of the external script.
-   * @param aCharset The charset parameter for the script.
-   * @param aType The type parameter for the script.
-   */
-  virtual void PreloadURI(nsIURI *aURI, const nsAString &aCharset,
-                          const nsAString &aType);
-
 protected:
   /**
-   * Start a load for aRequest's URI.
-   */
-  nsresult StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType);
-
-  /**
    * Process any pending requests asyncronously (i.e. off an event) if there
    * are any. Note that this is a no-op if there aren't any currently pending
    * requests.
    */
   virtual void ProcessPendingRequestsAsync();
 
   /**
    * If true, the loader is ready to execute scripts, and so are all its
@@ -263,35 +248,16 @@ protected:
                                 const PRUint8* aString);
 
   // Returns the first pending (non deferred) request
   nsScriptLoadRequest* GetFirstPendingRequest();
 
   nsIDocument* mDocument;                   // [WEAK]
   nsCOMArray<nsIScriptLoaderObserver> mObservers;
   nsCOMArray<nsScriptLoadRequest> mRequests;
-
-  // In mRequests, the additional information here is stored by the element.
-  struct PreloadInfo {
-    nsRefPtr<nsScriptLoadRequest> mRequest;
-    nsString mCharset;
-  };
-
-  struct PreloadRequestComparator {
-    PRBool Equals(const PreloadInfo &aPi, nsScriptLoadRequest * const &aRequest)
-        const
-    {
-      return aRequest == aPi.mRequest;
-    }
-  };
-  struct PreloadURIComparator {
-    PRBool Equals(const PreloadInfo &aPi, nsIURI * const &aURI) const;
-  };
-  nsTArray<PreloadInfo> mPreloads;
-
   nsCOMPtr<nsIScriptElement> mCurrentScript;
   // XXXbz do we want to cycle-collect these or something?  Not sure.
   nsTArray< nsRefPtr<nsScriptLoader> > mPendingChildLoaders;
   PRUint32 mBlockerCount;
   PRPackedBool mEnabled;
   PRPackedBool mDeferEnabled;
 };
 
--- a/parser/htmlparser/src/CParserContext.cpp
+++ b/parser/htmlparser/src/CParserContext.cpp
@@ -58,17 +58,17 @@ CParserContext::CParserContext(nsScanner
     mScanner(aScanner),
     mDTDMode(eDTDMode_unknown),
     mStreamListenerState(eNone),
     mContextType(eCTNone),
     mAutoDetectStatus(aStatus),
     mParserCommand(aCommand),
     mMultipart(PR_TRUE),
     mCopyUnused(aCopyUnused),
-    mNumConsumed(0)
+    mTransferBufferSize(eTransferBufferSize)
 { 
   MOZ_COUNT_CTOR(CParserContext); 
 } 
 
 CParserContext::~CParserContext()
 {
   // It's ok to simply ingore the PrevContext.
   MOZ_COUNT_DTOR(CParserContext);
--- a/parser/htmlparser/src/CParserContext.h
+++ b/parser/htmlparser/src/CParserContext.h
@@ -55,51 +55,54 @@
 #include "nsAutoPtr.h"
 
 /**
  * Note that the parser is given FULL access to all
  * data in a parsercontext. Hey, that what it's for!
  */
 
 class CParserContext {
+
 public:
-   enum eContextType {eCTNone,eCTURL,eCTString,eCTStream};
+
+    enum {eTransferBufferSize=4096};
+    enum eContextType {eCTNone,eCTURL,eCTString,eCTStream};
 
-   CParserContext(nsScanner* aScanner,
-                  void* aKey = 0,
-                  eParserCommands aCommand = eViewNormal,
-                  nsIRequestObserver* aListener = 0,
-                  nsIDTD* aDTD = 0,
-                  eAutoDetectResult aStatus = eUnknownDetect,
-                  PRBool aCopyUnused = PR_FALSE);
-
+   CParserContext(  nsScanner* aScanner,
+                    void* aKey=0, 
+                    eParserCommands aCommand=eViewNormal,
+                    nsIRequestObserver* aListener=0, 
+                    nsIDTD *aDTD=0, 
+                    eAutoDetectResult aStatus=eUnknownDetect, 
+                    PRBool aCopyUnused=PR_FALSE); 
+    
     ~CParserContext();
 
     nsresult GetTokenizer(PRInt32 aType,
                           nsIContentSink* aSink,
                           nsITokenizer*& aTokenizer);
     void  SetMimeType(const nsACString& aMimeType);
 
     nsCOMPtr<nsIRequest> mRequest; // provided by necko to differnciate different input streams
                                    // why is mRequest strongly referenced? see bug 102376.
-    nsCOMPtr<nsIDTD>     mDTD;
+    nsCOMPtr<nsIDTD>	 mDTD;
     nsCOMPtr<nsIRequestObserver> mListener;
+    nsAutoArrayPtr<char> mTransferBuffer;
     void*                mKey;
     nsCOMPtr<nsITokenizer> mTokenizer;
     CParserContext*      mPrevContext;
     nsAutoPtr<nsScanner> mScanner;
-
+    
     nsCString            mMimeType;
     nsDTDMode            mDTDMode;
-
+    
     eParserDocType       mDocType;
-    eStreamState         mStreamListenerState;
+    eStreamState         mStreamListenerState; //this is really only here for debug purposes.
     eContextType         mContextType;
     eAutoDetectResult    mAutoDetectStatus;
-    eParserCommands      mParserCommand;
+    eParserCommands      mParserCommand;   //tells us to viewcontent/viewsource/viewerrors...
 
     PRPackedBool         mMultipart;
     PRPackedBool         mCopyUnused;
-
-    PRUint32             mNumConsumed;
+    PRUint32             mTransferBufferSize;
 };
 
 #endif
--- a/parser/htmlparser/src/nsParser.cpp
+++ b/parser/htmlparser/src/nsParser.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=2 ts=2 et tw=79: */
+/* vim: set sw=2 ts=2 et tw=78: */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -47,33 +47,25 @@
 #include "nsIChannel.h"
 #include "nsICachingChannel.h"
 #include "nsICacheEntryDescriptor.h"
 #include "nsICharsetAlias.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIInputStream.h"
 #include "CNavDTD.h"
 #include "prenv.h"
-#include "prlock.h"
-#include "prcvar.h"
-#include "nsAutoLock.h"
 #include "nsParserCIID.h"
 #include "nsReadableUtils.h"
 #include "nsCOMPtr.h"
 #include "nsExpatDriver.h"
 #include "nsIServiceManager.h"
 #include "nsICategoryManager.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIFragmentContentSink.h"
 #include "nsStreamUtils.h"
-#include "nsHTMLTokenizer.h"
-#include "nsIDocument.h"
-#include "nsNetUtil.h"
-#include "nsScriptLoader.h"
-#include "nsDataHashtable.h"
 
 #ifdef MOZ_VIEW_SOURCE
 #include "nsViewSourceHTML.h"
 #endif
 
 #define NS_PARSER_FLAG_PARSER_ENABLED         0x00000002
 #define NS_PARSER_FLAG_OBSERVERS_ENABLED      0x00000004
 #define NS_PARSER_FLAG_PENDING_CONTINUE_EVENT 0x00000008
@@ -158,488 +150,16 @@ public:
   {
     mParser->HandleParserContinueEvent(this);
     return NS_OK;
   }
 };
 
 //-------------- End ParseContinue Event Definition ------------------------
 
-template <class Type>
-class Holder {
-public:
-  typedef void (*Reaper)(Type *);
-
-  Holder(Reaper aReaper)
-    : mHoldee(nsnull), mReaper(aReaper)
-  {
-  }
-
-  ~Holder() {
-    if (mHoldee) {
-      mReaper(mHoldee);
-    }
-  }
-
-  Type *get() {
-    return mHoldee;
-  }
-  const Holder &operator =(Type *aHoldee) {
-    if (mHoldee && aHoldee != mHoldee) {
-      mReaper(mHoldee);
-    }
-    mHoldee = aHoldee;
-    return *this;
-  }
-
-private:
-  Type *mHoldee;
-  Reaper mReaper;
-};
-
-class nsSpeculativeScriptThread : public nsIRunnable {
-public:
-  nsSpeculativeScriptThread(nsTokenAllocator *aTokenAllocator)
-    : mLock(PR_DestroyLock),
-      mCVar(PR_DestroyCondVar),
-      mKeepParsing(0),
-      mCurrentlyParsing(0),
-      mNumURIs(0),
-      mNumConsumed(0),
-      mTokenAllocator(aTokenAllocator) {
-  }
-
-  ~nsSpeculativeScriptThread() {
-    if (mThread) {
-      mThread->Shutdown();
-    }
-  }
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIRUNNABLE
-
-  nsresult StartParsing(nsParser *aParser);
-  void StopParsing(PRBool aFromDocWrite);
-
-  enum PrefetchType { SCRIPT, STYLESHEET, IMAGE };
-  struct PrefetchEntry {
-    PrefetchType type;
-    nsString uri;
-    nsString charset;
-    nsString elementType;
-  };
-
-  nsIDocument *GetDocument() {
-    NS_ASSERTION(NS_IsMainThread(), "Potential threadsafety hazard");
-    return mDocument;
-  }
-
-  PRBool Parsing() {
-    return mCurrentlyParsing;
-  }
-
-  CParserContext *Context() {
-    return mContext;
-  }
-
-  typedef nsDataHashtable<nsCStringHashKey, PRBool> PreloadedType;
-  PreloadedType& GetPreloadedURIs() {
-    return mPreloadedURIs;
-  }
-
-private:
-
-  nsresult ProcessToken(CToken *aToken);
-
-  void AddToPrefetchList(const nsAString &src,
-                         const nsAString &charset,
-                         const nsAString &elementType,
-                         PrefetchType type);
-
-  // The following members are shared across the main thread and the
-  // speculatively parsing thread.
-  Holder<PRLock> mLock;
-  Holder<PRCondVar> mCVar;
-
-  PRUint32 mKeepParsing;
-  PRUint32 mCurrentlyParsing;
-  nsRefPtr<nsHTMLTokenizer> mTokenizer;
-  nsAutoPtr<nsScanner> mScanner;
-
-  enum { kBatchPrefetchURIs = 5 };
-  nsAutoTArray<PrefetchEntry, kBatchPrefetchURIs> mURIs;
-  PRUint16 mNumURIs;
-
-  // Number of characters consumed by the last speculative parse.
-  PRUint32 mNumConsumed;
-
-  // These members are only accessed on the main thread.
-  nsCOMPtr<nsIThread> mThread;
-  nsCOMPtr<nsIDocument> mDocument;
-  CParserContext *mContext;
-  PreloadedType mPreloadedURIs;
-
-  // These members are only accessed on the speculatively parsing thread.
-  nsTokenAllocator *mTokenAllocator;
-};
-
-class nsPreloadURIs : public nsIRunnable {
-public:
-  nsPreloadURIs(nsAutoTArray<nsSpeculativeScriptThread::PrefetchEntry, 5> &aURIs,
-                nsSpeculativeScriptThread *aScriptThread)
-    : mURIs(aURIs),
-      mScriptThread(aScriptThread) {
-  }
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIRUNNABLE
-
-  static void PreloadURIs(const nsAutoTArray<nsSpeculativeScriptThread::PrefetchEntry, 5> &aURIs,
-                          nsSpeculativeScriptThread *aScriptThread);
-
-private:
-  nsAutoTArray<nsSpeculativeScriptThread::PrefetchEntry, 5> mURIs;
-  nsRefPtr<nsSpeculativeScriptThread> mScriptThread;
-};
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsPreloadURIs, nsIRunnable)
-
-NS_IMETHODIMP
-nsPreloadURIs::Run()
-{
-  PreloadURIs(mURIs, mScriptThread);
-  return NS_OK;
-}
-
-void
-nsPreloadURIs::PreloadURIs(const nsAutoTArray<nsSpeculativeScriptThread::PrefetchEntry, 5> &aURIs,
-                           nsSpeculativeScriptThread *aScriptThread)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Touching non-threadsafe objects off thread");
-
-  nsIDocument *doc = aScriptThread->GetDocument();
-  NS_ASSERTION(doc, "We shouldn't have started preloading without a document");
-
-  // Note: Per the code in the HTML content sink, we should be keeping track
-  // of each <base href> as it comes. However, because we do our speculative
-  // parsing off the main thread, this is hard to emulate. For now, just load
-  // the URIs using the document's base URI at the potential cost of being
-  // wrong and having to re-load a given relative URI later.
-  nsIURI *base = doc->GetBaseURI();
-  const nsCString &charset = doc->GetDocumentCharacterSet();
-  nsSpeculativeScriptThread::PreloadedType &alreadyPreloaded =
-    aScriptThread->GetPreloadedURIs();
-  for (PRUint32 i = 0, e = aURIs.Length(); i < e; ++i) {
-    const nsSpeculativeScriptThread::PrefetchEntry &pe = aURIs[i];
-    if (pe.type != nsSpeculativeScriptThread::SCRIPT) {
-      continue;
-    }
-
-    nsCOMPtr<nsIURI> uri;
-    nsresult rv = NS_NewURI(getter_AddRefs(uri), pe.uri, charset.get(), base);
-    if (NS_FAILED(rv)) {
-      NS_WARNING("Failed to create a URI");
-      continue;
-    }
-
-    nsCAutoString spec;
-    uri->GetSpec(spec);
-    PRBool answer;
-    if (alreadyPreloaded.Get(spec, &answer)) {
-      // Already preloaded. Don't preload again.
-      continue;
-    }
-
-    alreadyPreloaded.Put(spec, PR_TRUE);
-
-    doc->ScriptLoader()->PreloadURI(uri, pe.charset, pe.elementType);
-  }
-}
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsSpeculativeScriptThread, nsIRunnable)
-
-NS_IMETHODIMP
-nsSpeculativeScriptThread::Run()
-{
-  nsScannerIterator start;
-  mScanner->CurrentPosition(start);
-  mTokenizer->WillTokenize(PR_FALSE, mTokenAllocator);
-  while (mKeepParsing) {
-    PRBool flushTokens = PR_FALSE;
-    nsresult rv = mTokenizer->ConsumeToken(*mScanner, flushTokens);
-    if (rv == kEOF) {
-      break;
-    }
-
-    // TODO Don't pop the tokens.
-    CToken *token;
-    while (mKeepParsing && NS_SUCCEEDED(rv) && (token = mTokenizer->PopToken())) {
-      rv = ProcessToken(token);
-    }
-  }
-  mTokenizer->DidTokenize(PR_FALSE);
-
-  nsAutoLock al(mLock.get());
-
-  nsScannerIterator end;
-  mScanner->CurrentPosition(end);
-
-  mNumConsumed = Distance(start, end);
-
-  mCurrentlyParsing = 0;
-  PR_NotifyCondVar(mCVar.get());
-  return NS_OK;
-}
-
-nsresult
-nsSpeculativeScriptThread::StartParsing(nsParser *aParser)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Called on the wrong thread");
-  NS_ASSERTION(!mCurrentlyParsing, "Bad race happening");
-
-  nsIContentSink *sink = aParser->GetContentSink();
-  if (!sink) {
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIDocument> doc = do_QueryInterface(sink->GetTarget());
-  if (!doc) {
-    return NS_OK;
-  }
-
-  nsAutoString toScan;
-  CParserContext *context = aParser->PeekContext();
-  if (!mThread) {
-    nsresult rv = NS_NewThread(getter_AddRefs(mThread), nsnull);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    mLock = PR_NewLock();
-    if (!mLock.get()) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    mCVar = PR_NewCondVar(mLock.get());
-    if (!mCVar.get()) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    if (!mPreloadedURIs.Init(15)) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    mTokenizer = new nsHTMLTokenizer(context->mDTDMode, context->mDocType,
-                                     context->mParserCommand, 0);
-    if (!mTokenizer) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-    mTokenizer->CopyState(context->mTokenizer);
-    context->mScanner->CopyUnusedData(toScan);
-  } else if (context == mContext) {
-    // Don't parse the same part of the document twice.
-    nsScannerIterator end;
-    context->mScanner->EndReading(end);
-
-    nsScannerIterator start;
-    context->mScanner->CurrentPosition(start);
-
-    if (mNumConsumed > context->mNumConsumed) {
-      // We consumed more the last time we tried speculatively parsing than we
-      // did the last time we actually parsed. 
-      PRUint32 distance = Distance(start, end);
-      start.advance(PR_MIN(mNumConsumed - context->mNumConsumed, distance));
-    }
-
-    if (start == end) {
-      // We're at the end of this context's buffer, nothing else to do.
-      return NS_OK;
-    }
-
-    CopyUnicodeTo(start, end, toScan);
-  } else {
-    // Grab all of the context.
-    context->mScanner->CopyUnusedData(toScan);
-    if (toScan.IsEmpty()) {
-      // Nothing to parse, don't do anything.
-      return NS_OK;
-    }
-  }
-
-  nsCAutoString charset;
-  PRInt32 source;
-  aParser->GetDocumentCharset(charset, source);
-
-  mScanner = new nsScanner(toScan, charset, source);
-  if (!mScanner) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  mDocument.swap(doc);
-  mKeepParsing = 1;
-  mCurrentlyParsing = 1;
-  mContext = context;
-  return mThread->Dispatch(this, nsIEventTarget::DISPATCH_NORMAL);
-}
-
-void
-nsSpeculativeScriptThread::StopParsing(PRBool aFromDocWrite)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Can't stop parsing from another thread");
-
-  if (!mThread) {
-    // If we bailed early out of StartParsing, don't do anything.
-    return;
-  }
-
-  {
-    nsAutoLock al(mLock.get());
-
-    mKeepParsing = 0;
-    if (mCurrentlyParsing) {
-      PR_WaitCondVar(mCVar.get(), PR_INTERVAL_NO_TIMEOUT);
-      NS_ASSERTION(!mCurrentlyParsing, "Didn't actually stop parsing?");
-    }
-  }
-
-  // The thread is now idle. It is now safe to touch mContext on the main
-  // thread.
-  if (mNumURIs) {
-    nsPreloadURIs::PreloadURIs(mURIs, this);
-    mNumURIs = 0;
-    mURIs.Clear();
-  }
-
-  // Note: Currently, we pop the tokens off (see the comment in Run) so this
-  // isn't a problem. If and when we actually use the tokens created
-  // off-thread, we'll need to use aFromDocWrite for real.
-  (void)aFromDocWrite;
-}
-
-nsresult
-nsSpeculativeScriptThread::ProcessToken(CToken *aToken)
-{
-  // Only called on the speculative script thread.
-
-  CHTMLToken *token = static_cast<CHTMLToken *>(aToken);
-  switch (static_cast<eHTMLTokenTypes>(token->GetTokenType())) {
-    case eToken_start: {
-        CStartToken *start = static_cast<CStartToken *>(aToken);
-        nsHTMLTag tag = static_cast<nsHTMLTag>(start->GetTypeID());
-        PRInt16 attrs = start->GetAttributeCount();
-        PRInt16 i = 0;
-        nsAutoString src;
-        nsAutoString elementType;
-        nsAutoString charset;
-        PrefetchType ptype;
-
-        switch (tag) {
-#if 0 // TODO Support stylesheet and image preloading.
-          case eHTMLTag_link: {
-            // If this is a <link rel=stylesheet> find the src.
-            PRBool isRelStylesheet = PR_FALSE;
-            for (; i < attrs; ++i) {
-              CAttributeToken *attr = static_cast<CAttributeToken *>(mTokenizer->PopToken());
-              NS_ASSERTION(attr->GetTokenType() == eToken_attribute, "Weird token");
-
-              if (attr->GetKey().EqualsLiteral("rel")) {
-                if (!attr->GetValue().EqualsLiteral("stylesheet")) {
-                  IF_FREE(attr, mTokenAllocator);
-                  break;
-                }
-                isRelStylesheet = PR_TRUE;
-              } else if (attr->GetKey().EqualsLiteral("src")) {
-                src.Assign(attr->GetValue());
-                if (isRelStylesheet) {
-                  IF_FREE(attr, mTokenAllocator);
-                  break;
-                }
-              }
-
-              IF_FREE(attr, mTokenAllocator);
-            }
-
-            if (isRelStylesheet && !src.IsEmpty()) {
-              AddToPrefetchList(src, STYLESHEET);
-            }
-            break;
-          }
-
-          case eHTMLTag_style:
-            ptype = STYLESHEET;
-          case eHTMLTag_img:
-            if (tag == eHTMLTag_img)
-              ptype = IMAGE;
-#endif
-          case eHTMLTag_script:
-            if (tag == eHTMLTag_script)
-              ptype = SCRIPT;
-
-            for (; i < attrs; ++i) {
-              CAttributeToken *attr = static_cast<CAttributeToken *>(mTokenizer->PopToken());
-              NS_ASSERTION(attr->GetTokenType() == eToken_attribute, "Weird token");
-
-              if (attr->GetKey().EqualsLiteral("src")) {
-                src.Assign(attr->GetValue());
-              } else if (attr->GetKey().EqualsLiteral("charset")) {
-                charset.Assign(attr->GetValue());
-              } else if (attr->GetKey().EqualsLiteral("type")) {
-                elementType.Assign(attr->GetValue());
-              }
-              IF_FREE(attr, mTokenAllocator);
-            }
-
-            if (!src.IsEmpty()) {
-              AddToPrefetchList(src, charset, elementType, ptype);
-            }
-            break;
-
-          default:
-            break;
-        }
-
-        for (; i < attrs; ++i) {
-          CToken *attr = mTokenizer->PopToken();
-          if (!attr) {
-            break;
-          }
-          NS_ASSERTION(attr->GetTokenType() == eToken_attribute, "Weird token");
-          IF_FREE(attr, mTokenAllocator);
-        }
-
-        break;
-      }
-
-    default:
-      break;
-  }
-
-  IF_FREE(aToken, mTokenAllocator);
-  return NS_OK;
-}
-
-void
-nsSpeculativeScriptThread::AddToPrefetchList(const nsAString &src,
-                                      const nsAString &charset,
-                                      const nsAString &elementType,
-                                      PrefetchType type)
-{
-  PrefetchEntry *pe = mURIs.InsertElementAt(mNumURIs++);
-  pe->type = type;
-  pe->uri = src;
-  pe->charset = charset;
-  pe->elementType = elementType;
-
-  if (mNumURIs == kBatchPrefetchURIs) {
-    nsCOMPtr<nsIRunnable> r = new nsPreloadURIs(mURIs, this);
-
-    mNumURIs = 0;
-    mURIs.Clear();
-    NS_DispatchToMainThread(r, NS_DISPATCH_NORMAL);
-  }
-}
-
 nsICharsetAlias* nsParser::sCharsetAliasService = nsnull;
 nsICharsetConverterManager* nsParser::sCharsetConverterManager = nsnull;
 
 /**
  *  This gets called when the htmlparser module is initialized.
  */
 // static
 nsresult
@@ -796,20 +316,16 @@ nsParser::Cleanup()
     delete mParserContext;
     mParserContext = pc;
   }
 
   // It should not be possible for this flag to be set when we are getting
   // destroyed since this flag implies a pending nsParserContinueEvent, which
   // has an owning reference to |this|.
   NS_ASSERTION(!(mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT), "bad");
-  if (mSpeculativeScriptThread) {
-    mSpeculativeScriptThread->StopParsing(PR_FALSE);
-    mSpeculativeScriptThread = nsnull;
-  }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsParser)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsParser)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSink)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mObserver)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -1486,36 +1002,16 @@ nsParser::DidBuildModel(nsresult anError
       //Ref. to bug 61462.
       mParserContext->mRequest = 0;
     }
   }
 
   return result;
 }
 
-void
-nsParser::SpeculativelyParse()
-{
-  if (mParserContext->mParserCommand == eViewNormal &&
-      !mParserContext->mMimeType.EqualsLiteral("text/html")) {
-    return;
-  }
-
-  if (!mSpeculativeScriptThread) {
-    mSpeculativeScriptThread = new nsSpeculativeScriptThread(&mTokenAllocator);
-    if (!mSpeculativeScriptThread) {
-      return;
-    }
-  }
-
-  nsresult rv = mSpeculativeScriptThread->StartParsing(this);
-  if (NS_FAILED(rv)) {
-    mSpeculativeScriptThread = nsnull;
-  }
-}
 
 /**
  * This method adds a new parser context to the list,
  * pushing the current one to the next position.
  *
  * @param   ptr to new context
  */
 void
@@ -1606,19 +1102,16 @@ nsParser::Terminate(void)
   mInternalState = result = NS_ERROR_HTMLPARSER_STOPPARSING;
 
   // CancelParsingEvents must be called to avoid leaking the nsParser object
   // @see bug 108049
   // If NS_PARSER_FLAG_PENDING_CONTINUE_EVENT is set then CancelParsingEvents
   // will reset it so DidBuildModel will call DidBuildModel on the DTD. Note:
   // The IsComplete() call inside of DidBuildModel looks at the pendingContinueEvents flag.
   CancelParsingEvents();
-  if (mSpeculativeScriptThread) {
-    mSpeculativeScriptThread->StopParsing(PR_FALSE);
-  }
 
   // If we got interrupted in the middle of a document.write, then we might
   // have more than one parser context on our parsercontext stack. This has
   // the effect of making DidBuildModel a no-op, meaning that we never call
   // our sink's DidBuildModel and break the reference cycle, causing a leak.
   // Since we're getting terminated, we manually clean up our context stack.
   while (mParserContext && mParserContext->mPrevContext) {
     CParserContext *prev = mParserContext->mPrevContext;
@@ -1665,20 +1158,16 @@ nsParser::ContinueInterruptedParsing()
   nsCOMPtr<nsIParser> kungFuDeathGrip(this);
 
 #ifdef DEBUG
   if (!(mFlags & NS_PARSER_FLAG_PARSER_ENABLED)) {
     NS_WARNING("Don't call ContinueInterruptedParsing on a blocked parser.");
   }
 #endif
 
-  if (mSpeculativeScriptThread) {
-    mSpeculativeScriptThread->StopParsing(PR_FALSE);
-  }
-
   PRBool isFinalChunk = mParserContext &&
                         mParserContext->mStreamListenerState == eOnStop;
 
   result = ResumeParse(PR_TRUE, isFinalChunk); // Ref. bug 57999
 
   if (result != NS_OK) {
     result=mInternalState;
   }
@@ -1801,17 +1290,16 @@ nsParser::SetCanInterrupt(PRBool aCanInt
 NS_IMETHODIMP
 nsParser::Parse(nsIURI* aURL,
                 nsIRequestObserver* aListener,
                 void* aKey,
                 nsDTDMode aMode)
 {
 
   NS_PRECONDITION(aURL, "Error: Null URL given");
-  NS_ASSERTION(!mSpeculativeScriptThread, "Can't reuse a parser like this");
 
   nsresult result=kBadURL;
   mObserver = aListener;
 
   if (aURL) {
     nsCAutoString spec;
     nsresult rv = aURL->GetSpec(spec);
     if (rv != NS_OK) {
@@ -1869,20 +1357,16 @@ nsParser::Parse(const nsAString& aSource
     // Nothing is being passed to the parser so return
     // immediately. mUnusedInput will get processed when
     // some data is actually passed in.
     // But if this is the last call, make sure to finish up
     // stuff correctly.
     return result;
   }
 
-  if (mSpeculativeScriptThread) {
-    mSpeculativeScriptThread->StopParsing(PR_TRUE);
-  }
-
   // Hack to pass on to the dtd the caller's desire to
   // parse a fragment without worrying about containment rules
   if (aMode == eDTDMode_fragment)
     mCommand = eViewFragment;
 
   // Maintain a reference to ourselves so we don't go away
   // till we're completely done.
   nsCOMPtr<nsIParser> kungFuDeathGrip(this);
@@ -1993,18 +1477,16 @@ nsParser::ParseFragment(const nsAString&
   nsresult result = NS_OK;
   nsAutoString  theContext;
   PRUint32 theCount = aTagStack.Length();
   PRUint32 theIndex = 0;
 
   // Disable observers for fragments
   mFlags &= ~NS_PARSER_FLAG_OBSERVERS_ENABLED;
 
-  NS_ASSERTION(!mSpeculativeScriptThread, "Can't reuse a parser like this");
-
   for (theIndex = 0; theIndex < theCount; theIndex++) {
     theContext.AppendLiteral("<");
     theContext.Append(aTagStack[theCount - theIndex - 1]);
     theContext.AppendLiteral(">");
   }
 
   if (theCount == 0) {
     // Ensure that the buffer is not empty. Because none of the DTDs care
@@ -2135,18 +1617,16 @@ nsParser::ResumeParse(PRBool allowIterat
 {
   nsresult result = NS_OK;
 
   if ((mFlags & NS_PARSER_FLAG_PARSER_ENABLED) &&
       mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
     MOZ_TIMER_DEBUGLOG(("Start: Parse Time: nsParser::ResumeParse(), this=%p\n", this));
     MOZ_TIMER_START(mParseTime);
 
-    NS_ASSERTION(!mSpeculativeScriptThread || !mSpeculativeScriptThread->Parsing(), "Bad races happening");
-
     result = WillBuildModel(mParserContext->mScanner->GetFilename());
     if (NS_FAILED(result)) {
       mFlags &= ~NS_PARSER_FLAG_CAN_TOKENIZE;
       return result;
     }
 
     if (mParserContext->mDTD) {
       mParserContext->mDTD->WillResumeParse(mSink);
@@ -2186,17 +1666,16 @@ nsParser::ResumeParse(PRBool allowIterat
         // If we're told to block the parser, we disable all further parsing
         // (and cache any data coming in) until the parser is re-enabled.
         if (NS_ERROR_HTMLPARSER_BLOCK == result) {
           if (mParserContext->mDTD) {
             mParserContext->mDTD->WillInterruptParse(mSink);
           }
 
           BlockParser();
-          SpeculativelyParse();
           return NS_OK;
         }
         if (NS_ERROR_HTMLPARSER_STOPPARSING == result) {
           // Note: Parser Terminate() calls DidBuildModel.
           if (mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
             DidBuildModel(mStreamStatus);
             mInternalState = result;
           }
@@ -2776,21 +2255,16 @@ nsParser::OnDataAvailable(nsIRequest *re
 
   while (theContext && theContext->mRequest != request) {
     theContext = theContext->mPrevContext;
   }
 
   if (theContext) {
     theContext->mStreamListenerState = eOnDataAvail;
 
-    if ((mFlags & NS_PARSER_FLAG_PARSER_ENABLED) &&
-        mSpeculativeScriptThread) {
-      mSpeculativeScriptThread->StopParsing(PR_FALSE);
-    }
-
     if (eInvalidDetect == theContext->mAutoDetectStatus) {
       if (theContext->mScanner) {
         nsScannerIterator iter;
         theContext->mScanner->EndReading(iter);
         theContext->mScanner->SetPosition(iter, PR_TRUE);
       }
     }
 
@@ -2825,20 +2299,16 @@ nsParser::OnDataAvailable(nsIRequest *re
  *  has been collected from the net.
  */
 nsresult
 nsParser::OnStopRequest(nsIRequest *request, nsISupports* aContext,
                         nsresult status)
 {
   nsresult rv = NS_OK;
 
-  if (mSpeculativeScriptThread) {
-    mSpeculativeScriptThread->StopParsing(PR_FALSE);
-  }
-
   if (eOnStart == mParserContext->mStreamListenerState) {
     // If you're here, then OnDataAvailable() never got called.  Prior
     // to necko, we never dealt with this case, but the problem may
     // have existed.  Everybody can live with an empty input stream, so
     // just resume parsing.
     rv = ResumeParse(PR_TRUE, PR_TRUE);
   }
 
@@ -2942,38 +2412,36 @@ nsresult nsParser::Tokenize(PRBool aIsFi
       // Reset since the tokens have been flushed.
       mFlags &= ~NS_PARSER_FLAG_FLUSH_TOKENS;
     }
 
     PRBool flushTokens = PR_FALSE;
 
     MOZ_TIMER_START(mTokenizeTime);
 
-    mParserContext->mNumConsumed = 0;
-
     WillTokenize(aIsFinalChunk);
     while (NS_SUCCEEDED(result)) {
-      mParserContext->mNumConsumed += mParserContext->mScanner->Mark();
+      mParserContext->mScanner->Mark();
       result = theTokenizer->ConsumeToken(*mParserContext->mScanner,
                                           flushTokens);
       if (NS_FAILED(result)) {
         mParserContext->mScanner->RewindToMark();
         if (kEOF == result){
           break;
         }
         if (NS_ERROR_HTMLPARSER_STOPPARSING == result) {
           result = Terminate();
           break;
         }
       } else if (flushTokens && (mFlags & NS_PARSER_FLAG_OBSERVERS_ENABLED)) {
         // I added the extra test of NS_PARSER_FLAG_OBSERVERS_ENABLED to fix Bug# 23931.
         // Flush tokens on seeing </SCRIPT> -- Ref: Bug# 22485 --
         // Also remember to update the marked position.
         mFlags |= NS_PARSER_FLAG_FLUSH_TOKENS;
-        mParserContext->mNumConsumed += mParserContext->mScanner->Mark();
+        mParserContext->mScanner->Mark();
         break;
       }
     }
     DidTokenize(aIsFinalChunk);
 
     MOZ_TIMER_STOP(mTokenizeTime);
   } else {
     result = mInternalState = NS_ERROR_HTMLPARSER_BADTOKENIZER;
--- a/parser/htmlparser/src/nsParser.h
+++ b/parser/htmlparser/src/nsParser.h
@@ -90,17 +90,16 @@
 #include "nsIUnicharStreamListener.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsICharsetConverterManager;
 class nsICharsetAlias;
 class nsIDTD;
 class nsScanner;
 class nsIProgressEventSink;
-class nsSpeculativeScriptThread;
 
 #ifdef _MSC_VER
 #pragma warning( disable : 4275 )
 #endif
 
 
 class nsParser : public nsIParser,
                  public nsIStreamListener{
@@ -402,19 +401,17 @@ class nsParser : public nsIParser,
 
     /**
      * 
      * @update	gess5/18/98
      * @param 
      * @return
      */
     nsresult DidBuildModel(nsresult anErrorCode);
-
-    void SpeculativelyParse();
-
+    
 private:
 
     /*******************************************
       These are the tokenization methods...
      *******************************************/
 
     /**
      *  Part of the code sandwich, this gets called right before
@@ -455,17 +452,16 @@ protected:
     // And now, some data members...
     //*********************************************
     
       
     CParserContext*              mParserContext;
     nsCOMPtr<nsIRequestObserver> mObserver;
     nsCOMPtr<nsIContentSink>     mSink;
     nsIRunnable*                 mContinueEvent;  // weak ref
-    nsRefPtr<nsSpeculativeScriptThread> mSpeculativeScriptThread;
    
     nsCOMPtr<nsIParserFilter> mParserFilter;
     nsTokenAllocator          mTokenAllocator;
     
     eParserCommands     mCommand;
     nsresult            mInternalState;
     PRInt32             mStreamStatus;
     PRInt32             mCharsetSource;
--- a/parser/htmlparser/src/nsScanner.cpp
+++ b/parser/htmlparser/src/nsScanner.cpp
@@ -141,25 +141,26 @@ nsScanner::nsScanner(nsString& aFilename
   mFirstNonWhitespacePosition = -1;
   mCountRemaining = 0;
 
   mUnicodeDecoder = 0;
   mCharsetSource = kCharsetUninitialized;
   SetDocumentCharset(aCharset, aSource);
 }
 
-nsresult nsScanner::SetDocumentCharset(const nsACString& aCharset , PRInt32 aSource)
-{
-  if (aSource < mCharsetSource) // priority is lower the the current one , just
-    return NS_OK;
+nsresult nsScanner::SetDocumentCharset(const nsACString& aCharset , PRInt32 aSource) {
+
+  nsresult res = NS_OK;
+
+  if( aSource < mCharsetSource) // priority is lower the the current one , just
+    return res;
 
   nsICharsetAlias* calias = nsParser::GetCharsetAliasService();
   NS_ASSERTION(calias, "Must have the charset alias service!");
 
-  nsresult res = NS_OK;
   if (!mCharset.IsEmpty())
   {
     PRBool same;
     res = calias->Equals(aCharset, mCharset, &same);
     if(NS_SUCCEEDED(res) && same)
     {
       return NS_OK; // no difference, don't change it
     }
@@ -179,18 +180,27 @@ nsresult nsScanner::SetDocumentCharset(c
     mCharset.Assign(charsetName);
   }
 
   mCharsetSource = aSource;
 
   NS_ASSERTION(nsParser::GetCharsetConverterManager(),
                "Must have the charset converter manager!");
 
-  return nsParser::GetCharsetConverterManager()->
-    GetUnicodeDecoderRaw(mCharset.get(), getter_AddRefs(mUnicodeDecoder));
+  nsIUnicodeDecoder * decoder = nsnull;
+  res = nsParser::GetCharsetConverterManager()->
+    GetUnicodeDecoderRaw(mCharset.get(), &decoder);
+  if(NS_SUCCEEDED(res) && (nsnull != decoder))
+  {
+     NS_IF_RELEASE(mUnicodeDecoder);
+
+     mUnicodeDecoder = decoder;
+  }
+
+  return res;
 }
 
 
 /**
  *  default destructor
  *  
  *  @update  gess 3/25/98
  *  @param   
@@ -198,16 +208,18 @@ nsresult nsScanner::SetDocumentCharset(c
  */
 nsScanner::~nsScanner() {
 
   if (mSlidingBuffer) {
     delete mSlidingBuffer;
   }
 
   MOZ_COUNT_DTOR(nsScanner);
+
+  NS_IF_RELEASE(mUnicodeDecoder);
 }
 
 /**
  *  Resets current offset position of input stream to marked position. 
  *  This allows us to back up to this point if the need should arise, 
  *  such as when tokenization gets interrupted.
  *  NOTE: IT IS REALLY BAD FORM TO CALL RELEASE WITHOUT CALLING MARK FIRST!
  *
@@ -227,31 +239,24 @@ void nsScanner::RewindToMark(void){
  *  Records current offset position in input stream. This allows us
  *  to back up to this point if the need should arise, such as when
  *  tokenization gets interrupted.
  *
  *  @update  gess 7/29/98
  *  @param   
  *  @return  
  */
-PRInt32 nsScanner::Mark() {
-  PRInt32 distance = 0;
+void nsScanner::Mark() {
   if (mSlidingBuffer) {
-    nsScannerIterator oldStart;
-    mSlidingBuffer->BeginReading(oldStart);
-
-    distance = Distance(oldStart, mCurrentPosition);
-
     mSlidingBuffer->DiscardPrefix(mCurrentPosition);
     mSlidingBuffer->BeginReading(mCurrentPosition);
     mMarkPosition = mCurrentPosition;
   }
-
-  return distance;
 }
+ 
 
 /** 
  * Insert data to our underlying input buffer as
  * if it were read from an input stream.
  *
  * @update  harishd 01/12/99
  * @return  error code 
  */
--- a/parser/htmlparser/src/nsScanner.h
+++ b/parser/htmlparser/src/nsScanner.h
@@ -202,17 +202,17 @@ class nsScanner {
        *  Records current offset position in input stream. This allows us
        *  to back up to this point if the need should arise, such as when
        *  tokenization gets interrupted.
        *  
        *  @update  gess 5/12/98
        *  @param   
        *  @return  
        */
-      PRInt32 Mark(void);
+      void Mark(void);
 
       /**
        *  Resets current offset position of input stream to marked position. 
        *  This allows us to back up to this point if the need should arise, 
        *  such as when tokenization gets interrupted.
        *  NOTE: IT IS REALLY BAD FORM TO CALL RELEASE WITHOUT CALLING MARK FIRST!
        *  
        *  @update  gess 5/12/98
@@ -333,18 +333,15 @@ class nsScanner {
       nsScannerIterator            mEndPosition;     // The current end of the scanner buffer
       nsString        mFilename;
       PRUint32        mCountRemaining; // The number of bytes still to be read
                                        // from the scanner buffer
       PRPackedBool    mIncremental;
       PRInt32         mFirstNonWhitespacePosition;
       PRInt32         mCharsetSource;
       nsCString       mCharset;
-      nsCOMPtr<nsIUnicodeDecoder> mUnicodeDecoder;
+      nsIUnicodeDecoder *mUnicodeDecoder;
       nsParser        *mParser;
-
-  private:
-      nsScanner &operator =(const nsScanner &); // Not implemented.
 };
 
 #endif