| /* |
| * Copyright (C) 2012 Apple Inc. All Rights Reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef CodeCache_h |
| #define CodeCache_h |
| |
| #include "CodeSpecializationKind.h" |
| #include "ParserModes.h" |
| #include "Strong.h" |
| #include "WeakRandom.h" |
| |
| #include <wtf/FixedArray.h> |
| #include <wtf/Forward.h> |
| #include <wtf/PassOwnPtr.h> |
| #include <wtf/RandomNumber.h> |
| #include <wtf/text/WTFString.h> |
| |
| namespace JSC { |
| |
| class EvalExecutable; |
| class FunctionBodyNode; |
| class Identifier; |
| class ProgramExecutable; |
| class UnlinkedCodeBlock; |
| class UnlinkedEvalCodeBlock; |
| class UnlinkedFunctionCodeBlock; |
| class UnlinkedFunctionExecutable; |
| class UnlinkedProgramCodeBlock; |
| class JSGlobalData; |
| struct ParserError; |
| class SourceCode; |
| class SourceProvider; |
| |
| template <typename KeyType, typename EntryType, int CacheSize> class CacheMap { |
| typedef typename HashMap<KeyType, unsigned>::iterator iterator; |
| public: |
| CacheMap() |
| : m_randomGenerator((static_cast<uint32_t>(randomNumber() * std::numeric_limits<uint32_t>::max()))) |
| { |
| } |
| const EntryType* find(const KeyType& key) |
| { |
| iterator result = m_map.find(key); |
| if (result == m_map.end()) |
| return 0; |
| return &m_data[result->value].second; |
| } |
| void add(const KeyType& key, const EntryType& value) |
| { |
| iterator result = m_map.find(key); |
| if (result != m_map.end()) { |
| m_data[result->value].second = value; |
| return; |
| } |
| size_t newIndex = m_randomGenerator.getUint32() % CacheSize; |
| if (m_data[newIndex].second) |
| m_map.remove(m_data[newIndex].first); |
| m_map.add(key, newIndex); |
| m_data[newIndex].first = key; |
| m_data[newIndex].second = value; |
| ASSERT(m_map.size() <= CacheSize); |
| } |
| |
| void clear() |
| { |
| m_map.clear(); |
| for (size_t i = 0; i < CacheSize; i++) { |
| m_data[i].first = KeyType(); |
| m_data[i].second = EntryType(); |
| } |
| } |
| |
| |
| private: |
| HashMap<KeyType, unsigned> m_map; |
| FixedArray<std::pair<KeyType, EntryType>, CacheSize> m_data; |
| WeakRandom m_randomGenerator; |
| }; |
| |
| class CodeCache { |
| public: |
| static PassOwnPtr<CodeCache> create() { return adoptPtr(new CodeCache); } |
| |
| UnlinkedProgramCodeBlock* getProgramCodeBlock(JSGlobalData&, ProgramExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&); |
| UnlinkedEvalCodeBlock* getEvalCodeBlock(JSGlobalData&, EvalExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&); |
| UnlinkedFunctionCodeBlock* getFunctionCodeBlock(JSGlobalData&, UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&); |
| UnlinkedFunctionExecutable* getFunctionExecutableFromGlobalCode(JSGlobalData&, const Identifier&, const SourceCode&, ParserError&); |
| void usedFunctionCode(JSGlobalData&, UnlinkedFunctionCodeBlock*); |
| ~CodeCache(); |
| |
| void clear() |
| { |
| m_cachedCodeBlocks.clear(); |
| m_cachedGlobalFunctions.clear(); |
| m_recentlyUsedFunctionCode.clear(); |
| } |
| |
| enum CodeType { EvalType, ProgramType, FunctionCallType, FunctionConstructType }; |
| typedef std::pair<String, unsigned> CodeBlockKey; |
| typedef std::pair<String, String> GlobalFunctionKey; |
| |
| private: |
| CodeCache(); |
| |
| UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(JSGlobalData&, UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&); |
| |
| template <class UnlinkedCodeBlockType, class ExecutableType> inline UnlinkedCodeBlockType* getCodeBlock(JSGlobalData&, ExecutableType*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&); |
| CodeBlockKey makeCodeBlockKey(const SourceCode&, CodeType, JSParserStrictness); |
| GlobalFunctionKey makeGlobalFunctionKey(const SourceCode&, const String&); |
| |
| enum { |
| kMaxRootCodeBlockEntries = 1024, |
| kMaxGlobalFunctionEntries = 1024, |
| // Sampling content on a number of sites indicates that |
| // on average there are 6-7 functions used per root codeblock. |
| // So we'll allow an average of 8 to give some leeway for increasing |
| // page complexity over time. Note that is simply a probabalistic |
| // measure and does not result in a hard limit of cache entries |
| // in each code block. |
| kMaxFunctionCodeBlocks = kMaxRootCodeBlockEntries * 8 |
| }; |
| |
| CacheMap<CodeBlockKey, Strong<UnlinkedCodeBlock>, kMaxRootCodeBlockEntries> m_cachedCodeBlocks; |
| CacheMap<GlobalFunctionKey, Strong<UnlinkedFunctionExecutable>, kMaxFunctionCodeBlocks> m_cachedGlobalFunctions; |
| CacheMap<UnlinkedFunctionCodeBlock*, Strong<UnlinkedFunctionCodeBlock>, kMaxFunctionCodeBlocks> m_recentlyUsedFunctionCode; |
| }; |
| |
| } |
| |
| #endif |