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