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