-
Notifications
You must be signed in to change notification settings - Fork 6
/
llrb_insn_invokesuper.c
47 lines (40 loc) · 1.49 KB
/
llrb_insn_invokesuper.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include "cruby.h"
#define CALL_METHOD(calling, ci, cc) (*(cc)->call)(th, cfp, (calling), (ci), (cc))
VALUE vm_exec(rb_thread_t *th);
static inline void
_llrb_push_result(rb_control_frame_t *cfp, VALUE result)
{
// PUSH(result)
*(cfp->sp) = result;
cfp->sp += 1;
}
void vm_caller_setup_arg_block(const rb_thread_t *th, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling, const struct rb_call_info *ci, rb_iseq_t *blockiseq, const int is_super);
void vm_search_super_method(rb_thread_t *th, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling, struct rb_call_info *ci, struct rb_call_cache *cc);
VALUE
llrb_insn_invokesuper(VALUE th_v, VALUE cfp_v, VALUE ci_v, VALUE cc_v, VALUE blockiseq_v, unsigned int stack_size, ...)
{
rb_thread_t *th = (rb_thread_t *)th_v;
rb_control_frame_t *cfp = (rb_control_frame_t *)cfp_v;
CALL_INFO ci = (CALL_INFO)ci_v;
CALL_CACHE cc = (CALL_CACHE)cc_v;
ISEQ blockiseq = (ISEQ)blockiseq_v;
va_list ar;
va_start(ar, stack_size);
for (unsigned int i = 0; i < stack_size; i++) {
_llrb_push_result(cfp, va_arg(ar, VALUE));
}
va_end(ar);
struct rb_calling_info calling;
calling.argc = ci->orig_argc;
vm_caller_setup_arg_block(th, cfp, &calling, ci, blockiseq, 1);
calling.recv = th->cfp->self;
vm_search_super_method(th, th->cfp, &calling, ci, cc);
VALUE result = CALL_METHOD(&calling, ci, cc);
if (result == Qundef) {
VM_ENV_FLAGS_SET(th->cfp->ep, VM_FRAME_FLAG_FINISH);
return vm_exec(th);
}
return result;
}