| 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 15 matching lines...) Expand all Loading... |
| 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 #include "serialize.h" | 31 #include "serialize.h" |
| 32 | 32 |
| 33 namespace v8 { | 33 namespace v8 { |
| 34 namespace internal { | 34 namespace internal { |
| 35 | 35 |
| 36 // The number of sub caches covering the different types to cache. | |
| 37 static const int kSubCacheCount = 4; | |
| 38 | 36 |
| 39 // The number of generations for each sub cache. | 37 // The number of generations for each sub cache. |
| 40 // The number of ScriptGenerations is carefully chosen based on histograms. | 38 // The number of ScriptGenerations is carefully chosen based on histograms. |
| 41 // See issue 458: http://code.google.com/p/v8/issues/detail?id=458 | 39 // See issue 458: http://code.google.com/p/v8/issues/detail?id=458 |
| 42 static const int kScriptGenerations = 5; | 40 static const int kScriptGenerations = 5; |
| 43 static const int kEvalGlobalGenerations = 2; | 41 static const int kEvalGlobalGenerations = 2; |
| 44 static const int kEvalContextualGenerations = 2; | 42 static const int kEvalContextualGenerations = 2; |
| 45 static const int kRegExpGenerations = 2; | 43 static const int kRegExpGenerations = 2; |
| 46 | 44 |
| 47 // Initial size of each compilation cache table allocated. | 45 // Initial size of each compilation cache table allocated. |
| 48 static const int kInitialCacheSize = 64; | 46 static const int kInitialCacheSize = 64; |
| 49 | 47 |
| 50 // Index for the first generation in the cache. | |
| 51 static const int kFirstGeneration = 0; | |
| 52 | 48 |
| 53 // The compilation cache consists of several generational sub-caches which uses | 49 CompilationCache::CompilationCache() |
| 54 // this class as a base class. A sub-cache contains a compilation cache tables | 50 : script_(kScriptGenerations), |
| 55 // for each generation of the sub-cache. Since the same source code string has | 51 eval_global_(kEvalGlobalGenerations), |
| 56 // different compiled code for scripts and evals, we use separate sub-caches | 52 eval_contextual_(kEvalContextualGenerations), |
| 57 // for different compilation modes, to avoid retrieving the wrong result. | 53 reg_exp_(kRegExpGenerations), |
| 58 class CompilationSubCache { | 54 enabled_(true), |
| 59 public: | 55 eager_optimizing_set_(NULL) { |
| 60 explicit CompilationSubCache(int generations): generations_(generations) { | 56 CompilationSubCache* subcaches[kSubCacheCount] = |
| 61 tables_ = NewArray<Object*>(generations); | 57 {&script_, &eval_global_, &eval_contextual_, ®_exp_}; |
| 58 for (int i = 0; i < kSubCacheCount; ++i) { |
| 59 subcaches_[i] = subcaches[i]; |
| 62 } | 60 } |
| 63 | 61 } |
| 64 ~CompilationSubCache() { DeleteArray(tables_); } | |
| 65 | |
| 66 // Get the compilation cache tables for a specific generation. | |
| 67 Handle<CompilationCacheTable> GetTable(int generation); | |
| 68 | |
| 69 // Accessors for first generation. | |
| 70 Handle<CompilationCacheTable> GetFirstTable() { | |
| 71 return GetTable(kFirstGeneration); | |
| 72 } | |
| 73 void SetFirstTable(Handle<CompilationCacheTable> value) { | |
| 74 ASSERT(kFirstGeneration < generations_); | |
| 75 tables_[kFirstGeneration] = *value; | |
| 76 } | |
| 77 | |
| 78 // Age the sub-cache by evicting the oldest generation and creating a new | |
| 79 // young generation. | |
| 80 void Age(); | |
| 81 | |
| 82 // GC support. | |
| 83 void Iterate(ObjectVisitor* v); | |
| 84 void IterateFunctions(ObjectVisitor* v); | |
| 85 | |
| 86 // Clear this sub-cache evicting all its content. | |
| 87 void Clear(); | |
| 88 | |
| 89 // Remove given shared function info from sub-cache. | |
| 90 void Remove(Handle<SharedFunctionInfo> function_info); | |
| 91 | |
| 92 // Number of generations in this sub-cache. | |
| 93 inline int generations() { return generations_; } | |
| 94 | |
| 95 private: | |
| 96 int generations_; // Number of generations. | |
| 97 Object** tables_; // Compilation cache tables - one for each generation. | |
| 98 | |
| 99 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationSubCache); | |
| 100 }; | |
| 101 | 62 |
| 102 | 63 |
| 103 // Sub-cache for scripts. | 64 CompilationCache::~CompilationCache() { |
| 104 class CompilationCacheScript : public CompilationSubCache { | 65 delete eager_optimizing_set_; |
| 105 public: | 66 eager_optimizing_set_ = NULL; |
| 106 explicit CompilationCacheScript(int generations) | |
| 107 : CompilationSubCache(generations) { } | |
| 108 | |
| 109 Handle<SharedFunctionInfo> Lookup(Handle<String> source, | |
| 110 Handle<Object> name, | |
| 111 int line_offset, | |
| 112 int column_offset); | |
| 113 void Put(Handle<String> source, Handle<SharedFunctionInfo> function_info); | |
| 114 | |
| 115 private: | |
| 116 MUST_USE_RESULT MaybeObject* TryTablePut( | |
| 117 Handle<String> source, Handle<SharedFunctionInfo> function_info); | |
| 118 | |
| 119 // Note: Returns a new hash table if operation results in expansion. | |
| 120 Handle<CompilationCacheTable> TablePut( | |
| 121 Handle<String> source, Handle<SharedFunctionInfo> function_info); | |
| 122 | |
| 123 bool HasOrigin(Handle<SharedFunctionInfo> function_info, | |
| 124 Handle<Object> name, | |
| 125 int line_offset, | |
| 126 int column_offset); | |
| 127 | |
| 128 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript); | |
| 129 }; | |
| 130 | |
| 131 | |
| 132 // Sub-cache for eval scripts. | |
| 133 class CompilationCacheEval: public CompilationSubCache { | |
| 134 public: | |
| 135 explicit CompilationCacheEval(int generations) | |
| 136 : CompilationSubCache(generations) { } | |
| 137 | |
| 138 Handle<SharedFunctionInfo> Lookup(Handle<String> source, | |
| 139 Handle<Context> context, | |
| 140 StrictModeFlag strict_mode); | |
| 141 | |
| 142 void Put(Handle<String> source, | |
| 143 Handle<Context> context, | |
| 144 Handle<SharedFunctionInfo> function_info); | |
| 145 | |
| 146 private: | |
| 147 MUST_USE_RESULT MaybeObject* TryTablePut( | |
| 148 Handle<String> source, | |
| 149 Handle<Context> context, | |
| 150 Handle<SharedFunctionInfo> function_info); | |
| 151 | |
| 152 | |
| 153 // Note: Returns a new hash table if operation results in expansion. | |
| 154 Handle<CompilationCacheTable> TablePut( | |
| 155 Handle<String> source, | |
| 156 Handle<Context> context, | |
| 157 Handle<SharedFunctionInfo> function_info); | |
| 158 | |
| 159 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval); | |
| 160 }; | |
| 161 | |
| 162 | |
| 163 // Sub-cache for regular expressions. | |
| 164 class CompilationCacheRegExp: public CompilationSubCache { | |
| 165 public: | |
| 166 explicit CompilationCacheRegExp(int generations) | |
| 167 : CompilationSubCache(generations) { } | |
| 168 | |
| 169 Handle<FixedArray> Lookup(Handle<String> source, JSRegExp::Flags flags); | |
| 170 | |
| 171 void Put(Handle<String> source, | |
| 172 JSRegExp::Flags flags, | |
| 173 Handle<FixedArray> data); | |
| 174 private: | |
| 175 MUST_USE_RESULT MaybeObject* TryTablePut(Handle<String> source, | |
| 176 JSRegExp::Flags flags, | |
| 177 Handle<FixedArray> data); | |
| 178 | |
| 179 // Note: Returns a new hash table if operation results in expansion. | |
| 180 Handle<CompilationCacheTable> TablePut(Handle<String> source, | |
| 181 JSRegExp::Flags flags, | |
| 182 Handle<FixedArray> data); | |
| 183 | |
| 184 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheRegExp); | |
| 185 }; | |
| 186 | |
| 187 | |
| 188 // Statically allocate all the sub-caches. | |
| 189 static CompilationCacheScript script(kScriptGenerations); | |
| 190 static CompilationCacheEval eval_global(kEvalGlobalGenerations); | |
| 191 static CompilationCacheEval eval_contextual(kEvalContextualGenerations); | |
| 192 static CompilationCacheRegExp reg_exp(kRegExpGenerations); | |
| 193 static CompilationSubCache* subcaches[kSubCacheCount] = | |
| 194 {&script, &eval_global, &eval_contextual, ®_exp}; | |
| 195 | |
| 196 | |
| 197 // Current enable state of the compilation cache. | |
| 198 static bool enabled = true; | |
| 199 static inline bool IsEnabled() { | |
| 200 return FLAG_compilation_cache && enabled; | |
| 201 } | 67 } |
| 202 | 68 |
| 203 | 69 |
| 204 static Handle<CompilationCacheTable> AllocateTable(int size) { | 70 static Handle<CompilationCacheTable> AllocateTable(int size) { |
| 205 CALL_HEAP_FUNCTION(CompilationCacheTable::Allocate(size), | 71 Isolate* isolate = Isolate::Current(); |
| 72 CALL_HEAP_FUNCTION(isolate, |
| 73 CompilationCacheTable::Allocate(size), |
| 206 CompilationCacheTable); | 74 CompilationCacheTable); |
| 207 } | 75 } |
| 208 | 76 |
| 209 | 77 |
| 210 Handle<CompilationCacheTable> CompilationSubCache::GetTable(int generation) { | 78 Handle<CompilationCacheTable> CompilationSubCache::GetTable(int generation) { |
| 211 ASSERT(generation < generations_); | 79 ASSERT(generation < generations_); |
| 212 Handle<CompilationCacheTable> result; | 80 Handle<CompilationCacheTable> result; |
| 213 if (tables_[generation]->IsUndefined()) { | 81 if (tables_[generation]->IsUndefined()) { |
| 214 result = AllocateTable(kInitialCacheSize); | 82 result = AllocateTable(kInitialCacheSize); |
| 215 tables_[generation] = *result; | 83 tables_[generation] = *result; |
| 216 } else { | 84 } else { |
| 217 CompilationCacheTable* table = | 85 CompilationCacheTable* table = |
| 218 CompilationCacheTable::cast(tables_[generation]); | 86 CompilationCacheTable::cast(tables_[generation]); |
| 219 result = Handle<CompilationCacheTable>(table); | 87 result = Handle<CompilationCacheTable>(table); |
| 220 } | 88 } |
| 221 return result; | 89 return result; |
| 222 } | 90 } |
| 223 | 91 |
| 224 | |
| 225 void CompilationSubCache::Age() { | 92 void CompilationSubCache::Age() { |
| 226 // Age the generations implicitly killing off the oldest. | 93 // Age the generations implicitly killing off the oldest. |
| 227 for (int i = generations_ - 1; i > 0; i--) { | 94 for (int i = generations_ - 1; i > 0; i--) { |
| 228 tables_[i] = tables_[i - 1]; | 95 tables_[i] = tables_[i - 1]; |
| 229 } | 96 } |
| 230 | 97 |
| 231 // Set the first generation as unborn. | 98 // Set the first generation as unborn. |
| 232 tables_[0] = Heap::undefined_value(); | 99 tables_[0] = HEAP->undefined_value(); |
| 233 } | 100 } |
| 234 | 101 |
| 235 | 102 |
| 236 void CompilationSubCache::IterateFunctions(ObjectVisitor* v) { | 103 void CompilationSubCache::IterateFunctions(ObjectVisitor* v) { |
| 237 Object* undefined = Heap::raw_unchecked_undefined_value(); | 104 Object* undefined = HEAP->raw_unchecked_undefined_value(); |
| 238 for (int i = 0; i < generations_; i++) { | 105 for (int i = 0; i < generations_; i++) { |
| 239 if (tables_[i] != undefined) { | 106 if (tables_[i] != undefined) { |
| 240 reinterpret_cast<CompilationCacheTable*>(tables_[i])->IterateElements(v); | 107 reinterpret_cast<CompilationCacheTable*>(tables_[i])->IterateElements(v); |
| 241 } | 108 } |
| 242 } | 109 } |
| 243 } | 110 } |
| 244 | 111 |
| 245 | 112 |
| 246 void CompilationSubCache::Iterate(ObjectVisitor* v) { | 113 void CompilationSubCache::Iterate(ObjectVisitor* v) { |
| 247 v->VisitPointers(&tables_[0], &tables_[generations_]); | 114 v->VisitPointers(&tables_[0], &tables_[generations_]); |
| 248 } | 115 } |
| 249 | 116 |
| 250 | 117 |
| 251 void CompilationSubCache::Clear() { | 118 void CompilationSubCache::Clear() { |
| 252 MemsetPointer(tables_, Heap::undefined_value(), generations_); | 119 MemsetPointer(tables_, HEAP->undefined_value(), generations_); |
| 253 } | 120 } |
| 254 | 121 |
| 255 | 122 |
| 256 void CompilationSubCache::Remove(Handle<SharedFunctionInfo> function_info) { | 123 void CompilationSubCache::Remove(Handle<SharedFunctionInfo> function_info) { |
| 257 // Probe the script generation tables. Make sure not to leak handles | 124 // Probe the script generation tables. Make sure not to leak handles |
| 258 // into the caller's handle scope. | 125 // into the caller's handle scope. |
| 259 { HandleScope scope; | 126 { HandleScope scope; |
| 260 for (int generation = 0; generation < generations(); generation++) { | 127 for (int generation = 0; generation < generations(); generation++) { |
| 261 Handle<CompilationCacheTable> table = GetTable(generation); | 128 Handle<CompilationCacheTable> table = GetTable(generation); |
| 262 table->Remove(*function_info); | 129 table->Remove(*function_info); |
| 263 } | 130 } |
| 264 } | 131 } |
| 265 } | 132 } |
| 266 | 133 |
| 267 | 134 |
| 135 CompilationCacheScript::CompilationCacheScript(int generations) |
| 136 : CompilationSubCache(generations), |
| 137 script_histogram_(NULL), |
| 138 script_histogram_initialized_(false) { |
| 139 } |
| 140 |
| 141 |
| 268 // We only re-use a cached function for some script source code if the | 142 // We only re-use a cached function for some script source code if the |
| 269 // script originates from the same place. This is to avoid issues | 143 // script originates from the same place. This is to avoid issues |
| 270 // when reporting errors, etc. | 144 // when reporting errors, etc. |
| 271 bool CompilationCacheScript::HasOrigin( | 145 bool CompilationCacheScript::HasOrigin( |
| 272 Handle<SharedFunctionInfo> function_info, | 146 Handle<SharedFunctionInfo> function_info, |
| 273 Handle<Object> name, | 147 Handle<Object> name, |
| 274 int line_offset, | 148 int line_offset, |
| 275 int column_offset) { | 149 int column_offset) { |
| 276 Handle<Script> script = | 150 Handle<Script> script = |
| 277 Handle<Script>(Script::cast(function_info->script())); | 151 Handle<Script>(Script::cast(function_info->script())); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 // Break when we've found a suitable shared function info that | 187 // Break when we've found a suitable shared function info that |
| 314 // matches the origin. | 188 // matches the origin. |
| 315 if (HasOrigin(function_info, name, line_offset, column_offset)) { | 189 if (HasOrigin(function_info, name, line_offset, column_offset)) { |
| 316 result = *function_info; | 190 result = *function_info; |
| 317 break; | 191 break; |
| 318 } | 192 } |
| 319 } | 193 } |
| 320 } | 194 } |
| 321 } | 195 } |
| 322 | 196 |
| 323 static void* script_histogram = StatsTable::CreateHistogram( | 197 Isolate* isolate = Isolate::Current(); |
| 324 "V8.ScriptCache", | 198 if (!script_histogram_initialized_) { |
| 325 0, | 199 script_histogram_ = isolate->stats_table()->CreateHistogram( |
| 326 kScriptGenerations, | 200 "V8.ScriptCache", |
| 327 kScriptGenerations + 1); | 201 0, |
| 202 kScriptGenerations, |
| 203 kScriptGenerations + 1); |
| 204 script_histogram_initialized_ = true; |
| 205 } |
| 328 | 206 |
| 329 if (script_histogram != NULL) { | 207 if (script_histogram_ != NULL) { |
| 330 // The level NUMBER_OF_SCRIPT_GENERATIONS is equivalent to a cache miss. | 208 // The level NUMBER_OF_SCRIPT_GENERATIONS is equivalent to a cache miss. |
| 331 StatsTable::AddHistogramSample(script_histogram, generation); | 209 isolate->stats_table()->AddHistogramSample(script_histogram_, generation); |
| 332 } | 210 } |
| 333 | 211 |
| 334 // Once outside the manacles of the handle scope, we need to recheck | 212 // Once outside the manacles of the handle scope, we need to recheck |
| 335 // to see if we actually found a cached script. If so, we return a | 213 // to see if we actually found a cached script. If so, we return a |
| 336 // handle created in the caller's handle scope. | 214 // handle created in the caller's handle scope. |
| 337 if (result != NULL) { | 215 if (result != NULL) { |
| 338 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result)); | 216 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result)); |
| 339 ASSERT(HasOrigin(shared, name, line_offset, column_offset)); | 217 ASSERT(HasOrigin(shared, name, line_offset, column_offset)); |
| 340 // If the script was found in a later generation, we promote it to | 218 // If the script was found in a later generation, we promote it to |
| 341 // the first generation to let it survive longer in the cache. | 219 // the first generation to let it survive longer in the cache. |
| 342 if (generation != 0) Put(source, shared); | 220 if (generation != 0) Put(source, shared); |
| 343 Counters::compilation_cache_hits.Increment(); | 221 isolate->counters()->compilation_cache_hits()->Increment(); |
| 344 return shared; | 222 return shared; |
| 345 } else { | 223 } else { |
| 346 Counters::compilation_cache_misses.Increment(); | 224 isolate->counters()->compilation_cache_misses()->Increment(); |
| 347 return Handle<SharedFunctionInfo>::null(); | 225 return Handle<SharedFunctionInfo>::null(); |
| 348 } | 226 } |
| 349 } | 227 } |
| 350 | 228 |
| 351 | 229 |
| 352 MaybeObject* CompilationCacheScript::TryTablePut( | 230 MaybeObject* CompilationCacheScript::TryTablePut( |
| 353 Handle<String> source, | 231 Handle<String> source, |
| 354 Handle<SharedFunctionInfo> function_info) { | 232 Handle<SharedFunctionInfo> function_info) { |
| 355 Handle<CompilationCacheTable> table = GetFirstTable(); | 233 Handle<CompilationCacheTable> table = GetFirstTable(); |
| 356 return table->Put(*source, *function_info); | 234 return table->Put(*source, *function_info); |
| 357 } | 235 } |
| 358 | 236 |
| 359 | 237 |
| 360 Handle<CompilationCacheTable> CompilationCacheScript::TablePut( | 238 Handle<CompilationCacheTable> CompilationCacheScript::TablePut( |
| 361 Handle<String> source, | 239 Handle<String> source, |
| 362 Handle<SharedFunctionInfo> function_info) { | 240 Handle<SharedFunctionInfo> function_info) { |
| 363 CALL_HEAP_FUNCTION(TryTablePut(source, function_info), CompilationCacheTable); | 241 Isolate* isolate = Isolate::Current(); |
| 242 CALL_HEAP_FUNCTION(isolate, |
| 243 TryTablePut(source, function_info), |
| 244 CompilationCacheTable); |
| 364 } | 245 } |
| 365 | 246 |
| 366 | 247 |
| 367 void CompilationCacheScript::Put(Handle<String> source, | 248 void CompilationCacheScript::Put(Handle<String> source, |
| 368 Handle<SharedFunctionInfo> function_info) { | 249 Handle<SharedFunctionInfo> function_info) { |
| 369 HandleScope scope; | 250 HandleScope scope; |
| 370 SetFirstTable(TablePut(source, function_info)); | 251 SetFirstTable(TablePut(source, function_info)); |
| 371 } | 252 } |
| 372 | 253 |
| 373 | 254 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 388 break; | 269 break; |
| 389 } | 270 } |
| 390 } | 271 } |
| 391 } | 272 } |
| 392 if (result->IsSharedFunctionInfo()) { | 273 if (result->IsSharedFunctionInfo()) { |
| 393 Handle<SharedFunctionInfo> | 274 Handle<SharedFunctionInfo> |
| 394 function_info(SharedFunctionInfo::cast(result)); | 275 function_info(SharedFunctionInfo::cast(result)); |
| 395 if (generation != 0) { | 276 if (generation != 0) { |
| 396 Put(source, context, function_info); | 277 Put(source, context, function_info); |
| 397 } | 278 } |
| 398 Counters::compilation_cache_hits.Increment(); | 279 COUNTERS->compilation_cache_hits()->Increment(); |
| 399 return function_info; | 280 return function_info; |
| 400 } else { | 281 } else { |
| 401 Counters::compilation_cache_misses.Increment(); | 282 COUNTERS->compilation_cache_misses()->Increment(); |
| 402 return Handle<SharedFunctionInfo>::null(); | 283 return Handle<SharedFunctionInfo>::null(); |
| 403 } | 284 } |
| 404 } | 285 } |
| 405 | 286 |
| 406 | 287 |
| 407 MaybeObject* CompilationCacheEval::TryTablePut( | 288 MaybeObject* CompilationCacheEval::TryTablePut( |
| 408 Handle<String> source, | 289 Handle<String> source, |
| 409 Handle<Context> context, | 290 Handle<Context> context, |
| 410 Handle<SharedFunctionInfo> function_info) { | 291 Handle<SharedFunctionInfo> function_info) { |
| 411 Handle<CompilationCacheTable> table = GetFirstTable(); | 292 Handle<CompilationCacheTable> table = GetFirstTable(); |
| 412 return table->PutEval(*source, *context, *function_info); | 293 return table->PutEval(*source, *context, *function_info); |
| 413 } | 294 } |
| 414 | 295 |
| 415 | 296 |
| 416 Handle<CompilationCacheTable> CompilationCacheEval::TablePut( | 297 Handle<CompilationCacheTable> CompilationCacheEval::TablePut( |
| 417 Handle<String> source, | 298 Handle<String> source, |
| 418 Handle<Context> context, | 299 Handle<Context> context, |
| 419 Handle<SharedFunctionInfo> function_info) { | 300 Handle<SharedFunctionInfo> function_info) { |
| 420 CALL_HEAP_FUNCTION(TryTablePut(source, context, function_info), | 301 Isolate* isolate = Isolate::Current(); |
| 302 CALL_HEAP_FUNCTION(isolate, |
| 303 TryTablePut(source, context, function_info), |
| 421 CompilationCacheTable); | 304 CompilationCacheTable); |
| 422 } | 305 } |
| 423 | 306 |
| 424 | 307 |
| 425 void CompilationCacheEval::Put(Handle<String> source, | 308 void CompilationCacheEval::Put(Handle<String> source, |
| 426 Handle<Context> context, | 309 Handle<Context> context, |
| 427 Handle<SharedFunctionInfo> function_info) { | 310 Handle<SharedFunctionInfo> function_info) { |
| 428 HandleScope scope; | 311 HandleScope scope; |
| 429 SetFirstTable(TablePut(source, context, function_info)); | 312 SetFirstTable(TablePut(source, context, function_info)); |
| 430 } | 313 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 444 if (result->IsFixedArray()) { | 327 if (result->IsFixedArray()) { |
| 445 break; | 328 break; |
| 446 } | 329 } |
| 447 } | 330 } |
| 448 } | 331 } |
| 449 if (result->IsFixedArray()) { | 332 if (result->IsFixedArray()) { |
| 450 Handle<FixedArray> data(FixedArray::cast(result)); | 333 Handle<FixedArray> data(FixedArray::cast(result)); |
| 451 if (generation != 0) { | 334 if (generation != 0) { |
| 452 Put(source, flags, data); | 335 Put(source, flags, data); |
| 453 } | 336 } |
| 454 Counters::compilation_cache_hits.Increment(); | 337 COUNTERS->compilation_cache_hits()->Increment(); |
| 455 return data; | 338 return data; |
| 456 } else { | 339 } else { |
| 457 Counters::compilation_cache_misses.Increment(); | 340 COUNTERS->compilation_cache_misses()->Increment(); |
| 458 return Handle<FixedArray>::null(); | 341 return Handle<FixedArray>::null(); |
| 459 } | 342 } |
| 460 } | 343 } |
| 461 | 344 |
| 462 | 345 |
| 463 MaybeObject* CompilationCacheRegExp::TryTablePut( | 346 MaybeObject* CompilationCacheRegExp::TryTablePut( |
| 464 Handle<String> source, | 347 Handle<String> source, |
| 465 JSRegExp::Flags flags, | 348 JSRegExp::Flags flags, |
| 466 Handle<FixedArray> data) { | 349 Handle<FixedArray> data) { |
| 467 Handle<CompilationCacheTable> table = GetFirstTable(); | 350 Handle<CompilationCacheTable> table = GetFirstTable(); |
| 468 return table->PutRegExp(*source, flags, *data); | 351 return table->PutRegExp(*source, flags, *data); |
| 469 } | 352 } |
| 470 | 353 |
| 471 | 354 |
| 472 Handle<CompilationCacheTable> CompilationCacheRegExp::TablePut( | 355 Handle<CompilationCacheTable> CompilationCacheRegExp::TablePut( |
| 473 Handle<String> source, | 356 Handle<String> source, |
| 474 JSRegExp::Flags flags, | 357 JSRegExp::Flags flags, |
| 475 Handle<FixedArray> data) { | 358 Handle<FixedArray> data) { |
| 476 CALL_HEAP_FUNCTION(TryTablePut(source, flags, data), CompilationCacheTable); | 359 Isolate* isolate = Isolate::Current(); |
| 360 CALL_HEAP_FUNCTION(isolate, |
| 361 TryTablePut(source, flags, data), |
| 362 CompilationCacheTable); |
| 477 } | 363 } |
| 478 | 364 |
| 479 | 365 |
| 480 void CompilationCacheRegExp::Put(Handle<String> source, | 366 void CompilationCacheRegExp::Put(Handle<String> source, |
| 481 JSRegExp::Flags flags, | 367 JSRegExp::Flags flags, |
| 482 Handle<FixedArray> data) { | 368 Handle<FixedArray> data) { |
| 483 HandleScope scope; | 369 HandleScope scope; |
| 484 SetFirstTable(TablePut(source, flags, data)); | 370 SetFirstTable(TablePut(source, flags, data)); |
| 485 } | 371 } |
| 486 | 372 |
| 487 | 373 |
| 488 void CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) { | 374 void CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) { |
| 489 if (!IsEnabled()) return; | 375 if (!IsEnabled()) return; |
| 490 | 376 |
| 491 eval_global.Remove(function_info); | 377 eval_global_.Remove(function_info); |
| 492 eval_contextual.Remove(function_info); | 378 eval_contextual_.Remove(function_info); |
| 493 script.Remove(function_info); | 379 script_.Remove(function_info); |
| 494 } | 380 } |
| 495 | 381 |
| 496 | 382 |
| 497 Handle<SharedFunctionInfo> CompilationCache::LookupScript(Handle<String> source, | 383 Handle<SharedFunctionInfo> CompilationCache::LookupScript(Handle<String> source, |
| 498 Handle<Object> name, | 384 Handle<Object> name, |
| 499 int line_offset, | 385 int line_offset, |
| 500 int column_offset) { | 386 int column_offset) { |
| 501 if (!IsEnabled()) { | 387 if (!IsEnabled()) { |
| 502 return Handle<SharedFunctionInfo>::null(); | 388 return Handle<SharedFunctionInfo>::null(); |
| 503 } | 389 } |
| 504 | 390 |
| 505 return script.Lookup(source, name, line_offset, column_offset); | 391 return script_.Lookup(source, name, line_offset, column_offset); |
| 506 } | 392 } |
| 507 | 393 |
| 508 | 394 |
| 509 Handle<SharedFunctionInfo> CompilationCache::LookupEval( | 395 Handle<SharedFunctionInfo> CompilationCache::LookupEval( |
| 510 Handle<String> source, | 396 Handle<String> source, |
| 511 Handle<Context> context, | 397 Handle<Context> context, |
| 512 bool is_global, | 398 bool is_global, |
| 513 StrictModeFlag strict_mode) { | 399 StrictModeFlag strict_mode) { |
| 514 if (!IsEnabled()) { | 400 if (!IsEnabled()) { |
| 515 return Handle<SharedFunctionInfo>::null(); | 401 return Handle<SharedFunctionInfo>::null(); |
| 516 } | 402 } |
| 517 | 403 |
| 518 Handle<SharedFunctionInfo> result; | 404 Handle<SharedFunctionInfo> result; |
| 519 if (is_global) { | 405 if (is_global) { |
| 520 result = eval_global.Lookup(source, context, strict_mode); | 406 result = eval_global_.Lookup(source, context, strict_mode); |
| 521 } else { | 407 } else { |
| 522 result = eval_contextual.Lookup(source, context, strict_mode); | 408 result = eval_contextual_.Lookup(source, context, strict_mode); |
| 523 } | 409 } |
| 524 return result; | 410 return result; |
| 525 } | 411 } |
| 526 | 412 |
| 527 | 413 |
| 528 Handle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source, | 414 Handle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source, |
| 529 JSRegExp::Flags flags) { | 415 JSRegExp::Flags flags) { |
| 530 if (!IsEnabled()) { | 416 if (!IsEnabled()) { |
| 531 return Handle<FixedArray>::null(); | 417 return Handle<FixedArray>::null(); |
| 532 } | 418 } |
| 533 | 419 |
| 534 return reg_exp.Lookup(source, flags); | 420 return reg_exp_.Lookup(source, flags); |
| 535 } | 421 } |
| 536 | 422 |
| 537 | 423 |
| 538 void CompilationCache::PutScript(Handle<String> source, | 424 void CompilationCache::PutScript(Handle<String> source, |
| 539 Handle<SharedFunctionInfo> function_info) { | 425 Handle<SharedFunctionInfo> function_info) { |
| 540 if (!IsEnabled()) { | 426 if (!IsEnabled()) { |
| 541 return; | 427 return; |
| 542 } | 428 } |
| 543 | 429 |
| 544 script.Put(source, function_info); | 430 script_.Put(source, function_info); |
| 545 } | 431 } |
| 546 | 432 |
| 547 | 433 |
| 548 void CompilationCache::PutEval(Handle<String> source, | 434 void CompilationCache::PutEval(Handle<String> source, |
| 549 Handle<Context> context, | 435 Handle<Context> context, |
| 550 bool is_global, | 436 bool is_global, |
| 551 Handle<SharedFunctionInfo> function_info) { | 437 Handle<SharedFunctionInfo> function_info) { |
| 552 if (!IsEnabled()) { | 438 if (!IsEnabled()) { |
| 553 return; | 439 return; |
| 554 } | 440 } |
| 555 | 441 |
| 556 HandleScope scope; | 442 HandleScope scope; |
| 557 if (is_global) { | 443 if (is_global) { |
| 558 eval_global.Put(source, context, function_info); | 444 eval_global_.Put(source, context, function_info); |
| 559 } else { | 445 } else { |
| 560 eval_contextual.Put(source, context, function_info); | 446 eval_contextual_.Put(source, context, function_info); |
| 561 } | 447 } |
| 562 } | 448 } |
| 563 | 449 |
| 564 | 450 |
| 565 | 451 |
| 566 void CompilationCache::PutRegExp(Handle<String> source, | 452 void CompilationCache::PutRegExp(Handle<String> source, |
| 567 JSRegExp::Flags flags, | 453 JSRegExp::Flags flags, |
| 568 Handle<FixedArray> data) { | 454 Handle<FixedArray> data) { |
| 569 if (!IsEnabled()) { | 455 if (!IsEnabled()) { |
| 570 return; | 456 return; |
| 571 } | 457 } |
| 572 | 458 |
| 573 reg_exp.Put(source, flags, data); | 459 reg_exp_.Put(source, flags, data); |
| 574 } | 460 } |
| 575 | 461 |
| 576 | 462 |
| 577 static bool SourceHashCompare(void* key1, void* key2) { | 463 static bool SourceHashCompare(void* key1, void* key2) { |
| 578 return key1 == key2; | 464 return key1 == key2; |
| 579 } | 465 } |
| 580 | 466 |
| 581 | 467 |
| 582 static HashMap* EagerOptimizingSet() { | 468 HashMap* CompilationCache::EagerOptimizingSet() { |
| 583 static HashMap map(&SourceHashCompare); | 469 if (eager_optimizing_set_ == NULL) { |
| 584 return ↦ | 470 eager_optimizing_set_ = new HashMap(&SourceHashCompare); |
| 471 } |
| 472 return eager_optimizing_set_; |
| 585 } | 473 } |
| 586 | 474 |
| 587 | 475 |
| 588 bool CompilationCache::ShouldOptimizeEagerly(Handle<JSFunction> function) { | 476 bool CompilationCache::ShouldOptimizeEagerly(Handle<JSFunction> function) { |
| 589 if (FLAG_opt_eagerly) return true; | 477 if (FLAG_opt_eagerly) return true; |
| 590 uint32_t hash = function->SourceHash(); | 478 uint32_t hash = function->SourceHash(); |
| 591 void* key = reinterpret_cast<void*>(hash); | 479 void* key = reinterpret_cast<void*>(hash); |
| 592 return EagerOptimizingSet()->Lookup(key, hash, false) != NULL; | 480 return EagerOptimizingSet()->Lookup(key, hash, false) != NULL; |
| 593 } | 481 } |
| 594 | 482 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 608 | 496 |
| 609 | 497 |
| 610 void CompilationCache::ResetEagerOptimizingData() { | 498 void CompilationCache::ResetEagerOptimizingData() { |
| 611 HashMap* set = EagerOptimizingSet(); | 499 HashMap* set = EagerOptimizingSet(); |
| 612 if (set->occupancy() > 0) set->Clear(); | 500 if (set->occupancy() > 0) set->Clear(); |
| 613 } | 501 } |
| 614 | 502 |
| 615 | 503 |
| 616 void CompilationCache::Clear() { | 504 void CompilationCache::Clear() { |
| 617 for (int i = 0; i < kSubCacheCount; i++) { | 505 for (int i = 0; i < kSubCacheCount; i++) { |
| 618 subcaches[i]->Clear(); | 506 subcaches_[i]->Clear(); |
| 619 } | 507 } |
| 620 } | 508 } |
| 621 | 509 |
| 510 |
| 622 void CompilationCache::Iterate(ObjectVisitor* v) { | 511 void CompilationCache::Iterate(ObjectVisitor* v) { |
| 623 for (int i = 0; i < kSubCacheCount; i++) { | 512 for (int i = 0; i < kSubCacheCount; i++) { |
| 624 subcaches[i]->Iterate(v); | 513 subcaches_[i]->Iterate(v); |
| 625 } | 514 } |
| 626 } | 515 } |
| 627 | 516 |
| 628 | 517 |
| 629 void CompilationCache::IterateFunctions(ObjectVisitor* v) { | 518 void CompilationCache::IterateFunctions(ObjectVisitor* v) { |
| 630 for (int i = 0; i < kSubCacheCount; i++) { | 519 for (int i = 0; i < kSubCacheCount; i++) { |
| 631 subcaches[i]->IterateFunctions(v); | 520 subcaches_[i]->IterateFunctions(v); |
| 632 } | 521 } |
| 633 } | 522 } |
| 634 | 523 |
| 635 | 524 |
| 636 void CompilationCache::MarkCompactPrologue() { | 525 void CompilationCache::MarkCompactPrologue() { |
| 637 for (int i = 0; i < kSubCacheCount; i++) { | 526 for (int i = 0; i < kSubCacheCount; i++) { |
| 638 subcaches[i]->Age(); | 527 subcaches_[i]->Age(); |
| 639 } | 528 } |
| 640 } | 529 } |
| 641 | 530 |
| 642 | 531 |
| 643 void CompilationCache::Enable() { | 532 void CompilationCache::Enable() { |
| 644 enabled = true; | 533 enabled_ = true; |
| 645 } | 534 } |
| 646 | 535 |
| 647 | 536 |
| 648 void CompilationCache::Disable() { | 537 void CompilationCache::Disable() { |
| 649 enabled = false; | 538 enabled_ = false; |
| 650 Clear(); | 539 Clear(); |
| 651 } | 540 } |
| 652 | 541 |
| 653 | 542 |
| 654 } } // namespace v8::internal | 543 } } // namespace v8::internal |
| OLD | NEW |