Changeset 76177 in webkit
- Timestamp:
- Jan 19, 2011 4:13:03 PM (13 years ago)
- Location:
- trunk/Source
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r76176 r76177 1 2011-01-19 Antti Koivisto <antti@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 Cache function offsets to speed up javascript parsing 6 https://bugs.webkit.org/show_bug.cgi?id=52622 7 8 Use cache to save function offsets and some other info. 9 This avoids quite a bit of work when reparsing the source. 10 11 * parser/ASTBuilder.h: 12 * parser/JSParser.cpp: 13 (JSC::JSParser::CachedFunctionInfo::CachedFunctionInfo): 14 (JSC::JSParser::CachedFunctionInfo::approximateByteSize): 15 (JSC::JSParser::CachedFunctionInfo::closeBraceToken): 16 (JSC::JSParser::Scope::copyCapturedVariablesToVector): 17 (JSC::JSParser::Scope::saveFunctionInfo): 18 (JSC::JSParser::Scope::restoreFunctionInfo): 19 (JSC::JSParser::findCachedFunctionInfo): 20 (JSC::JSParser::JSParser): 21 (JSC::JSParser::parseProgram): 22 (JSC::JSParser::parseFunctionInfo): 23 * parser/Lexer.h: 24 (JSC::Lexer::setOffset): 25 (JSC::Lexer::setLineNumber): 26 (JSC::Lexer::sourceProvider): 27 * parser/SourceProvider.h: 28 (JSC::SourceProviderCache::SourceProviderCache): 29 (JSC::SourceProviderCache::~SourceProviderCache): 30 (JSC::SourceProviderCache::byteSize): 31 (JSC::SourceProviderCache::add): 32 (JSC::SourceProviderCache::get): 33 (JSC::SourceProvider::SourceProvider): 34 (JSC::SourceProvider::~SourceProvider): 35 (JSC::SourceProvider::cache): 36 (JSC::SourceProvider::notifyCacheSizeChanged): 37 (JSC::SourceProvider::cacheSizeChanged): 38 * parser/SyntaxChecker.h: 39 1 40 2011-01-19 Mark Rowe <mrowe@apple.com> 2 41 -
trunk/Source/JavaScriptCore/parser/ASTBuilder.h
r75896 r76177 109 109 static const bool CreatesAST = true; 110 110 static const bool NeedsFreeVariableInfo = true; 111 static const bool CanUseFunctionCache = true; 111 112 112 113 ExpressionNode* makeBinaryNode(int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>); -
trunk/Source/JavaScriptCore/parser/JSParser.cpp
r76148 r76177 34 34 #include "NodeInfo.h" 35 35 #include "ASTBuilder.h" 36 #include "SourceProvider.h" 36 37 #include <wtf/HashFunctions.h> 37 38 #include <wtf/WTFThreadData.h> … … 94 95 StringImpl* m_ident; 95 96 bool m_isLoop; 97 }; 98 99 struct CachedFunctionInfo : public SourceProviderCache::Item { 100 CachedFunctionInfo(int closeBraceLine, int closeBracePos) 101 : closeBraceLine(closeBraceLine) 102 , closeBracePos(closeBracePos) 103 { 104 } 105 unsigned approximateByteSize() const 106 { 107 // The identifiers are uniqued strings so most likely there are few names that actually use any additional memory. 108 static const unsigned assummedAverageIdentifierSize = sizeof(RefPtr<StringImpl>) + 2; 109 unsigned size = sizeof(*this); 110 size += usedVariables.size() * assummedAverageIdentifierSize; 111 size += writtenVariables.size() * assummedAverageIdentifierSize; 112 return size; 113 } 114 JSToken closeBraceToken() const 115 { 116 JSToken token; 117 token.m_type = CLOSEBRACE; 118 token.m_data.intValue = closeBracePos; 119 token.m_info.startOffset = closeBracePos; 120 token.m_info.endOffset = closeBracePos + 1; 121 token.m_info.line = closeBraceLine; 122 return token; 123 } 124 125 int closeBraceLine; 126 int closeBracePos; 127 bool usesEval; 128 Vector<RefPtr<StringImpl> > usedVariables; 129 Vector<RefPtr<StringImpl> > writtenVariables; 96 130 }; 97 131 … … 418 452 bool isValidStrictMode() const { return m_isValidStrictMode; } 419 453 bool shadowsArguments() const { return m_shadowsArguments; } 454 455 void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector<RefPtr<StringImpl> >& vector) 456 { 457 IdentifierSet::iterator end = capturedVariables.end(); 458 for (IdentifierSet::iterator it = capturedVariables.begin(); it != end; ++it) { 459 if (m_declaredVariables.contains(*it)) 460 continue; 461 vector.append(*it); 462 } 463 vector.shrinkToFit(); 464 } 465 466 void saveFunctionInfo(CachedFunctionInfo* info) 467 { 468 ASSERT(m_isFunction); 469 info->usesEval = m_usesEval; 470 copyCapturedVariablesToVector(m_writtenVariables, info->writtenVariables); 471 copyCapturedVariablesToVector(m_usedVariables, info->usedVariables); 472 } 473 474 void restoreFunctionInfo(const CachedFunctionInfo* info) 475 { 476 ASSERT(m_isFunction); 477 m_usesEval = info->usesEval; 478 unsigned size = info->usedVariables.size(); 479 for (unsigned i = 0; i < size; ++i) 480 m_usedVariables.add(info->usedVariables[i]); 481 size = info->writtenVariables.size(); 482 for (unsigned i = 0; i < size; ++i) 483 m_writtenVariables.add(info->writtenVariables[i]); 484 } 420 485 421 486 private: … … 544 609 545 610 ScopeStack m_scopeStack; 611 612 const CachedFunctionInfo* findCachedFunctionInfo(int openBracePos) 613 { 614 return m_functionCache ? static_cast<const CachedFunctionInfo*>(m_functionCache->get(openBracePos)) : 0; 615 } 616 617 SourceProviderCache* m_functionCache; 546 618 }; 547 619 … … 567 639 , m_nonTrivialExpressionCount(0) 568 640 , m_lastIdentifier(0) 641 , m_functionCache(m_lexer->sourceProvider()->cache()) 569 642 { 570 643 ScopeRef scope = pushScope(); … … 583 656 const char* JSParser::parseProgram() 584 657 { 658 unsigned oldFunctionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0; 585 659 ASTBuilder context(m_globalData, m_lexer); 586 660 if (m_lexer->isReparsing()) … … 597 671 if (scope->shadowsArguments()) 598 672 features |= ShadowsArgumentsFeature; 673 674 unsigned functionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0; 675 if (functionCacheSize != oldFunctionCacheSize) 676 m_lexer->sourceProvider()->notifyCacheSizeChanged(functionCacheSize - oldFunctionCacheSize); 599 677 600 678 m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features, … … 1240 1318 openBracePos = m_token.m_data.intValue; 1241 1319 bodyStartLine = tokenLine(); 1320 1321 if (const CachedFunctionInfo* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBracePos) : 0) { 1322 // If we know about this function already, we can use the cached info and skip the parser to the end of the function. 1323 body = context.createFunctionBody(strictMode()); 1324 1325 functionScope->restoreFunctionInfo(cachedInfo); 1326 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo)); 1327 1328 closeBracePos = cachedInfo->closeBracePos; 1329 m_token = cachedInfo->closeBraceToken(); 1330 m_lexer->setOffset(m_token.m_info.endOffset); 1331 m_lexer->setLineNumber(m_token.m_info.line); 1332 1333 next(); 1334 return true; 1335 } 1336 1242 1337 next(); 1243 1338 … … 1248 1343 failIfTrue(m_globalData->propertyNames->eval == *name); 1249 1344 } 1345 closeBracePos = m_token.m_data.intValue; 1346 1347 // Cache the tokenizer state and the function scope the first time the function is parsed. 1348 // Any future reparsing can then skip the function. 1349 static const int minimumFunctionLengthToCache = 64; 1350 OwnPtr<CachedFunctionInfo> newInfo; 1351 int functionLength = closeBracePos - openBracePos; 1352 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) { 1353 newInfo = adoptPtr(new CachedFunctionInfo(m_token.m_info.line, closeBracePos)); 1354 functionScope->saveFunctionInfo(newInfo.get()); 1355 } 1356 1250 1357 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo)); 1251 1358 matchOrFail(CLOSEBRACE); 1252 closeBracePos = m_token.m_data.intValue; 1359 1360 if (newInfo) 1361 m_functionCache->add(openBracePos, newInfo.release(), newInfo->approximateByteSize()); 1362 1253 1363 next(); 1254 1364 return true; -
trunk/Source/JavaScriptCore/parser/Lexer.h
r75862 r76177 74 74 m_buffer8.resize(0); 75 75 m_buffer16.resize(0); 76 if (UNLIKELY(m_code == m_codeEnd)) 77 m_current = -1; 76 78 } 79 void setLineNumber(int line) 80 { 81 m_lineNumber = line; 82 } 83 84 SourceProvider* sourceProvider() const { return m_source->provider(); } 77 85 78 86 private: -
trunk/Source/JavaScriptCore/parser/SourceProvider.h
r76129 r76177 31 31 32 32 #include "UString.h" 33 #include <wtf/HashMap.h> 34 #include <wtf/PassOwnPtr.h> 33 35 #include <wtf/RefCounted.h> 36 #include <wtf/UnusedParam.h> 34 37 #include <wtf/text/TextPosition.h> 38 35 39 36 40 namespace JSC { 37 41 42 class SourceProviderCache { 43 public: 44 struct Item {}; 45 46 SourceProviderCache() : m_contentByteSize(0) {} 47 ~SourceProviderCache() { deleteAllValues(m_map); } 48 49 unsigned byteSize() const { return m_contentByteSize + sizeof(*this) + m_map.capacity() * sizeof(Item*); } 50 void add(int sourcePosition, PassOwnPtr<Item> item, unsigned size) { m_map.add(sourcePosition, item.leakPtr()); m_contentByteSize += size; } 51 const Item* get(int sourcePosition) const { return m_map.get(sourcePosition); } 52 53 private: 54 HashMap<int, Item*> m_map; 55 unsigned m_contentByteSize; 56 }; 57 38 58 class SourceProvider : public RefCounted<SourceProvider> { 39 59 public: 40 SourceProvider(const UString& url )60 SourceProvider(const UString& url, SourceProviderCache* cache = 0) 41 61 : m_url(url) 42 62 , m_validated(false) 63 , m_cache(cache ? cache : new SourceProviderCache) 64 , m_cacheOwned(!cache) 43 65 { 44 66 } 45 virtual ~SourceProvider() { } 67 virtual ~SourceProvider() 68 { 69 if (m_cacheOwned) 70 delete m_cache; 71 } 46 72 47 73 virtual UString getRange(int start, int end) const = 0; … … 56 82 void setValid() { m_validated = true; } 57 83 84 SourceProviderCache* cache() const { return m_cache; } 85 void notifyCacheSizeChanged(int delta) { if (!m_cacheOwned) cacheSizeChanged(delta); } 86 58 87 private: 88 virtual void cacheSizeChanged(int delta) { UNUSED_PARAM(delta); } 89 59 90 UString m_url; 60 91 bool m_validated; 92 SourceProviderCache* m_cache; 93 bool m_cacheOwned; 61 94 }; 62 95 -
trunk/Source/JavaScriptCore/parser/SyntaxChecker.h
r75896 r76177 113 113 static const bool CreatesAST = false; 114 114 static const bool NeedsFreeVariableInfo = false; 115 static const bool CanUseFunctionCache = true; 115 116 116 117 int createSourceElements() { return 1; } -
trunk/Source/WebCore/ChangeLog
r76175 r76177 1 2011-01-19 Antti Koivisto <antti@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 Cache function offsets to speed up javascript parsing 6 https://bugs.webkit.org/show_bug.cgi?id=52622 7 8 Use cache to save function offsets and some other info. 9 This avoids quite a bit of work when reparsing the source. 10 11 * bindings/js/CachedScriptSourceProvider.h: 12 (WebCore::CachedScriptSourceProvider::cache): 13 (WebCore::CachedScriptSourceProvider::cacheSizeChanged): 14 (WebCore::CachedScriptSourceProvider::CachedScriptSourceProvider): 15 * bindings/js/ScriptSourceProvider.h: 16 (WebCore::ScriptSourceProvider::ScriptSourceProvider): 17 * loader/cache/CachedScript.cpp: 18 (WebCore::CachedScript::destroyDecodedData): 19 (WebCore::CachedScript::sourceProviderCache): 20 (WebCore::CachedScript::sourceProviderCacheSizeChanged): 21 * loader/cache/CachedScript.h: 22 1 23 2011-01-11 Martin Robinson <mrobinson@igalia.com> 2 24 -
trunk/Source/WebCore/bindings/js/CachedScriptSourceProvider.h
r60275 r76177 50 50 const String& source() const { return m_cachedScript->script(); } 51 51 52 virtual void cacheSizeChanged(int delta) 53 { 54 m_cachedScript->sourceProviderCacheSizeChanged(delta); 55 } 56 52 57 private: 53 58 CachedScriptSourceProvider(CachedScript* cachedScript) 54 : ScriptSourceProvider(stringToUString(cachedScript->url()) )59 : ScriptSourceProvider(stringToUString(cachedScript->url()), cachedScript->sourceProviderCache()) 55 60 , m_cachedScript(cachedScript) 56 61 { -
trunk/Source/WebCore/bindings/js/ScriptSourceProvider.h
r65021 r76177 35 35 class ScriptSourceProvider : public JSC::SourceProvider { 36 36 public: 37 ScriptSourceProvider(const JSC::UString& url )38 : SourceProvider(url )37 ScriptSourceProvider(const JSC::UString& url, JSC::SourceProviderCache* cache = 0) 38 : SourceProvider(url, cache) 39 39 { 40 40 } -
trunk/Source/WebCore/loader/cache/CachedScript.cpp
r72230 r76177 34 34 #include "TextResourceDecoder.h" 35 35 #include <wtf/Vector.h> 36 37 #if USE(JSC) 38 #include <parser/SourceProvider.h> 39 #endif 36 40 37 41 namespace WebCore { … … 112 116 { 113 117 m_script = String(); 114 setDecodedSize(0); 118 unsigned extraSize = 0; 119 #if USE(JSC) 120 // FIXME: SourceInfoCache should be wiped out too but not this easily. 121 extraSize = m_sourceProviderCache ? m_sourceProviderCache->byteSize() : 0; 122 #endif 123 setDecodedSize(extraSize); 115 124 if (!MemoryCache::shouldMakeResourcePurgeableOnEviction() && isSafeToMakePurgeable()) 116 125 makePurgeable(true); … … 122 131 } 123 132 133 #if USE(JSC) 134 JSC::SourceProviderCache* CachedScript::sourceProviderCache() const 135 { 136 if (!m_sourceProviderCache) 137 m_sourceProviderCache = adoptPtr(new JSC::SourceProviderCache); 138 return m_sourceProviderCache.get(); 139 } 140 141 void CachedScript::sourceProviderCacheSizeChanged(int delta) 142 { 143 setDecodedSize(decodedSize() + delta); 144 } 145 #endif 146 124 147 } // namespace WebCore -
trunk/Source/WebCore/loader/cache/CachedScript.h
r72230 r76177 30 30 #include "Timer.h" 31 31 32 #if USE(JSC) 33 namespace JSC { 34 class SourceProviderCache; 35 } 36 #endif 37 32 38 namespace WebCore { 33 39 … … 52 58 53 59 virtual void destroyDecodedData(); 54 60 #if USE(JSC) 61 // Allows JSC to cache additional information about the source. 62 JSC::SourceProviderCache* sourceProviderCache() const; 63 void sourceProviderCacheSizeChanged(int delta); 64 #endif 55 65 private: 56 66 void decodedDataDeletionTimerFired(Timer<CachedScript>*); … … 60 70 RefPtr<TextResourceDecoder> m_decoder; 61 71 Timer<CachedScript> m_decodedDataDeletionTimer; 72 #if USE(JSC) 73 mutable OwnPtr<JSC::SourceProviderCache> m_sourceProviderCache; 74 #endif 62 75 }; 63 76 }
Note: See TracChangeset
for help on using the changeset viewer.