michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef MOZ_PROFILE_ENTRY_H michael@0: #define MOZ_PROFILE_ENTRY_H michael@0: michael@0: #include michael@0: #include "GeckoProfiler.h" michael@0: #include "platform.h" michael@0: #include "JSStreamWriter.h" michael@0: #include "ProfilerBacktrace.h" michael@0: #include "mozilla/Mutex.h" michael@0: michael@0: class ThreadProfile; michael@0: michael@0: #pragma pack(push, 1) michael@0: michael@0: class ProfileEntry michael@0: { michael@0: public: michael@0: ProfileEntry(); michael@0: michael@0: // aTagData must not need release (i.e. be a string from the text segment) michael@0: ProfileEntry(char aTagName, const char *aTagData); michael@0: ProfileEntry(char aTagName, void *aTagPtr); michael@0: ProfileEntry(char aTagName, ProfilerMarker *aTagMarker); michael@0: ProfileEntry(char aTagName, float aTagFloat); michael@0: ProfileEntry(char aTagName, uintptr_t aTagOffset); michael@0: ProfileEntry(char aTagName, Address aTagAddress); michael@0: ProfileEntry(char aTagName, int aTagLine); michael@0: ProfileEntry(char aTagName, char aTagChar); michael@0: friend std::ostream& operator<<(std::ostream& stream, const ProfileEntry& entry); michael@0: bool is_ent_hint(char hintChar); michael@0: bool is_ent_hint(); michael@0: bool is_ent(char tagName); michael@0: void* get_tagPtr(); michael@0: void log(); michael@0: const ProfilerMarker* getMarker() { michael@0: MOZ_ASSERT(mTagName == 'm'); michael@0: return mTagMarker; michael@0: } michael@0: michael@0: char getTagName() const { return mTagName; } michael@0: michael@0: private: michael@0: friend class ThreadProfile; michael@0: union { michael@0: const char* mTagData; michael@0: char mTagChars[sizeof(void*)]; michael@0: void* mTagPtr; michael@0: ProfilerMarker* mTagMarker; michael@0: float mTagFloat; michael@0: Address mTagAddress; michael@0: uintptr_t mTagOffset; michael@0: int mTagLine; michael@0: char mTagChar; michael@0: }; michael@0: char mTagName; michael@0: }; michael@0: michael@0: #pragma pack(pop) michael@0: michael@0: typedef void (*IterateTagsCallback)(const ProfileEntry& entry, const char* tagStringData); michael@0: michael@0: class ThreadProfile michael@0: { michael@0: public: michael@0: ThreadProfile(const char* aName, int aEntrySize, PseudoStack *aStack, michael@0: Thread::tid_t aThreadId, PlatformData* aPlatformData, michael@0: bool aIsMainThread, void *aStackTop); michael@0: virtual ~ThreadProfile(); michael@0: void addTag(ProfileEntry aTag); michael@0: void flush(); michael@0: void erase(); michael@0: char* processDynamicTag(int readPos, int* tagsConsumed, char* tagBuff); michael@0: void IterateTags(IterateTagsCallback aCallback); michael@0: friend std::ostream& operator<<(std::ostream& stream, michael@0: const ThreadProfile& profile); michael@0: void ToStreamAsJSON(std::ostream& stream); michael@0: JSObject *ToJSObject(JSContext *aCx); michael@0: PseudoStack* GetPseudoStack(); michael@0: mozilla::Mutex* GetMutex(); michael@0: void StreamJSObject(JSStreamWriter& b); michael@0: void BeginUnwind(); michael@0: virtual void EndUnwind(); michael@0: virtual SyncProfile* AsSyncProfile() { return nullptr; } michael@0: michael@0: bool IsMainThread() const { return mIsMainThread; } michael@0: const char* Name() const { return mName; } michael@0: Thread::tid_t ThreadId() const { return mThreadId; } michael@0: michael@0: PlatformData* GetPlatformData() { return mPlatformData; } michael@0: int GetGenerationID() const { return mGeneration; } michael@0: bool HasGenerationExpired(int aGenID) { michael@0: return aGenID + 2 <= mGeneration; michael@0: } michael@0: void* GetStackTop() const { return mStackTop; } michael@0: void DuplicateLastSample(); michael@0: private: michael@0: // Circular buffer 'Keep One Slot Open' implementation michael@0: // for simplicity michael@0: ProfileEntry* mEntries; michael@0: int mWritePos; // points to the next entry we will write to michael@0: int mLastFlushPos; // points to the next entry since the last flush() michael@0: int mReadPos; // points to the next entry we will read to michael@0: int mEntrySize; michael@0: PseudoStack* mPseudoStack; michael@0: mozilla::Mutex mMutex; michael@0: char* mName; michael@0: Thread::tid_t mThreadId; michael@0: bool mIsMainThread; michael@0: PlatformData* mPlatformData; // Platform specific data. michael@0: int mGeneration; michael@0: int mPendingGenerationFlush; michael@0: void* const mStackTop; michael@0: }; michael@0: michael@0: std::ostream& operator<<(std::ostream& stream, const ThreadProfile& profile); michael@0: michael@0: #endif /* ndef MOZ_PROFILE_ENTRY_H */