1 : // Copyright (c) 2006-2011 The Chromium Authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifdef ANDROID
6 : #include <android/log.h>
7 : #else
8 : #define __android_log_print(a, ...)
9 : #endif
10 :
11 : #include "mozilla/StandardInteger.h"
12 : #include "mozilla/Util.h"
13 : #include "mozilla/unused.h"
14 : #include "mozilla/TimeStamp.h"
15 : #include "v8-support.h"
16 : #include <vector>
17 : #define ASSERT(a) MOZ_ASSERT(a)
18 : #ifdef ANDROID
19 : #ifdef defined(__arm__) || defined(__thumb__)
20 : #define ENABLE_SPS_LEAF_DATA
21 : #endif
22 : #define LOG(text) __android_log_print(ANDROID_LOG_ERROR, "profiler", "%s", text);
23 : #else
24 : #define LOG(text) printf("Profiler: %s\n", text)
25 : #endif
26 :
27 : typedef uint8_t* Address;
28 :
29 : // ----------------------------------------------------------------------------
30 : // Mutex
31 : //
32 : // Mutexes are used for serializing access to non-reentrant sections of code.
33 : // The implementations of mutex should allow for nested/recursive locking.
34 :
35 : class Mutex {
36 : public:
37 : virtual ~Mutex() {}
38 :
39 : // Locks the given mutex. If the mutex is currently unlocked, it becomes
40 : // locked and owned by the calling thread, and immediately. If the mutex
41 : // is already locked by another thread, suspends the calling thread until
42 : // the mutex is unlocked.
43 : virtual int Lock() = 0;
44 :
45 : // Unlocks the given mutex. The mutex is assumed to be locked and owned by
46 : // the calling thread on entrance.
47 : virtual int Unlock() = 0;
48 :
49 : // Tries to lock the given mutex. Returns whether the mutex was
50 : // successfully locked.
51 : virtual bool TryLock() = 0;
52 : };
53 :
54 : // ----------------------------------------------------------------------------
55 : // ScopedLock
56 : //
57 : // Stack-allocated ScopedLocks provide block-scoped locking and
58 : // unlocking of a mutex.
59 : class ScopedLock {
60 : public:
61 : explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
62 : ASSERT(mutex_ != NULL);
63 : mutex_->Lock();
64 : }
65 : ~ScopedLock() {
66 : mutex_->Unlock();
67 : }
68 :
69 : private:
70 : Mutex* mutex_;
71 : DISALLOW_COPY_AND_ASSIGN(ScopedLock);
72 : };
73 :
74 :
75 :
76 : // ----------------------------------------------------------------------------
77 : // OS
78 : //
79 : // This class has static methods for the different platform specific
80 : // functions. Add methods here to cope with differences between the
81 : // supported platforms.
82 :
83 : class OS {
84 : public:
85 :
86 : // Sleep for a number of milliseconds.
87 : static void Sleep(const int milliseconds);
88 :
89 : // Factory method for creating platform dependent Mutex.
90 : // Please use delete to reclaim the storage for the returned Mutex.
91 : static Mutex* CreateMutex();
92 :
93 : private:
94 : static const int msPerSecond = 1000;
95 :
96 : };
97 :
98 :
99 :
100 :
101 : // ----------------------------------------------------------------------------
102 : // Thread
103 : //
104 : // Thread objects are used for creating and running threads. When the start()
105 : // method is called the new thread starts running the run() method in the new
106 : // thread. The Thread object should not be deallocated before the thread has
107 : // terminated.
108 :
109 : class Thread {
110 : public:
111 : // Create new thread.
112 : explicit Thread(const char* name);
113 : virtual ~Thread();
114 :
115 : // Start new thread by calling the Run() method in the new thread.
116 : void Start();
117 :
118 : void Join();
119 :
120 : inline const char* name() const {
121 : return name_;
122 : }
123 :
124 : // Abstract method for run handler.
125 : virtual void Run() = 0;
126 :
127 : // The thread name length is limited to 16 based on Linux's implementation of
128 : // prctl().
129 : static const int kMaxThreadNameLength = 16;
130 :
131 : class PlatformData;
132 : PlatformData* data() { return data_; }
133 :
134 : private:
135 : void set_name(const char *name);
136 :
137 : PlatformData* data_;
138 :
139 : char name_[kMaxThreadNameLength];
140 : int stack_size_;
141 :
142 : DISALLOW_COPY_AND_ASSIGN(Thread);
143 : };
144 :
145 :
146 :
147 : // ----------------------------------------------------------------------------
148 : // Sampler
149 : //
150 : // A sampler periodically samples the state of the VM and optionally
151 : // (if used for profiling) the program counter and stack pointer for
152 : // the thread that created it.
153 :
154 : // TickSample captures the information collected for each sample.
155 : class TickSample {
156 : public:
157 0 : TickSample()
158 : :
159 : pc(NULL),
160 : sp(NULL),
161 : fp(NULL),
162 : function(NULL),
163 0 : frames_count(0) {}
164 : Address pc; // Instruction pointer.
165 : Address sp; // Stack pointer.
166 : Address fp; // Frame pointer.
167 : Address function; // The last called JS function.
168 : static const int kMaxFramesCount = 64;
169 : Address stack[kMaxFramesCount]; // Call stack.
170 : int frames_count; // Number of captured frames.
171 : mozilla::TimeStamp timestamp;
172 : };
173 :
174 : class Sampler {
175 : public:
176 : // Initialize sampler.
177 : explicit Sampler(int interval, bool profiling);
178 : virtual ~Sampler();
179 :
180 : int interval() const { return interval_; }
181 :
182 : // Performs stack sampling.
183 : virtual void SampleStack(TickSample* sample) = 0;
184 :
185 : // This method is called for each sampling period with the current
186 : // program counter.
187 : virtual void Tick(TickSample* sample) = 0;
188 :
189 : // Request a save from a signal handler
190 : virtual void RequestSave() = 0;
191 : // Process any outstanding request outside a signal handler.
192 : virtual void HandleSaveRequest() = 0;
193 :
194 : // Start and stop sampler.
195 : void Start();
196 : void Stop();
197 :
198 : // Is the sampler used for profiling?
199 : bool IsProfiling() const { return profiling_; }
200 :
201 : // Whether the sampler is running (that is, consumes resources).
202 0 : bool IsActive() const { return active_; }
203 :
204 : class PlatformData;
205 :
206 : PlatformData* platform_data() { return data_; }
207 :
208 : // If we move the backtracing code into the platform files we won't
209 : // need to have these hacks
210 : #ifdef XP_WIN
211 : // xxxehsan sucky hack :(
212 : static uintptr_t GetThreadHandle(PlatformData*);
213 : #endif
214 : #ifdef XP_MACOSX
215 : static pthread_t GetProfiledThread(PlatformData*);
216 : #endif
217 : private:
218 0 : void SetActive(bool value) { NoBarrier_Store(&active_, value); }
219 :
220 : const int interval_;
221 : const bool profiling_;
222 : Atomic32 active_;
223 : PlatformData* data_; // Platform specific data.
224 : };
225 :
|