summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2021-11-16 17:57:49 +0900
committerKoichi Sasada <ko1@atdot.net>2021-11-17 22:21:42 +0900
commitb2255153cf2fe9d7b851c59cc09b358c0630e0a2 (patch)
tree7d4142a5872963a91d94bbc5103e904258eb83c6
parent84aba250315d7fea728a6708e33ae8bf11f607b2 (diff)
`vm_empty_cc_for_super`
Same as `vm_empty_cc`, introduce a global variable which has `.call_ = vm_call_super_method`. Use it if the `cme == NULL` on `vm_search_super_method`.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5122
-rw-r--r--vm.c16
-rw-r--r--vm_callinfo.h1
-rw-r--r--vm_insnhelper.c37
3 files changed, 44 insertions, 10 deletions
diff --git a/vm.c b/vm.c
index f13e07cef3..a868355bbe 100644
--- a/vm.c
+++ b/vm.c
@@ -439,6 +439,16 @@ static const struct rb_callcache vm_empty_cc = {
}
};
+static const struct rb_callcache vm_empty_cc_for_super = {
+ .flags = T_IMEMO | (imemo_callcache << FL_USHIFT) | VM_CALLCACHE_UNMARKABLE,
+ .klass = Qfalse,
+ .cme_ = NULL,
+ .call_ = vm_call_super_method,
+ .aux_ = {
+ .v = Qfalse,
+ }
+};
+
static void thread_free(void *ptr);
void
@@ -4176,6 +4186,12 @@ rb_vm_empty_cc(void)
return &vm_empty_cc;
}
+MJIT_FUNC_EXPORTED const struct rb_callcache *
+rb_vm_empty_cc_for_super(void)
+{
+ return &vm_empty_cc_for_super;
+}
+
#endif /* #ifndef MJIT_HEADER */
#include "vm_call_iseq_optimized.inc" /* required from vm_insnhelper.c */
diff --git a/vm_callinfo.h b/vm_callinfo.h
index fa35c98d17..2641ee79c5 100644
--- a/vm_callinfo.h
+++ b/vm_callinfo.h
@@ -382,6 +382,7 @@ vm_cc_valid_p(const struct rb_callcache *cc, const rb_callable_method_entry_t *c
}
extern const struct rb_callcache *rb_vm_empty_cc(void);
+extern const struct rb_callcache *rb_vm_empty_cc_for_super(void);
#define vm_cc_empty() rb_vm_empty_cc()
/* callcache: mutate */
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 5e5554cb67..ff02f14141 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -38,6 +38,7 @@ extern VALUE rb_make_no_method_exception(VALUE exc, VALUE format, VALUE obj,
#ifndef MJIT_HEADER
static const struct rb_callcache vm_empty_cc;
+static const struct rb_callcache vm_empty_cc_for_super;
#endif
/* control stack frame */
@@ -3711,6 +3712,11 @@ vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, st
{
RB_DEBUG_COUNTER_INC(ccf_super_method);
+ // This line is introduced to make different from `vm_call_general` because some compilers (VC we found)
+ // can merge the function and the address of the function becomes same.
+ // The address of `vm_call_super_method` is used in `search_refined_method`, so it should be different.
+ if (ec == NULL) rb_bug("unreachable");
+
/* this check is required to distinguish with other functions. */
VM_ASSERT(vm_cc_call(calling->cc) == vm_call_super_method);
return vm_call_method(ec, reg_cfp, calling);
@@ -3738,6 +3744,16 @@ vm_super_outside(void)
}
static const struct rb_callcache *
+empty_cc_for_super(void)
+{
+#ifdef MJIT_HEADER
+ return rb_vm_empty_cc_for_super();
+#else
+ return &vm_empty_cc_for_super;
+#endif
+}
+
+static const struct rb_callcache *
vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *cd, VALUE recv)
{
VALUE current_defined_class;
@@ -3800,19 +3816,18 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c
// define_method can cache for different method id
if (cached_cme == NULL) {
- // temporary CC. revisit it
- static const struct rb_callcache *empty_cc_for_super = NULL;
- if (empty_cc_for_super == NULL) {
- empty_cc_for_super = vm_cc_new(0, NULL, vm_call_super_method);
- FL_SET_RAW((VALUE)empty_cc_for_super, VM_CALLCACHE_UNMARKABLE);
- rb_gc_register_mark_object((VALUE)empty_cc_for_super);
- }
- RB_OBJ_WRITE(reg_cfp->iseq, &cd->cc, cc = empty_cc_for_super);
+ // empty_cc_for_super is not markable object
+ cd->cc = empty_cc_for_super();
}
else if (cached_cme->called_id != mid) {
const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
- cc = vm_cc_new(klass, cme, vm_call_super_method);
- RB_OBJ_WRITE(reg_cfp->iseq, &cd->cc, cc);
+ if (cme) {
+ cc = vm_cc_new(klass, cme, vm_call_super_method);
+ RB_OBJ_WRITE(reg_cfp->iseq, &cd->cc, cc);
+ }
+ else {
+ cd->cc = cc = empty_cc_for_super();
+ }
}
else {
switch (cached_cme->def->type) {
@@ -3829,6 +3844,8 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c
}
}
+ VM_ASSERT((vm_cc_cme(cc), true));
+
return cc;
}