1 | // Copyright 2012 the V8 project authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef V8_COMPILATION_CACHE_H_ |
6 | #define V8_COMPILATION_CACHE_H_ |
7 | |
8 | #include "src/allocation.h" |
9 | #include "src/objects/compilation-cache.h" |
10 | |
11 | namespace v8 { |
12 | namespace internal { |
13 | |
14 | template <typename T> |
15 | class Handle; |
16 | |
17 | class RootVisitor; |
18 | |
19 | // The compilation cache consists of several generational sub-caches which uses |
20 | // this class as a base class. A sub-cache contains a compilation cache tables |
21 | // for each generation of the sub-cache. Since the same source code string has |
22 | // different compiled code for scripts and evals, we use separate sub-caches |
23 | // for different compilation modes, to avoid retrieving the wrong result. |
24 | class CompilationSubCache { |
25 | public: |
26 | CompilationSubCache(Isolate* isolate, int generations) |
27 | : isolate_(isolate), |
28 | generations_(generations) { |
29 | tables_ = NewArray<Object>(generations); |
30 | } |
31 | |
32 | ~CompilationSubCache() { DeleteArray(tables_); } |
33 | |
34 | // Index for the first generation in the cache. |
35 | static const int kFirstGeneration = 0; |
36 | |
37 | // Get the compilation cache tables for a specific generation. |
38 | Handle<CompilationCacheTable> GetTable(int generation); |
39 | |
40 | // Accessors for first generation. |
41 | Handle<CompilationCacheTable> GetFirstTable() { |
42 | return GetTable(kFirstGeneration); |
43 | } |
44 | void SetFirstTable(Handle<CompilationCacheTable> value) { |
45 | DCHECK_LT(kFirstGeneration, generations_); |
46 | tables_[kFirstGeneration] = *value; |
47 | } |
48 | |
49 | // Age the sub-cache by evicting the oldest generation and creating a new |
50 | // young generation. |
51 | void Age(); |
52 | |
53 | // GC support. |
54 | void Iterate(RootVisitor* v); |
55 | |
56 | // Clear this sub-cache evicting all its content. |
57 | void Clear(); |
58 | |
59 | // Remove given shared function info from sub-cache. |
60 | void Remove(Handle<SharedFunctionInfo> function_info); |
61 | |
62 | // Number of generations in this sub-cache. |
63 | inline int generations() { return generations_; } |
64 | |
65 | protected: |
66 | Isolate* isolate() { return isolate_; } |
67 | |
68 | private: |
69 | Isolate* isolate_; |
70 | int generations_; // Number of generations. |
71 | Object* tables_; // Compilation cache tables - one for each generation. |
72 | |
73 | DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationSubCache); |
74 | }; |
75 | |
76 | |
77 | // Sub-cache for scripts. |
78 | class CompilationCacheScript : public CompilationSubCache { |
79 | public: |
80 | explicit CompilationCacheScript(Isolate* isolate); |
81 | |
82 | MaybeHandle<SharedFunctionInfo> Lookup(Handle<String> source, |
83 | MaybeHandle<Object> name, |
84 | int line_offset, int column_offset, |
85 | ScriptOriginOptions resource_options, |
86 | Handle<Context> native_context, |
87 | LanguageMode language_mode); |
88 | |
89 | void Put(Handle<String> source, Handle<Context> context, |
90 | LanguageMode language_mode, |
91 | Handle<SharedFunctionInfo> function_info); |
92 | |
93 | private: |
94 | bool HasOrigin(Handle<SharedFunctionInfo> function_info, |
95 | MaybeHandle<Object> name, int line_offset, int column_offset, |
96 | ScriptOriginOptions resource_options); |
97 | |
98 | DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript); |
99 | }; |
100 | |
101 | |
102 | // Sub-cache for eval scripts. Two caches for eval are used. One for eval calls |
103 | // in native contexts and one for eval calls in other contexts. The cache |
104 | // considers the following pieces of information when checking for matching |
105 | // entries: |
106 | // 1. The source string. |
107 | // 2. The shared function info of the calling function. |
108 | // 3. Whether the source should be compiled as strict code or as sloppy code. |
109 | // Note: Currently there are clients of CompileEval that always compile |
110 | // sloppy code even if the calling function is a strict mode function. |
111 | // More specifically these are the CompileString, DebugEvaluate and |
112 | // DebugEvaluateGlobal runtime functions. |
113 | // 4. The start position of the calling scope. |
114 | class CompilationCacheEval: public CompilationSubCache { |
115 | public: |
116 | explicit CompilationCacheEval(Isolate* isolate) |
117 | : CompilationSubCache(isolate, 1) {} |
118 | |
119 | InfoCellPair Lookup(Handle<String> source, |
120 | Handle<SharedFunctionInfo> outer_info, |
121 | Handle<Context> native_context, |
122 | LanguageMode language_mode, int position); |
123 | |
124 | void Put(Handle<String> source, Handle<SharedFunctionInfo> outer_info, |
125 | Handle<SharedFunctionInfo> function_info, |
126 | Handle<Context> native_context, Handle<FeedbackCell> feedback_cell, |
127 | int position); |
128 | |
129 | private: |
130 | DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval); |
131 | }; |
132 | |
133 | |
134 | // Sub-cache for regular expressions. |
135 | class CompilationCacheRegExp: public CompilationSubCache { |
136 | public: |
137 | CompilationCacheRegExp(Isolate* isolate, int generations) |
138 | : CompilationSubCache(isolate, generations) { } |
139 | |
140 | MaybeHandle<FixedArray> Lookup(Handle<String> source, JSRegExp::Flags flags); |
141 | |
142 | void Put(Handle<String> source, |
143 | JSRegExp::Flags flags, |
144 | Handle<FixedArray> data); |
145 | private: |
146 | DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheRegExp); |
147 | }; |
148 | |
149 | // The compilation cache keeps shared function infos for compiled |
150 | // scripts and evals. The shared function infos are looked up using |
151 | // the source string as the key. For regular expressions the |
152 | // compilation data is cached. |
153 | class V8_EXPORT_PRIVATE CompilationCache { |
154 | public: |
155 | // Finds the script shared function info for a source |
156 | // string. Returns an empty handle if the cache doesn't contain a |
157 | // script for the given source string with the right origin. |
158 | MaybeHandle<SharedFunctionInfo> LookupScript( |
159 | Handle<String> source, MaybeHandle<Object> name, int line_offset, |
160 | int column_offset, ScriptOriginOptions resource_options, |
161 | Handle<Context> native_context, LanguageMode language_mode); |
162 | |
163 | // Finds the shared function info for a source string for eval in a |
164 | // given context. Returns an empty handle if the cache doesn't |
165 | // contain a script for the given source string. |
166 | InfoCellPair LookupEval(Handle<String> source, |
167 | Handle<SharedFunctionInfo> outer_info, |
168 | Handle<Context> context, LanguageMode language_mode, |
169 | int position); |
170 | |
171 | // Returns the regexp data associated with the given regexp if it |
172 | // is in cache, otherwise an empty handle. |
173 | MaybeHandle<FixedArray> LookupRegExp( |
174 | Handle<String> source, JSRegExp::Flags flags); |
175 | |
176 | // Associate the (source, kind) pair to the shared function |
177 | // info. This may overwrite an existing mapping. |
178 | void PutScript(Handle<String> source, Handle<Context> native_context, |
179 | LanguageMode language_mode, |
180 | Handle<SharedFunctionInfo> function_info); |
181 | |
182 | // Associate the (source, context->closure()->shared(), kind) triple |
183 | // with the shared function info. This may overwrite an existing mapping. |
184 | void PutEval(Handle<String> source, Handle<SharedFunctionInfo> outer_info, |
185 | Handle<Context> context, |
186 | Handle<SharedFunctionInfo> function_info, |
187 | Handle<FeedbackCell> feedback_cell, int position); |
188 | |
189 | // Associate the (source, flags) pair to the given regexp data. |
190 | // This may overwrite an existing mapping. |
191 | void PutRegExp(Handle<String> source, |
192 | JSRegExp::Flags flags, |
193 | Handle<FixedArray> data); |
194 | |
195 | // Clear the cache - also used to initialize the cache at startup. |
196 | void Clear(); |
197 | |
198 | // Remove given shared function info from all caches. |
199 | void Remove(Handle<SharedFunctionInfo> function_info); |
200 | |
201 | // GC support. |
202 | void Iterate(RootVisitor* v); |
203 | |
204 | // Notify the cache that a mark-sweep garbage collection is about to |
205 | // take place. This is used to retire entries from the cache to |
206 | // avoid keeping them alive too long without using them. |
207 | void MarkCompactPrologue(); |
208 | |
209 | // Enable/disable compilation cache. Used by debugger to disable compilation |
210 | // cache during debugging to make sure new scripts are always compiled. |
211 | void Enable(); |
212 | void Disable(); |
213 | |
214 | private: |
215 | explicit CompilationCache(Isolate* isolate); |
216 | ~CompilationCache() = default; |
217 | |
218 | base::HashMap* EagerOptimizingSet(); |
219 | |
220 | // The number of sub caches covering the different types to cache. |
221 | static const int kSubCacheCount = 4; |
222 | |
223 | bool IsEnabled() const { return FLAG_compilation_cache && enabled_; } |
224 | |
225 | Isolate* isolate() const { return isolate_; } |
226 | |
227 | Isolate* isolate_; |
228 | |
229 | CompilationCacheScript script_; |
230 | CompilationCacheEval eval_global_; |
231 | CompilationCacheEval eval_contextual_; |
232 | CompilationCacheRegExp reg_exp_; |
233 | CompilationSubCache* subcaches_[kSubCacheCount]; |
234 | |
235 | // Current enable state of the compilation cache. |
236 | bool enabled_; |
237 | |
238 | friend class Isolate; |
239 | |
240 | DISALLOW_COPY_AND_ASSIGN(CompilationCache); |
241 | }; |
242 | |
243 | } // namespace internal |
244 | } // namespace v8 |
245 | |
246 | #endif // V8_COMPILATION_CACHE_H_ |
247 | |