• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IsEnabled()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 
NotifyICChanged()64   void NotifyICChanged() { any_ic_changed_ = true; }
65 
NotifyCodeGenerated(int generated_code_size)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:
RuntimeProfilerRateLimiter()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 
IsolateEnteredJS(Isolate * isolate)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 
IsolateExitedJS(Isolate * isolate)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