blob: 15c209713e93b42aa34ed24539865092afbe66d4 [file] [log] [blame]
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001// 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
kasperl@chromium.orga5551262010-12-07 12:49:48 +000031#include "allocation.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000032#include "atomicops.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000033
34namespace v8 {
35namespace internal {
36
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000037class Isolate;
38class JSFunction;
39class Object;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000040class Semaphore;
41
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000042class RuntimeProfiler {
kasperl@chromium.orga5551262010-12-07 12:49:48 +000043 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000044 explicit RuntimeProfiler(Isolate* isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000045
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000046 static void GlobalSetup();
47
48 static inline bool IsEnabled() {
49 ASSERT(has_been_globally_setup_);
50 return enabled_;
51 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000052
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000053 void OptimizeNow();
kasperl@chromium.orga5551262010-12-07 12:49:48 +000054
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000055 void NotifyTick();
kasperl@chromium.orga5551262010-12-07 12:49:48 +000056
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000057 void Setup();
58 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
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +000087 // Stops the runtime profiler thread when profiling support is being
88 // turned off.
89 static void StopRuntimeProfilerThreadBeforeShutdown(Thread* thread);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000090
91 void UpdateSamplesAfterScavenge();
92 void RemoveDeadSamples();
93 void UpdateSamplesAfterCompact(ObjectVisitor* visitor);
94
95 private:
96 static const int kSamplerWindowSize = 16;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000097
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000098 static void HandleWakeUp(Isolate* isolate);
99
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000100 void Optimize(JSFunction* function);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000101
102 void AttemptOnStackReplacement(JSFunction* function);
103
104 void ClearSampleBuffer();
105
106 void ClearSampleBufferNewSpaceEntries();
107
108 int LookupSample(JSFunction* function);
109
110 void AddSample(JSFunction* function, int weight);
111
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000112 Isolate* isolate_;
113
114 int sampler_threshold_;
115 int sampler_threshold_size_factor_;
116 int sampler_ticks_until_threshold_adjustment_;
117
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000118 Object* sampler_window_[kSamplerWindowSize];
119 int sampler_window_position_;
120 int sampler_window_weight_[kSamplerWindowSize];
121
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000122 // 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_;
126 static Semaphore* semaphore_;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000127
128#ifdef DEBUG
129 static bool has_been_globally_setup_;
130#endif
131 static bool enabled_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000132};
133
134
135// Rate limiter intended to be used in the profiler thread.
136class RuntimeProfilerRateLimiter BASE_EMBEDDED {
137 public:
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000138 RuntimeProfilerRateLimiter() {}
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000139
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000140 // 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.)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000144 //
145 // Does nothing when runtime profiling is not enabled.
146 bool SuspendIfNecessary();
147
148 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000149 DISALLOW_COPY_AND_ASSIGN(RuntimeProfilerRateLimiter);
150};
151
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000152
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
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000173} } // namespace v8::internal
174
175#endif // V8_RUNTIME_PROFILER_H_