ruby-changes:69133
From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:20:57 +0900 (JST)
Subject: [ruby-changes:69133] b3e993a64b (master): Make sure that there is always an index table entry for getivars
https://git.ruby-lang.org/ruby.git/commit/?id=b3e993a64b From b3e993a64bb10e20280a7a5c604f9f0fe3939a4b Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...> Date: Wed, 25 Aug 2021 16:10:05 -0400 Subject: Make sure that there is always an index table entry for getivars --- yjit_codegen.c | 125 +++++++++++++++++++++++++++++---------------------------- yjit_iface.h | 1 - 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/yjit_codegen.c b/yjit_codegen.c index a5f39d273b..aaac15b1cb 100644 --- a/yjit_codegen.c +++ b/yjit_codegen.c @@ -1442,82 +1442,83 @@ 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#L1442 struct rb_iv_index_tbl_entry *ent; struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(comptime_receiver); - // Lookup index for the ivar the instruction loads - if (iv_index_tbl && rb_iv_index_tbl_lookup(iv_index_tbl, id, &ent)) { - uint32_t ivar_index = ent->index; + // Make sure there is a mapping for this ivar in the index table + if (!iv_index_tbl || !rb_iv_index_tbl_lookup(iv_index_tbl, id, &ent)) { + rb_ivar_set(comptime_receiver, id, Qundef); + iv_index_tbl = ROBJECT_IV_INDEX_TBL(comptime_receiver); + RUBY_ASSERT(iv_index_tbl && rb_iv_index_tbl_lookup(iv_index_tbl, id, &ent)); + } - // Pop receiver if it's on the temp stack - if (!reg0_opnd.is_self) { - (void)ctx_stack_pop(ctx, 1); - } + uint32_t ivar_index = ent->index; - // Compile time self is embedded and the ivar index lands within the object - if (RB_FL_TEST_RAW(comptime_receiver, ROBJECT_EMBED) && ivar_index < ROBJECT_EMBED_LEN_MAX) { - // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h + // Pop receiver if it's on the temp stack + if (!reg0_opnd.is_self) { + (void)ctx_stack_pop(ctx, 1); + } - // Guard that self is embedded - // TODO: BT and JC is shorter - ADD_COMMENT(cb, "guard embedded getivar"); - x86opnd_t flags_opnd = member_opnd(REG0, struct RBasic, flags); - test(cb, flags_opnd, imm_opnd(ROBJECT_EMBED)); - jit_chain_guard(JCC_JZ, jit, &starting_context, max_chain_depth, side_exit); + // Compile time self is embedded and the ivar index lands within the object + if (RB_FL_TEST_RAW(comptime_receiver, ROBJECT_EMBED) && ivar_index < ROBJECT_EMBED_LEN_MAX) { + // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h - // Load the variable - x86opnd_t ivar_opnd = mem_opnd(64, REG0, offsetof(struct RObject, as.ary) + ivar_index * SIZEOF_VALUE); - mov(cb, REG1, ivar_opnd); + // Guard that self is embedded + // TODO: BT and JC is shorter + ADD_COMMENT(cb, "guard embedded getivar"); + x86opnd_t flags_opnd = member_opnd(REG0, struct RBasic, flags); + test(cb, flags_opnd, imm_opnd(ROBJECT_EMBED)); + jit_chain_guard(JCC_JZ, jit, &starting_context, max_chain_depth, side_exit); - // Guard that the variable is not Qundef - cmp(cb, REG1, imm_opnd(Qundef)); - mov(cb, REG0, imm_opnd(Qnil)); - cmove(cb, REG1, REG0); + // Load the variable + x86opnd_t ivar_opnd = mem_opnd(64, REG0, offsetof(struct RObject, as.ary) + ivar_index * SIZEOF_VALUE); + mov(cb, REG1, ivar_opnd); - // Push the ivar on the stack - x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN); - mov(cb, out_opnd, REG1); - } - else { - // Compile time value is *not* embeded. + // Guard that the variable is not Qundef + cmp(cb, REG1, imm_opnd(Qundef)); + mov(cb, REG0, imm_opnd(Qnil)); + cmove(cb, REG1, REG0); - // Guard that value is *not* embedded - // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h - ADD_COMMENT(cb, "guard extended getivar"); - x86opnd_t flags_opnd = member_opnd(REG0, struct RBasic, flags); - test(cb, flags_opnd, imm_opnd(ROBJECT_EMBED)); - jit_chain_guard(JCC_JNZ, jit, &starting_context, max_chain_depth, side_exit); - - // check that the extended table is big enough - if (ivar_index >= ROBJECT_EMBED_LEN_MAX + 1) { - // Check that the slot is inside the extended table (num_slots > index) - x86opnd_t num_slots = mem_opnd(32, REG0, offsetof(struct RObject, as.heap.numiv)); - cmp(cb, num_slots, imm_opnd(ivar_index)); - jle_ptr(cb, COUNTED_EXIT(side_exit, getivar_idx_out_of_range)); - } + // Push the ivar on the stack + x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, out_opnd, REG1); + } + else { + // Compile time value is *not* embeded. - // Get a pointer to the extended table - x86opnd_t tbl_opnd = mem_opnd(64, REG0, offsetof(struct RObject, as.heap.ivptr)); - mov(cb, REG0, tbl_opnd); + // Guard that value is *not* embedded + // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h + ADD_COMMENT(cb, "guard extended getivar"); + x86opnd_t flags_opnd = member_opnd(REG0, struct RBasic, flags); + test(cb, flags_opnd, imm_opnd(ROBJECT_EMBED)); + jit_chain_guard(JCC_JNZ, jit, &starting_context, max_chain_depth, side_exit); + + // check that the extended table is big enough + if (ivar_index >= ROBJECT_EMBED_LEN_MAX + 1) { + // Check that the slot is inside the extended table (num_slots > index) + x86opnd_t num_slots = mem_opnd(32, REG0, offsetof(struct RObject, as.heap.numiv)); + cmp(cb, num_slots, imm_opnd(ivar_index)); + jle_ptr(cb, COUNTED_EXIT(side_exit, getivar_idx_out_of_range)); + } - // Read the ivar from the extended table - x86opnd_t ivar_opnd = mem_opnd(64, REG0, sizeof(VALUE) * ivar_index); - mov(cb, REG0, ivar_opnd); + // Get a pointer to the extended table + x86opnd_t tbl_opnd = mem_opnd(64, REG0, offsetof(struct RObject, as.heap.ivptr)); + mov(cb, REG0, tbl_opnd); - // Check that the ivar is not Qundef - cmp(cb, REG0, imm_opnd(Qundef)); - mov(cb, REG1, imm_opnd(Qnil)); - cmove(cb, REG0, REG1); + // Read the ivar from the extended table + x86opnd_t ivar_opnd = mem_opnd(64, REG0, sizeof(VALUE) * ivar_index); + mov(cb, REG0, ivar_opnd); - // Push the ivar on the stack - x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN); - mov(cb, out_opnd, REG0); - } + // Check that the ivar is not Qundef + cmp(cb, REG0, imm_opnd(Qundef)); + mov(cb, REG1, imm_opnd(Qnil)); + cmove(cb, REG0, REG1); - // Jump to next instruction. This allows guard chains to share the same successor. - jit_jump_to_next_insn(jit, ctx); - return YJIT_END_BLOCK; + // Push the ivar on the stack + x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, out_opnd, REG0); } - GEN_COUNTER_INC(cb, getivar_name_not_mapped); - return YJIT_CANT_COMPILE; + // Jump to next instruction. This allows guard chains to share the same successor. + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; } static codegen_status_t diff --git a/yjit_iface.h b/yjit_iface.h index 6f7aa69cea..c253153321 100644 --- a/yjit_iface.h +++ b/yjit_iface.h @@ -69,7 +69,6 @@ YJIT_DECLARE_COUNTERS( https://github.com/ruby/ruby/blob/trunk/yjit_iface.h#L69 getivar_se_self_not_heap, getivar_idx_out_of_range, - getivar_name_not_mapped, setivar_se_self_not_heap, setivar_idx_out_of_range, -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/