Changeset 133975 in webkit
- Timestamp:
- Nov 8, 2012 5:12:47 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r133971 r133975 1 2012-11-08 Oliver Hunt <oliver@apple.com> 2 3 Improve effectiveness of function-level caching 4 https://bugs.webkit.org/show_bug.cgi?id=101667 5 6 Reviewed by Filip Pizlo. 7 8 Added a random-eviction based cache for unlinked functions, and switch 9 UnlinkedFunctionExecutable's code references to Weak<>, thereby letting 10 us remove the explicit UnlinkedFunctionExecutable::clearCode() calls that 11 were being triggered by GC. 12 13 Refactored the random eviction part of the CodeCache into a separate data 14 structure so that I didn't have to duplicate the code again, and then used 15 that for the new function cache. 16 17 * bytecode/UnlinkedCodeBlock.cpp: 18 (JSC::UnlinkedFunctionExecutable::visitChildren): 19 (JSC::UnlinkedFunctionExecutable::codeBlockFor): 20 * bytecode/UnlinkedCodeBlock.h: 21 (JSC::UnlinkedFunctionExecutable::clearCodeForRecompilation): 22 (UnlinkedFunctionExecutable): 23 * debugger/Debugger.cpp: 24 * runtime/CodeCache.cpp: 25 (JSC::CodeCache::getCodeBlock): 26 (JSC::CodeCache::generateFunctionCodeBlock): 27 (JSC::CodeCache::getFunctionExecutableFromGlobalCode): 28 (JSC::CodeCache::usedFunctionCode): 29 (JSC): 30 * runtime/Executable.cpp: 31 (JSC::FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling): 32 (JSC::FunctionExecutable::clearCode): 33 * runtime/Executable.h: 34 (FunctionExecutable): 35 1 36 2012-11-07 Filip Pizlo <fpizlo@apple.com> 2 37 -
trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
r133953 r133975 81 81 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); 82 82 Base::visitChildren(thisObject, visitor); 83 visitor.append(&thisObject->m_codeBlockForCall);84 visitor.append(&thisObject->m_codeBlockForConstruct);85 83 visitor.append(&thisObject->m_nameValue); 86 84 visitor.append(&thisObject->m_symbolTableForCall); … … 113 111 switch (specializationKind) { 114 112 case CodeForCall: 115 if (m_codeBlockForCall) 116 return m_codeBlockForCall.get(); 113 if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForCall.get()) { 114 globalData.codeCache()->usedFunctionCode(globalData, codeBlock); 115 return codeBlock; 116 } 117 117 break; 118 118 case CodeForConstruct: 119 if (m_codeBlockForConstruct) 120 return m_codeBlockForConstruct.get(); 119 if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForConstruct.get()) { 120 globalData.codeCache()->usedFunctionCode(globalData, codeBlock); 121 return codeBlock; 122 } 121 123 break; 122 124 } … … 129 131 switch (specializationKind) { 130 132 case CodeForCall: 131 m_codeBlockForCall .set(globalData, this,result);133 m_codeBlockForCall = PassWeak<UnlinkedFunctionCodeBlock>(result); 132 134 m_symbolTableForCall.set(globalData, this, result->symbolTable()); 133 135 break; 134 136 case CodeForConstruct: 135 m_codeBlockForConstruct .set(globalData, this,result);137 m_codeBlockForConstruct = PassWeak<UnlinkedFunctionCodeBlock>(result); 136 138 m_symbolTableForConstruct.set(globalData, this, result->symbolTable()); 137 139 break; -
trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
r133953 r133975 37 37 #include "RegExp.h" 38 38 #include "SpecialPointer.h" 39 #include "Weak.h" 39 40 40 41 #include <wtf/RefCountedArray.h> … … 109 110 FunctionExecutable* link(JSGlobalData&, const SourceCode&, size_t lineOffset, size_t sourceOffset); 110 111 111 void clearCode ()112 void clearCodeForRecompilation() 112 113 { 113 114 m_symbolTableForCall.clear(); … … 137 138 private: 138 139 UnlinkedFunctionExecutable(JSGlobalData*, Structure*, const SourceCode&, FunctionBodyNode*); 139 W riteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;140 W riteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;140 Weak<UnlinkedFunctionCodeBlock> m_codeBlockForCall; 141 Weak<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct; 141 142 142 143 unsigned m_numCapturedVariables : 29; -
trunk/Source/JavaScriptCore/debugger/Debugger.cpp
r133688 r133975 81 81 ExecState* exec = function->scope()->globalObject()->JSGlobalObject::globalExec(); 82 82 executable->clearCodeIfNotCompiling(); 83 executable->clearUnlinkedCode IfNotCompiling();83 executable->clearUnlinkedCodeForRecompilationIfNotCompiling(); 84 84 if (m_debugger == function->scope()->globalObject()->debugger()) 85 85 m_sourceProviders.add(executable->source().provider(), exec); -
trunk/Source/JavaScriptCore/runtime/CodeCache.cpp
r133688 r133975 37 37 38 38 CodeCache::CodeCache() 39 : m_randomGenerator(static_cast<uint32_t>(randomNumber() * UINT32_MAX))40 39 { 41 40 } … … 68 67 bool storeInCache = false; 69 68 if (debuggerMode == DebuggerOff && profilerMode == ProfilerOff) { 70 CodeBlockIndicesMap::iterator result = m_cachedCodeBlockIndices.find(key);71 if (result != m_cachedCodeBlockIndices.end()) {72 UnlinkedCodeBlockType* unlinkedCode = jsCast<UnlinkedCodeBlockType*>( m_cachedCodeBlocks[result->value].second.get());69 const Strong<UnlinkedCodeBlock>* result = m_cachedCodeBlocks.find(key); 70 if (result) { 71 UnlinkedCodeBlockType* unlinkedCode = jsCast<UnlinkedCodeBlockType*>(result->get()); 73 72 unsigned firstLine = source.firstLine() + unlinkedCode->firstLine(); 74 73 executable->recordParse(unlinkedCode->codeFeatures(), unlinkedCode->hasCapturedVariables(), firstLine, firstLine + unlinkedCode->lineCount()); … … 92 91 return 0; 93 92 94 if (storeInCache) { 95 size_t index = m_randomGenerator.getUint32() % kMaxCodeBlockEntries; 96 if (m_cachedCodeBlocks[index].second) 97 m_cachedCodeBlockIndices.remove(m_cachedCodeBlocks[index].first); 98 m_cachedCodeBlockIndices.set(key, index); 99 m_cachedCodeBlocks[index].second.set(globalData, unlinkedCode); 100 m_cachedCodeBlocks[index].first = key; 101 } 93 if (storeInCache) 94 m_cachedCodeBlocks.add(key, Strong<UnlinkedCodeBlock>(globalData, unlinkedCode)); 102 95 103 96 return unlinkedCode; … … 134 127 if (error.m_type != ParserError::ErrorNone) 135 128 return 0; 129 m_cachedFunctionCode.add(result, Strong<UnlinkedFunctionCodeBlock>(globalData, result)); 136 130 return result; 137 131 } … … 150 144 { 151 145 GlobalFunctionKey key = makeGlobalFunctionKey(source, name.string()); 152 GlobalFunctionIndicesMap::iterator result = m_cachedGlobalFunctionIndices.find(key);153 if (result != m_cachedGlobalFunctionIndices.end())154 return m_cachedGlobalFunctions[result->value].second.get();146 const Strong<UnlinkedFunctionExecutable>* result = m_cachedGlobalFunctions.find(key); 147 if (result) 148 return result->get(); 155 149 156 150 RefPtr<ProgramNode> program = parse<ProgramNode>(&globalData, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error); … … 174 168 functionExecutable->m_nameValue.set(globalData, functionExecutable, jsString(&globalData, name.string())); 175 169 176 size_t index = m_randomGenerator.getUint32() % kMaxGlobalFunctionEntries; 177 if (m_cachedGlobalFunctions[index].second) 178 m_cachedGlobalFunctionIndices.remove(m_cachedGlobalFunctions[index].first); 179 m_cachedGlobalFunctionIndices.set(key, index); 180 m_cachedGlobalFunctions[index].second.set(globalData, functionExecutable); 181 m_cachedGlobalFunctions[index].first = key; 182 170 m_cachedGlobalFunctions.add(key, Strong<UnlinkedFunctionExecutable>(globalData, functionExecutable)); 183 171 return functionExecutable; 184 172 } 185 173 174 void CodeCache::usedFunctionCode(JSGlobalData& globalData, UnlinkedFunctionCodeBlock* codeBlock) 175 { 176 m_cachedFunctionCode.add(codeBlock, Strong<UnlinkedFunctionCodeBlock>(globalData, codeBlock)); 186 177 } 178 179 } -
trunk/Source/JavaScriptCore/runtime/CodeCache.h
r133688 r133975 35 35 #include <wtf/Forward.h> 36 36 #include <wtf/PassOwnPtr.h> 37 #include <wtf/RandomNumber.h> 37 38 #include <wtf/text/WTFString.h> 38 39 … … 52 53 class SourceProvider; 53 54 55 template <typename KeyType, typename EntryType, int CacheSize> class Thingy { 56 typedef typename HashMap<KeyType, unsigned>::iterator iterator; 57 public: 58 Thingy() 59 : m_randomGenerator((static_cast<uint32_t>(randomNumber() * UINT32_MAX))) 60 { 61 } 62 const EntryType* find(const KeyType& key) 63 { 64 iterator result = m_map.find(key); 65 if (result == m_map.end()) 66 return 0; 67 return &m_data[result->value].second; 68 } 69 void add(const KeyType& key, const EntryType& value) 70 { 71 iterator result = m_map.find(key); 72 if (result != m_map.end()) { 73 m_data[result->value].second = value; 74 return; 75 } 76 size_t newIndex = m_randomGenerator.getUint32() % CacheSize; 77 if (m_data[newIndex].second) 78 m_map.remove(m_data[newIndex].first); 79 m_map.add(key, newIndex); 80 m_data[newIndex].first = key; 81 m_data[newIndex].second = value; 82 ASSERT(m_map.size() <= CacheSize); 83 } 84 private: 85 HashMap<KeyType, unsigned> m_map; 86 FixedArray<std::pair<KeyType, EntryType>, CacheSize> m_data; 87 WeakRandom m_randomGenerator; 88 }; 89 54 90 class CodeCache { 55 91 public: … … 60 96 UnlinkedFunctionCodeBlock* getFunctionCodeBlock(JSGlobalData&, UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&); 61 97 UnlinkedFunctionExecutable* getFunctionExecutableFromGlobalCode(JSGlobalData&, const Identifier&, const SourceCode&, ParserError&); 98 void usedFunctionCode(JSGlobalData&, UnlinkedFunctionCodeBlock*); 62 99 ~CodeCache(); 63 100 64 101 enum CodeType { EvalType, ProgramType, FunctionType }; 65 102 typedef std::pair<String, unsigned> CodeBlockKey; 66 typedef HashMap<CodeBlockKey, unsigned> CodeBlockIndicesMap;67 103 typedef std::pair<String, String> GlobalFunctionKey; 68 typedef HashMap<GlobalFunctionKey, unsigned> GlobalFunctionIndicesMap;69 104 70 105 private: … … 75 110 template <class UnlinkedCodeBlockType, class ExecutableType> inline UnlinkedCodeBlockType* getCodeBlock(JSGlobalData&, ExecutableType*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&); 76 111 CodeBlockKey makeCodeBlockKey(const SourceCode&, CodeType, JSParserStrictness); 77 CodeBlockIndicesMap m_cachedCodeBlockIndices;78 112 GlobalFunctionKey makeGlobalFunctionKey(const SourceCode&, const String&); 79 GlobalFunctionIndicesMap m_cachedGlobalFunctionIndices;80 113 81 114 enum { 82 115 kMaxCodeBlockEntries = 1024, 83 kMaxGlobalFunctionEntries = 1024 116 kMaxGlobalFunctionEntries = 1024, 117 kMaxFunctionCodeBlocks = 1024 84 118 }; 85 119 86 FixedArray<std::pair<CodeBlockKey, Strong<UnlinkedCodeBlock>>, kMaxCodeBlockEntries> m_cachedCodeBlocks;87 FixedArray<std::pair<GlobalFunctionKey, Strong<UnlinkedFunctionExecutable>>, kMaxGlobalFunctionEntries> m_cachedGlobalFunctions;88 WeakRandom m_randomGenerator;120 Thingy<CodeBlockKey, Strong<UnlinkedCodeBlock>, kMaxCodeBlockEntries> m_cachedCodeBlocks; 121 Thingy<GlobalFunctionKey, Strong<UnlinkedFunctionExecutable>, kMaxGlobalFunctionEntries> m_cachedGlobalFunctions; 122 Thingy<UnlinkedFunctionCodeBlock*, Strong<UnlinkedFunctionCodeBlock>, kMaxFunctionCodeBlocks> m_cachedFunctionCode; 89 123 }; 90 124 -
trunk/Source/JavaScriptCore/runtime/Executable.cpp
r133688 r133975 621 621 } 622 622 623 void FunctionExecutable::clearUnlinkedCode IfNotCompiling()623 void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling() 624 624 { 625 625 if (isCompiling()) 626 626 return; 627 m_unlinkedExecutable->clearCode ();627 m_unlinkedExecutable->clearCodeForRecompilation(); 628 628 } 629 629 … … 632 632 m_codeBlockForCall.clear(); 633 633 m_codeBlockForConstruct.clear(); 634 m_unlinkedExecutable->clearCode();635 634 Base::clearCode(); 636 635 } -
trunk/Source/JavaScriptCore/runtime/Executable.h
r133688 r133975 705 705 706 706 void clearCodeIfNotCompiling(); 707 void clearUnlinkedCode IfNotCompiling();707 void clearUnlinkedCodeForRecompilationIfNotCompiling(); 708 708 static void visitChildren(JSCell*, SlotVisitor&); 709 709 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
Note: See TracChangeset
for help on using the changeset viewer.