Skip to content

Commit

Permalink
Use rb_ivar_get() for general case of getivar (#17)
Browse files Browse the repository at this point in the history
* 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@gmail.com>
  • Loading branch information
XrXr and maximecb committed Oct 20, 2021
1 parent 37c1ccd commit 0f07fd7
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 2 deletions.
27 changes: 27 additions & 0 deletions bootstraptest/test_yjit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,33 @@ def bar(ins)
[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
Expand Down
23 changes: 21 additions & 2 deletions yjit_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -924,8 +924,27 @@ gen_get_ivar(jitstate_t *jit, ctx_t *ctx, const int max_chain_depth, VALUE compt
// 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

Expand Down

0 comments on commit 0f07fd7

Please sign in to comment.