|
| 1 | +// hotpatch has two requirements: |
| 2 | +// 1. the first instruction of a functin must be at least two bytes long |
| 3 | +// 2. there must not be a jump to the first instruction |
| 4 | + |
| 5 | +// the hotpatch flag should insert nops as needed to fullfil the requirements, |
| 6 | +// but only if the the function does not already fulfill them. |
| 7 | +// Over 99% of function in regular codebases already fulfill the conditions, |
| 8 | +// so its important to check that those are |
| 9 | +// unneccessarily affected |
| 10 | + |
| 11 | +// ------------------------------------------------------------------------------------------------ |
| 12 | + |
| 13 | +// regularly this tailcall would jump to the first instruction the function |
| 14 | +// CHECK-LABEL: <tailcall_fn>: |
| 15 | +// CHECK: jne 0x0 <tailcall_fn> |
| 16 | + |
| 17 | +// hotpatch insert nops so that the tailcall will not jump to the first instruction of the function |
| 18 | +// HOTPATCH-LABEL: <tailcall_fn>: |
| 19 | +// HOTPATCH-NOT: jne 0x0 <tailcall_fn> |
| 20 | + |
| 21 | +#[no_mangle] |
| 22 | +pub fn tailcall_fn() { |
| 23 | + use std::sync::atomic::{AtomicUsize, Ordering}; |
| 24 | + static COUNT: AtomicUsize = AtomicUsize::new(0); |
| 25 | + if COUNT.fetch_sub(1, Ordering::Relaxed) != 0 { |
| 26 | + tailcall_fn() |
| 27 | + } |
| 28 | +} |
| 29 | + |
| 30 | +// ------------------------------------------------------------------------------------------------ |
| 31 | + |
| 32 | +// empty_fn just returns. Note that 'ret' is a single byte instruction, but hotpatch requires a two |
| 33 | +// or more byte instructions to be at the start of the functions. |
| 34 | +// Preferably we would also tests a different single byte instruction, |
| 35 | +// but I was not able to make rustc emit anything but 'ret'. |
| 36 | + |
| 37 | +// CHECK-LABEL: <empty_fn>: |
| 38 | +// CHECK-NEXT: ret |
| 39 | + |
| 40 | +// HOTPATCH-LABEL: <empty_fn>: |
| 41 | +// HOTPATCH-NOT: ret |
| 42 | +// HOTPATCH: ret |
| 43 | + |
| 44 | +#[no_mangle] |
| 45 | +#[inline(never)] |
| 46 | +pub fn empty_fn() {} |
| 47 | + |
| 48 | +// ------------------------------------------------------------------------------------------------ |
| 49 | + |
| 50 | +// return_42 should not be affected by hotpatch |
| 51 | + |
| 52 | +// CHECK-LABEL: <return_42>: |
| 53 | +// CHECK-NEXT: 0: |
| 54 | +// CHECK-NEXT: ret |
| 55 | + |
| 56 | +// HOTPATCH-LABEL: <return_42>: |
| 57 | +// HOTPATCH-NEXT: 0: |
| 58 | +// HOTPATCH-NEXT: ret |
| 59 | + |
| 60 | +#[no_mangle] |
| 61 | +#[inline(never)] |
| 62 | +pub fn return_42() -> i32 { |
| 63 | + 42 |
| 64 | +} |
0 commit comments