зеркало из https://github.com/github/ruby.git
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@gmail.com>
This commit is contained in:
Родитель
62c1297e24
Коммит
684e84df7c
|
@ -656,6 +656,33 @@ assert_equal '[100, 299]', %q{
|
||||||
[bar(ins), bar(oth)]
|
[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
|
# get ivar on String
|
||||||
assert_equal '[nil, nil, 42, 42]', %q{
|
assert_equal '[nil, nil, 42, 42]', %q{
|
||||||
# @foo to exercise the getinstancevariable instruction
|
# @foo to exercise the getinstancevariable instruction
|
||||||
|
|
|
@ -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
|
// Eventually, we can encode whether an object is T_OBJECT or not
|
||||||
// inside object shapes.
|
// inside object shapes.
|
||||||
if (rb_get_alloc_func(comptime_val_klass) != rb_class_allocate_instance) {
|
if (rb_get_alloc_func(comptime_val_klass) != rb_class_allocate_instance) {
|
||||||
GEN_COUNTER_INC(cb, getivar_not_object);
|
// General case. Call rb_ivar_get(). No need to reconstruct interpreter
|
||||||
return YJIT_CANT_COMPILE;
|
// 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
|
RUBY_ASSERT(BUILTIN_TYPE(comptime_receiver) == T_OBJECT); // because we checked the allocator
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче