summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2021-07-15 15:35:20 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:37 -0400
commit9a436da064b966c1278ac530c6d6f2d02b0636dc (patch)
tree86ed8ad25318649369c22ca9d1168d25b86bebbe
parent1943b27fe9f7ad237a1c5119550d2d71958cf4cd (diff)
Ensure we guard the value before we return
Otherwise you can end up not implicitly calling `to_ary`, which if it has side-effects will result in different behavior.
-rw-r--r--bootstraptest/test_yjit.rb15
-rw-r--r--yjit_codegen.c10
2 files changed, 20 insertions, 5 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 9541be0570..725eca5eb5 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -1479,3 +1479,18 @@ assert_equal '2', %q{
expandarray_postarg
expandarray_postarg
}
+
+assert_equal '10', %q{
+ obj = Object.new
+ val = nil
+ obj.define_singleton_method(:to_ary) { val = 10; [] }
+
+ def expandarray_always_call_to_ary(object)
+ * = object
+ end
+
+ expandarray_always_call_to_ary(obj)
+ expandarray_always_call_to_ary(obj)
+
+ val
+}
diff --git a/yjit_codegen.c b/yjit_codegen.c
index efafb68665..f126407dc8 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -774,16 +774,16 @@ gen_expandarray(jitstate_t* jit, ctx_t* ctx)
rb_num_t num = (rb_num_t) jit_get_arg(jit, 0);
x86opnd_t array_opnd = ctx_stack_pop(ctx, 1);
- // If we don't actually want any values, then just return.
- if (num == 0) {
- return YJIT_KEEP_COMPILING;
- }
-
// Move the array from the stack into REG0 and check that it's an array.
mov(cb, REG0, array_opnd);
guard_object_is_heap(cb, REG0, ctx, COUNTED_EXIT(side_exit, expandarray_not_array));
guard_object_is_array(cb, REG0, REG1, ctx, COUNTED_EXIT(side_exit, expandarray_not_array));
+ // If we don't actually want any values, then just return.
+ if (num == 0) {
+ return YJIT_KEEP_COMPILING;
+ }
+
// Pull out the embed flag to check if it's an embedded array.
x86opnd_t flags_opnd = member_opnd(REG0, struct RBasic, flags);
mov(cb, REG1, flags_opnd);