22 #include "insns_info.inc" 24 #define ISEQ_MAJOR_VERSION 2 25 #define ISEQ_MINOR_VERSION 1 29 #define hidden_obj_p(obj) (!SPECIAL_CONST_P(obj) && !RBASIC(obj)->klass) 199 #define ISEQ_SET_CREF(iseq, cref) RB_OBJ_WRITE((iseq)->self, &(iseq)->cref_stack, (cref)) 209 if (
type == ISEQ_TYPE_TOP) {
216 cref->nd_refinements =
Qnil;
223 else if (
type == ISEQ_TYPE_METHOD ||
type == ISEQ_TYPE_CLASS) {
228 else if (
RTEST(parent)) {
239 if (
type == ISEQ_TYPE_MAIN) {
269 if (
RTEST(absolute_path))
309 if (
RTEST(coverages)) {
354 else if (opt ==
Qtrue) {
362 #define SET_COMPILE_OPTION(o, h, mem) \ 363 { VALUE flag = rb_hash_aref((h), ID2SYM(rb_intern(#mem))); \ 364 if (flag == Qtrue) { (o)->mem = 1; } \ 365 else if (flag == Qfalse) { (o)->mem = 0; } \ 367 #define SET_COMPILE_OPTION_NUM(o, h, mem) \ 368 { VALUE num = rb_hash_aref(opt, ID2SYM(rb_intern(#mem))); \ 369 if (!NIL_P(num)) (o)->mem = NUM2INT(num); \ 380 #undef SET_COMPILE_OPTION 381 #undef SET_COMPILE_OPTION_NUM 392 #define SET_COMPILE_OPTION(o, h, mem) \ 393 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), (o)->mem ? Qtrue : Qfalse) 394 #define SET_COMPILE_OPTION_NUM(o, h, mem) \ 395 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), INT2NUM((o)->mem)) 407 #undef SET_COMPILE_OPTION 408 #undef SET_COMPILE_OPTION_NUM 472 #define CHECK_ARRAY(v) rb_convert_type((v), T_ARRAY, "Array", "to_ary") 473 #define CHECK_STRING(v) rb_convert_type((v), T_STRING, "String", "to_str") 474 #define CHECK_SYMBOL(v) rb_convert_type((v), T_SYMBOL, "Symbol", "to_sym") 481 VALUE magic, version1, version2, format_type, misc;
482 VALUE name, path, absolute_path, first_lineno;
483 VALUE type, body, locals, args, exception;
486 static struct st_table *type_map_cache = 0;
504 ((void)magic, (
void)version1, (void)version2, (
void)format_type, (void)misc);
524 iseq->
self = iseqval;
527 type_map = type_map_cache;
543 type_map = cached_map;
556 if (parent ==
Qnil) {
562 parent, (
enum iseq_type)iseq_type, 0, &option);
621 if (base_block && base_block->
iseq) {
623 file, absolute_path, line, base_block->
iseq->
self,
624 ISEQ_TYPE_EVAL, &option);
628 ISEQ_TYPE_TOP, &option);
731 ISEQ_TYPE_TOP, &option);
980 if (local_iseq->
type == ISEQ_TYPE_METHOD) {
1092 const int debug = 0;
1103 else if (
size == 1) {
1107 for (i=1; i<
size; i++) {
1150 str = default_value;
1161 int len,
size_t pos,
VALUE *pnop,
VALUE child)
1163 const char *types = insn_op_types(insn);
1164 char type = types[op_no];
1177 if (insn == BIN(getlocal) || insn == BIN(setlocal)) {
1182 for (i = 0; i <
level; i++) {
1277 rb_bug(
"insn_operand_intern: unknown operand type: %c",
type);
1290 VALUE insn = iseq[pos];
1291 int len = insn_len(insn);
1293 const char *types = insn_op_types(insn);
1295 const char *insn_name_buff;
1297 insn_name_buff = insn_name(insn);
1303 (
int)strcspn(insn_name_buff,
"_"), insn_name_buff);
1306 for (j = 0; types[j]; j++) {
1307 const char *types = insn_op_types(insn);
1309 len, pos, &iseq[pos + j + 2],
1320 unsigned int prev = pos == 0 ? 0 :
find_line_no(iseqdat, pos - 1);
1321 if (line_no && line_no != prev) {
1323 slen = (slen > 70) ? 0 : (70 - slen);
1324 str =
rb_str_catf(str,
"%*s(%4d)", (
int)slen,
"", line_no);
1342 case CATCH_TYPE_RESCUE:
1344 case CATCH_TYPE_ENSURE:
1346 case CATCH_TYPE_RETRY:
1348 case CATCH_TYPE_BREAK:
1350 case CATCH_TYPE_REDO:
1352 case CATCH_TYPE_NEXT:
1390 enum {header_minlen = 72};
1394 iseq = iseqdat->
iseq;
1402 memset(
RSTRING_PTR(str) + l,
'=', header_minlen - l);
1413 "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
1415 (
int)entry->
end, (
int)entry->
sp, (
int)entry->
cont);
1421 rb_str_cat2(str,
"|-------------------------------------" 1422 "-----------------------------------\n");
1430 "local table (size: %d, argc: %d " 1431 "[opts: %d, rest: %d, post: %d, block: %d, keyword: %d@%d] s%d)\n",
1441 char argi[0x100] =
"";
1442 char opti[0x100] =
"";
1447 if (i >=
argc && i <
argc + opts - 1) {
1453 snprintf(argi,
sizeof(argi),
"%s%s%s%s%s",
1454 iseqdat->
argc > i ?
"Arg" :
"",
1456 iseqdat->
arg_rest == i ?
"Rest" :
"",
1458 i < iseqdat->arg_post_start + iseqdat->
arg_post_len) ?
"Post" :
"",
1459 iseqdat->
arg_block == i ?
"Block" :
"");
1474 for (n = 0; n <
size;) {
1607 #include "node_name.inc" 1609 rb_bug(
"unknown node (%d)", node);
1614 #define DECL_SYMBOL(name) \ 1615 static VALUE sym_##name 1617 #define INIT_SYMBOL(name) \ 1618 sym_##name = ID2SYM(rb_intern(#name)) 1624 char buff[8 + (
sizeof(idx) *
CHAR_BIT * 32 / 100)];
1626 snprintf(buff,
sizeof(buff),
"label_%lu", idx);
1663 unsigned int line = 0;
1675 static VALUE insn_syms[VM_INSTRUCTION_SIZE];
1690 for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
1705 switch (iseq->
type) {
1706 case ISEQ_TYPE_TOP:
type = sym_top;
break;
1707 case ISEQ_TYPE_METHOD:
type = sym_method;
break;
1708 case ISEQ_TYPE_BLOCK:
type = sym_block;
break;
1709 case ISEQ_TYPE_CLASS:
type = sym_class;
break;
1710 case ISEQ_TYPE_RESCUE:
type = sym_rescue;
break;
1711 case ISEQ_TYPE_ENSURE:
type = sym_ensure;
break;
1712 case ISEQ_TYPE_EVAL:
type = sym_eval;
break;
1713 case ISEQ_TYPE_MAIN:
type = sym_main;
break;
1714 case ISEQ_TYPE_DEFINED_GUARD:
type = sym_defined_guard;
break;
1715 default:
rb_bug(
"unsupported iseq type");
1765 for (seq = iseq->
iseq; seq < iseq->iseq + iseq->
iseq_size; ) {
1766 VALUE insn = *seq++;
1767 int j, len = insn_len(insn);
1768 VALUE *nseq = seq + len - 1;
1772 for (j=0; j<len-1; j++, seq++) {
1773 switch (insn_op_type(insn, j)) {
1775 unsigned long idx = nseq - iseq->
iseq + *seq;
1834 unsigned long idx = nseq - iseq->
iseq + pos;
1843 rb_bug(
"unknown operand: %c", insn_op_type(insn, j));
1879 if (
st_lookup(labels_table, pos, &label)) {
1883 if (ti < iseq->line_info_size &&
iseq->line_info_table[ti].position == pos) {
1884 line =
iseq->line_info_table[ti].line_no;
1933 iseq1->
self = newiseq;
1958 ID req, opt, rest, block,
key, keyrest;
1959 #define PARAM_TYPE(type) rb_ary_push(a = rb_ary_new2(2), ID2SYM(type)) 1960 #define PARAM_ID(i) iseq->local_table[(i)] 1961 #define PARAM(i, type) ( \ 1963 rb_id2str(PARAM_ID(i)) ? \ 1964 rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \ 1970 for (i = 0; i <
iseq->argc; i++) {
1977 for (i = 0; i <
iseq->argc; i++) {
1981 r =
iseq->argc +
iseq->arg_opts - 1;
1982 for (; i < r; i++) {
1989 if (
iseq->arg_rest != -1) {
1993 r =
iseq->arg_post_start +
iseq->arg_post_len;
1995 for (i =
iseq->arg_post_start; i < r; i++) {
2002 for (i =
iseq->arg_post_start; i < r; i++) {
2006 if (
iseq->arg_keyword != -1) {
2008 if (
iseq->arg_keyword_required) {
2011 for (; i <
iseq->arg_keyword_required; i++) {
2020 for (; i <
iseq->arg_keywords; i++) {
2027 if (!
iseq->arg_keyword_check) {
2032 if (
iseq->arg_block != -1) {
2042 static const char expr_names[][18] = {
2044 "instance-variable",
2061 if ((
unsigned)(
type - 1) >= (
unsigned)
numberof(expr_names))
return 0;
2062 estr = expr_names[
type - 1];
2063 if (!estr[0])
return 0;
2064 defs =
GET_VM()->defined_strings;
2067 GET_VM()->defined_strings = defs;
2085 const char **local_table,
2086 const VALUE *arg_opt_table,
2090 const unsigned short first_lineno)
2101 iseq->location.first_lineno = first_lineno;
2103 iseq->self = iseqval;
2107 for (i=0; i<
iseq->iseq_size; i+=2) {
2108 iseq->iseq[i] = BIN(opt_call_c_function);
2114 #define ALLOC_AND_COPY(dst, src, type, size) do { \ 2116 (dst) = ALLOC_N(type, (size)); \ 2117 MEMCPY((dst), (src), type, (size)); \ 2148 for (pos = 0;
cont && pos <
iseq->iseq_size; pos += insn_len(insn)) {
2149 insn =
iseq->iseq[pos];
2151 if (insn == BIN(trace)) {
2161 cont = (*func)(line, &events, data);
2162 if (current_events != events) {
2163 iseq->iseq[pos+1] =
iseq->iseq_encoded[pos+1] =
2205 if (data->
pos == 0) {
2251 if (data.prev == 0) {
#define RBASIC_CLEAR_CLASS(obj)
#define VM_CALL_ARGS_BLOCKARG
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.
static VALUE prepare_iseq_build(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno, VALUE parent, enum iseq_type type, VALUE block_opt, const rb_compile_option_t *option)
unsigned int rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
VALUE rb_ary_entry(VALUE ary, long offset)
void rb_bug(const char *fmt,...)
#define RUBY_TYPED_FREE_IMMEDIATELY
#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)
VALUE rb_iseq_new(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE parent, enum iseq_type type)
VALUE rb_iseq_line_trace_all(VALUE iseqval)
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)
int rb_iseq_line_trace_each(VALUE iseqval, int(*func)(int line, rb_event_flag_t *events_ptr, void *d), void *data)
static void set_relation(rb_iseq_t *iseq, const VALUE parent)
#define ATOMIC_PTR_CAS(var, oldval, val)
int st_insert(st_table *, st_data_t, st_data_t)
struct iseq_compile_data * compile_data
struct iseq_compile_data_storage * storage_head
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
rb_call_info_t * callinfo_entries
static VALUE iseq_s_compile(int argc, VALUE *argv, VALUE self)
static VALUE id_to_name(ID id, VALUE default_value)
int rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
VALUE rb_ary_push(VALUE ary, VALUE item)
SSL_METHOD *(* func)(void)
void st_free_table(st_table *)
VALUE rb_str_concat(VALUE, VALUE)
#define OPT_INLINE_CONST_CACHE
VALUE rb_ary_tmp_new(long capa)
VALUE rb_iseq_defined_string(enum defined_type type)
VALUE rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, rb_block_t *base_block, VALUE opt)
static int cdhash_each(VALUE key, VALUE value, VALUE ary)
if((ID)(DISPID) nameid !=nameid)
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)
#define VM_CALL_ARGS_SPLAT
static VALUE rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno, VALUE parent, enum iseq_type type, VALUE bopt, const rb_compile_option_t *option)
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 *)
int rb_str_cmp(VALUE, VALUE)
const char * rb_obj_classname(VALUE)
#define OPT_TAILCALL_OPTIMIZATION
const rb_compile_option_t * option
static rb_iseq_location_t * iseq_location_setup(rb_iseq_t *iseq, VALUE path, VALUE absolute_path, VALUE name, size_t first_lineno)
const VALUE catch_table_ary
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
enum iseq_catch_table_entry::catch_type type
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)
#define RB_TYPE_P(obj, type)
void * ruby_xcalloc(size_t n, size_t size)
enum rb_iseq_struct::iseq_type type
static VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
int st_lookup(st_table *, st_data_t, st_data_t *)
#define MEMZERO(p, type, n)
static rb_compile_option_t COMPILE_OPTION_DEFAULT
#define OPT_PEEPHOLE_OPTIMIZATION
static struct iseq_line_info_entry * get_line_info(const rb_iseq_t *iseq, size_t pos)
int rb_str_symname_p(VALUE)
#define RUBY_TYPED_WB_PROTECTED
VALUE rb_iseq_new_main(NODE *node, VALUE path, VALUE absolute_path)
VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE parent)
static VALUE CHECK_INTEGER(VALUE v)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
#define VM_CALL_ARGS_SKIP_SETUP
RUBY_EXTERN VALUE rb_cObject
static VALUE register_label(struct st_table *table, unsigned long idx)
VALUE rb_get_coverages(void)
VALUE rb_str_cat2(VALUE, const char *)
static unsigned int find_line_no(const rb_iseq_t *iseq, size_t pos)
static VALUE obj_resurrect(VALUE obj)
static VALUE make_compile_option_value(rb_compile_option_t *option)
int argc
argument information
static VALUE iseq_s_of(VALUE klass, VALUE body)
VALUE rb_iseq_absolute_path(VALUE self)
VALUE rb_iseq_method_name(VALUE self)
static VALUE iseq_eval(VALUE self)
void rb_ary_store(VALUE ary, long idx, VALUE val)
#define RUBY_MARK_ENTER(msg)
#define MEMCPY(p1, p2, type, n)
VALUE rb_iseq_klass(VALUE self)
#define OPT_INSTRUCTIONS_UNIFICATION
VALUE rb_str_resurrect(VALUE str)
VALUE rb_str_resize(VALUE, long)
static VALUE exception_type2symbol(VALUE type)
#define INIT_SYMBOL(name)
#define ISEQ_SET_CREF(iseq, cref)
#define RUBY_EVENT_SPECIFIED_LINE
#define hidden_obj_p(obj)
VALUE rb_obj_is_proc(VALUE)
#define ISEQ_MINOR_VERSION
VALUE rb_sprintf(const char *format,...)
#define OPT_TRACE_INSTRUCTION
VALUE rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args, VALUE exception, VALUE body)
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)
VALUE rb_iseq_first_lineno(VALUE self)
VALUE rb_iseq_build_for_ruby2cext(const rb_iseq_t *iseq_template, const rb_insn_func_t *func, const struct iseq_line_info_entry *line_info_table, const char **local_table, const VALUE *arg_opt_table, const struct iseq_catch_table_entry *catch_table, const char *name, const char *path, const unsigned short first_lineno)
#define SET_COMPILE_OPTION(o, h, mem)
VALUE rb_iseq_eval(VALUE iseqval)
VALUE rb_iseq_path(VALUE self)
rb_iseq_location_t location
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
#define INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE
#define OPT_STACK_CACHING
VALUE rb_str_new_cstr(const char *)
#define RARRAY_LENINT(ary)
st_table * st_init_numtable(void)
static VALUE cleanup_iseq_build(rb_iseq_t *iseq)
VALUE rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno, VALUE parent, enum iseq_type type, VALUE bopt)
#define StringValueCStr(v)
void rb_iseq_add_mark_object(rb_iseq_t *iseq, VALUE obj)
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)
VALUE rb_iseq_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set)
struct rb_iseq_struct rb_iseq_t
#define OPT_SPECIALISED_INSTRUCTION
static VALUE iseq_alloc(VALUE klass)
#define ISEQ_MAJOR_VERSION
static int line_trace_specify(int line, rb_event_flag_t *events_ptr, void *ptr)
#define RARRAY_AREF(a, i)
#define RUBY_FREE_LEAVE(msg)
unsigned long rb_event_flag_t
#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 *)
VALUE rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, rb_block_t *base_block)
static VALUE iseq_to_a(VALUE self)
static VALUE iseq_inspect(VALUE self)
#define RUBY_MARK_UNLESS_NULL(ptr)
struct iseq_line_info_entry * line_info_table
static const rb_data_type_t iseq_data_type
#define TypedData_Make_Struct(klass, type, data_type, sval)
VALUE rb_str_inspect(VALUE)
rb_iseq_t * rb_method_get_iseq(VALUE body)
static unsigned int hash(const char *str, unsigned int len)
VALUE rb_ary_join(VALUE ary, VALUE sep)
static const char * catch_type(int type)
VALUE rb_parser_new(void)
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
int main(int argc, char **argv)
#define GetISeqPtr(obj, ptr)
VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase)
const char * rb_id2name(ID id)
static const rb_compile_option_t COMPILE_OPTION_FALSE
const VALUE absolute_path
NODE * rb_parser_compile_string_path(volatile VALUE vparser, VALUE f, VALUE s, int line)
VALUE rb_iseq_base_label(VALUE self)
#define CONST_ID(var, str)
struct rb_call_info_struct rb_call_info_t
VALUE rb_iseq_label(VALUE self)
VALUE rb_ary_resurrect(VALUE ary)
VALUE rb_insn_operand_intern(rb_iseq_t *iseq, VALUE insn, int op_no, VALUE op, int len, size_t pos, VALUE *pnop, VALUE child)
static int collect_trace(int line, rb_event_flag_t *events_ptr, void *ptr)
static void iseq_free(void *ptr)
static rb_thread_t * GET_THREAD(void)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_str_append(VALUE, VALUE)
VALUE rb_iseq_disasm(VALUE self)
VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
NODE * rb_parser_compile_file_path(volatile VALUE vparser, VALUE fname, VALUE file, int start)
#define OPT_OPERANDS_UNIFICATION
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)
VALUE rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno, VALUE parent, enum iseq_type type, const rb_compile_option_t *option)
#define RB_OBJ_WRITE(a, slot, b)
static rb_iseq_t * iseq_check(VALUE val)
static VALUE iseq_s_compile_option_get(VALUE self)
union iseq_inline_storage_entry * is_entries
VALUE rb_str_new(const char *, long)