ruby-changes:69004
From: Alan <ko1@a...>
Date: Thu, 21 Oct 2021 08:19:39 +0900 (JST)
Subject: [ruby-changes:69004] 684e84df7c (master): Use rb_ivar_get() for general case of getivar (#17)
https://git.ruby-lang.org/ruby.git/commit/?id=684e84df7c From 684e84df7cdfd47d2b66d717369121337a2bd32d Mon Sep 17 00:00:00 2001 From: Alan Wu <XrXr@u...> Date: Thu, 29 Apr 2021 11:47:19 -0400 Subject: Use rb_ivar_get() for general case of getivar (#17) * Use rb_ivar_get() for general case of getivar Pretty straight forward. Buys about 1% coverage on railsbench. * Update yjit_codegen.c Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@g...> --- bootstraptest/test_yjit.rb | 27 +++++++++++++++++++++++++++ yjit_codegen.c | 23 +++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 6bf0f53e9e..6ac31f8134 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -656,6 +656,33 @@ assert_equal '[100, 299]', %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_yjit.rb#L656 [bar(ins), bar(oth)] } +# get ivar on object, then on hash +assert_equal '[42, 100]', %q{ + class Hash + attr_accessor :foo + end + + class A + attr_reader :foo + + def initialize + @foo = 42 + end + end + + def use(val) + val.foo + end + + + h = {} + h.foo = 100 + obj = A.new + + use(obj) + [use(obj), use(h)] +} + # get ivar on String assert_equal '[nil, nil, 42, 42]', %q{ # @foo to exercise the getinstancevariable instruction diff --git a/yjit_codegen.c b/yjit_codegen.c index ace2df622d..99e77fc82f 100644 --- a/yjit_codegen.c +++ b/yjit_codegen.c @@ -924,8 +924,27 @@ gen_get_ivar(jitstate_t *jit, ctx_t *ctx, const int max_chain_depth, VALUE compt https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L924 // Eventually, we can encode whether an object is T_OBJECT or not // inside object shapes. if (rb_get_alloc_func(comptime_val_klass) != rb_class_allocate_instance) { - GEN_COUNTER_INC(cb, getivar_not_object); - return YJIT_CANT_COMPILE; + // General case. Call rb_ivar_get(). No need to reconstruct interpreter + // state since the routine never raises exceptions or allocate objects + // visibile to Ruby. + // VALUE rb_ivar_get(VALUE obj, ID id) + ADD_COMMENT(cb, "call rb_ivar_get()"); + yjit_save_regs(cb); + mov(cb, C_ARG_REGS[0], REG0); + mov(cb, C_ARG_REGS[1], imm_opnd((int64_t)ivar_name)); + call_ptr(cb, REG1, (void *)rb_ivar_get); + yjit_load_regs(cb); + + if (!reg0_opnd.is_self) { + (void)ctx_stack_pop(ctx, 1); + } + // Push the ivar on the stack + x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, out_opnd, RAX); + + // Jump to next instruction. This allows guard chains to share the same successor. + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; } RUBY_ASSERT(BUILTIN_TYPE(comptime_receiver) == T_OBJECT); // because we checked the allocator -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/