declare ::VM::InstructionSequence
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); }
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); }
static VALUE iseq_s_compile_option_get(VALUE self) { return make_compile_option_value(&COMPILE_OPTION_DEFAULT); }
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; }
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; }
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; }
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); }
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); }
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; }
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; }
static VALUE iseq_eval(VALUE self) { rb_secure(1); return rb_iseq_eval(self); }
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)); }