mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-04 19:26:09 +03:00
196 lines
7.3 KiB
C
196 lines
7.3 KiB
C
|
// Copyright 2020 The Chromium Authors
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#ifndef BASE_TRACE_EVENT_INTERNED_ARGS_HELPER_H_
|
||
|
#define BASE_TRACE_EVENT_INTERNED_ARGS_HELPER_H_
|
||
|
|
||
|
#include <string>
|
||
|
|
||
|
#include "base/base_export.h"
|
||
|
#include "base/containers/span.h"
|
||
|
#include "base/hash/hash.h"
|
||
|
#include "base/location.h"
|
||
|
#include "base/profiler/module_cache.h"
|
||
|
#include "base/trace_event/trace_event.h"
|
||
|
#include "build/build_config.h"
|
||
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||
|
#include "third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h"
|
||
|
#include "third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h"
|
||
|
|
||
|
namespace base {
|
||
|
namespace trace_event {
|
||
|
|
||
|
// TrackEventInternedDataIndex expects the same data structure to be used for
|
||
|
// all interned fields with the same field number. We can't use base::Location
|
||
|
// for log event's location since base::Location uses program counter based
|
||
|
// location.
|
||
|
struct BASE_EXPORT TraceSourceLocation {
|
||
|
const char* function_name = nullptr;
|
||
|
const char* file_name = nullptr;
|
||
|
int line_number = 0;
|
||
|
|
||
|
TraceSourceLocation() = default;
|
||
|
TraceSourceLocation(const char* function_name,
|
||
|
const char* file_name,
|
||
|
int line_number)
|
||
|
: function_name(function_name),
|
||
|
file_name(file_name),
|
||
|
line_number(line_number) {}
|
||
|
// Construct a new source location from an existing base::Location, the only
|
||
|
// attributes that are read are |function_name|, |file_name| and
|
||
|
// |line_number|.
|
||
|
explicit TraceSourceLocation(const base::Location& location)
|
||
|
: function_name(location.function_name()),
|
||
|
file_name(location.file_name()),
|
||
|
line_number(location.line_number()) {}
|
||
|
|
||
|
bool operator==(const TraceSourceLocation& other) const {
|
||
|
return file_name == other.file_name &&
|
||
|
function_name == other.function_name &&
|
||
|
line_number == other.line_number;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Data structure for constructing an interned
|
||
|
// perfetto.protos.UnsymbolizedSourceLocation proto message.
|
||
|
struct BASE_EXPORT UnsymbolizedSourceLocation {
|
||
|
uint64_t mapping_id = 0;
|
||
|
uint64_t rel_pc = 0;
|
||
|
|
||
|
UnsymbolizedSourceLocation() = default;
|
||
|
UnsymbolizedSourceLocation(uint64_t mapping_id, uint64_t rel_pc)
|
||
|
: mapping_id(mapping_id), rel_pc(rel_pc) {}
|
||
|
|
||
|
bool operator==(const UnsymbolizedSourceLocation& other) const {
|
||
|
return mapping_id == other.mapping_id && rel_pc == other.rel_pc;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
} // namespace trace_event
|
||
|
} // namespace base
|
||
|
|
||
|
namespace std {
|
||
|
|
||
|
template <>
|
||
|
struct hash<base::trace_event::TraceSourceLocation> {
|
||
|
std::size_t operator()(
|
||
|
const base::trace_event::TraceSourceLocation& loc) const {
|
||
|
return base::HashInts(
|
||
|
base::HashInts(reinterpret_cast<uintptr_t>(loc.file_name),
|
||
|
reinterpret_cast<uintptr_t>(loc.function_name)),
|
||
|
static_cast<size_t>(loc.line_number));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <>
|
||
|
struct hash<base::trace_event::UnsymbolizedSourceLocation> {
|
||
|
std::size_t operator()(
|
||
|
const base::trace_event::UnsymbolizedSourceLocation& module) const {
|
||
|
return base::HashInts(module.mapping_id, module.rel_pc);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
} // namespace std
|
||
|
|
||
|
namespace base {
|
||
|
namespace trace_event {
|
||
|
|
||
|
struct BASE_EXPORT InternedSourceLocation
|
||
|
: public perfetto::TrackEventInternedDataIndex<
|
||
|
InternedSourceLocation,
|
||
|
perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber,
|
||
|
TraceSourceLocation> {
|
||
|
static void Add(perfetto::protos::pbzero::InternedData* interned_data,
|
||
|
size_t iid,
|
||
|
const TraceSourceLocation& location);
|
||
|
using perfetto::TrackEventInternedDataIndex<
|
||
|
InternedSourceLocation,
|
||
|
perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber,
|
||
|
TraceSourceLocation>::Get;
|
||
|
static size_t Get(perfetto::EventContext* ctx, const Location& location) {
|
||
|
return perfetto::TrackEventInternedDataIndex<
|
||
|
InternedSourceLocation,
|
||
|
perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber,
|
||
|
TraceSourceLocation>::Get(ctx, TraceSourceLocation(location));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct BASE_EXPORT InternedLogMessage
|
||
|
: public perfetto::TrackEventInternedDataIndex<
|
||
|
InternedLogMessage,
|
||
|
perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
|
||
|
std::string> {
|
||
|
static void Add(perfetto::protos::pbzero::InternedData* interned_data,
|
||
|
size_t iid,
|
||
|
const std::string& log_message);
|
||
|
};
|
||
|
|
||
|
struct BASE_EXPORT InternedBuildId
|
||
|
: public perfetto::TrackEventInternedDataIndex<
|
||
|
InternedBuildId,
|
||
|
perfetto::protos::pbzero::InternedData::kBuildIdsFieldNumber,
|
||
|
std::string> {
|
||
|
static void Add(perfetto::protos::pbzero::InternedData* interned_data,
|
||
|
size_t iid,
|
||
|
const std::string& build_id);
|
||
|
};
|
||
|
|
||
|
struct BASE_EXPORT InternedMappingPath
|
||
|
: public perfetto::TrackEventInternedDataIndex<
|
||
|
InternedMappingPath,
|
||
|
perfetto::protos::pbzero::InternedData::kMappingPathsFieldNumber,
|
||
|
std::string> {
|
||
|
static void Add(perfetto::protos::pbzero::InternedData* interned_data,
|
||
|
size_t iid,
|
||
|
const std::string& mapping_path);
|
||
|
};
|
||
|
|
||
|
struct BASE_EXPORT InternedMapping
|
||
|
: public perfetto::TrackEventInternedDataIndex<
|
||
|
InternedMapping,
|
||
|
perfetto::protos::pbzero::InternedData::kMappingsFieldNumber,
|
||
|
const base::ModuleCache::Module*> {
|
||
|
// We need a custom implementation here to plumb EventContext to Add.
|
||
|
static size_t Get(perfetto::EventContext* ctx,
|
||
|
const base::ModuleCache::Module* module);
|
||
|
static void Add(perfetto::EventContext* ctx,
|
||
|
size_t iid,
|
||
|
const base::ModuleCache::Module* module);
|
||
|
};
|
||
|
|
||
|
// Interns an unsymbolized source code location + all it's "dependencies", i.e.
|
||
|
// module, strings used in the module definition, and so on.
|
||
|
struct BASE_EXPORT InternedUnsymbolizedSourceLocation
|
||
|
: public perfetto::TrackEventInternedDataIndex<
|
||
|
InternedUnsymbolizedSourceLocation,
|
||
|
perfetto::protos::pbzero::InternedData::
|
||
|
kUnsymbolizedSourceLocationsFieldNumber,
|
||
|
uintptr_t> {
|
||
|
// We need a custom Get implementation to use ModuleCache, and to return
|
||
|
// a nullopt if a module for the given address cannot be found.
|
||
|
static absl::optional<size_t> Get(perfetto::EventContext* ctx,
|
||
|
uintptr_t address);
|
||
|
static void Add(perfetto::protos::pbzero::InternedData* interned_data,
|
||
|
size_t iid,
|
||
|
const UnsymbolizedSourceLocation& location);
|
||
|
|
||
|
// We use thread local storage for the module cache if we are using the
|
||
|
// client library since it is more optimal. It was not worth it to write
|
||
|
// optimal caching for not client library users since everyone will convert.
|
||
|
#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
|
||
|
private:
|
||
|
// This implies that a module cache lifetime = incremental state.
|
||
|
// We don't want unlimited lifetime because it keeps modules pinned in
|
||
|
// memory on some platforms (Windows).
|
||
|
// TODO(b/237055179): Consider tying module cache to DataSource instead so
|
||
|
// that the cache is not unnecessarily cleared on incremental state change.
|
||
|
base::ModuleCache module_cache_;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
} // namespace trace_event
|
||
|
} // namespace base
|
||
|
|
||
|
#endif // BASE_TRACE_EVENT_INTERNED_ARGS_HELPER_H_
|