summaryrefslogtreecommitdiff
path: root/cont.c
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2023-11-30 18:35:55 -0800
committerGitHub <[email protected]>2023-11-30 21:35:55 -0500
commitba1cdadfc8ad6f284efeefbcebef1ca85bae178c (patch)
treec9ea54db14ca957a0df99487b9be19c368908dca /cont.c
parent5888a16a125e573c1749000b343d41db76289c15 (diff)
YJIT: Cancel on-stack jit_return on invalidation (#9086)
* YJIT: Cancel on-stack jit_return on invalidation Co-authored-by: Alan Wu <[email protected]> * Use RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P --------- Co-authored-by: Alan Wu <[email protected]>
Diffstat (limited to 'cont.c')
-rw-r--r--cont.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/cont.c b/cont.c
index 621de351cb..6bafc07ca8 100644
--- a/cont.c
+++ b/cont.c
@@ -1290,18 +1290,37 @@ rb_jit_cont_each_iseq(rb_iseq_callback callback, void *data)
if (cont->ec->vm_stack == NULL)
continue;
- const rb_control_frame_t *cfp;
- for (cfp = RUBY_VM_END_CONTROL_FRAME(cont->ec) - 1; ; cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
- const rb_iseq_t *iseq;
- if (cfp->pc && (iseq = cfp->iseq) != NULL && imemo_type((VALUE)iseq) == imemo_iseq) {
- callback(iseq, data);
+ const rb_control_frame_t *cfp = cont->ec->cfp;
+ while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(cont->ec, cfp)) {
+ if (cfp->pc && cfp->iseq && imemo_type((VALUE)cfp->iseq) == imemo_iseq) {
+ callback(cfp->iseq, data);
}
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+ }
+ }
+}
+
+#if USE_YJIT
+// Update the jit_return of all CFPs to leave_exit unless it's leave_exception or not set.
+// This prevents jit_exec_exception from jumping to the caller after invalidation.
+void
+rb_yjit_cancel_jit_return(void *leave_exit, void *leave_exception)
+{
+ struct rb_jit_cont *cont;
+ for (cont = first_jit_cont; cont != NULL; cont = cont->next) {
+ if (cont->ec->vm_stack == NULL)
+ continue;
- if (cfp == cont->ec->cfp)
- break; // reached the most recent cfp
+ const rb_control_frame_t *cfp = cont->ec->cfp;
+ while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(cont->ec, cfp)) {
+ if (cfp->jit_return && cfp->jit_return != leave_exception) {
+ ((rb_control_frame_t *)cfp)->jit_return = leave_exit;
+ }
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
}
}
+#endif
// Finish working with jit_cont.
void