Be smarter about searching the array of elements seen in this append batch in HTML5 parsing

This commit is contained in:
Henri Sivonen 2009-03-04 16:36:52 +02:00
parent 2c98cfad79
commit c1c7b938f9
2 changed files with 33 additions and 31 deletions

View File

@ -256,6 +256,9 @@ nsHtml5TreeBuilder::end()
#ifdef DEBUG_hsivonen
printf("MAX INSERTION BATCH LEN: %d\n", sInsertionBatchMaxLength);
printf("MAX NOTIFICATION BATCH LEN: %d\n", sAppendBatchMaxSize);
if (sAppendBatchExaminations != 0) {
printf("AVERAGE SLOTS EXAMINED: %d\n", sAppendBatchSlotsExamined / sAppendBatchExaminations);
}
#endif
}
@ -445,15 +448,18 @@ nsHtml5TreeBuilder::Flush()
{
if (!mFlushing) {
mFlushing = PR_TRUE;
PRUint32 opQueueLength = mOpQueue.Length();
mElementsSeenInThisAppendBatch.SetCapacity(opQueueLength * 2);
// XXX alloc failure
const nsHtml5TreeOperation* start = mOpQueue.Elements();
const nsHtml5TreeOperation* end = start + mOpQueue.Length();
const nsHtml5TreeOperation* end = start + opQueueLength;
for (nsHtml5TreeOperation* iter = (nsHtml5TreeOperation*)start; iter < end; ++iter) {
iter->Perform(this);
}
FlushPendingAppendNotifications();
#ifdef DEBUG_hsivonen
if (mOpQueue.Length() > sInsertionBatchMaxLength) {
sInsertionBatchMaxLength = mOpQueue.Length();
sInsertionBatchMaxLength = opQueueLength;
}
#endif
mOpQueue.Clear();
@ -464,5 +470,7 @@ nsHtml5TreeBuilder::Flush()
#ifdef DEBUG_hsivonen
PRUint32 nsHtml5TreeBuilder::sInsertionBatchMaxLength = 0;
PRUint32 nsHtml5TreeBuilder::sAppendBatchMaxSize = 0;
PRUint32 nsHtml5TreeBuilder::sAppendBatchSlotsExamined = 0;
PRUint32 nsHtml5TreeBuilder::sAppendBatchExaminations = 0;
#endif

View File

@ -39,6 +39,8 @@
#ifdef DEBUG_hsivonen
static PRUint32 sInsertionBatchMaxLength;
static PRUint32 sAppendBatchMaxSize;
static PRUint32 sAppendBatchSlotsExamined;
static PRUint32 sAppendBatchExaminations;
#endif
nsHtml5Parser* mParser; // weak ref
PRBool mHasProcessedBase;
@ -53,38 +55,30 @@
void Flush();
inline void PostPendingAppendNotification(nsIContent* aParent, nsIContent* aChild) {
nsIContent* parent = aParent; // this gets nulled when found
nsIContent* child = aChild->IsNodeOfType(nsINode::eELEMENT) ? aChild : nsnull; // this gets nulled when found
const nsIContentPtr* start = mElementsSeenInThisAppendBatch.Elements();
const nsIContentPtr* end = start + mElementsSeenInThisAppendBatch.Length();
// XXX backwards iterate
for (const nsIContentPtr* iter = start; iter < end; ++iter) {
if (*iter == parent) {
parent = nsnull;
}
if (*iter == child) {
child = nsnull;
}
if (!(parent || child)) {
PRBool newParent = PR_TRUE;
const nsIContentPtr* first = mElementsSeenInThisAppendBatch.Elements();
const nsIContentPtr* last = first + (mElementsSeenInThisAppendBatch.Length() - 1);
for (const nsIContentPtr* iter = last; iter >= first; --iter) {
#ifdef DEBUG_hsivonen
sAppendBatchSlotsExamined++;
#endif
if (*iter == aParent) {
newParent = PR_FALSE;
break;
}
}
if (child) {
mElementsSeenInThisAppendBatch.AppendElement(child);
}
if (parent) {
// parents that are in mPendingNotifications don't need to be added to
// mElementsSeenInThisAppendBatch
const nsHtml5PendingNotification* startNotifications = mPendingNotifications.Elements();
const nsHtml5PendingNotification* endNotifications = startNotifications + mPendingNotifications.Length();
// XXX backwards iterate
for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)startNotifications; iter < endNotifications; ++iter) {
if (iter->Contains(parent)) {
return;
}
}
mPendingNotifications.AppendElement(parent);
}
if (aChild->IsNodeOfType(nsINode::eELEMENT)) {
mElementsSeenInThisAppendBatch.AppendElement(aChild);
}
mElementsSeenInThisAppendBatch.AppendElement(aParent);
if (newParent) {
mPendingNotifications.AppendElement(aParent);
}
#ifdef DEBUG_hsivonen
sAppendBatchExaminations++;
#endif
}
inline void FlushPendingAppendNotifications() {