blob: e3388492cbae8ca96af6d47c2707df2d6ad12a6b [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002// 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;
Steve Block44f0eee2011-05-26 01:26:41 +010040class Semaphore;
41
Steve Block44f0eee2011-05-26 01:26:41 +010042class RuntimeProfiler {
Ben Murdochb0fe1622011-05-05 13:52:32 +010043 public:
Steve Block44f0eee2011-05-26 01:26:41 +010044 explicit RuntimeProfiler(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010045
Ben Murdoch8b112d22011-06-08 16:22:53 +010046 static void GlobalSetup();
47
48 static inline bool IsEnabled() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010049 ASSERT(has_been_globally_set_up_);
Ben Murdoch8b112d22011-06-08 16:22:53 +010050 return enabled_;
51 }
Ben Murdochb0fe1622011-05-05 13:52:32 +010052
Steve Block44f0eee2011-05-26 01:26:41 +010053 void OptimizeNow();
Ben Murdochb0fe1622011-05-05 13:52:32 +010054
Steve Block44f0eee2011-05-26 01:26:41 +010055 void NotifyTick();
Ben Murdochb0fe1622011-05-05 13:52:32 +010056
Ben Murdoch3ef787d2012-04-12 10:51:47 +010057 void SetUp();
Steve Block44f0eee2011-05-26 01:26:41 +010058 void Reset();
59 void TearDown();
60
61 Object** SamplerWindowAddress();
62 int SamplerWindowSize();
63
Ben Murdoch3ef787d2012-04-12 10:51:47 +010064 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
Steve Block44f0eee2011-05-26 01:26:41 +010073 // 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
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000096 // Stops the runtime profiler thread when profiling support is being
97 // turned off.
98 static void StopRuntimeProfilerThreadBeforeShutdown(Thread* thread);
Steve Block44f0eee2011-05-26 01:26:41 +010099
100 void UpdateSamplesAfterScavenge();
101 void RemoveDeadSamples();
102 void UpdateSamplesAfterCompact(ObjectVisitor* visitor);
103
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100104 void AttemptOnStackReplacement(JSFunction* function);
105
Steve Block44f0eee2011-05-26 01:26:41 +0100106 private:
107 static const int kSamplerWindowSize = 16;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100108
Steve Block44f0eee2011-05-26 01:26:41 +0100109 static void HandleWakeUp(Isolate* isolate);
110
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100111 void Optimize(JSFunction* function, const char* reason);
Steve Block44f0eee2011-05-26 01:26:41 +0100112
113 void ClearSampleBuffer();
114
115 void ClearSampleBufferNewSpaceEntries();
116
117 int LookupSample(JSFunction* function);
118
119 void AddSample(JSFunction* function, int weight);
120
Steve Block44f0eee2011-05-26 01:26:41 +0100121 Isolate* isolate_;
122
123 int sampler_threshold_;
124 int sampler_threshold_size_factor_;
125 int sampler_ticks_until_threshold_adjustment_;
126
Steve Block44f0eee2011-05-26 01:26:41 +0100127 Object* sampler_window_[kSamplerWindowSize];
128 int sampler_window_position_;
129 int sampler_window_weight_[kSamplerWindowSize];
130
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100131 bool any_ic_changed_;
132 bool code_generated_;
133 int total_code_generated_;
134
Steve Block44f0eee2011-05-26 01:26:41 +0100135 // 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_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100139
140#ifdef DEBUG
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100141 static bool has_been_globally_set_up_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100142#endif
143 static bool enabled_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100144};
145
146
147// Rate limiter intended to be used in the profiler thread.
148class RuntimeProfilerRateLimiter BASE_EMBEDDED {
149 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000150 RuntimeProfilerRateLimiter() {}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100151
Steve Block44f0eee2011-05-26 01:26:41 +0100152 // 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.)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100156 //
157 // Does nothing when runtime profiling is not enabled.
158 bool SuspendIfNecessary();
159
160 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100161 DISALLOW_COPY_AND_ASSIGN(RuntimeProfilerRateLimiter);
162};
163
Steve Block44f0eee2011-05-26 01:26:41 +0100164
165// Implementation of RuntimeProfiler inline functions.
166
167void 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
179void RuntimeProfiler::IsolateExitedJS(Isolate* isolate) {
180 Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, -1);
181 ASSERT(new_state >= 0);
182 USE(new_state);
183}
184
Ben Murdochb0fe1622011-05-05 13:52:32 +0100185} } // namespace v8::internal
186
187#endif // V8_RUNTIME_PROFILER_H_