mirror of
https://github.com/ruby/ruby.git
synced 2026-11-08 01:20:26 +08:00
eliminate cross-TU calls to rb_vm_empty_cc()
rb_vm_empty_cc(), rb_vm_empty_cc_for_super() and rb_vm_uncached_cc() shouldn't be real function calls. rb_iseq_mark_and_move was calling these as real functions in a loop.
This commit is contained in:
parent
ae2c6841c4
commit
25eb737f03
Notes:
git
2026-10-27 13:49:56 +00:00
6
iseq.c
6
iseq.c
@ -433,8 +433,8 @@ rb_iseq_mark_and_move(const struct rb_gc_mark_ctx *ctx, rb_iseq_t *iseq, bool re
|
||||
if (cds[i].ci) rb_gc_mark_and_move_ptr_ctx(ctx, &cds[i].ci);
|
||||
|
||||
const struct rb_callcache *cc = cds[i].cc;
|
||||
if (!cc || cc == rb_vm_empty_cc() || cc == rb_vm_empty_cc_for_super() ||
|
||||
cc == rb_vm_uncached_cc()) {
|
||||
if (!cc || cc == &rb_vm_empty_cc || cc == &rb_vm_empty_cc_for_super ||
|
||||
cc == &rb_vm_uncached_cc) {
|
||||
// No need for marking, reference updating, or clearing
|
||||
// We also want to avoid reassigning to improve CoW
|
||||
continue;
|
||||
@ -450,7 +450,7 @@ rb_iseq_mark_and_move(const struct rb_gc_mark_ctx *ctx, rb_iseq_t *iseq, bool re
|
||||
else {
|
||||
// Either the CC or CME has been invalidated. Replace
|
||||
// it with the empty CC so that it can be GC'd.
|
||||
cds[i].cc = rb_vm_empty_cc();
|
||||
cds[i].cc = &rb_vm_empty_cc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
vm.c
24
vm.c
@ -771,7 +771,7 @@ rb_serial_t ruby_vm_constant_cache_invalidations = 0;
|
||||
rb_serial_t ruby_vm_constant_cache_misses = 0;
|
||||
rb_serial_t ruby_vm_global_cvar_state = 1;
|
||||
|
||||
static const struct rb_callcache vm_empty_cc = {
|
||||
const struct rb_callcache rb_vm_empty_cc = {
|
||||
.flags = T_IMEMO | (imemo_callcache << FL_USHIFT) | VM_CALLCACHE_UNMARKABLE,
|
||||
.klass = Qundef,
|
||||
.cme_ = NULL,
|
||||
@ -784,7 +784,7 @@ static const struct rb_callcache vm_empty_cc = {
|
||||
/* Installed instead of a real cc at call sites of methods that opted out of
|
||||
* call caching: dispatch resolves the cme on every call rather than leaving a
|
||||
* cc behind on the receiver's class. */
|
||||
static const struct rb_callcache vm_uncached_cc = {
|
||||
const struct rb_callcache rb_vm_uncached_cc = {
|
||||
.flags = T_IMEMO | (imemo_callcache << FL_USHIFT) | VM_CALLCACHE_UNMARKABLE,
|
||||
.klass = Qundef,
|
||||
.cme_ = NULL,
|
||||
@ -794,7 +794,7 @@ static const struct rb_callcache vm_uncached_cc = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct rb_callcache vm_empty_cc_for_super = {
|
||||
const struct rb_callcache rb_vm_empty_cc_for_super = {
|
||||
.flags = T_IMEMO | (imemo_callcache << FL_USHIFT) | VM_CALLCACHE_UNMARKABLE,
|
||||
.klass = Qundef,
|
||||
.cme_ = NULL,
|
||||
@ -5464,22 +5464,4 @@ vm_collect_usage_register(int reg, int isset)
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct rb_callcache *
|
||||
rb_vm_empty_cc(void)
|
||||
{
|
||||
return &vm_empty_cc;
|
||||
}
|
||||
|
||||
const struct rb_callcache *
|
||||
rb_vm_empty_cc_for_super(void)
|
||||
{
|
||||
return &vm_empty_cc_for_super;
|
||||
}
|
||||
|
||||
const struct rb_callcache *
|
||||
rb_vm_uncached_cc(void)
|
||||
{
|
||||
return &vm_uncached_cc;
|
||||
}
|
||||
|
||||
#include "vm_call_iseq_optimized.inc" /* required from vm_insnhelper.c */
|
||||
|
||||
@ -324,11 +324,11 @@ enum vm_cc_type {
|
||||
cc_type_refinement,
|
||||
};
|
||||
|
||||
extern const struct rb_callcache *rb_vm_empty_cc(void);
|
||||
extern const struct rb_callcache *rb_vm_empty_cc_for_super(void);
|
||||
extern const struct rb_callcache *rb_vm_uncached_cc(void);
|
||||
extern const struct rb_callcache rb_vm_empty_cc;
|
||||
extern const struct rb_callcache rb_vm_empty_cc_for_super;
|
||||
extern const struct rb_callcache rb_vm_uncached_cc;
|
||||
|
||||
#define vm_cc_empty() rb_vm_empty_cc()
|
||||
#define vm_cc_empty() (&rb_vm_empty_cc)
|
||||
|
||||
static inline VALUE
|
||||
cc_check_class(VALUE klass)
|
||||
|
||||
@ -420,7 +420,7 @@ gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, unsigned int index, const
|
||||
|
||||
vm_search_method_slowpath0(vm->self, &cd, klass);
|
||||
|
||||
if (UNLIKELY(cd.cc == rb_vm_uncached_cc())) {
|
||||
if (UNLIKELY(cd.cc == &rb_vm_uncached_cc)) {
|
||||
// Carries no cme, so it would only ever miss here. Don't evict a usable entry for it.
|
||||
return cd.cc;
|
||||
}
|
||||
@ -571,7 +571,7 @@ rb_call0(rb_execution_context_t *ec,
|
||||
|
||||
const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, &ci);
|
||||
|
||||
if (UNLIKELY(cc == rb_vm_uncached_cc())) {
|
||||
if (UNLIKELY(cc == &rb_vm_uncached_cc)) {
|
||||
return vm_call0_uncached(ec, recv, mid, argc, argv, kw_splat, scope, self);
|
||||
}
|
||||
|
||||
|
||||
@ -42,10 +42,6 @@ extern int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_me
|
||||
extern VALUE rb_make_no_method_exception(VALUE exc, VALUE format, VALUE obj,
|
||||
int argc, const VALUE *argv, int priv);
|
||||
|
||||
static const struct rb_callcache vm_empty_cc;
|
||||
static const struct rb_callcache vm_empty_cc_for_super;
|
||||
static const struct rb_callcache vm_uncached_cc;
|
||||
|
||||
/* control stack frame */
|
||||
|
||||
static rb_control_frame_t *vm_get_ruby_level_caller_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp);
|
||||
@ -2110,8 +2106,8 @@ vm_populate_cc(VALUE klass, const struct rb_callinfo * const ci, ID mid)
|
||||
|
||||
if (cme == NULL) {
|
||||
// undef or not found: can't cache the information
|
||||
VM_ASSERT(vm_cc_cme(&vm_empty_cc) == NULL);
|
||||
return &vm_empty_cc;
|
||||
VM_ASSERT(vm_cc_cme(&rb_vm_empty_cc) == NULL);
|
||||
return &rb_vm_empty_cc;
|
||||
}
|
||||
|
||||
if (UNLIKELY(cme->def->uncached && !(vm_ci_flag(ci) & VM_CALL_SUPER))) {
|
||||
@ -2119,7 +2115,7 @@ vm_populate_cc(VALUE klass, const struct rb_callinfo * const ci, ID mid)
|
||||
// is usually a metaclass, so the cost would scale with the number of
|
||||
// classes. invokesuper is excluded because vm_search_super_method needs a
|
||||
// cme in the cc it gets back.
|
||||
return &vm_uncached_cc;
|
||||
return &rb_vm_uncached_cc;
|
||||
}
|
||||
|
||||
VALUE cc_tbl = RCLASS_WRITABLE_CC_TBL(klass);
|
||||
@ -2259,7 +2255,7 @@ vm_search_cc(const VALUE klass, const struct rb_callinfo * const ci)
|
||||
static bool
|
||||
vm_cc_resolved_p(const struct rb_callcache *cc)
|
||||
{
|
||||
return cc != &vm_empty_cc && cc != &vm_uncached_cc;
|
||||
return cc != &rb_vm_empty_cc && cc != &rb_vm_uncached_cc;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2326,7 +2322,7 @@ vm_search_method_slowpath0(VALUE cd_owner, struct rb_call_data *cd, VALUE klass)
|
||||
}
|
||||
|
||||
#if USE_DEBUG_COUNTER
|
||||
const struct rb_callcache *empty_cc = &vm_empty_cc;
|
||||
const struct rb_callcache *empty_cc = &rb_vm_empty_cc;
|
||||
if (!old_cc || old_cc == empty_cc) {
|
||||
// empty
|
||||
RB_DEBUG_COUNTER_INC(mc_inline_miss_empty);
|
||||
@ -2386,7 +2382,7 @@ vm_search_method_fastpath(const struct rb_control_frame_struct *reg_cfp, struct
|
||||
if (vm_cc_hit_p(cc, cd, klass)) {
|
||||
return cc;
|
||||
}
|
||||
if (UNLIKELY(cc == &vm_uncached_cc)) {
|
||||
if (UNLIKELY(cc == &rb_vm_uncached_cc)) {
|
||||
return cc;
|
||||
}
|
||||
|
||||
@ -2435,7 +2431,7 @@ rb_zjit_vm_search_method(VALUE cd_owner, struct rb_call_data *cd, VALUE recv)
|
||||
VALUE klass = CLASS_OF(recv);
|
||||
const struct rb_callcache *cc = cd->cc;
|
||||
if (!vm_cc_hit_p(cc, cd, klass)) {
|
||||
if (UNLIKELY(cc == &vm_uncached_cc)) {
|
||||
if (UNLIKELY(cc == &rb_vm_uncached_cc)) {
|
||||
return rb_callable_method_entry(klass, vm_ci_mid(cd->ci));
|
||||
}
|
||||
cc = vm_search_method_slowpath0(cd_owner, cd, klass);
|
||||
@ -5234,7 +5230,7 @@ vm_super_outside(void)
|
||||
static const struct rb_callcache *
|
||||
empty_cc_for_super(void)
|
||||
{
|
||||
return &vm_empty_cc_for_super;
|
||||
return &rb_vm_empty_cc_for_super;
|
||||
}
|
||||
|
||||
static const struct rb_callcache *
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user