tizen beta release
[profile/ivi/webkit-efl.git] / Source / JavaScriptCore / 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             iter->second.codeBlock->m_shouldDiscardBytecode = iter->second.oldValueOfShouldDiscardBytecode;
142         }
143     }
144     
145     CodeBlock* get(const CodeBlockKey& key, ScopeChainNode* scope)
146     {
147         Map::iterator iter = m_map.find(key);
148         if (iter != m_map.end())
149             return iter->second.codeBlock;
150         
151         ByteCodeCacheValue value;
152         
153         // First see if there is already a parsed code block that still has some
154         // bytecode in it.
155         value.codeBlock = key.executable()->codeBlockWithBytecodeFor(key.kind());
156         if (value.codeBlock) {
157             value.owned = false;
158             value.oldValueOfShouldDiscardBytecode = value.codeBlock->m_shouldDiscardBytecode;
159         } else {
160             // Nope, so try to parse one.
161             JSObject* exception;
162             value.owned = true;
163             value.codeBlock = key.executable()->produceCodeBlockFor(scope, OptimizingCompilation, key.kind(), exception).leakPtr();
164         }
165         
166         // Check if there is any reason to reject this from our cache. If so, then
167         // poison it.
168         if (!!value.codeBlock && !filterFunction(value.codeBlock, key.kind())) {
169             if (value.owned)
170                 delete value.codeBlock;
171             value.codeBlock = 0;
172         }
173         
174         // If we're about to return a code block, make sure that we're not going
175         // to be discarding its bytecode if a GC were to happen during DFG
176         // compilation. That's unlikely, but it's good to thoroughly enjoy this
177         // kind of paranoia.
178         if (!!value.codeBlock)
179             value.codeBlock->m_shouldDiscardBytecode = false;
180         
181         m_map.add(key, value);
182         
183         return value.codeBlock;
184     }
185
186 private:
187     Map m_map;
188 };
189
190 } } // namespace JSC::DFG
191
192 #endif // ENABLE(DFG_JIT)
193
194 #endif // DFGByteCodeCache_h