1/**********************************************************************
2
3  iseq.c -
4
5  $Author: nagachika $
6  created at: 2006-07-11(Tue) 09:00:03 +0900
7
8  Copyright (C) 2006 Koichi Sasada
9
10**********************************************************************/
11
12#include "ruby/ruby.h"
13#include "internal.h"
14#include "eval_intern.h"
15
16/* #define RUBY_MARK_FREE_DEBUG 1 */
17#include "gc.h"
18#include "vm_core.h"
19#include "iseq.h"
20
21#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
22
23#include "insns.inc"
24#include "insns_info.inc"
25
26#define ISEQ_MAJOR_VERSION 2
27#define ISEQ_MINOR_VERSION 0
28
29VALUE rb_cISeq;
30
31#define hidden_obj_p(obj) (!SPECIAL_CONST_P(obj) && !RBASIC(obj)->klass)
32
33static inline VALUE
34obj_resurrect(VALUE obj)
35{
36    if (hidden_obj_p(obj)) {
37	switch (BUILTIN_TYPE(obj)) {
38	  case T_STRING:
39	    obj = rb_str_resurrect(obj);
40	    break;
41	  case T_ARRAY:
42	    obj = rb_ary_resurrect(obj);
43	    break;
44	}
45    }
46    return obj;
47}
48
49static void
50compile_data_free(struct iseq_compile_data *compile_data)
51{
52    if (compile_data) {
53	struct iseq_compile_data_storage *cur, *next;
54	cur = compile_data->storage_head;
55	while (cur) {
56	    next = cur->next;
57	    ruby_xfree(cur);
58	    cur = next;
59	}
60	ruby_xfree(compile_data);
61    }
62}
63
64static void
65iseq_free(void *ptr)
66{
67    rb_iseq_t *iseq;
68    RUBY_FREE_ENTER("iseq");
69
70    if (ptr) {
71	iseq = ptr;
72	if (!iseq->orig) {
73	    /* It's possible that strings are freed */
74	    if (0) {
75		RUBY_GC_INFO("%s @ %s\n", RSTRING_PTR(iseq->location.label),
76					  RSTRING_PTR(iseq->location.path));
77	    }
78
79	    if (iseq->iseq != iseq->iseq_encoded) {
80		RUBY_FREE_UNLESS_NULL(iseq->iseq_encoded);
81	    }
82
83	    RUBY_FREE_UNLESS_NULL(iseq->iseq);
84	    RUBY_FREE_UNLESS_NULL(iseq->line_info_table);
85	    RUBY_FREE_UNLESS_NULL(iseq->local_table);
86	    RUBY_FREE_UNLESS_NULL(iseq->ic_entries);
87	    RUBY_FREE_UNLESS_NULL(iseq->callinfo_entries);
88	    RUBY_FREE_UNLESS_NULL(iseq->catch_table);
89	    RUBY_FREE_UNLESS_NULL(iseq->arg_opt_table);
90	    RUBY_FREE_UNLESS_NULL(iseq->arg_keyword_table);
91	    compile_data_free(iseq->compile_data);
92	}
93	ruby_xfree(ptr);
94    }
95    RUBY_FREE_LEAVE("iseq");
96}
97
98static void
99iseq_mark(void *ptr)
100{
101    RUBY_MARK_ENTER("iseq");
102
103    if (ptr) {
104	rb_iseq_t *iseq = ptr;
105
106	RUBY_GC_INFO("%s @ %s\n", RSTRING_PTR(iseq->location.label), RSTRING_PTR(iseq->location.path));
107	RUBY_MARK_UNLESS_NULL(iseq->mark_ary);
108
109	RUBY_MARK_UNLESS_NULL(iseq->location.label);
110	RUBY_MARK_UNLESS_NULL(iseq->location.base_label);
111	RUBY_MARK_UNLESS_NULL(iseq->location.path);
112	RUBY_MARK_UNLESS_NULL(iseq->location.absolute_path);
113
114	RUBY_MARK_UNLESS_NULL((VALUE)iseq->cref_stack);
115	RUBY_MARK_UNLESS_NULL(iseq->klass);
116	RUBY_MARK_UNLESS_NULL(iseq->coverage);
117#if 0
118	RUBY_MARK_UNLESS_NULL((VALUE)iseq->node);
119	RUBY_MARK_UNLESS_NULL(iseq->cached_special_block);
120#endif
121	RUBY_MARK_UNLESS_NULL(iseq->orig);
122
123	if (iseq->compile_data != 0) {
124	    struct iseq_compile_data *const compile_data = iseq->compile_data;
125	    RUBY_MARK_UNLESS_NULL(compile_data->mark_ary);
126	    RUBY_MARK_UNLESS_NULL(compile_data->err_info);
127	    RUBY_MARK_UNLESS_NULL(compile_data->catch_table_ary);
128	}
129    }
130    RUBY_MARK_LEAVE("iseq");
131}
132
133static size_t
134iseq_memsize(const void *ptr)
135{
136    size_t size = sizeof(rb_iseq_t);
137    const rb_iseq_t *iseq;
138
139    if (ptr) {
140	iseq = ptr;
141	if (!iseq->orig) {
142	    if (iseq->iseq != iseq->iseq_encoded) {
143		size += iseq->iseq_size * sizeof(VALUE);
144	    }
145
146	    size += iseq->iseq_size * sizeof(VALUE);
147	    size += iseq->line_info_size * sizeof(struct iseq_line_info_entry);
148	    size += iseq->local_table_size * sizeof(ID);
149	    size += iseq->catch_table_size * sizeof(struct iseq_catch_table_entry);
150	    size += iseq->arg_opts * sizeof(VALUE);
151	    size += iseq->ic_size * sizeof(struct iseq_inline_cache_entry);
152	    size += iseq->callinfo_size * sizeof(rb_call_info_t);
153
154	    if (iseq->compile_data) {
155		struct iseq_compile_data_storage *cur;
156
157		cur = iseq->compile_data->storage_head;
158		while (cur) {
159		    size += cur->size + sizeof(struct iseq_compile_data_storage);
160		    cur = cur->next;
161		}
162		size += sizeof(struct iseq_compile_data);
163	    }
164	}
165    }
166
167    return size;
168}
169
170static const rb_data_type_t iseq_data_type = {
171    "iseq",
172    {
173	iseq_mark,
174	iseq_free,
175	iseq_memsize,
176    },
177};
178
179static VALUE
180iseq_alloc(VALUE klass)
181{
182    rb_iseq_t *iseq;
183    return TypedData_Make_Struct(klass, rb_iseq_t, &iseq_data_type, iseq);
184}
185
186static rb_iseq_location_t *
187iseq_location_setup(rb_iseq_t *iseq, VALUE path, VALUE absolute_path, VALUE name, size_t first_lineno)
188{
189    rb_iseq_location_t *loc = &iseq->location;
190    loc->path = path;
191    if (RTEST(absolute_path) && rb_str_cmp(path, absolute_path) == 0)
192	loc->absolute_path = path;
193    else
194	loc->absolute_path = absolute_path;
195    loc->label = loc->base_label = name;
196    loc->first_lineno = first_lineno;
197    return loc;
198}
199
200static void
201set_relation(rb_iseq_t *iseq, const VALUE parent)
202{
203    const VALUE type = iseq->type;
204    rb_thread_t *th = GET_THREAD();
205    rb_iseq_t *piseq;
206
207    /* set class nest stack */
208    if (type == ISEQ_TYPE_TOP) {
209	/* toplevel is private */
210	iseq->cref_stack = NEW_CREF(rb_cObject);
211	iseq->cref_stack->nd_refinements = Qnil;
212	iseq->cref_stack->nd_visi = NOEX_PRIVATE;
213	if (th->top_wrapper) {
214	    NODE *cref = NEW_CREF(th->top_wrapper);
215	    cref->nd_refinements = Qnil;
216	    cref->nd_visi = NOEX_PRIVATE;
217	    cref->nd_next = iseq->cref_stack;
218	    iseq->cref_stack = cref;
219	}
220	iseq->local_iseq = iseq;
221    }
222    else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
223	iseq->cref_stack = NEW_CREF(0); /* place holder */
224	iseq->cref_stack->nd_refinements = Qnil;
225	iseq->local_iseq = iseq;
226    }
227    else if (RTEST(parent)) {
228	GetISeqPtr(parent, piseq);
229	iseq->cref_stack = piseq->cref_stack;
230	iseq->local_iseq = piseq->local_iseq;
231    }
232
233    if (RTEST(parent)) {
234	GetISeqPtr(parent, piseq);
235	iseq->parent_iseq = piseq;
236    }
237
238    if (type == ISEQ_TYPE_MAIN) {
239	iseq->local_iseq = iseq;
240    }
241}
242
243void
244rb_iseq_add_mark_object(rb_iseq_t *iseq, VALUE obj)
245{
246    if (!RTEST(iseq->mark_ary)) {
247	iseq->mark_ary = rb_ary_tmp_new(3);
248	OBJ_UNTRUST(iseq->mark_ary);
249	RBASIC(iseq->mark_ary)->klass = 0;
250    }
251    rb_ary_push(iseq->mark_ary, obj);
252}
253
254static VALUE
255prepare_iseq_build(rb_iseq_t *iseq,
256		   VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno,
257		   VALUE parent, enum iseq_type type, VALUE block_opt,
258		   const rb_compile_option_t *option)
259{
260    iseq->type = type;
261    iseq->arg_rest = -1;
262    iseq->arg_block = -1;
263    iseq->arg_keyword = -1;
264    iseq->klass = 0;
265    set_relation(iseq, parent);
266
267    OBJ_FREEZE(name);
268    OBJ_FREEZE(path);
269
270    iseq_location_setup(iseq, path, absolute_path, name, first_lineno);
271    if (iseq != iseq->local_iseq) {
272	iseq->location.base_label = iseq->local_iseq->location.label;
273    }
274
275    iseq->defined_method_id = 0;
276    iseq->mark_ary = 0;
277
278
279    /*
280     * iseq->special_block_builder = GC_GUARDED_PTR_REF(block_opt);
281     * iseq->cached_special_block_builder = 0;
282     * iseq->cached_special_block = 0;
283     */
284
285    iseq->compile_data = ALLOC(struct iseq_compile_data);
286    MEMZERO(iseq->compile_data, struct iseq_compile_data, 1);
287    iseq->compile_data->err_info = Qnil;
288    iseq->compile_data->mark_ary = rb_ary_tmp_new(3);
289
290    iseq->compile_data->storage_head = iseq->compile_data->storage_current =
291      (struct iseq_compile_data_storage *)
292	ALLOC_N(char, INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE +
293		sizeof(struct iseq_compile_data_storage));
294
295    iseq->compile_data->catch_table_ary = rb_ary_new();
296    iseq->compile_data->storage_head->pos = 0;
297    iseq->compile_data->storage_head->next = 0;
298    iseq->compile_data->storage_head->size =
299      INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE;
300    iseq->compile_data->storage_head->buff =
301      (char *)(&iseq->compile_data->storage_head->buff + 1);
302    iseq->compile_data->option = option;
303    iseq->compile_data->last_coverable_line = -1;
304
305    iseq->coverage = Qfalse;
306    if (!GET_THREAD()->parse_in_eval) {
307	VALUE coverages = rb_get_coverages();
308	if (RTEST(coverages)) {
309	    iseq->coverage = rb_hash_lookup(coverages, path);
310	    if (NIL_P(iseq->coverage)) iseq->coverage = Qfalse;
311	}
312    }
313
314    return Qtrue;
315}
316
317static VALUE
318cleanup_iseq_build(rb_iseq_t *iseq)
319{
320    struct iseq_compile_data *data = iseq->compile_data;
321    VALUE err = data->err_info;
322    iseq->compile_data = 0;
323    compile_data_free(data);
324
325    if (RTEST(err)) {
326	rb_funcall2(err, rb_intern("set_backtrace"), 1, &iseq->location.path);
327	rb_exc_raise(err);
328    }
329    return Qtrue;
330}
331
332static rb_compile_option_t COMPILE_OPTION_DEFAULT = {
333    OPT_INLINE_CONST_CACHE, /* int inline_const_cache; */
334    OPT_PEEPHOLE_OPTIMIZATION, /* int peephole_optimization; */
335    OPT_TAILCALL_OPTIMIZATION, /* int tailcall_optimization */
336    OPT_SPECIALISED_INSTRUCTION, /* int specialized_instruction; */
337    OPT_OPERANDS_UNIFICATION, /* int operands_unification; */
338    OPT_INSTRUCTIONS_UNIFICATION, /* int instructions_unification; */
339    OPT_STACK_CACHING, /* int stack_caching; */
340    OPT_TRACE_INSTRUCTION, /* int trace_instruction */
341};
342static const rb_compile_option_t COMPILE_OPTION_FALSE = {0};
343
344static void
345make_compile_option(rb_compile_option_t *option, VALUE opt)
346{
347    if (opt == Qnil) {
348	*option = COMPILE_OPTION_DEFAULT;
349    }
350    else if (opt == Qfalse) {
351	*option = COMPILE_OPTION_FALSE;
352    }
353    else if (opt == Qtrue) {
354	memset(option, 1, sizeof(rb_compile_option_t));
355    }
356    else if (CLASS_OF(opt) == rb_cHash) {
357	*option = COMPILE_OPTION_DEFAULT;
358
359#define SET_COMPILE_OPTION(o, h, mem) \
360  { VALUE flag = rb_hash_aref((h), ID2SYM(rb_intern(#mem))); \
361      if (flag == Qtrue)  { (o)->mem = 1; } \
362      else if (flag == Qfalse)  { (o)->mem = 0; } \
363  }
364#define SET_COMPILE_OPTION_NUM(o, h, mem) \
365  { VALUE num = rb_hash_aref(opt, ID2SYM(rb_intern(#mem))); \
366      if (!NIL_P(num)) (o)->mem = NUM2INT(num); \
367  }
368	SET_COMPILE_OPTION(option, opt, inline_const_cache);
369	SET_COMPILE_OPTION(option, opt, peephole_optimization);
370	SET_COMPILE_OPTION(option, opt, tailcall_optimization);
371	SET_COMPILE_OPTION(option, opt, specialized_instruction);
372	SET_COMPILE_OPTION(option, opt, operands_unification);
373	SET_COMPILE_OPTION(option, opt, instructions_unification);
374	SET_COMPILE_OPTION(option, opt, stack_caching);
375	SET_COMPILE_OPTION(option, opt, trace_instruction);
376	SET_COMPILE_OPTION_NUM(option, opt, debug_level);
377#undef SET_COMPILE_OPTION
378#undef SET_COMPILE_OPTION_NUM
379    }
380    else {
381	rb_raise(rb_eTypeError, "Compile option must be Hash/true/false/nil");
382    }
383}
384
385static VALUE
386make_compile_option_value(rb_compile_option_t *option)
387{
388    VALUE opt = rb_hash_new();
389#define SET_COMPILE_OPTION(o, h, mem) \
390  rb_hash_aset((h), ID2SYM(rb_intern(#mem)), (o)->mem ? Qtrue : Qfalse)
391#define SET_COMPILE_OPTION_NUM(o, h, mem) \
392  rb_hash_aset((h), ID2SYM(rb_intern(#mem)), INT2NUM((o)->mem))
393    {
394	SET_COMPILE_OPTION(option, opt, inline_const_cache);
395	SET_COMPILE_OPTION(option, opt, peephole_optimization);
396	SET_COMPILE_OPTION(option, opt, tailcall_optimization);
397	SET_COMPILE_OPTION(option, opt, specialized_instruction);
398	SET_COMPILE_OPTION(option, opt, operands_unification);
399	SET_COMPILE_OPTION(option, opt, instructions_unification);
400	SET_COMPILE_OPTION(option, opt, stack_caching);
401	SET_COMPILE_OPTION(option, opt, trace_instruction);
402	SET_COMPILE_OPTION_NUM(option, opt, debug_level);
403    }
404#undef SET_COMPILE_OPTION
405#undef SET_COMPILE_OPTION_NUM
406    return opt;
407}
408
409VALUE
410rb_iseq_new(NODE *node, VALUE name, VALUE path, VALUE absolute_path,
411	    VALUE parent, enum iseq_type type)
412{
413    return rb_iseq_new_with_opt(node, name, path, absolute_path, INT2FIX(0), parent, type,
414				&COMPILE_OPTION_DEFAULT);
415}
416
417VALUE
418rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE parent)
419{
420    return rb_iseq_new_with_opt(node, name, path, absolute_path, INT2FIX(0), parent, ISEQ_TYPE_TOP,
421				&COMPILE_OPTION_DEFAULT);
422}
423
424VALUE
425rb_iseq_new_main(NODE *node, VALUE path, VALUE absolute_path)
426{
427    rb_thread_t *th = GET_THREAD();
428    VALUE parent = th->base_block->iseq->self;
429    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), path, absolute_path, INT2FIX(0),
430				parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
431}
432
433static VALUE
434rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno,
435				VALUE parent, enum iseq_type type, VALUE bopt,
436				const rb_compile_option_t *option)
437{
438    rb_iseq_t *iseq;
439    VALUE self = iseq_alloc(rb_cISeq);
440
441    GetISeqPtr(self, iseq);
442    iseq->self = self;
443
444    prepare_iseq_build(iseq, name, path, absolute_path, first_lineno, parent, type, bopt, option);
445    rb_iseq_compile_node(self, node);
446    cleanup_iseq_build(iseq);
447    return self;
448}
449
450VALUE
451rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno,
452		     VALUE parent, enum iseq_type type,
453		     const rb_compile_option_t *option)
454{
455    /* TODO: argument check */
456    return rb_iseq_new_with_bopt_and_opt(node, name, path, absolute_path, first_lineno, parent, type,
457					   Qfalse, option);
458}
459
460VALUE
461rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno,
462		       VALUE parent, enum iseq_type type, VALUE bopt)
463{
464    /* TODO: argument check */
465    return rb_iseq_new_with_bopt_and_opt(node, name, path, absolute_path, first_lineno, parent, type,
466					   bopt, &COMPILE_OPTION_DEFAULT);
467}
468
469#define CHECK_ARRAY(v)   rb_convert_type((v), T_ARRAY, "Array", "to_ary")
470#define CHECK_STRING(v)  rb_convert_type((v), T_STRING, "String", "to_str")
471#define CHECK_SYMBOL(v)  rb_convert_type((v), T_SYMBOL, "Symbol", "to_sym")
472static inline VALUE CHECK_INTEGER(VALUE v) {(void)NUM2LONG(v); return v;}
473static VALUE
474iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
475{
476    VALUE iseqval = iseq_alloc(self);
477
478    VALUE magic, version1, version2, format_type, misc;
479    VALUE name, path, absolute_path, first_lineno;
480    VALUE type, body, locals, args, exception;
481
482    st_data_t iseq_type;
483    static struct st_table *type_map_cache = 0;
484    struct st_table *type_map = 0;
485    rb_iseq_t *iseq;
486    rb_compile_option_t option;
487    int i = 0;
488
489    /* [magic, major_version, minor_version, format_type, misc,
490     *  label, path, first_lineno,
491     *  type, locals, args, exception_table, body]
492     */
493
494    data        = CHECK_ARRAY(data);
495
496    magic       = CHECK_STRING(rb_ary_entry(data, i++));
497    version1    = CHECK_INTEGER(rb_ary_entry(data, i++));
498    version2    = CHECK_INTEGER(rb_ary_entry(data, i++));
499    format_type = CHECK_INTEGER(rb_ary_entry(data, i++));
500    misc        = rb_ary_entry(data, i++); /* TODO */
501    ((void)magic, (void)version1, (void)version2, (void)format_type, (void)misc);
502
503    name        = CHECK_STRING(rb_ary_entry(data, i++));
504    path        = CHECK_STRING(rb_ary_entry(data, i++));
505    absolute_path = rb_ary_entry(data, i++);
506    absolute_path = NIL_P(absolute_path) ? Qnil : CHECK_STRING(absolute_path);
507    first_lineno = CHECK_INTEGER(rb_ary_entry(data, i++));
508
509    type        = CHECK_SYMBOL(rb_ary_entry(data, i++));
510    locals      = CHECK_ARRAY(rb_ary_entry(data, i++));
511
512    args        = rb_ary_entry(data, i++);
513    if (FIXNUM_P(args) || (args = CHECK_ARRAY(args))) {
514	/* */
515    }
516
517    exception   = CHECK_ARRAY(rb_ary_entry(data, i++));
518    body        = CHECK_ARRAY(rb_ary_entry(data, i++));
519
520    GetISeqPtr(iseqval, iseq);
521    iseq->self = iseqval;
522
523    type_map = type_map_cache;
524    if (type_map == 0) {
525	struct st_table *cached_map;
526	type_map = st_init_numtable();
527	st_insert(type_map, ID2SYM(rb_intern("top")), ISEQ_TYPE_TOP);
528	st_insert(type_map, ID2SYM(rb_intern("method")), ISEQ_TYPE_METHOD);
529	st_insert(type_map, ID2SYM(rb_intern("block")), ISEQ_TYPE_BLOCK);
530	st_insert(type_map, ID2SYM(rb_intern("class")), ISEQ_TYPE_CLASS);
531	st_insert(type_map, ID2SYM(rb_intern("rescue")), ISEQ_TYPE_RESCUE);
532	st_insert(type_map, ID2SYM(rb_intern("ensure")), ISEQ_TYPE_ENSURE);
533	st_insert(type_map, ID2SYM(rb_intern("eval")), ISEQ_TYPE_EVAL);
534	st_insert(type_map, ID2SYM(rb_intern("main")), ISEQ_TYPE_MAIN);
535	st_insert(type_map, ID2SYM(rb_intern("defined_guard")), ISEQ_TYPE_DEFINED_GUARD);
536	cached_map = ATOMIC_PTR_CAS(type_map_cache, (struct st_table *)0, type_map);
537	if (cached_map) {
538	    st_free_table(type_map);
539	    type_map = cached_map;
540	}
541    }
542
543    if (st_lookup(type_map, type, &iseq_type) == 0) {
544	ID typeid = SYM2ID(type);
545	VALUE typename = rb_id2str(typeid);
546	if (typename)
547	    rb_raise(rb_eTypeError, "unsupport type: :%"PRIsVALUE, typename);
548	else
549	    rb_raise(rb_eTypeError, "unsupport type: %p", (void *)typeid);
550    }
551
552    if (parent == Qnil) {
553	parent = 0;
554    }
555
556    make_compile_option(&option, opt);
557    prepare_iseq_build(iseq, name, path, absolute_path, first_lineno,
558		       parent, (enum iseq_type)iseq_type, 0, &option);
559
560    rb_iseq_build_from_ary(iseq, locals, args, exception, body);
561
562    cleanup_iseq_build(iseq);
563    return iseqval;
564}
565
566/*
567 * :nodoc:
568 */
569static VALUE
570iseq_s_load(int argc, VALUE *argv, VALUE self)
571{
572    VALUE data, opt=Qnil;
573    rb_scan_args(argc, argv, "11", &data, &opt);
574
575    return iseq_load(self, data, 0, opt);
576}
577
578VALUE
579rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
580{
581    return iseq_load(rb_cISeq, data, parent, opt);
582}
583
584VALUE
585rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, rb_block_t *base_block, VALUE opt)
586{
587    int state;
588    rb_thread_t *th = GET_THREAD();
589    rb_block_t *prev_base_block = th->base_block;
590    VALUE iseqval = Qundef;
591
592    th->base_block = base_block;
593
594    TH_PUSH_TAG(th);
595    if ((state = EXEC_TAG()) == 0) {
596	VALUE parser;
597	int ln = NUM2INT(line);
598	NODE *node;
599	rb_compile_option_t option;
600
601	StringValueCStr(file);
602	make_compile_option(&option, opt);
603
604	parser = rb_parser_new();
605
606	if (RB_TYPE_P((src), T_FILE))
607	    node = rb_parser_compile_file_path(parser, file, src, ln);
608	else {
609	    node = rb_parser_compile_string_path(parser, file, src, ln);
610
611	    if (!node) {
612		rb_exc_raise(GET_THREAD()->errinfo);	/* TODO: check err */
613	    }
614	}
615
616	if (base_block && base_block->iseq) {
617	    iseqval = rb_iseq_new_with_opt(node, base_block->iseq->location.label,
618					   file, absolute_path, line, base_block->iseq->self,
619					   ISEQ_TYPE_EVAL, &option);
620	}
621	else {
622	    iseqval = rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, absolute_path, line, Qfalse,
623					   ISEQ_TYPE_TOP, &option);
624	}
625    }
626    TH_POP_TAG();
627
628    th->base_block = prev_base_block;
629
630    if (state) {
631	JUMP_TAG(state);
632    }
633
634    return iseqval;
635}
636
637VALUE
638rb_iseq_compile(VALUE src, VALUE file, VALUE line)
639{
640    return rb_iseq_compile_with_option(src, file, Qnil, line, 0, Qnil);
641}
642
643VALUE
644rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, rb_block_t *base_block)
645{
646    return rb_iseq_compile_with_option(src, file, Qnil, line, base_block, Qnil);
647}
648
649/*
650 *  call-seq:
651 *     InstructionSequence.compile(source[, file[, path[, line[, options]]]]) -> iseq
652 *     InstructionSequence.new(source[, file[, path[, line[, options]]]]) -> iseq
653 *
654 *  Takes +source+, a String of Ruby code and compiles it to an
655 *  InstructionSequence.
656 *
657 *  Optionally takes +file+, +path+, and +line+ which describe the filename,
658 *  absolute path and first line number of the ruby code in +source+ which are
659 *  metadata attached to the returned +iseq+.
660 *
661 *  +options+, which can be +true+, +false+ or a +Hash+, is used to
662 *  modify the default behavior of the Ruby iseq compiler.
663 *
664 *  For details regarding valid compile options see ::compile_option=.
665 *
666 *     RubyVM::InstructionSequence.compile("a = 1 + 2")
667 *     #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
668 *
669 */
670static VALUE
671iseq_s_compile(int argc, VALUE *argv, VALUE self)
672{
673    VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;
674
675    rb_secure(1);
676
677    rb_scan_args(argc, argv, "14", &src, &file, &path, &line, &opt);
678    if (NIL_P(file)) file = rb_str_new2("<compiled>");
679    if (NIL_P(line)) line = INT2FIX(1);
680
681    return rb_iseq_compile_with_option(src, file, path, line, 0, opt);
682}
683
684/*
685 *  call-seq:
686 *      InstructionSequence.compile_file(file[, options]) -> iseq
687 *
688 *  Takes +file+, a String with the location of a Ruby source file, reads,
689 *  parses and compiles the file, and returns +iseq+, the compiled
690 *  InstructionSequence with source location metadata set.
691 *
692 *  Optionally takes +options+, which can be +true+, +false+ or a +Hash+, to
693 *  modify the default behavior of the Ruby iseq compiler.
694 *
695 *  For details regarding valid compile options see ::compile_option=.
696 *
697 *      # /tmp/hello.rb
698 *      puts "Hello, world!"
699 *
700 *      # elsewhere
701 *      RubyVM::InstructionSequence.compile_file("/tmp/hello.rb")
702 *      #=> <RubyVM::InstructionSequence:<main>@/tmp/hello.rb>
703 */
704static VALUE
705iseq_s_compile_file(int argc, VALUE *argv, VALUE self)
706{
707    VALUE file, line = INT2FIX(1), opt = Qnil;
708    VALUE parser;
709    VALUE f;
710    NODE *node;
711    const char *fname;
712    rb_compile_option_t option;
713
714    rb_secure(1);
715    rb_scan_args(argc, argv, "11", &file, &opt);
716    FilePathValue(file);
717    fname = StringValueCStr(file);
718
719    f = rb_file_open_str(file, "r");
720
721    parser = rb_parser_new();
722    node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));
723    make_compile_option(&option, opt);
724    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file,
725				rb_realpath_internal(Qnil, file, 1), line, Qfalse,
726				ISEQ_TYPE_TOP, &option);
727}
728
729/*
730 *  call-seq:
731 *     InstructionSequence.compile_option = options
732 *
733 *  Sets the default values for various optimizations in the Ruby iseq
734 *  compiler.
735 *
736 *  Possible values for +options+ include +true+, which enables all options,
737 *  +false+ which disables all options, and +nil+ which leaves all options
738 *  unchanged.
739 *
740 *  You can also pass a +Hash+ of +options+ that you want to change, any
741 *  options not present in the hash will be left unchanged.
742 *
743 *  Possible option names (which are keys in +options+) which can be set to
744 *  +true+ or +false+ include:
745 *
746 *  * +:inline_const_cache+
747 *  * +:instructions_unification+
748 *  * +:operands_unification+
749 *  * +:peephole_optimization+
750 *  * +:specialized_instruction+
751 *  * +:stack_caching+
752 *  * +:tailcall_optimization+
753 *  * +:trace_instruction+
754 *
755 *  Additionally, +:debug_level+ can be set to an integer.
756 *
757 *  These default options can be overwritten for a single run of the iseq
758 *  compiler by passing any of the above values as the +options+ parameter to
759 *  ::new, ::compile and ::compile_file.
760 */
761static VALUE
762iseq_s_compile_option_set(VALUE self, VALUE opt)
763{
764    rb_compile_option_t option;
765    rb_secure(1);
766    make_compile_option(&option, opt);
767    COMPILE_OPTION_DEFAULT = option;
768    return opt;
769}
770
771/*
772 *  call-seq:
773 *     InstructionSequence.compile_option -> options
774 *
775 *  Returns a hash of default options used by the Ruby iseq compiler.
776 *
777 *  For details, see InstructionSequence.compile_option=.
778 */
779static VALUE
780iseq_s_compile_option_get(VALUE self)
781{
782    return make_compile_option_value(&COMPILE_OPTION_DEFAULT);
783}
784
785static rb_iseq_t *
786iseq_check(VALUE val)
787{
788    rb_iseq_t *iseq;
789    GetISeqPtr(val, iseq);
790    if (!iseq->location.label) {
791	rb_raise(rb_eTypeError, "uninitialized InstructionSequence");
792    }
793    return iseq;
794}
795
796/*
797 *  call-seq:
798 *     iseq.eval -> obj
799 *
800 *  Evaluates the instruction sequence and returns the result.
801 *
802 *      RubyVM::InstructionSequence.compile("1 + 2").eval #=> 3
803 */
804static VALUE
805iseq_eval(VALUE self)
806{
807    rb_secure(1);
808    return rb_iseq_eval(self);
809}
810
811/*
812 *  Returns a human-readable string representation of this instruction
813 *  sequence, including the #label and #path.
814 */
815static VALUE
816iseq_inspect(VALUE self)
817{
818    rb_iseq_t *iseq;
819    GetISeqPtr(self, iseq);
820    if (!iseq->location.label) {
821        return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self));
822    }
823
824    return rb_sprintf("<%s:%s@%s>",
825                      rb_obj_classname(self),
826		      RSTRING_PTR(iseq->location.label), RSTRING_PTR(iseq->location.path));
827}
828
829/*
830 *  Returns the path of this instruction sequence.
831 *
832 *  <code><compiled></code> if the iseq was evaluated from a string.
833 *
834 *  For example, using irb:
835 *
836 *	iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
837 *	#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
838 *	iseq.path
839 *	#=> "<compiled>"
840 *
841 *  Using ::compile_file:
842 *
843 *	# /tmp/method.rb
844 *	def hello
845 *	  puts "hello, world"
846 *	end
847 *
848 *	# in irb
849 *	> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
850 *	> iseq.path #=> /tmp/method.rb
851 */
852static VALUE
853iseq_path(VALUE self)
854{
855    rb_iseq_t *iseq;
856    GetISeqPtr(self, iseq);
857    return iseq->location.path;
858}
859
860/*
861 *  Returns the absolute path of this instruction sequence.
862 *
863 *  +nil+ if the iseq was evaluated from a string.
864 *
865 *  For example, using ::compile_file:
866 *
867 *	# /tmp/method.rb
868 *	def hello
869 *	  puts "hello, world"
870 *	end
871 *
872 *	# in irb
873 *	> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
874 *	> iseq.absolute_path #=> /tmp/method.rb
875 */
876static VALUE
877iseq_absolute_path(VALUE self)
878{
879    rb_iseq_t *iseq;
880    GetISeqPtr(self, iseq);
881    return iseq->location.absolute_path;
882}
883
884/*  Returns the label of this instruction sequence.
885 *
886 *  <code><main></code> if it's at the top level, <code><compiled></code> if it
887 *  was evaluated from a string.
888 *
889 *  For example, using irb:
890 *
891 *	iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
892 *	#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
893 *	iseq.label
894 *	#=> "<compiled>"
895 *
896 *  Using ::compile_file:
897 *
898 *	# /tmp/method.rb
899 *	def hello
900 *	  puts "hello, world"
901 *	end
902 *
903 *	# in irb
904 *	> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
905 *	> iseq.label #=> <main>
906 */
907static VALUE
908iseq_label(VALUE self)
909{
910    rb_iseq_t *iseq;
911    GetISeqPtr(self, iseq);
912    return iseq->location.label;
913}
914
915/*  Returns the base label of this instruction sequence.
916 *
917 *  For example, using irb:
918 *
919 *	iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
920 *	#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
921 *	iseq.base_label
922 *	#=> "<compiled>"
923 *
924 *  Using ::compile_file:
925 *
926 *	# /tmp/method.rb
927 *	def hello
928 *	  puts "hello, world"
929 *	end
930 *
931 *	# in irb
932 *	> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
933 *	> iseq.base_label #=> <main>
934 */
935static VALUE
936iseq_base_label(VALUE self)
937{
938    rb_iseq_t *iseq;
939    GetISeqPtr(self, iseq);
940    return iseq->location.base_label;
941}
942
943/*  Returns the number of the first source line where the instruction sequence
944 *  was loaded from.
945 *
946 *  For example, using irb:
947 *
948 *	iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
949 *	#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
950 *	iseq.first_lineno
951 *	#=> 1
952 */
953static VALUE
954iseq_first_lineno(VALUE self)
955{
956    rb_iseq_t *iseq;
957    GetISeqPtr(self, iseq);
958    return iseq->location.first_lineno;
959}
960
961static
962VALUE iseq_data_to_ary(rb_iseq_t *iseq);
963
964/*
965 *  call-seq:
966 *     iseq.to_a -> ary
967 *
968 *  Returns an Array with 14 elements representing the instruction sequence
969 *  with the following data:
970 *
971 *  [magic]
972 *    A string identifying the data format. <b>Always
973 *    +YARVInstructionSequence/SimpleDataFormat+.</b>
974 *
975 *  [major_version]
976 *    The major version of the instruction sequence.
977 *
978 *  [minor_version]
979 *    The minor version of the instruction sequence.
980 *
981 *  [format_type]
982 *    A number identifying the data format. <b>Always 1</b>.
983 *
984 *  [misc]
985 *    A hash containing:
986 *
987 *    [+:arg_size+]
988 *	the total number of arguments taken by the method or the block (0 if
989 *	_iseq_ doesn't represent a method or block)
990 *    [+:local_size+]
991 *	the number of local variables + 1
992 *    [+:stack_max+]
993 *	used in calculating the stack depth at which a SystemStackError is
994 *	thrown.
995 *
996 *  [#label]
997 *    The name of the context (block, method, class, module, etc.) that this
998 *    instruction sequence belongs to.
999 *
1000 *    <code><main></code> if it's at the top level, <code><compiled></code> if
1001 *    it was evaluated from a string.
1002 *
1003 *  [#path]
1004 *    The relative path to the Ruby file where the instruction sequence was
1005 *    loaded from.
1006 *
1007 *    <code><compiled></code> if the iseq was evaluated from a string.
1008 *
1009 *  [#absolute_path]
1010 *    The absolute path to the Ruby file where the instruction sequence was
1011 *    loaded from.
1012 *
1013 *    +nil+ if the iseq was evaluated from a string.
1014 *
1015 *  [#first_lineno]
1016 *    The number of the first source line where the instruction sequence was
1017 *    loaded from.
1018 *
1019 *  [type]
1020 *    The type of the instruction sequence.
1021 *
1022 *    Valid values are +:top+, +:method+, +:block+, +:class+, +:rescue+,
1023 *    +:ensure+, +:eval+, +:main+, and +:defined_guard+.
1024 *
1025 *  [locals]
1026 *    An array containing the names of all arguments and local variables as
1027 *    symbols.
1028 *
1029 *  [args]
1030 *    The arity if the method or block only has required arguments.
1031 *
1032 *    Otherwise an array of:
1033 *
1034 *      [required_argc, [optional_arg_labels, ...],
1035 *       splat_index, post_splat_argc, post_splat_index,
1036 *       block_index, simple]
1037 *
1038 *    More info about these values can be found in +vm_core.h+.
1039 *
1040 *  [catch_table]
1041 *    A list of exceptions and control flow operators (rescue, next, redo,
1042 *    break, etc.).
1043 *
1044 *  [bytecode]
1045 *    An array of arrays containing the instruction names and operands that
1046 *    make up the body of the instruction sequence.
1047 *
1048 */
1049static VALUE
1050iseq_to_a(VALUE self)
1051{
1052    rb_iseq_t *iseq = iseq_check(self);
1053    rb_secure(1);
1054    return iseq_data_to_ary(iseq);
1055}
1056
1057int
1058rb_iseq_first_lineno(const rb_iseq_t *iseq)
1059{
1060    return FIX2INT(iseq->location.first_lineno);
1061}
1062
1063/* TODO: search algorithm is brute force.
1064         this should be binary search or so. */
1065
1066static struct iseq_line_info_entry *
1067get_line_info(const rb_iseq_t *iseq, size_t pos)
1068{
1069    size_t i = 0, size = iseq->line_info_size;
1070    struct iseq_line_info_entry *table = iseq->line_info_table;
1071    const int debug = 0;
1072
1073    if (debug) {
1074	printf("size: %"PRIdSIZE"\n", size);
1075	printf("table[%"PRIdSIZE"]: position: %d, line: %d, pos: %"PRIdSIZE"\n",
1076	       i, table[i].position, table[i].line_no, pos);
1077    }
1078
1079    if (size == 0) {
1080	return 0;
1081    }
1082    else if (size == 1) {
1083	return &table[0];
1084    }
1085    else {
1086	for (i=1; i<size; i++) {
1087	    if (debug) printf("table[%"PRIdSIZE"]: position: %d, line: %d, pos: %"PRIdSIZE"\n",
1088			      i, table[i].position, table[i].line_no, pos);
1089
1090	    if (table[i].position == pos) {
1091		return &table[i];
1092	    }
1093	    if (table[i].position > pos) {
1094		return &table[i-1];
1095	    }
1096	}
1097    }
1098    return &table[i-1];
1099}
1100
1101static unsigned int
1102find_line_no(const rb_iseq_t *iseq, size_t pos)
1103{
1104    struct iseq_line_info_entry *entry = get_line_info(iseq, pos);
1105    if (entry) {
1106	return entry->line_no;
1107    }
1108    else {
1109	return 0;
1110    }
1111}
1112
1113unsigned int
1114rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
1115{
1116    if (pos == 0) {
1117	return find_line_no(iseq, pos);
1118    }
1119    else {
1120	return find_line_no(iseq, pos - 1);
1121    }
1122}
1123
1124static VALUE
1125id_to_name(ID id, VALUE default_value)
1126{
1127    VALUE str = rb_id2str(id);
1128    if (!str) {
1129	str = default_value;
1130    }
1131    else if (!rb_str_symname_p(str)) {
1132	str = rb_str_inspect(str);
1133    }
1134    return str;
1135}
1136
1137VALUE
1138insn_operand_intern(rb_iseq_t *iseq,
1139		    VALUE insn, int op_no, VALUE op,
1140		    int len, size_t pos, VALUE *pnop, VALUE child)
1141{
1142    const char *types = insn_op_types(insn);
1143    char type = types[op_no];
1144    VALUE ret;
1145
1146    switch (type) {
1147      case TS_OFFSET:		/* LONG */
1148	ret = rb_sprintf("%"PRIdVALUE, (VALUE)(pos + len + op));
1149	break;
1150
1151      case TS_NUM:		/* ULONG */
1152	ret = rb_sprintf("%"PRIuVALUE, op);
1153	break;
1154
1155      case TS_LINDEX:{
1156	if (insn == BIN(getlocal) || insn == BIN(setlocal)) {
1157	    if (pnop) {
1158		rb_iseq_t *diseq = iseq;
1159		VALUE level = *pnop, i;
1160
1161		for (i = 0; i < level; i++) {
1162		    diseq = diseq->parent_iseq;
1163		}
1164		ret = id_to_name(diseq->local_table[diseq->local_size - op], INT2FIX('*'));
1165	    }
1166	    else {
1167		ret = rb_sprintf("%"PRIuVALUE, op);
1168	    }
1169	}
1170	else {
1171	    ret = rb_inspect(INT2FIX(op));
1172	}
1173	break;
1174      }
1175      case TS_ID:		/* ID (symbol) */
1176	op = ID2SYM(op);
1177
1178      case TS_VALUE:		/* VALUE */
1179	op = obj_resurrect(op);
1180	ret = rb_inspect(op);
1181	if (CLASS_OF(op) == rb_cISeq) {
1182	    if (child) {
1183		rb_ary_push(child, op);
1184	    }
1185	}
1186	break;
1187
1188      case TS_ISEQ:		/* iseq */
1189	{
1190	    rb_iseq_t *iseq = (rb_iseq_t *)op;
1191	    if (iseq) {
1192		ret = iseq->location.label;
1193		if (child) {
1194		    rb_ary_push(child, iseq->self);
1195		}
1196	    }
1197	    else {
1198		ret = rb_str_new2("nil");
1199	    }
1200	    break;
1201	}
1202      case TS_GENTRY:
1203	{
1204	    struct rb_global_entry *entry = (struct rb_global_entry *)op;
1205	    ret = rb_str_dup(rb_id2str(entry->id));
1206	}
1207	break;
1208
1209      case TS_IC:
1210	ret = rb_sprintf("<ic:%"PRIdPTRDIFF">", (struct iseq_inline_cache_entry *)op - iseq->ic_entries);
1211	break;
1212
1213      case TS_CALLINFO:
1214	{
1215	    rb_call_info_t *ci = (rb_call_info_t *)op;
1216	    VALUE ary = rb_ary_new();
1217
1218	    if (ci->mid) {
1219		rb_ary_push(ary, rb_sprintf("mid:%s", rb_id2name(ci->mid)));
1220	    }
1221
1222	    rb_ary_push(ary, rb_sprintf("argc:%d", ci->orig_argc));
1223
1224	    if (ci->blockiseq) {
1225		if (child) {
1226		    rb_ary_push(child, ci->blockiseq->self);
1227		}
1228		rb_ary_push(ary, rb_sprintf("block:%"PRIsVALUE, ci->blockiseq->location.label));
1229	    }
1230
1231	    if (ci->flag) {
1232		VALUE flags = rb_ary_new();
1233		if (ci->flag & VM_CALL_ARGS_SPLAT) rb_ary_push(flags, rb_str_new2("ARGS_SPLAT"));
1234		if (ci->flag & VM_CALL_ARGS_BLOCKARG) rb_ary_push(flags, rb_str_new2("ARGS_BLOCKARG"));
1235		if (ci->flag & VM_CALL_FCALL) rb_ary_push(flags, rb_str_new2("FCALL"));
1236		if (ci->flag & VM_CALL_VCALL) rb_ary_push(flags, rb_str_new2("VCALL"));
1237		if (ci->flag & VM_CALL_TAILCALL) rb_ary_push(flags, rb_str_new2("TAILCALL"));
1238		if (ci->flag & VM_CALL_SUPER) rb_ary_push(flags, rb_str_new2("SUPER"));
1239		if (ci->flag & VM_CALL_OPT_SEND) rb_ary_push(flags, rb_str_new2("SNED")); /* maybe not reachable */
1240		if (ci->flag & VM_CALL_ARGS_SKIP_SETUP) rb_ary_push(flags, rb_str_new2("ARGS_SKIP")); /* maybe not reachable */
1241		rb_ary_push(ary, rb_ary_join(flags, rb_str_new2("|")));
1242	    }
1243	    ret = rb_sprintf("<callinfo!%"PRIsVALUE">", rb_ary_join(ary, rb_str_new2(", ")));
1244	}
1245	break;
1246
1247      case TS_CDHASH:
1248	ret = rb_str_new2("<cdhash>");
1249	break;
1250
1251      case TS_FUNCPTR:
1252	ret = rb_str_new2("<funcptr>");
1253	break;
1254
1255      default:
1256	rb_bug("insn_operand_intern: unknown operand type: %c", type);
1257    }
1258    return ret;
1259}
1260
1261/**
1262 * Disassemble a instruction
1263 * Iseq -> Iseq inspect object
1264 */
1265int
1266rb_iseq_disasm_insn(VALUE ret, VALUE *iseq, size_t pos,
1267		    rb_iseq_t *iseqdat, VALUE child)
1268{
1269    VALUE insn = iseq[pos];
1270    int len = insn_len(insn);
1271    int j;
1272    const char *types = insn_op_types(insn);
1273    VALUE str = rb_str_new(0, 0);
1274    const char *insn_name_buff;
1275
1276    insn_name_buff = insn_name(insn);
1277    if (1) {
1278	rb_str_catf(str, "%04"PRIdSIZE" %-16s ", pos, insn_name_buff);
1279    }
1280    else {
1281	rb_str_catf(str, "%04"PRIdSIZE" %-16.*s ", pos,
1282		    (int)strcspn(insn_name_buff, "_"), insn_name_buff);
1283    }
1284
1285    for (j = 0; types[j]; j++) {
1286	const char *types = insn_op_types(insn);
1287	VALUE opstr = insn_operand_intern(iseqdat, insn, j, iseq[pos + j + 1],
1288					  len, pos, &iseq[pos + j + 2],
1289					  child);
1290	rb_str_concat(str, opstr);
1291
1292	if (types[j + 1]) {
1293	    rb_str_cat2(str, ", ");
1294	}
1295    }
1296
1297    {
1298	unsigned int line_no = find_line_no(iseqdat, pos);
1299	unsigned int prev = pos == 0 ? 0 : find_line_no(iseqdat, pos - 1);
1300	if (line_no && line_no != prev) {
1301	    long slen = RSTRING_LEN(str);
1302	    slen = (slen > 70) ? 0 : (70 - slen);
1303	    str = rb_str_catf(str, "%*s(%4d)", (int)slen, "", line_no);
1304	}
1305    }
1306
1307    if (ret) {
1308	rb_str_cat2(str, "\n");
1309	rb_str_concat(ret, str);
1310    }
1311    else {
1312	printf("%s\n", RSTRING_PTR(str));
1313    }
1314    return len;
1315}
1316
1317static const char *
1318catch_type(int type)
1319{
1320    switch (type) {
1321      case CATCH_TYPE_RESCUE:
1322	return "rescue";
1323      case CATCH_TYPE_ENSURE:
1324	return "ensure";
1325      case CATCH_TYPE_RETRY:
1326	return "retry";
1327      case CATCH_TYPE_BREAK:
1328	return "break";
1329      case CATCH_TYPE_REDO:
1330	return "redo";
1331      case CATCH_TYPE_NEXT:
1332	return "next";
1333      default:
1334	rb_bug("unknown catch type (%d)", type);
1335	return 0;
1336    }
1337}
1338
1339/*
1340 *  call-seq:
1341 *     iseq.disasm -> str
1342 *     iseq.disassemble -> str
1343 *
1344 *  Returns the instruction sequence as a +String+ in human readable form.
1345 *
1346 *    puts RubyVM::InstructionSequence.compile('1 + 2').disasm
1347 *
1348 *  Produces:
1349 *
1350 *    == disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
1351 *    0000 trace            1                                               (   1)
1352 *    0002 putobject        1
1353 *    0004 putobject        2
1354 *    0006 opt_plus         <ic:1>
1355 *    0008 leave
1356 */
1357VALUE
1358rb_iseq_disasm(VALUE self)
1359{
1360    rb_iseq_t *iseqdat = iseq_check(self);
1361    VALUE *iseq;
1362    VALUE str = rb_str_new(0, 0);
1363    VALUE child = rb_ary_new();
1364    unsigned long size;
1365    int i;
1366    long l;
1367    ID *tbl;
1368    size_t n;
1369    enum {header_minlen = 72};
1370
1371    rb_secure(1);
1372
1373    iseq = iseqdat->iseq;
1374    size = iseqdat->iseq_size;
1375
1376    rb_str_cat2(str, "== disasm: ");
1377
1378    rb_str_concat(str, iseq_inspect(iseqdat->self));
1379    if ((l = RSTRING_LEN(str)) < header_minlen) {
1380	rb_str_resize(str, header_minlen);
1381	memset(RSTRING_PTR(str) + l, '=', header_minlen - l);
1382    }
1383    rb_str_cat2(str, "\n");
1384
1385    /* show catch table information */
1386    if (iseqdat->catch_table_size != 0) {
1387	rb_str_cat2(str, "== catch table\n");
1388    }
1389    for (i = 0; i < iseqdat->catch_table_size; i++) {
1390	struct iseq_catch_table_entry *entry = &iseqdat->catch_table[i];
1391	rb_str_catf(str,
1392		    "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
1393		    catch_type((int)entry->type), (int)entry->start,
1394		    (int)entry->end, (int)entry->sp, (int)entry->cont);
1395	if (entry->iseq) {
1396	    rb_str_concat(str, rb_iseq_disasm(entry->iseq));
1397	}
1398    }
1399    if (iseqdat->catch_table_size != 0) {
1400	rb_str_cat2(str, "|-------------------------------------"
1401		    "-----------------------------------\n");
1402    }
1403
1404    /* show local table information */
1405    tbl = iseqdat->local_table;
1406
1407    if (tbl) {
1408	rb_str_catf(str,
1409		    "local table (size: %d, argc: %d "
1410		    "[opts: %d, rest: %d, post: %d, block: %d] s%d)\n",
1411		    iseqdat->local_size, iseqdat->argc,
1412		    iseqdat->arg_opts, iseqdat->arg_rest,
1413		    iseqdat->arg_post_len, iseqdat->arg_block,
1414		    iseqdat->arg_simple);
1415
1416	for (i = 0; i < iseqdat->local_table_size; i++) {
1417	    long width;
1418	    VALUE name = id_to_name(tbl[i], 0);
1419	    char argi[0x100] = "";
1420	    char opti[0x100] = "";
1421
1422	    if (iseqdat->arg_opts) {
1423		int argc = iseqdat->argc;
1424		int opts = iseqdat->arg_opts;
1425		if (i >= argc && i < argc + opts - 1) {
1426		    snprintf(opti, sizeof(opti), "Opt=%"PRIdVALUE,
1427			     iseqdat->arg_opt_table[i - argc]);
1428		}
1429	    }
1430
1431	    snprintf(argi, sizeof(argi), "%s%s%s%s%s",	/* arg, opts, rest, post  block */
1432		     iseqdat->argc > i ? "Arg" : "",
1433		     opti,
1434		     iseqdat->arg_rest == i ? "Rest" : "",
1435		     (iseqdat->arg_post_start <= i &&
1436		      i < iseqdat->arg_post_start + iseqdat->arg_post_len) ? "Post" : "",
1437		     iseqdat->arg_block == i ? "Block" : "");
1438
1439	    rb_str_catf(str, "[%2d] ", iseqdat->local_size - i);
1440	    width = RSTRING_LEN(str) + 11;
1441	    if (name)
1442		rb_str_append(str, name);
1443	    else
1444		rb_str_cat2(str, "?");
1445	    if (*argi) rb_str_catf(str, "<%s>", argi);
1446	    if ((width -= RSTRING_LEN(str)) > 0) rb_str_catf(str, "%*s", (int)width, "");
1447	}
1448	rb_str_cat2(str, "\n");
1449    }
1450
1451    /* show each line */
1452    for (n = 0; n < size;) {
1453	n += rb_iseq_disasm_insn(str, iseq, n, iseqdat, child);
1454    }
1455
1456    for (i = 0; i < RARRAY_LEN(child); i++) {
1457	VALUE isv = rb_ary_entry(child, i);
1458	rb_str_concat(str, rb_iseq_disasm(isv));
1459    }
1460
1461    return str;
1462}
1463
1464/*
1465 *  Returns the instruction sequence containing the given proc or method.
1466 *
1467 *  For example, using irb:
1468 *
1469 *	# a proc
1470 *	> p = proc { num = 1 + 2 }
1471 *	> RubyVM::InstructionSequence.of(p)
1472 *	> #=> <RubyVM::InstructionSequence:block in irb_binding@(irb)>
1473 *
1474 *	# for a method
1475 *	> def foo(bar); puts bar; end
1476 *	> RubyVM::InstructionSequence.of(method(:foo))
1477 *	> #=> <RubyVM::InstructionSequence:foo@(irb)>
1478 *
1479 *  Using ::compile_file:
1480 *
1481 *	# /tmp/iseq_of.rb
1482 *	def hello
1483 *	  puts "hello, world"
1484 *	end
1485 *
1486 *	$a_global_proc = proc { str = 'a' + 'b' }
1487 *
1488 *	# in irb
1489 *	> require '/tmp/iseq_of.rb'
1490 *
1491 *	# first the method hello
1492 *	> RubyVM::InstructionSequence.of(method(:hello))
1493 *	> #=> #<RubyVM::InstructionSequence:0x007fb73d7cb1d0>
1494 *
1495 *	# then the global proc
1496 *	> RubyVM::InstructionSequence.of($a_global_proc)
1497 *	> #=> #<RubyVM::InstructionSequence:0x007fb73d7caf78>
1498 */
1499static VALUE
1500iseq_s_of(VALUE klass, VALUE body)
1501{
1502    VALUE ret = Qnil;
1503    rb_iseq_t *iseq;
1504
1505    rb_secure(1);
1506
1507    if (rb_obj_is_proc(body)) {
1508	rb_proc_t *proc;
1509	GetProcPtr(body, proc);
1510	iseq = proc->block.iseq;
1511	if (RUBY_VM_NORMAL_ISEQ_P(iseq)) {
1512	    ret = iseq->self;
1513	}
1514    }
1515    else if ((iseq = rb_method_get_iseq(body)) != 0) {
1516	ret = iseq->self;
1517    }
1518    return ret;
1519}
1520
1521/*
1522 *  call-seq:
1523 *     InstructionSequence.disasm(body) -> str
1524 *     InstructionSequence.disassemble(body) -> str
1525 *
1526 *  Takes +body+, a Method or Proc object, and returns a String with the
1527 *  human readable instructions for +body+.
1528 *
1529 *  For a Method object:
1530 *
1531 *    # /tmp/method.rb
1532 *    def hello
1533 *      puts "hello, world"
1534 *    end
1535 *
1536 *    puts RubyVM::InstructionSequence.disasm(method(:hello))
1537 *
1538 *  Produces:
1539 *
1540 *    == disasm: <RubyVM::InstructionSequence:hello@/tmp/method.rb>============
1541 *    0000 trace            8                                               (   1)
1542 *    0002 trace            1                                               (   2)
1543 *    0004 putself
1544 *    0005 putstring        "hello, world"
1545 *    0007 send             :puts, 1, nil, 8, <ic:0>
1546 *    0013 trace            16                                              (   3)
1547 *    0015 leave                                                            (   2)
1548 *
1549 *  For a Proc:
1550 *
1551 *    # /tmp/proc.rb
1552 *    p = proc { num = 1 + 2 }
1553 *    puts RubyVM::InstructionSequence.disasm(p)
1554 *
1555 *  Produces:
1556 *
1557 *    == disasm: <RubyVM::InstructionSequence:block in <main>@/tmp/proc.rb>===
1558 *    == catch table
1559 *    | catch type: redo   st: 0000 ed: 0012 sp: 0000 cont: 0000
1560 *    | catch type: next   st: 0000 ed: 0012 sp: 0000 cont: 0012
1561 *    |------------------------------------------------------------------------
1562 *    local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
1563 *    [ 2] num
1564 *    0000 trace            1                                               (   1)
1565 *    0002 putobject        1
1566 *    0004 putobject        2
1567 *    0006 opt_plus         <ic:1>
1568 *    0008 dup
1569 *    0009 setlocal         num, 0
1570 *    0012 leave
1571 *
1572 */
1573
1574static VALUE
1575iseq_s_disasm(VALUE klass, VALUE body)
1576{
1577    VALUE iseqval = iseq_s_of(klass, body);
1578    return NIL_P(iseqval) ? Qnil : rb_iseq_disasm(iseqval);
1579}
1580
1581const char *
1582ruby_node_name(int node)
1583{
1584    switch (node) {
1585#include "node_name.inc"
1586      default:
1587	rb_bug("unknown node (%d)", node);
1588	return 0;
1589    }
1590}
1591
1592#define DECL_SYMBOL(name) \
1593  static VALUE sym_##name
1594
1595#define INIT_SYMBOL(name) \
1596  sym_##name = ID2SYM(rb_intern(#name))
1597
1598static VALUE
1599register_label(struct st_table *table, unsigned long idx)
1600{
1601    VALUE sym;
1602    char buff[8 + (sizeof(idx) * CHAR_BIT * 32 / 100)];
1603
1604    snprintf(buff, sizeof(buff), "label_%lu", idx);
1605    sym = ID2SYM(rb_intern(buff));
1606    st_insert(table, idx, sym);
1607    return sym;
1608}
1609
1610static VALUE
1611exception_type2symbol(VALUE type)
1612{
1613    ID id;
1614    switch (type) {
1615      case CATCH_TYPE_RESCUE: CONST_ID(id, "rescue"); break;
1616      case CATCH_TYPE_ENSURE: CONST_ID(id, "ensure"); break;
1617      case CATCH_TYPE_RETRY:  CONST_ID(id, "retry");  break;
1618      case CATCH_TYPE_BREAK:  CONST_ID(id, "break");  break;
1619      case CATCH_TYPE_REDO:   CONST_ID(id, "redo");   break;
1620      case CATCH_TYPE_NEXT:   CONST_ID(id, "next");   break;
1621      default:
1622	rb_bug("...");
1623    }
1624    return ID2SYM(id);
1625}
1626
1627static int
1628cdhash_each(VALUE key, VALUE value, VALUE ary)
1629{
1630    rb_ary_push(ary, obj_resurrect(key));
1631    rb_ary_push(ary, value);
1632    return ST_CONTINUE;
1633}
1634
1635static VALUE
1636iseq_data_to_ary(rb_iseq_t *iseq)
1637{
1638    long i;
1639    size_t ti;
1640    unsigned int pos;
1641    unsigned int line = 0;
1642    VALUE *seq;
1643
1644    VALUE val = rb_ary_new();
1645    VALUE type; /* Symbol */
1646    VALUE locals = rb_ary_new();
1647    VALUE args = rb_ary_new();
1648    VALUE body = rb_ary_new(); /* [[:insn1, ...], ...] */
1649    VALUE nbody;
1650    VALUE exception = rb_ary_new(); /* [[....]] */
1651    VALUE misc = rb_hash_new();
1652
1653    static VALUE insn_syms[VM_INSTRUCTION_SIZE];
1654    struct st_table *labels_table = st_init_numtable();
1655
1656    DECL_SYMBOL(top);
1657    DECL_SYMBOL(method);
1658    DECL_SYMBOL(block);
1659    DECL_SYMBOL(class);
1660    DECL_SYMBOL(rescue);
1661    DECL_SYMBOL(ensure);
1662    DECL_SYMBOL(eval);
1663    DECL_SYMBOL(main);
1664    DECL_SYMBOL(defined_guard);
1665
1666    if (sym_top == 0) {
1667	int i;
1668	for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
1669	    insn_syms[i] = ID2SYM(rb_intern(insn_name(i)));
1670	}
1671	INIT_SYMBOL(top);
1672	INIT_SYMBOL(method);
1673	INIT_SYMBOL(block);
1674	INIT_SYMBOL(class);
1675	INIT_SYMBOL(rescue);
1676	INIT_SYMBOL(ensure);
1677	INIT_SYMBOL(eval);
1678	INIT_SYMBOL(main);
1679	INIT_SYMBOL(defined_guard);
1680    }
1681
1682    /* type */
1683    switch (iseq->type) {
1684      case ISEQ_TYPE_TOP:    type = sym_top;    break;
1685      case ISEQ_TYPE_METHOD: type = sym_method; break;
1686      case ISEQ_TYPE_BLOCK:  type = sym_block;  break;
1687      case ISEQ_TYPE_CLASS:  type = sym_class;  break;
1688      case ISEQ_TYPE_RESCUE: type = sym_rescue; break;
1689      case ISEQ_TYPE_ENSURE: type = sym_ensure; break;
1690      case ISEQ_TYPE_EVAL:   type = sym_eval;   break;
1691      case ISEQ_TYPE_MAIN:   type = sym_main;   break;
1692      case ISEQ_TYPE_DEFINED_GUARD: type = sym_defined_guard; break;
1693      default: rb_bug("unsupported iseq type");
1694    };
1695
1696    /* locals */
1697    for (i=0; i<iseq->local_table_size; i++) {
1698	ID lid = iseq->local_table[i];
1699	if (lid) {
1700	    if (rb_id2str(lid)) rb_ary_push(locals, ID2SYM(lid));
1701	}
1702	else {
1703	    rb_ary_push(locals, ID2SYM(rb_intern("#arg_rest")));
1704	}
1705    }
1706
1707    /* args */
1708    {
1709	/*
1710	 * [argc,                 # argc
1711	 *  [label1, label2, ...] # opts
1712	 *  rest index,
1713	 *  post_len
1714	 *  post_start
1715	 *  block index,
1716	 *  simple,
1717         * ]
1718	 */
1719	VALUE arg_opt_labels = rb_ary_new();
1720	int j;
1721
1722	for (j=0; j<iseq->arg_opts; j++) {
1723	    rb_ary_push(arg_opt_labels,
1724			register_label(labels_table, iseq->arg_opt_table[j]));
1725	}
1726
1727	/* commit */
1728	if (iseq->arg_simple == 1) {
1729	    args = INT2FIX(iseq->argc);
1730	}
1731	else {
1732	    rb_ary_push(args, INT2FIX(iseq->argc));
1733	    rb_ary_push(args, arg_opt_labels);
1734	    rb_ary_push(args, INT2FIX(iseq->arg_post_len));
1735	    rb_ary_push(args, INT2FIX(iseq->arg_post_start));
1736	    rb_ary_push(args, INT2FIX(iseq->arg_rest));
1737	    rb_ary_push(args, INT2FIX(iseq->arg_block));
1738	    rb_ary_push(args, INT2FIX(iseq->arg_simple));
1739	}
1740    }
1741
1742    /* body */
1743    for (seq = iseq->iseq; seq < iseq->iseq + iseq->iseq_size; ) {
1744	VALUE insn = *seq++;
1745	int j, len = insn_len(insn);
1746	VALUE *nseq = seq + len - 1;
1747	VALUE ary = rb_ary_new2(len);
1748
1749	rb_ary_push(ary, insn_syms[insn]);
1750	for (j=0; j<len-1; j++, seq++) {
1751	    switch (insn_op_type(insn, j)) {
1752	      case TS_OFFSET: {
1753		unsigned long idx = nseq - iseq->iseq + *seq;
1754		rb_ary_push(ary, register_label(labels_table, idx));
1755		break;
1756	      }
1757	      case TS_LINDEX:
1758	      case TS_NUM:
1759		rb_ary_push(ary, INT2FIX(*seq));
1760		break;
1761	      case TS_VALUE:
1762		rb_ary_push(ary, obj_resurrect(*seq));
1763		break;
1764	      case TS_ISEQ:
1765		{
1766		    rb_iseq_t *iseq = (rb_iseq_t *)*seq;
1767		    if (iseq) {
1768			VALUE val = iseq_data_to_ary(iseq);
1769			rb_ary_push(ary, val);
1770		    }
1771		    else {
1772			rb_ary_push(ary, Qnil);
1773		    }
1774		}
1775		break;
1776	      case TS_GENTRY:
1777		{
1778		    struct rb_global_entry *entry = (struct rb_global_entry *)*seq;
1779		    rb_ary_push(ary, ID2SYM(entry->id));
1780		}
1781		break;
1782	      case TS_IC: {
1783		  struct iseq_inline_cache_entry *ic = (struct iseq_inline_cache_entry *)*seq;
1784		    rb_ary_push(ary, INT2FIX(ic - iseq->ic_entries));
1785	        }
1786		break;
1787	      case TS_CALLINFO:
1788		{
1789		    rb_call_info_t *ci = (rb_call_info_t *)*seq;
1790		    VALUE e = rb_hash_new();
1791		    rb_hash_aset(e, ID2SYM(rb_intern("mid")), ci->mid ? ID2SYM(ci->mid) : Qnil);
1792		    rb_hash_aset(e, ID2SYM(rb_intern("flag")), ULONG2NUM(ci->flag));
1793		    rb_hash_aset(e, ID2SYM(rb_intern("orig_argc")), INT2FIX(ci->orig_argc));
1794		    rb_hash_aset(e, ID2SYM(rb_intern("blockptr")), ci->blockiseq ? iseq_data_to_ary(ci->blockiseq) : Qnil);
1795		    rb_ary_push(ary, e);
1796	        }
1797		break;
1798	      case TS_ID:
1799		rb_ary_push(ary, ID2SYM(*seq));
1800		break;
1801	      case TS_CDHASH:
1802		{
1803		    VALUE hash = *seq;
1804		    VALUE val = rb_ary_new();
1805		    int i;
1806
1807		    rb_hash_foreach(hash, cdhash_each, val);
1808
1809		    for (i=0; i<RARRAY_LEN(val); i+=2) {
1810			VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
1811			unsigned long idx = nseq - iseq->iseq + pos;
1812
1813			rb_ary_store(val, i+1,
1814				     register_label(labels_table, idx));
1815		    }
1816		    rb_ary_push(ary, val);
1817		}
1818		break;
1819	      default:
1820		rb_bug("unknown operand: %c", insn_op_type(insn, j));
1821	    }
1822	}
1823	rb_ary_push(body, ary);
1824    }
1825
1826    nbody = body;
1827
1828    /* exception */
1829    for (i=0; i<iseq->catch_table_size; i++) {
1830	VALUE ary = rb_ary_new();
1831	struct iseq_catch_table_entry *entry = &iseq->catch_table[i];
1832	rb_ary_push(ary, exception_type2symbol(entry->type));
1833	if (entry->iseq) {
1834	    rb_iseq_t *eiseq;
1835	    GetISeqPtr(entry->iseq, eiseq);
1836	    rb_ary_push(ary, iseq_data_to_ary(eiseq));
1837	}
1838	else {
1839	    rb_ary_push(ary, Qnil);
1840	}
1841	rb_ary_push(ary, register_label(labels_table, entry->start));
1842	rb_ary_push(ary, register_label(labels_table, entry->end));
1843	rb_ary_push(ary, register_label(labels_table, entry->cont));
1844	rb_ary_push(ary, INT2FIX(entry->sp));
1845	rb_ary_push(exception, ary);
1846    }
1847
1848    /* make body with labels and insert line number */
1849    body = rb_ary_new();
1850    ti = 0;
1851
1852    for (i=0, pos=0; i<RARRAY_LEN(nbody); i++) {
1853	VALUE ary = RARRAY_PTR(nbody)[i];
1854	st_data_t label;
1855
1856	if (st_lookup(labels_table, pos, &label)) {
1857	    rb_ary_push(body, (VALUE)label);
1858	}
1859
1860	if (ti < iseq->line_info_size && iseq->line_info_table[ti].position == pos) {
1861	    line = iseq->line_info_table[ti].line_no;
1862	    rb_ary_push(body, INT2FIX(line));
1863	    ti++;
1864	}
1865
1866	rb_ary_push(body, ary);
1867	pos += RARRAY_LENINT(ary); /* reject too huge data */
1868    }
1869
1870    st_free_table(labels_table);
1871
1872    rb_hash_aset(misc, ID2SYM(rb_intern("arg_size")), INT2FIX(iseq->arg_size));
1873    rb_hash_aset(misc, ID2SYM(rb_intern("local_size")), INT2FIX(iseq->local_size));
1874    rb_hash_aset(misc, ID2SYM(rb_intern("stack_max")), INT2FIX(iseq->stack_max));
1875
1876    /* TODO: compatibility issue */
1877    /*
1878     * [:magic, :major_version, :minor_version, :format_type, :misc,
1879     *  :name, :path, :absolute_path, :start_lineno, :type, :locals, :args,
1880     *  :catch_table, :bytecode]
1881     */
1882    rb_ary_push(val, rb_str_new2("YARVInstructionSequence/SimpleDataFormat"));
1883    rb_ary_push(val, INT2FIX(ISEQ_MAJOR_VERSION)); /* major */
1884    rb_ary_push(val, INT2FIX(ISEQ_MINOR_VERSION)); /* minor */
1885    rb_ary_push(val, INT2FIX(1));
1886    rb_ary_push(val, misc);
1887    rb_ary_push(val, iseq->location.label);
1888    rb_ary_push(val, iseq->location.path);
1889    rb_ary_push(val, iseq->location.absolute_path);
1890    rb_ary_push(val, iseq->location.first_lineno);
1891    rb_ary_push(val, type);
1892    rb_ary_push(val, locals);
1893    rb_ary_push(val, args);
1894    rb_ary_push(val, exception);
1895    rb_ary_push(val, body);
1896    return val;
1897}
1898
1899VALUE
1900rb_iseq_clone(VALUE iseqval, VALUE newcbase)
1901{
1902    VALUE newiseq = iseq_alloc(rb_cISeq);
1903    rb_iseq_t *iseq0, *iseq1;
1904
1905    GetISeqPtr(iseqval, iseq0);
1906    GetISeqPtr(newiseq, iseq1);
1907
1908    *iseq1 = *iseq0;
1909    iseq1->self = newiseq;
1910    if (!iseq1->orig) {
1911	iseq1->orig = iseqval;
1912    }
1913    if (iseq0->local_iseq == iseq0) {
1914	iseq1->local_iseq = iseq1;
1915    }
1916    if (newcbase) {
1917	iseq1->cref_stack = NEW_CREF(newcbase);
1918	iseq1->cref_stack->nd_refinements = iseq0->cref_stack->nd_refinements;
1919	iseq1->cref_stack->nd_visi = iseq0->cref_stack->nd_visi;
1920	if (iseq0->cref_stack->nd_next) {
1921	    iseq1->cref_stack->nd_next = iseq0->cref_stack->nd_next;
1922	}
1923	iseq1->klass = newcbase;
1924    }
1925
1926    return newiseq;
1927}
1928
1929VALUE
1930rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
1931{
1932    int i, r;
1933    VALUE a, args = rb_ary_new2(iseq->arg_size);
1934    ID req, opt, rest, block, key, keyrest;
1935#define PARAM_TYPE(type) rb_ary_push(a = rb_ary_new2(2), ID2SYM(type))
1936#define PARAM_ID(i) iseq->local_table[(i)]
1937#define PARAM(i, type) (		      \
1938	PARAM_TYPE(type),		      \
1939	rb_id2str(PARAM_ID(i)) ?	      \
1940	rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \
1941	a)
1942
1943    CONST_ID(req, "req");
1944    CONST_ID(opt, "opt");
1945    if (is_proc) {
1946	for (i = 0; i < iseq->argc; i++) {
1947	    PARAM_TYPE(opt);
1948	    rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
1949	    rb_ary_push(args, a);
1950	}
1951    }
1952    else {
1953	for (i = 0; i < iseq->argc; i++) {
1954	    rb_ary_push(args, PARAM(i, req));
1955	}
1956    }
1957    r = iseq->argc + iseq->arg_opts - 1;
1958    for (; i < r; i++) {
1959	PARAM_TYPE(opt);
1960	if (rb_id2str(PARAM_ID(i))) {
1961	    rb_ary_push(a, ID2SYM(PARAM_ID(i)));
1962	}
1963	rb_ary_push(args, a);
1964    }
1965    if (iseq->arg_rest != -1) {
1966	CONST_ID(rest, "rest");
1967	rb_ary_push(args, PARAM(iseq->arg_rest, rest));
1968    }
1969    r = iseq->arg_post_start + iseq->arg_post_len;
1970    if (is_proc) {
1971	for (i = iseq->arg_post_start; i < r; i++) {
1972	    PARAM_TYPE(opt);
1973	    rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
1974	    rb_ary_push(args, a);
1975	}
1976    }
1977    else {
1978	for (i = iseq->arg_post_start; i < r; i++) {
1979	    rb_ary_push(args, PARAM(i, req));
1980	}
1981    }
1982    if (iseq->arg_keyword != -1) {
1983	CONST_ID(key, "key");
1984	for (i = 0; i < iseq->arg_keywords; i++) {
1985	    PARAM_TYPE(key);
1986	    if (rb_id2str(iseq->arg_keyword_table[i])) {
1987		rb_ary_push(a, ID2SYM(iseq->arg_keyword_table[i]));
1988	    }
1989	    rb_ary_push(args, a);
1990	}
1991	if (rb_id2str(iseq->local_table[iseq->arg_keyword])) {
1992	    CONST_ID(keyrest, "keyrest");
1993	    rb_ary_push(args, PARAM(iseq->arg_keyword, keyrest));
1994	}
1995    }
1996    if (iseq->arg_block != -1) {
1997	CONST_ID(block, "block");
1998	rb_ary_push(args, PARAM(iseq->arg_block, block));
1999    }
2000    return args;
2001}
2002
2003VALUE
2004rb_iseq_defined_string(enum defined_type type)
2005{
2006    static const char expr_names[][18] = {
2007	"nil",
2008	"instance-variable",
2009	"local-variable",
2010	"global-variable",
2011	"class variable",
2012	"constant",
2013	"method",
2014	"yield",
2015	"super",
2016	"self",
2017	"true",
2018	"false",
2019	"assignment",
2020	"expression",
2021    };
2022    const char *estr;
2023    VALUE *defs, str;
2024
2025    if ((unsigned)(type - 1) >= (unsigned)numberof(expr_names)) return 0;
2026    estr = expr_names[type - 1];
2027    if (!estr[0]) return 0;
2028    defs = GET_VM()->defined_strings;
2029    if (!defs) {
2030	defs = ruby_xcalloc(numberof(expr_names), sizeof(VALUE));
2031	GET_VM()->defined_strings = defs;
2032    }
2033    str = defs[type-1];
2034    if (!str) {
2035	str = rb_str_new_cstr(estr);;
2036	OBJ_FREEZE(str);
2037	defs[type-1] = str;
2038    }
2039    return str;
2040}
2041
2042/* ruby2cext */
2043
2044VALUE
2045rb_iseq_build_for_ruby2cext(
2046    const rb_iseq_t *iseq_template,
2047    const rb_insn_func_t *func,
2048    const struct iseq_line_info_entry *line_info_table,
2049    const char **local_table,
2050    const VALUE *arg_opt_table,
2051    const struct iseq_catch_table_entry *catch_table,
2052    const char *name,
2053    const char *path,
2054    const unsigned short first_lineno)
2055{
2056    unsigned long i;
2057    VALUE iseqval = iseq_alloc(rb_cISeq);
2058    rb_iseq_t *iseq;
2059    GetISeqPtr(iseqval, iseq);
2060
2061    /* copy iseq */
2062    *iseq = *iseq_template;
2063    iseq->location.label = rb_str_new2(name);
2064    iseq->location.path = rb_str_new2(path);
2065    iseq->location.first_lineno = first_lineno;
2066    iseq->mark_ary = 0;
2067    iseq->self = iseqval;
2068
2069    iseq->iseq = ALLOC_N(VALUE, iseq->iseq_size);
2070
2071    for (i=0; i<iseq->iseq_size; i+=2) {
2072	iseq->iseq[i] = BIN(opt_call_c_function);
2073	iseq->iseq[i+1] = (VALUE)func;
2074    }
2075
2076    rb_iseq_translate_threaded_code(iseq);
2077
2078#define ALLOC_AND_COPY(dst, src, type, size) do { \
2079  if (size) { \
2080      (dst) = ALLOC_N(type, (size)); \
2081      MEMCPY((dst), (src), type, (size)); \
2082  } \
2083} while (0)
2084
2085    ALLOC_AND_COPY(iseq->line_info_table, line_info_table,
2086		   struct iseq_line_info_entry, iseq->line_info_size);
2087
2088    ALLOC_AND_COPY(iseq->catch_table, catch_table,
2089		   struct iseq_catch_table_entry, iseq->catch_table_size);
2090
2091    ALLOC_AND_COPY(iseq->arg_opt_table, arg_opt_table,
2092		   VALUE, iseq->arg_opts);
2093
2094    set_relation(iseq, 0);
2095
2096    return iseqval;
2097}
2098
2099/* Experimental tracing support: trace(line) -> trace(specified_line)
2100 * MRI Specific.
2101 */
2102
2103int
2104rb_iseq_line_trace_each(VALUE iseqval, int (*func)(int line, rb_event_flag_t *events_ptr, void *d), void *data)
2105{
2106    int trace_num = 0;
2107    size_t pos, insn;
2108    rb_iseq_t *iseq;
2109    int cont = 1;
2110    GetISeqPtr(iseqval, iseq);
2111
2112    for (pos = 0; cont && pos < iseq->iseq_size; pos += insn_len(insn)) {
2113	insn = iseq->iseq[pos];
2114
2115	if (insn == BIN(trace)) {
2116	    rb_event_flag_t current_events = (VALUE)iseq->iseq[pos+1];
2117
2118	    if (current_events & RUBY_EVENT_LINE) {
2119		rb_event_flag_t events = current_events & RUBY_EVENT_SPECIFIED_LINE;
2120		trace_num++;
2121
2122		if (func) {
2123		    int line = find_line_no(iseq, pos);
2124		    /* printf("line: %d\n", line); */
2125		    cont = (*func)(line, &events, data);
2126		    if (current_events != events) {
2127			iseq->iseq[pos+1] = iseq->iseq_encoded[pos+1] =
2128			  (VALUE)(current_events | (events & RUBY_EVENT_SPECIFIED_LINE));
2129		    }
2130		}
2131	    }
2132	}
2133    }
2134    return trace_num;
2135}
2136
2137static int
2138collect_trace(int line, rb_event_flag_t *events_ptr, void *ptr)
2139{
2140    VALUE result = (VALUE)ptr;
2141    rb_ary_push(result, INT2NUM(line));
2142    return 1;
2143}
2144
2145/*
2146 * <b>Experimental MRI specific feature, only available as C level api.</b>
2147 *
2148 * Returns all +specified_line+ events.
2149 */
2150VALUE
2151rb_iseq_line_trace_all(VALUE iseqval)
2152{
2153    VALUE result = rb_ary_new();
2154    rb_iseq_line_trace_each(iseqval, collect_trace, (void *)result);
2155    return result;
2156}
2157
2158struct set_specifc_data {
2159    int pos;
2160    int set;
2161    int prev; /* 1: set, 2: unset, 0: not found */
2162};
2163
2164static int
2165line_trace_specify(int line, rb_event_flag_t *events_ptr, void *ptr)
2166{
2167    struct set_specifc_data *data = (struct set_specifc_data *)ptr;
2168
2169    if (data->pos == 0) {
2170	data->prev = *events_ptr & RUBY_EVENT_SPECIFIED_LINE ? 1 : 2;
2171	if (data->set) {
2172	    *events_ptr = *events_ptr | RUBY_EVENT_SPECIFIED_LINE;
2173	}
2174	else {
2175	    *events_ptr = *events_ptr & ~RUBY_EVENT_SPECIFIED_LINE;
2176	}
2177	return 0; /* found */
2178    }
2179    else {
2180	data->pos--;
2181	return 1;
2182    }
2183}
2184
2185/*
2186 * <b>Experimental MRI specific feature, only available as C level api.</b>
2187 *
2188 * Set a +specified_line+ event at the given line position, if the +set+
2189 * parameter is +true+.
2190 *
2191 * This method is useful for building a debugger breakpoint at a specific line.
2192 *
2193 * A TypeError is raised if +set+ is not boolean.
2194 *
2195 * If +pos+ is a negative integer a TypeError exception is raised.
2196 */
2197VALUE
2198rb_iseq_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set)
2199{
2200    struct set_specifc_data data;
2201
2202    data.prev = 0;
2203    data.pos = NUM2INT(pos);
2204    if (data.pos < 0) rb_raise(rb_eTypeError, "`pos' is negative");
2205
2206    switch (set) {
2207      case Qtrue:  data.set = 1; break;
2208      case Qfalse: data.set = 0; break;
2209      default:
2210	rb_raise(rb_eTypeError, "`set' should be true/false");
2211    }
2212
2213    rb_iseq_line_trace_each(iseqval, line_trace_specify, (void *)&data);
2214
2215    if (data.prev == 0) {
2216	rb_raise(rb_eTypeError, "`pos' is out of range.");
2217    }
2218    return data.prev == 1 ? Qtrue : Qfalse;
2219}
2220
2221/*
2222 *  Document-class: RubyVM::InstructionSequence
2223 *
2224 *  The InstructionSequence class represents a compiled sequence of
2225 *  instructions for the Ruby Virtual Machine.
2226 *
2227 *  With it, you can get a handle to the instructions that make up a method or
2228 *  a proc, compile strings of Ruby code down to VM instructions, and
2229 *  disassemble instruction sequences to strings for easy inspection. It is
2230 *  mostly useful if you want to learn how the Ruby VM works, but it also lets
2231 *  you control various settings for the Ruby iseq compiler.
2232 *
2233 *  You can find the source for the VM instructions in +insns.def+ in the Ruby
2234 *  source.
2235 *
2236 *  The instruction sequence results will almost certainly change as Ruby
2237 *  changes, so example output in this documentation may be different from what
2238 *  you see.
2239 */
2240
2241void
2242Init_ISeq(void)
2243{
2244    /* declare ::RubyVM::InstructionSequence */
2245    rb_cISeq = rb_define_class_under(rb_cRubyVM, "InstructionSequence", rb_cObject);
2246    rb_define_alloc_func(rb_cISeq, iseq_alloc);
2247    rb_define_method(rb_cISeq, "inspect", iseq_inspect, 0);
2248    rb_define_method(rb_cISeq, "disasm", rb_iseq_disasm, 0);
2249    rb_define_method(rb_cISeq, "disassemble", rb_iseq_disasm, 0);
2250    rb_define_method(rb_cISeq, "to_a", iseq_to_a, 0);
2251    rb_define_method(rb_cISeq, "eval", iseq_eval, 0);
2252
2253    /* location APIs */
2254    rb_define_method(rb_cISeq, "path", iseq_path, 0);
2255    rb_define_method(rb_cISeq, "absolute_path", iseq_absolute_path, 0);
2256    rb_define_method(rb_cISeq, "label", iseq_label, 0);
2257    rb_define_method(rb_cISeq, "base_label", iseq_base_label, 0);
2258    rb_define_method(rb_cISeq, "first_lineno", iseq_first_lineno, 0);
2259
2260#if 0
2261    /* Now, it is experimental. No discussions, no tests. */
2262    /* They can be used from C level. Please give us feedback. */
2263    rb_define_method(rb_cISeq, "line_trace_all", rb_iseq_line_trace_all, 0);
2264    rb_define_method(rb_cISeq, "line_trace_specify", rb_iseq_line_trace_specify, 2);
2265#else
2266    (void)rb_iseq_line_trace_all;
2267    (void)rb_iseq_line_trace_specify;
2268#endif
2269
2270#if 0 /* TBD */
2271    rb_define_private_method(rb_cISeq, "marshal_dump", iseq_marshal_dump, 0);
2272    rb_define_private_method(rb_cISeq, "marshal_load", iseq_marshal_load, 1);
2273#endif
2274
2275    /* disable this feature because there is no verifier. */
2276    /* rb_define_singleton_method(rb_cISeq, "load", iseq_s_load, -1); */
2277    (void)iseq_s_load;
2278
2279    rb_define_singleton_method(rb_cISeq, "compile", iseq_s_compile, -1);
2280    rb_define_singleton_method(rb_cISeq, "new", iseq_s_compile, -1);
2281    rb_define_singleton_method(rb_cISeq, "compile_file", iseq_s_compile_file, -1);
2282    rb_define_singleton_method(rb_cISeq, "compile_option", iseq_s_compile_option_get, 0);
2283    rb_define_singleton_method(rb_cISeq, "compile_option=", iseq_s_compile_option_set, 1);
2284    rb_define_singleton_method(rb_cISeq, "disasm", iseq_s_disasm, 1);
2285    rb_define_singleton_method(rb_cISeq, "disassemble", iseq_s_disasm, 1);
2286    rb_define_singleton_method(rb_cISeq, "of", iseq_s_of, 1);
2287}
2288