| OLD | NEW | 
|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "src/compilation-cache.h" | 5 #include "src/compilation-cache.h" | 
| 6 | 6 | 
| 7 #include "src/counters.h" | 7 #include "src/counters.h" | 
| 8 #include "src/factory.h" | 8 #include "src/factory.h" | 
| 9 #include "src/globals.h" | 9 #include "src/globals.h" | 
| 10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" | 
| 11 | 11 | 
| 12 namespace v8 { | 12 namespace v8 { | 
| 13 namespace internal { | 13 namespace internal { | 
| 14 | 14 | 
| 15 | 15 | 
| 16 // The number of generations for each sub cache. | 16 // The number of generations for each sub cache. | 
| 17 static const int kRegExpGenerations = 2; | 17 static const int kRegExpGenerations = 2; | 
| 18 | 18 | 
| 19 // Initial size of each compilation cache table allocated. | 19 // Initial size of each compilation cache table allocated. | 
| 20 static const int kInitialCacheSize = 64; | 20 static const int kInitialCacheSize = 64; | 
| 21 | 21 | 
| 22 |  | 
| 23 CompilationCache::CompilationCache(Isolate* isolate) | 22 CompilationCache::CompilationCache(Isolate* isolate) | 
| 24     : isolate_(isolate), | 23     : isolate_(isolate), | 
| 25       script_(isolate, 1), | 24       script_(isolate), | 
| 26       eval_global_(isolate, 1), | 25       eval_global_(isolate), | 
| 27       eval_contextual_(isolate, 1), | 26       eval_contextual_(isolate), | 
| 28       reg_exp_(isolate, kRegExpGenerations), | 27       reg_exp_(isolate, kRegExpGenerations), | 
| 29       enabled_(true) { | 28       enabled_(true) { | 
| 30   CompilationSubCache* subcaches[kSubCacheCount] = | 29   CompilationSubCache* subcaches[kSubCacheCount] = | 
| 31     {&script_, &eval_global_, &eval_contextual_, ®_exp_}; | 30     {&script_, &eval_global_, &eval_contextual_, ®_exp_}; | 
| 32   for (int i = 0; i < kSubCacheCount; ++i) { | 31   for (int i = 0; i < kSubCacheCount; ++i) { | 
| 33     subcaches_[i] = subcaches[i]; | 32     subcaches_[i] = subcaches[i]; | 
| 34   } | 33   } | 
| 35 } | 34 } | 
| 36 | 35 | 
| 37 | 36 | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 96   // Probe the script generation tables. Make sure not to leak handles | 95   // Probe the script generation tables. Make sure not to leak handles | 
| 97   // into the caller's handle scope. | 96   // into the caller's handle scope. | 
| 98   { HandleScope scope(isolate()); | 97   { HandleScope scope(isolate()); | 
| 99     for (int generation = 0; generation < generations(); generation++) { | 98     for (int generation = 0; generation < generations(); generation++) { | 
| 100       Handle<CompilationCacheTable> table = GetTable(generation); | 99       Handle<CompilationCacheTable> table = GetTable(generation); | 
| 101       table->Remove(*function_info); | 100       table->Remove(*function_info); | 
| 102     } | 101     } | 
| 103   } | 102   } | 
| 104 } | 103 } | 
| 105 | 104 | 
| 106 | 105 CompilationCacheScript::CompilationCacheScript(Isolate* isolate) | 
| 107 CompilationCacheScript::CompilationCacheScript(Isolate* isolate, | 106     : CompilationSubCache(isolate, 1) {} | 
| 108                                                int generations) |  | 
| 109     : CompilationSubCache(isolate, generations) {} |  | 
| 110 |  | 
| 111 | 107 | 
| 112 // We only re-use a cached function for some script source code if the | 108 // We only re-use a cached function for some script source code if the | 
| 113 // script originates from the same place. This is to avoid issues | 109 // script originates from the same place. This is to avoid issues | 
| 114 // when reporting errors, etc. | 110 // when reporting errors, etc. | 
| 115 bool CompilationCacheScript::HasOrigin(Handle<SharedFunctionInfo> function_info, | 111 bool CompilationCacheScript::HasOrigin(Handle<SharedFunctionInfo> function_info, | 
| 116                                        Handle<Object> name, int line_offset, | 112                                        Handle<Object> name, int line_offset, | 
| 117                                        int column_offset, | 113                                        int column_offset, | 
| 118                                        ScriptOriginOptions resource_options) { | 114                                        ScriptOriginOptions resource_options) { | 
| 119   Handle<Script> script = | 115   Handle<Script> script = | 
| 120       Handle<Script>(Script::cast(function_info->script()), isolate()); | 116       Handle<Script>(Script::cast(function_info->script()), isolate()); | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 134   // Compare the two name strings for equality. | 130   // Compare the two name strings for equality. | 
| 135   return String::Equals(Handle<String>::cast(name), | 131   return String::Equals(Handle<String>::cast(name), | 
| 136                         Handle<String>(String::cast(script->name()))); | 132                         Handle<String>(String::cast(script->name()))); | 
| 137 } | 133 } | 
| 138 | 134 | 
| 139 | 135 | 
| 140 // TODO(245): Need to allow identical code from different contexts to | 136 // TODO(245): Need to allow identical code from different contexts to | 
| 141 // be cached in the same script generation. Currently the first use | 137 // be cached in the same script generation. Currently the first use | 
| 142 // will be cached, but subsequent code from different source / line | 138 // will be cached, but subsequent code from different source / line | 
| 143 // won't. | 139 // won't. | 
| 144 Handle<SharedFunctionInfo> CompilationCacheScript::Lookup( | 140 InfoVectorPair CompilationCacheScript::Lookup( | 
| 145     Handle<String> source, Handle<Object> name, int line_offset, | 141     Handle<String> source, Handle<Object> name, int line_offset, | 
| 146     int column_offset, ScriptOriginOptions resource_options, | 142     int column_offset, ScriptOriginOptions resource_options, | 
| 147     Handle<Context> context, LanguageMode language_mode) { | 143     Handle<Context> context, LanguageMode language_mode) { | 
| 148   Object* result = NULL; | 144   InfoVectorPair result; | 
| 149   int generation; |  | 
| 150 | 145 | 
| 151   // Probe the script generation tables. Make sure not to leak handles | 146   // Probe the script generation tables. Make sure not to leak handles | 
| 152   // into the caller's handle scope. | 147   // into the caller's handle scope. | 
| 153   { HandleScope scope(isolate()); | 148   { HandleScope scope(isolate()); | 
| 154     for (generation = 0; generation < generations(); generation++) { | 149     const int generation = 0; | 
| 155       Handle<CompilationCacheTable> table = GetTable(generation); | 150     DCHECK(generations() == 1); | 
| 156       Handle<Object> probe = table->Lookup(source, context, language_mode); | 151     Handle<CompilationCacheTable> table = GetTable(generation); | 
| 157       if (probe->IsSharedFunctionInfo()) { | 152     InfoVectorPair probe = table->LookupScript(source, context, language_mode); | 
| 158         Handle<SharedFunctionInfo> function_info = | 153     if (probe.has_shared()) { | 
| 159             Handle<SharedFunctionInfo>::cast(probe); | 154       Handle<SharedFunctionInfo> function_info(probe.shared(), isolate()); | 
| 160         // Break when we've found a suitable shared function info that | 155       Handle<Cell> vector_handle; | 
| 161         // matches the origin. | 156       if (probe.has_vector()) { | 
| 162         if (HasOrigin(function_info, name, line_offset, column_offset, | 157         vector_handle = Handle<Cell>(probe.vector(), isolate()); | 
| 163                       resource_options)) { | 158       } | 
| 164           result = *function_info; | 159       // Break when we've found a suitable shared function info that | 
| 165           break; | 160       // matches the origin. | 
| 166         } | 161       if (HasOrigin(function_info, name, line_offset, column_offset, | 
|  | 162                     resource_options)) { | 
|  | 163         result = InfoVectorPair(*function_info, | 
|  | 164                                 probe.has_vector() ? *vector_handle : nullptr); | 
| 167       } | 165       } | 
| 168     } | 166     } | 
| 169   } | 167   } | 
| 170 | 168 | 
| 171   // Once outside the manacles of the handle scope, we need to recheck | 169   // Once outside the manacles of the handle scope, we need to recheck | 
| 172   // to see if we actually found a cached script. If so, we return a | 170   // to see if we actually found a cached script. If so, we return a | 
| 173   // handle created in the caller's handle scope. | 171   // handle created in the caller's handle scope. | 
| 174   if (result != NULL) { | 172   if (result.has_shared()) { | 
| 175     Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result), | 173     Handle<SharedFunctionInfo> shared(result.shared(), isolate()); | 
| 176                                       isolate()); | 174     // TODO(mvstanton): Make sure HasOrigin can't allocate, or it will | 
|  | 175     // mess up our InfoVectorPair. | 
| 177     DCHECK( | 176     DCHECK( | 
| 178         HasOrigin(shared, name, line_offset, column_offset, resource_options)); | 177         HasOrigin(shared, name, line_offset, column_offset, resource_options)); | 
| 179     // If the script was found in a later generation, we promote it to |  | 
| 180     // the first generation to let it survive longer in the cache. |  | 
| 181     if (generation != 0) Put(source, context, language_mode, shared); |  | 
| 182     isolate()->counters()->compilation_cache_hits()->Increment(); | 178     isolate()->counters()->compilation_cache_hits()->Increment(); | 
| 183     return shared; |  | 
| 184   } else { | 179   } else { | 
| 185     isolate()->counters()->compilation_cache_misses()->Increment(); | 180     isolate()->counters()->compilation_cache_misses()->Increment(); | 
| 186     return Handle<SharedFunctionInfo>::null(); |  | 
| 187   } | 181   } | 
|  | 182   return result; | 
| 188 } | 183 } | 
| 189 | 184 | 
| 190 | 185 void CompilationCacheScript::Put(Handle<String> source, Handle<Context> context, | 
| 191 void CompilationCacheScript::Put(Handle<String> source, |  | 
| 192                                  Handle<Context> context, |  | 
| 193                                  LanguageMode language_mode, | 186                                  LanguageMode language_mode, | 
| 194                                  Handle<SharedFunctionInfo> function_info) { | 187                                  Handle<SharedFunctionInfo> function_info, | 
|  | 188                                  Handle<Cell> literals) { | 
| 195   HandleScope scope(isolate()); | 189   HandleScope scope(isolate()); | 
| 196   Handle<CompilationCacheTable> table = GetFirstTable(); | 190   Handle<CompilationCacheTable> table = GetFirstTable(); | 
| 197   SetFirstTable(CompilationCacheTable::Put(table, source, context, | 191   SetFirstTable(CompilationCacheTable::PutScript( | 
| 198                                            language_mode, function_info)); | 192       table, source, context, language_mode, function_info, literals)); | 
| 199 } | 193 } | 
| 200 | 194 | 
| 201 | 195 InfoVectorPair CompilationCacheEval::Lookup( | 
| 202 MaybeHandle<SharedFunctionInfo> CompilationCacheEval::Lookup( |  | 
| 203     Handle<String> source, Handle<SharedFunctionInfo> outer_info, | 196     Handle<String> source, Handle<SharedFunctionInfo> outer_info, | 
| 204     LanguageMode language_mode, int scope_position) { | 197     Handle<Context> native_context, LanguageMode language_mode, | 
|  | 198     int scope_position) { | 
| 205   HandleScope scope(isolate()); | 199   HandleScope scope(isolate()); | 
| 206   // Make sure not to leak the table into the surrounding handle | 200   // Make sure not to leak the table into the surrounding handle | 
| 207   // scope. Otherwise, we risk keeping old tables around even after | 201   // scope. Otherwise, we risk keeping old tables around even after | 
| 208   // having cleared the cache. | 202   // having cleared the cache. | 
| 209   Handle<Object> result = isolate()->factory()->undefined_value(); | 203   InfoVectorPair result; | 
| 210   int generation; | 204   const int generation = 0; | 
| 211   for (generation = 0; generation < generations(); generation++) { | 205   DCHECK(generations() == 1); | 
| 212     Handle<CompilationCacheTable> table = GetTable(generation); | 206   Handle<CompilationCacheTable> table = GetTable(generation); | 
| 213     result = | 207   result = table->LookupEval(source, outer_info, native_context, language_mode, | 
| 214         table->LookupEval(source, outer_info, language_mode, scope_position); | 208                              scope_position); | 
| 215     if (result->IsSharedFunctionInfo()) break; | 209   if (result.has_shared()) { | 
| 216   } |  | 
| 217   if (result->IsSharedFunctionInfo()) { |  | 
| 218     Handle<SharedFunctionInfo> function_info = |  | 
| 219         Handle<SharedFunctionInfo>::cast(result); |  | 
| 220     if (generation != 0) { |  | 
| 221       Put(source, outer_info, function_info, scope_position); |  | 
| 222     } |  | 
| 223     isolate()->counters()->compilation_cache_hits()->Increment(); | 210     isolate()->counters()->compilation_cache_hits()->Increment(); | 
| 224     return scope.CloseAndEscape(function_info); |  | 
| 225   } else { | 211   } else { | 
| 226     isolate()->counters()->compilation_cache_misses()->Increment(); | 212     isolate()->counters()->compilation_cache_misses()->Increment(); | 
| 227     return MaybeHandle<SharedFunctionInfo>(); |  | 
| 228   } | 213   } | 
|  | 214   return result; | 
| 229 } | 215 } | 
| 230 | 216 | 
| 231 |  | 
| 232 void CompilationCacheEval::Put(Handle<String> source, | 217 void CompilationCacheEval::Put(Handle<String> source, | 
| 233                                Handle<SharedFunctionInfo> outer_info, | 218                                Handle<SharedFunctionInfo> outer_info, | 
| 234                                Handle<SharedFunctionInfo> function_info, | 219                                Handle<SharedFunctionInfo> function_info, | 
| 235                                int scope_position) { | 220                                Handle<Context> native_context, | 
|  | 221                                Handle<Cell> literals, int scope_position) { | 
| 236   HandleScope scope(isolate()); | 222   HandleScope scope(isolate()); | 
| 237   Handle<CompilationCacheTable> table = GetFirstTable(); | 223   Handle<CompilationCacheTable> table = GetFirstTable(); | 
| 238   table = CompilationCacheTable::PutEval(table, source, outer_info, | 224   table = | 
| 239                                          function_info, scope_position); | 225       CompilationCacheTable::PutEval(table, source, outer_info, function_info, | 
|  | 226                                      native_context, literals, scope_position); | 
| 240   SetFirstTable(table); | 227   SetFirstTable(table); | 
| 241 } | 228 } | 
| 242 | 229 | 
| 243 | 230 | 
| 244 MaybeHandle<FixedArray> CompilationCacheRegExp::Lookup( | 231 MaybeHandle<FixedArray> CompilationCacheRegExp::Lookup( | 
| 245     Handle<String> source, | 232     Handle<String> source, | 
| 246     JSRegExp::Flags flags) { | 233     JSRegExp::Flags flags) { | 
| 247   HandleScope scope(isolate()); | 234   HandleScope scope(isolate()); | 
| 248   // Make sure not to leak the table into the surrounding handle | 235   // Make sure not to leak the table into the surrounding handle | 
| 249   // scope. Otherwise, we risk keeping old tables around even after | 236   // scope. Otherwise, we risk keeping old tables around even after | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 279 | 266 | 
| 280 | 267 | 
| 281 void CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) { | 268 void CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) { | 
| 282   if (!IsEnabled()) return; | 269   if (!IsEnabled()) return; | 
| 283 | 270 | 
| 284   eval_global_.Remove(function_info); | 271   eval_global_.Remove(function_info); | 
| 285   eval_contextual_.Remove(function_info); | 272   eval_contextual_.Remove(function_info); | 
| 286   script_.Remove(function_info); | 273   script_.Remove(function_info); | 
| 287 } | 274 } | 
| 288 | 275 | 
| 289 | 276 InfoVectorPair CompilationCache::LookupScript( | 
| 290 MaybeHandle<SharedFunctionInfo> CompilationCache::LookupScript( |  | 
| 291     Handle<String> source, Handle<Object> name, int line_offset, | 277     Handle<String> source, Handle<Object> name, int line_offset, | 
| 292     int column_offset, ScriptOriginOptions resource_options, | 278     int column_offset, ScriptOriginOptions resource_options, | 
| 293     Handle<Context> context, LanguageMode language_mode) { | 279     Handle<Context> context, LanguageMode language_mode) { | 
| 294   if (!IsEnabled()) return MaybeHandle<SharedFunctionInfo>(); | 280   InfoVectorPair empty_result; | 
|  | 281   if (!IsEnabled()) return empty_result; | 
| 295 | 282 | 
| 296   return script_.Lookup(source, name, line_offset, column_offset, | 283   return script_.Lookup(source, name, line_offset, column_offset, | 
| 297                         resource_options, context, language_mode); | 284                         resource_options, context, language_mode); | 
| 298 } | 285 } | 
| 299 | 286 | 
| 300 | 287 InfoVectorPair CompilationCache::LookupEval( | 
| 301 MaybeHandle<SharedFunctionInfo> CompilationCache::LookupEval( |  | 
| 302     Handle<String> source, Handle<SharedFunctionInfo> outer_info, | 288     Handle<String> source, Handle<SharedFunctionInfo> outer_info, | 
| 303     Handle<Context> context, LanguageMode language_mode, int scope_position) { | 289     Handle<Context> context, LanguageMode language_mode, int scope_position) { | 
| 304   if (!IsEnabled()) return MaybeHandle<SharedFunctionInfo>(); | 290   InfoVectorPair result; | 
|  | 291   if (!IsEnabled()) return result; | 
| 305 | 292 | 
| 306   MaybeHandle<SharedFunctionInfo> result; |  | 
| 307   if (context->IsNativeContext()) { | 293   if (context->IsNativeContext()) { | 
| 308     result = | 294     result = eval_global_.Lookup(source, outer_info, context, language_mode, | 
| 309         eval_global_.Lookup(source, outer_info, language_mode, scope_position); | 295                                  scope_position); | 
| 310   } else { | 296   } else { | 
| 311     DCHECK(scope_position != kNoSourcePosition); | 297     DCHECK(scope_position != kNoSourcePosition); | 
| 312     result = eval_contextual_.Lookup(source, outer_info, language_mode, | 298     Handle<Context> native_context(context->native_context(), isolate()); | 
| 313                                      scope_position); | 299     result = eval_contextual_.Lookup(source, outer_info, native_context, | 
|  | 300                                      language_mode, scope_position); | 
| 314   } | 301   } | 
|  | 302 | 
| 315   return result; | 303   return result; | 
| 316 } | 304 } | 
| 317 | 305 | 
| 318 | 306 | 
| 319 MaybeHandle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source, | 307 MaybeHandle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source, | 
| 320                                                        JSRegExp::Flags flags) { | 308                                                        JSRegExp::Flags flags) { | 
| 321   if (!IsEnabled()) return MaybeHandle<FixedArray>(); | 309   if (!IsEnabled()) return MaybeHandle<FixedArray>(); | 
| 322 | 310 | 
| 323   return reg_exp_.Lookup(source, flags); | 311   return reg_exp_.Lookup(source, flags); | 
| 324 } | 312 } | 
| 325 | 313 | 
| 326 | 314 void CompilationCache::PutScript(Handle<String> source, Handle<Context> context, | 
| 327 void CompilationCache::PutScript(Handle<String> source, |  | 
| 328                                  Handle<Context> context, |  | 
| 329                                  LanguageMode language_mode, | 315                                  LanguageMode language_mode, | 
| 330                                  Handle<SharedFunctionInfo> function_info) { | 316                                  Handle<SharedFunctionInfo> function_info, | 
|  | 317                                  Handle<Cell> literals) { | 
| 331   if (!IsEnabled()) return; | 318   if (!IsEnabled()) return; | 
| 332 | 319 | 
| 333   script_.Put(source, context, language_mode, function_info); | 320   script_.Put(source, context, language_mode, function_info, literals); | 
| 334 } | 321 } | 
| 335 | 322 | 
| 336 |  | 
| 337 void CompilationCache::PutEval(Handle<String> source, | 323 void CompilationCache::PutEval(Handle<String> source, | 
| 338                                Handle<SharedFunctionInfo> outer_info, | 324                                Handle<SharedFunctionInfo> outer_info, | 
| 339                                Handle<Context> context, | 325                                Handle<Context> context, | 
| 340                                Handle<SharedFunctionInfo> function_info, | 326                                Handle<SharedFunctionInfo> function_info, | 
| 341                                int scope_position) { | 327                                Handle<Cell> literals, int scope_position) { | 
| 342   if (!IsEnabled()) return; | 328   if (!IsEnabled()) return; | 
| 343 | 329 | 
| 344   HandleScope scope(isolate()); | 330   HandleScope scope(isolate()); | 
| 345   if (context->IsNativeContext()) { | 331   if (context->IsNativeContext()) { | 
| 346     eval_global_.Put(source, outer_info, function_info, scope_position); | 332     eval_global_.Put(source, outer_info, function_info, context, literals, | 
|  | 333                      scope_position); | 
| 347   } else { | 334   } else { | 
| 348     DCHECK(scope_position != kNoSourcePosition); | 335     DCHECK(scope_position != kNoSourcePosition); | 
| 349     eval_contextual_.Put(source, outer_info, function_info, scope_position); | 336     Handle<Context> native_context(context->native_context(), isolate()); | 
|  | 337     eval_contextual_.Put(source, outer_info, function_info, native_context, | 
|  | 338                          literals, scope_position); | 
| 350   } | 339   } | 
| 351 } | 340 } | 
| 352 | 341 | 
| 353 | 342 | 
| 354 | 343 | 
| 355 void CompilationCache::PutRegExp(Handle<String> source, | 344 void CompilationCache::PutRegExp(Handle<String> source, | 
| 356                                  JSRegExp::Flags flags, | 345                                  JSRegExp::Flags flags, | 
| 357                                  Handle<FixedArray> data) { | 346                                  Handle<FixedArray> data) { | 
| 358   if (!IsEnabled()) { | 347   if (!IsEnabled()) { | 
| 359     return; | 348     return; | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 397 | 386 | 
| 398 | 387 | 
| 399 void CompilationCache::Disable() { | 388 void CompilationCache::Disable() { | 
| 400   enabled_ = false; | 389   enabled_ = false; | 
| 401   Clear(); | 390   Clear(); | 
| 402 } | 391 } | 
| 403 | 392 | 
| 404 | 393 | 
| 405 }  // namespace internal | 394 }  // namespace internal | 
| 406 }  // namespace v8 | 395 }  // namespace v8 | 
| OLD | NEW | 
|---|