diff options
author | Alan Wu <XrXr@users.noreply.github.com> | 2020-10-21 18:15:43 -0400 |
---|---|---|
committer | Alan Wu <XrXr@users.noreply.github.com> | 2021-10-20 18:19:25 -0400 |
commit | c2cb6a6fd38eea3ce91d3370a62aaf6ba15e410a (patch) | |
tree | 3f80a115ce4acbd279fd27606ff6695addd1496f | |
parent | d49edada2eeb0e2fa25c2f36c06e9836e9288f56 (diff) |
MicroJIT: Read pointer to call cache from call data
The call cache changes when the call site becomes polymophic and can
result in the generated code falsely assuming cd->cc->cme is not NULL.
Here is a crasher:
def body(thing)
thing.strip
end
str = ""
10.times { body(str) }
body(0) rescue p 'not found'
body(str)
-rw-r--r-- | ujit_compile.c | 17 |
1 files changed, 8 insertions, 9 deletions
diff --git a/ujit_compile.c b/ujit_compile.c index 4dd2c988b1..7beab133c0 100644 --- a/ujit_compile.c +++ b/ujit_compile.c @@ -563,12 +563,14 @@ gen_opt_send_without_block(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx) // Pointer to the klass field of the receiver &(recv->klass) x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass)); - // FIXME: currently assuming that cc->klass doesn't change - // Ideally we would like the GC to update the klass pointer - // - // Check if we have a cache hit - mov(cb, REG1, const_ptr_opnd((void*)cd->cc->klass)); - cmp(cb, REG1, klass_opnd); + // Load the call cache into REG1 + mov(cb, REG1, const_ptr_opnd(cd)); + x86opnd_t ptr_to_cc = member_opnd(REG1, struct rb_call_data, cc); + mov(cb, REG1, ptr_to_cc); + + // Check the class of the receiver against the call cache + mov(cb, REG0, klass_opnd); + cmp(cb, REG0, mem_opnd(64, REG1, offsetof(struct rb_callcache, klass))); jne_ptr(cb, side_exit); // NOTE: there *has to be* a way to optimize the entry invalidated check @@ -577,9 +579,6 @@ gen_opt_send_without_block(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx) // Check that the method entry is not invalidated // cd->cc->cme->flags // #define METHOD_ENTRY_INVALIDATED(me) ((me)->flags & IMEMO_FL_USER5) - mov(cb, REG1, const_ptr_opnd(cd)); - x86opnd_t ptr_to_cc = member_opnd(REG1, struct rb_call_data, cc); - mov(cb, REG1, ptr_to_cc); x86opnd_t ptr_to_cme_ = mem_opnd(64, REG1, offsetof(struct rb_callcache, cme_)); mov(cb, REG1, ptr_to_cme_); x86opnd_t flags_opnd = mem_opnd(64, REG1, offsetof(rb_callable_method_entry_t, flags)); |