mark cc->cme_
if it is for super
`vm_search_super_method()` makes orphan CCs (they are not connected from ccs) and `cc->cme_` can be collected before without marking.
This commit is contained in:
parent
60ac719acc
commit
36023d5cb7
Notes:
git
2023-07-31 05:04:51 +00:00
8
gc.c
8
gc.c
@ -7030,7 +7030,15 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj)
|
|||||||
* - On the multi-Ractors, cme will be collected with global GC
|
* - On the multi-Ractors, cme will be collected with global GC
|
||||||
* so that it is safe if GC is not interleaving while accessing
|
* so that it is safe if GC is not interleaving while accessing
|
||||||
* cc and cme.
|
* cc and cme.
|
||||||
|
* - However, cc_type_super is not chained from cc so the cc->cme
|
||||||
|
* should be marked.
|
||||||
*/
|
*/
|
||||||
|
{
|
||||||
|
const struct rb_callcache *cc = (const struct rb_callcache *)obj;
|
||||||
|
if (vm_cc_super_p(cc)) {
|
||||||
|
gc_mark(objspace, (VALUE)cc->cme_);
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
case imemo_constcache:
|
case imemo_constcache:
|
||||||
{
|
{
|
||||||
|
@ -296,6 +296,15 @@ struct rb_callcache {
|
|||||||
#define VM_CALLCACHE_UNMARKABLE FL_FREEZE
|
#define VM_CALLCACHE_UNMARKABLE FL_FREEZE
|
||||||
#define VM_CALLCACHE_ON_STACK FL_EXIVAR
|
#define VM_CALLCACHE_ON_STACK FL_EXIVAR
|
||||||
|
|
||||||
|
#define VM_CALLCACHE_IVAR IMEMO_FL_USER0
|
||||||
|
#define VM_CALLCACHE_BF IMEMO_FL_USER1
|
||||||
|
#define VM_CALLCACHE_SUPER IMEMO_FL_USER2
|
||||||
|
|
||||||
|
enum vm_cc_type {
|
||||||
|
cc_type_normal, // chained from ccs
|
||||||
|
cc_type_super,
|
||||||
|
};
|
||||||
|
|
||||||
extern const struct rb_callcache *rb_vm_empty_cc(void);
|
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_empty_cc_for_super(void);
|
||||||
|
|
||||||
@ -312,14 +321,30 @@ vm_cc_attr_index_initialize(const struct rb_callcache *cc, shape_id_t shape_id)
|
|||||||
static inline const struct rb_callcache *
|
static inline const struct rb_callcache *
|
||||||
vm_cc_new(VALUE klass,
|
vm_cc_new(VALUE klass,
|
||||||
const struct rb_callable_method_entry_struct *cme,
|
const struct rb_callable_method_entry_struct *cme,
|
||||||
vm_call_handler call)
|
vm_call_handler call,
|
||||||
|
enum vm_cc_type type)
|
||||||
{
|
{
|
||||||
const struct rb_callcache *cc = (const struct rb_callcache *)rb_imemo_new(imemo_callcache, (VALUE)cme, (VALUE)call, 0, klass);
|
const struct rb_callcache *cc = (const struct rb_callcache *)rb_imemo_new(imemo_callcache, (VALUE)cme, (VALUE)call, 0, klass);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case cc_type_normal:
|
||||||
|
break;
|
||||||
|
case cc_type_super:
|
||||||
|
*(VALUE *)&cc->flags |= VM_CALLCACHE_SUPER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
|
vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
|
||||||
RB_DEBUG_COUNTER_INC(cc_new);
|
RB_DEBUG_COUNTER_INC(cc_new);
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
vm_cc_super_p(const struct rb_callcache *cc)
|
||||||
|
{
|
||||||
|
return (cc->flags & VM_CALLCACHE_SUPER) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
#define VM_CC_ON_STACK(clazz, call, aux, cme) \
|
#define VM_CC_ON_STACK(clazz, call, aux, cme) \
|
||||||
(struct rb_callcache) { \
|
(struct rb_callcache) { \
|
||||||
.flags = T_IMEMO | \
|
.flags = T_IMEMO | \
|
||||||
@ -439,9 +464,6 @@ vm_cc_valid_p(const struct rb_callcache *cc, const rb_callable_method_entry_t *c
|
|||||||
|
|
||||||
/* callcache: mutate */
|
/* callcache: mutate */
|
||||||
|
|
||||||
#define VM_CALLCACHE_IVAR IMEMO_FL_USER0
|
|
||||||
#define VM_CALLCACHE_BF IMEMO_FL_USER1
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
vm_cc_call_set(const struct rb_callcache *cc, vm_call_handler call)
|
vm_cc_call_set(const struct rb_callcache *cc, vm_call_handler call)
|
||||||
{
|
{
|
||||||
|
@ -425,7 +425,7 @@ cc_new(VALUE klass, ID mid, int argc, const rb_callable_method_entry_t *cme)
|
|||||||
|
|
||||||
if (cc == NULL) {
|
if (cc == NULL) {
|
||||||
const struct rb_callinfo *ci = vm_ci_new(mid, 0, argc, NULL); // TODO: proper ci
|
const struct rb_callinfo *ci = vm_ci_new(mid, 0, argc, NULL); // TODO: proper ci
|
||||||
cc = vm_cc_new(klass, cme, vm_call_general);
|
cc = vm_cc_new(klass, cme, vm_call_general, cc_type_normal);
|
||||||
METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct *)cme);
|
METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct *)cme);
|
||||||
vm_ccs_push(klass, ccs, ci, cc);
|
vm_ccs_push(klass, ccs, ci, cc);
|
||||||
}
|
}
|
||||||
|
@ -2096,7 +2096,7 @@ vm_search_cc(const VALUE klass, const struct rb_callinfo * const ci)
|
|||||||
|
|
||||||
cme = check_overloaded_cme(cme, ci);
|
cme = check_overloaded_cme(cme, ci);
|
||||||
|
|
||||||
const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general);
|
const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general, cc_type_normal);
|
||||||
vm_ccs_push(klass, ccs, ci, cc);
|
vm_ccs_push(klass, ccs, ci, cc);
|
||||||
|
|
||||||
VM_ASSERT(vm_cc_cme(cc) != NULL);
|
VM_ASSERT(vm_cc_cme(cc) != NULL);
|
||||||
@ -4630,7 +4630,7 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c
|
|||||||
|
|
||||||
if (!klass) {
|
if (!klass) {
|
||||||
/* bound instance method of module */
|
/* bound instance method of module */
|
||||||
cc = vm_cc_new(klass, NULL, vm_call_method_missing);
|
cc = vm_cc_new(klass, NULL, vm_call_method_missing, cc_type_super);
|
||||||
RB_OBJ_WRITE(reg_cfp->iseq, &cd->cc, cc);
|
RB_OBJ_WRITE(reg_cfp->iseq, &cd->cc, cc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -4645,7 +4645,7 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c
|
|||||||
else if (cached_cme->called_id != mid) {
|
else if (cached_cme->called_id != mid) {
|
||||||
const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
|
const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
|
||||||
if (cme) {
|
if (cme) {
|
||||||
cc = vm_cc_new(klass, cme, vm_call_super_method);
|
cc = vm_cc_new(klass, cme, vm_call_super_method, cc_type_super);
|
||||||
RB_OBJ_WRITE(reg_cfp->iseq, &cd->cc, cc);
|
RB_OBJ_WRITE(reg_cfp->iseq, &cd->cc, cc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user