/*
 *  call-seq:
 *     meth.call(args, ...)    => obj
 *     meth[args, ...]         => obj
 *  
 *  Invokes the <i>meth</i> with the specified arguments, returning the
 *  method's return value.
 *     
 *     m = 12.method("+")
 *     m.call(3)    #=> 15
 *     m.call(20)   #=> 32
 */

VALUE
rb_method_call(int argc, VALUE *argv, VALUE method)
{
    VALUE result = Qnil;        /* OK */
    struct METHOD *data;
    int state;
    volatile int safe = -1;

    Data_Get_Struct(method, struct METHOD, data);
    if (data->recv == Qundef) {
        rb_raise(rb_eTypeError, "can't call unbound method; bind first");
    }
    PUSH_TAG();
    if (OBJ_TAINTED(method)) {
        safe = rb_safe_level();
        if (rb_safe_level() < 4) {
            rb_set_safe_level_force(4);
        }
    }
    if ((state = EXEC_TAG()) == 0) {
        VALUE rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
                         int argc, const VALUE *argv, const NODE *body, int nosuper);

        PASS_PASSED_BLOCK();
        result = rb_vm_call(GET_THREAD(), data->oclass, data->recv, data->id, data->oid,
                            argc, argv, data->body, 0);
    }
    POP_TAG();
    if (safe >= 0)
        rb_set_safe_level_force(safe);
    if (state)
        JUMP_TAG(state);
    return result;
}