Changeset 61658 in webkit
- Timestamp:
- Jun 22, 2010 11:18:49 PM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 2 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/Android.mk
r61584 r61658 267 267 html/LegacyHTMLTreeConstructor.cpp \ 268 268 html/HTMLParserErrorCodes.cpp \ 269 html/HTMLParserScheduler.cpp \ 269 270 html/HTMLTableRowsCollection.cpp \ 270 271 html/HTMLDocumentParser.cpp \ -
trunk/WebCore/CMakeLists.txt
r61650 r61658 975 975 html/LegacyHTMLTreeConstructor.cpp 976 976 html/HTMLParserErrorCodes.cpp 977 html/HTMLParserScheduler.cpp 977 978 html/HTMLPlugInElement.cpp 978 979 html/HTMLPlugInImageElement.cpp -
trunk/WebCore/ChangeLog
r61655 r61658 1 2010-06-22 Eric Seidel <eric@webkit.org> 2 3 Reviewed by Adam Barth. 4 5 Split out HTML5DocumentParser yield/resume logic into a separate class 6 https://bugs.webkit.org/show_bug.cgi?id=41018 7 8 The HTML5DocumentParser is just the coordinator, and shouldn't have 9 any real parsing logic of his own. Continuing along that path, I'm 10 moving the when-to-yield/resume logic out into a separate class. 11 12 I could have create a new HTMLParserSchedulerHost virtual interface 13 to allow the HTMLParserScheduler to talk back to the 14 HTML5DocumentParser, but instead I just exposed the one method it 15 needs (resumeParsing()) as a public method. Since no code besides 16 HTMLDocument (and DocumentFrament) ever should know about the 17 HTML5DocumentParser DocumentParser subclass, no class should ever 18 see the resumeParsing() method anyway. 19 20 Most of this change is just moving code from HTML5DocumentParser 21 to the new HTMLParserScheduler. 22 23 Some of this change is wrapping previous direct access to 24 m_continueNextChunkTimer.isActive() with isScheduledForResume(). 25 26 * Android.mk: 27 * CMakeLists.txt: 28 * GNUmakefile.am: 29 * WebCore.gypi: 30 * WebCore.pro: 31 * WebCore.xcodeproj/project.pbxproj: 32 * html/HTML5DocumentParser.cpp: 33 (WebCore::HTML5DocumentParser::HTML5DocumentParser): 34 (WebCore::HTML5DocumentParser::stopParsing): 35 (WebCore::HTML5DocumentParser::processingData): 36 (WebCore::HTML5DocumentParser::pumpLexerIfPossible): 37 (WebCore::HTML5DocumentParser::isScheduledForResume): 38 (WebCore::HTML5DocumentParser::resumeParsing): 39 (WebCore::HTML5DocumentParser::pumpLexer): 40 (WebCore::HTML5DocumentParser::end): 41 (WebCore::HTML5DocumentParser::attemptToEnd): 42 (WebCore::HTML5DocumentParser::endIfDelayed): 43 * html/HTML5DocumentParser.h: 44 (WebCore::HTML5DocumentParser::document): 45 - Exposed for HTMLParserScheduler. 46 * html/HTMLParserScheduler.cpp: Added. 47 (WebCore::parserTimeLimit): Moved from HTML5DocumentParser. 48 (WebCore::parserChunkSize): ditto. 49 (WebCore::HTMLParserScheduler::HTMLParserScheduler): 50 (WebCore::HTMLParserScheduler::~HTMLParserScheduler): 51 (WebCore::isLayoutTimerActive): 52 (WebCore::HTMLParserScheduler::continueNextChunkTimerFired): 53 - Moved from HTML5DocumentParser. 54 * html/HTMLParserScheduler.h: Added. 55 (WebCore::HTMLParserScheduler::PumpSession::PumpSession): 56 - Moved from HTML5DocumentParser. 57 (WebCore::HTMLParserScheduler::shouldContinueParsing): 58 (WebCore::HTMLParserScheduler::isScheduledForResume): 59 1 60 2010-06-22 Pavel Feldman <pfeldman@chromium.org> 2 61 -
trunk/WebCore/GNUmakefile.am
r61650 r61658 1227 1227 WebCore/html/HTMLParserErrorCodes.h \ 1228 1228 WebCore/html/HTMLParserQuirks.h \ 1229 WebCore/html/HTMLParserScheduler.cpp \ 1230 WebCore/html/HTMLParserScheduler.h \ 1229 1231 WebCore/html/HTMLPlugInElement.cpp \ 1230 1232 WebCore/html/HTMLPlugInElement.h \ -
trunk/WebCore/WebCore.gypi
r61650 r61658 1613 1613 'html/HTMLParserErrorCodes.cpp', 1614 1614 'html/HTMLParserErrorCodes.h', 1615 'html/HTMLParserScheduler.cpp', 1616 'html/HTMLParserScheduler.h', 1615 1617 'html/HTMLPlugInElement.cpp', 1616 1618 'html/HTMLPlugInElement.h', -
trunk/WebCore/WebCore.pro
r61637 r61658 680 680 html/LegacyHTMLTreeConstructor.cpp \ 681 681 html/HTMLParserErrorCodes.cpp \ 682 html/HTMLParserScheduler.cpp \ 682 683 html/HTMLPlugInElement.cpp \ 683 684 html/HTMLPlugInImageElement.cpp \ -
trunk/WebCore/WebCore.xcodeproj/project.pbxproj
r61650 r61658 3280 3280 A8E545BF0CA9D1C20097D09B /* DOMSVGTextElement.h in Headers */ = {isa = PBXBuildFile; fileRef = A8E544C10CA9D1C20097D09B /* DOMSVGTextElement.h */; }; 3281 3281 A8E545C10CA9D1C20097D09B /* DOMSVGDescElementInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = A8E544C30CA9D1C20097D09B /* DOMSVGDescElementInternal.h */; }; 3282 A8E6A78111D1661B00311F4A /* HTMLParserScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = A8E6A77F11D1661B00311F4A /* HTMLParserScheduler.h */; }; 3283 A8E6A78211D1661B00311F4A /* HTMLParserScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8E6A78011D1661B00311F4A /* HTMLParserScheduler.cpp */; }; 3282 3284 A8EA73C30A1900E300A8EF5F /* RenderFieldset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8EA73AF0A1900E300A8EF5F /* RenderFieldset.cpp */; }; 3283 3285 A8EA73C40A1900E300A8EF5F /* RenderFieldset.h in Headers */ = {isa = PBXBuildFile; fileRef = A8EA73B00A1900E300A8EF5F /* RenderFieldset.h */; }; … … 8748 8750 A8E544C10CA9D1C20097D09B /* DOMSVGTextElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMSVGTextElement.h; sourceTree = "<group>"; }; 8749 8751 A8E544C30CA9D1C20097D09B /* DOMSVGDescElementInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMSVGDescElementInternal.h; sourceTree = "<group>"; }; 8752 A8E6A77F11D1661B00311F4A /* HTMLParserScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLParserScheduler.h; sourceTree = "<group>"; }; 8753 A8E6A78011D1661B00311F4A /* HTMLParserScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLParserScheduler.cpp; sourceTree = "<group>"; }; 8750 8754 A8EA73AF0A1900E300A8EF5F /* RenderFieldset.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderFieldset.cpp; sourceTree = "<group>"; }; 8751 8755 A8EA73B00A1900E300A8EF5F /* RenderFieldset.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderFieldset.h; sourceTree = "<group>"; }; … … 13425 13429 isa = PBXGroup; 13426 13430 children = ( 13427 9719AEFF11D09F2C00D45831 /* HTMLInputStream.h */,13428 49484FAE102CF01E00187DD3 /* canvas */,13429 13431 B0149E7911A4B21500196A7B /* AsyncImageResizer.cpp */, 13430 13432 B0149E7A11A4B21500196A7B /* AsyncImageResizer.h */, … … 13435 13437 89BED5EA11BE11CE00448492 /* BlobBuilder.h */, 13436 13438 89CD027911C859A80070B791 /* BlobBuilder.idl */, 13439 49484FAE102CF01E00187DD3 /* canvas */, 13437 13440 93C441ED0F813A1A00C1A634 /* CollectionCache.cpp */, 13438 13441 93C441EE0F813A1A00C1A634 /* CollectionCache.h */, … … 13610 13613 A81369B0097374F500D74463 /* HTMLInputElement.h */, 13611 13614 A80E7E170A1A7CCB007FB8C5 /* HTMLInputElement.idl */, 13615 9719AEFF11D09F2C00D45831 /* HTMLInputStream.h */, 13612 13616 A81369AF097374F500D74463 /* HTMLIsIndexElement.cpp */, 13613 13617 A81369AE097374F500D74463 /* HTMLIsIndexElement.h */, … … 13676 13680 BC588AEF0BFA6CF900EE679E /* HTMLParserErrorCodes.h */, 13677 13681 449B19F30FA72ECE0015CA4A /* HTMLParserQuirks.h */, 13682 A8E6A78011D1661B00311F4A /* HTMLParserScheduler.cpp */, 13683 A8E6A77F11D1661B00311F4A /* HTMLParserScheduler.h */, 13678 13684 A871D44D0A127CBC00B12A68 /* HTMLPlugInElement.cpp */, 13679 13685 A871D44C0A127CBC00B12A68 /* HTMLPlugInElement.h */, … … 19513 19519 9719AF0011D09F2C00D45831 /* HTMLInputStream.h in Headers */, 19514 19520 A853123D11D0471B00D4D077 /* FragmentScriptingPermission.h in Headers */, 19521 A8E6A78111D1661B00311F4A /* HTMLParserScheduler.h in Headers */, 19515 19522 ); 19516 19523 runOnlyForDeploymentPostprocessing = 0; … … 21830 21837 1AD8F81C11CAB9E900E93E54 /* PlatformStrategies.cpp in Sources */, 21831 21838 B525A96611CA2340003A23A8 /* JSSQLException.cpp in Sources */, 21839 A8E6A78211D1661B00311F4A /* HTMLParserScheduler.cpp in Sources */, 21832 21840 ); 21833 21841 runOnlyForDeploymentPostprocessing = 0; -
trunk/WebCore/html/HTML5DocumentParser.cpp
r61646 r61658 30 30 #include "Element.h" 31 31 #include "Frame.h" 32 #include " FrameView.h" // Only for isLayoutTimerActive32 #include "HTMLParserScheduler.h" 33 33 #include "HTML5Lexer.h" 34 34 #include "HTML5PreloadScanner.h" … … 36 36 #include "HTML5TreeBuilder.h" 37 37 #include "HTMLDocument.h" 38 #include "Page.h"39 38 #include "XSSAuditor.h" 40 39 #include <wtf/CurrentTime.h> … … 43 42 #include "InspectorTimelineAgent.h" 44 43 #endif 45 46 // defaultParserChunkSize is used to define how many tokens the parser will47 // process before checking against parserTimeLimit and possibly yielding.48 // This is a performance optimization to prevent checking after every token.49 static const int defaultParserChunkSize = 4096;50 51 // defaultParserTimeLimit is the seconds the parser will run in one write() call52 // before yielding. Inline <script> execution can cause it to excede the limit.53 // FIXME: We would like this value to be 0.2.54 static const double defaultParserTimeLimit = 0.500;55 44 56 45 namespace WebCore { … … 77 66 } // namespace 78 67 79 static double parserTimeLimit(Page* page)80 {81 // We're using the poorly named customHTMLTokenizerTimeDelay setting.82 if (page && page->hasCustomHTMLTokenizerTimeDelay())83 return page->customHTMLTokenizerTimeDelay();84 return defaultParserTimeLimit;85 }86 87 static int parserChunkSize(Page* page)88 {89 // FIXME: We may need to divide the value from customHTMLTokenizerChunkSize90 // by some constant to translate from the "character" based behavior of the91 // old HTMLDocumentParser to the token-based behavior of this parser.92 if (page && page->hasCustomHTMLTokenizerChunkSize())93 return page->customHTMLTokenizerChunkSize();94 return defaultParserChunkSize;95 }96 97 68 HTML5DocumentParser::HTML5DocumentParser(HTMLDocument* document, bool reportErrors) 98 69 : m_document(document) … … 100 71 , m_scriptRunner(new HTML5ScriptRunner(document, this)) 101 72 , m_treeConstructor(new HTML5TreeBuilder(m_lexer.get(), document, reportErrors)) 73 , m_parserScheduler(new HTMLParserScheduler(this)) 102 74 , m_endWasDelayed(false) 103 75 , m_writeNestingLevel(0) 104 , m_parserTimeLimit(parserTimeLimit(document->page()))105 , m_parserChunkSize(parserChunkSize(document->page()))106 , m_continueNextChunkTimer(this, &HTML5DocumentParser::continueNextChunkTimerFired)107 76 { 108 77 begin(); … … 117 86 , m_endWasDelayed(false) 118 87 , m_writeNestingLevel(0) 119 // FIXME: Parser yielding should be a separate class.120 , m_parserTimeLimit(0)121 , m_parserChunkSize(0)122 , m_continueNextChunkTimer(this, &HTML5DocumentParser::continueNextChunkTimerFired)123 88 { 124 89 begin(); … … 141 106 { 142 107 DocumentParser::stopParsing(); 143 m_ continueNextChunkTimer.stop();108 m_parserScheduler.clear(); // Deleting the scheduler will clear any timers. 144 109 } 145 110 146 111 bool HTML5DocumentParser::processingData() const 147 112 { 148 return m_continueNextChunkTimer.isActive() || inWrite();113 return isScheduledForResume() || inWrite(); 149 114 } 150 115 … … 154 119 return; 155 120 156 // Once a timer is set, it has control of when the parser continues.157 if ( m_continueNextChunkTimer.isActive()) {121 // Once a resume is scheduled, HTMLParserScheduler controls when we next pump. 122 if (isScheduledForResume()) { 158 123 ASSERT(mode == AllowYield); 159 124 return; … … 163 128 } 164 129 165 struct HTML5DocumentParser::PumpSession { 166 PumpSession() 167 : processedTokens(0) 168 , startTime(currentTime()) 169 { 170 } 171 172 int processedTokens; 173 double startTime; 174 }; 175 176 inline bool HTML5DocumentParser::shouldContinueParsing(PumpSession& session) 177 { 178 if (m_parserStopped) 179 return false; 180 181 if (session.processedTokens > m_parserChunkSize) { 182 session.processedTokens = 0; 183 double elapsedTime = currentTime() - session.startTime; 184 if (elapsedTime > m_parserTimeLimit) { 185 // Schedule an immediate timer and yield from the parser. 186 m_continueNextChunkTimer.startOneShot(0); 187 return false; 188 } 189 } 190 191 ++session.processedTokens; 192 return true; 130 bool HTML5DocumentParser::isScheduledForResume() const 131 { 132 return m_parserScheduler && m_parserScheduler->isScheduledForResume(); 133 } 134 135 // Used by HTMLParserScheduler 136 void HTML5DocumentParser::resumeParsingAfterYield() 137 { 138 // We should never be here unless we can pump immediately. Call pumpLexer() 139 // directly so that ASSERTS will fire if we're wrong. 140 pumpLexer(AllowYield); 193 141 } 194 142 … … 209 157 ASSERT(!m_parserStopped); 210 158 ASSERT(!m_treeConstructor->isPaused()); 211 ASSERT(! m_continueNextChunkTimer.isActive());159 ASSERT(!isScheduledForResume()); 212 160 213 161 // We tell the InspectorTimelineAgent about every pump, even if we … … 215 163 willPumpLexer(); 216 164 217 PumpSession session;165 HTMLParserScheduler::PumpSession session; 218 166 // FIXME: This loop body has is now too long and needs cleanup. 219 while (mode == ForceSynchronous || shouldContinueParsing(session)) {167 while (mode == ForceSynchronous || (!m_parserStopped && m_parserScheduler->shouldContinueParsing(session))) { 220 168 if (!m_lexer->nextToken(m_input.current(), m_token)) 221 169 break; … … 245 193 246 194 didPumpLexer(); 247 }248 249 // FIXME: This belongs on Document.250 static bool isLayoutTimerActive(Document* doc)251 {252 ASSERT(doc);253 return doc->view() && doc->view()->layoutPending() && !doc->minimumLayoutDelay();254 }255 256 void HTML5DocumentParser::continueNextChunkTimerFired(Timer<HTML5DocumentParser>* timer)257 {258 ASSERT_UNUSED(timer, timer == &m_continueNextChunkTimer);259 // FIXME: The timer class should handle timer priorities instead of this code.260 // If a layout is scheduled, wait again to let the layout timer run first.261 if (isLayoutTimerActive(m_document)) {262 m_continueNextChunkTimer.startOneShot(0);263 return;264 }265 266 // We should never be here unless we can pump immediately. Call pumpLexer()267 // directly so that ASSERTS will fire if we're wrong.268 pumpLexer(AllowYield);269 195 } 270 196 … … 315 241 void HTML5DocumentParser::end() 316 242 { 317 ASSERT(! m_continueNextChunkTimer.isActive());243 ASSERT(!isScheduledForResume()); 318 244 // NOTE: This pump should only ever emit buffered character tokens, 319 245 // so ForceSynchronous vs. AllowYield should be meaningless. … … 329 255 // an external script to load, we can't finish parsing quite yet. 330 256 331 if (inWrite() || isWaitingForScripts() || executingScript() || m_continueNextChunkTimer.isActive()) {257 if (inWrite() || isWaitingForScripts() || executingScript() || isScheduledForResume()) { 332 258 m_endWasDelayed = true; 333 259 return; … … 340 266 // We don't check inWrite() here since inWrite() will be true if this was 341 267 // called from write(). 342 if (!m_endWasDelayed || isWaitingForScripts() || executingScript() || m_continueNextChunkTimer.isActive())268 if (!m_endWasDelayed || isWaitingForScripts() || executingScript() || isScheduledForResume()) 343 269 return; 344 270 -
trunk/WebCore/html/HTML5DocumentParser.h
r61637 r61658 42 42 class DocumentFragment; 43 43 class HTMLDocument; 44 class HTMLParserScheduler; 44 45 class HTML5Lexer; 45 46 class HTML5ScriptRunner; … … 83 84 virtual void notifyFinished(CachedResource*); 84 85 86 // Exposed for HTMLParserScheduler 87 Document* document() const { return m_document; } 88 void resumeParsingAfterYield(); 89 85 90 private: 86 91 void willPumpLexer(); 87 92 void didPumpLexer(); 88 89 struct PumpSession;90 inline bool shouldContinueParsing(PumpSession&);91 bool runScriptsForPausedTreeConstructor();92 93 93 94 enum SynchronousMode { … … 97 98 void pumpLexer(SynchronousMode); 98 99 void pumpLexerIfPossible(SynchronousMode); 99 void continueNextChunkTimerFired(Timer<HTML5DocumentParser>*); 100 101 bool runScriptsForPausedTreeConstructor(); 100 102 void resumeParsingAfterScriptExecution(); 101 103 … … 103 105 void endIfDelayed(); 104 106 107 bool isScheduledForResume() const; 105 108 bool inScriptExecution() const; 106 109 bool inWrite() const { return m_writeNestingLevel > 0; } … … 120 123 OwnPtr<HTML5TreeBuilder> m_treeConstructor; 121 124 OwnPtr<HTML5PreloadScanner> m_preloadScanner; 125 OwnPtr<HTMLParserScheduler> m_parserScheduler; 122 126 123 127 bool m_endWasDelayed; 124 128 int m_writeNestingLevel; 125 126 // Used for yielding the parser to make WebKit applications more responsive.127 // FIXME: This should a separate class, used by HTML5DocumentParser.128 double m_parserTimeLimit;129 int m_parserChunkSize;130 Timer<HTML5DocumentParser> m_continueNextChunkTimer;131 129 }; 132 130
Note: See TracChangeset
for help on using the changeset viewer.