summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2021-07-29 12:41:59 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:38 -0400
commitf4f940e5a63e542a59fc7510332efb38ccafc10f (patch)
tree3f62b55ef5c5e153d46cd80fd93ed49f196b0e34
parentb91078ea743fda959ad42f17562c4f3091bcf585 (diff)
Save PC and SP before accessing globals
These instructions are marked as not leaf in insns.def, which indicate that they could raise exceptions and/or call Ruby methods.
-rw-r--r--bootstraptest/test_yjit.rb32
-rw-r--r--yjit_codegen.c13
2 files changed, 43 insertions, 2 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 1a683c1c41..a164b7a413 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -7,6 +7,19 @@ assert_equal 'string', %q{
foo
}
+# Check that exceptions work when setting global variables
+assert_equal 'rescued', %q{
+ def set_var
+ $var = 100
+ rescue
+ :rescued
+ end
+
+ set_var
+ trace_var(:$var) { raise }
+ set_var
+}
+
# Check that global variables work
assert_equal 'string', %q{
$foo = "string"
@@ -18,6 +31,25 @@ assert_equal 'string', %q{
foo
}
+# Check that exceptions work when getting global variable
+assert_equal 'rescued', %q{
+ module Warning
+ def warn(message)
+ raise
+ end
+ end
+
+ def get_var
+ $=
+ rescue
+ :rescued
+ end
+
+ $VERBOSE = true
+ get_var
+ get_var
+}
+
# Check that global tracepoints work
assert_equal 'true', %q{
def foo
diff --git a/yjit_codegen.c b/yjit_codegen.c
index 3658d208fa..5d05cce365 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -149,7 +149,7 @@ jit_type_of_value(VALUE val)
// Save the incremented PC on the CFP
// This is necessary when calleees can raise or allocate
-void
+static void
jit_save_pc(jitstate_t* jit, x86opnd_t scratch_reg)
{
mov(cb, scratch_reg, const_ptr_opnd(jit->pc + insn_len(jit->opcode)));
@@ -160,7 +160,7 @@ jit_save_pc(jitstate_t* jit, x86opnd_t scratch_reg)
// This realigns the interpreter SP with the JIT SP
// Note: this will change the current value of REG_SP,
// which could invalidate memory operands
-void
+static void
jit_save_sp(jitstate_t* jit, ctx_t* ctx)
{
if (ctx->sp_offset != 0) {
@@ -3431,6 +3431,10 @@ gen_getglobal(jitstate_t* jit, ctx_t* ctx)
{
ID gid = jit_get_arg(jit, 0);
+ // Save the PC and SP because we might make a Ruby call for warning
+ jit_save_pc(jit, REG0);
+ jit_save_sp(jit, ctx);
+
// Save YJIT registers
yjit_save_regs(cb);
@@ -3452,6 +3456,11 @@ gen_setglobal(jitstate_t* jit, ctx_t* ctx)
{
ID gid = jit_get_arg(jit, 0);
+ // Save the PC and SP because we might make a Ruby call for
+ // Kernel#set_trace_var
+ jit_save_pc(jit, REG0);
+ jit_save_sp(jit, ctx);
+
// Save YJIT registers
yjit_save_regs(cb);