Merged the global function cache into the source code cache
[WebKit-https.git] / Source / JavaScriptCore / runtime / CodeCache.h
1 /*
2  * Copyright (C) 2012 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef CodeCache_h
27 #define CodeCache_h
28
29 #include "CodeSpecializationKind.h"
30 #include "ParserModes.h"
31 #include "SourceCode.h"
32 #include "Strong.h"
33 #include "WeakRandom.h"
34 #include <wtf/FixedArray.h>
35 #include <wtf/Forward.h>
36 #include <wtf/PassOwnPtr.h>
37 #include <wtf/RandomNumber.h>
38 #include <wtf/text/WTFString.h>
39
40 namespace JSC {
41
42 class EvalExecutable;
43 class FunctionBodyNode;
44 class Identifier;
45 class ProgramExecutable;
46 class UnlinkedCodeBlock;
47 class UnlinkedEvalCodeBlock;
48 class UnlinkedFunctionCodeBlock;
49 class UnlinkedFunctionExecutable;
50 class UnlinkedProgramCodeBlock;
51 class JSGlobalData;
52 struct ParserError;
53 class SourceCode;
54 class SourceProvider;
55
56 template <int CacheSize, typename KeyType, typename EntryType, typename HashArg = typename DefaultHash<KeyType>::Hash, typename KeyTraitsArg = HashTraits<KeyType> >
57 class CacheMap {
58     typedef HashMap<KeyType, EntryType, HashArg, KeyTraitsArg> MapType;
59     typedef typename MapType::iterator iterator;
60
61 public:
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 &result->value;
68     }
69
70     void set(const KeyType& key, const EntryType& value)
71     {
72         if (m_map.size() >= CacheSize)
73             m_map.remove(m_map.begin());
74
75         m_map.set(key, value);
76     }
77
78     void clear() { m_map.clear(); }
79
80 private:
81     MapType m_map;
82 };
83
84 class SourceCodeKey {
85 public:
86     enum CodeType { EvalType, ProgramType, FunctionCallType, FunctionConstructType };
87
88     SourceCodeKey()
89         : m_flags(0)
90     {
91     }
92
93     SourceCodeKey(const SourceCode& sourceCode, const String& name, CodeType codeType, JSParserStrictness jsParserStrictness)
94         : m_sourceString(sourceCode.toString())
95         , m_name(name)
96         , m_flags((codeType << 1) | jsParserStrictness)
97     {
98     }
99
100     SourceCodeKey(WTF::HashTableDeletedValueType)
101         : m_sourceString(WTF::HashTableDeletedValue)
102     {
103     }
104
105     bool isHashTableDeletedValue() const { return m_sourceString.isHashTableDeletedValue(); }
106
107     unsigned hash() const { return m_sourceString.impl()->hash(); }
108
109     bool isNull() const { return m_sourceString.isNull(); }
110
111     bool operator==(const SourceCodeKey& other) const
112     {
113         return m_flags == other.m_flags
114             && m_name == other.m_name
115             && m_sourceString == other.m_sourceString;
116     }
117
118 private:
119     String m_sourceString;
120     String m_name;
121     unsigned m_flags;
122 };
123
124 struct SourceCodeKeyHash {
125     static unsigned hash(const SourceCodeKey& key) { return key.hash(); }
126     static bool equal(const SourceCodeKey& a, const SourceCodeKey& b) { return a == b; }
127     static const bool safeToCompareToEmptyOrDeleted = false;
128 };
129
130 struct SourceCodeKeyHashTraits : SimpleClassHashTraits<SourceCodeKey> {
131     static const bool hasIsEmptyValueFunction = true;
132     static bool isEmptyValue(const SourceCodeKey& sourceCodeKey) { return sourceCodeKey.isNull(); }
133 };
134
135 class CodeCache {
136 public:
137     static PassOwnPtr<CodeCache> create() { return adoptPtr(new CodeCache); }
138
139     UnlinkedProgramCodeBlock* getProgramCodeBlock(JSGlobalData&, ProgramExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
140     UnlinkedEvalCodeBlock* getEvalCodeBlock(JSGlobalData&, EvalExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
141     UnlinkedFunctionCodeBlock* getFunctionCodeBlock(JSGlobalData&, UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
142     UnlinkedFunctionExecutable* getFunctionExecutableFromGlobalCode(JSGlobalData&, const Identifier&, const SourceCode&, ParserError&);
143     void usedFunctionCode(JSGlobalData&, UnlinkedFunctionCodeBlock*);
144     ~CodeCache();
145
146     void clear()
147     {
148         m_sourceCode.clear();
149         m_recentlyUsedFunctions.clear();
150     }
151
152 private:
153     CodeCache();
154
155     UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(JSGlobalData&, UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
156
157     template <class UnlinkedCodeBlockType, class ExecutableType> inline UnlinkedCodeBlockType* getCodeBlock(JSGlobalData&, ExecutableType*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
158
159     enum {
160         MaxRootEntries = 1280, // Top-level code such as <script>, eval(), JSEvaluateScript(), etc.
161         MaxChildFunctionEntries = MaxRootEntries * 8 // Sampling shows that each root holds about 6 functions. 8 is enough to usually cache all the child functions for each top-level entry.
162     };
163
164     CacheMap<MaxRootEntries, SourceCodeKey, Strong<JSCell>, SourceCodeKeyHash, SourceCodeKeyHashTraits> m_sourceCode;
165     CacheMap<MaxChildFunctionEntries, UnlinkedFunctionCodeBlock*, Strong<UnlinkedFunctionCodeBlock> > m_recentlyUsedFunctions;
166 };
167
168 }
169
170 #endif // CodeCache_h