| Index: src/runtime-profiler.h
|
| ===================================================================
|
| --- src/runtime-profiler.h (revision 7563)
|
| +++ src/runtime-profiler.h (working copy)
|
| @@ -28,29 +28,122 @@
|
| #ifndef V8_RUNTIME_PROFILER_H_
|
| #define V8_RUNTIME_PROFILER_H_
|
|
|
| -#include "v8.h"
|
| #include "allocation.h"
|
| +#include "atomicops.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -class RuntimeProfiler : public AllStatic {
|
| +class Isolate;
|
| +class JSFunction;
|
| +class Object;
|
| +class PendingListNode;
|
| +class Semaphore;
|
| +
|
| +
|
| +enum SamplerState {
|
| + IN_NON_JS_STATE = 0,
|
| + IN_JS_STATE = 1
|
| +};
|
| +
|
| +
|
| +class RuntimeProfiler {
|
| public:
|
| - static bool IsEnabled() { return V8::UseCrankshaft() && FLAG_opt; }
|
| + explicit RuntimeProfiler(Isolate* isolate);
|
|
|
| - static void OptimizeNow();
|
| - static void OptimizeSoon(JSFunction* function);
|
| + static bool IsEnabled();
|
|
|
| - static void NotifyTick();
|
| + void OptimizeNow();
|
| + void OptimizeSoon(JSFunction* function);
|
|
|
| - static void Setup();
|
| - static void Reset();
|
| - static void TearDown();
|
| + void NotifyTick();
|
|
|
| - static int SamplerWindowSize();
|
| - static void UpdateSamplesAfterScavenge();
|
| - static void RemoveDeadSamples();
|
| - static void UpdateSamplesAfterCompact(ObjectVisitor* visitor);
|
| + void Setup();
|
| + void Reset();
|
| + void TearDown();
|
| +
|
| + Object** SamplerWindowAddress();
|
| + int SamplerWindowSize();
|
| +
|
| + // Rate limiting support.
|
| +
|
| + // VM thread interface.
|
| + //
|
| + // Called by isolates when their states change.
|
| + static inline void IsolateEnteredJS(Isolate* isolate);
|
| + static inline void IsolateExitedJS(Isolate* isolate);
|
| +
|
| + // Profiler thread interface.
|
| + //
|
| + // IsSomeIsolateInJS():
|
| + // The profiler thread can query whether some isolate is currently
|
| + // running JavaScript code.
|
| + //
|
| + // WaitForSomeIsolateToEnterJS():
|
| + // When no isolates are running JavaScript code for some time the
|
| + // profiler thread suspends itself by calling the wait function. The
|
| + // wait function returns true after it waited or false immediately.
|
| + // While the function was waiting the profiler may have been
|
| + // disabled so it *must check* whether it is allowed to continue.
|
| + static bool IsSomeIsolateInJS();
|
| + static bool WaitForSomeIsolateToEnterJS();
|
| +
|
| + // When shutting down we join the profiler thread. Doing so while
|
| + // it's waiting on a semaphore will cause a deadlock, so we have to
|
| + // wake it up first.
|
| + static void WakeUpRuntimeProfilerThreadBeforeShutdown();
|
| +
|
| + void UpdateSamplesAfterScavenge();
|
| + void RemoveDeadSamples();
|
| + void UpdateSamplesAfterCompact(ObjectVisitor* visitor);
|
| +
|
| + private:
|
| + static const int kSamplerWindowSize = 16;
|
| + static const int kStateWindowSize = 128;
|
| +
|
| + static void HandleWakeUp(Isolate* isolate);
|
| +
|
| + void Optimize(JSFunction* function, bool eager, int delay);
|
| +
|
| + void AttemptOnStackReplacement(JSFunction* function);
|
| +
|
| + void ClearSampleBuffer();
|
| +
|
| + void ClearSampleBufferNewSpaceEntries();
|
| +
|
| + int LookupSample(JSFunction* function);
|
| +
|
| + void AddSample(JSFunction* function, int weight);
|
| +
|
| +#ifdef ENABLE_LOGGING_AND_PROFILING
|
| + void UpdateStateRatio(SamplerState current_state);
|
| +#endif
|
| +
|
| + Isolate* isolate_;
|
| +
|
| + int sampler_threshold_;
|
| + int sampler_threshold_size_factor_;
|
| + int sampler_ticks_until_threshold_adjustment_;
|
| +
|
| + // The ratio of ticks spent in JS code in percent.
|
| + Atomic32 js_ratio_;
|
| +
|
| + Object* sampler_window_[kSamplerWindowSize];
|
| + int sampler_window_position_;
|
| + int sampler_window_weight_[kSamplerWindowSize];
|
| +
|
| + // Support for pending 'optimize soon' requests.
|
| + PendingListNode* optimize_soon_list_;
|
| +
|
| + SamplerState state_window_[kStateWindowSize];
|
| + int state_window_position_;
|
| + int state_counts_[2];
|
| +
|
| + // Possible state values:
|
| + // -1 => the profiler thread is waiting on the semaphore
|
| + // 0 or positive => the number of isolates running JavaScript code.
|
| + static Atomic32 state_;
|
| + static Semaphore* semaphore_;
|
| };
|
|
|
|
|
| @@ -59,9 +152,10 @@
|
| public:
|
| RuntimeProfilerRateLimiter() : non_js_ticks_(0) { }
|
|
|
| - // Suspends the current thread when not executing JavaScript to
|
| - // minimize CPU usage. Returns whether this thread was suspended
|
| - // (and so might have to check whether profiling is still active.)
|
| + // Suspends the current thread (which must be the profiler thread)
|
| + // when not executing JavaScript to minimize CPU usage. Returns
|
| + // whether the thread was suspended (and so must check whether
|
| + // profiling is still active.)
|
| //
|
| // Does nothing when runtime profiling is not enabled.
|
| bool SuspendIfNecessary();
|
| @@ -72,6 +166,27 @@
|
| DISALLOW_COPY_AND_ASSIGN(RuntimeProfilerRateLimiter);
|
| };
|
|
|
| +
|
| +// Implementation of RuntimeProfiler inline functions.
|
| +
|
| +void RuntimeProfiler::IsolateEnteredJS(Isolate* isolate) {
|
| + Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, 1);
|
| + if (new_state == 0) {
|
| + // Just incremented from -1 to 0. -1 can only be set by the
|
| + // profiler thread before it suspends itself and starts waiting on
|
| + // the semaphore.
|
| + HandleWakeUp(isolate);
|
| + }
|
| + ASSERT(new_state >= 0);
|
| +}
|
| +
|
| +
|
| +void RuntimeProfiler::IsolateExitedJS(Isolate* isolate) {
|
| + Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, -1);
|
| + ASSERT(new_state >= 0);
|
| + USE(new_state);
|
| +}
|
| +
|
| } } // namespace v8::internal
|
|
|
| #endif // V8_RUNTIME_PROFILER_H_
|
|
|