| OLD | NEW | 
|    1 // Copyright 2010 the V8 project authors. All rights reserved. |    1 // Copyright 2010 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   61  private: |   61  private: | 
|   62   void Destroy(); |   62   void Destroy(); | 
|   63   static void WeakCallback(v8::Persistent<v8::Value> object, void* data); |   63   static void WeakCallback(v8::Persistent<v8::Value> object, void* data); | 
|   64  |   64  | 
|   65   PendingListNode* next_; |   65   PendingListNode* next_; | 
|   66   Handle<Object> function_;  // Weak handle. |   66   Handle<Object> function_;  // Weak handle. | 
|   67   int64_t start_; |   67   int64_t start_; | 
|   68 }; |   68 }; | 
|   69  |   69  | 
|   70  |   70  | 
|   71 enum SamplerState { |  | 
|   72   IN_NON_JS_STATE = 0, |  | 
|   73   IN_JS_STATE = 1 |  | 
|   74 }; |  | 
|   75  |  | 
|   76  |  | 
|   77 // Optimization sampler constants. |   71 // Optimization sampler constants. | 
|   78 static const int kSamplerFrameCount = 2; |   72 static const int kSamplerFrameCount = 2; | 
|   79 static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 }; |   73 static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 }; | 
|   80 static const int kSamplerWindowSize = 16; |   74 static const int kSamplerWindowSize = 16; | 
|   81  |   75  | 
|   82 static const int kSamplerTicksBetweenThresholdAdjustment = 32; |   76 static const int kSamplerTicksDelta = 32; | 
|   83  |   77  | 
|   84 static const int kSamplerThresholdInit = 3; |   78 static const int kSamplerThresholdInit = 3; | 
|   85 static const int kSamplerThresholdMin = 1; |   79 static const int kSamplerThresholdMin = 1; | 
|   86 static const int kSamplerThresholdDelta = 1; |   80 static const int kSamplerThresholdDelta = 1; | 
|   87  |   81  | 
|   88 static const int kSamplerThresholdSizeFactorInit = 3; |   82 static const int kSamplerThresholdSizeFactorInit = 3; | 
|   89 static const int kSamplerThresholdSizeFactorMin = 1; |   83 static const int kSamplerThresholdSizeFactorMin = 1; | 
|   90 static const int kSamplerThresholdSizeFactorDelta = 1; |   84 static const int kSamplerThresholdSizeFactorDelta = 1; | 
|   91  |   85  | 
|   92 static const int kSizeLimit = 1500; |   86 static const int kSizeLimit = 1500; | 
|   93  |   87  | 
|   94 static int sampler_threshold = kSamplerThresholdInit; |   88 static int sampler_threshold = kSamplerThresholdInit; | 
|   95 static int sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; |   89 static int sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; | 
|   96  |   90  | 
|   97 static int sampler_ticks_until_threshold_adjustment = |  | 
|   98     kSamplerTicksBetweenThresholdAdjustment; |  | 
|   99  |  | 
|  100 // The ratio of ticks spent in JS code in percent. |  | 
|  101 static Atomic32 js_ratio; |  | 
|  102  |   91  | 
|  103 // The JSFunctions in the sampler window are not GC safe. Old-space |   92 // The JSFunctions in the sampler window are not GC safe. Old-space | 
|  104 // pointers are not cleared during mark-sweep collection and therefore |   93 // pointers are not cleared during mark-sweep collection and therefore | 
|  105 // the window might contain stale pointers. The window is updated on |   94 // the window might contain stale pointers. The window is updated on | 
|  106 // scavenges and (parts of it) cleared on mark-sweep and |   95 // scavenges and (parts of it) cleared on mark-sweep and | 
|  107 // mark-sweep-compact. |   96 // mark-sweep-compact. | 
|  108 static Object* sampler_window[kSamplerWindowSize] = { NULL, }; |   97 static Object* sampler_window[kSamplerWindowSize] = { NULL, }; | 
|  109 static int sampler_window_position = 0; |   98 static int sampler_window_position = 0; | 
|  110 static int sampler_window_weight[kSamplerWindowSize] = { 0, }; |   99 static int sampler_window_weight[kSamplerWindowSize] = { 0, }; | 
|  111  |  100  | 
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  265     } |  254     } | 
|  266     delete current; |  255     delete current; | 
|  267     current = next; |  256     current = next; | 
|  268   } |  257   } | 
|  269   optimize_soon_list = NULL; |  258   optimize_soon_list = NULL; | 
|  270  |  259  | 
|  271   // Run through the JavaScript frames and collect them. If we already |  260   // Run through the JavaScript frames and collect them. If we already | 
|  272   // have a sample of the function, we mark it for optimizations |  261   // have a sample of the function, we mark it for optimizations | 
|  273   // (eagerly or lazily). |  262   // (eagerly or lazily). | 
|  274   JSFunction* samples[kSamplerFrameCount]; |  263   JSFunction* samples[kSamplerFrameCount]; | 
|  275   int sample_count = 0; |  264   int count = 0; | 
|  276   int frame_count = 0; |  | 
|  277   for (JavaScriptFrameIterator it; |  265   for (JavaScriptFrameIterator it; | 
|  278        frame_count++ < kSamplerFrameCount && !it.done(); |  266        count < kSamplerFrameCount && !it.done(); | 
|  279        it.Advance()) { |  267        it.Advance()) { | 
|  280     JavaScriptFrame* frame = it.frame(); |  268     JavaScriptFrame* frame = it.frame(); | 
|  281     JSFunction* function = JSFunction::cast(frame->function()); |  269     JSFunction* function = JSFunction::cast(frame->function()); | 
|  282  |  270     int function_size = function->shared()->SourceSize(); | 
|  283     // Adjust threshold each time we have processed |  271     int threshold_size_factor; | 
|  284     // a certain number of ticks. |  272     if (function_size > kSizeLimit) { | 
|  285     if (sampler_ticks_until_threshold_adjustment > 0) { |  273       threshold_size_factor = sampler_threshold_size_factor; | 
|  286       sampler_ticks_until_threshold_adjustment--; |  274     } else { | 
|  287       if (sampler_ticks_until_threshold_adjustment <= 0) { |  275       threshold_size_factor = 1; | 
|  288         // If the threshold is not already at the minimum |  | 
|  289         // modify and reset the ticks until next adjustment. |  | 
|  290         if (sampler_threshold > kSamplerThresholdMin) { |  | 
|  291           sampler_threshold -= kSamplerThresholdDelta; |  | 
|  292           sampler_ticks_until_threshold_adjustment = |  | 
|  293               kSamplerTicksBetweenThresholdAdjustment; |  | 
|  294         } |  | 
|  295       } |  | 
|  296     } |  276     } | 
|  297  |  277  | 
 |  278     int threshold = sampler_threshold * threshold_size_factor; | 
 |  279     samples[count++] = function; | 
|  298     if (function->IsMarkedForLazyRecompilation()) { |  280     if (function->IsMarkedForLazyRecompilation()) { | 
|  299       Code* unoptimized = function->shared()->code(); |  281       Code* unoptimized = function->shared()->code(); | 
|  300       int nesting = unoptimized->allow_osr_at_loop_nesting_level(); |  282       int nesting = unoptimized->allow_osr_at_loop_nesting_level(); | 
|  301       if (nesting == 0) AttemptOnStackReplacement(function); |  283       if (nesting == 0) AttemptOnStackReplacement(function); | 
|  302       int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker); |  284       int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker); | 
|  303       unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting); |  285       unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting); | 
|  304     } |  286     } else if (LookupSample(function) >= threshold) { | 
|  305  |  287       if (IsOptimizable(function)) { | 
|  306     // Do not record non-optimizable functions. |  288         Optimize(function, false, 0); | 
|  307     if (!IsOptimizable(function)) continue; |  289         CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function)); | 
|  308     samples[sample_count++] = function; |  290       } | 
|  309  |  | 
|  310     int function_size = function->shared()->SourceSize(); |  | 
|  311     int threshold_size_factor = (function_size > kSizeLimit) |  | 
|  312         ? sampler_threshold_size_factor |  | 
|  313         : 1; |  | 
|  314  |  | 
|  315     int threshold = sampler_threshold * threshold_size_factor; |  | 
|  316     int current_js_ratio = NoBarrier_Load(&js_ratio); |  | 
|  317  |  | 
|  318     // Adjust threshold depending on the ratio of time spent |  | 
|  319     // in JS code. |  | 
|  320     if (current_js_ratio < 20) { |  | 
|  321       // If we spend less than 20% of the time in JS code, |  | 
|  322       // do not optimize. |  | 
|  323       continue; |  | 
|  324     } else if (current_js_ratio < 75) { |  | 
|  325       // Below 75% of time spent in JS code, only optimize very |  | 
|  326       // frequently used functions. |  | 
|  327       threshold *= 3; |  | 
|  328     } |  | 
|  329  |  | 
|  330     if (LookupSample(function) >= threshold) { |  | 
|  331       Optimize(function, false, 0); |  | 
|  332       CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function)); |  | 
|  333     } |  291     } | 
|  334   } |  292   } | 
|  335  |  293  | 
|  336   // Add the collected functions as samples. It's important not to do |  294   // Add the collected functions as samples. It's important not to do | 
|  337   // this as part of collecting them because this will interfere with |  295   // this as part of collecting them because this will interfere with | 
|  338   // the sample lookup in case of recursive functions. |  296   // the sample lookup in case of recursive functions. | 
|  339   for (int i = 0; i < sample_count; i++) { |  297   for (int i = 0; i < count; i++) { | 
|  340     AddSample(samples[i], kSamplerFrameWeight[i]); |  298     AddSample(samples[i], kSamplerFrameWeight[i]); | 
|  341   } |  299   } | 
|  342 } |  300 } | 
|  343  |  301  | 
|  344  |  302  | 
|  345 void RuntimeProfiler::OptimizeSoon(JSFunction* function) { |  303 void RuntimeProfiler::OptimizeSoon(JSFunction* function) { | 
|  346   if (!IsOptimizable(function)) return; |  304   if (!IsOptimizable(function)) return; | 
|  347   PendingListNode* node = new PendingListNode(function); |  305   PendingListNode* node = new PendingListNode(function); | 
|  348   node->set_next(optimize_soon_list); |  306   node->set_next(optimize_soon_list); | 
|  349   optimize_soon_list = node; |  307   optimize_soon_list = node; | 
|  350 } |  308 } | 
|  351  |  309  | 
|  352  |  310  | 
|  353 static void UpdateStateRatio(SamplerState current_state) { |  | 
|  354   static const int kStateWindowSize = 128; |  | 
|  355   static SamplerState state_window[kStateWindowSize]; |  | 
|  356   static int state_window_position = 0; |  | 
|  357   static int state_counts[2] = { kStateWindowSize, 0 }; |  | 
|  358  |  | 
|  359   SamplerState old_state = state_window[state_window_position]; |  | 
|  360   state_counts[old_state]--; |  | 
|  361   state_window[state_window_position] = current_state; |  | 
|  362   state_counts[current_state]++; |  | 
|  363   ASSERT(IsPowerOf2(kStateWindowSize)); |  | 
|  364   state_window_position = (state_window_position + 1) & |  | 
|  365       (kStateWindowSize - 1); |  | 
|  366   NoBarrier_Store(&js_ratio, state_counts[IN_JS_STATE] * 100 / |  | 
|  367                   kStateWindowSize); |  | 
|  368 } |  | 
|  369  |  | 
|  370  |  | 
|  371 void RuntimeProfiler::NotifyTick() { |  311 void RuntimeProfiler::NotifyTick() { | 
|  372   // Record state sample. |  | 
|  373   SamplerState state = Top::IsInJSState() |  | 
|  374       ? IN_JS_STATE |  | 
|  375       : IN_NON_JS_STATE; |  | 
|  376   UpdateStateRatio(state); |  | 
|  377   StackGuard::RequestRuntimeProfilerTick(); |  312   StackGuard::RequestRuntimeProfilerTick(); | 
|  378 } |  313 } | 
|  379  |  314  | 
|  380  |  315  | 
|  381 void RuntimeProfiler::MarkCompactPrologue(bool is_compacting) { |  316 void RuntimeProfiler::MarkCompactPrologue(bool is_compacting) { | 
|  382   if (is_compacting) { |  317   if (is_compacting) { | 
|  383     // Clear all samples before mark-sweep-compact because every |  318     // Clear all samples before mark-sweep-compact because every | 
|  384     // function might move. |  319     // function might move. | 
|  385     ClearSampleBuffer(); |  320     ClearSampleBuffer(); | 
|  386   } else { |  321   } else { | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|  399 void RuntimeProfiler::Setup() { |  334 void RuntimeProfiler::Setup() { | 
|  400   ClearSampleBuffer(); |  335   ClearSampleBuffer(); | 
|  401   // If the ticker hasn't already started, make sure to do so to get |  336   // If the ticker hasn't already started, make sure to do so to get | 
|  402   // the ticks for the runtime profiler. |  337   // the ticks for the runtime profiler. | 
|  403   if (IsEnabled()) Logger::EnsureTickerStarted(); |  338   if (IsEnabled()) Logger::EnsureTickerStarted(); | 
|  404 } |  339 } | 
|  405  |  340  | 
|  406  |  341  | 
|  407 void RuntimeProfiler::Reset() { |  342 void RuntimeProfiler::Reset() { | 
|  408   sampler_threshold = kSamplerThresholdInit; |  343   sampler_threshold = kSamplerThresholdInit; | 
|  409   sampler_ticks_until_threshold_adjustment = |  | 
|  410       kSamplerTicksBetweenThresholdAdjustment; |  | 
|  411   sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; |  344   sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; | 
|  412 } |  345 } | 
|  413  |  346  | 
|  414  |  347  | 
|  415 void RuntimeProfiler::TearDown() { |  348 void RuntimeProfiler::TearDown() { | 
|  416   // Nothing to do. |  349   // Nothing to do. | 
|  417 } |  350 } | 
|  418  |  351  | 
|  419  |  352  | 
|  420 Object** RuntimeProfiler::SamplerWindowAddress() { |  353 Object** RuntimeProfiler::SamplerWindowAddress() { | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
|  443       } else { |  376       } else { | 
|  444         if (Top::WaitForJSState()) return true; |  377         if (Top::WaitForJSState()) return true; | 
|  445       } |  378       } | 
|  446     } |  379     } | 
|  447   } |  380   } | 
|  448   return false; |  381   return false; | 
|  449 } |  382 } | 
|  450  |  383  | 
|  451  |  384  | 
|  452 } }  // namespace v8::internal |  385 } }  // namespace v8::internal | 
| OLD | NEW |