@@ -7,11 +7,36 @@ use std::cmp::min;
77use std:: collections:: HashMap ;
88use std:: convert:: TryFrom ;
99use std:: hash:: { DefaultHasher , Hash , Hasher } ;
10+ use std:: sync:: RwLock ;
1011use std:: { fs:: File , io:: Write } ;
1112
1213use crate :: analyzer:: { StackAnalyzer , StackStatus } ;
1314use crate :: chunker:: Chunker ;
1415
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+
1540#[ derive( Clone , Debug , Hash ) ]
1641pub enum Block {
1742 Call ( u64 ) ,
@@ -36,8 +61,6 @@ pub struct StructuredScript {
3661 extra_endif_positions : Vec < usize > ,
3762 max_if_interval : ( usize , usize ) ,
3863 pub blocks : Vec < Block > ,
39- // TODO: It may be worth to lazy initialize the script_map
40- pub script_map : HashMap < u64 , StructuredScript > ,
4164}
4265
4366impl Hash for StructuredScript {
@@ -65,7 +88,6 @@ impl StructuredScript {
6588 extra_endif_positions : vec ! [ ] ,
6689 max_if_interval : ( 0 , 0 ) ,
6790 blocks,
68- script_map : HashMap :: new ( ) ,
6991 }
7092 }
7193
@@ -87,7 +109,9 @@ impl StructuredScript {
87109 if self . is_script_buf ( ) {
88110 match & self . blocks [ 0 ] {
89111 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+ }
91115 }
92116 } else {
93117 false
@@ -109,10 +133,7 @@ impl StructuredScript {
109133 assert ! ( current_pos <= position, "Target position not found" ) ;
110134 match block {
111135 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) ;
116137 if position >= current_pos && position < current_pos + called_script. len ( ) {
117138 return called_script. debug_info ( position - current_pos) ;
118139 }
@@ -259,8 +280,8 @@ impl StructuredScript {
259280 self . num_unclosed_ifs += data. num_unclosed_ifs ;
260281 let id = calculate_hash ( & data) ;
261282 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) ;
264285 self
265286 }
266287
@@ -270,10 +291,7 @@ impl StructuredScript {
270291 for block in self . blocks . as_slice ( ) {
271292 match block {
272293 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) ;
277295 // Check if the script with the hash id is in cache
278296 match cache. get ( id) {
279297 Some ( called_start) => {
@@ -329,6 +347,7 @@ impl StructuredScript {
329347 }
330348
331349 pub fn compile ( self ) -> ScriptBuf {
350+ println ! ( "starting compile step" ) ;
332351 let mut script = Vec :: with_capacity ( self . size ) ;
333352 let mut cache = HashMap :: new ( ) ;
334353 self . compile_to_bytes ( & mut script, & mut cache) ;
@@ -348,12 +367,8 @@ impl StructuredScript {
348367 File :: create ( "analyzed_chunk_stats.txt" ) . expect ( "Unable to create stats file" ) ;
349368 let chunk_stats = chunker. chunks . iter ( ) . map ( |chunk| chunk. stats . clone ( ) ) ;
350369 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" ) ;
357372 }
358373 let mut chunk_sizes_iter = chunk_sizes. iter ( ) ;
359374 let mut scripts = vec ! [ ] ;
@@ -397,19 +412,19 @@ impl StructuredScript {
397412 Some ( hint) => {
398413 hint. stack_changed = changed;
399414 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) ) ,
402417 }
403418 self
404419 }
405-
420+
406421 pub fn add_altstack_hint ( mut self , access : i32 , changed : i32 ) -> Self {
407422 match & mut self . stack_hint {
408423 Some ( hint) => {
409424 hint. altstack_changed = changed;
410425 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) ) ,
413428 }
414429 self
415430 }
0 commit comments