コード例 #1
0
rb_method_entry_t *
rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me,
			  VALUE *defined_class_ptr)
{
    if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
	VALUE refinement;
	rb_method_entry_t *tmp_me;

	refinement = find_refinement(refinements, me->klass);
	if (NIL_P(refinement)) {
	    return get_original_method_entry(refinements, me,
					     defined_class_ptr);
	}
	tmp_me = rb_method_entry(refinement, me->called_id,
				 defined_class_ptr);
	if (tmp_me && tmp_me->def->type != VM_METHOD_TYPE_REFINED) {
	    return tmp_me;
	}
	else {
	    return get_original_method_entry(refinements, me,
					     defined_class_ptr);
	}
    }
    else {
	return (rb_method_entry_t *)me;
    }
}
コード例 #2
0
int
rb_method_basic_definition_p(VALUE klass, ID id)
{
    const rb_method_entry_t *me = rb_method_entry(klass, id, 0);
    if (me && (me->flag & NOEX_BASIC))
	return 1;
    return 0;
}
コード例 #3
0
ファイル: class.c プロジェクト: fi8on/ruby
int
rb_obj_basic_to_s_p(VALUE obj)
{
    const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"));
    if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
	me->def->body.cfunc.func == rb_any_to_s)
	return 1;
    return 0;
}
コード例 #4
0
static VALUE
check_definition(VALUE mod, ID mid, rb_method_flag_t noex)
{
    const rb_method_entry_t *me;
    me = rb_method_entry(mod, mid);
    if (me) {
	if (VISI_CHECK(me->flag, noex))
	    return Qtrue;
    }
    return Qfalse;
}
コード例 #5
0
rb_alloc_func_t
rb_get_alloc_func(VALUE klass)
{
    rb_method_entry_t *me;
    Check_Type(klass, T_CLASS);
    me = rb_method_entry(CLASS_OF(klass), ID_ALLOCATOR);

    if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC) {
	return (rb_alloc_func_t)me->def->body.cfunc.func;
    }
    else {
	return 0;
    }
}
コード例 #6
0
rb_method_entry_t *
rb_method_entry_with_refinements(VALUE klass, ID id,
				 VALUE *defined_class_ptr)
{
    VALUE defined_class;
    rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class);

    if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
	NODE *cref = rb_vm_cref();
	VALUE refinements = cref ? cref->nd_refinements : Qnil;

	me = rb_resolve_refined_method(refinements, me, &defined_class);
    }
    if (defined_class_ptr)
	*defined_class_ptr = defined_class;
    return me;
}
コード例 #7
0
int
rb_method_boundp(VALUE klass, ID id, int ex)
{
    rb_method_entry_t *me = rb_method_entry(klass, id);

    if (me != 0) {
	if ((ex & ~NOEX_RESPONDS) && (me->flag & NOEX_PRIVATE)) {
	    return FALSE;
	}
	if (!me->def) return 0;
	if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
	    if (ex & NOEX_RESPONDS) return 2;
	    return 0;
	}
	return 1;
    }
    return 0;
}
コード例 #8
0
rb_method_entry_t *
rb_method_entry_without_refinements(VALUE klass, ID id,
				    VALUE *defined_class_ptr)
{
    VALUE defined_class;
    rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class);

    if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
	me = rb_resolve_refined_method(Qnil, me, &defined_class);
    }
    if (defined_class_ptr)
	*defined_class_ptr = defined_class;
    if (UNDEFINED_METHOD_ENTRY_P(me)) {
	return 0;
    }
    else {
	return me;
    }
}
コード例 #9
0
static rb_method_entry_t *
get_original_method_entry(VALUE refinements,
			  const rb_method_entry_t *me,
			  VALUE *defined_class_ptr)
{
    VALUE super;

    if (me->def->body.orig_me) {
	return me->def->body.orig_me;
    }
    else if (!(super = RCLASS_SUPER(me->klass))) {
	return 0;
    }
    else {
	rb_method_entry_t *tmp_me;
	tmp_me = rb_method_entry(super, me->called_id,
				 defined_class_ptr);
	return rb_resolve_refined_method(refinements, tmp_me,
					 defined_class_ptr);
    }
}
コード例 #10
0
static inline VALUE
vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
	       int num, const rb_block_t *blockptr, VALUE flag,
	       ID id, const rb_method_entry_t *me, VALUE recv)
{
    VALUE val;

  start_method_dispatch:

    if (me != 0) {
	if ((me->flag == 0)) {
	  normal_method_dispatch:
	    switch (me->def->type) {
	      case VM_METHOD_TYPE_ISEQ:{
		vm_setup_method(th, cfp, recv, num, blockptr, flag, me);
		return Qundef;
	      }
	      case VM_METHOD_TYPE_NOTIMPLEMENTED:
	      case VM_METHOD_TYPE_CFUNC:{
		val = vm_call_cfunc(th, cfp, num, recv, blockptr, me);
		break;
	      }
	      case VM_METHOD_TYPE_ATTRSET:{
		if (num != 1) {
		    rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", num);
		}
		val = rb_ivar_set(recv, me->def->body.attr.id, *(cfp->sp - 1));
		cfp->sp -= 2;
		break;
	      }
	      case VM_METHOD_TYPE_IVAR:{
		if (num != 0) {
		    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", num);
		}
		val = rb_attr_get(recv, me->def->body.attr.id);
		cfp->sp -= 1;
		break;
	      }
	      case VM_METHOD_TYPE_MISSING:{
		VALUE *argv = ALLOCA_N(VALUE, num+1);
		argv[0] = ID2SYM(me->def->original_id);
		MEMCPY(argv+1, cfp->sp - num, VALUE, num);
		cfp->sp += - num - 1;
		th->passed_block = blockptr;
		val = rb_funcall2(recv, rb_intern("method_missing"), num+1, argv);
		break;
	      }
	      case VM_METHOD_TYPE_BMETHOD:{
		VALUE *argv = ALLOCA_N(VALUE, num);
		MEMCPY(argv, cfp->sp - num, VALUE, num);
		cfp->sp += - num - 1;
		val = vm_call_bmethod(th, recv, num, argv, blockptr, me);
		break;
	      }
	      case VM_METHOD_TYPE_ZSUPER:{
		VALUE klass = RCLASS_SUPER(me->klass);
		me = rb_method_entry(klass, id);

		if (me != 0) {
		    goto normal_method_dispatch;
		}
		else {
		    goto start_method_dispatch;
		}
	      }
	      case VM_METHOD_TYPE_OPTIMIZED:{
		switch (me->def->body.optimize_type) {
		  case OPTIMIZED_METHOD_TYPE_SEND: {
		    rb_control_frame_t *reg_cfp = cfp;
		    rb_num_t i = num - 1;
		    VALUE sym;

		    if (num == 0) {
			rb_raise(rb_eArgError, "no method name given");
		    }

		    sym = TOPN(i);
		    id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym);
		    /* shift arguments */
		    if (i > 0) {
			MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i);
		    }
		    me = rb_method_entry(CLASS_OF(recv), id);
		    num -= 1;
		    DEC_SP(1);
		    flag |= VM_CALL_FCALL_BIT | VM_CALL_OPT_SEND_BIT;

		    goto start_method_dispatch;
		  }
		  case OPTIMIZED_METHOD_TYPE_CALL: {
		    rb_proc_t *proc;
		    int argc = num;
		    VALUE *argv = ALLOCA_N(VALUE, num);
		    GetProcPtr(recv, proc);
		    MEMCPY(argv, cfp->sp - num, VALUE, num);
		    cfp->sp -= num + 1;

		    val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr);
		    break;
		  }
		  default:
		    rb_bug("eval_invoke_method: unsupported optimized method type (%d)",
			   me->def->body.optimize_type);
		}
		break;
	      }
	      default:{
		rb_bug("eval_invoke_method: unsupported method type (%d)", me->def->type);
		break;
	      }
	    }
	}
	else {
	    int noex_safe;

	    if (!(flag & VM_CALL_FCALL_BIT) &&
		(me->flag & 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 (!(flag & VM_CALL_OPT_SEND_BIT) && (me->flag & NOEX_MASK) & NOEX_PROTECTED) {
		VALUE defined_class = me->klass;

		if (RB_TYPE_P(defined_class, T_ICLASS)) {
		    defined_class = RBASIC(defined_class)->klass;
		}

		if (!rb_obj_is_kind_of(cfp->self, defined_class)) {
		    val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED);
		}
		else {
		    goto normal_method_dispatch;
		}
	    }
	    else if ((noex_safe = NOEX_SAFE(me->flag)) > th->safe_level &&
		     (noex_safe > 2)) {
		rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(id));
	    }
	    else {
		goto normal_method_dispatch;
	    }
	}
    }
    else {
	/* method missing */
	int stat = 0;
	if (flag & VM_CALL_VCALL_BIT) {
	    stat |= NOEX_VCALL;
	}
	if (flag & VM_CALL_SUPER_BIT) {
	    stat |= NOEX_SUPER;
	}
	if (id == idMethodMissing) {
	    VALUE *argv = ALLOCA_N(VALUE, num);
	    vm_method_missing_args(th, argv, num - 1, 0, stat);
	    rb_raise_method_missing(th, num, argv, recv, stat);
	}
	else {
	    val = vm_method_missing(th, id, recv, num, blockptr, stat);
	}
    }

    RUBY_VM_CHECK_INTS();
    return val;
}