In Files

  • iseq.c

RubyVM::InstructionSequence

declare ::VM::InstructionSequence

Public Class Methods

compile(p1, p2 = v2, p3 = v3, p4 = v4) click to toggle source
 
               static VALUE
iseq_s_compile(int argc, VALUE *argv, VALUE self)
{
    VALUE src, file = Qnil, line = INT2FIX(1), opt = Qnil;

    rb_secure(1);

    rb_scan_args(argc, argv, "13", &src, &file, &line, &opt);
    file = file == Qnil ? rb_str_new2("<compiled>") : file;
    line = line == Qnil ? INT2FIX(1) : line;

    return rb_iseq_compile_with_option(src, file, line, opt);
}
            
compile_file(p1, p2 = v2) click to toggle source
 
               static VALUE
iseq_s_compile_file(int argc, VALUE *argv, VALUE self)
{
    VALUE file, line = INT2FIX(1), opt = Qnil;
    VALUE parser;
    VALUE f;
    NODE *node;
    const char *fname;
    rb_compile_option_t option;

    rb_secure(1);
    rb_scan_args(argc, argv, "11", &file, &opt);
    FilePathValue(file);
    fname = StringValueCStr(file);

    f = rb_file_open_str(file, "r");

    parser = rb_parser_new();
    node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));
    make_compile_option(&option, opt);
    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file, line, Qfalse,
                                ISEQ_TYPE_TOP, &option);
}
            
compile_option() click to toggle source
 
               static VALUE
iseq_s_compile_option_get(VALUE self)
{
    return make_compile_option_value(&COMPILE_OPTION_DEFAULT);
}
            
compile_option=(p1) click to toggle source
 
               static VALUE
iseq_s_compile_option_set(VALUE self, VALUE opt)
{
    rb_compile_option_t option;
    rb_secure(1);
    make_compile_option(&option, opt);
    COMPILE_OPTION_DEFAULT = option;
    return opt;
}
            
disasm(p1) click to toggle source
 
               static VALUE
iseq_s_disasm(VALUE klass, VALUE body)
{
    extern NODE *rb_method_body(VALUE body);
    NODE *node;
    VALUE ret = Qnil;

    rb_secure(1);

    if ((node = rb_method_body(body)) != 0) {
        if (nd_type(node) == RUBY_VM_METHOD_NODE) {
            VALUE iseqval = (VALUE)node->nd_body;
            ret = rb_iseq_disasm(iseqval);
        }
    }

    return ret;
}
            
disassemble(p1) click to toggle source
 
               static VALUE
iseq_s_disasm(VALUE klass, VALUE body)
{
    extern NODE *rb_method_body(VALUE body);
    NODE *node;
    VALUE ret = Qnil;

    rb_secure(1);

    if ((node = rb_method_body(body)) != 0) {
        if (nd_type(node) == RUBY_VM_METHOD_NODE) {
            VALUE iseqval = (VALUE)node->nd_body;
            ret = rb_iseq_disasm(iseqval);
        }
    }

    return ret;
}
            
load(p1, p2 = v2) click to toggle source
 
               static VALUE
iseq_s_load(int argc, VALUE *argv, VALUE self)
{
    VALUE data, opt=Qnil;
    rb_scan_args(argc, argv, "11", &data, &opt);

    return iseq_load(self, data, 0, opt);
}
            
new(p1, p2 = v2, p3 = v3, p4 = v4) click to toggle source
 
               static VALUE
iseq_s_compile(int argc, VALUE *argv, VALUE self)
{
    VALUE src, file = Qnil, line = INT2FIX(1), opt = Qnil;

    rb_secure(1);

    rb_scan_args(argc, argv, "13", &src, &file, &line, &opt);
    file = file == Qnil ? rb_str_new2("<compiled>") : file;
    line = line == Qnil ? INT2FIX(1) : line;

    return rb_iseq_compile_with_option(src, file, line, opt);
}
            

Public Instance Methods

disasm() click to toggle source
 
               VALUE
rb_iseq_disasm(VALUE self)
{
    rb_iseq_t *iseqdat = iseq_check(self);
    VALUE *iseq;
    VALUE str = rb_str_new(0, 0);
    VALUE child = rb_ary_new();
    unsigned long size;
    int i;
    long l;
    ID *tbl;
    enum {header_minlen = 72};

    rb_secure(1);

    iseq = iseqdat->iseq;
    size = iseqdat->iseq_size;

    rb_str_cat2(str, "== disasm: ");

    rb_str_concat(str, iseq_inspect(iseqdat->self));
    if ((l = RSTRING_LEN(str)) < header_minlen) {
        rb_str_resize(str, header_minlen);
        memset(RSTRING_PTR(str) + l, '=', header_minlen - l);
    }
    rb_str_cat2(str, "\n");

    /* show catch table information */
    if (iseqdat->catch_table_size != 0) {
        rb_str_cat2(str, "== catch table\n");
    }
    for (i = 0; i < iseqdat->catch_table_size; i++) {
        struct iseq_catch_table_entry *entry = &iseqdat->catch_table[i];
        rb_str_catf(str,
                    "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
                    catch_type((int)entry->type), (int)entry->start,
                    (int)entry->end, (int)entry->sp, (int)entry->cont);
        if (entry->iseq) {
            rb_str_concat(str, rb_iseq_disasm(entry->iseq));
        }
    }
    if (iseqdat->catch_table_size != 0) {
        rb_str_cat2(str, "|-------------------------------------"
                    "-----------------------------------\n");
    }

    /* show local table information */
    tbl = iseqdat->local_table;

    if (tbl) {
        rb_str_catf(str,
                    "local table (size: %d, argc: %d "
                    "[opts: %d, rest: %d, post: %d, block: %d] s%d)\n",
                    iseqdat->local_size, iseqdat->argc,
                    iseqdat->arg_opts, iseqdat->arg_rest,
                    iseqdat->arg_post_len, iseqdat->arg_block,
                    iseqdat->arg_simple);

        for (i = 0; i < iseqdat->local_table_size; i++) {
            const char *name = rb_id2name(tbl[i]);
            char info[0x100];
            char argi[0x100] = "";
            char opti[0x100] = "";

            if (iseqdat->arg_opts) {
                int argc = iseqdat->argc;
                int opts = iseqdat->arg_opts;
                if (i >= argc && i < argc + opts - 1) {
                    snprintf(opti, sizeof(opti), "Opt=%ld",
                             iseqdat->arg_opt_table[i - argc]);
                }
            }

            snprintf(argi, sizeof(argi), "%s%s%s%s%s", /* arg, opts, rest, post  block */
                     iseqdat->argc > i ? "Arg" : "",
                     opti,
                     iseqdat->arg_rest == i ? "Rest" : "",
                     (iseqdat->arg_post_start <= i &&
                      i < iseqdat->arg_post_start + iseqdat->arg_post_len) ? "Post" : "",
                     iseqdat->arg_block == i ? "Block" : "");

            snprintf(info, sizeof(info), "%s%s%s%s", name ? name : "?",
                     *argi ? "<" : "", argi, *argi ? ">" : "");

            rb_str_catf(str, "[%2d] %-11s", iseqdat->local_size - i, info);
        }
        rb_str_cat2(str, "\n");
    }

    /* show each line */
    for (i = 0; i < size;) {
        i += rb_iseq_disasm_insn(str, iseq, i, iseqdat, child);
    }

    for (i = 0; i < RARRAY_LEN(child); i++) {
        VALUE isv = rb_ary_entry(child, i);
        rb_str_concat(str, rb_iseq_disasm(isv));
    }

    return str;
}
            
disassemble() click to toggle source
 
               VALUE
rb_iseq_disasm(VALUE self)
{
    rb_iseq_t *iseqdat = iseq_check(self);
    VALUE *iseq;
    VALUE str = rb_str_new(0, 0);
    VALUE child = rb_ary_new();
    unsigned long size;
    int i;
    long l;
    ID *tbl;
    enum {header_minlen = 72};

    rb_secure(1);

    iseq = iseqdat->iseq;
    size = iseqdat->iseq_size;

    rb_str_cat2(str, "== disasm: ");

    rb_str_concat(str, iseq_inspect(iseqdat->self));
    if ((l = RSTRING_LEN(str)) < header_minlen) {
        rb_str_resize(str, header_minlen);
        memset(RSTRING_PTR(str) + l, '=', header_minlen - l);
    }
    rb_str_cat2(str, "\n");

    /* show catch table information */
    if (iseqdat->catch_table_size != 0) {
        rb_str_cat2(str, "== catch table\n");
    }
    for (i = 0; i < iseqdat->catch_table_size; i++) {
        struct iseq_catch_table_entry *entry = &iseqdat->catch_table[i];
        rb_str_catf(str,
                    "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
                    catch_type((int)entry->type), (int)entry->start,
                    (int)entry->end, (int)entry->sp, (int)entry->cont);
        if (entry->iseq) {
            rb_str_concat(str, rb_iseq_disasm(entry->iseq));
        }
    }
    if (iseqdat->catch_table_size != 0) {
        rb_str_cat2(str, "|-------------------------------------"
                    "-----------------------------------\n");
    }

    /* show local table information */
    tbl = iseqdat->local_table;

    if (tbl) {
        rb_str_catf(str,
                    "local table (size: %d, argc: %d "
                    "[opts: %d, rest: %d, post: %d, block: %d] s%d)\n",
                    iseqdat->local_size, iseqdat->argc,
                    iseqdat->arg_opts, iseqdat->arg_rest,
                    iseqdat->arg_post_len, iseqdat->arg_block,
                    iseqdat->arg_simple);

        for (i = 0; i < iseqdat->local_table_size; i++) {
            const char *name = rb_id2name(tbl[i]);
            char info[0x100];
            char argi[0x100] = "";
            char opti[0x100] = "";

            if (iseqdat->arg_opts) {
                int argc = iseqdat->argc;
                int opts = iseqdat->arg_opts;
                if (i >= argc && i < argc + opts - 1) {
                    snprintf(opti, sizeof(opti), "Opt=%ld",
                             iseqdat->arg_opt_table[i - argc]);
                }
            }

            snprintf(argi, sizeof(argi), "%s%s%s%s%s", /* arg, opts, rest, post  block */
                     iseqdat->argc > i ? "Arg" : "",
                     opti,
                     iseqdat->arg_rest == i ? "Rest" : "",
                     (iseqdat->arg_post_start <= i &&
                      i < iseqdat->arg_post_start + iseqdat->arg_post_len) ? "Post" : "",
                     iseqdat->arg_block == i ? "Block" : "");

            snprintf(info, sizeof(info), "%s%s%s%s", name ? name : "?",
                     *argi ? "<" : "", argi, *argi ? ">" : "");

            rb_str_catf(str, "[%2d] %-11s", iseqdat->local_size - i, info);
        }
        rb_str_cat2(str, "\n");
    }

    /* show each line */
    for (i = 0; i < size;) {
        i += rb_iseq_disasm_insn(str, iseq, i, iseqdat, child);
    }

    for (i = 0; i < RARRAY_LEN(child); i++) {
        VALUE isv = rb_ary_entry(child, i);
        rb_str_concat(str, rb_iseq_disasm(isv));
    }

    return str;
}
            
eval() click to toggle source
 
               static VALUE
iseq_eval(VALUE self)
{
    rb_secure(1);
    return rb_iseq_eval(self);
}
            
inspect() click to toggle source
 
               static VALUE
iseq_inspect(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    if (!iseq->name) {
        return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self));
    }

    return rb_sprintf("<%s:%s@%s>",
                      rb_obj_classname(self),
                      RSTRING_PTR(iseq->name), RSTRING_PTR(iseq->filename));
}
            
to_a() click to toggle source
 
               static VALUE
iseq_to_a(VALUE self)
{
    rb_iseq_t *iseq = iseq_check(self);
    rb_secure(1);
    return iseq_data_to_ary(iseq);
}