Esempio n. 1
0
NODE *
rb_method_node(VALUE klass, ID id)
{
    struct cache_entry *ent;

    ent = cache + EXPR1(klass, id);
    if (ent->mid == id && ent->klass == klass && ent->method) {
	return ent->method;
    }

    return rb_get_method_body(klass, id, 0);
}
Esempio n. 2
0
static VALUE
mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)
{
    VALUE method;
    NODE *body;
    struct METHOD *data;
    VALUE rclass = klass;
    ID oid = id;

  again:
    if ((body = rb_get_method_body(klass, id, 0)) == 0) {
	rb_print_undef(rclass, oid, 0);
    }
    if (scope && (body->nd_noex & NOEX_MASK) != NOEX_PUBLIC) {
	rb_print_undef(rclass, oid, (body->nd_noex & NOEX_MASK));
    }

    klass = body->nd_clss;
    body = body->nd_body;

    if (nd_type(body) == NODE_ZSUPER) {
	klass = RCLASS_SUPER(klass);
	goto again;
    }

    while (rclass != klass &&
	   (RCLASS_SINGLETON(rclass) || TYPE(rclass) == T_ICLASS)) {
	rclass = RCLASS_SUPER(rclass);
    }
    if (TYPE(klass) == T_ICLASS)
	klass = RBASIC(klass)->klass;
    method = Data_Make_Struct(mclass, struct METHOD, bm_mark, -1, data);
    data->oclass = klass;
    GC_WB(&data->recv, obj);

    data->id = id;
    data->body = body;
    data->rclass = rclass;
    data->oid = oid;
#if !WITH_OBJC
    OBJ_INFECT(method, klass);
#endif

    return method;
}
Esempio n. 3
0
static VALUE
mnew(VALUE klass, VALUE obj, ID id, VALUE mklass)
{
    VALUE method;
    NODE *body;
    struct METHOD *data;
    VALUE rklass = klass;
    ID oid = id;

  again:
    if ((body = rb_get_method_body(klass, id, 0)) == 0) {
	print_undef(rklass, oid);
    }

    klass = body->nd_clss;
    body = body->nd_body;

    if (nd_type(body) == NODE_ZSUPER) {
	klass = RCLASS(klass)->super;
	goto again;
    }

    while (rklass != klass &&
	   (FL_TEST(rklass, FL_SINGLETON) || TYPE(rklass) == T_ICLASS)) {
	rklass = RCLASS(rklass)->super;
    }
    if (TYPE(klass) == T_ICLASS)
	klass = RBASIC(klass)->klass;
    method = Data_Make_Struct(mklass, struct METHOD, bm_mark, -1, data);
    data->klass = klass;
    data->recv = obj;

    data->id = id;
    data->body = body;
    data->rklass = rklass;
    data->oid = oid;
    OBJ_INFECT(method, klass);

    return method;
}
Esempio n. 4
0
static inline VALUE
rb_call0(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv,
	 int scope, VALUE self)
{
    NODE *body, *method;
    int noex;
    ID id = mid;
    struct cache_entry *ent;
    rb_thread_t *th = GET_THREAD();

    if (!klass) {
	rb_raise(rb_eNotImpError,
		 "method `%s' called on terminated object (%p)",
		 rb_id2name(mid), (void *)recv);
    }
    /* is it in the method cache? */
    ent = cache + EXPR1(klass, mid);

    if (ent->mid == mid && ent->klass == klass) {
	if (!ent->method)
	    return method_missing(recv, mid, argc, argv,
				  scope == 2 ? NOEX_VCALL : 0);
	id = ent->mid0;
	noex = ent->method->nd_noex;
	klass = ent->method->nd_clss;
	body = ent->method->nd_body;
    }
    else if ((method = rb_get_method_body(klass, id, &id)) != 0) {
	noex = method->nd_noex;
	klass = method->nd_clss;
	body = method->nd_body;
    }
    else {
	if (scope == 3) {
	    return method_missing(recv, mid, argc, argv, NOEX_SUPER);
	}
	return method_missing(recv, mid, argc, argv,
			      scope == 2 ? NOEX_VCALL : 0);
    }
    

    if (mid != idMethodMissing) {
	/* receiver specified form for private method */
	if (UNLIKELY(noex)) {
	    if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == 0) {
		return method_missing(recv, mid, argc, argv, NOEX_PRIVATE);
	    }

	    /* self must be kind of a specified form for protected method */
	    if (((noex & NOEX_MASK) & NOEX_PROTECTED) && scope == 0) {
		VALUE defined_class = klass;
		
		if (TYPE(defined_class) == T_ICLASS) {
		    defined_class = RBASIC(defined_class)->klass;
		}

		if (self == Qundef) {
		    self = th->cfp->self;
		}
		if (!rb_obj_is_kind_of(self, rb_class_real(defined_class))) {
		    return method_missing(recv, mid, argc, argv, NOEX_PROTECTED);
		}
	    }

	    if (NOEX_SAFE(noex) > th->safe_level) {
		rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(mid));
	    }
	}
    }

    stack_check();
    return vm_call0(th, klass, recv, mid, id, argc, argv, body, noex & NOEX_NOSUPER);
}