| OLD | NEW |
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "compilation-cache.h" | 30 #include "compilation-cache.h" |
| 31 | 31 |
| 32 namespace v8 { | 32 namespace v8 { |
| 33 namespace internal { | 33 namespace internal { |
| 34 | 34 |
| 35 | |
| 36 // The number of sub caches covering the different types to cache. | 35 // The number of sub caches covering the different types to cache. |
| 37 static const int kSubCacheCount = 4; | 36 static const int kSubCacheCount = 4; |
| 38 | 37 |
| 39 // The number of generations for each sub cache. | 38 // The number of generations for each sub cache. |
| 40 // The number of ScriptGenerations is carefully chosen based on histograms. | 39 // The number of ScriptGenerations is carefully chosen based on histograms. |
| 41 // See issue 458: http://code.google.com/p/v8/issues/detail?id=458 | 40 // See issue 458: http://code.google.com/p/v8/issues/detail?id=458 |
| 42 static const int kScriptGenerations = 5; | 41 static const int kScriptGenerations = 5; |
| 43 static const int kEvalGlobalGenerations = 2; | 42 static const int kEvalGlobalGenerations = 2; |
| 44 static const int kEvalContextualGenerations = 2; | 43 static const int kEvalContextualGenerations = 2; |
| 45 static const int kRegExpGenerations = 2; | 44 static const int kRegExpGenerations = 2; |
| 46 | 45 |
| 47 // Initial size of each compilation cache table allocated. | 46 // Initial size of each compilation cache table allocated. |
| 48 static const int kInitialCacheSize = 64; | 47 static const int kInitialCacheSize = 64; |
| 49 | 48 |
| 49 // Index for the first generation in the cache. |
| 50 static const int kFirstGeneration = 0; |
| 51 |
| 50 // The compilation cache consists of several generational sub-caches which uses | 52 // The compilation cache consists of several generational sub-caches which uses |
| 51 // this class as a base class. A sub-cache contains a compilation cache tables | 53 // this class as a base class. A sub-cache contains a compilation cache tables |
| 52 // for each generation of the sub-cache. Since the same source code string has | 54 // for each generation of the sub-cache. Since the same source code string has |
| 53 // different compiled code for scripts and evals, we use separate sub-caches | 55 // different compiled code for scripts and evals, we use separate sub-caches |
| 54 // for different compilation modes, to avoid retrieving the wrong result. | 56 // for different compilation modes, to avoid retrieving the wrong result. |
| 55 class CompilationSubCache { | 57 class CompilationSubCache { |
| 56 public: | 58 public: |
| 57 explicit CompilationSubCache(int generations): generations_(generations) { | 59 explicit CompilationSubCache(int generations): generations_(generations) { |
| 58 tables_ = NewArray<Object*>(generations); | 60 tables_ = NewArray<Object*>(generations); |
| 59 } | 61 } |
| 60 | 62 |
| 61 ~CompilationSubCache() { DeleteArray(tables_); } | 63 ~CompilationSubCache() { DeleteArray(tables_); } |
| 62 | 64 |
| 63 // Get the compilation cache tables for a specific generation. | 65 // Get the compilation cache tables for a specific generation. |
| 64 Handle<CompilationCacheTable> GetTable(int generation); | 66 Handle<CompilationCacheTable> GetTable(int generation); |
| 65 | 67 |
| 68 // Accessors for first generation. |
| 69 Handle<CompilationCacheTable> GetFirstTable() { |
| 70 return GetTable(kFirstGeneration); |
| 71 } |
| 72 void SetFirstTable(Handle<CompilationCacheTable> value) { |
| 73 ASSERT(kFirstGeneration < generations_); |
| 74 tables_[kFirstGeneration] = *value; |
| 75 } |
| 76 |
| 66 // Age the sub-cache by evicting the oldest generation and creating a new | 77 // Age the sub-cache by evicting the oldest generation and creating a new |
| 67 // young generation. | 78 // young generation. |
| 68 void Age(); | 79 void Age(); |
| 69 | 80 |
| 70 // GC support. | 81 // GC support. |
| 71 void Iterate(ObjectVisitor* v); | 82 void Iterate(ObjectVisitor* v); |
| 72 | 83 |
| 73 // Clear this sub-cache evicting all its content. | 84 // Clear this sub-cache evicting all its content. |
| 74 void Clear(); | 85 void Clear(); |
| 75 | 86 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 90 explicit CompilationCacheScript(int generations) | 101 explicit CompilationCacheScript(int generations) |
| 91 : CompilationSubCache(generations) { } | 102 : CompilationSubCache(generations) { } |
| 92 | 103 |
| 93 Handle<JSFunction> Lookup(Handle<String> source, | 104 Handle<JSFunction> Lookup(Handle<String> source, |
| 94 Handle<Object> name, | 105 Handle<Object> name, |
| 95 int line_offset, | 106 int line_offset, |
| 96 int column_offset); | 107 int column_offset); |
| 97 void Put(Handle<String> source, Handle<JSFunction> boilerplate); | 108 void Put(Handle<String> source, Handle<JSFunction> boilerplate); |
| 98 | 109 |
| 99 private: | 110 private: |
| 111 // Note: Returns a new hash table if operation results in expansion. |
| 112 Handle<CompilationCacheTable> TablePut(Handle<String> source, |
| 113 Handle<JSFunction> boilerplate); |
| 114 |
| 100 bool HasOrigin(Handle<JSFunction> boilerplate, | 115 bool HasOrigin(Handle<JSFunction> boilerplate, |
| 101 Handle<Object> name, | 116 Handle<Object> name, |
| 102 int line_offset, | 117 int line_offset, |
| 103 int column_offset); | 118 int column_offset); |
| 104 | 119 |
| 105 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript); | 120 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript); |
| 106 }; | 121 }; |
| 107 | 122 |
| 108 | 123 |
| 109 // Sub-cache for eval scripts. | 124 // Sub-cache for eval scripts. |
| 110 class CompilationCacheEval: public CompilationSubCache { | 125 class CompilationCacheEval: public CompilationSubCache { |
| 111 public: | 126 public: |
| 112 explicit CompilationCacheEval(int generations) | 127 explicit CompilationCacheEval(int generations) |
| 113 : CompilationSubCache(generations) { } | 128 : CompilationSubCache(generations) { } |
| 114 | 129 |
| 115 Handle<JSFunction> Lookup(Handle<String> source, Handle<Context> context); | 130 Handle<JSFunction> Lookup(Handle<String> source, Handle<Context> context); |
| 116 | 131 |
| 117 void Put(Handle<String> source, | 132 void Put(Handle<String> source, |
| 118 Handle<Context> context, | 133 Handle<Context> context, |
| 119 Handle<JSFunction> boilerplate); | 134 Handle<JSFunction> boilerplate); |
| 120 | 135 |
| 136 private: |
| 137 // Note: Returns a new hash table if operation results in expansion. |
| 138 Handle<CompilationCacheTable> TablePut(Handle<String> source, |
| 139 Handle<Context> context, |
| 140 Handle<JSFunction> boilerplate); |
| 141 |
| 121 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval); | 142 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval); |
| 122 }; | 143 }; |
| 123 | 144 |
| 124 | 145 |
| 125 // Sub-cache for regular expressions. | 146 // Sub-cache for regular expressions. |
| 126 class CompilationCacheRegExp: public CompilationSubCache { | 147 class CompilationCacheRegExp: public CompilationSubCache { |
| 127 public: | 148 public: |
| 128 explicit CompilationCacheRegExp(int generations) | 149 explicit CompilationCacheRegExp(int generations) |
| 129 : CompilationSubCache(generations) { } | 150 : CompilationSubCache(generations) { } |
| 130 | 151 |
| 131 Handle<FixedArray> Lookup(Handle<String> source, JSRegExp::Flags flags); | 152 Handle<FixedArray> Lookup(Handle<String> source, JSRegExp::Flags flags); |
| 132 | 153 |
| 133 void Put(Handle<String> source, | 154 void Put(Handle<String> source, |
| 134 JSRegExp::Flags flags, | 155 JSRegExp::Flags flags, |
| 135 Handle<FixedArray> data); | 156 Handle<FixedArray> data); |
| 157 private: |
| 158 // Note: Returns a new hash table if operation results in expansion. |
| 159 Handle<CompilationCacheTable> TablePut(Handle<String> source, |
| 160 JSRegExp::Flags flags, |
| 161 Handle<FixedArray> data); |
| 136 | 162 |
| 137 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheRegExp); | 163 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheRegExp); |
| 138 }; | 164 }; |
| 139 | 165 |
| 140 | 166 |
| 141 // Statically allocate all the sub-caches. | 167 // Statically allocate all the sub-caches. |
| 142 static CompilationCacheScript script(kScriptGenerations); | 168 static CompilationCacheScript script(kScriptGenerations); |
| 143 static CompilationCacheEval eval_global(kEvalGlobalGenerations); | 169 static CompilationCacheEval eval_global(kEvalGlobalGenerations); |
| 144 static CompilationCacheEval eval_contextual(kEvalContextualGenerations); | 170 static CompilationCacheEval eval_contextual(kEvalContextualGenerations); |
| 145 static CompilationCacheRegExp reg_exp(kRegExpGenerations); | 171 static CompilationCacheRegExp reg_exp(kRegExpGenerations); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 if (generation != 0) Put(source, boilerplate); | 299 if (generation != 0) Put(source, boilerplate); |
| 274 Counters::compilation_cache_hits.Increment(); | 300 Counters::compilation_cache_hits.Increment(); |
| 275 return boilerplate; | 301 return boilerplate; |
| 276 } else { | 302 } else { |
| 277 Counters::compilation_cache_misses.Increment(); | 303 Counters::compilation_cache_misses.Increment(); |
| 278 return Handle<JSFunction>::null(); | 304 return Handle<JSFunction>::null(); |
| 279 } | 305 } |
| 280 } | 306 } |
| 281 | 307 |
| 282 | 308 |
| 309 Handle<CompilationCacheTable> CompilationCacheScript::TablePut( |
| 310 Handle<String> source, |
| 311 Handle<JSFunction> boilerplate) { |
| 312 CALL_HEAP_FUNCTION(GetFirstTable()->Put(*source, *boilerplate), |
| 313 CompilationCacheTable); |
| 314 } |
| 315 |
| 316 |
| 283 void CompilationCacheScript::Put(Handle<String> source, | 317 void CompilationCacheScript::Put(Handle<String> source, |
| 284 Handle<JSFunction> boilerplate) { | 318 Handle<JSFunction> boilerplate) { |
| 285 HandleScope scope; | 319 HandleScope scope; |
| 286 ASSERT(boilerplate->IsBoilerplate()); | 320 ASSERT(boilerplate->IsBoilerplate()); |
| 287 Handle<CompilationCacheTable> table = GetTable(0); | 321 SetFirstTable(TablePut(source, boilerplate)); |
| 288 CALL_HEAP_FUNCTION_VOID(table->Put(*source, *boilerplate)); | |
| 289 } | 322 } |
| 290 | 323 |
| 291 | 324 |
| 292 Handle<JSFunction> CompilationCacheEval::Lookup(Handle<String> source, | 325 Handle<JSFunction> CompilationCacheEval::Lookup(Handle<String> source, |
| 293 Handle<Context> context) { | 326 Handle<Context> context) { |
| 294 // Make sure not to leak the table into the surrounding handle | 327 // Make sure not to leak the table into the surrounding handle |
| 295 // scope. Otherwise, we risk keeping old tables around even after | 328 // scope. Otherwise, we risk keeping old tables around even after |
| 296 // having cleared the cache. | 329 // having cleared the cache. |
| 297 Object* result = NULL; | 330 Object* result = NULL; |
| 298 int generation; | 331 int generation; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 312 } | 345 } |
| 313 Counters::compilation_cache_hits.Increment(); | 346 Counters::compilation_cache_hits.Increment(); |
| 314 return boilerplate; | 347 return boilerplate; |
| 315 } else { | 348 } else { |
| 316 Counters::compilation_cache_misses.Increment(); | 349 Counters::compilation_cache_misses.Increment(); |
| 317 return Handle<JSFunction>::null(); | 350 return Handle<JSFunction>::null(); |
| 318 } | 351 } |
| 319 } | 352 } |
| 320 | 353 |
| 321 | 354 |
| 355 Handle<CompilationCacheTable> CompilationCacheEval::TablePut( |
| 356 Handle<String> source, |
| 357 Handle<Context> context, |
| 358 Handle<JSFunction> boilerplate) { |
| 359 CALL_HEAP_FUNCTION(GetFirstTable()->PutEval(*source, *context, *boilerplate), |
| 360 CompilationCacheTable); |
| 361 } |
| 362 |
| 363 |
| 322 void CompilationCacheEval::Put(Handle<String> source, | 364 void CompilationCacheEval::Put(Handle<String> source, |
| 323 Handle<Context> context, | 365 Handle<Context> context, |
| 324 Handle<JSFunction> boilerplate) { | 366 Handle<JSFunction> boilerplate) { |
| 325 HandleScope scope; | 367 HandleScope scope; |
| 326 ASSERT(boilerplate->IsBoilerplate()); | 368 ASSERT(boilerplate->IsBoilerplate()); |
| 327 Handle<CompilationCacheTable> table = GetTable(0); | 369 SetFirstTable(TablePut(source, context, boilerplate)); |
| 328 CALL_HEAP_FUNCTION_VOID(table->PutEval(*source, *context, *boilerplate)); | |
| 329 } | 370 } |
| 330 | 371 |
| 331 | 372 |
| 332 Handle<FixedArray> CompilationCacheRegExp::Lookup(Handle<String> source, | 373 Handle<FixedArray> CompilationCacheRegExp::Lookup(Handle<String> source, |
| 333 JSRegExp::Flags flags) { | 374 JSRegExp::Flags flags) { |
| 334 // Make sure not to leak the table into the surrounding handle | 375 // Make sure not to leak the table into the surrounding handle |
| 335 // scope. Otherwise, we risk keeping old tables around even after | 376 // scope. Otherwise, we risk keeping old tables around even after |
| 336 // having cleared the cache. | 377 // having cleared the cache. |
| 337 Object* result = NULL; | 378 Object* result = NULL; |
| 338 int generation; | 379 int generation; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 352 } | 393 } |
| 353 Counters::compilation_cache_hits.Increment(); | 394 Counters::compilation_cache_hits.Increment(); |
| 354 return data; | 395 return data; |
| 355 } else { | 396 } else { |
| 356 Counters::compilation_cache_misses.Increment(); | 397 Counters::compilation_cache_misses.Increment(); |
| 357 return Handle<FixedArray>::null(); | 398 return Handle<FixedArray>::null(); |
| 358 } | 399 } |
| 359 } | 400 } |
| 360 | 401 |
| 361 | 402 |
| 403 Handle<CompilationCacheTable> CompilationCacheRegExp::TablePut( |
| 404 Handle<String> source, |
| 405 JSRegExp::Flags flags, |
| 406 Handle<FixedArray> data) { |
| 407 CALL_HEAP_FUNCTION(GetFirstTable()->PutRegExp(*source, flags, *data), |
| 408 CompilationCacheTable); |
| 409 } |
| 410 |
| 411 |
| 362 void CompilationCacheRegExp::Put(Handle<String> source, | 412 void CompilationCacheRegExp::Put(Handle<String> source, |
| 363 JSRegExp::Flags flags, | 413 JSRegExp::Flags flags, |
| 364 Handle<FixedArray> data) { | 414 Handle<FixedArray> data) { |
| 365 HandleScope scope; | 415 HandleScope scope; |
| 366 Handle<CompilationCacheTable> table = GetTable(0); | 416 SetFirstTable(TablePut(source, flags, data)); |
| 367 CALL_HEAP_FUNCTION_VOID(table->PutRegExp(*source, flags, *data)); | |
| 368 } | 417 } |
| 369 | 418 |
| 370 | 419 |
| 371 Handle<JSFunction> CompilationCache::LookupScript(Handle<String> source, | 420 Handle<JSFunction> CompilationCache::LookupScript(Handle<String> source, |
| 372 Handle<Object> name, | 421 Handle<Object> name, |
| 373 int line_offset, | 422 int line_offset, |
| 374 int column_offset) { | 423 int column_offset) { |
| 375 if (!IsEnabled()) { | 424 if (!IsEnabled()) { |
| 376 return Handle<JSFunction>::null(); | 425 return Handle<JSFunction>::null(); |
| 377 } | 426 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 } | 523 } |
| 475 | 524 |
| 476 | 525 |
| 477 void CompilationCache::Disable() { | 526 void CompilationCache::Disable() { |
| 478 enabled = false; | 527 enabled = false; |
| 479 Clear(); | 528 Clear(); |
| 480 } | 529 } |
| 481 | 530 |
| 482 | 531 |
| 483 } } // namespace v8::internal | 532 } } // namespace v8::internal |
| OLD | NEW |