Changeset 76177 in webkit for trunk/Source/JavaScriptCore/parser/JSParser.cpp
- Timestamp:
- Jan 19, 2011, 4:13:03 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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;
Note:
See TracChangeset
for help on using the changeset viewer.