// Copyright (c) 2006-2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifdef ANDROID #include #else #define __android_log_print(a, ...) #endif #include "mozilla/StdInt.h" #include "mozilla/Util.h" #include "mozilla/unused.h" #include "mozilla/TimeStamp.h" #include "v8-support.h" #include #define ASSERT(a) MOZ_ASSERT(a) #ifdef ANDROID #ifdef defined(__arm__) || defined(__thumb__) #define ENABLE_SPS_LEAF_DATA #endif #define LOG(text) __android_log_print(ANDROID_LOG_ERROR, "profiler", "%s", text); #else #define LOG(text) printf("Profiler: %s\n", text) #endif typedef uint8_t* Address; // ---------------------------------------------------------------------------- // Mutex // // Mutexes are used for serializing access to non-reentrant sections of code. // The implementations of mutex should allow for nested/recursive locking. class Mutex { public: virtual ~Mutex() {} // Locks the given mutex. If the mutex is currently unlocked, it becomes // locked and owned by the calling thread, and immediately. If the mutex // is already locked by another thread, suspends the calling thread until // the mutex is unlocked. virtual int Lock() = 0; // Unlocks the given mutex. The mutex is assumed to be locked and owned by // the calling thread on entrance. virtual int Unlock() = 0; // Tries to lock the given mutex. Returns whether the mutex was // successfully locked. virtual bool TryLock() = 0; }; // ---------------------------------------------------------------------------- // ScopedLock // // Stack-allocated ScopedLocks provide block-scoped locking and // unlocking of a mutex. class ScopedLock { public: explicit ScopedLock(Mutex* mutex): mutex_(mutex) { ASSERT(mutex_ != NULL); mutex_->Lock(); } ~ScopedLock() { mutex_->Unlock(); } private: Mutex* mutex_; DISALLOW_COPY_AND_ASSIGN(ScopedLock); }; // ---------------------------------------------------------------------------- // OS // // This class has static methods for the different platform specific // functions. Add methods here to cope with differences between the // supported platforms. class OS { public: // Sleep for a number of milliseconds. static void Sleep(const int milliseconds); // Factory method for creating platform dependent Mutex. // Please use delete to reclaim the storage for the returned Mutex. static Mutex* CreateMutex(); private: static const int msPerSecond = 1000; }; // ---------------------------------------------------------------------------- // Thread // // Thread objects are used for creating and running threads. When the start() // method is called the new thread starts running the run() method in the new // thread. The Thread object should not be deallocated before the thread has // terminated. class Thread { public: // Create new thread. explicit Thread(const char* name); virtual ~Thread(); // Start new thread by calling the Run() method in the new thread. void Start(); void Join(); inline const char* name() const { return name_; } // Abstract method for run handler. virtual void Run() = 0; // The thread name length is limited to 16 based on Linux's implementation of // prctl(). static const int kMaxThreadNameLength = 16; class PlatformData; PlatformData* data() { return data_; } private: void set_name(const char *name); PlatformData* data_; char name_[kMaxThreadNameLength]; int stack_size_; DISALLOW_COPY_AND_ASSIGN(Thread); }; // ---------------------------------------------------------------------------- // Sampler // // A sampler periodically samples the state of the VM and optionally // (if used for profiling) the program counter and stack pointer for // the thread that created it. // TickSample captures the information collected for each sample. class TickSample { public: TickSample() : pc(NULL), sp(NULL), fp(NULL), function(NULL), frames_count(0) {} Address pc; // Instruction pointer. Address sp; // Stack pointer. Address fp; // Frame pointer. Address function; // The last called JS function. static const int kMaxFramesCount = 64; Address stack[kMaxFramesCount]; // Call stack. int frames_count; // Number of captured frames. mozilla::TimeStamp timestamp; }; class Sampler { public: // Initialize sampler. explicit Sampler(int interval, bool profiling); virtual ~Sampler(); int interval() const { return interval_; } // Performs stack sampling. virtual void SampleStack(TickSample* sample) = 0; // This method is called for each sampling period with the current // program counter. virtual void Tick(TickSample* sample) = 0; // Request a save from a signal handler virtual void RequestSave() = 0; // Process any outstanding request outside a signal handler. virtual void HandleSaveRequest() = 0; // Start and stop sampler. void Start(); void Stop(); // Is the sampler used for profiling? bool IsProfiling() const { return profiling_; } // Whether the sampler is running (that is, consumes resources). bool IsActive() const { return active_; } class PlatformData; PlatformData* platform_data() { return data_; } #ifdef XP_WIN // xxxehsan sucky hack :( static uintptr_t GetThreadHandle(PlatformData*); #endif private: void SetActive(bool value) { NoBarrier_Store(&active_, value); } const int interval_; const bool profiling_; Atomic32 active_; PlatformData* data_; // Platform specific data. };