> +/* One PC's symbolization, resolved on first use and reused after that.
> + LOCATIONS[0] is the primary location; the rest are alternates. */
> +struct instruction_map_entry
> +{
> + bool valid = false;
> + const std::vector<dwarf_debug::source_location> *locations = nullptr;
> + const std::vector<dwarf_debug::inline_frame> *inline_stack = nullptr;
> + uint64_t inline_stack_hash = 0;
> + inline_path_cache_entry *inline_path = nullptr;
> +};
Wouldn't an inline vector be more space efficient? Should probably
optimize for the common no or single inline, single location case.
> +
> +/* Per-PC entries for one function, indexed directly when the function is
> + small enough and hashed otherwise. */
> +struct function_inst_map
> +{
> + uint64_t base = 0;
> + std::vector<instruction_map_entry> dense;
> + std::unordered_map<uint64_t, instruction_map_entry> sparse;
> +
> + bool dense_p () const { return !dense.empty (); }
> +
> + /* A map covering [START, END), dense when that span is small enough to
> + index directly and sparse otherwise. */
> + static function_inst_map make (uint64_t start, uint64_t end)
> + {
> + function_inst_map map;
> + if (end > start && end - start <= DENSE_ADDR_MASS_MAX_SPAN)
> + {
> + map.base = start;
> + map.dense.resize (static_cast<size_t> (end - start));
> + }
> + return map;
So map is uninitialized when the check fails?
> + whose declaration starts at or before it. Null when nothing fits. */
> +function_builder *
> +source_owner_along_inline_path (
> + const std::vector<function_builder *> &path,
> + const std::vector<dwarf_debug::inline_frame> &stack,
> + const dwarf_debug::source_location &loc)
> +{
> + afdo_assert (!path.empty ());
> + size_t caller_index = 0;
> + for (const dwarf_debug::inline_frame &frame : stack)
> + {
> + if (frame.call_line == 0)
> + continue;
> + if (caller_index >= path.size ())
> + break;
> + if (loc.line_number == frame.call_line)
> + {
> + dwarf_debug::interned_string call_file = frame.caller_file_path;
> + if (dwarf_debug::string_empty (call_file))
> + call_file = frame.file_path;
> + const bool same_file
> + = dwarf_debug::string_empty (loc.file_path)
> + || dwarf_debug::string_empty (call_file)
> + || source_path::equivalent (
> + dwarf_debug::string_value (loc.file_path),
> + dwarf_debug::string_value (call_file));
Why do empty strings count as same file?