Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     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.
     27 
     28 #ifndef V8_RUNTIME_PROFILER_H_
     29 #define V8_RUNTIME_PROFILER_H_
     30 
     31 #include "allocation.h"
     32 #include "atomicops.h"
     33 
     34 namespace v8 {
     35 namespace internal {
     36 
     37 class Isolate;
     38 class JSFunction;
     39 class Object;
     40 class Semaphore;
     41 
     42 class RuntimeProfiler {
     43  public:
     44   explicit RuntimeProfiler(Isolate* isolate);
     45 
     46   static void GlobalSetup();
     47 
     48   static inline bool IsEnabled() {
     49     ASSERT(has_been_globally_set_up_);
     50     return enabled_;
     51   }
     52 
     53   void OptimizeNow();
     54 
     55   void NotifyTick();
     56 
     57   void SetUp();
     58   void Reset();
     59   void TearDown();
     60 
     61   Object** SamplerWindowAddress();
     62   int SamplerWindowSize();
     63 
     64   void NotifyICChanged() { any_ic_changed_ = true; }
     65 
     66   void NotifyCodeGenerated(int generated_code_size) {
     67     if (FLAG_watch_ic_patching) {
     68       code_generated_ = true;
     69       total_code_generated_ += generated_code_size;
     70     }
     71   }
     72 
     73   // Rate limiting support.
     74 
     75   // VM thread interface.
     76   //
     77   // Called by isolates when their states change.
     78   static inline void IsolateEnteredJS(Isolate* isolate);
     79   static inline void IsolateExitedJS(Isolate* isolate);
     80 
     81   // Profiler thread interface.
     82   //
     83   // IsSomeIsolateInJS():
     84   // The profiler thread can query whether some isolate is currently
     85   // running JavaScript code.
     86   //
     87   // WaitForSomeIsolateToEnterJS():
     88   // When no isolates are running JavaScript code for some time the
     89   // profiler thread suspends itself by calling the wait function. The
     90   // wait function returns true after it waited or false immediately.
     91   // While the function was waiting the profiler may have been
     92   // disabled so it *must check* whether it is allowed to continue.
     93   static bool IsSomeIsolateInJS();
     94   static bool WaitForSomeIsolateToEnterJS();
     95 
     96   // Stops the runtime profiler thread when profiling support is being
     97   // turned off.
     98   static void StopRuntimeProfilerThreadBeforeShutdown(Thread* thread);
     99 
    100   void UpdateSamplesAfterScavenge();
    101   void RemoveDeadSamples();
    102   void UpdateSamplesAfterCompact(ObjectVisitor* visitor);
    103 
    104   void AttemptOnStackReplacement(JSFunction* function);
    105 
    106  private:
    107   static const int kSamplerWindowSize = 16;
    108 
    109   static void HandleWakeUp(Isolate* isolate);
    110 
    111   void Optimize(JSFunction* function, const char* reason);
    112 
    113   void ClearSampleBuffer();
    114 
    115   void ClearSampleBufferNewSpaceEntries();
    116 
    117   int LookupSample(JSFunction* function);
    118 
    119   void AddSample(JSFunction* function, int weight);
    120 
    121   Isolate* isolate_;
    122 
    123   int sampler_threshold_;
    124   int sampler_threshold_size_factor_;
    125   int sampler_ticks_until_threshold_adjustment_;
    126 
    127   Object* sampler_window_[kSamplerWindowSize];
    128   int sampler_window_position_;
    129   int sampler_window_weight_[kSamplerWindowSize];
    130 
    131   bool any_ic_changed_;
    132   bool code_generated_;
    133   int total_code_generated_;
    134 
    135   // Possible state values:
    136   //   -1            => the profiler thread is waiting on the semaphore
    137   //   0 or positive => the number of isolates running JavaScript code.
    138   static Atomic32 state_;
    139 
    140 #ifdef DEBUG
    141   static bool has_been_globally_set_up_;
    142 #endif
    143   static bool enabled_;
    144 };
    145 
    146 
    147 // Rate limiter intended to be used in the profiler thread.
    148 class RuntimeProfilerRateLimiter BASE_EMBEDDED {
    149  public:
    150   RuntimeProfilerRateLimiter() {}
    151 
    152   // Suspends the current thread (which must be the profiler thread)
    153   // when not executing JavaScript to minimize CPU usage. Returns
    154   // whether the thread was suspended (and so must check whether
    155   // profiling is still active.)
    156   //
    157   // Does nothing when runtime profiling is not enabled.
    158   bool SuspendIfNecessary();
    159 
    160  private:
    161   DISALLOW_COPY_AND_ASSIGN(RuntimeProfilerRateLimiter);
    162 };
    163 
    164 
    165 // Implementation of RuntimeProfiler inline functions.
    166 
    167 void RuntimeProfiler::IsolateEnteredJS(Isolate* isolate) {
    168   Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, 1);
    169   if (new_state == 0) {
    170     // Just incremented from -1 to 0. -1 can only be set by the
    171     // profiler thread before it suspends itself and starts waiting on
    172     // the semaphore.
    173     HandleWakeUp(isolate);
    174   }
    175   ASSERT(new_state >= 0);
    176 }
    177 
    178 
    179 void RuntimeProfiler::IsolateExitedJS(Isolate* isolate) {
    180   Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, -1);
    181   ASSERT(new_state >= 0);
    182   USE(new_state);
    183 }
    184 
    185 } }  // namespace v8::internal
    186 
    187 #endif  // V8_RUNTIME_PROFILER_H_
    188