blob: 8074035a92da02d37c4c8217db7f9275c508d98a [file] [log] [blame]
Ben Murdochb0fe1622011-05-05 13:52:32 +01001// Copyright 2010 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
Ben Murdochb0fe1622011-05-05 13:52:32 +010031#include "allocation.h"
Steve Block44f0eee2011-05-26 01:26:41 +010032#include "atomicops.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010033
34namespace v8 {
35namespace internal {
36
Steve Block44f0eee2011-05-26 01:26:41 +010037class Isolate;
38class JSFunction;
39class Object;
40class PendingListNode;
41class Semaphore;
42
43
44enum SamplerState {
45 IN_NON_JS_STATE = 0,
46 IN_JS_STATE = 1
47};
48
49
50class RuntimeProfiler {
Ben Murdochb0fe1622011-05-05 13:52:32 +010051 public:
Steve Block44f0eee2011-05-26 01:26:41 +010052 explicit RuntimeProfiler(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010053
Steve Block44f0eee2011-05-26 01:26:41 +010054 static bool IsEnabled();
Ben Murdochb0fe1622011-05-05 13:52:32 +010055
Steve Block44f0eee2011-05-26 01:26:41 +010056 void OptimizeNow();
57 void OptimizeSoon(JSFunction* function);
Ben Murdochb0fe1622011-05-05 13:52:32 +010058
Steve Block44f0eee2011-05-26 01:26:41 +010059 void NotifyTick();
Ben Murdochb0fe1622011-05-05 13:52:32 +010060
Steve Block44f0eee2011-05-26 01:26:41 +010061 void Setup();
62 void Reset();
63 void TearDown();
64
65 Object** SamplerWindowAddress();
66 int SamplerWindowSize();
67
68 // Rate limiting support.
69
70 // VM thread interface.
71 //
72 // Called by isolates when their states change.
73 static inline void IsolateEnteredJS(Isolate* isolate);
74 static inline void IsolateExitedJS(Isolate* isolate);
75
76 // Profiler thread interface.
77 //
78 // IsSomeIsolateInJS():
79 // The profiler thread can query whether some isolate is currently
80 // running JavaScript code.
81 //
82 // WaitForSomeIsolateToEnterJS():
83 // When no isolates are running JavaScript code for some time the
84 // profiler thread suspends itself by calling the wait function. The
85 // wait function returns true after it waited or false immediately.
86 // While the function was waiting the profiler may have been
87 // disabled so it *must check* whether it is allowed to continue.
88 static bool IsSomeIsolateInJS();
89 static bool WaitForSomeIsolateToEnterJS();
90
91 // When shutting down we join the profiler thread. Doing so while
92 // it's waiting on a semaphore will cause a deadlock, so we have to
93 // wake it up first.
94 static void WakeUpRuntimeProfilerThreadBeforeShutdown();
95
96 void UpdateSamplesAfterScavenge();
97 void RemoveDeadSamples();
98 void UpdateSamplesAfterCompact(ObjectVisitor* visitor);
99
100 private:
101 static const int kSamplerWindowSize = 16;
102 static const int kStateWindowSize = 128;
103
104 static void HandleWakeUp(Isolate* isolate);
105
106 void Optimize(JSFunction* function, bool eager, int delay);
107
108 void AttemptOnStackReplacement(JSFunction* function);
109
110 void ClearSampleBuffer();
111
112 void ClearSampleBufferNewSpaceEntries();
113
114 int LookupSample(JSFunction* function);
115
116 void AddSample(JSFunction* function, int weight);
117
118#ifdef ENABLE_LOGGING_AND_PROFILING
119 void UpdateStateRatio(SamplerState current_state);
120#endif
121
122 Isolate* isolate_;
123
124 int sampler_threshold_;
125 int sampler_threshold_size_factor_;
126 int sampler_ticks_until_threshold_adjustment_;
127
128 // The ratio of ticks spent in JS code in percent.
129 Atomic32 js_ratio_;
130
131 Object* sampler_window_[kSamplerWindowSize];
132 int sampler_window_position_;
133 int sampler_window_weight_[kSamplerWindowSize];
134
135 // Support for pending 'optimize soon' requests.
136 PendingListNode* optimize_soon_list_;
137
138 SamplerState state_window_[kStateWindowSize];
139 int state_window_position_;
140 int state_counts_[2];
141
142 // Possible state values:
143 // -1 => the profiler thread is waiting on the semaphore
144 // 0 or positive => the number of isolates running JavaScript code.
145 static Atomic32 state_;
146 static Semaphore* semaphore_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100147};
148
149
150// Rate limiter intended to be used in the profiler thread.
151class RuntimeProfilerRateLimiter BASE_EMBEDDED {
152 public:
153 RuntimeProfilerRateLimiter() : non_js_ticks_(0) { }
154
Steve Block44f0eee2011-05-26 01:26:41 +0100155 // Suspends the current thread (which must be the profiler thread)
156 // when not executing JavaScript to minimize CPU usage. Returns
157 // whether the thread was suspended (and so must check whether
158 // profiling is still active.)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100159 //
160 // Does nothing when runtime profiling is not enabled.
161 bool SuspendIfNecessary();
162
163 private:
164 int non_js_ticks_;
165
166 DISALLOW_COPY_AND_ASSIGN(RuntimeProfilerRateLimiter);
167};
168
Steve Block44f0eee2011-05-26 01:26:41 +0100169
170// Implementation of RuntimeProfiler inline functions.
171
172void RuntimeProfiler::IsolateEnteredJS(Isolate* isolate) {
173 Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, 1);
174 if (new_state == 0) {
175 // Just incremented from -1 to 0. -1 can only be set by the
176 // profiler thread before it suspends itself and starts waiting on
177 // the semaphore.
178 HandleWakeUp(isolate);
179 }
180 ASSERT(new_state >= 0);
181}
182
183
184void RuntimeProfiler::IsolateExitedJS(Isolate* isolate) {
185 Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, -1);
186 ASSERT(new_state >= 0);
187 USE(new_state);
188}
189
Ben Murdochb0fe1622011-05-05 13:52:32 +0100190} } // namespace v8::internal
191
192#endif // V8_RUNTIME_PROFILER_H_