Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Control point control flow #1481

Closed
wants to merge 14 commits into from
63 changes: 63 additions & 0 deletions tests/c/early_return.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Run-time:
// env-var: YKD_LOG_IR=-:jit-post-opt
// env-var: YKD_SERIALISE_COMPILATION=1
// env-var: YK_LOG=4
// stderr:
// 3
// 2
// yk-jit-event: start-tracing
// 1
// yk-jit-event: stop-tracing-early-return
// return
// yk-jit-event: start-tracing
// 3
// yk-jit-event: stop-tracing
// --- Begin jit-pre-opt ---
// ...
// --- End jit-pre-opt ---
// exit

// Check that basic trace compilation works.

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <yk.h>
#include <yk_testing.h>

void loop(YkMT *, YkLocation *);

void loop(YkMT *mt, YkLocation *loc) {
int res = 9998;
int i = 3;
NOOPT_VAL(res);
NOOPT_VAL(i);
while (i > 0) {
yk_mt_control_point(mt, loc);
fprintf(stderr, "%d\n", i);
i--;
}
yk_mt_early_return(mt);
fprintf(stderr, "return\n");
NOOPT_VAL(res);
}

int main(int argc, char **argv) {
YkMT *mt = yk_mt_new(NULL);
yk_mt_hot_threshold_set(mt, 2);
YkLocation loc = yk_location_new();

int res = 9998;
int i = 4;
NOOPT_VAL(loc);
NOOPT_VAL(res);
NOOPT_VAL(i);
loop(mt, &loc);
loop(mt, &loc);
fprintf(stderr, "exit\n");
NOOPT_VAL(res);
yk_location_drop(loc);
yk_mt_shutdown(mt);
return (EXIT_SUCCESS);
}
1 change: 0 additions & 1 deletion tests/c/fcmp_double.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Run-time:
// env-var: YKD_LOG_IR=aot,jit-pre-opt,jit-asm
// env-var: YKD_SERIALISE_COMPILATION=1
// env-var: YK_LOG=4
// stderr:
Expand Down
1 change: 0 additions & 1 deletion tests/c/fcmp_float.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Run-time:
// env-var: YKD_LOG_IR=aot,jit-pre-opt,jit-asm
// env-var: YKD_SERIALISE_COMPILATION=1
// env-var: YK_LOG=4
// stderr:
Expand Down
63 changes: 63 additions & 0 deletions tests/c/recursive.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Run-time:
// env-var: YKD_LOG_IR=-:jit-pre-opt,jit-post-opt
// env-var: YKD_SERIALISE_COMPILATION=1
// env-var: YK_LOG=4
// stderr:
// 3
// 2
// yk-jit-event: start-tracing
// 1
// yk-jit-event: stop-tracing-early-return
// return
// yk-jit-event: start-tracing
// 3
// yk-jit-event: stop-tracing
// --- Begin jit-pre-opt ---
// ...
// --- End jit-pre-opt ---
// exit

// Check that basic trace compilation works.

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <yk.h>
#include <yk_testing.h>

int loop(YkMT *, YkLocation *, int);

int loop(YkMT *mt, YkLocation *loc, int i) {
int res = 9998;
NOOPT_VAL(res);
NOOPT_VAL(i);
while (i > 0) {
yk_mt_control_point(mt, loc);
if (i > 2) {
loop(mt, loc, i - 1);
}
fprintf(stderr, "%d\n", i);
i--;
}
yk_mt_early_return(mt);
fprintf(stderr, "return\n");
NOOPT_VAL(res);
return i;
}

int main(int argc, char **argv) {
YkMT *mt = yk_mt_new(NULL);
yk_mt_hot_threshold_set(mt, 2);
YkLocation loc = yk_location_new();

int res = 9998;
NOOPT_VAL(loc);
NOOPT_VAL(res);
loop(mt, &loc, 3);
fprintf(stderr, "exit\n");
NOOPT_VAL(res);
yk_location_drop(loc);
yk_mt_shutdown(mt);
return (EXIT_SUCCESS);
}
7 changes: 7 additions & 0 deletions ykcapi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ pub extern "C" fn yk_mt_control_point(_mt: *mut MT, _loc: *mut Location) {
// Intentionally empty.
}

#[no_mangle]
pub extern "C" fn __yk_mt_early_return(mt: *mut MT, frameaddr: *mut c_void) {
let mt = unsafe { &*mt };
let arc = unsafe { Arc::from_raw(mt) };
arc.early_return(frameaddr);
}

// The new control point called after the interpreter has been patched by ykllvm.
#[cfg(target_arch = "x86_64")]
#[naked]
Expand Down
16 changes: 16 additions & 0 deletions ykcapi/yk.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ void yk_mt_shutdown(YkMT *);
// execute JITted code.
void yk_mt_control_point(YkMT *, YkLocation *);

// At each point a function containing a control point can exit "early" this
// function must be called. "Early" includes, but is not
// limited to, the following:
//
// 1. Immediately after a non-infinite loop containing a call to
// `yk_mt_control_point`.
// 2. Immediately before `return` statements in code reachable from a
// `yk_mt_control_point`.
//
// Failure to call this function will lead to undefined behaviour.
# define yk_mt_early_return(mt) __yk_mt_early_return(mt, __builtin_frame_address(0))

// This is an internal function to yk: calling it directly leads to undefined
// behaviour.
void __yk_mt_early_return(YkMT *, void *);

// Set the threshold at which `YkLocation`'s are considered hot.
void yk_mt_hot_threshold_set(YkMT *, YkHotThreshold);

Expand Down
4 changes: 2 additions & 2 deletions ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fn running_trace(gidxs: &[usize]) -> Arc<X64CompiledTrace> {
/// * glen - Length for list in `gptr`.
#[no_mangle]
pub(crate) extern "C" fn __yk_deopt(
frameaddr: *const c_void,
frameaddr: *mut c_void,
gidx: u64,
gp_regs: &[u64; 16],
fp_regs: &[u64; 16],
Expand Down Expand Up @@ -320,7 +320,7 @@ pub(crate) extern "C" fn __yk_deopt(

// The `clone` should really be `Arc::clone(&ctr)` but that doesn't play well with type
// inference in this (unusual) case.
ctr.mt.guard_failure(ctr.clone(), gidx);
ctr.mt.guard_failure(ctr.clone(), gidx, frameaddr);

// Since we won't return from this function, drop `ctr` manually.
drop(ctr);
Expand Down
Loading