blob: 15c209713e93b42aa34ed24539865092afbe66d4 [file] [log] [blame]
Ben Murdoch85b71792012-04-11 18:30:58 +01001// Copyright 2010 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 Murdoch85b71792012-04-11 18:30:58 +010049 ASSERT(has_been_globally_setup_);
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 Murdoch85b71792012-04-11 18:30:58 +010057 void Setup();
Steve Block44f0eee2011-05-26 01:26:41 +010058 void Reset();
59 void TearDown();
60
61 Object** SamplerWindowAddress();
62 int SamplerWindowSize();
63
64 // Rate limiting support.
65
66 // VM thread interface.
67 //
68 // Called by isolates when their states change.
69 static inline void IsolateEnteredJS(Isolate* isolate);
70 static inline void IsolateExitedJS(Isolate* isolate);
71
72 // Profiler thread interface.
73 //
74 // IsSomeIsolateInJS():
75 // The profiler thread can query whether some isolate is currently
76 // running JavaScript code.
77 //
78 // WaitForSomeIsolateToEnterJS():
79 // When no isolates are running JavaScript code for some time the
80 // profiler thread suspends itself by calling the wait function. The
81 // wait function returns true after it waited or false immediately.
82 // While the function was waiting the profiler may have been
83 // disabled so it *must check* whether it is allowed to continue.
84 static bool IsSomeIsolateInJS();
85 static bool WaitForSomeIsolateToEnterJS();
86
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000087 // Stops the runtime profiler thread when profiling support is being
88 // turned off.
89 static void StopRuntimeProfilerThreadBeforeShutdown(Thread* thread);
Steve Block44f0eee2011-05-26 01:26:41 +010090
91 void UpdateSamplesAfterScavenge();
92 void RemoveDeadSamples();
93 void UpdateSamplesAfterCompact(ObjectVisitor* visitor);
94
95 private:
96 static const int kSamplerWindowSize = 16;
Ben Murdoch8b112d22011-06-08 16:22:53 +010097
Steve Block44f0eee2011-05-26 01:26:41 +010098 static void HandleWakeUp(Isolate* isolate);
99
Ben Murdoch85b71792012-04-11 18:30:58 +0100100 void Optimize(JSFunction* function);
101
102 void AttemptOnStackReplacement(JSFunction* function);
Steve Block44f0eee2011-05-26 01:26:41 +0100103
104 void ClearSampleBuffer();
105
106 void ClearSampleBufferNewSpaceEntries();
107
108 int LookupSample(JSFunction* function);
109
110 void AddSample(JSFunction* function, int weight);
111
Steve Block44f0eee2011-05-26 01:26:41 +0100112 Isolate* isolate_;
113
114 int sampler_threshold_;
115 int sampler_threshold_size_factor_;
116 int sampler_ticks_until_threshold_adjustment_;
117
Steve Block44f0eee2011-05-26 01:26:41 +0100118 Object* sampler_window_[kSamplerWindowSize];
119 int sampler_window_position_;
120 int sampler_window_weight_[kSamplerWindowSize];
121
Steve Block44f0eee2011-05-26 01:26:41 +0100122 // Possible state values:
123 // -1 => the profiler thread is waiting on the semaphore
124 // 0 or positive => the number of isolates running JavaScript code.
125 static Atomic32 state_;
Ben Murdoch85b71792012-04-11 18:30:58 +0100126 static Semaphore* semaphore_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100127
128#ifdef DEBUG
Ben Murdoch85b71792012-04-11 18:30:58 +0100129 static bool has_been_globally_setup_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100130#endif
131 static bool enabled_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100132};
133
134
135// Rate limiter intended to be used in the profiler thread.
136class RuntimeProfilerRateLimiter BASE_EMBEDDED {
137 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000138 RuntimeProfilerRateLimiter() {}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100139
Steve Block44f0eee2011-05-26 01:26:41 +0100140 // Suspends the current thread (which must be the profiler thread)
141 // when not executing JavaScript to minimize CPU usage. Returns
142 // whether the thread was suspended (and so must check whether
143 // profiling is still active.)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100144 //
145 // Does nothing when runtime profiling is not enabled.
146 bool SuspendIfNecessary();
147
148 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100149 DISALLOW_COPY_AND_ASSIGN(RuntimeProfilerRateLimiter);
150};
151
Steve Block44f0eee2011-05-26 01:26:41 +0100152
153// Implementation of RuntimeProfiler inline functions.
154
155void RuntimeProfiler::IsolateEnteredJS(Isolate* isolate) {
156 Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, 1);
157 if (new_state == 0) {
158 // Just incremented from -1 to 0. -1 can only be set by the
159 // profiler thread before it suspends itself and starts waiting on
160 // the semaphore.
161 HandleWakeUp(isolate);
162 }
163 ASSERT(new_state >= 0);
164}
165
166
167void RuntimeProfiler::IsolateExitedJS(Isolate* isolate) {
168 Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, -1);
169 ASSERT(new_state >= 0);
170 USE(new_state);
171}
172
Ben Murdochb0fe1622011-05-05 13:52:32 +0100173} } // namespace v8::internal
174
175#endif // V8_RUNTIME_PROFILER_H_