@@ -37,6 +37,7 @@ enum UnsafeMessage {
37
37
/// this message is sent.
38
38
JitFn {
39
39
instance_ptr : * const Instance < ' static > ,
40
+ trampoline_ptr : * const u8 ,
40
41
tx : mpsc:: Sender < * const u8 > ,
41
42
} ,
42
43
}
@@ -192,19 +193,19 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
192
193
loop {
193
194
match rx. recv ( ) . unwrap ( ) {
194
195
// lazy JIT compilation request - compile requested instance and return pointer to result
195
- UnsafeMessage :: JitFn { instance_ptr, tx } => {
196
- tx. send ( jit_fn ( instance_ptr) )
196
+ UnsafeMessage :: JitFn { instance_ptr, trampoline_ptr , tx } => {
197
+ tx. send ( jit_fn ( instance_ptr, trampoline_ptr ) )
197
198
. expect ( "jitted runtime hung up before response to lazy JIT request was sent" ) ;
198
199
}
199
200
}
200
201
}
201
202
}
202
203
203
204
#[ no_mangle]
204
- extern "C" fn __clif_jit_fn ( instance_ptr : * const Instance < ' static > ) -> * const u8 {
205
+ extern "C" fn __clif_jit_fn ( instance_ptr : * const Instance < ' static > , trampoline_ptr : * const u8 ) -> * const u8 {
205
206
// send the JIT request to the rustc thread, with a channel for the response
206
207
let ( tx, rx) = mpsc:: channel ( ) ;
207
- UnsafeMessage :: JitFn { instance_ptr, tx }
208
+ UnsafeMessage :: JitFn { instance_ptr, trampoline_ptr , tx }
208
209
. send ( )
209
210
. expect ( "rustc thread hung up before lazy JIT request was sent" ) ;
210
211
@@ -213,7 +214,7 @@ extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8
213
214
. expect ( "rustc thread hung up before responding to sent lazy JIT request" )
214
215
}
215
216
216
- fn jit_fn ( instance_ptr : * const Instance < ' static > ) -> * const u8 {
217
+ fn jit_fn ( instance_ptr : * const Instance < ' static > , trampoline_ptr : * const u8 ) -> * const u8 {
217
218
rustc_middle:: ty:: tls:: with ( |tcx| {
218
219
// lift is used to ensure the correct lifetime for instance.
219
220
let instance = tcx. lift ( unsafe { * instance_ptr } ) . unwrap ( ) ;
@@ -227,6 +228,17 @@ fn jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 {
227
228
let name = tcx. symbol_name ( instance) . name ;
228
229
let sig = crate :: abi:: get_function_sig ( tcx, jit_module. isa ( ) . triple ( ) , instance) ;
229
230
let func_id = jit_module. declare_function ( name, Linkage :: Export , & sig) . unwrap ( ) ;
231
+
232
+ let current_ptr = jit_module. read_got_entry ( func_id) ;
233
+
234
+ // If the function's GOT entry has already been updated to point at something other
235
+ // than the shim trampoline, don't re-jit but just return the new pointer instead.
236
+ // This does not need synchronization as this code is executed only by a sole rustc
237
+ // thread.
238
+ if current_ptr != trampoline_ptr {
239
+ return current_ptr;
240
+ }
241
+
230
242
jit_module. prepare_for_function_redefine ( func_id) . unwrap ( ) ;
231
243
232
244
let mut cx = crate :: CodegenCx :: new ( tcx, backend_config, jit_module. isa ( ) , false ) ;
@@ -321,7 +333,7 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In
321
333
Linkage :: Import ,
322
334
& Signature {
323
335
call_conv : module. target_config ( ) . default_call_conv ,
324
- params : vec ! [ AbiParam :: new( pointer_type) ] ,
336
+ params : vec ! [ AbiParam :: new( pointer_type) , AbiParam :: new ( pointer_type ) ] ,
325
337
returns : vec ! [ AbiParam :: new( pointer_type) ] ,
326
338
} ,
327
339
)
@@ -334,6 +346,7 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In
334
346
let mut builder_ctx = FunctionBuilderContext :: new ( ) ;
335
347
let mut trampoline_builder = FunctionBuilder :: new ( trampoline, & mut builder_ctx) ;
336
348
349
+ let trampoline_fn = module. declare_func_in_func ( func_id, trampoline_builder. func ) ;
337
350
let jit_fn = module. declare_func_in_func ( jit_fn, trampoline_builder. func ) ;
338
351
let sig_ref = trampoline_builder. func . import_signature ( sig) ;
339
352
@@ -343,7 +356,8 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In
343
356
344
357
trampoline_builder. switch_to_block ( entry_block) ;
345
358
let instance_ptr = trampoline_builder. ins ( ) . iconst ( pointer_type, instance_ptr as u64 as i64 ) ;
346
- let jitted_fn = trampoline_builder. ins ( ) . call ( jit_fn, & [ instance_ptr] ) ;
359
+ let trampoline_ptr = trampoline_builder. ins ( ) . func_addr ( pointer_type, trampoline_fn) ;
360
+ let jitted_fn = trampoline_builder. ins ( ) . call ( jit_fn, & [ instance_ptr, trampoline_ptr] ) ;
347
361
let jitted_fn = trampoline_builder. func . dfg . inst_results ( jitted_fn) [ 0 ] ;
348
362
let call_inst = trampoline_builder. ins ( ) . call_indirect ( sig_ref, jitted_fn, & fn_args) ;
349
363
let ret_vals = trampoline_builder. func . dfg . inst_results ( call_inst) . to_vec ( ) ;
0 commit comments