Skip to content

Commit 38c1519

Browse files
XrXrmaximecb
andauthored
Use rb_ivar_get() for general case of getivar (ruby#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@gmail.com>
1 parent e584708 commit 38c1519

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

bootstraptest/test_yjit.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,33 @@ def bar(ins)
656656
[bar(ins), bar(oth)]
657657
}
658658

659+
# get ivar on object, then on hash
660+
assert_equal '[42, 100]', %q{
661+
class Hash
662+
attr_accessor :foo
663+
end
664+
665+
class A
666+
attr_reader :foo
667+
668+
def initialize
669+
@foo = 42
670+
end
671+
end
672+
673+
def use(val)
674+
val.foo
675+
end
676+
677+
678+
h = {}
679+
h.foo = 100
680+
obj = A.new
681+
682+
use(obj)
683+
[use(obj), use(h)]
684+
}
685+
659686
# get ivar on String
660687
assert_equal '[nil, nil, 42, 42]', %q{
661688
# @foo to exercise the getinstancevariable instruction

yjit_codegen.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -922,8 +922,27 @@ gen_get_ivar(jitstate_t *jit, ctx_t *ctx, const int max_chain_depth, VALUE compt
922922
// Eventually, we can encode whether an object is T_OBJECT or not
923923
// inside object shapes.
924924
if (rb_get_alloc_func(comptime_val_klass) != rb_class_allocate_instance) {
925-
GEN_COUNTER_INC(cb, getivar_not_object);
926-
return YJIT_CANT_COMPILE;
925+
// General case. Call rb_ivar_get(). No need to reconstruct interpreter
926+
// state since the routine never raises exceptions or allocate objects
927+
// visibile to Ruby.
928+
// VALUE rb_ivar_get(VALUE obj, ID id)
929+
ADD_COMMENT(cb, "call rb_ivar_get()");
930+
yjit_save_regs(cb);
931+
mov(cb, C_ARG_REGS[0], REG0);
932+
mov(cb, C_ARG_REGS[1], imm_opnd((int64_t)ivar_name));
933+
call_ptr(cb, REG1, (void *)rb_ivar_get);
934+
yjit_load_regs(cb);
935+
936+
if (!reg0_opnd.is_self) {
937+
(void)ctx_stack_pop(ctx, 1);
938+
}
939+
// Push the ivar on the stack
940+
x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN);
941+
mov(cb, out_opnd, RAX);
942+
943+
// Jump to next instruction. This allows guard chains to share the same successor.
944+
jit_jump_to_next_insn(jit, ctx);
945+
return YJIT_END_BLOCK;
927946
}
928947
RUBY_ASSERT(BUILTIN_TYPE(comptime_receiver) == T_OBJECT); // because we checked the allocator
929948

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy