]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGByteCodeCache.h
JavaScriptCore-1097.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGByteCodeCache.h
1 /*
2 * Copyright (C) 2011 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 DFGByteCodeCache_h
27 #define DFGByteCodeCache_h
28
29 #include <wtf/Platform.h>
30
31 #if ENABLE(DFG_JIT)
32
33 #include "CodeBlock.h"
34 #include "Executable.h"
35 #include "JSFunction.h"
36 #include <wtf/HashMap.h>
37
38 namespace JSC { namespace DFG {
39
40 class CodeBlockKey {
41 public:
42 CodeBlockKey()
43 : m_executable(0)
44 , m_kind(CodeForCall) // CodeForCall = empty value
45 {
46 }
47
48 CodeBlockKey(WTF::HashTableDeletedValueType)
49 : m_executable(0)
50 , m_kind(CodeForConstruct) // CodeForConstruct = deleted value
51 {
52 }
53
54 CodeBlockKey(FunctionExecutable* executable, CodeSpecializationKind kind)
55 : m_executable(executable)
56 , m_kind(kind)
57 {
58 }
59
60 bool operator==(const CodeBlockKey& other) const
61 {
62 return m_executable == other.m_executable
63 && m_kind == other.m_kind;
64 }
65
66 unsigned hash() const
67 {
68 return WTF::PtrHash<FunctionExecutable*>::hash(m_executable) ^ static_cast<unsigned>(m_kind);
69 }
70
71 FunctionExecutable* executable() const { return m_executable; }
72 CodeSpecializationKind kind() const { return m_kind; }
73
74 bool isHashTableDeletedValue() const
75 {
76 return !m_executable && m_kind == CodeForConstruct;
77 }
78
79 private:
80 FunctionExecutable* m_executable;
81 CodeSpecializationKind m_kind;
82 };
83
84 struct CodeBlockKeyHash {
85 static unsigned hash(const CodeBlockKey& key) { return key.hash(); }
86 static bool equal(const CodeBlockKey& a, const CodeBlockKey& b) { return a == b; }
87
88 static const bool safeToCompareToEmptyOrDeleted = true;
89 };
90
91 } } // namespace JSC::DFG
92
93 namespace WTF {
94
95 template<typename T> struct DefaultHash;
96 template<> struct DefaultHash<JSC::DFG::CodeBlockKey> {
97 typedef JSC::DFG::CodeBlockKeyHash Hash;
98 };
99
100 template<typename T> struct HashTraits;
101 template<> struct HashTraits<JSC::DFG::CodeBlockKey> : SimpleClassHashTraits<JSC::DFG::CodeBlockKey> { };
102
103 } // namespace WTF
104
105 namespace JSC { namespace DFG {
106
107 struct ByteCodeCacheValue {
108 FunctionCodeBlock* codeBlock;
109 bool owned;
110 bool oldValueOfShouldDiscardBytecode;
111
112 // All uses of this struct initialize everything manually. But gcc isn't
113 // smart enough to see that, so this constructor is just here to make the
114 // compiler happy.
115 ByteCodeCacheValue()
116 : codeBlock(0)
117 , owned(false)
118 , oldValueOfShouldDiscardBytecode(false)
119 {
120 }
121 };
122
123 template<bool (*filterFunction)(CodeBlock*, CodeSpecializationKind)>
124 class ByteCodeCache {
125 public:
126 typedef HashMap<CodeBlockKey, ByteCodeCacheValue> Map;
127
128 ByteCodeCache() { }
129
130 ~ByteCodeCache()
131 {
132 Map::iterator begin = m_map.begin();
133 Map::iterator end = m_map.end();
134 for (Map::iterator iter = begin; iter != end; ++iter) {
135 if (!iter->second.codeBlock)
136 continue;
137 if (iter->second.owned) {
138 delete iter->second.codeBlock;
139 continue;
140 }
141 }
142 }
143
144 CodeBlock* get(const CodeBlockKey& key, ScopeChainNode* scope)
145 {
146 Map::iterator iter = m_map.find(key);
147 if (iter != m_map.end())
148 return iter->second.codeBlock;
149
150 ByteCodeCacheValue value;
151
152 // First see if there is already a parsed code block that still has some
153 // bytecode in it.
154 value.codeBlock = key.executable()->codeBlockWithBytecodeFor(key.kind());
155 if (value.codeBlock) {
156 value.owned = false;
157 } else {
158 // Nope, so try to parse one.
159 JSObject* exception;
160 value.owned = true;
161 value.codeBlock = key.executable()->produceCodeBlockFor(scope, OptimizingCompilation, key.kind(), exception).leakPtr();
162 }
163
164 // Check if there is any reason to reject this from our cache. If so, then
165 // poison it.
166 if (!!value.codeBlock && !filterFunction(value.codeBlock, key.kind())) {
167 if (value.owned)
168 delete value.codeBlock;
169 value.codeBlock = 0;
170 }
171
172 m_map.add(key, value);
173
174 return value.codeBlock;
175 }
176
177 private:
178 Map m_map;
179 };
180
181 } } // namespace JSC::DFG
182
183 #endif // ENABLE(DFG_JIT)
184
185 #endif // DFGByteCodeCache_h