зеркало из https://github.com/github/ruby.git
* insn_send.ci: removed.
* common.mk: ditto. * vm.c (vm_call_bmethod), isnsn.def: added. fix to use this function instead of using goto. * vm.c (vm_call_bmethod): renamed from th_invoke_bmethod(). * vm.c (vm_method_missing): renamed from eval_methdo_missing(). * vm_evalbody.ci: remove tmp_* variables. * insnhelper.h: add some macros. * insns.def: forbid zsuper from method defined by define_method(). * test/ruby/test_super.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12601 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
904b9e5d54
Коммит
62deb7dbbd
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
|||
Sun Jun 24 22:00:17 2007 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* insn_send.ci: removed.
|
||||
|
||||
* common.mk: ditto.
|
||||
|
||||
* vm.c (vm_call_bmethod), isnsn.def: added. fix to use this
|
||||
function instead of using goto.
|
||||
|
||||
* vm.c (vm_call_bmethod): renamed from th_invoke_bmethod().
|
||||
|
||||
* vm.c (vm_method_missing): renamed from eval_methdo_missing().
|
||||
|
||||
* vm_evalbody.ci: remove tmp_* variables.
|
||||
|
||||
* insnhelper.h: add some macros.
|
||||
|
||||
* insns.def: forbid zsuper from method defined by define_method().
|
||||
|
||||
* test/ruby/test_super.rb: ditto.
|
||||
|
||||
Sun Jun 24 20:01:08 2007 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* vm_macro.def: removed.
|
||||
|
|
|
@ -552,21 +552,20 @@ compile.$(OBJEXT): {$(VPATH)}compile.c {$(VPATH)}yarvcore.h \
|
|||
{$(VPATH)}compile.h {$(VPATH)}debug.h {$(VPATH)}ruby.h {$(VPATH)}config.h \
|
||||
{$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
|
||||
{$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}signal.h \
|
||||
{$(VPATH)}insns.inc {$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc \
|
||||
{$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc \
|
||||
{$(VPATH)}opt_sc.inc {$(VPATH)}optunifs.inc {$(VPATH)}vm_opts.h \
|
||||
{$(VPATH)}thread_$(THREAD_MODEL).h
|
||||
iseq.$(OBJEXT): {$(VPATH)}iseq.c {$(VPATH)}yarvcore.h {$(VPATH)}debug.h \
|
||||
{$(VPATH)}ruby.h {$(VPATH)}defines.h {$(VPATH)}missing.h \
|
||||
{$(VPATH)}intern.h {$(VPATH)}st.h {$(VPATH)}signal.h \
|
||||
{$(VPATH)}gc.h {$(VPATH)}vm_opts.h {$(VPATH)}config.h {$(VPATH)}node.h \
|
||||
{$(VPATH)}thread_$(THREAD_MODEL).h\
|
||||
{$(VPATH)}insns.inc {$(VPATH)}insns_info.inc
|
||||
{$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}insns_info.inc
|
||||
vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}vm.h {$(VPATH)}insnhelper.h \
|
||||
{$(VPATH)}yarvcore.h {$(VPATH)}debug.h {$(VPATH)}ruby.h {$(VPATH)}config.h\
|
||||
{$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}signal.h {$(VPATH)}dln.h \
|
||||
{$(VPATH)}vm_evalbody.ci {$(VPATH)}call_cfunc.ci \
|
||||
{$(VPATH)}insns.inc {$(VPATH)}vm.inc {$(VPATH)}vmtc.inc \
|
||||
{$(VPATH)}insn_send.ci {$(VPATH)}vm_opts.h {$(VPATH)}eval_intern.h \
|
||||
{$(VPATH)}vm_opts.h {$(VPATH)}eval_intern.h \
|
||||
{$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
|
||||
{$(VPATH)}gc.h {$(VPATH)}thread_$(THREAD_MODEL).h
|
||||
vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c {$(VPATH)}yarvcore.h {$(VPATH)}vm.h \
|
||||
|
|
226
insn_send.ci
226
insn_send.ci
|
@ -1,226 +0,0 @@
|
|||
/* -*-c-*- */
|
||||
/* send instruction body */
|
||||
|
||||
{
|
||||
NODE *mn;
|
||||
VALUE recv;
|
||||
VALUE klass;
|
||||
rb_block_t *blockptr = 0;
|
||||
rb_num_t num;
|
||||
rb_num_t flag = op_flag;
|
||||
ID id = op_id;
|
||||
|
||||
num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &blockptr);
|
||||
|
||||
if (flag & VM_CALL_FCALL_BIT) {
|
||||
/* method(...) */
|
||||
recv = GET_SELF();
|
||||
}
|
||||
else {
|
||||
/* recv.method(...) */
|
||||
recv = TOPN(num);
|
||||
}
|
||||
|
||||
klass = CLASS_OF(recv);
|
||||
|
||||
mn = eval_method_search(id, klass, ic);
|
||||
|
||||
if ((flag & VM_CALL_SEND_BIT) && mn && nd_type(mn->nd_body) == NODE_CFUNC) {
|
||||
NODE *node = mn->nd_body;
|
||||
extern VALUE rb_f_funcall(int argc, VALUE *argv, VALUE recv);
|
||||
extern VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
|
||||
|
||||
if (node->nd_cfnc == rb_f_funcall || node->nd_cfnc == rb_f_send) {
|
||||
int i;
|
||||
VALUE sym = TOPN(num - 1);
|
||||
id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym);
|
||||
|
||||
/* shift arguments */
|
||||
for (i=num-1; i>0; i--) {
|
||||
TOPN(i) = TOPN(i-1);
|
||||
}
|
||||
|
||||
mn = rb_method_node(klass, id);
|
||||
|
||||
num -= 1;
|
||||
DEC_SP(1);
|
||||
}
|
||||
|
||||
if (node->nd_cfnc == rb_f_funcall) {
|
||||
flag |= VM_CALL_FCALL_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
#if CURRENT_INSN_send || CURRENT_INSN_send_SC_xx_ax
|
||||
#if !YARV_AOT_COMPILED
|
||||
if (0) {
|
||||
if (0) {
|
||||
LABEL_IS_SC(start_init_in_send_for_opt_1):
|
||||
num = 1;
|
||||
recv = TOPN(1);
|
||||
}
|
||||
else if (0) {
|
||||
LABEL_IS_SC(start_init_in_send_for_opt_2):
|
||||
num = 2;
|
||||
recv = TOPN(2);
|
||||
}
|
||||
flag = 0;
|
||||
id = tmp_id;
|
||||
klass = CLASS_OF(recv);
|
||||
blockptr = 0;
|
||||
mn = rb_method_node(klass, id);
|
||||
}
|
||||
if (0) {
|
||||
LABEL_IS_SC(start_init_in_super):
|
||||
{
|
||||
rb_iseq_t *iseq = GET_ISEQ();
|
||||
rb_iseq_t *ip = iseq;
|
||||
|
||||
num = tmp_num;
|
||||
flag = VM_CALL_FCALL_BIT;
|
||||
recv = GET_SELF();
|
||||
|
||||
while (ip && !ip->klass) {
|
||||
ip = ip->parent_iseq;
|
||||
}
|
||||
|
||||
if (ip == 0) {
|
||||
rb_raise(rb_eNoMethodError, "super called outside of method");
|
||||
}
|
||||
|
||||
id = ip->defined_method_id;
|
||||
|
||||
if (ip != ip->local_iseq) {
|
||||
/* defined by Module#define_method() */
|
||||
rb_control_frame_t *lcfp = GET_CFP();
|
||||
|
||||
while (lcfp->iseq != ip) {
|
||||
VALUE *tdfp = GET_PREV_DFP(lcfp->dfp);
|
||||
while (1) {
|
||||
lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp);
|
||||
if (lcfp->dfp == tdfp) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
id = lcfp->method_id;
|
||||
klass = search_super_klass(lcfp->method_klass, recv);
|
||||
|
||||
if (TOPN(num) == Qfalse) {
|
||||
/* for ZSUPER */
|
||||
int i;
|
||||
POPN(num);
|
||||
num = ip->argc;
|
||||
for (i = 0; i < ip->argc; i++) {
|
||||
PUSH(lcfp->dfp[i - ip->local_size]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
klass = search_super_klass(ip->klass, recv);
|
||||
}
|
||||
|
||||
flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT;
|
||||
blockptr = tmp_blockptr;
|
||||
mn = rb_method_node(klass, id);
|
||||
}
|
||||
}
|
||||
LABEL_IS_SC(start_method_dispatch):
|
||||
#endif
|
||||
#endif
|
||||
/* method missing */
|
||||
if (mn == 0) {
|
||||
/* temporarily */
|
||||
if (id == idMethodMissing) {
|
||||
rb_bug("method missing");
|
||||
}
|
||||
else {
|
||||
int stat = 0;
|
||||
if (flag & VM_CALL_VCALL_BIT) {
|
||||
stat |= NOEX_VCALL;
|
||||
}
|
||||
if (flag & VM_CALL_SUPER_BIT) {
|
||||
stat |= NOEX_SUPER;
|
||||
}
|
||||
val = eval_method_missing(th, id, recv, num, blockptr, stat);
|
||||
}
|
||||
}
|
||||
else if (!(flag & VM_CALL_FCALL_BIT) &&
|
||||
(mn->nd_noex & NOEX_MASK) & NOEX_PRIVATE) {
|
||||
int stat = NOEX_PRIVATE;
|
||||
if (flag & VM_CALL_VCALL_BIT) {
|
||||
stat |= NOEX_VCALL;
|
||||
}
|
||||
val = eval_method_missing(th, id, recv, num, blockptr, stat);
|
||||
}
|
||||
else if ((mn->nd_noex & NOEX_MASK) & NOEX_PROTECTED) {
|
||||
VALUE defined_class = mn->nd_clss;
|
||||
|
||||
if (TYPE(defined_class) == T_ICLASS) {
|
||||
defined_class = RBASIC(defined_class)->klass;
|
||||
}
|
||||
if (!rb_obj_is_kind_of(GET_SELF(), rb_class_real(defined_class))) {
|
||||
val =
|
||||
eval_method_missing(th, id, recv, num, blockptr,
|
||||
NOEX_PROTECTED);
|
||||
}
|
||||
else {
|
||||
goto INSN_LABEL(normal_method_dispatch);
|
||||
}
|
||||
}
|
||||
else {
|
||||
NODE *node;
|
||||
INSN_LABEL(normal_method_dispatch):
|
||||
|
||||
node = mn->nd_body;
|
||||
switch (nd_type(node)) {
|
||||
case RUBY_VM_METHOD_NODE:{
|
||||
vm_setup_method(th, GET_CFP(), num, blockptr, flag, (VALUE)node->nd_body, recv, klass);
|
||||
RESTORE_REGS();
|
||||
NEXT_INSN();
|
||||
}
|
||||
case NODE_CFUNC:{
|
||||
val = vm_call_cfunc(th, GET_CFP(), num, id, recv, klass, node, blockptr);
|
||||
break;
|
||||
}
|
||||
case NODE_ATTRSET:{
|
||||
val = rb_ivar_set(recv, node->nd_vid, TOPN(0));
|
||||
POPN(2);
|
||||
break;
|
||||
}
|
||||
case NODE_IVAR:{
|
||||
val = rb_ivar_get(recv, node->nd_vid);
|
||||
POP();
|
||||
break;
|
||||
}
|
||||
case NODE_BMETHOD:{
|
||||
VALUE *argv = GET_SP() - num;
|
||||
val = th_invoke_bmethod(th, id, node->nd_cval,
|
||||
recv, klass, num, argv);
|
||||
INC_SP(-num-1);
|
||||
break;
|
||||
}
|
||||
case NODE_ZSUPER:{
|
||||
klass = RCLASS(mn->nd_clss)->super;
|
||||
mn = rb_method_node(klass, id);
|
||||
|
||||
if (mn != 0) {
|
||||
goto INSN_LABEL(normal_method_dispatch);
|
||||
}
|
||||
else {
|
||||
goto LABEL_IS_SC(start_method_dispatch);
|
||||
}
|
||||
}
|
||||
default:{
|
||||
printf("node: %s\n", ruby_node_name(nd_type(node)));
|
||||
rb_bug("eval_invoke_method: unreachable");
|
||||
/* unreachable */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RUBY_VM_CHECK_INTS();
|
||||
}
|
||||
|
16
insnhelper.h
16
insnhelper.h
|
@ -146,4 +146,20 @@ while (0)
|
|||
#define BASIC_OP_UNREDEFINED_P(op) ((yarv_redefined_flag & (op)) == 0)
|
||||
#define HEAP_CLASS_OF(obj) RBASIC(obj)->klass
|
||||
|
||||
#define CALL_METHOD(num, blockptr, flag, id, mn, recv, klass) do { \
|
||||
VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, mn, recv, klass); \
|
||||
if (v == Qundef) { \
|
||||
RESTORE_REGS(); \
|
||||
NEXT_INSN(); \
|
||||
} \
|
||||
else { \
|
||||
val = v; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CALL_SIMPLE_METHOD(num, id, recv) do { \
|
||||
VALUE klass = CLASS_OF(recv); \
|
||||
CALL_METHOD(num, 0, 0, id, rb_method_node(klass, id), recv, CLASS_OF(recv)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* _INSNHELPER_H_INCLUDED_ */
|
||||
|
|
236
insns.def
236
insns.def
|
@ -1152,7 +1152,55 @@ send
|
|||
(...)
|
||||
(VALUE val) // inc += - (op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
|
||||
{
|
||||
#include "insn_send.ci"
|
||||
NODE *mn;
|
||||
VALUE recv, klass, v;
|
||||
rb_block_t *blockptr = 0;
|
||||
rb_num_t num = caller_setup_args(th, GET_CFP(), op_flag, op_argc, blockiseq, &blockptr);
|
||||
rb_num_t flag = op_flag;
|
||||
ID id = op_id;
|
||||
|
||||
/* get receiver */
|
||||
if (flag & VM_CALL_FCALL_BIT) {
|
||||
/* method(...) */
|
||||
recv = GET_SELF();
|
||||
}
|
||||
else {
|
||||
/* recv.method(...) */
|
||||
recv = TOPN(num);
|
||||
}
|
||||
|
||||
klass = CLASS_OF(recv);
|
||||
|
||||
mn = eval_method_search(id, klass, ic);
|
||||
|
||||
/* send/funcall optimization */
|
||||
if ((flag & VM_CALL_SEND_BIT) && mn && nd_type(mn->nd_body) == NODE_CFUNC) {
|
||||
NODE *node = mn->nd_body;
|
||||
extern VALUE rb_f_funcall(int argc, VALUE *argv, VALUE recv);
|
||||
extern VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
|
||||
|
||||
if (node->nd_cfnc == rb_f_funcall || node->nd_cfnc == rb_f_send) {
|
||||
int i;
|
||||
VALUE sym = TOPN(num - 1);
|
||||
id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym);
|
||||
|
||||
/* shift arguments */
|
||||
for (i=num-1; i>0; i--) {
|
||||
TOPN(i) = TOPN(i-1);
|
||||
}
|
||||
|
||||
mn = rb_method_node(klass, id);
|
||||
|
||||
num -= 1;
|
||||
DEC_SP(1);
|
||||
}
|
||||
|
||||
if (node->nd_cfnc == rb_f_funcall) {
|
||||
flag |= VM_CALL_FCALL_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
CALL_METHOD(num, blockptr, flag, id, mn, recv, klass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1162,21 +1210,65 @@ send
|
|||
*/
|
||||
DEFINE_INSN
|
||||
invokesuper
|
||||
(rb_num_t op_argc, ISEQ blockiseq, rb_num_t flag)
|
||||
(rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag)
|
||||
(...)
|
||||
(VALUE val) // inc += - op_argc;
|
||||
{
|
||||
#if YARV_AOT_COMPILED
|
||||
/* TODO: */
|
||||
rb_bug("...");
|
||||
#else
|
||||
tmp_blockptr = 0;
|
||||
tmp_num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &tmp_blockptr);
|
||||
if (!tmp_blockptr && !(flag & VM_CALL_ARGS_BLOCKARG_BIT)) {
|
||||
tmp_blockptr = GET_BLOCK_PTR();
|
||||
rb_block_t *blockptr = 0;
|
||||
VALUE flag = op_flag;
|
||||
int num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &blockptr);
|
||||
rb_iseq_t *iseq = GET_ISEQ();
|
||||
rb_iseq_t *ip = iseq;
|
||||
VALUE recv, klass;
|
||||
ID id;
|
||||
NODE *mn;
|
||||
|
||||
if (!blockptr && !(flag & VM_CALL_ARGS_BLOCKARG_BIT)) {
|
||||
blockptr = GET_BLOCK_PTR();
|
||||
}
|
||||
goto LABEL_IS_SC(start_init_in_super);
|
||||
#endif
|
||||
|
||||
recv = GET_SELF();
|
||||
|
||||
while (ip && !ip->klass) {
|
||||
ip = ip->parent_iseq;
|
||||
}
|
||||
|
||||
if (ip == 0) {
|
||||
rb_raise(rb_eNoMethodError, "super called outside of method");
|
||||
}
|
||||
|
||||
id = ip->defined_method_id;
|
||||
|
||||
if (ip != ip->local_iseq) {
|
||||
/* defined by Module#define_method() */
|
||||
rb_control_frame_t *lcfp = GET_CFP();
|
||||
|
||||
while (lcfp->iseq != ip) {
|
||||
VALUE *tdfp = GET_PREV_DFP(lcfp->dfp);
|
||||
while (1) {
|
||||
lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp);
|
||||
if (lcfp->dfp == tdfp) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
id = lcfp->method_id;
|
||||
klass = search_super_klass(lcfp->method_klass, recv);
|
||||
|
||||
if (TOPN(num) == Qfalse) {
|
||||
/* zsuper */
|
||||
rb_raise(rb_eRuntimeError, "zsuper from method defined by define_method() is not supported. Specify all arguments.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
klass = search_super_klass(ip->klass, recv);
|
||||
}
|
||||
|
||||
flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT;
|
||||
mn = rb_method_node(klass, id);
|
||||
|
||||
CALL_METHOD(num, blockptr, flag, id, mn, recv, klass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1581,15 +1673,9 @@ opt_plus
|
|||
}
|
||||
else {
|
||||
INSN_LABEL(normal_dispatch):
|
||||
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idPLUS, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idPLUS;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idPLUS, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1619,14 +1705,9 @@ opt_minus
|
|||
}
|
||||
else {
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idMINUS, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idMINUS;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idMINUS, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1675,16 +1756,9 @@ opt_mult
|
|||
}
|
||||
else {
|
||||
INSN_LABEL(normal_dispatch):
|
||||
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idMULT, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idMULT;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idMULT, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1746,16 +1820,9 @@ opt_div
|
|||
}
|
||||
else {
|
||||
INSN_LABEL(normal_dispatch):
|
||||
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idDIV, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idDIV;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idDIV, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1837,16 +1904,9 @@ opt_mod
|
|||
}
|
||||
else {
|
||||
INSN_LABEL(normal_dispatch):
|
||||
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idMOD, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idMOD;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idMOD, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1916,14 +1976,9 @@ opt_eq
|
|||
else {
|
||||
INSN_LABEL(normal_dispatch):
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idEq, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idEq;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idEq, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1951,15 +2006,9 @@ opt_lt
|
|||
}
|
||||
}
|
||||
else {
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idLT, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idLT;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idLT, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1987,14 +2036,9 @@ opt_le
|
|||
}
|
||||
else {
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idLE, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idLE;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idLE, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2021,15 +2065,9 @@ opt_gt
|
|||
}
|
||||
}
|
||||
else {
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idGT, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idGT;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idGT, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2056,15 +2094,9 @@ opt_ge
|
|||
}
|
||||
}
|
||||
else {
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idGE, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idGE;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idGE, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2096,15 +2128,9 @@ opt_ltlt
|
|||
}
|
||||
else {
|
||||
INSN_LABEL(normal_dispatch):
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idLTLT, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idLTLT;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idLTLT, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2132,15 +2158,9 @@ opt_aref
|
|||
}
|
||||
else {
|
||||
INSN_LABEL(normal_dispatch):
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idAREF, 1, obj);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
tmp_id = idAREF;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(1, idAREF, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2171,16 +2191,10 @@ opt_aset
|
|||
}
|
||||
else {
|
||||
INSN_LABEL(normal_dispatch):
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idASET, 2, obj, set);
|
||||
#else
|
||||
PUSH(recv);
|
||||
PUSH(obj);
|
||||
PUSH(set);
|
||||
tmp_id = idASET;
|
||||
goto LABEL_IS_SC(start_init_in_send_for_opt_2);
|
||||
#endif
|
||||
CALL_SIMPLE_METHOD(2, idASET, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2212,12 +2226,8 @@ opt_length
|
|||
}
|
||||
else {
|
||||
INSN_LABEL(normal_dispatch):
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idLength, 0);
|
||||
#else
|
||||
val = rb_funcall(recv, idLength, 0);
|
||||
#endif
|
||||
PUSH(recv);
|
||||
CALL_SIMPLE_METHOD(0, idLength, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2262,12 +2272,8 @@ opt_succ
|
|||
}
|
||||
if (0) {
|
||||
INSN_LABEL(normal_dispatch):
|
||||
/* other */
|
||||
#ifdef YARV_AOT_COMPILED
|
||||
val = rb_funcall(recv, idSucc, 0);
|
||||
#else
|
||||
val = rb_funcall(recv, idSucc, 0);
|
||||
#endif
|
||||
PUSH(recv);
|
||||
CALL_SIMPLE_METHOD(0, idSucc, recv);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ class TestSuper < Test::Unit::TestCase
|
|||
def uu(a)
|
||||
class << self
|
||||
define_method(:tt) do |sym|
|
||||
super
|
||||
super(sym)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
172
vm.c
172
vm.c
|
@ -371,6 +371,38 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp, int num,
|
|||
return val;
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
vm_call_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv,
|
||||
VALUE klass, int argc, VALUE *argv)
|
||||
{
|
||||
rb_control_frame_t *cfp = th->cfp;
|
||||
rb_proc_t *proc;
|
||||
VALUE val;
|
||||
|
||||
/* control block frame */
|
||||
(cfp-2)->method_id = id;
|
||||
(cfp-2)->method_klass = klass;
|
||||
|
||||
GetProcPtr(procval, proc);
|
||||
val = th_invoke_proc(th, proc, recv, argc, argv);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
vm_method_missing(rb_thread_t *th, ID id, VALUE recv, int num,
|
||||
rb_block_t *blockptr, int opt)
|
||||
{
|
||||
rb_control_frame_t *reg_cfp = th->cfp;
|
||||
VALUE *argv = STACK_ADDR_FROM_TOP(num + 1);
|
||||
VALUE val;
|
||||
argv[0] = ID2SYM(id);
|
||||
th->method_missing_reason = opt;
|
||||
th->passed_block = blockptr;
|
||||
val = rb_funcall2(recv, idMethodMissing, num + 1, argv);
|
||||
POPN(num + 1);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void
|
||||
vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
|
||||
int argc, rb_block_t *blockptr, VALUE flag,
|
||||
|
@ -428,6 +460,110 @@ vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
|
|||
}
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
|
||||
int num, rb_block_t *blockptr, VALUE flag,
|
||||
ID id, NODE *mn, VALUE recv, VALUE klass)
|
||||
{
|
||||
VALUE val;
|
||||
|
||||
start_method_dispatch:
|
||||
|
||||
/* method missing */
|
||||
if (mn == 0) {
|
||||
if (id == idMethodMissing) {
|
||||
rb_bug("method missing");
|
||||
}
|
||||
else {
|
||||
int stat = 0;
|
||||
if (flag & VM_CALL_VCALL_BIT) {
|
||||
stat |= NOEX_VCALL;
|
||||
}
|
||||
if (flag & VM_CALL_SUPER_BIT) {
|
||||
stat |= NOEX_SUPER;
|
||||
}
|
||||
val = vm_method_missing(th, id, recv, num, blockptr, stat);
|
||||
}
|
||||
}
|
||||
else if (!(flag & VM_CALL_FCALL_BIT) &&
|
||||
(mn->nd_noex & NOEX_MASK) & NOEX_PRIVATE) {
|
||||
int stat = NOEX_PRIVATE;
|
||||
if (flag & VM_CALL_VCALL_BIT) {
|
||||
stat |= NOEX_VCALL;
|
||||
}
|
||||
val = vm_method_missing(th, id, recv, num, blockptr, stat);
|
||||
}
|
||||
else if ((mn->nd_noex & NOEX_MASK) & NOEX_PROTECTED) {
|
||||
VALUE defined_class = mn->nd_clss;
|
||||
|
||||
if (TYPE(defined_class) == T_ICLASS) {
|
||||
defined_class = RBASIC(defined_class)->klass;
|
||||
}
|
||||
|
||||
if (!rb_obj_is_kind_of(cfp->self, rb_class_real(defined_class))) {
|
||||
val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED);
|
||||
}
|
||||
else {
|
||||
goto normal_method_dispatch;
|
||||
}
|
||||
}
|
||||
|
||||
/* dispatch method */
|
||||
else {
|
||||
NODE *node;
|
||||
normal_method_dispatch:
|
||||
|
||||
node = mn->nd_body;
|
||||
switch (nd_type(node)) {
|
||||
case RUBY_VM_METHOD_NODE:{
|
||||
vm_setup_method(th, cfp, num, blockptr, flag, (VALUE)node->nd_body, recv, klass);
|
||||
return Qundef;
|
||||
}
|
||||
case NODE_CFUNC:{
|
||||
val = vm_call_cfunc(th, cfp, num, id, recv, klass, node, blockptr);
|
||||
break;
|
||||
}
|
||||
case NODE_ATTRSET:{
|
||||
val = rb_ivar_set(recv, node->nd_vid, *(cfp->sp - 1));
|
||||
cfp->sp -= 2;
|
||||
break;
|
||||
}
|
||||
case NODE_IVAR:{
|
||||
val = rb_ivar_get(recv, node->nd_vid);
|
||||
cfp->sp -= 1;
|
||||
break;
|
||||
}
|
||||
case NODE_BMETHOD:{
|
||||
VALUE *argv = cfp->sp - num;
|
||||
val = vm_call_bmethod(th, id, node->nd_cval, recv, klass, num, argv);
|
||||
cfp->sp += - num - 1;
|
||||
break;
|
||||
}
|
||||
case NODE_ZSUPER:{
|
||||
klass = RCLASS(mn->nd_clss)->super;
|
||||
mn = rb_method_node(klass, id);
|
||||
|
||||
if (mn != 0) {
|
||||
goto normal_method_dispatch;
|
||||
}
|
||||
else {
|
||||
goto start_method_dispatch;
|
||||
}
|
||||
}
|
||||
default:{
|
||||
printf("node: %s\n", ruby_node_name(nd_type(node)));
|
||||
rb_bug("eval_invoke_method: unreachable");
|
||||
/* unreachable */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RUBY_VM_CHECK_INTS();
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/* Env */
|
||||
|
||||
static void
|
||||
|
@ -735,23 +871,6 @@ th_make_proc(rb_thread_t *th,
|
|||
return procval;
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
th_invoke_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv,
|
||||
VALUE klass, int argc, VALUE *argv)
|
||||
{
|
||||
rb_control_frame_t *cfp = th->cfp;
|
||||
rb_proc_t *proc;
|
||||
VALUE val;
|
||||
|
||||
/* control block frame */
|
||||
(cfp-2)->method_id = id;
|
||||
(cfp-2)->method_klass = klass;
|
||||
|
||||
GetProcPtr(procval, proc);
|
||||
val = th_invoke_proc(th, proc, recv, argc, argv);
|
||||
return val;
|
||||
}
|
||||
|
||||
VALUE
|
||||
th_call0(rb_thread_t *th, VALUE klass, VALUE recv,
|
||||
VALUE id, ID oid, int argc, const VALUE *argv,
|
||||
|
@ -829,8 +948,8 @@ th_call0(rb_thread_t *th, VALUE klass, VALUE recv,
|
|||
break;
|
||||
}
|
||||
case NODE_BMETHOD:{
|
||||
val = th_invoke_bmethod(th, id, body->nd_cval,
|
||||
recv, klass, argc, (VALUE *)argv);
|
||||
val = vm_call_bmethod(th, id, body->nd_cval,
|
||||
recv, klass, argc, (VALUE *)argv);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1555,21 +1674,6 @@ eval_define_method(rb_thread_t *th, VALUE obj,
|
|||
INC_VM_STATE_VERSION();
|
||||
}
|
||||
|
||||
EVALBODY_HELPER_FUNCTION VALUE
|
||||
eval_method_missing(rb_thread_t *th, ID id, VALUE recv, int num,
|
||||
rb_block_t *blockptr, int opt)
|
||||
{
|
||||
rb_control_frame_t *reg_cfp = th->cfp;
|
||||
VALUE *argv = STACK_ADDR_FROM_TOP(num + 1);
|
||||
VALUE val;
|
||||
argv[0] = ID2SYM(id);
|
||||
th->method_missing_reason = opt;
|
||||
th->passed_block = blockptr;
|
||||
val = rb_funcall2(recv, idMethodMissing, num + 1, argv);
|
||||
POPN(num + 1);
|
||||
return val;
|
||||
}
|
||||
|
||||
EVALBODY_HELPER_FUNCTION NODE *
|
||||
eval_method_search(VALUE id, VALUE klass, IC ic)
|
||||
{
|
||||
|
|
|
@ -76,10 +76,6 @@ th_eval(rb_thread_t *th, VALUE initial)
|
|||
#define SET_PC(x) (reg_cfp->pc = REG_PC = (x))
|
||||
#endif
|
||||
|
||||
ID tmp_id;
|
||||
rb_block_t *tmp_blockptr;
|
||||
rb_num_t tmp_num;
|
||||
|
||||
#if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
|
||||
#include "vmtc.inc"
|
||||
if (th == 0) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче