summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2021-09-04 01:50:25 -0700
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:39 -0400
commitfd34c831f6f61691cb9f2d171c690c9769183437 (patch)
tree4566875028229396355da95403c5bf7a157c4be6
parentd098c5560b7ae43f6f6798bedd9561f80604986f (diff)
Allow special case of expandarray with nil
-rw-r--r--test/ruby/test_yjit.rb13
-rw-r--r--yjit_codegen.c11
2 files changed, 24 insertions, 0 deletions
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb
index 94989dae9e..ccd0e6bae0 100644
--- a/test/ruby/test_yjit.rb
+++ b/test/ruby/test_yjit.rb
@@ -136,6 +136,19 @@ class TestYJIT < Test::Unit::TestCase
RUBY
end
+ def test_expandarray
+ assert_compiles(<<~'RUBY', insns: %i[expandarray], result: [1, 2])
+ a, b = [1, 2]
+ RUBY
+ end
+
+ def test_expandarray_nil
+ assert_compiles(<<~'RUBY', insns: %i[expandarray], result: [nil, nil])
+ a, b = nil
+ [a, b]
+ RUBY
+ end
+
def test_compile_opt_getinlinecache
assert_compiles(<<~RUBY, insns: %i[opt_getinlinecache], result: 123, min_calls: 2)
def get_foo
diff --git a/yjit_codegen.c b/yjit_codegen.c
index f63166725a..9eff50b2e4 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -987,8 +987,19 @@ gen_expandarray(jitstate_t* jit, ctx_t* ctx)
// num is the number of requested values. If there aren't enough in the
// array then we're going to push on nils.
rb_num_t num = (rb_num_t) jit_get_arg(jit, 0);
+ val_type_t array_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
x86opnd_t array_opnd = ctx_stack_pop(ctx, 1);
+ if (array_type.type == ETYPE_NIL) {
+ // special case for a, b = nil pattern
+ // push N nils onto the stack
+ for (int i = 0; i < num; i++) {
+ x86opnd_t push = ctx_stack_push(ctx, TYPE_NIL);
+ mov(cb, push, imm_opnd(Qnil));
+ }
+ 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));