@@ -22,6 +22,7 @@ pub struct SnapshotGenerator<'a> {
22
22
nodes : Vec < Node > ,
23
23
nodes_map : HashMap < Address , NodeId > ,
24
24
edges : Vec < Edge > ,
25
+ edge_buffer : Vec < Edge > ,
25
26
strings : Vec < String > ,
26
27
strings_map : HashMap < String , StringId > ,
27
28
shape_name_map : HashMap < NodeId , StringId > ,
@@ -30,26 +31,30 @@ pub struct SnapshotGenerator<'a> {
30
31
empty_string_id : StringId ,
31
32
shape_edge_name_id : StringId ,
32
33
shape_type_name_id : StringId ,
34
+ length_name_id : StringId ,
33
35
vm : & ' a VM ,
34
36
}
35
37
36
38
impl < ' a > SnapshotGenerator < ' a > {
37
39
pub fn new ( vm : & ' a VM , path : PathBuf ) -> IoResult < SnapshotGenerator < ' a > > {
38
40
let f = File :: create ( path) ?;
39
41
let writer = BufWriter :: new ( f) ;
42
+ let placeholder = StringId ( 0 ) ;
40
43
41
44
Ok ( SnapshotGenerator {
42
45
writer,
43
46
nodes : Vec :: new ( ) ,
44
47
nodes_map : HashMap :: new ( ) ,
45
48
edges : Vec :: new ( ) ,
49
+ edge_buffer : Vec :: new ( ) ,
46
50
strings : Vec :: new ( ) ,
47
51
strings_map : HashMap :: new ( ) ,
48
52
shape_name_map : HashMap :: new ( ) ,
49
53
meta_space_start : vm. meta_space_start ( ) ,
50
- shape_edge_name_id : StringId ( 0 ) , // Will be initialized later.
51
- shape_type_name_id : StringId ( 0 ) ,
52
- empty_string_id : StringId ( 0 ) ,
54
+ shape_edge_name_id : placeholder, // Will be initialized later.
55
+ shape_type_name_id : placeholder,
56
+ empty_string_id : placeholder,
57
+ length_name_id : placeholder,
53
58
value_map : HashMap :: new ( ) ,
54
59
vm,
55
60
} )
@@ -70,6 +75,7 @@ impl<'a> SnapshotGenerator<'a> {
70
75
self . empty_string_id = self . ensure_string ( "" . to_string ( ) ) ;
71
76
self . shape_edge_name_id = self . ensure_string ( "shape" . to_string ( ) ) ;
72
77
self . shape_type_name_id = self . ensure_string ( "Shape" . to_string ( ) ) ;
78
+ self . length_name_id = self . ensure_string ( "length" . to_string ( ) ) ;
73
79
}
74
80
75
81
fn iterate_roots ( & mut self , threads : & [ Arc < DoraThread > ] ) {
@@ -121,7 +127,7 @@ impl<'a> SnapshotGenerator<'a> {
121
127
122
128
fn iterate_heap ( & mut self ) {
123
129
let swiper = self . vm . gc . collector ( ) . to_swiper ( ) ;
124
- swiper. iterate_heap ( self . vm , |address| self . process_object ( self . vm , address) ) ;
130
+ swiper. iterate_heap ( self . vm , |address| self . process_object ( address) ) ;
125
131
}
126
132
127
133
fn verify_snapshot ( & mut self ) {
@@ -140,7 +146,7 @@ impl<'a> SnapshotGenerator<'a> {
140
146
assert_eq ! ( self . edges. len( ) , edge_count) ;
141
147
}
142
148
143
- fn process_object ( & mut self , vm : & VM , address : Address ) {
149
+ fn process_object ( & mut self , address : Address ) {
144
150
let node_id = self . ensure_node ( address) ;
145
151
let object = address. to_obj ( ) ;
146
152
let size = object. size ( self . meta_space_start ) ;
@@ -151,27 +157,34 @@ impl<'a> SnapshotGenerator<'a> {
151
157
self . node_mut ( node_id) . first_edge = EdgeId ( self . edges . len ( ) ) ;
152
158
self . node_mut ( node_id) . self_size = size;
153
159
154
- let mut edge_count = 1 ;
155
- self . add_edge ( Edge {
160
+ let edge_start_idx = self . edge_buffer . len ( ) ;
161
+
162
+ self . edge_buffer . push ( Edge {
156
163
name_or_idx : self . shape_edge_name_id . 0 ,
157
164
to_node_index : shape_node_id,
158
165
kind : EdgeKind :: Property ,
159
166
} ) ;
160
167
161
- edge_count += match shape. kind ( ) {
168
+ let mut is_string = false ;
169
+
170
+ match shape. kind ( ) {
162
171
ShapeKind :: Class ( cls_id, type_params) => {
163
- self . process_class_object ( address, * cls_id, type_params, shape)
172
+ self . process_class_object ( address, * cls_id, type_params, shape) ;
164
173
}
165
174
ShapeKind :: Array ( cls_id, type_params) => {
166
- self . process_array_object ( address, * cls_id, type_params, shape)
175
+ self . process_array_object ( address, * cls_id, type_params, shape) ;
167
176
}
168
- ShapeKind :: String => 0 ,
169
- _ => 0 ,
170
- } ;
171
177
172
- self . node_mut ( node_id) . edge_count = edge_count;
178
+ ShapeKind :: String => {
179
+ is_string = true ;
180
+ }
181
+ _ => { }
182
+ }
173
183
174
- if std:: ptr:: eq ( vm. known . string_shape ( ) , shape) {
184
+ self . node_mut ( node_id) . edge_count = self . edge_buffer . len ( ) - edge_start_idx;
185
+ self . edges . extend ( self . edge_buffer . drain ( edge_start_idx..) ) ;
186
+
187
+ if is_string {
175
188
let value: String = Str :: cast ( object) . content_utf8 ( ) . into ( ) ;
176
189
self . node_mut ( node_id) . name = Some ( self . ensure_string ( value) ) ;
177
190
self . node_mut ( node_id) . kind = NodeKind :: String ;
@@ -256,8 +269,7 @@ impl<'a> SnapshotGenerator<'a> {
256
269
cls_id : ClassId ,
257
270
type_params : & BytecodeTypeArray ,
258
271
shape : & Shape ,
259
- ) -> usize {
260
- let mut edge_count = 0 ;
272
+ ) {
261
273
let class = self . vm . class ( cls_id) ;
262
274
263
275
for ( field_idx, field) in class. fields . iter ( ) . enumerate ( ) {
@@ -274,15 +286,12 @@ impl<'a> SnapshotGenerator<'a> {
274
286
} ;
275
287
276
288
let field_name_idx = self . ensure_string ( field_name) ;
277
- self . add_edge ( Edge {
289
+ self . edge_buffer . push ( Edge {
278
290
name_or_idx : field_name_idx. 0 ,
279
291
to_node_index : value_node_id,
280
292
kind : EdgeKind :: Property ,
281
293
} ) ;
282
- edge_count += 1 ;
283
294
}
284
-
285
- edge_count
286
295
}
287
296
288
297
fn process_value ( & mut self , value_address : Address , ty : & BytecodeType ) -> NodeId {
@@ -347,8 +356,7 @@ impl<'a> SnapshotGenerator<'a> {
347
356
_cls_id : ClassId ,
348
357
type_params : & BytecodeTypeArray ,
349
358
shape : & Shape ,
350
- ) -> usize {
351
- let mut edge_count = 0 ;
359
+ ) {
352
360
let array: Ref < Array < u8 > > = address. into ( ) ;
353
361
let length = array. len ( ) ;
354
362
@@ -359,18 +367,23 @@ impl<'a> SnapshotGenerator<'a> {
359
367
assert_eq ! ( type_params. len( ) , 1 ) ;
360
368
let ty = type_params[ 0 ] . clone ( ) ;
361
369
370
+ let length_id = self . ensure_value ( format ! ( "{}" , length) ) ;
371
+
372
+ self . edge_buffer . push ( Edge {
373
+ name_or_idx : self . length_name_id . 0 ,
374
+ to_node_index : length_id,
375
+ kind : EdgeKind :: Property ,
376
+ } ) ;
377
+
362
378
for element_idx in 0 ..length {
363
379
let element_node_id = self . process_value ( element_addr, & ty) ;
364
- self . add_edge ( Edge {
380
+ self . edge_buffer . push ( Edge {
365
381
name_or_idx : element_idx,
366
382
to_node_index : element_node_id,
367
383
kind : EdgeKind :: Element ,
368
384
} ) ;
369
- edge_count += 1 ;
370
385
element_addr = element_addr. offset ( element_size) ;
371
386
}
372
-
373
- edge_count
374
387
}
375
388
376
389
fn add_edge ( & mut self , edge : Edge ) -> EdgeId {
0 commit comments