@@ -7,11 +7,36 @@ use std::cmp::min;
7
7
use std:: collections:: HashMap ;
8
8
use std:: convert:: TryFrom ;
9
9
use std:: hash:: { DefaultHasher , Hash , Hasher } ;
10
+ use std:: sync:: RwLock ;
10
11
use std:: { fs:: File , io:: Write } ;
11
12
12
13
use crate :: analyzer:: { StackAnalyzer , StackStatus } ;
13
14
use crate :: chunker:: Chunker ;
14
15
16
+ // One global script map per thread.
17
+ thread_local ! {
18
+ static SCRIPT_MAP : RwLock <HashMap <u64 , Box <StructuredScript >>> =
19
+ RwLock :: new( HashMap :: new( ) ) ;
20
+ }
21
+
22
+ pub ( crate ) fn thread_add_script ( id : u64 , script : StructuredScript ) {
23
+ SCRIPT_MAP . with ( |script_map| {
24
+ let mut map = script_map. write ( ) . unwrap ( ) ;
25
+ if !map. contains_key ( & id) {
26
+ map. insert ( id, Box :: new ( script) ) ;
27
+ }
28
+ } ) ;
29
+ }
30
+
31
+ pub ( crate ) fn thread_get_script ( id : & u64 ) -> Box < StructuredScript > {
32
+ SCRIPT_MAP . with ( |script_map| {
33
+ let map = script_map. read ( ) . unwrap ( ) ;
34
+ map. get ( id)
35
+ . expect ( "script id not found in SCRIPT_MAP" )
36
+ . clone ( )
37
+ } )
38
+ }
39
+
15
40
#[ derive( Clone , Debug , Hash ) ]
16
41
pub enum Block {
17
42
Call ( u64 ) ,
@@ -36,8 +61,6 @@ pub struct StructuredScript {
36
61
extra_endif_positions : Vec < usize > ,
37
62
max_if_interval : ( usize , usize ) ,
38
63
pub blocks : Vec < Block > ,
39
- // TODO: It may be worth to lazy initialize the script_map
40
- pub script_map : HashMap < u64 , StructuredScript > ,
41
64
}
42
65
43
66
impl Hash for StructuredScript {
@@ -65,7 +88,6 @@ impl StructuredScript {
65
88
extra_endif_positions : vec ! [ ] ,
66
89
max_if_interval : ( 0 , 0 ) ,
67
90
blocks,
68
- script_map : HashMap :: new ( ) ,
69
91
}
70
92
}
71
93
@@ -87,7 +109,9 @@ impl StructuredScript {
87
109
if self . is_script_buf ( ) {
88
110
match & self . blocks [ 0 ] {
89
111
Block :: Call ( _) => unreachable ! ( ) ,
90
- Block :: Script ( block_script) => block_script. instructions ( ) . collect :: < Vec < _ > > ( ) . len ( ) == 1 ,
112
+ Block :: Script ( block_script) => {
113
+ block_script. instructions ( ) . collect :: < Vec < _ > > ( ) . len ( ) == 1
114
+ }
91
115
}
92
116
} else {
93
117
false
@@ -109,10 +133,7 @@ impl StructuredScript {
109
133
assert ! ( current_pos <= position, "Target position not found" ) ;
110
134
match block {
111
135
Block :: Call ( id) => {
112
- let called_script = self
113
- . script_map
114
- . get ( id)
115
- . expect ( "Missing entry for a called script" ) ;
136
+ let called_script = thread_get_script ( id) ;
116
137
if position >= current_pos && position < current_pos + called_script. len ( ) {
117
138
return called_script. debug_info ( position - current_pos) ;
118
139
}
@@ -259,8 +280,8 @@ impl StructuredScript {
259
280
self . num_unclosed_ifs += data. num_unclosed_ifs ;
260
281
let id = calculate_hash ( & data) ;
261
282
self . blocks . push ( Block :: Call ( id) ) ;
262
- // Register script
263
- self . script_map . entry ( id) . or_insert ( data) ;
283
+ // Register script in the global script map
284
+ thread_add_script ( id, data) ;
264
285
self
265
286
}
266
287
@@ -270,10 +291,7 @@ impl StructuredScript {
270
291
for block in self . blocks . as_slice ( ) {
271
292
match block {
272
293
Block :: Call ( id) => {
273
- let called_script = self
274
- . script_map
275
- . get ( id)
276
- . expect ( "Missing entry for a called script" ) ;
294
+ let called_script = thread_get_script ( id) ;
277
295
// Check if the script with the hash id is in cache
278
296
match cache. get ( id) {
279
297
Some ( called_start) => {
@@ -329,6 +347,7 @@ impl StructuredScript {
329
347
}
330
348
331
349
pub fn compile ( self ) -> ScriptBuf {
350
+ println ! ( "starting compile step" ) ;
332
351
let mut script = Vec :: with_capacity ( self . size ) ;
333
352
let mut cache = HashMap :: new ( ) ;
334
353
self . compile_to_bytes ( & mut script, & mut cache) ;
@@ -348,12 +367,8 @@ impl StructuredScript {
348
367
File :: create ( "analyzed_chunk_stats.txt" ) . expect ( "Unable to create stats file" ) ;
349
368
let chunk_stats = chunker. chunks . iter ( ) . map ( |chunk| chunk. stats . clone ( ) ) ;
350
369
for entry in chunk_stats {
351
- writeln ! (
352
- stats_file,
353
- "{:?}" ,
354
- entry. stack_input_size
355
- )
356
- . expect ( "Unable to write to stats file" ) ;
370
+ writeln ! ( stats_file, "{:?}" , entry. stack_input_size)
371
+ . expect ( "Unable to write to stats file" ) ;
357
372
}
358
373
let mut chunk_sizes_iter = chunk_sizes. iter ( ) ;
359
374
let mut scripts = vec ! [ ] ;
@@ -397,19 +412,19 @@ impl StructuredScript {
397
412
Some ( hint) => {
398
413
hint. stack_changed = changed;
399
414
hint. deepest_stack_accessed = access;
400
- } ,
401
- None => self . stack_hint = Some ( StackAnalyzer :: plain_stack_status ( access, changed) )
415
+ }
416
+ None => self . stack_hint = Some ( StackAnalyzer :: plain_stack_status ( access, changed) ) ,
402
417
}
403
418
self
404
419
}
405
-
420
+
406
421
pub fn add_altstack_hint ( mut self , access : i32 , changed : i32 ) -> Self {
407
422
match & mut self . stack_hint {
408
423
Some ( hint) => {
409
424
hint. altstack_changed = changed;
410
425
hint. deepest_altstack_accessed = access;
411
- } ,
412
- None => self . stack_hint = Some ( StackAnalyzer :: plain_stack_status ( access, changed) )
426
+ }
427
+ None => self . stack_hint = Some ( StackAnalyzer :: plain_stack_status ( access, changed) ) ,
413
428
}
414
429
self
415
430
}
0 commit comments