summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2021-02-03 15:29:26 +0900
committerKoichi Sasada <ko1@atdot.net>2021-02-03 17:28:12 +0900
commit583f364f7187337b284061b78a47b29875398e33 (patch)
treeeb3848f5f36a7e34f59c0a303b698a44a51a4bd9
parentf600226fb4ad7e3faa9a184bfe9b2de6404551f3 (diff)
use goto intead of recursion on vm_call0_body()
"alias" type method entries can chain another aliased method so that machine stack can be overflow on nested alias chain. http://ci.rvm.jp/results/trunk-repeat20@phosphorus-docker/3344209 This patch fix this issue by use goto instead of recursion if possible. TODO: Essentially, the alias method should not points another aliased method entry. Try to fix it later.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4148
-rw-r--r--vm_eval.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/vm_eval.c b/vm_eval.c
index 0f3d1e4e1f..eae9464a1b 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -157,6 +157,8 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const
const struct rb_callcache *cc = calling->cc;
VALUE ret;
+ retry:
+
switch (vm_cc_cme(cc)->def->type) {
case VM_METHOD_TYPE_ISEQ:
{
@@ -222,7 +224,20 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const
return vm_call0_super(ec, calling, argv, klass, 0);
}
case VM_METHOD_TYPE_ALIAS:
- return vm_call0_cme(ec, calling, argv, aliased_callable_method_entry(vm_cc_cme(cc)));
+ {
+ const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
+ const rb_callable_method_entry_t *orig_cme = aliased_callable_method_entry(cme);
+
+ if (cme == orig_cme) rb_bug("same!!");
+
+ if (vm_cc_markable(cc)) {
+ return vm_call0_cme(ec, calling, argv, orig_cme);
+ }
+ else {
+ *((const rb_callable_method_entry_t **)&cc->cme_) = orig_cme;
+ goto retry;
+ }
+ }
case VM_METHOD_TYPE_MISSING:
{
vm_passed_block_handler_set(ec, calling->block_handler);