ProfilerHelpers.cpp (7998B)
1 /* -*- Mode: C++; tab-width: 8; 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 "ProfilerHelpers.h" 8 9 #include "BackgroundChildImpl.h" 10 #include "GeckoProfiler.h" 11 #include "IDBDatabase.h" 12 #include "IDBIndex.h" 13 #include "IDBKeyRange.h" 14 #include "IDBObjectStore.h" 15 #include "IDBTransaction.h" 16 #include "Key.h" 17 #include "ThreadLocal.h" 18 #include "mozilla/dom/Event.h" 19 #include "nsReadableUtils.h" 20 21 namespace mozilla::dom::indexedDB { 22 23 namespace { 24 static const char kQuote = '\"'; 25 static const char kOpenBracket = '['; 26 static const char kCloseBracket = ']'; 27 static const char kOpenParen = '('; 28 static const char kCloseParen = ')'; 29 30 void LoggingHelper(bool aUseProfiler, const char* aFmt, va_list args) { 31 MOZ_ASSERT(IndexedDatabaseManager::GetLoggingMode() != 32 IndexedDatabaseManager::Logging_Disabled); 33 MOZ_ASSERT(aFmt); 34 35 mozilla::LogModule* logModule = IndexedDatabaseManager::GetLoggingModule(); 36 MOZ_ASSERT(logModule); 37 38 static const mozilla::LogLevel logLevel = LogLevel::Warning; 39 40 if (MOZ_LOG_TEST(logModule, logLevel) || 41 (aUseProfiler && profiler_thread_is_being_profiled_for_markers())) { 42 nsAutoCString message; 43 44 message.AppendVprintf(aFmt, args); 45 46 MOZ_LOG(logModule, logLevel, ("%s", message.get())); 47 48 if (aUseProfiler) { 49 PROFILER_MARKER_UNTYPED(message, DOM); 50 } 51 } 52 } 53 } // namespace 54 55 template <bool CheckLoggingMode> 56 LoggingIdString<CheckLoggingMode>::LoggingIdString() { 57 using mozilla::ipc::BackgroundChildImpl; 58 59 if (!CheckLoggingMode || IndexedDatabaseManager::GetLoggingMode() != 60 IndexedDatabaseManager::Logging_Disabled) { 61 const BackgroundChildImpl::ThreadLocal* threadLocal = 62 BackgroundChildImpl::GetThreadLocalForCurrentThread(); 63 if (threadLocal) { 64 const auto& idbThreadLocal = threadLocal->mIndexedDBThreadLocal; 65 if (idbThreadLocal) { 66 Assign(idbThreadLocal->IdString()); 67 } 68 } 69 } 70 } 71 72 template <bool CheckLoggingMode> 73 LoggingIdString<CheckLoggingMode>::LoggingIdString(const nsID& aID) { 74 static_assert(NSID_LENGTH > 1, "NSID_LENGTH is set incorrectly!"); 75 static_assert(NSID_LENGTH <= kStorageSize, 76 "nsID string won't fit in our storage!"); 77 // Capacity() excludes the null terminator; NSID_LENGTH includes it. 78 MOZ_ASSERT(Capacity() + 1 == NSID_LENGTH); 79 80 if (!CheckLoggingMode || IndexedDatabaseManager::GetLoggingMode() != 81 IndexedDatabaseManager::Logging_Disabled) { 82 // NSID_LENGTH counts the null terminator, SetLength() does not. 83 SetLength(NSID_LENGTH - 1); 84 85 aID.ToProvidedString( 86 *reinterpret_cast<char(*)[NSID_LENGTH]>(BeginWriting())); 87 } 88 } 89 90 template class LoggingIdString<false>; 91 template class LoggingIdString<true>; 92 93 LoggingString::LoggingString(IDBDatabase* aDatabase) : nsAutoCString(kQuote) { 94 MOZ_ASSERT(aDatabase); 95 96 AppendUTF16toUTF8(aDatabase->Name(), *this); 97 Append(kQuote); 98 } 99 100 LoggingString::LoggingString(const IDBTransaction& aTransaction) 101 : nsAutoCString(kOpenBracket) { 102 constexpr auto kCommaSpace = ", "_ns; 103 104 StringJoinAppend(*this, kCommaSpace, aTransaction.ObjectStoreNamesInternal(), 105 [](nsACString& dest, const auto& store) { 106 dest.Append(kQuote); 107 AppendUTF16toUTF8(store, dest); 108 dest.Append(kQuote); 109 }); 110 111 Append(kCloseBracket); 112 Append(kCommaSpace); 113 114 switch (aTransaction.GetMode()) { 115 case IDBTransaction::Mode::ReadOnly: 116 AppendLiteral("\"readonly\""); 117 break; 118 case IDBTransaction::Mode::ReadWrite: 119 AppendLiteral("\"readwrite\""); 120 break; 121 case IDBTransaction::Mode::ReadWriteFlush: 122 AppendLiteral("\"readwriteflush\""); 123 break; 124 case IDBTransaction::Mode::Cleanup: 125 AppendLiteral("\"cleanup\""); 126 break; 127 case IDBTransaction::Mode::VersionChange: 128 AppendLiteral("\"versionchange\""); 129 break; 130 default: 131 MOZ_CRASH("Unknown mode!"); 132 }; 133 } 134 135 LoggingString::LoggingString(IDBObjectStore* aObjectStore) 136 : nsAutoCString(kQuote) { 137 MOZ_ASSERT(aObjectStore); 138 139 AppendUTF16toUTF8(aObjectStore->Name(), *this); 140 Append(kQuote); 141 } 142 143 LoggingString::LoggingString(IDBIndex* aIndex) : nsAutoCString(kQuote) { 144 MOZ_ASSERT(aIndex); 145 146 AppendUTF16toUTF8(aIndex->Name(), *this); 147 Append(kQuote); 148 } 149 150 LoggingString::LoggingString(IDBKeyRange* aKeyRange) { 151 if (aKeyRange) { 152 if (aKeyRange->IsOnly()) { 153 Assign(LoggingString(aKeyRange->Lower())); 154 } else { 155 if (aKeyRange->LowerOpen()) { 156 Assign(kOpenParen); 157 } else { 158 Assign(kOpenBracket); 159 } 160 161 Append(LoggingString(aKeyRange->Lower())); 162 AppendLiteral(", "); 163 Append(LoggingString(aKeyRange->Upper())); 164 165 if (aKeyRange->UpperOpen()) { 166 Append(kCloseParen); 167 } else { 168 Append(kCloseBracket); 169 } 170 } 171 } else { 172 AssignLiteral("<undefined>"); 173 } 174 } 175 176 LoggingString::LoggingString(const Key& aKey) { 177 if (aKey.IsUnset()) { 178 AssignLiteral("<undefined>"); 179 } else if (aKey.IsFloat()) { 180 AppendPrintf("%g", aKey.ToFloat()); 181 } else if (aKey.IsDate()) { 182 AppendPrintf("<Date %g>", aKey.ToDateMsec()); 183 } else if (aKey.IsString()) { 184 AppendPrintf("\"%s\"", NS_ConvertUTF16toUTF8(aKey.ToString()).get()); 185 } else if (aKey.IsBinary()) { 186 AssignLiteral("[object ArrayBuffer]"); 187 } else { 188 MOZ_ASSERT(aKey.IsArray()); 189 AssignLiteral("[...]"); 190 } 191 } 192 193 LoggingString::LoggingString(const IDBCursorDirection aDirection) { 194 switch (aDirection) { 195 case IDBCursorDirection::Next: 196 AssignLiteral("\"next\""); 197 break; 198 case IDBCursorDirection::Nextunique: 199 AssignLiteral("\"nextunique\""); 200 break; 201 case IDBCursorDirection::Prev: 202 AssignLiteral("\"prev\""); 203 break; 204 case IDBCursorDirection::Prevunique: 205 AssignLiteral("\"prevunique\""); 206 break; 207 default: 208 MOZ_CRASH("Unknown direction!"); 209 }; 210 } 211 212 LoggingString::LoggingString(const Optional<uint64_t>& aVersion) { 213 if (aVersion.WasPassed()) { 214 AppendInt(aVersion.Value()); 215 } else { 216 AssignLiteral("<undefined>"); 217 } 218 } 219 220 LoggingString::LoggingString(const Optional<uint32_t>& aLimit) { 221 if (aLimit.WasPassed()) { 222 AppendInt(aLimit.Value()); 223 } else { 224 AssignLiteral("<undefined>"); 225 } 226 } 227 228 LoggingString::LoggingString(IDBObjectStore* aObjectStore, const Key& aKey) { 229 MOZ_ASSERT(aObjectStore); 230 231 if (!aObjectStore->HasValidKeyPath()) { 232 Append(LoggingString(aKey)); 233 } 234 } 235 236 LoggingString::LoggingString(Event* aEvent, const char16_t* aDefault) 237 : nsAutoCString(kQuote) { 238 MOZ_ASSERT(aDefault); 239 240 nsAutoString eventType; 241 242 if (aEvent) { 243 aEvent->GetType(eventType); 244 } else { 245 eventType = nsDependentString(aDefault); 246 } 247 248 AppendUTF16toUTF8(eventType, *this); 249 Append(kQuote); 250 } 251 252 void LoggingHelper(const char* aDetailedFmt, const char* aConciseFmt, ...) { 253 const IndexedDatabaseManager::LoggingMode mode = 254 IndexedDatabaseManager::GetLoggingMode(); 255 256 if (mode != IndexedDatabaseManager::Logging_Disabled) { 257 const char* fmt; 258 if (mode == IndexedDatabaseManager::Logging_Concise || 259 mode == IndexedDatabaseManager::Logging_ConciseProfilerMarks) { 260 fmt = aConciseFmt; 261 } else { 262 MOZ_ASSERT(mode == IndexedDatabaseManager::Logging_Detailed || 263 mode == IndexedDatabaseManager::Logging_DetailedProfilerMarks); 264 fmt = aDetailedFmt; 265 } 266 267 const bool useProfiler = 268 mode == IndexedDatabaseManager::Logging_ConciseProfilerMarks || 269 mode == IndexedDatabaseManager::Logging_DetailedProfilerMarks; 270 271 va_list args; 272 va_start(args, aConciseFmt); 273 274 LoggingHelper(useProfiler, fmt, args); 275 276 va_end(args); 277 } 278 } 279 280 } // namespace mozilla::dom::indexedDB