@@ -5,19 +5,26 @@ use crate::fast_hash_map::FastHashMap;
5
5
use crate :: frame:: FrameFlags ;
6
6
use crate :: func_table:: { FuncIndex , FuncTable } ;
7
7
use crate :: global_lib_table:: { GlobalLibIndex , GlobalLibTable } ;
8
- use crate :: native_symbols:: { NativeSymbolIndex , NativeSymbols } ;
8
+ use crate :: native_symbols:: NativeSymbolIndex ;
9
9
use crate :: resource_table:: ResourceTable ;
10
10
use crate :: serialization_helpers:: SerializableSingleValueColumn ;
11
11
use crate :: thread_string_table:: { ThreadInternalStringIndex , ThreadStringTable } ;
12
12
13
13
#[ derive( Debug , Clone , Default ) ]
14
14
pub struct FrameTable {
15
- addresses : Vec < Option < u32 > > ,
16
- categories : Vec < CategoryHandle > ,
17
- subcategories : Vec < SubcategoryIndex > ,
18
- funcs : Vec < FuncIndex > ,
19
- native_symbols : Vec < Option < NativeSymbolIndex > > ,
20
- internal_frame_to_frame_index : FastHashMap < InternalFrame , usize > ,
15
+ name_col : Vec < ThreadInternalStringIndex > ,
16
+ category_col : Vec < CategoryHandle > ,
17
+ subcategory_col : Vec < SubcategoryIndex > ,
18
+ flags_col : Vec < FrameFlags > ,
19
+ file_col : Vec < Option < ThreadInternalStringIndex > > ,
20
+ line_col : Vec < Option < u32 > > ,
21
+ column_col : Vec < Option < u32 > > ,
22
+ lib_col : Vec < Option < GlobalLibIndex > > ,
23
+ address_col : Vec < Option < u32 > > ,
24
+ native_symbol_col : Vec < Option < NativeSymbolIndex > > ,
25
+ inline_depth_col : Vec < u16 > ,
26
+ frame_key_to_frame_index : FastHashMap < InternalFrameKey , usize > ,
27
+ contains_js_frame : bool ,
21
28
}
22
29
23
30
impl FrameTable {
@@ -27,91 +34,130 @@ impl FrameTable {
27
34
28
35
pub fn index_for_frame (
29
36
& mut self ,
30
- string_table : & mut ThreadStringTable ,
31
- resource_table : & mut ResourceTable ,
32
- func_table : & mut FuncTable ,
33
- native_symbol_table : & mut NativeSymbols ,
34
- global_libs : & mut GlobalLibTable ,
35
37
frame : InternalFrame ,
38
+ global_lib_index_to_thread_string_index : & mut FastHashMap <
39
+ GlobalLibIndex ,
40
+ ThreadInternalStringIndex ,
41
+ > ,
42
+ global_libs : & mut GlobalLibTable ,
43
+ string_table : & mut ThreadStringTable ,
36
44
) -> usize {
37
- let addresses = & mut self . addresses ;
38
- let funcs = & mut self . funcs ;
39
- let native_symbols = & mut self . native_symbols ;
40
- let categories = & mut self . categories ;
41
- let subcategories = & mut self . subcategories ;
42
- * self
43
- . internal_frame_to_frame_index
44
- . entry ( frame. clone ( ) )
45
- . or_insert_with ( || {
46
- let frame_index = addresses. len ( ) ;
47
- let ( address, location_string_index, native_symbol, resource) = match frame. location
48
- {
49
- InternalFrameLocation :: UnknownAddress ( address) => {
50
- let location_string = format ! ( "0x{address:x}" ) ;
51
- let s = string_table. index_for_string ( & location_string) ;
52
- ( None , s, None , None )
53
- }
54
- InternalFrameLocation :: AddressInLib ( address, lib_index) => {
55
- let res =
56
- resource_table. resource_for_lib ( lib_index, global_libs, string_table) ;
57
- let lib = global_libs. get_lib ( lib_index) . unwrap ( ) ;
58
- let native_symbol_and_name =
59
- lib. symbol_table . as_deref ( ) . and_then ( |symbol_table| {
60
- let symbol = symbol_table. lookup ( address) ?;
61
- Some (
62
- native_symbol_table. symbol_index_and_string_index_for_symbol (
63
- lib_index,
64
- symbol,
65
- string_table,
66
- ) ,
67
- )
68
- } ) ;
69
- let ( native_symbol, s) = match native_symbol_and_name {
70
- Some ( ( native_symbol, name_string_index) ) => {
71
- ( Some ( native_symbol) , name_string_index)
72
- }
73
- None => {
74
- // This isn't in the pre-provided symbol table, and we know it's in a library.
75
- global_libs. add_lib_used_rva ( lib_index, address) ;
76
-
77
- let location_string = format ! ( "0x{address:x}" ) ;
78
- ( None , string_table. index_for_string ( & location_string) )
79
- }
80
- } ;
81
- ( Some ( address) , s, native_symbol, Some ( res) )
82
- }
83
- InternalFrameLocation :: Label ( string_index) => ( None , string_index, None , None ) ,
84
- } ;
85
- let func_index =
86
- func_table. index_for_func ( location_string_index, resource, frame. flags ) ;
87
- let SubcategoryHandle ( category, subcategory) = frame. subcategory ;
88
- addresses. push ( address) ;
89
- categories. push ( category) ;
90
- subcategories. push ( subcategory) ;
91
- funcs. push ( func_index) ;
92
- native_symbols. push ( native_symbol) ;
93
- frame_index
45
+ if let Some ( index) = self . frame_key_to_frame_index . get ( & frame. key ) {
46
+ return * index;
47
+ }
48
+
49
+ let flags = frame. key . flags ;
50
+
51
+ let frame_index = self . name_col . len ( ) ;
52
+ let SubcategoryHandle ( category, subcategory) = frame. key . subcategory ;
53
+ self . name_col . push ( frame. name ) ;
54
+ self . category_col . push ( category) ;
55
+ self . subcategory_col . push ( subcategory) ;
56
+ self . flags_col . push ( flags) ;
57
+
58
+ match frame. key . variant {
59
+ InternalFrameKeyVariant :: Label {
60
+ file_path,
61
+ line,
62
+ col,
63
+ ..
64
+ } => {
65
+ self . file_col . push ( file_path) ;
66
+ self . line_col . push ( line) ;
67
+ self . column_col . push ( col) ;
68
+ self . lib_col . push ( None ) ;
69
+ self . address_col . push ( None ) ;
70
+ self . native_symbol_col . push ( None ) ;
71
+ self . inline_depth_col . push ( 0 ) ;
72
+ }
73
+ InternalFrameKeyVariant :: Native {
74
+ lib,
75
+ relative_address,
76
+ inline_depth,
77
+ } => {
78
+ self . file_col . push ( None ) ;
79
+ self . line_col . push ( None ) ;
80
+ self . column_col . push ( None ) ;
81
+ self . lib_col . push ( Some ( lib) ) ;
82
+ self . address_col . push ( Some ( relative_address) ) ;
83
+ self . native_symbol_col . push ( frame. native_symbol ) ;
84
+ self . inline_depth_col . push ( inline_depth) ;
85
+
86
+ global_libs. add_lib_used_rva ( lib, relative_address) ;
87
+
88
+ global_lib_index_to_thread_string_index
89
+ . entry ( lib)
90
+ . or_insert_with ( || {
91
+ let lib_name = & global_libs. get_lib ( lib) . unwrap ( ) . name ;
92
+ string_table. index_for_string ( lib_name)
93
+ } ) ;
94
+ }
95
+ }
96
+
97
+ self . frame_key_to_frame_index . insert ( frame. key , frame_index) ;
98
+
99
+ if flags. intersects ( FrameFlags :: IS_JS | FrameFlags :: IS_RELEVANT_FOR_JS ) {
100
+ self . contains_js_frame = true ;
101
+ }
102
+
103
+ frame_index
104
+ }
105
+
106
+ pub fn contains_js_frame ( & self ) -> bool {
107
+ self . contains_js_frame
108
+ }
109
+
110
+ pub fn get_serializable_tables (
111
+ & self ,
112
+ global_lib_index_to_thread_string_index : & FastHashMap <
113
+ GlobalLibIndex ,
114
+ ThreadInternalStringIndex ,
115
+ > ,
116
+ ) -> ( SerializableFrameTable < ' _ > , FuncTable , ResourceTable ) {
117
+ let mut func_table = FuncTable :: new ( ) ;
118
+ let mut resource_table = ResourceTable :: new ( ) ;
119
+ let func_col = self
120
+ . name_col
121
+ . iter ( )
122
+ . cloned ( )
123
+ . zip ( self . flags_col . iter ( ) . cloned ( ) )
124
+ . zip ( self . lib_col . iter ( ) . cloned ( ) )
125
+ . zip ( self . file_col . iter ( ) . cloned ( ) )
126
+ . map ( |( ( ( name, flags) , lib) , file) | {
127
+ let resource = lib. map ( |lib| {
128
+ resource_table. resource_for_lib ( lib, global_lib_index_to_thread_string_index)
129
+ } ) ;
130
+ func_table. index_for_func ( name, file, resource, flags)
94
131
} )
132
+ . collect ( ) ;
133
+ (
134
+ SerializableFrameTable ( self , func_col) ,
135
+ func_table,
136
+ resource_table,
137
+ )
95
138
}
96
139
}
97
140
98
- impl Serialize for FrameTable {
141
+ pub struct SerializableFrameTable < ' a > ( & ' a FrameTable , Vec < FuncIndex > ) ;
142
+
143
+ impl Serialize for SerializableFrameTable < ' _ > {
99
144
fn serialize < S : Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
100
- let len = self . addresses . len ( ) ;
145
+ let SerializableFrameTable ( table, func_col) = self ;
146
+ let len = table. name_col . len ( ) ;
101
147
let mut map = serializer. serialize_map ( None ) ?;
102
148
map. serialize_entry ( "length" , & len) ?;
103
149
map. serialize_entry (
104
150
"address" ,
105
- & SerializableFrameTableAddressColumn ( & self . addresses ) ,
151
+ & SerializableFrameTableAddressColumn ( & table . address_col ) ,
106
152
) ?;
107
- map. serialize_entry ( "inlineDepth" , & SerializableSingleValueColumn ( 0u32 , len ) ) ?;
108
- map. serialize_entry ( "category" , & self . categories ) ?;
109
- map. serialize_entry ( "subcategory" , & self . subcategories ) ?;
110
- map. serialize_entry ( "func" , & self . funcs ) ?;
111
- map. serialize_entry ( "nativeSymbol" , & self . native_symbols ) ?;
153
+ map. serialize_entry ( "inlineDepth" , & table . inline_depth_col ) ?;
154
+ map. serialize_entry ( "category" , & table . category_col ) ?;
155
+ map. serialize_entry ( "subcategory" , & table . subcategory_col ) ?;
156
+ map. serialize_entry ( "func" , func_col ) ?;
157
+ map. serialize_entry ( "nativeSymbol" , & table . native_symbol_col ) ?;
112
158
map. serialize_entry ( "innerWindowID" , & SerializableSingleValueColumn ( 0 , len) ) ?;
113
- map. serialize_entry ( "line" , & SerializableSingleValueColumn ( ( ) , len ) ) ?;
114
- map. serialize_entry ( "column" , & SerializableSingleValueColumn ( ( ) , len ) ) ?;
159
+ map. serialize_entry ( "line" , & table . line_col ) ?;
160
+ map. serialize_entry ( "column" , & table . column_col ) ?;
115
161
map. end ( )
116
162
}
117
163
}
@@ -133,14 +179,49 @@ impl Serialize for SerializableFrameTableAddressColumn<'_> {
133
179
134
180
#[ derive( Debug , Clone , PartialOrd , Ord , PartialEq , Eq , Hash ) ]
135
181
pub struct InternalFrame {
136
- pub location : InternalFrameLocation ,
182
+ pub key : InternalFrameKey ,
183
+ pub name : ThreadInternalStringIndex ,
184
+ pub native_symbol : Option < NativeSymbolIndex > , // only used when key.variant is InternalFrameKeyVariant::Native
185
+ pub file_path : Option < ThreadInternalStringIndex > ,
186
+ pub line : Option < u32 > ,
187
+ pub col : Option < u32 > ,
188
+ }
189
+
190
+ #[ derive( Debug , Clone , Copy , PartialOrd , Ord , PartialEq , Eq , Hash ) ]
191
+ pub struct InternalFrameKey {
192
+ pub variant : InternalFrameKeyVariant ,
137
193
pub subcategory : SubcategoryHandle ,
138
194
pub flags : FrameFlags ,
139
195
}
140
196
197
+ #[ derive( Debug , Clone , Copy , PartialOrd , Ord , PartialEq , Eq , Hash ) ]
198
+ pub enum InternalFrameKeyVariant {
199
+ Label {
200
+ name : ThreadInternalStringIndex ,
201
+ file_path : Option < ThreadInternalStringIndex > ,
202
+ line : Option < u32 > ,
203
+ col : Option < u32 > ,
204
+ } ,
205
+ Native {
206
+ lib : GlobalLibIndex ,
207
+ relative_address : u32 ,
208
+ inline_depth : u16 ,
209
+ } ,
210
+ }
211
+
212
+ impl InternalFrameKeyVariant {
213
+ pub fn new_label ( name : ThreadInternalStringIndex ) -> Self {
214
+ InternalFrameKeyVariant :: Label {
215
+ name,
216
+ file_path : None ,
217
+ line : None ,
218
+ col : None ,
219
+ }
220
+ }
221
+ }
222
+
141
223
#[ derive( Debug , Clone , PartialOrd , Ord , PartialEq , Eq , Hash ) ]
142
- pub enum InternalFrameLocation {
143
- UnknownAddress ( u64 ) ,
144
- AddressInLib ( u32 , GlobalLibIndex ) ,
145
- Label ( ThreadInternalStringIndex ) ,
224
+ pub enum InternalFrameAddress {
225
+ Unknown ( u64 ) ,
226
+ InLib ( u32 , GlobalLibIndex ) ,
146
227
}
0 commit comments