LLDB mainline
Statistics.cpp
Go to the documentation of this file.
1//===-- Statistics.cpp ----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11#include "lldb/Core/Debugger.h"
12#include "lldb/Core/Module.h"
16#include "lldb/Target/Process.h"
17#include "lldb/Target/Target.h"
20
21using namespace lldb;
22using namespace lldb_private;
23using namespace llvm;
24
25static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
26 const std::string &str) {
27 if (str.empty())
28 return;
29 if (LLVM_LIKELY(llvm::json::isUTF8(str)))
30 obj.try_emplace(key, str);
31 else
32 obj.try_emplace(key, llvm::json::fixUTF8(str));
33}
34
35json::Value StatsSuccessFail::ToJSON() const {
36 return json::Object{{"successes", successes}, {"failures", failures}};
37}
38
39static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end) {
41 end.time_since_epoch() - start.time_since_epoch();
42 return elapsed.count();
43}
44
47 for (ModuleSP module_sp : target.GetImages().Modules())
48 m_module_identifiers.emplace_back((intptr_t)module_sp.get());
49}
50
51json::Value ModuleStats::ToJSON() const {
52 json::Object module;
53 EmplaceSafeString(module, "path", path);
54 EmplaceSafeString(module, "uuid", uuid);
55 EmplaceSafeString(module, "triple", triple);
56 module.try_emplace("identifier", identifier);
57 module.try_emplace("symbolTableParseTime", symtab_parse_time);
58 module.try_emplace("symbolTableIndexTime", symtab_index_time);
59 module.try_emplace("symbolTableLoadedFromCache", symtab_loaded_from_cache);
60 module.try_emplace("symbolTableSavedToCache", symtab_saved_to_cache);
61 module.try_emplace("debugInfoParseTime", debug_parse_time);
62 module.try_emplace("debugInfoIndexTime", debug_index_time);
63 module.try_emplace("debugInfoByteSize", (int64_t)debug_info_size);
64 module.try_emplace("debugInfoIndexLoadedFromCache",
66 module.try_emplace("debugInfoIndexSavedToCache",
68 module.try_emplace("debugInfoEnabled", debug_info_enabled);
69 module.try_emplace("debugInfoHadVariableErrors",
71 module.try_emplace("debugInfoHadIncompleteTypes",
73 module.try_emplace("symbolTableStripped", symtab_stripped);
74 if (!symfile_path.empty())
75 module.try_emplace("symbolFilePath", symfile_path);
76
77 if (!symfile_modules.empty()) {
78 json::Array symfile_ids;
79 for (const auto symfile_id: symfile_modules)
80 symfile_ids.emplace_back(symfile_id);
81 module.try_emplace("symbolFileModuleIdentifiers", std::move(symfile_ids));
82 }
83
84 if (!type_system_stats.empty()) {
85 json::Array type_systems;
86 for (const auto &entry : type_system_stats) {
87 json::Object obj;
88 obj.try_emplace(entry.first().str(), entry.second);
89 type_systems.emplace_back(std::move(obj));
90 }
91 module.try_emplace("typeSystemInfo", std::move(type_systems));
92 }
93
94 return module;
95}
96
97llvm::json::Value ConstStringStats::ToJSON() const {
98 json::Object obj;
99 obj.try_emplace<int64_t>("bytesTotal", stats.GetBytesTotal());
100 obj.try_emplace<int64_t>("bytesUsed", stats.GetBytesUsed());
101 obj.try_emplace<int64_t>("bytesUnused", stats.GetBytesUnused());
102 return obj;
103}
104
105json::Value
107 const lldb_private::StatisticsOptions &options) {
108 json::Object target_metrics_json;
109 ProcessSP process_sp = target.GetProcessSP();
110 const bool summary_only = options.GetSummaryOnly();
111 const bool include_modules = options.GetIncludeModules();
112 if (!summary_only) {
113 CollectStats(target);
114
115 json::Array json_module_uuid_array;
116 for (auto module_identifier : m_module_identifiers)
117 json_module_uuid_array.emplace_back(module_identifier);
118
119 target_metrics_json.try_emplace(m_expr_eval.name, m_expr_eval.ToJSON());
120 target_metrics_json.try_emplace(m_frame_var.name, m_frame_var.ToJSON());
121 if (include_modules)
122 target_metrics_json.try_emplace("moduleIdentifiers",
123 std::move(json_module_uuid_array));
124
126 double elapsed_time =
128 target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time);
129 }
131 double elapsed_time =
133 target_metrics_json.try_emplace("firstStopTime", elapsed_time);
134 }
135 target_metrics_json.try_emplace("targetCreateTime",
136 m_create_time.get().count());
137
138 json::Array breakpoints_array;
139 double totalBreakpointResolveTime = 0.0;
140 // Report both the normal breakpoint list and the internal breakpoint list.
141 for (int i = 0; i < 2; ++i) {
142 BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
143 std::unique_lock<std::recursive_mutex> lock;
144 breakpoints.GetListMutex(lock);
145 size_t num_breakpoints = breakpoints.GetSize();
146 for (size_t i = 0; i < num_breakpoints; i++) {
147 Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
148 breakpoints_array.push_back(bp->GetStatistics());
149 totalBreakpointResolveTime += bp->GetResolveTime().count();
150 }
151 }
152 target_metrics_json.try_emplace("breakpoints",
153 std::move(breakpoints_array));
154 target_metrics_json.try_emplace("totalBreakpointResolveTime",
155 totalBreakpointResolveTime);
156
157 if (process_sp) {
158 UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
159 if (unix_signals_sp)
160 target_metrics_json.try_emplace(
161 "signals", unix_signals_sp->GetHitCountStatistics());
162 }
163 }
164
165 // Counting "totalSharedLibraryEventHitCount" from breakpoints of kind
166 // "shared-library-event".
167 {
168 uint32_t shared_library_event_breakpoint_hit_count = 0;
169 // The "shared-library-event" is only found in the internal breakpoint list.
170 BreakpointList &breakpoints = target.GetBreakpointList(/* internal */ true);
171 std::unique_lock<std::recursive_mutex> lock;
172 breakpoints.GetListMutex(lock);
173 size_t num_breakpoints = breakpoints.GetSize();
174 for (size_t i = 0; i < num_breakpoints; i++) {
175 Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
176 if (strcmp(bp->GetBreakpointKind(), "shared-library-event") == 0)
177 shared_library_event_breakpoint_hit_count += bp->GetHitCount();
178 }
179
180 target_metrics_json.try_emplace("totalSharedLibraryEventHitCount",
181 shared_library_event_breakpoint_hit_count);
182 }
183
184 if (process_sp) {
185 uint32_t stop_id = process_sp->GetStopID();
186 target_metrics_json.try_emplace("stopCount", stop_id);
187
188 llvm::StringRef dyld_plugin_name;
189 if (process_sp->GetDynamicLoader())
190 dyld_plugin_name = process_sp->GetDynamicLoader()->GetPluginName();
191 target_metrics_json.try_emplace("dyldPluginName", dyld_plugin_name);
192 }
193 target_metrics_json.try_emplace("sourceMapDeduceCount",
195 target_metrics_json.try_emplace("sourceRealpathAttemptCount",
197 target_metrics_json.try_emplace("sourceRealpathCompatibleCount",
199 return target_metrics_json;
200}
201
203 m_launch_or_attach_time = StatsClock::now();
204 m_first_private_stop_time = std::nullopt;
205}
206
208 // Launching and attaching has many paths depending on if synchronous mode
209 // was used or if we are stopping at the entry point or not. Only set the
210 // first stop time if it hasn't already been set.
212 m_first_private_stop_time = StatsClock::now();
213}
214
216 // Launching and attaching has many paths depending on if synchronous mode
217 // was used or if we are stopping at the entry point or not. Only set the
218 // first stop time if it hasn't already been set.
220 m_first_public_stop_time = StatsClock::now();
221}
222
225}
226
229}
230
233}
234
236
238 Debugger &debugger, Target *target,
239 const lldb_private::StatisticsOptions &options) {
240
241 const bool summary_only = options.GetSummaryOnly();
242 const bool load_all_debug_info = options.GetLoadAllDebugInfo();
243 const bool include_targets = options.GetIncludeTargets();
244 const bool include_modules = options.GetIncludeModules();
245 const bool include_transcript = options.GetIncludeTranscript();
246
247 json::Array json_targets;
248 json::Array json_modules;
249 double symtab_parse_time = 0.0;
250 double symtab_index_time = 0.0;
251 double debug_parse_time = 0.0;
252 double debug_index_time = 0.0;
253 uint32_t symtabs_loaded = 0;
254 uint32_t symtabs_saved = 0;
255 uint32_t debug_index_loaded = 0;
256 uint32_t debug_index_saved = 0;
257 uint64_t debug_info_size = 0;
258
259 std::vector<ModuleStats> modules;
260 std::lock_guard<std::recursive_mutex> guard(
262 const uint64_t num_modules = Module::GetNumberAllocatedModules();
263 uint32_t num_debug_info_enabled_modules = 0;
264 uint32_t num_modules_has_debug_info = 0;
265 uint32_t num_modules_with_variable_errors = 0;
266 uint32_t num_modules_with_incomplete_types = 0;
267 uint32_t num_stripped_modules = 0;
268 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
269 Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
270 ModuleStats module_stat;
271 module_stat.symtab_parse_time = module->GetSymtabParseTime().get().count();
272 module_stat.symtab_index_time = module->GetSymtabIndexTime().get().count();
273 Symtab *symtab = module->GetSymtab();
274 if (symtab) {
275 module_stat.symtab_loaded_from_cache = symtab->GetWasLoadedFromCache();
276 if (module_stat.symtab_loaded_from_cache)
277 ++symtabs_loaded;
278 module_stat.symtab_saved_to_cache = symtab->GetWasSavedToCache();
279 if (module_stat.symtab_saved_to_cache)
280 ++symtabs_saved;
281 }
282 SymbolFile *sym_file = module->GetSymbolFile();
283 if (sym_file) {
284 if (!summary_only) {
285 if (sym_file->GetObjectFile() != module->GetObjectFile())
286 module_stat.symfile_path =
287 sym_file->GetObjectFile()->GetFileSpec().GetPath();
288 ModuleList symbol_modules = sym_file->GetDebugInfoModules();
289 for (const auto &symbol_module : symbol_modules.Modules())
290 module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
291 }
295 ++debug_index_loaded;
298 if (module_stat.debug_info_index_saved_to_cache)
299 ++debug_index_saved;
300 module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
301 module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
302 module_stat.debug_info_size =
303 sym_file->GetDebugInfoSize(load_all_debug_info);
304 module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
305 if (module_stat.symtab_stripped)
306 ++num_stripped_modules;
307 module_stat.debug_info_enabled = sym_file->GetLoadDebugInfoEnabled() &&
308 module_stat.debug_info_size > 0;
311 if (module_stat.debug_info_enabled)
312 ++num_debug_info_enabled_modules;
313 if (module_stat.debug_info_size > 0)
314 ++num_modules_has_debug_info;
315 if (module_stat.debug_info_had_variable_errors)
316 ++num_modules_with_variable_errors;
317 }
318 symtab_parse_time += module_stat.symtab_parse_time;
319 symtab_index_time += module_stat.symtab_index_time;
320 debug_parse_time += module_stat.debug_parse_time;
321 debug_index_time += module_stat.debug_index_time;
322 debug_info_size += module_stat.debug_info_size;
323 module->ForEachTypeSystem([&](lldb::TypeSystemSP ts) {
324 if (auto stats = ts->ReportStatistics())
325 module_stat.type_system_stats.insert({ts->GetPluginName(), *stats});
326 if (ts->GetHasForcefullyCompletedTypes())
327 module_stat.debug_info_had_incomplete_types = true;
328 return true;
329 });
330 if (module_stat.debug_info_had_incomplete_types)
331 ++num_modules_with_incomplete_types;
332
333 if (include_modules) {
334 module_stat.identifier = (intptr_t)module;
335 module_stat.path = module->GetFileSpec().GetPath();
336 if (ConstString object_name = module->GetObjectName()) {
337 module_stat.path.append(1, '(');
338 module_stat.path.append(object_name.GetStringRef().str());
339 module_stat.path.append(1, ')');
340 }
341 module_stat.uuid = module->GetUUID().GetAsString();
342 module_stat.triple = module->GetArchitecture().GetTriple().str();
343 json_modules.emplace_back(module_stat.ToJSON());
344 }
345 }
346
347 json::Object global_stats{
348 {"totalSymbolTableParseTime", symtab_parse_time},
349 {"totalSymbolTableIndexTime", symtab_index_time},
350 {"totalSymbolTablesLoadedFromCache", symtabs_loaded},
351 {"totalSymbolTablesSavedToCache", symtabs_saved},
352 {"totalDebugInfoParseTime", debug_parse_time},
353 {"totalDebugInfoIndexTime", debug_index_time},
354 {"totalDebugInfoIndexLoadedFromCache", debug_index_loaded},
355 {"totalDebugInfoIndexSavedToCache", debug_index_saved},
356 {"totalDebugInfoByteSize", debug_info_size},
357 {"totalModuleCount", num_modules},
358 {"totalModuleCountHasDebugInfo", num_modules_has_debug_info},
359 {"totalModuleCountWithVariableErrors", num_modules_with_variable_errors},
360 {"totalModuleCountWithIncompleteTypes",
361 num_modules_with_incomplete_types},
362 {"totalDebugInfoEnabled", num_debug_info_enabled_modules},
363 {"totalSymbolTableStripped", num_stripped_modules},
364 };
365
366 if (include_targets) {
367 if (target) {
368 json_targets.emplace_back(target->ReportStatistics(options));
369 } else {
370 for (const auto &target : debugger.GetTargetList().Targets())
371 json_targets.emplace_back(target->ReportStatistics(options));
372 }
373 global_stats.try_emplace("targets", std::move(json_targets));
374 }
375
376 ConstStringStats const_string_stats;
377 json::Object json_memory{
378 {"strings", const_string_stats.ToJSON()},
379 };
380 global_stats.try_emplace("memory", std::move(json_memory));
381 if (!summary_only) {
382 json::Value cmd_stats = debugger.GetCommandInterpreter().GetStatistics();
383 global_stats.try_emplace("commands", std::move(cmd_stats));
384 }
385
386 if (include_modules) {
387 global_stats.try_emplace("modules", std::move(json_modules));
388 }
389
390 if (include_transcript) {
391 // When transcript is available, add it to the to-be-returned statistics.
392 //
393 // NOTE:
394 // When the statistics is polled by an LLDB command:
395 // - The transcript in the returned statistics *will NOT* contain the
396 // returned statistics itself (otherwise infinite recursion).
397 // - The returned statistics *will* be written to the internal transcript
398 // buffer. It *will* appear in the next statistcs or transcript poll.
399 //
400 // For example, let's say the following commands are run in order:
401 // - "version"
402 // - "statistics dump" <- call it "A"
403 // - "statistics dump" <- call it "B"
404 // The output of "A" will contain the transcript of "version" and
405 // "statistics dump" (A), with the latter having empty output. The output
406 // of B will contain the trascnript of "version", "statistics dump" (A),
407 // "statistics dump" (B), with A's output populated and B's output empty.
408 const StructuredData::Array &transcript =
410 if (transcript.GetSize() != 0) {
411 std::string buffer;
412 llvm::raw_string_ostream ss(buffer);
413 json::OStream json_os(ss);
414 transcript.Serialize(json_os);
415 if (auto json_transcript = llvm::json::parse(ss.str()))
416 global_stats.try_emplace("transcript",
417 std::move(json_transcript.get()));
418 }
419 }
420
421 return std::move(global_stats);
422}
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end)
Definition: Statistics.cpp:39
static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key, const std::string &str)
Definition: Statistics.cpp:25
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:450
General Outline: Allows adding and removing breakpoints and find by ID and index.
void GetListMutex(std::unique_lock< std::recursive_mutex > &lock)
Sets the passed in Locker to hold the Breakpoint List mutex.
size_t GetSize() const
Returns the number of elements in this breakpoint list.
lldb::BreakpointSP GetBreakpointAtIndex(size_t i) const
Returns a shared pointer to the breakpoint with index i.
General Outline: A breakpoint has four main parts, a filter, a resolver, the list of breakpoint locat...
Definition: Breakpoint.h:81
llvm::json::Value GetStatistics()
Get statistics associated with this breakpoint in JSON format.
const char * GetBreakpointKind() const
Return the "kind" description for a breakpoint.
Definition: Breakpoint.h:458
uint32_t GetHitCount() const
Return the current hit count for all locations.
Definition: Breakpoint.cpp:319
StatsDuration::Duration GetResolveTime() const
Get the time it took to resolve all locations in this breakpoint.
Definition: Breakpoint.h:592
const StructuredData::Array & GetTranscript() const
A uniqued constant string class.
Definition: ConstString.h:40
static bool g_collecting_stats
Definition: Statistics.h:239
static llvm::json::Value ReportStatistics(Debugger &debugger, Target *target, const lldb_private::StatisticsOptions &options)
Get metrics associated with one or all targets in a debugger in JSON format.
Definition: Statistics.cpp:237
A class to manage flag bits.
Definition: Debugger.h:80
CommandInterpreter & GetCommandInterpreter()
Definition: Debugger.h:168
TargetList & GetTargetList()
Get accessor for the target list.
Definition: Debugger.h:198
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:367
A collection class for Module objects.
Definition: ModuleList.h:103
ModuleIterable Modules() const
Definition: ModuleList.h:527
A class that describes an executable image and its associated object and symbol files.
Definition: Module.h:88
const lldb_private::UUID & GetUUID()
Get a reference to the UUID value contained in this object.
Definition: Module.cpp:346
virtual ObjectFile * GetObjectFile()
Get the object file representation for the current architecture.
Definition: Module.cpp:1189
virtual SymbolFile * GetSymbolFile(bool can_create=true, Stream *feedback_strm=nullptr)
Get the module's symbol file.
Definition: Module.cpp:998
ConstString GetObjectName() const
Definition: Module.cpp:1187
static Module * GetAllocatedModuleAtIndex(size_t idx)
Definition: Module.cpp:124
static std::recursive_mutex & GetAllocationModuleCollectionMutex()
Definition: Module.cpp:106
Symtab * GetSymtab()
Definition: Module.cpp:1025
static size_t GetNumberAllocatedModules()
Definition: Module.cpp:118
void ForEachTypeSystem(llvm::function_ref< bool(lldb::TypeSystemSP)> callback)
Call callback for each TypeSystem in this Module.
Definition: Module.cpp:376
const ArchSpec & GetArchitecture() const
Get const accessor for the module architecture.
Definition: Module.cpp:1040
StatsDuration & GetSymtabIndexTime()
Accessor for the symbol table index time metric.
Definition: Module.h:881
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition: Module.h:452
StatsDuration & GetSymtabParseTime()
Accessor for the symbol table parse time metric.
Definition: Module.h:875
virtual bool IsStripped()=0
Detect if this object file has been stripped of local symbols.
virtual FileSpec & GetFileSpec()
Get accessor to the object file specification.
Definition: ObjectFile.h:275
Duration get() const
Definition: Statistics.h:34
std::chrono::duration< double > Duration
Definition: Statistics.h:32
void Serialize(llvm::json::OStream &s) const override
Provides public interface for all SymbolFiles.
Definition: SymbolFile.h:50
virtual uint64_t GetDebugInfoSize(bool load_all_debug_info=false)=0
Metrics gathering functions.
virtual bool GetDebugInfoIndexWasLoadedFromCache() const =0
Accessors for the bool that indicates if the debug info index was loaded from, or saved to the module...
virtual bool GetDebugInfoIndexWasSavedToCache() const =0
virtual StatsDuration::Duration GetDebugInfoParseTime()
Return the time taken to parse the debug information.
Definition: SymbolFile.h:416
virtual bool GetLoadDebugInfoEnabled()
Whether debug info will be loaded or not.
Definition: SymbolFile.h:135
virtual bool GetDebugInfoHadFrameVariableErrors() const =0
Accessors for the bool that indicates if there was debug info, but errors stopped variables from bein...
virtual ModuleList GetDebugInfoModules()
Get the additional modules that this symbol file uses to parse debug info.
Definition: SymbolFile.h:432
virtual StatsDuration::Duration GetDebugInfoIndexTime()
Return the time it took to index the debug information in the object file.
Definition: SymbolFile.h:423
virtual ObjectFile * GetObjectFile()=0
bool GetWasLoadedFromCache() const
Accessors for the bool that indicates if the debug info index was loaded from, or saved to the module...
Definition: Symtab.h:228
bool GetWasSavedToCache() const
Definition: Symtab.h:234
TargetIterable Targets()
Definition: TargetList.h:194
StatsSuccessFail m_frame_var
Definition: Statistics.h:201
std::optional< StatsTimepoint > m_launch_or_attach_time
Definition: Statistics.h:197
uint32_t m_source_map_deduce_count
Definition: Statistics.h:203
void CollectStats(Target &target)
Definition: Statistics.cpp:45
llvm::json::Value ToJSON(Target &target, const lldb_private::StatisticsOptions &options)
Definition: Statistics.cpp:106
StatsDuration m_create_time
Definition: Statistics.h:196
std::optional< StatsTimepoint > m_first_public_stop_time
Definition: Statistics.h:199
void IncreaseSourceRealpathAttemptCount(uint32_t count)
Definition: Statistics.cpp:227
uint32_t m_source_realpath_compatible_count
Definition: Statistics.h:205
StatsSuccessFail m_expr_eval
Definition: Statistics.h:200
std::vector< intptr_t > m_module_identifiers
Definition: Statistics.h:202
uint32_t m_source_realpath_attempt_count
Definition: Statistics.h:204
void IncreaseSourceRealpathCompatibleCount(uint32_t count)
Definition: Statistics.cpp:231
std::optional< StatsTimepoint > m_first_private_stop_time
Definition: Statistics.h:198
BreakpointList & GetBreakpointList(bool internal=false)
Definition: Target.cpp:315
const lldb::ProcessSP & GetProcessSP() const
Definition: Target.cpp:222
llvm::json::Value ReportStatistics(const lldb_private::StatisticsOptions &options)
Get metrics associated with this target in JSON format.
Definition: Target.cpp:4972
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:986
std::string GetAsString(llvm::StringRef separator="-") const
Definition: UUID.cpp:49
A class that represents a running process on the host machine.
std::chrono::time_point< StatsClock > StatsTimepoint
Definition: Statistics.h:28
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::TypeSystem > TypeSystemSP
Definition: lldb-forward.h:465
std::shared_ptr< lldb_private::UnixSignals > UnixSignalsSP
Definition: lldb-forward.h:476
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:387
std::shared_ptr< lldb_private::Module > ModuleSP
Definition: lldb-forward.h:371
Definition: Debugger.h:54
ConstString::MemoryStats stats
Definition: Statistics.h:131
llvm::json::Value ToJSON() const
Definition: Statistics.cpp:97
A class that represents statistics for a since lldb_private::Module.
Definition: Statistics.h:100
llvm::json::Value ToJSON() const
Definition: Statistics.cpp:51
llvm::StringMap< llvm::json::Value > type_system_stats
Definition: Statistics.h:113
std::vector< intptr_t > symfile_modules
Definition: Statistics.h:112
llvm::json::Value ToJSON() const
Definition: Statistics.cpp:35