File tree 1 file changed +23
-3
lines changed
1 file changed +23
-3
lines changed Original file line number Diff line number Diff line change @@ -317,9 +317,29 @@ impl<T: FromWasmAbi + 'static> Deref for JsStatic<T> {
317
317
type Target = T ;
318
318
fn deref ( & self ) -> & T {
319
319
unsafe {
320
- ( * self . __inner . get ( ) ) . get_or_insert_with ( || {
321
- ( self . __init ) ( )
322
- } )
320
+ // Ideally we want to use `get_or_insert_with` here but
321
+ // unfortunately that has subpar codegen for now.
322
+ //
323
+ // If we get past the `Some` branch here LLVM statically
324
+ // knows that we're `None`, but the after the call to the `__init`
325
+ // function LLVM can no longer know this because `__init` could
326
+ // recursively call this function again (aka if JS came back to Rust
327
+ // and Rust referenced this static).
328
+ //
329
+ // We know, however, that cannot happen. As a result we can
330
+ // conclude that even after the call to `__init` our `ptr` still
331
+ // points to `None` (and a debug assertion to this effect). Then
332
+ // using `ptr::write` should tell rustc to not run destuctors
333
+ // (as one isn't there) and this should tighten up codegen for
334
+ // `JsStatic` a bit as well.
335
+ let ptr = self . __inner . get ( ) ;
336
+ if let Some ( ref t) = * ptr {
337
+ return t
338
+ }
339
+ let init = Some ( ( self . __init ) ( ) ) ;
340
+ debug_assert ! ( ( * ptr) . is_none( ) ) ;
341
+ ptr:: write ( ptr, init) ;
342
+ ( * ptr) . as_ref ( ) . unwrap ( )
323
343
}
324
344
}
325
345
}
You can’t perform that action at this time.
0 commit comments