ruby-changes:69477
From: John <ko1@a...>
Date: Wed, 27 Oct 2021 23:55:57 +0900 (JST)
Subject: [ruby-changes:69477] a6104b392a (master): YJIT: Support newhash with values (#5029)
https://git.ruby-lang.org/ruby.git/commit/?id=a6104b392a From a6104b392ab347c323c93a51fb3b95c3c2cc9e8f Mon Sep 17 00:00:00 2001 From: John Hawthorn <john@h...> Date: Wed, 27 Oct 2021 07:55:43 -0700 Subject: YJIT: Support newhash with values (#5029) * YJIT: Implement newhash with values * YJIT: Add test of duphash * Fix compilation on macos/clang --- bootstraptest/test_yjit.rb | 10 ++++++++++ test/ruby/test_yjit.rb | 10 ++++++++++ yjit_codegen.c | 37 ++++++++++++++++++++++++++++--------- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index c94c710c4dd..0a3aa81860d 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -2278,3 +2278,13 @@ assert_equal '{:foo=>123}', %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_yjit.rb#L2278 foo foo } + +# newhash +assert_equal '{:foo=>2}', %q{ + def foo + {foo: 1+1} + end + + foo + foo +} diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index 9b26e6c37f2..7b8cde6c0cd 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -85,6 +85,16 @@ class TestYJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_yjit.rb#L85 assert_compiles('e = 5; (..e)', insns: %i[newrange], result: ..5) end + def test_compile_duphash + assert_compiles('{ two: 2 }', insns: %i[duphash], result: { two: 2 }) + end + + def test_compile_newhash + assert_compiles('{}', insns: %i[newhash], result: {}) + assert_compiles('{ two: 1 + 1 }', insns: %i[newhash], result: { two: 2 }) + assert_compiles('{ 1 + 1 => :two }', insns: %i[newhash], result: { 2 => :two }) + end + def test_compile_opt_nil_p assert_compiles('nil.nil?', insns: %i[opt_nil_p], result: true) assert_compiles('false.nil?', insns: %i[opt_nil_p], result: false) diff --git a/yjit_codegen.c b/yjit_codegen.c index 374786571c0..b0d799c0132 100644 --- a/yjit_codegen.c +++ b/yjit_codegen.c @@ -1078,23 +1078,42 @@ gen_expandarray(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1078 static codegen_status_t gen_newhash(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) { - rb_num_t n = (rb_num_t)jit_get_arg(jit, 0); + int32_t num = (int32_t)jit_get_arg(jit, 0); - if (n == 0) { - // Save the PC and SP because we are allocating - jit_prepare_routine_call(jit, ctx, REG0); + // Save the PC and SP because we are allocating + jit_prepare_routine_call(jit, ctx, REG0); - // val = rb_hash_new(); - call_ptr(cb, REG0, (void *)rb_hash_new); + if (num) { + // val = rb_hash_new_with_size(num / 2); + mov(cb, C_ARG_REGS[0], imm_opnd(num / 2)); + call_ptr(cb, REG0, (void *)rb_hash_new_with_size); + + // save the allocated hash as we want to push it after insertion + push(cb, RAX); + push(cb, RAX); // alignment + + // rb_hash_bulk_insert(num, STACK_ADDR_FROM_TOP(num), val); + mov(cb, C_ARG_REGS[0], imm_opnd(num)); + lea(cb, C_ARG_REGS[1], ctx_stack_opnd(ctx, num - 1)); + mov(cb, C_ARG_REGS[2], RAX); + call_ptr(cb, REG0, (void *)rb_hash_bulk_insert); + pop(cb, RAX); // alignment + pop(cb, RAX); + + ctx_stack_pop(ctx, num); x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_HASH); mov(cb, stack_ret, RAX); - - return YJIT_KEEP_COMPILING; } else { - return YJIT_CANT_COMPILE; + // val = rb_hash_new(); + call_ptr(cb, REG0, (void *)rb_hash_new); + + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_HASH); + mov(cb, stack_ret, RAX); } + + return YJIT_KEEP_COMPILING; } static codegen_status_t -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/