Bug 717203 - Remove obsolete speculative parsing code. r=mrbkap.
authorHenri Sivonen <hsivonen@iki.fi>
Wed, 11 Jan 2012 17:49:57 +0200
changeset 84290 39e49fcaed223e445a19760bb3974a3958b56178
parent 84289 418f713f7092d824aac7798069886318c1a92259
child 84291 dc3f10e2e734bc0b4dd389d60ad536644f09c74d
push id21839
push usermbrubeck@mozilla.com
push dateThu, 12 Jan 2012 16:24:29 +0000
treeherdermozilla-central@fb5bcf9ae739 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs717203
milestone12.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 717203 - Remove obsolete speculative parsing code. r=mrbkap.
parser/htmlparser/src/nsParser.cpp
parser/htmlparser/src/nsParser.h
--- a/parser/htmlparser/src/nsParser.cpp
+++ b/parser/htmlparser/src/nsParser.cpp
@@ -157,513 +157,18 @@ 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()
-    : mLock("nsSpeculativeScriptThread.mLock"),
-      mCVar(mLock, "nsSpeculativeScriptThread.mCVar"),
-      mKeepParsing(false),
-      mCurrentlyParsing(false),
-      mNumConsumed(0),
-      mContext(nsnull),
-      mTerminated(false) {
-  }
-
-  ~nsSpeculativeScriptThread() {
-    NS_ASSERTION(NS_IsMainThread() || !mDocument,
-                 "Destroying the document on the wrong thread");
-  }
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIRUNNABLE
-
-  nsresult StartParsing(nsParser *aParser);
-  void StopParsing(bool aFromDocWrite);
-
-  enum PrefetchType { NONE, SCRIPT, STYLESHEET, IMAGE };
-  struct PrefetchEntry {
-    PrefetchType type;
-    nsString uri;
-    nsString charset;
-    nsString elementType;
-  };
-
-  nsIDocument *GetDocument() {
-    NS_ASSERTION(NS_IsMainThread(), "Potential threadsafety hazard");
-    return mDocument;
-  }
-
-  bool Parsing() {
-    return mCurrentlyParsing;
-  }
-
-  CParserContext *Context() {
-    return mContext;
-  }
-
-  typedef nsDataHashtable<nsCStringHashKey, bool> PreloadedType;
-  PreloadedType& GetPreloadedURIs() {
-    return mPreloadedURIs;
-  }
-
-  void Terminate() {
-    mTerminated = true;
-    StopParsing(false);
-  }
-  bool Terminated() {
-    return mTerminated;
-  }
-
-private:
-
-  void ProcessToken(CToken *aToken);
-
-  void AddToPrefetchList(const nsAString &src,
-                         const nsAString &charset,
-                         const nsAString &elementType,
-                         PrefetchType type);
-
-  void FlushURIs();
-
-  // These members are only accessed on the speculatively parsing thread.
-  nsTokenAllocator mTokenAllocator;
-
-  // The following members are shared across the main thread and the
-  // speculatively parsing thread.
-  Mutex mLock;
-  CondVar mCVar;
-
-  volatile bool mKeepParsing;
-  volatile bool mCurrentlyParsing;
-  nsRefPtr<nsHTMLTokenizer> mTokenizer;
-  nsAutoPtr<nsScanner> mScanner;
-
-  enum { kBatchPrefetchURIs = 5 };
-  nsAutoTArray<PrefetchEntry, kBatchPrefetchURIs> mURIs;
-
-  // Number of characters consumed by the last speculative parse.
-  PRUint32 mNumConsumed;
-
-  // These members are only accessed on the main thread.
-  nsCOMPtr<nsIDocument> mDocument;
-  CParserContext *mContext;
-  PreloadedType mPreloadedURIs;
-  bool mTerminated;
-};
-
-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");
-
-  if (aScriptThread->Terminated()) {
-    return;
-  }
-
-  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->GetDocBaseURI();
-  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];
-    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);
-    bool answer;
-    if (alreadyPreloaded.Get(spec, &answer)) {
-      // Already preloaded. Don't preload again.
-      continue;
-    }
-
-    alreadyPreloaded.Put(spec, true);
-
-    switch (pe.type) {
-      case nsSpeculativeScriptThread::SCRIPT:
-        doc->ScriptLoader()->PreloadURI(uri, pe.charset, pe.elementType);
-        break;
-      case nsSpeculativeScriptThread::IMAGE:
-        doc->MaybePreLoadImage(uri, EmptyString());
-        break;
-      case nsSpeculativeScriptThread::STYLESHEET:
-        doc->PreloadStyle(uri, pe.charset);
-        break;
-      case nsSpeculativeScriptThread::NONE:
-        NS_NOTREACHED("Uninitialized preload entry?");
-        break;
-    }
-  }
-}
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsSpeculativeScriptThread, nsIRunnable)
-
-NS_IMETHODIMP
-nsSpeculativeScriptThread::Run()
-{
-  NS_ASSERTION(!NS_IsMainThread(), "Speculative parsing on the main thread?");
-
-  mNumConsumed = 0;
-
-  mTokenizer->WillTokenize(false, &mTokenAllocator);
-  while (mKeepParsing) {
-    bool flushTokens = false;
-    nsresult rv = mTokenizer->ConsumeToken(*mScanner, flushTokens);
-    if (NS_FAILED(rv)) {
-      break;
-    }
-
-    mNumConsumed += mScanner->Mark();
-
-    // TODO Don't pop the tokens.
-    CToken *token;
-    while (mKeepParsing && (token = mTokenizer->PopToken())) {
-      ProcessToken(token);
-    }
-  }
-  mTokenizer->DidTokenize(false);
-
-  if (mKeepParsing) {
-    // Ran out of room in this part of the document -- flush out the URIs we
-    // gathered so far so we don't end up waiting for the parser's current
-    // load to finish.
-    if (!mURIs.IsEmpty()) {
-      FlushURIs();
-    }
-  }
-
-  {
-    MutexAutoLock al(mLock);
-
-    mCurrentlyParsing = false;
-    mCVar.Notify();
-  }
-  return NS_OK;
-}
-
-nsresult
-nsSpeculativeScriptThread::StartParsing(nsParser *aParser)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Called on the wrong thread");
-  NS_ASSERTION(!mCurrentlyParsing, "Bad race happening");
-
-  if (!aParser->ThreadPool()) {
-    return NS_OK;
-  }
-
-  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 (!mTokenizer) {
-    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);
-    if (toScan.IsEmpty()) {
-      return NS_OK;
-    }
-  } 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(NS_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;
-  }
-  mScanner->SetIncremental(true);
-
-  mDocument.swap(doc);
-  mKeepParsing = true;
-  mCurrentlyParsing = true;
-  mContext = context;
-  return aParser->ThreadPool()->Dispatch(this, NS_DISPATCH_NORMAL);
-}
-
-void
-nsSpeculativeScriptThread::StopParsing(bool /*aFromDocWrite*/)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Can't stop parsing from another thread");
-
-  {
-    MutexAutoLock al(mLock);
-
-    mKeepParsing = false;
-    if (mCurrentlyParsing) {
-      mCVar.Wait();
-      NS_ASSERTION(!mCurrentlyParsing, "Didn't actually stop parsing?");
-    }
-  }
-
-  // The thread is now idle.
-  if (mTerminated) {
-    // If we're terminated, then we need to ensure that we release our document
-    // and tokenizer here on the main thread so that our last reference to them
-    // isn't our alter-ego rescheduled on another thread.
-    mDocument = nsnull;
-    mTokenizer = nsnull;
-    mScanner = nsnull;
-  } else if (mURIs.Length()) {
-    // Note: Don't do this if we're terminated.
-    nsPreloadURIs::PreloadURIs(mURIs, this);
-    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
-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;
-        nsAutoString href;
-        nsAutoString rel;
-        PrefetchType ptype = NONE;
-
-        switch (tag) {
-          case eHTMLTag_link:
-              ptype = STYLESHEET;
-              break;
-
-          case eHTMLTag_img:
-              ptype = IMAGE;
-              break;
-
-          case eHTMLTag_script:
-              ptype = SCRIPT;
-              break;
-
-          default:
-              break;
-        }
-
-        // We currently handle the following element/attribute combos :
-        //     <link rel="stylesheet" href= charset= type>
-        //     <script src= charset= type=>
-        if (ptype != NONE) {
-            // loop over all attributes to extract relevant info
-            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("href")) {
-                href.Assign(attr->GetValue());
-              } else if (attr->GetKey().EqualsLiteral("rel")) {
-                rel.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);
-            }
-
-            // ensure we have the right kind if it's a link-element
-            if (ptype == STYLESHEET) {
-              if (rel.EqualsLiteral("stylesheet")) {
-                src = href; // src is the important variable below
-              } else {
-                src.Truncate(); // clear src if wrong kind of link
-              }
-            }
-
-            // add to list if we have a valid src
-            if (!src.IsEmpty()) {
-              AddToPrefetchList(src, charset, elementType, ptype);
-            }
-        } else {
-            // Irrelevant tag, but pop and free all its attributes in any case
-            for (; i < attrs ; ++i) {
-              CToken *attr = mTokenizer->PopToken();
-              IF_FREE(attr, &mTokenAllocator);
-            }
-        }
-        break;
-      }
-
-    default:
-      break;
-  }
-
-  IF_FREE(aToken, &mTokenAllocator);
-}
-
-void
-nsSpeculativeScriptThread::AddToPrefetchList(const nsAString &src,
-                                             const nsAString &charset,
-                                             const nsAString &elementType,
-                                             PrefetchType type)
-{
-  PrefetchEntry *pe = mURIs.AppendElement();
-  pe->type = type;
-  pe->uri = src;
-  pe->charset = charset;
-  pe->elementType = elementType;
-
-  if (mURIs.Length() == kBatchPrefetchURIs) {
-    FlushURIs();
-  }
-}
-
-void
-nsSpeculativeScriptThread::FlushURIs()
-{
-  nsCOMPtr<nsIRunnable> r = new nsPreloadURIs(mURIs, this);
-  if (!r) {
-    return;
-  }
-
-  mURIs.Clear();
-  NS_DispatchToMainThread(r, NS_DISPATCH_NORMAL);
-}
-
 nsICharsetAlias* nsParser::sCharsetAliasService = nsnull;
 nsICharsetConverterManager* nsParser::sCharsetConverterManager = nsnull;
-nsIThreadPool* nsParser::sSpeculativeThreadPool = nsnull;
 
 /**
  *  This gets called when the htmlparser module is initialized.
  */
 // static
 nsresult
 nsParser::Init()
 {
@@ -675,47 +180,28 @@ nsParser::Init()
 
   nsCOMPtr<nsICharsetConverterManager> charsetConverter =
     do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   charsetAlias.swap(sCharsetAliasService);
   charsetConverter.swap(sCharsetConverterManager);
 
-  nsCOMPtr<nsIThreadPool> threadPool =
-    do_CreateInstance(NS_THREADPOOL_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = threadPool->SetThreadLimit(kSpeculativeThreadLimit);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = threadPool->SetIdleThreadLimit(kIdleThreadLimit);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = threadPool->SetIdleThreadTimeout(kIdleThreadTimeout);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  threadPool.swap(sSpeculativeThreadPool);
-
   return NS_OK;
 }
 
 
 /**
  *  This gets called when the htmlparser module is shutdown.
  */
 // static
 void nsParser::Shutdown()
 {
   NS_IF_RELEASE(sCharsetAliasService);
   NS_IF_RELEASE(sCharsetConverterManager);
-  if (sSpeculativeThreadPool) {
-    sSpeculativeThreadPool->Shutdown();
-    NS_RELEASE(sSpeculativeThreadPool);
-  }
 }
 
 #ifdef DEBUG
 static bool gDumpContent=false;
 #endif
 
 /**
  *  default constructor
@@ -790,20 +276,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->Terminate();
-    mSpeculativeScriptThread = nsnull;
-  }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsParser)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsParser)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDTD)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSink)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mObserver)
@@ -1522,48 +1004,22 @@ nsParser::DidBuildModel(nsresult anError
         // DTD was to NS_ENSURE_SUCCESS the sink DidBuildModel call, so if the
         // sink returns failure we should use sinkResult instead of dtdResult,
         // to preserve the old error handling behavior of the DTD:
         result = NS_FAILED(sinkResult) ? sinkResult : dtdResult;
       }
 
       //Ref. to bug 61462.
       mParserContext->mRequest = 0;
-
-      if (mSpeculativeScriptThread) {
-        mSpeculativeScriptThread->Terminate();
-        mSpeculativeScriptThread = nsnull;
-      }
     }
   }
 
   return result;
 }
 
-void
-nsParser::SpeculativelyParse()
-{
-  if (mParserContext->mParserCommand == eViewNormal &&
-      !mParserContext->mMimeType.EqualsLiteral("text/html")) {
-    return;
-  }
-
-  if (!mSpeculativeScriptThread) {
-    mSpeculativeScriptThread = new nsSpeculativeScriptThread();
-    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
 nsParser::PushContext(CParserContext& aContext)
@@ -1655,20 +1111,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->Terminate();
-    mSpeculativeScriptThread = nsnull;
-  }
 
   // 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;
@@ -1707,20 +1159,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(false);
-  }
-
   bool isFinalChunk = mParserContext &&
                         mParserContext->mStreamListenerState == eOnStop;
 
   mProcessingNetworkData = true;
   if (mSink) {
     mSink->WillParse();
   }
   result = ResumeParse(true, isFinalChunk); // Ref. bug 57999
@@ -1845,17 +1293,16 @@ nsParser::SetCanInterrupt(bool aCanInter
 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) {
@@ -1907,20 +1354,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(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);
@@ -2022,18 +1465,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
@@ -2141,18 +1582,16 @@ nsParser::ParseFragment(const nsAString&
 nsresult
 nsParser::ResumeParse(bool allowIteration, bool aIsFinalChunk,
                       bool aCanInterrupt)
 {
   nsresult result = NS_OK;
 
   if ((mFlags & NS_PARSER_FLAG_PARSER_ENABLED) &&
       mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
-    NS_ASSERTION(!mSpeculativeScriptThread || !mSpeculativeScriptThread->Parsing(),
-                 "Bad races happening, expect to crash!");
 
     result = WillBuildModel(mParserContext->mScanner->GetFilename());
     if (NS_FAILED(result)) {
       mFlags &= ~NS_PARSER_FLAG_CAN_TOKENIZE;
       return result;
     }
 
     if (mDTD) {
@@ -2192,17 +1631,16 @@ nsParser::ResumeParse(bool allowIteratio
 
         // 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) {
           mSink->WillInterrupt();
           if (mFlags & NS_PARSER_FLAG_PARSER_ENABLED) {
             // If we were blocked by a recursive invocation, don't re-block.
             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;
@@ -2713,21 +2151,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(false);
-    }
-
     if (eInvalidDetect == theContext->mAutoDetectStatus) {
       if (theContext->mScanner) {
         nsScannerIterator iter;
         theContext->mScanner->EndReading(iter);
         theContext->mScanner->SetPosition(iter, true);
       }
     }
 
@@ -2767,21 +2200,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 ((mFlags & NS_PARSER_FLAG_PARSER_ENABLED) &&
-      mSpeculativeScriptThread) {
-    mSpeculativeScriptThread->StopParsing(false);
-  }
-
   CParserContext *pc = mParserContext;
   while (pc) {
     if (pc->mRequest == request) {
       pc->mStreamListenerState = eOnStop;
       pc->mScanner->SetIncremental(false);
       break;
     }
 
--- a/parser/htmlparser/src/nsParser.h
+++ b/parser/htmlparser/src/nsParser.h
@@ -87,17 +87,16 @@
 #include "nsCOMArray.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsWeakReference.h"
 
 class nsICharsetConverterManager;
 class nsICharsetAlias;
 class nsIDTD;
 class nsScanner;
-class nsSpeculativeScriptThread;
 class nsIThreadPool;
 
 #ifdef _MSC_VER
 #pragma warning( disable : 4275 )
 #endif
 
 
 class nsParser : public nsIParser,
@@ -375,20 +374,16 @@ class nsParser : public nsIParser,
       return sCharsetConverterManager;
     }
 
     virtual void Reset() {
       Cleanup();
       Initialize();
     }
 
-    nsIThreadPool* ThreadPool() {
-      return sSpeculativeThreadPool;
-    }
-
     bool IsScriptExecuting() {
       return mSink && mSink->IsScriptExecuting();
     }
 
     bool IsOkToProcessNetworkData() {
       return !IsScriptExecuting() && !mProcessingNetworkData;
     }
 
@@ -408,18 +403,16 @@ 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
@@ -460,17 +453,16 @@ protected:
     //*********************************************
     
       
     CParserContext*              mParserContext;
     nsCOMPtr<nsIDTD>             mDTD;
     nsCOMPtr<nsIRequestObserver> mObserver;
     nsCOMPtr<nsIContentSink>     mSink;
     nsIRunnable*                 mContinueEvent;  // weak ref
-    nsRefPtr<nsSpeculativeScriptThread> mSpeculativeScriptThread;
    
     nsTokenAllocator          mTokenAllocator;
     
     eParserCommands     mCommand;
     nsresult            mInternalState;
     PRInt32             mStreamStatus;
     PRInt32             mCharsetSource;
     
@@ -479,19 +471,12 @@ protected:
     nsString            mUnusedInput;
     nsCString           mCharset;
     nsCString           mCommandStr;
 
     bool                mProcessingNetworkData;
 
     static nsICharsetAlias*            sCharsetAliasService;
     static nsICharsetConverterManager* sCharsetConverterManager;
-    static nsIThreadPool*              sSpeculativeThreadPool;
-
-    enum {
-      kSpeculativeThreadLimit = 15,
-      kIdleThreadLimit = 0,
-      kIdleThreadTimeout = 50
-    };
 };
 
 #endif