Skip to content

Commit 1cff6d0

Browse files
authored
Add proper presymbolication support (#634)
This changes `--unstable-presymbolicate` to `--presymbolicate` and actually includes the symbols in the generated profile JSON.
2 parents b75b50c + 107e0cd commit 1cff6d0

23 files changed

+1360
-531
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use indexmap::IndexSet;
2-
use rustc_hash::FxHashMap;
2+
use rustc_hash::{FxHashMap, FxHashSet};
33

44
pub type FastHashMap<K, V> = FxHashMap<K, V>;
5+
pub type FastHashSet<V> = FxHashSet<V>;
56
pub type FastIndexSet<V> = IndexSet<V, rustc_hash::FxBuildHasher>;

fxprof-processed-profile/src/frame_table.rs

Lines changed: 101 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,119 +4,144 @@ use crate::category::{CategoryHandle, SubcategoryHandle, SubcategoryIndex};
44
use crate::fast_hash_map::FastIndexSet;
55
use crate::frame::FrameFlags;
66
use crate::func_table::{FuncIndex, FuncKey, FuncTable};
7-
use crate::global_lib_table::{GlobalLibIndex, GlobalLibTable};
7+
use crate::global_lib_table::{GlobalLibIndex, UsedLibraryAddressesCollector};
88
use crate::native_symbols::NativeSymbolIndex;
99
use crate::resource_table::ResourceTable;
1010
use crate::serialization_helpers::SerializableSingleValueColumn;
11-
use crate::string_table::{ProfileStringTable, StringHandle};
11+
use crate::string_table::StringHandle;
1212
use crate::SourceLocation;
1313

1414
#[derive(Debug, Clone, Default)]
15-
pub struct FrameTable {
16-
func_table: FuncTable,
17-
resource_table: ResourceTable,
18-
19-
func_col: Vec<FuncIndex>,
20-
category_col: Vec<CategoryHandle>,
21-
subcategory_col: Vec<SubcategoryIndex>,
22-
line_col: Vec<Option<u32>>,
23-
column_col: Vec<Option<u32>>,
24-
address_col: Vec<Option<u32>>,
25-
native_symbol_col: Vec<Option<NativeSymbolIndex>>,
26-
inline_depth_col: Vec<u16>,
27-
15+
pub struct FrameInterner {
2816
frame_key_set: FastIndexSet<InternalFrame>,
17+
contains_js_frame: bool,
2918
}
3019

31-
impl FrameTable {
20+
impl FrameInterner {
3221
pub fn new() -> Self {
3322
Default::default()
3423
}
3524

36-
pub fn index_for_frame(
37-
&mut self,
38-
frame: InternalFrame,
39-
global_libs: &mut GlobalLibTable,
40-
string_table: &mut ProfileStringTable,
41-
) -> usize {
25+
pub fn index_for_frame(&mut self, frame: InternalFrame) -> usize {
4226
let (frame_index, is_new) = self.frame_key_set.insert_full(frame);
4327

44-
if !is_new {
45-
return frame_index;
28+
if is_new
29+
&& frame
30+
.flags
31+
.intersects(FrameFlags::IS_JS | FrameFlags::IS_RELEVANT_FOR_JS)
32+
{
33+
self.contains_js_frame = true;
4634
}
35+
frame_index
36+
}
4737

48-
let func_key = frame.func_key();
49-
let func = self.func_table.index_for_func(
50-
func_key,
51-
&mut self.resource_table,
52-
global_libs,
53-
string_table,
54-
);
55-
56-
self.func_col.push(func);
57-
let SubcategoryHandle(category, subcategory) = frame.subcategory;
58-
self.category_col.push(category);
59-
self.subcategory_col.push(subcategory);
60-
self.line_col.push(frame.source_location.line);
61-
self.column_col.push(frame.source_location.col);
62-
63-
match frame.variant {
64-
InternalFrameVariant::Label => {
65-
self.address_col.push(None);
66-
self.native_symbol_col.push(None);
67-
self.inline_depth_col.push(0);
68-
}
69-
InternalFrameVariant::Native(NativeFrameData {
38+
pub fn gather_used_rvas(&self, collector: &mut UsedLibraryAddressesCollector) {
39+
for frame in &self.frame_key_set {
40+
if let InternalFrameVariant::Native(NativeFrameData {
7041
lib,
71-
native_symbol,
7242
relative_address,
73-
inline_depth,
74-
}) => {
75-
global_libs.add_lib_used_rva(lib, relative_address);
76-
77-
self.address_col.push(Some(relative_address));
78-
self.native_symbol_col.push(native_symbol);
79-
self.inline_depth_col.push(inline_depth);
43+
..
44+
}) = frame.variant
45+
{
46+
collector.add_lib_used_rva(lib, relative_address);
8047
}
8148
}
49+
}
8250

83-
frame_index
51+
pub fn into_frames(self) -> impl Iterator<Item = InternalFrame> {
52+
self.frame_key_set.into_iter()
8453
}
8554

8655
pub fn contains_js_frame(&self) -> bool {
87-
self.func_table.contains_js_func()
56+
self.contains_js_frame
8857
}
8958

90-
pub fn get_serializable_tables(
91-
&self,
92-
) -> (SerializableFrameTable<'_>, &'_ FuncTable, &'_ ResourceTable) {
93-
(
94-
SerializableFrameTable(self),
95-
&self.func_table,
96-
&self.resource_table,
97-
)
59+
pub fn create_tables(&self) -> (FrameTable, FuncTable, ResourceTable) {
60+
let len = self.frame_key_set.len();
61+
let mut func_col = Vec::with_capacity(len);
62+
let mut category_col = Vec::with_capacity(len);
63+
let mut subcategory_col = Vec::with_capacity(len);
64+
let mut line_col = Vec::with_capacity(len);
65+
let mut column_col = Vec::with_capacity(len);
66+
let mut address_col = Vec::with_capacity(len);
67+
let mut native_symbol_col = Vec::with_capacity(len);
68+
let mut inline_depth_col = Vec::with_capacity(len);
69+
70+
let mut func_table = FuncTable::default();
71+
let mut resource_table = ResourceTable::default();
72+
73+
for frame in &self.frame_key_set {
74+
let func_key = frame.func_key();
75+
let func = func_table.index_for_func(func_key, &mut resource_table);
76+
77+
func_col.push(func);
78+
let SubcategoryHandle(category, subcategory) = frame.subcategory;
79+
category_col.push(category);
80+
subcategory_col.push(subcategory);
81+
line_col.push(frame.source_location.line);
82+
column_col.push(frame.source_location.col);
83+
84+
match frame.variant {
85+
InternalFrameVariant::Label => {
86+
address_col.push(None);
87+
native_symbol_col.push(None);
88+
inline_depth_col.push(0);
89+
}
90+
InternalFrameVariant::Native(NativeFrameData {
91+
native_symbol,
92+
relative_address,
93+
inline_depth,
94+
..
95+
}) => {
96+
address_col.push(Some(relative_address));
97+
native_symbol_col.push(native_symbol);
98+
inline_depth_col.push(inline_depth);
99+
}
100+
}
101+
}
102+
103+
let frame_table = FrameTable {
104+
func_col,
105+
category_col,
106+
subcategory_col,
107+
line_col,
108+
column_col,
109+
address_col,
110+
native_symbol_col,
111+
inline_depth_col,
112+
};
113+
114+
(frame_table, func_table, resource_table)
98115
}
99116
}
100117

101-
pub struct SerializableFrameTable<'a>(&'a FrameTable);
118+
pub struct FrameTable {
119+
func_col: Vec<FuncIndex>,
120+
category_col: Vec<CategoryHandle>,
121+
subcategory_col: Vec<SubcategoryIndex>,
122+
line_col: Vec<Option<u32>>,
123+
column_col: Vec<Option<u32>>,
124+
address_col: Vec<Option<u32>>,
125+
native_symbol_col: Vec<Option<NativeSymbolIndex>>,
126+
inline_depth_col: Vec<u16>,
127+
}
102128

103-
impl Serialize for SerializableFrameTable<'_> {
129+
impl Serialize for FrameTable {
104130
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
105-
let SerializableFrameTable(table) = self;
106-
let len = table.func_col.len();
131+
let len = self.func_col.len();
107132
let mut map = serializer.serialize_map(None)?;
108133
map.serialize_entry("length", &len)?;
109-
map.serialize_entry("func", &table.func_col)?;
110-
map.serialize_entry("category", &table.category_col)?;
111-
map.serialize_entry("subcategory", &table.subcategory_col)?;
112-
map.serialize_entry("line", &table.line_col)?;
113-
map.serialize_entry("column", &table.column_col)?;
134+
map.serialize_entry("func", &self.func_col)?;
135+
map.serialize_entry("category", &self.category_col)?;
136+
map.serialize_entry("subcategory", &self.subcategory_col)?;
137+
map.serialize_entry("line", &self.line_col)?;
138+
map.serialize_entry("column", &self.column_col)?;
114139
map.serialize_entry(
115140
"address",
116-
&SerializableFrameTableAddressColumn(&table.address_col),
141+
&SerializableFrameTableAddressColumn(&self.address_col),
117142
)?;
118-
map.serialize_entry("nativeSymbol", &table.native_symbol_col)?;
119-
map.serialize_entry("inlineDepth", &table.inline_depth_col)?;
143+
map.serialize_entry("nativeSymbol", &self.native_symbol_col)?;
144+
map.serialize_entry("inlineDepth", &self.inline_depth_col)?;
120145
map.serialize_entry("innerWindowID", &SerializableSingleValueColumn(0, len))?;
121146
map.end()
122147
}

fxprof-processed-profile/src/func_table.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
22

33
use crate::fast_hash_map::FastIndexSet;
44
use crate::frame::FrameFlags;
5-
use crate::global_lib_table::{GlobalLibIndex, GlobalLibTable};
5+
use crate::global_lib_table::GlobalLibIndex;
66
use crate::resource_table::{ResourceIndex, ResourceTable};
77
use crate::serialization_helpers::SerializableSingleValueColumn;
8-
use crate::string_table::{ProfileStringTable, StringHandle};
8+
use crate::string_table::StringHandle;
99

1010
#[derive(Debug, Clone, Default)]
1111
pub struct FuncTable {
@@ -15,8 +15,6 @@ pub struct FuncTable {
1515
flags: Vec<FrameFlags>,
1616

1717
func_key_set: FastIndexSet<FuncKey>,
18-
19-
contains_js_func: bool,
2018
}
2119

2220
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
@@ -32,8 +30,6 @@ impl FuncTable {
3230
&mut self,
3331
func_key: FuncKey,
3432
resource_table: &mut ResourceTable,
35-
global_libs: &mut GlobalLibTable,
36-
string_table: &mut ProfileStringTable,
3733
) -> FuncIndex {
3834
let (index, is_new) = self.func_key_set.insert_full(func_key);
3935

@@ -49,24 +45,15 @@ impl FuncTable {
4945
flags,
5046
} = func_key;
5147

52-
let resource =
53-
lib.map(|lib| resource_table.resource_for_lib(lib, global_libs, string_table));
48+
let resource = lib.map(|lib| resource_table.resource_for_lib(lib));
5449

5550
self.names.push(name);
5651
self.files.push(file_path);
5752
self.resources.push(resource);
5853
self.flags.push(flags);
5954

60-
if flags.intersects(FrameFlags::IS_JS | FrameFlags::IS_RELEVANT_FOR_JS) {
61-
self.contains_js_func = true;
62-
}
63-
6455
func_index
6556
}
66-
67-
pub fn contains_js_func(&self) -> bool {
68-
self.contains_js_func
69-
}
7057
}
7158

7259
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]

0 commit comments

Comments
 (0)