Changeset 76177 in webkit for trunk/Source/JavaScriptCore
- Timestamp:
- Jan 19, 2011, 4:13:03 PM (14 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r76176 r76177 1 2011-01-19 Antti Koivisto <[email protected]> 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 <[email protected]> 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; }
Note:
See TracChangeset
for help on using the changeset viewer.