• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Google, Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "core/html/parser/HTMLParserScheduler.h"
28 
29 #include "core/dom/Document.h"
30 #include "core/html/parser/HTMLDocumentParser.h"
31 #include "core/frame/FrameView.h"
32 
33 namespace blink {
34 
35 // parserChunkSize is used to define how many tokens the parser will
36 // process before checking against parserTimeLimit and possibly yielding.
37 // This is a performance optimization to prevent checking after every token.
38 const int HTMLParserScheduler::parserChunkSize = 4096;
39 
40 // parserTimeLimit is the seconds the parser will run in one write() call
41 // before yielding. Inline <script> execution can cause it to exceed the limit.
42 const double HTMLParserScheduler::parserTimeLimit = 0.2;
43 
ActiveParserSession(Document * document)44 ActiveParserSession::ActiveParserSession(Document* document)
45     : m_document(document)
46 {
47     if (!m_document)
48         return;
49     m_document->incrementActiveParserCount();
50 }
51 
~ActiveParserSession()52 ActiveParserSession::~ActiveParserSession()
53 {
54     if (!m_document)
55         return;
56     m_document->decrementActiveParserCount();
57 }
58 
PumpSession(unsigned & nestingLevel,Document * document)59 PumpSession::PumpSession(unsigned& nestingLevel, Document* document)
60     : NestingLevelIncrementer(nestingLevel)
61     , ActiveParserSession(document)
62     // Setting processedTokens to INT_MAX causes us to check for yields
63     // after any token during any parse where yielding is allowed.
64     // At that time we'll initialize startTime.
65     , processedTokens(INT_MAX)
66     , startTime(0)
67     , needsYield(false)
68     , didSeeScript(false)
69 {
70 }
71 
~PumpSession()72 PumpSession::~PumpSession()
73 {
74 }
75 
HTMLParserScheduler(HTMLDocumentParser * parser)76 HTMLParserScheduler::HTMLParserScheduler(HTMLDocumentParser* parser)
77     : m_parser(parser)
78     , m_continueNextChunkTimer(this, &HTMLParserScheduler::continueNextChunkTimerFired)
79     , m_isSuspendedWithActiveTimer(false)
80 {
81 }
82 
~HTMLParserScheduler()83 HTMLParserScheduler::~HTMLParserScheduler()
84 {
85     m_continueNextChunkTimer.stop();
86 }
87 
continueNextChunkTimerFired(Timer<HTMLParserScheduler> * timer)88 void HTMLParserScheduler::continueNextChunkTimerFired(Timer<HTMLParserScheduler>* timer)
89 {
90     ASSERT_UNUSED(timer, timer == &m_continueNextChunkTimer);
91     m_parser->resumeParsingAfterYield();
92 }
93 
scheduleForResume()94 void HTMLParserScheduler::scheduleForResume()
95 {
96     m_continueNextChunkTimer.startOneShot(0, FROM_HERE);
97 }
98 
suspend()99 void HTMLParserScheduler::suspend()
100 {
101     ASSERT(!m_isSuspendedWithActiveTimer);
102     if (!m_continueNextChunkTimer.isActive())
103         return;
104     m_isSuspendedWithActiveTimer = true;
105     m_continueNextChunkTimer.stop();
106 }
107 
resume()108 void HTMLParserScheduler::resume()
109 {
110     ASSERT(!m_continueNextChunkTimer.isActive());
111     if (!m_isSuspendedWithActiveTimer)
112         return;
113     m_isSuspendedWithActiveTimer = false;
114     m_continueNextChunkTimer.startOneShot(0, FROM_HERE);
115 }
116 
117 }
118