23 #define ISEQ_MAJOR_VERSION 1
24 #define ISEQ_MINOR_VERSION 2
28 #define hidden_obj_p(obj) (!SPECIAL_CONST_P(obj) && !RBASIC(obj)->klass)
184 if (type == ISEQ_TYPE_TOP) {
195 else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
198 else if (
RTEST(parent)) {
204 if (type == ISEQ_TYPE_TOP ||
205 type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
208 else if (
RTEST(parent)) {
220 if (type == ISEQ_TYPE_MAIN) {
237 iseq->
line_no = (
unsigned short)line_no;
279 if (
RTEST(coverages)) {
324 else if (opt ==
Qtrue) {
330 #define SET_COMPILE_OPTION(o, h, mem) \
331 { VALUE flag = rb_hash_aref((h), ID2SYM(rb_intern(#mem))); \
332 if (flag == Qtrue) { (o)->mem = 1; } \
333 else if (flag == Qfalse) { (o)->mem = 0; } \
335 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
336 { VALUE num = rb_hash_aref(opt, ID2SYM(rb_intern(#mem))); \
337 if (!NIL_P(num)) (o)->mem = NUM2INT(num); \
348 #undef SET_COMPILE_OPTION
349 #undef SET_COMPILE_OPTION_NUM
360 #define SET_COMPILE_OPTION(o, h, mem) \
361 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), (o)->mem ? Qtrue : Qfalse)
362 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
363 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), INT2NUM((o)->mem))
374 #undef SET_COMPILE_OPTION
375 #undef SET_COMPILE_OPTION_NUM
384 &COMPILE_OPTION_DEFAULT);
391 &COMPILE_OPTION_DEFAULT);
400 parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
414 prepare_iseq_build(iseq, name, filename, filepath, line_no, parent, type, bopt, option);
436 bopt, &COMPILE_OPTION_DEFAULT);
439 #define CHECK_ARRAY(v) rb_convert_type((v), T_ARRAY, "Array", "to_ary")
440 #define CHECK_STRING(v) rb_convert_type((v), T_STRING, "String", "to_str")
441 #define CHECK_SYMBOL(v) rb_convert_type((v), T_SYMBOL, "Symbol", "to_sym")
448 VALUE magic, version1, version2, format_type, misc;
489 iseq->
self = iseqval;
504 if (
st_lookup(type_map, type, &iseq_type) == 0) {
512 if (parent ==
Qnil) {
518 parent, (
enum iseq_type)iseq_type, 0, &option);
566 ISEQ_TYPE_EVAL, &option);
570 ISEQ_TYPE_TOP, &option);
587 rb_scan_args(argc, argv,
"14", &src, &file, &path, &line, &opt);
616 ISEQ_TYPE_TOP, &option);
625 COMPILE_OPTION_DEFAULT = option;
693 for (i = 0; i <
size; i++) {
702 static unsigned short
714 static unsigned short
720 for (i = 0; i <
size; i++) {
739 const char *
types = insn_op_types(insn);
740 char type = types[op_no];
767 if (insn == BIN(getdynamic) || insn == BIN(setdynamic)) {
771 for (i = 0; i < level; i++) {
831 rb_bug(
"rb_iseq_disasm: unknown operand type: %c", type);
844 VALUE insn = iseq[pos];
845 int len = insn_len(insn);
847 const char *
types = insn_op_types(insn);
849 const char *insn_name_buff;
851 insn_name_buff = insn_name(insn);
857 (
int)strcspn(insn_name_buff,
"_"), insn_name_buff);
860 for (j = 0; types[j]; j++) {
861 const char *types = insn_op_types(insn);
863 len, pos, &iseq[pos + j + 2],
875 if (line_no && line_no != prev) {
877 slen = (slen > 70) ? 0 : (70 - slen);
878 str =
rb_str_catf(str,
"%*s(%4d)", (
int)slen,
"", line_no);
885 slen = (slen > 60) ? 0 : (60 - slen);
887 (
int)slen,
"", entry->
line_no, entry->
sp);
904 case CATCH_TYPE_RESCUE:
906 case CATCH_TYPE_ENSURE:
908 case CATCH_TYPE_RETRY:
910 case CATCH_TYPE_BREAK:
912 case CATCH_TYPE_REDO:
914 case CATCH_TYPE_NEXT:
917 rb_bug(
"unknown catch type (%d)", type);
934 enum {header_minlen = 72};
938 iseq = iseqdat->
iseq;
946 memset(
RSTRING_PTR(str) + l,
'=', header_minlen - l);
957 "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
959 (
int)entry->
end, (
int)entry->
sp, (
int)entry->
cont);
965 rb_str_cat2(str,
"|-------------------------------------"
966 "-----------------------------------\n");
974 "local table (size: %d, argc: %d "
975 "[opts: %d, rest: %d, post: %d, block: %d] s%d)\n",
984 char argi[0x100] =
"";
985 char opti[0x100] =
"";
990 if (i >= argc && i < argc + opts - 1) {
996 snprintf(argi,
sizeof(argi),
"%s%s%s%s%s",
997 iseqdat->
argc > i ?
"Arg" :
"",
999 iseqdat->
arg_rest == i ?
"Rest" :
"",
1001 i < iseqdat->arg_post_start + iseqdat->
arg_post_len) ?
"Post" :
"",
1002 iseqdat->
arg_block == i ?
"Block" :
"");
1004 snprintf(info,
sizeof(info),
"%s%s%s%s", name ? name :
"?",
1005 *argi ?
"<" :
"", argi, *argi ?
">" :
"");
1013 for (n = 0; n <
size;) {
1054 rb_bug(
"unknown node (%d)", node);
1059 #define DECL_SYMBOL(name) \
1060 static VALUE sym_##name
1062 #define INIT_SYMBOL(name) \
1063 sym_##name = ID2SYM(rb_intern(#name))
1069 char buff[8 + (
sizeof(idx) *
CHAR_BIT * 32 / 100)];
1071 snprintf(buff,
sizeof(buff),
"label_%lu", idx);
1118 static VALUE insn_syms[VM_INSTRUCTION_SIZE];
1133 for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
1148 switch(iseq->
type) {
1149 case ISEQ_TYPE_TOP: type = sym_top;
break;
1150 case ISEQ_TYPE_METHOD: type = sym_method;
break;
1151 case ISEQ_TYPE_BLOCK: type = sym_block;
break;
1152 case ISEQ_TYPE_CLASS: type = sym_class;
break;
1153 case ISEQ_TYPE_RESCUE: type = sym_rescue;
break;
1154 case ISEQ_TYPE_ENSURE: type = sym_ensure;
break;
1155 case ISEQ_TYPE_EVAL: type = sym_eval;
break;
1156 case ISEQ_TYPE_MAIN: type = sym_main;
break;
1157 case ISEQ_TYPE_DEFINED_GUARD: type = sym_defined_guard;
break;
1158 default:
rb_bug(
"unsupported iseq type");
1208 for (seq = iseq->
iseq; seq < iseq->iseq + iseq->
iseq_size; ) {
1209 VALUE insn = *seq++;
1210 int j,
len = insn_len(insn);
1211 VALUE *nseq = seq + len - 1;
1215 for (j=0; j<len-1; j++, seq++) {
1216 switch (insn_op_type(insn, j)) {
1218 unsigned long idx = nseq - iseq->
iseq + *seq;
1266 unsigned long idx = nseq - iseq->
iseq + pos;
1275 rb_bug(
"unknown operand: %c", insn_op_type(insn, j));
1310 if (
st_lookup(labels_table, pos, &label)) {
1361 iseq1->
self = newiseq;
1363 iseq1->
orig = iseqval;
1373 iseq1->
klass = newcbase;
1384 ID req, opt, rest, block;
1385 #define PARAM_TYPE(type) rb_ary_push(a = rb_ary_new2(2), ID2SYM(type))
1386 #define PARAM_ID(i) iseq->local_table[(i)]
1387 #define PARAM(i, type) ( \
1389 rb_id2name(PARAM_ID(i)) ? \
1390 rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \
1396 for (i = 0; i < iseq->
argc; i++) {
1403 for (i = 0; i < iseq->
argc; i++) {
1411 for (s = i; i < r; i++) {
1449 const char **local_table,
1450 const VALUE *arg_opt_table,
1453 const char *filename,
1454 const unsigned short line_no)
1462 *iseq = *iseq_template;
1468 iseq->
self = iseqval;
1473 iseq->
iseq[
i] = BIN(opt_call_c_function);
1479 #define ALLOC_AND_COPY(dst, src, type, size) do { \
1481 (dst) = ALLOC_N(type, (size)); \
1482 MEMCPY((dst), (src), type, (size)); \
#define RSTRING_LEN(string)
static long NUM2LONG(VALUE x)
int rb_iseq_disasm_insn(VALUE ret, VALUE *iseq, size_t pos, rb_iseq_t *iseqdat, VALUE child)
Disassemble a instruction Iseq -> Iseq inspect object.
int rb_iseq_first_lineno(rb_iseq_t *iseq)
VALUE rb_get_coverages(void)
VALUE rb_ary_entry(VALUE ary, long offset)
void rb_bug(const char *fmt,...)
#define DECL_SYMBOL(name)
NODE * rb_parser_compile_file(volatile VALUE vparser, const char *f, VALUE file, int start)
static void iseq_mark(void *ptr)
#define OPT_SPECIALISED_INSTRUCTION
static void make_compile_option(rb_compile_option_t *option, VALUE opt)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
#define GetProcPtr(obj, ptr)
#define RUBY_VM_NORMAL_ISEQ_P(ptr)
static void set_relation(rb_iseq_t *iseq, const VALUE parent)
struct iseq_compile_data * compile_data
static unsigned short find_line_no(rb_iseq_t *iseq, unsigned long pos)
struct iseq_compile_data_storage * storage_head
static VALUE iseq_s_compile(int argc, VALUE *argv, VALUE self)
int rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
VALUE rb_ary_push(VALUE ary, VALUE item)
VALUE rb_str_concat(VALUE, VALUE)
VALUE rb_ary_tmp_new(long capa)
static int cdhash_each(VALUE key, VALUE value, VALUE ary)
#define RSTRING_PTR(string)
struct rb_iseq_struct * local_iseq
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_raise(VALUE exc, const char *fmt,...)
#define RUBY_MARK_LEAVE(msg)
struct iseq_compile_data_storage * next
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
struct iseq_inline_cache_entry * ic_entries
#define RARRAY_LEN(ARRAY)
VALUE rb_iseq_compile_node(VALUE self, NODE *node)
#define ALLOC_AND_COPY(dst, src, type, size)
VALUE rb_file_open_str(VALUE, const char *)
static VALUE rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no, VALUE parent, enum iseq_type type, VALUE bopt, const rb_compile_option_t *option)
const char * rb_obj_classname(VALUE)
const rb_compile_option_t * option
enum iseq_catch_table_entry::catch_type type
#define OPT_STACK_CACHING
void rb_hash_foreach(VALUE hash, int(*func)(ANYARGS), VALUE farg)
void rb_exc_raise(VALUE mesg)
#define SET_COMPILE_OPTION_NUM(o, h, mem)
static VALUE iseq_s_compile_file(int argc, VALUE *argv, VALUE self)
enum rb_iseq_struct::iseq_type type
static VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
#define MEMZERO(p, type, n)
static rb_compile_option_t COMPILE_OPTION_DEFAULT
NODE * rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line)
static VALUE CHECK_INTEGER(VALUE v)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
RUBY_EXTERN VALUE rb_cObject
static VALUE register_label(struct st_table *table, unsigned long idx)
VALUE rb_str_cat2(VALUE, const char *)
static VALUE obj_resurrect(VALUE obj)
VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent)
static VALUE make_compile_option_value(rb_compile_option_t *option)
VALUE rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no, VALUE parent, enum iseq_type type, VALUE bopt)
int argc
argument information
static VALUE iseq_eval(VALUE self)
void rb_ary_store(VALUE ary, long idx, VALUE val)
#define RUBY_MARK_ENTER(msg)
static unsigned short find_prev_line_no(rb_iseq_t *iseqdat, unsigned long pos)
static struct iseq_insn_info_entry * get_insn_info(const rb_iseq_t *iseq, const unsigned long pos)
VALUE rb_str_resurrect(VALUE str)
#define OPT_INLINE_CONST_CACHE
VALUE rb_str_resize(VALUE, long)
static VALUE exception_type2symbol(VALUE type)
#define INIT_SYMBOL(name)
#define hidden_obj_p(obj)
VALUE rb_iseq_build_for_ruby2cext(const rb_iseq_t *iseq_template, const rb_insn_func_t *func, const struct iseq_insn_info_entry *insn_info_table, const char **local_table, const VALUE *arg_opt_table, const struct iseq_catch_table_entry *catch_table, const char *name, const char *filename, const unsigned short line_no)
SSL_METHOD *(* func)(void)
VALUE rb_obj_is_proc(VALUE)
VALUE rb_funcall2(VALUE, ID, int, const VALUE *)
Calls a method.
VALUE rb_iseq_new_main(NODE *node, VALUE filename, VALUE filepath)
#define ISEQ_MINOR_VERSION
VALUE rb_sprintf(const char *format,...)
static VALUE prepare_iseq_build(rb_iseq_t *iseq, VALUE name, VALUE filename, VALUE filepath, VALUE line_no, VALUE parent, enum iseq_type type, VALUE block_opt, const rb_compile_option_t *option)
VALUE rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args, VALUE exception, VALUE body)
#define OPT_PEEPHOLE_OPTIMIZATION
static VALUE iseq_data_to_ary(rb_iseq_t *iseq)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
struct rb_iseq_struct * parent_iseq
static VALUE iseq_s_compile_option_set(VALUE self, VALUE opt)
#define OPT_INSTRUCTIONS_UNIFICATION
#define SET_COMPILE_OPTION(o, h, mem)
VALUE rb_iseq_eval(VALUE iseqval)
register unsigned int len
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
#define RARRAY_PTR(ARRAY)
#define INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE
#define RARRAY_LENINT(ary)
static VALUE cleanup_iseq_build(rb_iseq_t *iseq)
#define StringValueCStr(v)
static VALUE iseq_s_disasm(VALUE klass, VALUE body)
static VALUE iseq_s_load(int argc, VALUE *argv, VALUE self)
#define RUBY_FREE_UNLESS_NULL(ptr)
struct rb_iseq_struct rb_iseq_t
static VALUE iseq_alloc(VALUE klass)
#define ISEQ_MAJOR_VERSION
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
static VALUE insn_operand_intern(rb_iseq_t *iseq, VALUE insn, int op_no, VALUE op, int len, size_t pos, VALUE *pnop, VALUE child)
static NODE * parse_string(VALUE str, const char *file, int line)
#define RUBY_FREE_LEAVE(msg)
#define RUBY_FREE_ENTER(msg)
const char * ruby_node_name(int node)
VALUE rb_str_catf(VALUE str, const char *format,...)
struct iseq_compile_data_storage * storage_current
struct iseq_catch_table_entry * catch_table
rb_control_frame_t *FUNC_FASTCALL rb_insn_func_t(rb_thread_t *, rb_control_frame_t *)
static VALUE iseq_to_a(VALUE self)
static VALUE iseq_inspect(VALUE self)
VALUE rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE filepath, VALUE line, VALUE opt)
#define RUBY_MARK_UNLESS_NULL(ptr)
static const rb_data_type_t iseq_data_type
#define TypedData_Make_Struct(klass, type, data_type, sval)
#define OPT_TRACE_INSTRUCTION
#define OPT_OPERANDS_UNIFICATION
rb_iseq_t * rb_method_get_iseq(VALUE body)
static unsigned int hash(const char *str, unsigned int len)
#define OPT_TAILCALL_OPTIMIZATION
VALUE rb_ary_new2(long capa)
static const char * catch_type(int type)
VALUE rb_parser_new(void)
int main(int argc, char **argv)
#define GetISeqPtr(obj, ptr)
const char * rb_id2name(ID id)
static const rb_compile_option_t COMPILE_OPTION_FALSE
#define CONST_ID(var, str)
VALUE rb_iseq_new(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent, enum iseq_type type)
struct iseq_insn_info_entry * insn_info_table
VALUE rb_ary_resurrect(VALUE ary)
static void iseq_free(void *ptr)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_iseq_disasm(VALUE self)
VALUE rb_str_new2(const char *)
VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
VALUE rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no, VALUE parent, enum iseq_type type, const rb_compile_option_t *option)
static size_t iseq_memsize(const void *ptr)
VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line)
static void compile_data_free(struct iseq_compile_data *compile_data)
static rb_iseq_t * iseq_check(VALUE val)
static VALUE iseq_s_compile_option_get(VALUE self)
VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase)
VALUE rb_str_new(const char *, long)