From 9a436da064b966c1278ac530c6d6f2d02b0636dc Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 15 Jul 2021 15:35:20 -0400 Subject: 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. --- bootstraptest/test_yjit.rb | 15 +++++++++++++++ yjit_codegen.c | 10 +++++----- 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); -- cgit v1.2.3