@@ -8,6 +8,7 @@ use std::str;
8
8
use walrus:: MemoryId ;
9
9
use walrus:: { ExportId , FunctionId , ImportId , Module } ;
10
10
use wasm_bindgen_shared:: struct_function_export_name;
11
+ use wasm_bindgen_threads_xform:: ThreadCounterAddr ;
11
12
12
13
mod incoming;
13
14
mod nonstandard;
@@ -32,6 +33,7 @@ struct Context<'a> {
32
33
descriptors : HashMap < String , Descriptor > ,
33
34
externref_enabled : bool ,
34
35
wasm_interface_types : bool ,
36
+ thread_counter_addr : Option < ThreadCounterAddr > ,
35
37
support_start : bool ,
36
38
}
37
39
@@ -47,6 +49,7 @@ pub fn process(
47
49
module : & mut Module ,
48
50
externref_enabled : bool ,
49
51
wasm_interface_types : bool ,
52
+ thread_counter_addr : Option < ThreadCounterAddr > ,
50
53
support_start : bool ,
51
54
) -> Result < ( NonstandardWitSectionId , WasmBindgenAuxId ) , Error > {
52
55
let mut storage = Vec :: new ( ) ;
@@ -66,6 +69,7 @@ pub fn process(
66
69
start_found : false ,
67
70
externref_enabled,
68
71
wasm_interface_types,
72
+ thread_counter_addr,
69
73
support_start,
70
74
} ;
71
75
cx. init ( ) ?;
@@ -476,22 +480,38 @@ impl<'a> Context<'a> {
476
480
return Ok ( ( ) ) ;
477
481
}
478
482
479
- let prev_start = match self . module . start {
480
- Some ( f) => f,
481
- None => {
482
- self . module . start = Some ( id) ;
483
- return Ok ( ( ) ) ;
484
- }
483
+ let prev_start = if let Some ( prev_start) = self . module . start {
484
+ // Note that we call the previous start function, if any, first. This is
485
+ // because the start function currently only shows up when it's injected
486
+ // through thread/externref transforms. These injected start functions
487
+ // need to happen before user code, so we always schedule them first.
488
+ let mut builder = walrus:: FunctionBuilder :: new ( & mut self . module . types , & [ ] , & [ ] ) ;
489
+ builder. func_body ( ) . call ( prev_start) ;
490
+ Some ( builder)
491
+ } else {
492
+ None
485
493
} ;
486
494
487
- // Note that we call the previous start function, if any, first. This is
488
- // because the start function currently only shows up when it's injected
489
- // through thread/externref transforms. These injected start functions
490
- // need to happen before user code, so we always schedule them first.
491
- let mut builder = walrus:: FunctionBuilder :: new ( & mut self . module . types , & [ ] , & [ ] ) ;
492
- builder. func_body ( ) . call ( prev_start) . call ( id) ;
493
- let new_start = builder. finish ( Vec :: new ( ) , & mut self . module . funcs ) ;
494
- self . module . start = Some ( new_start) ;
495
+ if let Some ( thread_counter_addr) = self . thread_counter_addr {
496
+ // If we support shared memory, we re-use the thread counter address to
497
+ // call the start function only once.
498
+ let mut builder = prev_start
499
+ . unwrap_or_else ( || walrus:: FunctionBuilder :: new ( & mut self . module . types , & [ ] , & [ ] ) ) ;
500
+
501
+ thread_counter_addr. wrap_start ( self . memory ( ) ?, builder. func_body ( ) , id) ;
502
+
503
+ self . module . start = Some ( builder. finish ( Vec :: new ( ) , & mut self . module . funcs ) ) ;
504
+ } else if let Some ( mut builder) = prev_start {
505
+ // If we don't support shared memory, we still have to call the start
506
+ // function if we had a previous start function.
507
+ builder. func_body ( ) . call ( id) ;
508
+ self . module . start = Some ( builder. finish ( Vec :: new ( ) , & mut self . module . funcs ) ) ;
509
+ } else {
510
+ // If we didn't have a previous start function and don't support shared memory,
511
+ // just add the start function.
512
+ self . module . start = Some ( id) ;
513
+ }
514
+
495
515
Ok ( ( ) )
496
516
}
497
517
0 commit comments