[Chrome FastLoad]
Patch to make FastLoad Service return the previous URI selected when selecting a new one, as well as fixing a few issues relating to dependencies on non-existent files. Patch from brendan, r=dbaron, sr=waterson
This commit is contained in:
Родитель
197f887b3d
Коммит
f084944245
|
@ -307,7 +307,8 @@ nsFastLoadFileReader::SetChecksum(PRUint32 aChecksum)
|
|||
}
|
||||
|
||||
struct nsStringMapEntry : public PLDHashEntryHdr {
|
||||
const char* mString; // key, must come first
|
||||
const char* mString; // key, must come first
|
||||
nsISupports* mURI; // for SelectMuxedDocument return value
|
||||
};
|
||||
|
||||
struct nsDocumentMapEntry : public nsStringMapEntry {
|
||||
|
@ -340,6 +341,7 @@ strmap_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
|
|||
|
||||
if (entry->mString)
|
||||
nsMemory::Free((void*) entry->mString);
|
||||
NS_IF_RELEASE(entry->mURI);
|
||||
PL_DHashClearEntryStub(aTable, aHdr);
|
||||
}
|
||||
|
||||
|
@ -417,6 +419,8 @@ nsFastLoadFileReader::StartMuxedDocument(nsISupports* aURI, const char* aURISpec
|
|||
if (uriMapEntry->mDocMapEntry)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
docMapEntry->mURI = aURI;
|
||||
NS_ADDREF(docMapEntry->mURI);
|
||||
uriMapEntry->mObject = key;
|
||||
NS_ADDREF(uriMapEntry->mObject);
|
||||
uriMapEntry->mDocMapEntry = docMapEntry;
|
||||
|
@ -425,7 +429,8 @@ nsFastLoadFileReader::StartMuxedDocument(nsISupports* aURI, const char* aURISpec
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFastLoadFileReader::SelectMuxedDocument(nsISupports* aURI)
|
||||
nsFastLoadFileReader::SelectMuxedDocument(nsISupports* aURI,
|
||||
nsISupports** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
|
@ -443,9 +448,9 @@ nsFastLoadFileReader::SelectMuxedDocument(nsISupports* aURI)
|
|||
|
||||
// If we're interrupting another document's segment, save its offset so
|
||||
// we can seek back when it's reselected.
|
||||
nsDocumentMapReadEntry* docMapEntry = mCurrentDocumentMapEntry;
|
||||
if (docMapEntry && docMapEntry->mBytesLeft) {
|
||||
rv = Tell(&docMapEntry->mSaveOffset);
|
||||
nsDocumentMapReadEntry* prevDocMapEntry = mCurrentDocumentMapEntry;
|
||||
if (prevDocMapEntry && prevDocMapEntry->mBytesLeft) {
|
||||
rv = Tell(&prevDocMapEntry->mSaveOffset);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
@ -454,7 +459,7 @@ nsFastLoadFileReader::SelectMuxedDocument(nsISupports* aURI)
|
|||
// non-blocking hunks of data from the parser that are devoid of scripts.
|
||||
// As more data gets FastLoaded, the number of these useless selects will
|
||||
// decline.
|
||||
docMapEntry = uriMapEntry->mDocMapEntry;
|
||||
nsDocumentMapReadEntry* docMapEntry = uriMapEntry->mDocMapEntry;
|
||||
if (docMapEntry == mCurrentDocumentMapEntry) {
|
||||
TRACE_MUX(('r', "select prev %s same as current!\n",
|
||||
docMapEntry->mString));
|
||||
|
@ -474,6 +479,9 @@ nsFastLoadFileReader::SelectMuxedDocument(nsISupports* aURI)
|
|||
return rv;
|
||||
}
|
||||
|
||||
*aResult = prevDocMapEntry ? prevDocMapEntry->mURI : nsnull;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
|
||||
mCurrentDocumentMapEntry = docMapEntry;
|
||||
#ifdef DEBUG_MUX
|
||||
PRUint32 currentSegmentOffset;
|
||||
|
@ -498,6 +506,11 @@ nsFastLoadFileReader::EndMuxedDocument(nsISupports* aURI)
|
|||
if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// Drop our ref to the URI object that was passed to StartMuxedDocument,
|
||||
// we no longer need it, and we do not want to extend its lifetime.
|
||||
if (uriMapEntry->mDocMapEntry)
|
||||
NS_RELEASE(uriMapEntry->mDocMapEntry->mURI);
|
||||
|
||||
// Shrink the table if half the entries are removed sentinels.
|
||||
PRUint32 size = PL_DHASH_TABLE_SIZE(&mFooter.mURIMap);
|
||||
if (mFooter.mURIMap.removedCount >= (size >> 2))
|
||||
|
@ -681,6 +694,8 @@ nsFastLoadFileReader::ReadFooter(nsFastLoadFooter *aFooter)
|
|||
|
||||
entry->mReadObject = nsnull;
|
||||
entry->mSkipOffset = 0;
|
||||
entry->mSaveStrongRefCnt = entry->mStrongRefCnt;
|
||||
entry->mSaveWeakRefCnt = entry->mWeakRefCnt;
|
||||
}
|
||||
|
||||
if (!PL_DHashTableInit(&aFooter->mDocumentMap, &strmap_DHashTableOps,
|
||||
|
@ -716,6 +731,7 @@ nsFastLoadFileReader::ReadFooter(nsFastLoadFooter *aFooter)
|
|||
|
||||
NS_ASSERTION(!entry->mString, "duplicate URISpec in MuxedDocumentMap");
|
||||
entry->mString = info.mURISpec;
|
||||
entry->mURI = nsnull;
|
||||
entry->mInitialSegmentOffset = info.mInitialSegmentOffset;
|
||||
entry->mNextSegmentOffset = info.mInitialSegmentOffset;
|
||||
entry->mBytesLeft = 0;
|
||||
|
@ -1327,6 +1343,8 @@ nsFastLoadFileWriter::StartMuxedDocument(nsISupports* aURI,
|
|||
if (!spec)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
docMapEntry->mString = NS_REINTERPRET_CAST(const char*, spec);
|
||||
docMapEntry->mURI = aURI;
|
||||
NS_ADDREF(docMapEntry->mURI);
|
||||
|
||||
nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
|
||||
nsURIMapWriteEntry* uriMapEntry =
|
||||
|
@ -1350,7 +1368,8 @@ nsFastLoadFileWriter::StartMuxedDocument(nsISupports* aURI,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI)
|
||||
nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI,
|
||||
nsISupports** aResult)
|
||||
{
|
||||
// Avoid repeatedly QI'ing to nsISeekableStream as we tell and seek.
|
||||
nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
|
||||
|
@ -1397,6 +1416,8 @@ nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI)
|
|||
if (prevDocMapEntry == docMapEntry) {
|
||||
TRACE_MUX(('w', "select prev %s same as current!\n",
|
||||
prevDocMapEntry->mString));
|
||||
*aResult = docMapEntry->mURI;
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1460,6 +1481,9 @@ nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI)
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
*aResult = prevDocMapEntry ? prevDocMapEntry->mURI : nsnull;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
|
||||
mCurrentDocumentMapEntry = docMapEntry;
|
||||
TRACE_MUX(('w', "select %p (%p) offset %lu\n",
|
||||
aURI, key.get(), currentSegmentOffset));
|
||||
|
@ -1470,15 +1494,24 @@ NS_IMETHODIMP
|
|||
nsFastLoadFileWriter::EndMuxedDocument(nsISupports* aURI)
|
||||
{
|
||||
nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
|
||||
#ifdef NS_DEBUG
|
||||
nsURIMapWriteEntry* uriMapEntry =
|
||||
NS_STATIC_CAST(nsURIMapWriteEntry*,
|
||||
PL_DHashTableOperate(&mURIMap, key, PL_DHASH_LOOKUP));
|
||||
NS_ASSERTION(uriMapEntry && uriMapEntry->mDocMapEntry,
|
||||
NS_ASSERTION(uriMapEntry->mDocMapEntry,
|
||||
"unknown aURI passed to EndMuxedDocument!");
|
||||
#endif
|
||||
|
||||
PL_DHashTableOperate(&mURIMap, key, PL_DHASH_REMOVE);
|
||||
// Drop our ref to the URI object that was passed to StartMuxedDocument,
|
||||
// we no longer need it, and we do not want to extend its lifetime.
|
||||
if (uriMapEntry->mDocMapEntry)
|
||||
NS_RELEASE(uriMapEntry->mDocMapEntry->mURI);
|
||||
|
||||
// Shrink the table if half the entries are removed sentinels.
|
||||
PRUint32 size = PL_DHASH_TABLE_SIZE(&mURIMap);
|
||||
if (mURIMap.removedCount >= (size >> 2))
|
||||
PL_DHashTableOperate(&mURIMap, key, PL_DHASH_REMOVE);
|
||||
else
|
||||
PL_DHashTableRawRemove(&mURIMap, uriMapEntry);
|
||||
|
||||
TRACE_MUX(('w', "end %p (%p)\n", aURI, key.get()));
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1507,7 +1540,19 @@ nsFastLoadFileWriter::AddDependency(nsIFile* aFile)
|
|||
if (!tmp)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
entry->mString = tmp;
|
||||
|
||||
// If we can't get the last modified time from aFile, assume it does
|
||||
// not exist, or is otherwise inaccessible to us (due to permissions),
|
||||
// remove the dependency, and suppress the failure.
|
||||
//
|
||||
// Otherwise, we would end up aborting the fastload process due to a
|
||||
// missing .js or .xul or other file on every startup.
|
||||
|
||||
rv = aFile->GetLastModifiedTime(&entry->mLastModified);
|
||||
if (NS_FAILED(rv)) {
|
||||
PL_DHashTableOperate(&mDependencyMap, path.get(), PL_DHASH_REMOVE);
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -2229,6 +2274,7 @@ nsFastLoadFileUpdater::CopyReadDocumentMapEntryToUpdater(PLDHashTable *aTable,
|
|||
}
|
||||
|
||||
writeEntry->mString = NS_REINTERPRET_CAST(const char*, spec);
|
||||
writeEntry->mURI = nsnull;
|
||||
writeEntry->mInitialSegmentOffset = readEntry->mInitialSegmentOffset;
|
||||
writeEntry->mCurrentSegmentOffset = 0;
|
||||
return PL_DHASH_NEXT;
|
||||
|
@ -2284,12 +2330,13 @@ nsFastLoadFileUpdater::Open(nsFastLoadFileReader* aReader)
|
|||
NS_IF_ADDREF(obj);
|
||||
writeEntry->mObject = NS_REINTERPRET_CAST(nsISupports*, key);
|
||||
writeEntry->mOID = oid;
|
||||
writeEntry->mInfo = *NS_STATIC_CAST(nsFastLoadSharpObjectInfo*,
|
||||
readEntry);
|
||||
writeEntry->mInfo.mCIDOffset = readEntry->mCIDOffset;
|
||||
writeEntry->mInfo.mStrongRefCnt = readEntry->mSaveStrongRefCnt;
|
||||
writeEntry->mInfo.mWeakRefCnt = readEntry->mSaveWeakRefCnt;
|
||||
}
|
||||
|
||||
// Copy URI spec string and initial segment offset in FastLoad file from
|
||||
// nsDocumentMapReadEntry in reader to mDocumentMapWriteEntry in updater.
|
||||
// nsDocumentMapReadEntry in reader to nsDocumentMapWriteEntry in updater.
|
||||
// If we didn't enumerate all entries, we ran out of memory.
|
||||
n = PL_DHashTableEnumerate(&aReader->mFooter.mDocumentMap,
|
||||
CopyReadDocumentMapEntryToUpdater,
|
||||
|
|
|
@ -284,6 +284,8 @@ class nsFastLoadFileReader
|
|||
struct nsObjectMapEntry : public nsFastLoadSharpObjectInfo {
|
||||
nsCOMPtr<nsISupports> mReadObject;
|
||||
PRUint32 mSkipOffset;
|
||||
PRUint16 mSaveStrongRefCnt; // saved for an Update
|
||||
PRUint16 mSaveWeakRefCnt; // after a Read
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -75,10 +75,16 @@ interface nsIFastLoadFileControl : nsISupports
|
|||
* some (but not all, at first, or for a while during development) of the
|
||||
* results of parsing and compiling various inputs can be multiplexed to
|
||||
* or from a FastLoad file.
|
||||
*
|
||||
* Note: Select returns the previously selected URI object in case the
|
||||
* caller is synchronously selecting and writing data to the FastLoad
|
||||
* file, so the caller can reselect the previous URI and return to code
|
||||
* the continues to write FastLoad data for the previous URI, unaware of
|
||||
* the nested select/write/reselect.
|
||||
*/
|
||||
void startMuxedDocument(in nsISupports aURI, in string aURISpec);
|
||||
void selectMuxedDocument(in nsISupports aURI);
|
||||
void endMuxedDocument(in nsISupports aURI);
|
||||
void startMuxedDocument(in nsISupports aURI, in string aURISpec);
|
||||
nsISupports selectMuxedDocument(in nsISupports aURI);
|
||||
void endMuxedDocument(in nsISupports aURI);
|
||||
};
|
||||
|
||||
[scriptable, uuid(652ecec6-d40b-45b6-afef-641d6c63a35b)]
|
||||
|
|
|
@ -72,24 +72,32 @@ interface nsIFastLoadService : nsISupports
|
|||
readonly attribute PRInt32 direction;
|
||||
|
||||
/**
|
||||
* These methods associate a URI object with its spec, for faster select
|
||||
* using the object pointer as a key, rather than the spec string. The
|
||||
* selectMuxedDocument method returns the previously selected URI object,
|
||||
* in case a caller needs to reselect the previous after muxing data for
|
||||
* a given URI synchronously. For the non-blocking or "asynchronous" i/o
|
||||
* case, the caller must select the source URI from the FastLoad multiplex
|
||||
* before writing a new burst of data parsed from the slow-loaded source.
|
||||
*
|
||||
* Clients of inputStream and outputStream should try to demultiplex data
|
||||
* from the input stream only if fastLoadService->StartMuxedDocument(uri,
|
||||
* urispec, NS_FASTLOAD_READ) succeeds. If StartMuxedDocument fails with
|
||||
* NS_ERROR_NOT_AVAILABLE, callers should slow-load the documents, muxing
|
||||
* their data to the current output stream.
|
||||
*/
|
||||
void startMuxedDocument(in nsISupports aURI,
|
||||
in string aURISpec,
|
||||
in PRInt32 aDirectionFlags);
|
||||
void selectMuxedDocument(in nsISupports aURI);
|
||||
void endMuxedDocument(in nsISupports aURI);
|
||||
void startMuxedDocument(in nsISupports aURI,
|
||||
in string aURISpec,
|
||||
in PRInt32 aDirectionFlags);
|
||||
nsISupports selectMuxedDocument(in nsISupports aURI);
|
||||
void endMuxedDocument(in nsISupports aURI);
|
||||
|
||||
void addDependency(in nsIFile aFile);
|
||||
void addDependency(in nsIFile aFile);
|
||||
|
||||
PRUint32 computeChecksum(in nsIFile aFile,
|
||||
in nsIFastLoadReadControl aControl);
|
||||
void cacheChecksum(in nsIFile aFile,
|
||||
in nsIObjectOutputStream aStream);
|
||||
PRUint32 computeChecksum(in nsIFile aFile,
|
||||
in nsIFastLoadReadControl aControl);
|
||||
void cacheChecksum(in nsIFile aFile,
|
||||
in nsIObjectOutputStream aStream);
|
||||
|
||||
[noscript] void getFastLoadReferent(inout nsISupports aPtr);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче