Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "ProfileBuffer.h"
8 :
9 : #include "ProfilerMarker.h"
10 :
11 0 : ProfileBuffer::ProfileBuffer(int aEntrySize)
12 : : mEntries(mozilla::MakeUnique<ProfileBufferEntry[]>(aEntrySize))
13 : , mWritePos(0)
14 : , mReadPos(0)
15 : , mEntrySize(aEntrySize)
16 0 : , mGeneration(0)
17 : {
18 0 : }
19 :
20 0 : ProfileBuffer::~ProfileBuffer()
21 : {
22 0 : while (mStoredMarkers.peek()) {
23 0 : delete mStoredMarkers.popHead();
24 : }
25 0 : }
26 :
27 : // Called from signal, call only reentrant functions
28 : void
29 0 : ProfileBuffer::AddEntry(const ProfileBufferEntry& aEntry)
30 : {
31 0 : mEntries[mWritePos++] = aEntry;
32 0 : if (mWritePos == mEntrySize) {
33 : // Wrapping around may result in things referenced in the buffer (e.g.,
34 : // JIT code addresses and markers) being incorrectly collected.
35 0 : MOZ_ASSERT(mGeneration != UINT32_MAX);
36 0 : mGeneration++;
37 0 : mWritePos = 0;
38 : }
39 :
40 0 : if (mWritePos == mReadPos) {
41 : // Keep one slot open.
42 0 : mEntries[mReadPos] = ProfileBufferEntry();
43 0 : mReadPos = (mReadPos + 1) % mEntrySize;
44 : }
45 0 : }
46 :
47 : void
48 0 : ProfileBuffer::AddThreadIdEntry(int aThreadId, LastSample* aLS)
49 : {
50 0 : if (aLS) {
51 : // This is the start of a sample, so make a note of its location in |aLS|.
52 0 : aLS->mGeneration = mGeneration;
53 0 : aLS->mPos = mWritePos;
54 : }
55 0 : AddEntry(ProfileBufferEntry::ThreadId(aThreadId));
56 0 : }
57 :
58 : void
59 0 : ProfileBuffer::AddDynamicStringEntry(const char* aStr)
60 : {
61 0 : size_t strLen = strlen(aStr) + 1; // +1 for the null terminator
62 0 : for (size_t j = 0; j < strLen; ) {
63 : // Store up to kNumChars characters in the entry.
64 : char chars[ProfileBufferEntry::kNumChars];
65 0 : size_t len = ProfileBufferEntry::kNumChars;
66 0 : if (j + len >= strLen) {
67 0 : len = strLen - j;
68 : }
69 0 : memcpy(chars, &aStr[j], len);
70 0 : j += ProfileBufferEntry::kNumChars;
71 :
72 0 : AddEntry(ProfileBufferEntry::DynamicStringFragment(chars));
73 : }
74 0 : }
75 :
76 : void
77 0 : ProfileBuffer::AddStoredMarker(ProfilerMarker *aStoredMarker)
78 : {
79 0 : aStoredMarker->SetGeneration(mGeneration);
80 0 : mStoredMarkers.insert(aStoredMarker);
81 0 : }
82 :
83 : void
84 0 : ProfileBuffer::DeleteExpiredStoredMarkers()
85 : {
86 : // Delete markers of samples that have been overwritten due to circular
87 : // buffer wraparound.
88 0 : uint32_t generation = mGeneration;
89 0 : while (mStoredMarkers.peek() &&
90 0 : mStoredMarkers.peek()->HasExpired(generation)) {
91 0 : delete mStoredMarkers.popHead();
92 : }
93 0 : }
94 :
95 : void
96 0 : ProfileBuffer::Reset()
97 : {
98 0 : mGeneration += 2;
99 0 : mReadPos = mWritePos = 0;
100 0 : }
101 :
102 : size_t
103 0 : ProfileBuffer::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
104 : {
105 0 : size_t n = aMallocSizeOf(this);
106 0 : n += aMallocSizeOf(mEntries.get());
107 :
108 : // Measurement of the following members may be added later if DMD finds it
109 : // is worthwhile:
110 : // - memory pointed to by the elements within mEntries
111 : // - mStoredMarkers
112 :
113 0 : return n;
114 : }
115 :
|