|  | // Copyright 2015 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ | 
|  | #define BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ | 
|  |  | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <functional> | 
|  |  | 
|  | #include "base/base_export.h" | 
|  |  | 
|  | namespace base { | 
|  | namespace trace_event { | 
|  |  | 
|  | // When heap profiling is enabled, tracing keeps track of the allocation | 
|  | // context for each allocation intercepted. It is generated by the | 
|  | // |AllocationContextTracker| which keeps stacks of context in TLS. | 
|  | // The tracker is initialized lazily. | 
|  |  | 
|  | // The backtrace in the allocation context is a snapshot of the stack. For now, | 
|  | // this is the pseudo stack where frames are created by trace event macros. In | 
|  | // the future, we might add the option to use the native call stack. In that | 
|  | // case, |Backtrace| and |AllocationContextTracker::GetContextSnapshot| might | 
|  | // have different implementations that can be selected by a compile time flag. | 
|  |  | 
|  | // The number of stack frames stored in the backtrace is a trade off between | 
|  | // memory used for tracing and accuracy. Measurements done on a prototype | 
|  | // revealed that: | 
|  | // | 
|  | // - In 60 percent of the cases, pseudo stack depth <= 7. | 
|  | // - In 87 percent of the cases, pseudo stack depth <= 9. | 
|  | // - In 95 percent of the cases, pseudo stack depth <= 11. | 
|  | // | 
|  | // See the design doc (https://goo.gl/4s7v7b) for more details. | 
|  |  | 
|  | // Represents (pseudo) stack frame. Used in Backtrace class below. | 
|  | // | 
|  | // Conceptually stack frame is identified by its value, and type is used | 
|  | // mostly to properly format the value. Value is expected to be a valid | 
|  | // pointer from process' address space. | 
|  | struct BASE_EXPORT StackFrame { | 
|  | enum class Type { | 
|  | TRACE_EVENT_NAME,   // const char* string | 
|  | THREAD_NAME,        // const char* thread name | 
|  | PROGRAM_COUNTER,    // as returned by stack tracing (e.g. by StackTrace) | 
|  | }; | 
|  |  | 
|  | static StackFrame FromTraceEventName(const char* name) { | 
|  | return {Type::TRACE_EVENT_NAME, name}; | 
|  | } | 
|  | static StackFrame FromThreadName(const char* name) { | 
|  | return {Type::THREAD_NAME, name}; | 
|  | } | 
|  | static StackFrame FromProgramCounter(const void* pc) { | 
|  | return {Type::PROGRAM_COUNTER, pc}; | 
|  | } | 
|  |  | 
|  | Type type; | 
|  | const void* value; | 
|  | }; | 
|  |  | 
|  | bool BASE_EXPORT operator < (const StackFrame& lhs, const StackFrame& rhs); | 
|  | bool BASE_EXPORT operator == (const StackFrame& lhs, const StackFrame& rhs); | 
|  | bool BASE_EXPORT operator != (const StackFrame& lhs, const StackFrame& rhs); | 
|  |  | 
|  | struct BASE_EXPORT Backtrace { | 
|  | Backtrace(); | 
|  |  | 
|  | // If the stack is higher than what can be stored here, the top frames | 
|  | // (the ones further from main()) are stored. Depth of 12 is enough for most | 
|  | // pseudo traces (see above), but not for native traces, where we need more. | 
|  | enum { kMaxFrameCount = 48 }; | 
|  | StackFrame frames[kMaxFrameCount]; | 
|  | size_t frame_count = 0; | 
|  | }; | 
|  |  | 
|  | bool BASE_EXPORT operator==(const Backtrace& lhs, const Backtrace& rhs); | 
|  | bool BASE_EXPORT operator!=(const Backtrace& lhs, const Backtrace& rhs); | 
|  |  | 
|  | // The |AllocationContext| is context metadata that is kept for every allocation | 
|  | // when heap profiling is enabled. To simplify memory management for book- | 
|  | // keeping, this struct has a fixed size. | 
|  | struct BASE_EXPORT AllocationContext { | 
|  | AllocationContext(); | 
|  | AllocationContext(const Backtrace& backtrace, const char* type_name); | 
|  |  | 
|  | Backtrace backtrace; | 
|  |  | 
|  | // Type name of the type stored in the allocated memory. A null pointer | 
|  | // indicates "unknown type". Grouping is done by comparing pointers, not by | 
|  | // deep string comparison. In a component build, where a type name can have a | 
|  | // string literal in several dynamic libraries, this may distort grouping. | 
|  | const char* type_name; | 
|  | }; | 
|  |  | 
|  | bool BASE_EXPORT operator==(const AllocationContext& lhs, | 
|  | const AllocationContext& rhs); | 
|  | bool BASE_EXPORT operator!=(const AllocationContext& lhs, | 
|  | const AllocationContext& rhs); | 
|  |  | 
|  | // Struct to store the size and count of the allocations. | 
|  | struct AllocationMetrics { | 
|  | size_t size; | 
|  | size_t count; | 
|  | }; | 
|  |  | 
|  | }  // namespace trace_event | 
|  | }  // namespace base | 
|  |  | 
|  | namespace std { | 
|  |  | 
|  | template <> | 
|  | struct BASE_EXPORT hash<base::trace_event::StackFrame> { | 
|  | size_t operator()(const base::trace_event::StackFrame& frame) const; | 
|  | }; | 
|  |  | 
|  | template <> | 
|  | struct BASE_EXPORT hash<base::trace_event::Backtrace> { | 
|  | size_t operator()(const base::trace_event::Backtrace& backtrace) const; | 
|  | }; | 
|  |  | 
|  | template <> | 
|  | struct BASE_EXPORT hash<base::trace_event::AllocationContext> { | 
|  | size_t operator()(const base::trace_event::AllocationContext& context) const; | 
|  | }; | 
|  |  | 
|  | }  // namespace std | 
|  |  | 
|  | #endif  // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ |