00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "ruby/ruby.h"
00013 #include "internal.h"
00014 #include "eval_intern.h"
00015
00016
00017 #include "gc.h"
00018 #include "vm_core.h"
00019 #include "iseq.h"
00020
00021 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00022
00023 #include "insns.inc"
00024 #include "insns_info.inc"
00025
00026 #define ISEQ_MAJOR_VERSION 2
00027 #define ISEQ_MINOR_VERSION 0
00028
00029 VALUE rb_cISeq;
00030
00031 #define hidden_obj_p(obj) (!SPECIAL_CONST_P(obj) && !RBASIC(obj)->klass)
00032
00033 static inline VALUE
00034 obj_resurrect(VALUE obj)
00035 {
00036 if (hidden_obj_p(obj)) {
00037 switch (BUILTIN_TYPE(obj)) {
00038 case T_STRING:
00039 obj = rb_str_resurrect(obj);
00040 break;
00041 case T_ARRAY:
00042 obj = rb_ary_resurrect(obj);
00043 break;
00044 }
00045 }
00046 return obj;
00047 }
00048
00049 static void
00050 compile_data_free(struct iseq_compile_data *compile_data)
00051 {
00052 if (compile_data) {
00053 struct iseq_compile_data_storage *cur, *next;
00054 cur = compile_data->storage_head;
00055 while (cur) {
00056 next = cur->next;
00057 ruby_xfree(cur);
00058 cur = next;
00059 }
00060 ruby_xfree(compile_data);
00061 }
00062 }
00063
00064 static void
00065 iseq_free(void *ptr)
00066 {
00067 rb_iseq_t *iseq;
00068 RUBY_FREE_ENTER("iseq");
00069
00070 if (ptr) {
00071 iseq = ptr;
00072 if (!iseq->orig) {
00073
00074 if (0) {
00075 RUBY_GC_INFO("%s @ %s\n", RSTRING_PTR(iseq->location.label),
00076 RSTRING_PTR(iseq->location.path));
00077 }
00078
00079 if (iseq->iseq != iseq->iseq_encoded) {
00080 RUBY_FREE_UNLESS_NULL(iseq->iseq_encoded);
00081 }
00082
00083 RUBY_FREE_UNLESS_NULL(iseq->iseq);
00084 RUBY_FREE_UNLESS_NULL(iseq->line_info_table);
00085 RUBY_FREE_UNLESS_NULL(iseq->local_table);
00086 RUBY_FREE_UNLESS_NULL(iseq->ic_entries);
00087 RUBY_FREE_UNLESS_NULL(iseq->callinfo_entries);
00088 RUBY_FREE_UNLESS_NULL(iseq->catch_table);
00089 RUBY_FREE_UNLESS_NULL(iseq->arg_opt_table);
00090 RUBY_FREE_UNLESS_NULL(iseq->arg_keyword_table);
00091 compile_data_free(iseq->compile_data);
00092 }
00093 ruby_xfree(ptr);
00094 }
00095 RUBY_FREE_LEAVE("iseq");
00096 }
00097
00098 static void
00099 iseq_mark(void *ptr)
00100 {
00101 RUBY_MARK_ENTER("iseq");
00102
00103 if (ptr) {
00104 rb_iseq_t *iseq = ptr;
00105
00106 RUBY_GC_INFO("%s @ %s\n", RSTRING_PTR(iseq->location.label), RSTRING_PTR(iseq->location.path));
00107 RUBY_MARK_UNLESS_NULL(iseq->mark_ary);
00108
00109 RUBY_MARK_UNLESS_NULL(iseq->location.label);
00110 RUBY_MARK_UNLESS_NULL(iseq->location.base_label);
00111 RUBY_MARK_UNLESS_NULL(iseq->location.path);
00112 RUBY_MARK_UNLESS_NULL(iseq->location.absolute_path);
00113
00114 RUBY_MARK_UNLESS_NULL((VALUE)iseq->cref_stack);
00115 RUBY_MARK_UNLESS_NULL(iseq->klass);
00116 RUBY_MARK_UNLESS_NULL(iseq->coverage);
00117 #if 0
00118 RUBY_MARK_UNLESS_NULL((VALUE)iseq->node);
00119 RUBY_MARK_UNLESS_NULL(iseq->cached_special_block);
00120 #endif
00121 RUBY_MARK_UNLESS_NULL(iseq->orig);
00122
00123 if (iseq->compile_data != 0) {
00124 struct iseq_compile_data *const compile_data = iseq->compile_data;
00125 RUBY_MARK_UNLESS_NULL(compile_data->mark_ary);
00126 RUBY_MARK_UNLESS_NULL(compile_data->err_info);
00127 RUBY_MARK_UNLESS_NULL(compile_data->catch_table_ary);
00128 }
00129 }
00130 RUBY_MARK_LEAVE("iseq");
00131 }
00132
00133 static size_t
00134 iseq_memsize(const void *ptr)
00135 {
00136 size_t size = sizeof(rb_iseq_t);
00137 const rb_iseq_t *iseq;
00138
00139 if (ptr) {
00140 iseq = ptr;
00141 if (!iseq->orig) {
00142 if (iseq->iseq != iseq->iseq_encoded) {
00143 size += iseq->iseq_size * sizeof(VALUE);
00144 }
00145
00146 size += iseq->iseq_size * sizeof(VALUE);
00147 size += iseq->line_info_size * sizeof(struct iseq_line_info_entry);
00148 size += iseq->local_table_size * sizeof(ID);
00149 size += iseq->catch_table_size * sizeof(struct iseq_catch_table_entry);
00150 size += iseq->arg_opts * sizeof(VALUE);
00151 size += iseq->ic_size * sizeof(struct iseq_inline_cache_entry);
00152 size += iseq->callinfo_size * sizeof(rb_call_info_t);
00153
00154 if (iseq->compile_data) {
00155 struct iseq_compile_data_storage *cur;
00156
00157 cur = iseq->compile_data->storage_head;
00158 while (cur) {
00159 size += cur->size + sizeof(struct iseq_compile_data_storage);
00160 cur = cur->next;
00161 }
00162 size += sizeof(struct iseq_compile_data);
00163 }
00164 }
00165 }
00166
00167 return size;
00168 }
00169
00170 static const rb_data_type_t iseq_data_type = {
00171 "iseq",
00172 {
00173 iseq_mark,
00174 iseq_free,
00175 iseq_memsize,
00176 },
00177 };
00178
00179 static VALUE
00180 iseq_alloc(VALUE klass)
00181 {
00182 rb_iseq_t *iseq;
00183 return TypedData_Make_Struct(klass, rb_iseq_t, &iseq_data_type, iseq);
00184 }
00185
00186 static rb_iseq_location_t *
00187 iseq_location_setup(rb_iseq_t *iseq, VALUE path, VALUE absolute_path, VALUE name, size_t first_lineno)
00188 {
00189 rb_iseq_location_t *loc = &iseq->location;
00190 loc->path = path;
00191 if (RTEST(absolute_path) && rb_str_cmp(path, absolute_path) == 0)
00192 loc->absolute_path = path;
00193 else
00194 loc->absolute_path = absolute_path;
00195 loc->label = loc->base_label = name;
00196 loc->first_lineno = first_lineno;
00197 return loc;
00198 }
00199
00200 static void
00201 set_relation(rb_iseq_t *iseq, const VALUE parent)
00202 {
00203 const VALUE type = iseq->type;
00204 rb_thread_t *th = GET_THREAD();
00205 rb_iseq_t *piseq;
00206
00207
00208 if (type == ISEQ_TYPE_TOP) {
00209
00210 iseq->cref_stack = NEW_CREF(rb_cObject);
00211 iseq->cref_stack->nd_refinements = Qnil;
00212 iseq->cref_stack->nd_visi = NOEX_PRIVATE;
00213 if (th->top_wrapper) {
00214 NODE *cref = NEW_CREF(th->top_wrapper);
00215 cref->nd_refinements = Qnil;
00216 cref->nd_visi = NOEX_PRIVATE;
00217 cref->nd_next = iseq->cref_stack;
00218 iseq->cref_stack = cref;
00219 }
00220 iseq->local_iseq = iseq;
00221 }
00222 else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
00223 iseq->cref_stack = NEW_CREF(0);
00224 iseq->cref_stack->nd_refinements = Qnil;
00225 iseq->local_iseq = iseq;
00226 }
00227 else if (RTEST(parent)) {
00228 GetISeqPtr(parent, piseq);
00229 iseq->cref_stack = piseq->cref_stack;
00230 iseq->local_iseq = piseq->local_iseq;
00231 }
00232
00233 if (RTEST(parent)) {
00234 GetISeqPtr(parent, piseq);
00235 iseq->parent_iseq = piseq;
00236 }
00237
00238 if (type == ISEQ_TYPE_MAIN) {
00239 iseq->local_iseq = iseq;
00240 }
00241 }
00242
00243 void
00244 rb_iseq_add_mark_object(rb_iseq_t *iseq, VALUE obj)
00245 {
00246 if (!RTEST(iseq->mark_ary)) {
00247 iseq->mark_ary = rb_ary_tmp_new(3);
00248 OBJ_UNTRUST(iseq->mark_ary);
00249 RBASIC(iseq->mark_ary)->klass = 0;
00250 }
00251 rb_ary_push(iseq->mark_ary, obj);
00252 }
00253
00254 static VALUE
00255 prepare_iseq_build(rb_iseq_t *iseq,
00256 VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno,
00257 VALUE parent, enum iseq_type type, VALUE block_opt,
00258 const rb_compile_option_t *option)
00259 {
00260 iseq->type = type;
00261 iseq->arg_rest = -1;
00262 iseq->arg_block = -1;
00263 iseq->arg_keyword = -1;
00264 iseq->klass = 0;
00265 set_relation(iseq, parent);
00266
00267 OBJ_FREEZE(name);
00268 OBJ_FREEZE(path);
00269
00270 iseq_location_setup(iseq, path, absolute_path, name, first_lineno);
00271 if (iseq != iseq->local_iseq) {
00272 iseq->location.base_label = iseq->local_iseq->location.label;
00273 }
00274
00275 iseq->defined_method_id = 0;
00276 iseq->mark_ary = 0;
00277
00278
00279
00280
00281
00282
00283
00284
00285 iseq->compile_data = ALLOC(struct iseq_compile_data);
00286 MEMZERO(iseq->compile_data, struct iseq_compile_data, 1);
00287 iseq->compile_data->err_info = Qnil;
00288 iseq->compile_data->mark_ary = rb_ary_tmp_new(3);
00289
00290 iseq->compile_data->storage_head = iseq->compile_data->storage_current =
00291 (struct iseq_compile_data_storage *)
00292 ALLOC_N(char, INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE +
00293 sizeof(struct iseq_compile_data_storage));
00294
00295 iseq->compile_data->catch_table_ary = rb_ary_new();
00296 iseq->compile_data->storage_head->pos = 0;
00297 iseq->compile_data->storage_head->next = 0;
00298 iseq->compile_data->storage_head->size =
00299 INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE;
00300 iseq->compile_data->storage_head->buff =
00301 (char *)(&iseq->compile_data->storage_head->buff + 1);
00302 iseq->compile_data->option = option;
00303 iseq->compile_data->last_coverable_line = -1;
00304
00305 iseq->coverage = Qfalse;
00306 if (!GET_THREAD()->parse_in_eval) {
00307 VALUE coverages = rb_get_coverages();
00308 if (RTEST(coverages)) {
00309 iseq->coverage = rb_hash_lookup(coverages, path);
00310 if (NIL_P(iseq->coverage)) iseq->coverage = Qfalse;
00311 }
00312 }
00313
00314 return Qtrue;
00315 }
00316
00317 static VALUE
00318 cleanup_iseq_build(rb_iseq_t *iseq)
00319 {
00320 struct iseq_compile_data *data = iseq->compile_data;
00321 VALUE err = data->err_info;
00322 iseq->compile_data = 0;
00323 compile_data_free(data);
00324
00325 if (RTEST(err)) {
00326 rb_funcall2(err, rb_intern("set_backtrace"), 1, &iseq->location.path);
00327 rb_exc_raise(err);
00328 }
00329 return Qtrue;
00330 }
00331
00332 static rb_compile_option_t COMPILE_OPTION_DEFAULT = {
00333 OPT_INLINE_CONST_CACHE,
00334 OPT_PEEPHOLE_OPTIMIZATION,
00335 OPT_TAILCALL_OPTIMIZATION,
00336 OPT_SPECIALISED_INSTRUCTION,
00337 OPT_OPERANDS_UNIFICATION,
00338 OPT_INSTRUCTIONS_UNIFICATION,
00339 OPT_STACK_CACHING,
00340 OPT_TRACE_INSTRUCTION,
00341 };
00342 static const rb_compile_option_t COMPILE_OPTION_FALSE = {0};
00343
00344 static void
00345 make_compile_option(rb_compile_option_t *option, VALUE opt)
00346 {
00347 if (opt == Qnil) {
00348 *option = COMPILE_OPTION_DEFAULT;
00349 }
00350 else if (opt == Qfalse) {
00351 *option = COMPILE_OPTION_FALSE;
00352 }
00353 else if (opt == Qtrue) {
00354 memset(option, 1, sizeof(rb_compile_option_t));
00355 }
00356 else if (CLASS_OF(opt) == rb_cHash) {
00357 *option = COMPILE_OPTION_DEFAULT;
00358
00359 #define SET_COMPILE_OPTION(o, h, mem) \
00360 { VALUE flag = rb_hash_aref((h), ID2SYM(rb_intern(#mem))); \
00361 if (flag == Qtrue) { (o)->mem = 1; } \
00362 else if (flag == Qfalse) { (o)->mem = 0; } \
00363 }
00364 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
00365 { VALUE num = rb_hash_aref(opt, ID2SYM(rb_intern(#mem))); \
00366 if (!NIL_P(num)) (o)->mem = NUM2INT(num); \
00367 }
00368 SET_COMPILE_OPTION(option, opt, inline_const_cache);
00369 SET_COMPILE_OPTION(option, opt, peephole_optimization);
00370 SET_COMPILE_OPTION(option, opt, tailcall_optimization);
00371 SET_COMPILE_OPTION(option, opt, specialized_instruction);
00372 SET_COMPILE_OPTION(option, opt, operands_unification);
00373 SET_COMPILE_OPTION(option, opt, instructions_unification);
00374 SET_COMPILE_OPTION(option, opt, stack_caching);
00375 SET_COMPILE_OPTION(option, opt, trace_instruction);
00376 SET_COMPILE_OPTION_NUM(option, opt, debug_level);
00377 #undef SET_COMPILE_OPTION
00378 #undef SET_COMPILE_OPTION_NUM
00379 }
00380 else {
00381 rb_raise(rb_eTypeError, "Compile option must be Hash/true/false/nil");
00382 }
00383 }
00384
00385 static VALUE
00386 make_compile_option_value(rb_compile_option_t *option)
00387 {
00388 VALUE opt = rb_hash_new();
00389 #define SET_COMPILE_OPTION(o, h, mem) \
00390 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), (o)->mem ? Qtrue : Qfalse)
00391 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
00392 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), INT2NUM((o)->mem))
00393 {
00394 SET_COMPILE_OPTION(option, opt, inline_const_cache);
00395 SET_COMPILE_OPTION(option, opt, peephole_optimization);
00396 SET_COMPILE_OPTION(option, opt, tailcall_optimization);
00397 SET_COMPILE_OPTION(option, opt, specialized_instruction);
00398 SET_COMPILE_OPTION(option, opt, operands_unification);
00399 SET_COMPILE_OPTION(option, opt, instructions_unification);
00400 SET_COMPILE_OPTION(option, opt, stack_caching);
00401 SET_COMPILE_OPTION(option, opt, trace_instruction);
00402 SET_COMPILE_OPTION_NUM(option, opt, debug_level);
00403 }
00404 #undef SET_COMPILE_OPTION
00405 #undef SET_COMPILE_OPTION_NUM
00406 return opt;
00407 }
00408
00409 VALUE
00410 rb_iseq_new(NODE *node, VALUE name, VALUE path, VALUE absolute_path,
00411 VALUE parent, enum iseq_type type)
00412 {
00413 return rb_iseq_new_with_opt(node, name, path, absolute_path, INT2FIX(0), parent, type,
00414 &COMPILE_OPTION_DEFAULT);
00415 }
00416
00417 VALUE
00418 rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE parent)
00419 {
00420 return rb_iseq_new_with_opt(node, name, path, absolute_path, INT2FIX(0), parent, ISEQ_TYPE_TOP,
00421 &COMPILE_OPTION_DEFAULT);
00422 }
00423
00424 VALUE
00425 rb_iseq_new_main(NODE *node, VALUE path, VALUE absolute_path)
00426 {
00427 rb_thread_t *th = GET_THREAD();
00428 VALUE parent = th->base_block->iseq->self;
00429 return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), path, absolute_path, INT2FIX(0),
00430 parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
00431 }
00432
00433 static VALUE
00434 rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno,
00435 VALUE parent, enum iseq_type type, VALUE bopt,
00436 const rb_compile_option_t *option)
00437 {
00438 rb_iseq_t *iseq;
00439 VALUE self = iseq_alloc(rb_cISeq);
00440
00441 GetISeqPtr(self, iseq);
00442 iseq->self = self;
00443
00444 prepare_iseq_build(iseq, name, path, absolute_path, first_lineno, parent, type, bopt, option);
00445 rb_iseq_compile_node(self, node);
00446 cleanup_iseq_build(iseq);
00447 return self;
00448 }
00449
00450 VALUE
00451 rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno,
00452 VALUE parent, enum iseq_type type,
00453 const rb_compile_option_t *option)
00454 {
00455
00456 return rb_iseq_new_with_bopt_and_opt(node, name, path, absolute_path, first_lineno, parent, type,
00457 Qfalse, option);
00458 }
00459
00460 VALUE
00461 rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno,
00462 VALUE parent, enum iseq_type type, VALUE bopt)
00463 {
00464
00465 return rb_iseq_new_with_bopt_and_opt(node, name, path, absolute_path, first_lineno, parent, type,
00466 bopt, &COMPILE_OPTION_DEFAULT);
00467 }
00468
00469 #define CHECK_ARRAY(v) rb_convert_type((v), T_ARRAY, "Array", "to_ary")
00470 #define CHECK_STRING(v) rb_convert_type((v), T_STRING, "String", "to_str")
00471 #define CHECK_SYMBOL(v) rb_convert_type((v), T_SYMBOL, "Symbol", "to_sym")
00472 static inline VALUE CHECK_INTEGER(VALUE v) {(void)NUM2LONG(v); return v;}
00473 static VALUE
00474 iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
00475 {
00476 VALUE iseqval = iseq_alloc(self);
00477
00478 VALUE magic, version1, version2, format_type, misc;
00479 VALUE name, path, absolute_path, first_lineno;
00480 VALUE type, body, locals, args, exception;
00481
00482 st_data_t iseq_type;
00483 static struct st_table *type_map_cache = 0;
00484 struct st_table *type_map = 0;
00485 rb_iseq_t *iseq;
00486 rb_compile_option_t option;
00487 int i = 0;
00488
00489
00490
00491
00492
00493
00494 data = CHECK_ARRAY(data);
00495
00496 magic = CHECK_STRING(rb_ary_entry(data, i++));
00497 version1 = CHECK_INTEGER(rb_ary_entry(data, i++));
00498 version2 = CHECK_INTEGER(rb_ary_entry(data, i++));
00499 format_type = CHECK_INTEGER(rb_ary_entry(data, i++));
00500 misc = rb_ary_entry(data, i++);
00501 ((void)magic, (void)version1, (void)version2, (void)format_type, (void)misc);
00502
00503 name = CHECK_STRING(rb_ary_entry(data, i++));
00504 path = CHECK_STRING(rb_ary_entry(data, i++));
00505 absolute_path = rb_ary_entry(data, i++);
00506 absolute_path = NIL_P(absolute_path) ? Qnil : CHECK_STRING(absolute_path);
00507 first_lineno = CHECK_INTEGER(rb_ary_entry(data, i++));
00508
00509 type = CHECK_SYMBOL(rb_ary_entry(data, i++));
00510 locals = CHECK_ARRAY(rb_ary_entry(data, i++));
00511
00512 args = rb_ary_entry(data, i++);
00513 if (FIXNUM_P(args) || (args = CHECK_ARRAY(args))) {
00514
00515 }
00516
00517 exception = CHECK_ARRAY(rb_ary_entry(data, i++));
00518 body = CHECK_ARRAY(rb_ary_entry(data, i++));
00519
00520 GetISeqPtr(iseqval, iseq);
00521 iseq->self = iseqval;
00522
00523 type_map = type_map_cache;
00524 if (type_map == 0) {
00525 struct st_table *cached_map;
00526 type_map = st_init_numtable();
00527 st_insert(type_map, ID2SYM(rb_intern("top")), ISEQ_TYPE_TOP);
00528 st_insert(type_map, ID2SYM(rb_intern("method")), ISEQ_TYPE_METHOD);
00529 st_insert(type_map, ID2SYM(rb_intern("block")), ISEQ_TYPE_BLOCK);
00530 st_insert(type_map, ID2SYM(rb_intern("class")), ISEQ_TYPE_CLASS);
00531 st_insert(type_map, ID2SYM(rb_intern("rescue")), ISEQ_TYPE_RESCUE);
00532 st_insert(type_map, ID2SYM(rb_intern("ensure")), ISEQ_TYPE_ENSURE);
00533 st_insert(type_map, ID2SYM(rb_intern("eval")), ISEQ_TYPE_EVAL);
00534 st_insert(type_map, ID2SYM(rb_intern("main")), ISEQ_TYPE_MAIN);
00535 st_insert(type_map, ID2SYM(rb_intern("defined_guard")), ISEQ_TYPE_DEFINED_GUARD);
00536 cached_map = ATOMIC_PTR_CAS(type_map_cache, (struct st_table *)0, type_map);
00537 if (cached_map) {
00538 st_free_table(type_map);
00539 type_map = cached_map;
00540 }
00541 }
00542
00543 if (st_lookup(type_map, type, &iseq_type) == 0) {
00544 ID typeid = SYM2ID(type);
00545 VALUE typename = rb_id2str(typeid);
00546 if (typename)
00547 rb_raise(rb_eTypeError, "unsupport type: :%"PRIsVALUE, typename);
00548 else
00549 rb_raise(rb_eTypeError, "unsupport type: %p", (void *)typeid);
00550 }
00551
00552 if (parent == Qnil) {
00553 parent = 0;
00554 }
00555
00556 make_compile_option(&option, opt);
00557 prepare_iseq_build(iseq, name, path, absolute_path, first_lineno,
00558 parent, (enum iseq_type)iseq_type, 0, &option);
00559
00560 rb_iseq_build_from_ary(iseq, locals, args, exception, body);
00561
00562 cleanup_iseq_build(iseq);
00563 return iseqval;
00564 }
00565
00566
00567
00568
00569 static VALUE
00570 iseq_s_load(int argc, VALUE *argv, VALUE self)
00571 {
00572 VALUE data, opt=Qnil;
00573 rb_scan_args(argc, argv, "11", &data, &opt);
00574
00575 return iseq_load(self, data, 0, opt);
00576 }
00577
00578 VALUE
00579 rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
00580 {
00581 return iseq_load(rb_cISeq, data, parent, opt);
00582 }
00583
00584 VALUE
00585 rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, rb_block_t *base_block, VALUE opt)
00586 {
00587 int state;
00588 rb_thread_t *th = GET_THREAD();
00589 rb_block_t *prev_base_block = th->base_block;
00590 VALUE iseqval = Qundef;
00591
00592 th->base_block = base_block;
00593
00594 TH_PUSH_TAG(th);
00595 if ((state = EXEC_TAG()) == 0) {
00596 VALUE parser;
00597 int ln = NUM2INT(line);
00598 NODE *node;
00599 rb_compile_option_t option;
00600
00601 StringValueCStr(file);
00602 make_compile_option(&option, opt);
00603
00604 parser = rb_parser_new();
00605
00606 if (RB_TYPE_P((src), T_FILE))
00607 node = rb_parser_compile_file_path(parser, file, src, ln);
00608 else {
00609 node = rb_parser_compile_string_path(parser, file, src, ln);
00610
00611 if (!node) {
00612 rb_exc_raise(GET_THREAD()->errinfo);
00613 }
00614 }
00615
00616 if (base_block && base_block->iseq) {
00617 iseqval = rb_iseq_new_with_opt(node, base_block->iseq->location.label,
00618 file, absolute_path, line, base_block->iseq->self,
00619 ISEQ_TYPE_EVAL, &option);
00620 }
00621 else {
00622 iseqval = rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, absolute_path, line, Qfalse,
00623 ISEQ_TYPE_TOP, &option);
00624 }
00625 }
00626 TH_POP_TAG();
00627
00628 th->base_block = prev_base_block;
00629
00630 if (state) {
00631 JUMP_TAG(state);
00632 }
00633
00634 return iseqval;
00635 }
00636
00637 VALUE
00638 rb_iseq_compile(VALUE src, VALUE file, VALUE line)
00639 {
00640 return rb_iseq_compile_with_option(src, file, Qnil, line, 0, Qnil);
00641 }
00642
00643 VALUE
00644 rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, rb_block_t *base_block)
00645 {
00646 return rb_iseq_compile_with_option(src, file, Qnil, line, base_block, Qnil);
00647 }
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 static VALUE
00671 iseq_s_compile(int argc, VALUE *argv, VALUE self)
00672 {
00673 VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;
00674
00675 rb_secure(1);
00676
00677 rb_scan_args(argc, argv, "14", &src, &file, &path, &line, &opt);
00678 if (NIL_P(file)) file = rb_str_new2("<compiled>");
00679 if (NIL_P(line)) line = INT2FIX(1);
00680
00681 return rb_iseq_compile_with_option(src, file, path, line, 0, opt);
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704 static VALUE
00705 iseq_s_compile_file(int argc, VALUE *argv, VALUE self)
00706 {
00707 VALUE file, line = INT2FIX(1), opt = Qnil;
00708 VALUE parser;
00709 VALUE f;
00710 NODE *node;
00711 const char *fname;
00712 rb_compile_option_t option;
00713
00714 rb_secure(1);
00715 rb_scan_args(argc, argv, "11", &file, &opt);
00716 FilePathValue(file);
00717 fname = StringValueCStr(file);
00718
00719 f = rb_file_open_str(file, "r");
00720
00721 parser = rb_parser_new();
00722 node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));
00723 make_compile_option(&option, opt);
00724 return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file,
00725 rb_realpath_internal(Qnil, file, 1), line, Qfalse,
00726 ISEQ_TYPE_TOP, &option);
00727 }
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 static VALUE
00762 iseq_s_compile_option_set(VALUE self, VALUE opt)
00763 {
00764 rb_compile_option_t option;
00765 rb_secure(1);
00766 make_compile_option(&option, opt);
00767 COMPILE_OPTION_DEFAULT = option;
00768 return opt;
00769 }
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779 static VALUE
00780 iseq_s_compile_option_get(VALUE self)
00781 {
00782 return make_compile_option_value(&COMPILE_OPTION_DEFAULT);
00783 }
00784
00785 static rb_iseq_t *
00786 iseq_check(VALUE val)
00787 {
00788 rb_iseq_t *iseq;
00789 GetISeqPtr(val, iseq);
00790 if (!iseq->location.label) {
00791 rb_raise(rb_eTypeError, "uninitialized InstructionSequence");
00792 }
00793 return iseq;
00794 }
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804 static VALUE
00805 iseq_eval(VALUE self)
00806 {
00807 rb_secure(1);
00808 return rb_iseq_eval(self);
00809 }
00810
00811
00812
00813
00814
00815 static VALUE
00816 iseq_inspect(VALUE self)
00817 {
00818 rb_iseq_t *iseq;
00819 GetISeqPtr(self, iseq);
00820 if (!iseq->location.label) {
00821 return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self));
00822 }
00823
00824 return rb_sprintf("<%s:%s@%s>",
00825 rb_obj_classname(self),
00826 RSTRING_PTR(iseq->location.label), RSTRING_PTR(iseq->location.path));
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852 static VALUE
00853 iseq_path(VALUE self)
00854 {
00855 rb_iseq_t *iseq;
00856 GetISeqPtr(self, iseq);
00857 return iseq->location.path;
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 static VALUE
00877 iseq_absolute_path(VALUE self)
00878 {
00879 rb_iseq_t *iseq;
00880 GetISeqPtr(self, iseq);
00881 return iseq->location.absolute_path;
00882 }
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 static VALUE
00908 iseq_label(VALUE self)
00909 {
00910 rb_iseq_t *iseq;
00911 GetISeqPtr(self, iseq);
00912 return iseq->location.label;
00913 }
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935 static VALUE
00936 iseq_base_label(VALUE self)
00937 {
00938 rb_iseq_t *iseq;
00939 GetISeqPtr(self, iseq);
00940 return iseq->location.base_label;
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953 static VALUE
00954 iseq_first_lineno(VALUE self)
00955 {
00956 rb_iseq_t *iseq;
00957 GetISeqPtr(self, iseq);
00958 return iseq->location.first_lineno;
00959 }
00960
00961 static
00962 VALUE iseq_data_to_ary(rb_iseq_t *iseq);
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049 static VALUE
01050 iseq_to_a(VALUE self)
01051 {
01052 rb_iseq_t *iseq = iseq_check(self);
01053 rb_secure(1);
01054 return iseq_data_to_ary(iseq);
01055 }
01056
01057 int
01058 rb_iseq_first_lineno(const rb_iseq_t *iseq)
01059 {
01060 return FIX2INT(iseq->location.first_lineno);
01061 }
01062
01063
01064
01065
01066 static struct iseq_line_info_entry *
01067 get_line_info(const rb_iseq_t *iseq, size_t pos)
01068 {
01069 size_t i = 0, size = iseq->line_info_size;
01070 struct iseq_line_info_entry *table = iseq->line_info_table;
01071 const int debug = 0;
01072
01073 if (debug) {
01074 printf("size: %"PRIdSIZE"\n", size);
01075 printf("table[%"PRIdSIZE"]: position: %d, line: %d, pos: %"PRIdSIZE"\n",
01076 i, table[i].position, table[i].line_no, pos);
01077 }
01078
01079 if (size == 0) {
01080 return 0;
01081 }
01082 else if (size == 1) {
01083 return &table[0];
01084 }
01085 else {
01086 for (i=1; i<size; i++) {
01087 if (debug) printf("table[%"PRIdSIZE"]: position: %d, line: %d, pos: %"PRIdSIZE"\n",
01088 i, table[i].position, table[i].line_no, pos);
01089
01090 if (table[i].position == pos) {
01091 return &table[i];
01092 }
01093 if (table[i].position > pos) {
01094 return &table[i-1];
01095 }
01096 }
01097 }
01098 return &table[i-1];
01099 }
01100
01101 static unsigned int
01102 find_line_no(const rb_iseq_t *iseq, size_t pos)
01103 {
01104 struct iseq_line_info_entry *entry = get_line_info(iseq, pos);
01105 if (entry) {
01106 return entry->line_no;
01107 }
01108 else {
01109 return 0;
01110 }
01111 }
01112
01113 unsigned int
01114 rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
01115 {
01116 if (pos == 0) {
01117 return find_line_no(iseq, pos);
01118 }
01119 else {
01120 return find_line_no(iseq, pos - 1);
01121 }
01122 }
01123
01124 static VALUE
01125 id_to_name(ID id, VALUE default_value)
01126 {
01127 VALUE str = rb_id2str(id);
01128 if (!str) {
01129 str = default_value;
01130 }
01131 else if (!rb_str_symname_p(str)) {
01132 str = rb_str_inspect(str);
01133 }
01134 return str;
01135 }
01136
01137 VALUE
01138 insn_operand_intern(rb_iseq_t *iseq,
01139 VALUE insn, int op_no, VALUE op,
01140 int len, size_t pos, VALUE *pnop, VALUE child)
01141 {
01142 const char *types = insn_op_types(insn);
01143 char type = types[op_no];
01144 VALUE ret;
01145
01146 switch (type) {
01147 case TS_OFFSET:
01148 ret = rb_sprintf("%"PRIdVALUE, (VALUE)(pos + len + op));
01149 break;
01150
01151 case TS_NUM:
01152 ret = rb_sprintf("%"PRIuVALUE, op);
01153 break;
01154
01155 case TS_LINDEX:{
01156 if (insn == BIN(getlocal) || insn == BIN(setlocal)) {
01157 if (pnop) {
01158 rb_iseq_t *diseq = iseq;
01159 VALUE level = *pnop, i;
01160
01161 for (i = 0; i < level; i++) {
01162 diseq = diseq->parent_iseq;
01163 }
01164 ret = id_to_name(diseq->local_table[diseq->local_size - op], INT2FIX('*'));
01165 }
01166 else {
01167 ret = rb_sprintf("%"PRIuVALUE, op);
01168 }
01169 }
01170 else {
01171 ret = rb_inspect(INT2FIX(op));
01172 }
01173 break;
01174 }
01175 case TS_ID:
01176 op = ID2SYM(op);
01177
01178 case TS_VALUE:
01179 op = obj_resurrect(op);
01180 ret = rb_inspect(op);
01181 if (CLASS_OF(op) == rb_cISeq) {
01182 if (child) {
01183 rb_ary_push(child, op);
01184 }
01185 }
01186 break;
01187
01188 case TS_ISEQ:
01189 {
01190 rb_iseq_t *iseq = (rb_iseq_t *)op;
01191 if (iseq) {
01192 ret = iseq->location.label;
01193 if (child) {
01194 rb_ary_push(child, iseq->self);
01195 }
01196 }
01197 else {
01198 ret = rb_str_new2("nil");
01199 }
01200 break;
01201 }
01202 case TS_GENTRY:
01203 {
01204 struct rb_global_entry *entry = (struct rb_global_entry *)op;
01205 ret = rb_str_dup(rb_id2str(entry->id));
01206 }
01207 break;
01208
01209 case TS_IC:
01210 ret = rb_sprintf("<ic:%"PRIdPTRDIFF">", (struct iseq_inline_cache_entry *)op - iseq->ic_entries);
01211 break;
01212
01213 case TS_CALLINFO:
01214 {
01215 rb_call_info_t *ci = (rb_call_info_t *)op;
01216 VALUE ary = rb_ary_new();
01217
01218 if (ci->mid) {
01219 rb_ary_push(ary, rb_sprintf("mid:%s", rb_id2name(ci->mid)));
01220 }
01221
01222 rb_ary_push(ary, rb_sprintf("argc:%d", ci->orig_argc));
01223
01224 if (ci->blockiseq) {
01225 if (child) {
01226 rb_ary_push(child, ci->blockiseq->self);
01227 }
01228 rb_ary_push(ary, rb_sprintf("block:%"PRIsVALUE, ci->blockiseq->location.label));
01229 }
01230
01231 if (ci->flag) {
01232 VALUE flags = rb_ary_new();
01233 if (ci->flag & VM_CALL_ARGS_SPLAT) rb_ary_push(flags, rb_str_new2("ARGS_SPLAT"));
01234 if (ci->flag & VM_CALL_ARGS_BLOCKARG) rb_ary_push(flags, rb_str_new2("ARGS_BLOCKARG"));
01235 if (ci->flag & VM_CALL_FCALL) rb_ary_push(flags, rb_str_new2("FCALL"));
01236 if (ci->flag & VM_CALL_VCALL) rb_ary_push(flags, rb_str_new2("VCALL"));
01237 if (ci->flag & VM_CALL_TAILCALL) rb_ary_push(flags, rb_str_new2("TAILCALL"));
01238 if (ci->flag & VM_CALL_SUPER) rb_ary_push(flags, rb_str_new2("SUPER"));
01239 if (ci->flag & VM_CALL_OPT_SEND) rb_ary_push(flags, rb_str_new2("SNED"));
01240 if (ci->flag & VM_CALL_ARGS_SKIP_SETUP) rb_ary_push(flags, rb_str_new2("ARGS_SKIP"));
01241 rb_ary_push(ary, rb_ary_join(flags, rb_str_new2("|")));
01242 }
01243 ret = rb_sprintf("<callinfo!%"PRIsVALUE">", rb_ary_join(ary, rb_str_new2(", ")));
01244 }
01245 break;
01246
01247 case TS_CDHASH:
01248 ret = rb_str_new2("<cdhash>");
01249 break;
01250
01251 case TS_FUNCPTR:
01252 ret = rb_str_new2("<funcptr>");
01253 break;
01254
01255 default:
01256 rb_bug("insn_operand_intern: unknown operand type: %c", type);
01257 }
01258 return ret;
01259 }
01260
01265 int
01266 rb_iseq_disasm_insn(VALUE ret, VALUE *iseq, size_t pos,
01267 rb_iseq_t *iseqdat, VALUE child)
01268 {
01269 VALUE insn = iseq[pos];
01270 int len = insn_len(insn);
01271 int j;
01272 const char *types = insn_op_types(insn);
01273 VALUE str = rb_str_new(0, 0);
01274 const char *insn_name_buff;
01275
01276 insn_name_buff = insn_name(insn);
01277 if (1) {
01278 rb_str_catf(str, "%04"PRIdSIZE" %-16s ", pos, insn_name_buff);
01279 }
01280 else {
01281 rb_str_catf(str, "%04"PRIdSIZE" %-16.*s ", pos,
01282 (int)strcspn(insn_name_buff, "_"), insn_name_buff);
01283 }
01284
01285 for (j = 0; types[j]; j++) {
01286 const char *types = insn_op_types(insn);
01287 VALUE opstr = insn_operand_intern(iseqdat, insn, j, iseq[pos + j + 1],
01288 len, pos, &iseq[pos + j + 2],
01289 child);
01290 rb_str_concat(str, opstr);
01291
01292 if (types[j + 1]) {
01293 rb_str_cat2(str, ", ");
01294 }
01295 }
01296
01297 {
01298 unsigned int line_no = find_line_no(iseqdat, pos);
01299 unsigned int prev = pos == 0 ? 0 : find_line_no(iseqdat, pos - 1);
01300 if (line_no && line_no != prev) {
01301 long slen = RSTRING_LEN(str);
01302 slen = (slen > 70) ? 0 : (70 - slen);
01303 str = rb_str_catf(str, "%*s(%4d)", (int)slen, "", line_no);
01304 }
01305 }
01306
01307 if (ret) {
01308 rb_str_cat2(str, "\n");
01309 rb_str_concat(ret, str);
01310 }
01311 else {
01312 printf("%s\n", RSTRING_PTR(str));
01313 }
01314 return len;
01315 }
01316
01317 static const char *
01318 catch_type(int type)
01319 {
01320 switch (type) {
01321 case CATCH_TYPE_RESCUE:
01322 return "rescue";
01323 case CATCH_TYPE_ENSURE:
01324 return "ensure";
01325 case CATCH_TYPE_RETRY:
01326 return "retry";
01327 case CATCH_TYPE_BREAK:
01328 return "break";
01329 case CATCH_TYPE_REDO:
01330 return "redo";
01331 case CATCH_TYPE_NEXT:
01332 return "next";
01333 default:
01334 rb_bug("unknown catch type (%d)", type);
01335 return 0;
01336 }
01337 }
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357 VALUE
01358 rb_iseq_disasm(VALUE self)
01359 {
01360 rb_iseq_t *iseqdat = iseq_check(self);
01361 VALUE *iseq;
01362 VALUE str = rb_str_new(0, 0);
01363 VALUE child = rb_ary_new();
01364 unsigned long size;
01365 int i;
01366 long l;
01367 ID *tbl;
01368 size_t n;
01369 enum {header_minlen = 72};
01370
01371 rb_secure(1);
01372
01373 iseq = iseqdat->iseq;
01374 size = iseqdat->iseq_size;
01375
01376 rb_str_cat2(str, "== disasm: ");
01377
01378 rb_str_concat(str, iseq_inspect(iseqdat->self));
01379 if ((l = RSTRING_LEN(str)) < header_minlen) {
01380 rb_str_resize(str, header_minlen);
01381 memset(RSTRING_PTR(str) + l, '=', header_minlen - l);
01382 }
01383 rb_str_cat2(str, "\n");
01384
01385
01386 if (iseqdat->catch_table_size != 0) {
01387 rb_str_cat2(str, "== catch table\n");
01388 }
01389 for (i = 0; i < iseqdat->catch_table_size; i++) {
01390 struct iseq_catch_table_entry *entry = &iseqdat->catch_table[i];
01391 rb_str_catf(str,
01392 "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
01393 catch_type((int)entry->type), (int)entry->start,
01394 (int)entry->end, (int)entry->sp, (int)entry->cont);
01395 if (entry->iseq) {
01396 rb_str_concat(str, rb_iseq_disasm(entry->iseq));
01397 }
01398 }
01399 if (iseqdat->catch_table_size != 0) {
01400 rb_str_cat2(str, "|-------------------------------------"
01401 "-----------------------------------\n");
01402 }
01403
01404
01405 tbl = iseqdat->local_table;
01406
01407 if (tbl) {
01408 rb_str_catf(str,
01409 "local table (size: %d, argc: %d "
01410 "[opts: %d, rest: %d, post: %d, block: %d] s%d)\n",
01411 iseqdat->local_size, iseqdat->argc,
01412 iseqdat->arg_opts, iseqdat->arg_rest,
01413 iseqdat->arg_post_len, iseqdat->arg_block,
01414 iseqdat->arg_simple);
01415
01416 for (i = 0; i < iseqdat->local_table_size; i++) {
01417 long width;
01418 VALUE name = id_to_name(tbl[i], 0);
01419 char argi[0x100] = "";
01420 char opti[0x100] = "";
01421
01422 if (iseqdat->arg_opts) {
01423 int argc = iseqdat->argc;
01424 int opts = iseqdat->arg_opts;
01425 if (i >= argc && i < argc + opts - 1) {
01426 snprintf(opti, sizeof(opti), "Opt=%"PRIdVALUE,
01427 iseqdat->arg_opt_table[i - argc]);
01428 }
01429 }
01430
01431 snprintf(argi, sizeof(argi), "%s%s%s%s%s",
01432 iseqdat->argc > i ? "Arg" : "",
01433 opti,
01434 iseqdat->arg_rest == i ? "Rest" : "",
01435 (iseqdat->arg_post_start <= i &&
01436 i < iseqdat->arg_post_start + iseqdat->arg_post_len) ? "Post" : "",
01437 iseqdat->arg_block == i ? "Block" : "");
01438
01439 rb_str_catf(str, "[%2d] ", iseqdat->local_size - i);
01440 width = RSTRING_LEN(str) + 11;
01441 if (name)
01442 rb_str_append(str, name);
01443 else
01444 rb_str_cat2(str, "?");
01445 if (*argi) rb_str_catf(str, "<%s>", argi);
01446 if ((width -= RSTRING_LEN(str)) > 0) rb_str_catf(str, "%*s", (int)width, "");
01447 }
01448 rb_str_cat2(str, "\n");
01449 }
01450
01451
01452 for (n = 0; n < size;) {
01453 n += rb_iseq_disasm_insn(str, iseq, n, iseqdat, child);
01454 }
01455
01456 for (i = 0; i < RARRAY_LEN(child); i++) {
01457 VALUE isv = rb_ary_entry(child, i);
01458 rb_str_concat(str, rb_iseq_disasm(isv));
01459 }
01460
01461 return str;
01462 }
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499 static VALUE
01500 iseq_s_of(VALUE klass, VALUE body)
01501 {
01502 VALUE ret = Qnil;
01503 rb_iseq_t *iseq;
01504
01505 rb_secure(1);
01506
01507 if (rb_obj_is_proc(body)) {
01508 rb_proc_t *proc;
01509 GetProcPtr(body, proc);
01510 iseq = proc->block.iseq;
01511 if (RUBY_VM_NORMAL_ISEQ_P(iseq)) {
01512 ret = iseq->self;
01513 }
01514 }
01515 else if ((iseq = rb_method_get_iseq(body)) != 0) {
01516 ret = iseq->self;
01517 }
01518 return ret;
01519 }
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574 static VALUE
01575 iseq_s_disasm(VALUE klass, VALUE body)
01576 {
01577 VALUE iseqval = iseq_s_of(klass, body);
01578 return NIL_P(iseqval) ? Qnil : rb_iseq_disasm(iseqval);
01579 }
01580
01581 const char *
01582 ruby_node_name(int node)
01583 {
01584 switch (node) {
01585 #include "node_name.inc"
01586 default:
01587 rb_bug("unknown node (%d)", node);
01588 return 0;
01589 }
01590 }
01591
01592 #define DECL_SYMBOL(name) \
01593 static VALUE sym_##name
01594
01595 #define INIT_SYMBOL(name) \
01596 sym_##name = ID2SYM(rb_intern(#name))
01597
01598 static VALUE
01599 register_label(struct st_table *table, unsigned long idx)
01600 {
01601 VALUE sym;
01602 char buff[8 + (sizeof(idx) * CHAR_BIT * 32 / 100)];
01603
01604 snprintf(buff, sizeof(buff), "label_%lu", idx);
01605 sym = ID2SYM(rb_intern(buff));
01606 st_insert(table, idx, sym);
01607 return sym;
01608 }
01609
01610 static VALUE
01611 exception_type2symbol(VALUE type)
01612 {
01613 ID id;
01614 switch (type) {
01615 case CATCH_TYPE_RESCUE: CONST_ID(id, "rescue"); break;
01616 case CATCH_TYPE_ENSURE: CONST_ID(id, "ensure"); break;
01617 case CATCH_TYPE_RETRY: CONST_ID(id, "retry"); break;
01618 case CATCH_TYPE_BREAK: CONST_ID(id, "break"); break;
01619 case CATCH_TYPE_REDO: CONST_ID(id, "redo"); break;
01620 case CATCH_TYPE_NEXT: CONST_ID(id, "next"); break;
01621 default:
01622 rb_bug("...");
01623 }
01624 return ID2SYM(id);
01625 }
01626
01627 static int
01628 cdhash_each(VALUE key, VALUE value, VALUE ary)
01629 {
01630 rb_ary_push(ary, obj_resurrect(key));
01631 rb_ary_push(ary, value);
01632 return ST_CONTINUE;
01633 }
01634
01635 static VALUE
01636 iseq_data_to_ary(rb_iseq_t *iseq)
01637 {
01638 long i;
01639 size_t ti;
01640 unsigned int pos;
01641 unsigned int line = 0;
01642 VALUE *seq;
01643
01644 VALUE val = rb_ary_new();
01645 VALUE type;
01646 VALUE locals = rb_ary_new();
01647 VALUE args = rb_ary_new();
01648 VALUE body = rb_ary_new();
01649 VALUE nbody;
01650 VALUE exception = rb_ary_new();
01651 VALUE misc = rb_hash_new();
01652
01653 static VALUE insn_syms[VM_INSTRUCTION_SIZE];
01654 struct st_table *labels_table = st_init_numtable();
01655
01656 DECL_SYMBOL(top);
01657 DECL_SYMBOL(method);
01658 DECL_SYMBOL(block);
01659 DECL_SYMBOL(class);
01660 DECL_SYMBOL(rescue);
01661 DECL_SYMBOL(ensure);
01662 DECL_SYMBOL(eval);
01663 DECL_SYMBOL(main);
01664 DECL_SYMBOL(defined_guard);
01665
01666 if (sym_top == 0) {
01667 int i;
01668 for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
01669 insn_syms[i] = ID2SYM(rb_intern(insn_name(i)));
01670 }
01671 INIT_SYMBOL(top);
01672 INIT_SYMBOL(method);
01673 INIT_SYMBOL(block);
01674 INIT_SYMBOL(class);
01675 INIT_SYMBOL(rescue);
01676 INIT_SYMBOL(ensure);
01677 INIT_SYMBOL(eval);
01678 INIT_SYMBOL(main);
01679 INIT_SYMBOL(defined_guard);
01680 }
01681
01682
01683 switch (iseq->type) {
01684 case ISEQ_TYPE_TOP: type = sym_top; break;
01685 case ISEQ_TYPE_METHOD: type = sym_method; break;
01686 case ISEQ_TYPE_BLOCK: type = sym_block; break;
01687 case ISEQ_TYPE_CLASS: type = sym_class; break;
01688 case ISEQ_TYPE_RESCUE: type = sym_rescue; break;
01689 case ISEQ_TYPE_ENSURE: type = sym_ensure; break;
01690 case ISEQ_TYPE_EVAL: type = sym_eval; break;
01691 case ISEQ_TYPE_MAIN: type = sym_main; break;
01692 case ISEQ_TYPE_DEFINED_GUARD: type = sym_defined_guard; break;
01693 default: rb_bug("unsupported iseq type");
01694 };
01695
01696
01697 for (i=0; i<iseq->local_table_size; i++) {
01698 ID lid = iseq->local_table[i];
01699 if (lid) {
01700 if (rb_id2str(lid)) rb_ary_push(locals, ID2SYM(lid));
01701 }
01702 else {
01703 rb_ary_push(locals, ID2SYM(rb_intern("#arg_rest")));
01704 }
01705 }
01706
01707
01708 {
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719 VALUE arg_opt_labels = rb_ary_new();
01720 int j;
01721
01722 for (j=0; j<iseq->arg_opts; j++) {
01723 rb_ary_push(arg_opt_labels,
01724 register_label(labels_table, iseq->arg_opt_table[j]));
01725 }
01726
01727
01728 if (iseq->arg_simple == 1) {
01729 args = INT2FIX(iseq->argc);
01730 }
01731 else {
01732 rb_ary_push(args, INT2FIX(iseq->argc));
01733 rb_ary_push(args, arg_opt_labels);
01734 rb_ary_push(args, INT2FIX(iseq->arg_post_len));
01735 rb_ary_push(args, INT2FIX(iseq->arg_post_start));
01736 rb_ary_push(args, INT2FIX(iseq->arg_rest));
01737 rb_ary_push(args, INT2FIX(iseq->arg_block));
01738 rb_ary_push(args, INT2FIX(iseq->arg_simple));
01739 }
01740 }
01741
01742
01743 for (seq = iseq->iseq; seq < iseq->iseq + iseq->iseq_size; ) {
01744 VALUE insn = *seq++;
01745 int j, len = insn_len(insn);
01746 VALUE *nseq = seq + len - 1;
01747 VALUE ary = rb_ary_new2(len);
01748
01749 rb_ary_push(ary, insn_syms[insn]);
01750 for (j=0; j<len-1; j++, seq++) {
01751 switch (insn_op_type(insn, j)) {
01752 case TS_OFFSET: {
01753 unsigned long idx = nseq - iseq->iseq + *seq;
01754 rb_ary_push(ary, register_label(labels_table, idx));
01755 break;
01756 }
01757 case TS_LINDEX:
01758 case TS_NUM:
01759 rb_ary_push(ary, INT2FIX(*seq));
01760 break;
01761 case TS_VALUE:
01762 rb_ary_push(ary, obj_resurrect(*seq));
01763 break;
01764 case TS_ISEQ:
01765 {
01766 rb_iseq_t *iseq = (rb_iseq_t *)*seq;
01767 if (iseq) {
01768 VALUE val = iseq_data_to_ary(iseq);
01769 rb_ary_push(ary, val);
01770 }
01771 else {
01772 rb_ary_push(ary, Qnil);
01773 }
01774 }
01775 break;
01776 case TS_GENTRY:
01777 {
01778 struct rb_global_entry *entry = (struct rb_global_entry *)*seq;
01779 rb_ary_push(ary, ID2SYM(entry->id));
01780 }
01781 break;
01782 case TS_IC: {
01783 struct iseq_inline_cache_entry *ic = (struct iseq_inline_cache_entry *)*seq;
01784 rb_ary_push(ary, INT2FIX(ic - iseq->ic_entries));
01785 }
01786 break;
01787 case TS_CALLINFO:
01788 {
01789 rb_call_info_t *ci = (rb_call_info_t *)*seq;
01790 VALUE e = rb_hash_new();
01791 rb_hash_aset(e, ID2SYM(rb_intern("mid")), ci->mid ? ID2SYM(ci->mid) : Qnil);
01792 rb_hash_aset(e, ID2SYM(rb_intern("flag")), ULONG2NUM(ci->flag));
01793 rb_hash_aset(e, ID2SYM(rb_intern("orig_argc")), INT2FIX(ci->orig_argc));
01794 rb_hash_aset(e, ID2SYM(rb_intern("blockptr")), ci->blockiseq ? iseq_data_to_ary(ci->blockiseq) : Qnil);
01795 rb_ary_push(ary, e);
01796 }
01797 break;
01798 case TS_ID:
01799 rb_ary_push(ary, ID2SYM(*seq));
01800 break;
01801 case TS_CDHASH:
01802 {
01803 VALUE hash = *seq;
01804 VALUE val = rb_ary_new();
01805 int i;
01806
01807 rb_hash_foreach(hash, cdhash_each, val);
01808
01809 for (i=0; i<RARRAY_LEN(val); i+=2) {
01810 VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
01811 unsigned long idx = nseq - iseq->iseq + pos;
01812
01813 rb_ary_store(val, i+1,
01814 register_label(labels_table, idx));
01815 }
01816 rb_ary_push(ary, val);
01817 }
01818 break;
01819 default:
01820 rb_bug("unknown operand: %c", insn_op_type(insn, j));
01821 }
01822 }
01823 rb_ary_push(body, ary);
01824 }
01825
01826 nbody = body;
01827
01828
01829 for (i=0; i<iseq->catch_table_size; i++) {
01830 VALUE ary = rb_ary_new();
01831 struct iseq_catch_table_entry *entry = &iseq->catch_table[i];
01832 rb_ary_push(ary, exception_type2symbol(entry->type));
01833 if (entry->iseq) {
01834 rb_iseq_t *eiseq;
01835 GetISeqPtr(entry->iseq, eiseq);
01836 rb_ary_push(ary, iseq_data_to_ary(eiseq));
01837 }
01838 else {
01839 rb_ary_push(ary, Qnil);
01840 }
01841 rb_ary_push(ary, register_label(labels_table, entry->start));
01842 rb_ary_push(ary, register_label(labels_table, entry->end));
01843 rb_ary_push(ary, register_label(labels_table, entry->cont));
01844 rb_ary_push(ary, INT2FIX(entry->sp));
01845 rb_ary_push(exception, ary);
01846 }
01847
01848
01849 body = rb_ary_new();
01850 ti = 0;
01851
01852 for (i=0, pos=0; i<RARRAY_LEN(nbody); i++) {
01853 VALUE ary = RARRAY_PTR(nbody)[i];
01854 st_data_t label;
01855
01856 if (st_lookup(labels_table, pos, &label)) {
01857 rb_ary_push(body, (VALUE)label);
01858 }
01859
01860 if (ti < iseq->line_info_size && iseq->line_info_table[ti].position == pos) {
01861 line = iseq->line_info_table[ti].line_no;
01862 rb_ary_push(body, INT2FIX(line));
01863 ti++;
01864 }
01865
01866 rb_ary_push(body, ary);
01867 pos += RARRAY_LENINT(ary);
01868 }
01869
01870 st_free_table(labels_table);
01871
01872 rb_hash_aset(misc, ID2SYM(rb_intern("arg_size")), INT2FIX(iseq->arg_size));
01873 rb_hash_aset(misc, ID2SYM(rb_intern("local_size")), INT2FIX(iseq->local_size));
01874 rb_hash_aset(misc, ID2SYM(rb_intern("stack_max")), INT2FIX(iseq->stack_max));
01875
01876
01877
01878
01879
01880
01881
01882 rb_ary_push(val, rb_str_new2("YARVInstructionSequence/SimpleDataFormat"));
01883 rb_ary_push(val, INT2FIX(ISEQ_MAJOR_VERSION));
01884 rb_ary_push(val, INT2FIX(ISEQ_MINOR_VERSION));
01885 rb_ary_push(val, INT2FIX(1));
01886 rb_ary_push(val, misc);
01887 rb_ary_push(val, iseq->location.label);
01888 rb_ary_push(val, iseq->location.path);
01889 rb_ary_push(val, iseq->location.absolute_path);
01890 rb_ary_push(val, iseq->location.first_lineno);
01891 rb_ary_push(val, type);
01892 rb_ary_push(val, locals);
01893 rb_ary_push(val, args);
01894 rb_ary_push(val, exception);
01895 rb_ary_push(val, body);
01896 return val;
01897 }
01898
01899 VALUE
01900 rb_iseq_clone(VALUE iseqval, VALUE newcbase)
01901 {
01902 VALUE newiseq = iseq_alloc(rb_cISeq);
01903 rb_iseq_t *iseq0, *iseq1;
01904
01905 GetISeqPtr(iseqval, iseq0);
01906 GetISeqPtr(newiseq, iseq1);
01907
01908 *iseq1 = *iseq0;
01909 iseq1->self = newiseq;
01910 if (!iseq1->orig) {
01911 iseq1->orig = iseqval;
01912 }
01913 if (iseq0->local_iseq == iseq0) {
01914 iseq1->local_iseq = iseq1;
01915 }
01916 if (newcbase) {
01917 iseq1->cref_stack = NEW_CREF(newcbase);
01918 iseq1->cref_stack->nd_refinements = iseq0->cref_stack->nd_refinements;
01919 iseq1->cref_stack->nd_visi = iseq0->cref_stack->nd_visi;
01920 if (iseq0->cref_stack->nd_next) {
01921 iseq1->cref_stack->nd_next = iseq0->cref_stack->nd_next;
01922 }
01923 iseq1->klass = newcbase;
01924 }
01925
01926 return newiseq;
01927 }
01928
01929 VALUE
01930 rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
01931 {
01932 int i, r;
01933 VALUE a, args = rb_ary_new2(iseq->arg_size);
01934 ID req, opt, rest, block, key, keyrest;
01935 #define PARAM_TYPE(type) rb_ary_push(a = rb_ary_new2(2), ID2SYM(type))
01936 #define PARAM_ID(i) iseq->local_table[(i)]
01937 #define PARAM(i, type) ( \
01938 PARAM_TYPE(type), \
01939 rb_id2str(PARAM_ID(i)) ? \
01940 rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \
01941 a)
01942
01943 CONST_ID(req, "req");
01944 CONST_ID(opt, "opt");
01945 if (is_proc) {
01946 for (i = 0; i < iseq->argc; i++) {
01947 PARAM_TYPE(opt);
01948 rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
01949 rb_ary_push(args, a);
01950 }
01951 }
01952 else {
01953 for (i = 0; i < iseq->argc; i++) {
01954 rb_ary_push(args, PARAM(i, req));
01955 }
01956 }
01957 r = iseq->argc + iseq->arg_opts - 1;
01958 for (; i < r; i++) {
01959 PARAM_TYPE(opt);
01960 if (rb_id2str(PARAM_ID(i))) {
01961 rb_ary_push(a, ID2SYM(PARAM_ID(i)));
01962 }
01963 rb_ary_push(args, a);
01964 }
01965 if (iseq->arg_rest != -1) {
01966 CONST_ID(rest, "rest");
01967 rb_ary_push(args, PARAM(iseq->arg_rest, rest));
01968 }
01969 r = iseq->arg_post_start + iseq->arg_post_len;
01970 if (is_proc) {
01971 for (i = iseq->arg_post_start; i < r; i++) {
01972 PARAM_TYPE(opt);
01973 rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
01974 rb_ary_push(args, a);
01975 }
01976 }
01977 else {
01978 for (i = iseq->arg_post_start; i < r; i++) {
01979 rb_ary_push(args, PARAM(i, req));
01980 }
01981 }
01982 if (iseq->arg_keyword != -1) {
01983 CONST_ID(key, "key");
01984 for (i = 0; i < iseq->arg_keywords; i++) {
01985 PARAM_TYPE(key);
01986 if (rb_id2str(iseq->arg_keyword_table[i])) {
01987 rb_ary_push(a, ID2SYM(iseq->arg_keyword_table[i]));
01988 }
01989 rb_ary_push(args, a);
01990 }
01991 if (rb_id2str(iseq->local_table[iseq->arg_keyword])) {
01992 CONST_ID(keyrest, "keyrest");
01993 rb_ary_push(args, PARAM(iseq->arg_keyword, keyrest));
01994 }
01995 }
01996 if (iseq->arg_block != -1) {
01997 CONST_ID(block, "block");
01998 rb_ary_push(args, PARAM(iseq->arg_block, block));
01999 }
02000 return args;
02001 }
02002
02003 VALUE
02004 rb_iseq_defined_string(enum defined_type type)
02005 {
02006 static const char expr_names[][18] = {
02007 "nil",
02008 "instance-variable",
02009 "local-variable",
02010 "global-variable",
02011 "class variable",
02012 "constant",
02013 "method",
02014 "yield",
02015 "super",
02016 "self",
02017 "true",
02018 "false",
02019 "assignment",
02020 "expression",
02021 };
02022 const char *estr;
02023 VALUE *defs, str;
02024
02025 if ((unsigned)(type - 1) >= (unsigned)numberof(expr_names)) return 0;
02026 estr = expr_names[type - 1];
02027 if (!estr[0]) return 0;
02028 defs = GET_VM()->defined_strings;
02029 if (!defs) {
02030 defs = ruby_xcalloc(numberof(expr_names), sizeof(VALUE));
02031 GET_VM()->defined_strings = defs;
02032 }
02033 str = defs[type-1];
02034 if (!str) {
02035 str = rb_str_new_cstr(estr);;
02036 OBJ_FREEZE(str);
02037 defs[type-1] = str;
02038 }
02039 return str;
02040 }
02041
02042
02043
02044 VALUE
02045 rb_iseq_build_for_ruby2cext(
02046 const rb_iseq_t *iseq_template,
02047 const rb_insn_func_t *func,
02048 const struct iseq_line_info_entry *line_info_table,
02049 const char **local_table,
02050 const VALUE *arg_opt_table,
02051 const struct iseq_catch_table_entry *catch_table,
02052 const char *name,
02053 const char *path,
02054 const unsigned short first_lineno)
02055 {
02056 unsigned long i;
02057 VALUE iseqval = iseq_alloc(rb_cISeq);
02058 rb_iseq_t *iseq;
02059 GetISeqPtr(iseqval, iseq);
02060
02061
02062 *iseq = *iseq_template;
02063 iseq->location.label = rb_str_new2(name);
02064 iseq->location.path = rb_str_new2(path);
02065 iseq->location.first_lineno = first_lineno;
02066 iseq->mark_ary = 0;
02067 iseq->self = iseqval;
02068
02069 iseq->iseq = ALLOC_N(VALUE, iseq->iseq_size);
02070
02071 for (i=0; i<iseq->iseq_size; i+=2) {
02072 iseq->iseq[i] = BIN(opt_call_c_function);
02073 iseq->iseq[i+1] = (VALUE)func;
02074 }
02075
02076 rb_iseq_translate_threaded_code(iseq);
02077
02078 #define ALLOC_AND_COPY(dst, src, type, size) do { \
02079 if (size) { \
02080 (dst) = ALLOC_N(type, (size)); \
02081 MEMCPY((dst), (src), type, (size)); \
02082 } \
02083 } while (0)
02084
02085 ALLOC_AND_COPY(iseq->line_info_table, line_info_table,
02086 struct iseq_line_info_entry, iseq->line_info_size);
02087
02088 ALLOC_AND_COPY(iseq->catch_table, catch_table,
02089 struct iseq_catch_table_entry, iseq->catch_table_size);
02090
02091 ALLOC_AND_COPY(iseq->arg_opt_table, arg_opt_table,
02092 VALUE, iseq->arg_opts);
02093
02094 set_relation(iseq, 0);
02095
02096 return iseqval;
02097 }
02098
02099
02100
02101
02102
02103 int
02104 rb_iseq_line_trace_each(VALUE iseqval, int (*func)(int line, rb_event_flag_t *events_ptr, void *d), void *data)
02105 {
02106 int trace_num = 0;
02107 size_t pos, insn;
02108 rb_iseq_t *iseq;
02109 int cont = 1;
02110 GetISeqPtr(iseqval, iseq);
02111
02112 for (pos = 0; cont && pos < iseq->iseq_size; pos += insn_len(insn)) {
02113 insn = iseq->iseq[pos];
02114
02115 if (insn == BIN(trace)) {
02116 rb_event_flag_t current_events = (VALUE)iseq->iseq[pos+1];
02117
02118 if (current_events & RUBY_EVENT_LINE) {
02119 rb_event_flag_t events = current_events & RUBY_EVENT_SPECIFIED_LINE;
02120 trace_num++;
02121
02122 if (func) {
02123 int line = find_line_no(iseq, pos);
02124
02125 cont = (*func)(line, &events, data);
02126 if (current_events != events) {
02127 iseq->iseq[pos+1] = iseq->iseq_encoded[pos+1] =
02128 (VALUE)(current_events | (events & RUBY_EVENT_SPECIFIED_LINE));
02129 }
02130 }
02131 }
02132 }
02133 }
02134 return trace_num;
02135 }
02136
02137 static int
02138 collect_trace(int line, rb_event_flag_t *events_ptr, void *ptr)
02139 {
02140 VALUE result = (VALUE)ptr;
02141 rb_ary_push(result, INT2NUM(line));
02142 return 1;
02143 }
02144
02145
02146
02147
02148
02149
02150 VALUE
02151 rb_iseq_line_trace_all(VALUE iseqval)
02152 {
02153 VALUE result = rb_ary_new();
02154 rb_iseq_line_trace_each(iseqval, collect_trace, (void *)result);
02155 return result;
02156 }
02157
02158 struct set_specifc_data {
02159 int pos;
02160 int set;
02161 int prev;
02162 };
02163
02164 static int
02165 line_trace_specify(int line, rb_event_flag_t *events_ptr, void *ptr)
02166 {
02167 struct set_specifc_data *data = (struct set_specifc_data *)ptr;
02168
02169 if (data->pos == 0) {
02170 data->prev = *events_ptr & RUBY_EVENT_SPECIFIED_LINE ? 1 : 2;
02171 if (data->set) {
02172 *events_ptr = *events_ptr | RUBY_EVENT_SPECIFIED_LINE;
02173 }
02174 else {
02175 *events_ptr = *events_ptr & ~RUBY_EVENT_SPECIFIED_LINE;
02176 }
02177 return 0;
02178 }
02179 else {
02180 data->pos--;
02181 return 1;
02182 }
02183 }
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197 VALUE
02198 rb_iseq_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set)
02199 {
02200 struct set_specifc_data data;
02201
02202 data.prev = 0;
02203 data.pos = NUM2INT(pos);
02204 if (data.pos < 0) rb_raise(rb_eTypeError, "`pos' is negative");
02205
02206 switch (set) {
02207 case Qtrue: data.set = 1; break;
02208 case Qfalse: data.set = 0; break;
02209 default:
02210 rb_raise(rb_eTypeError, "`set' should be true/false");
02211 }
02212
02213 rb_iseq_line_trace_each(iseqval, line_trace_specify, (void *)&data);
02214
02215 if (data.prev == 0) {
02216 rb_raise(rb_eTypeError, "`pos' is out of range.");
02217 }
02218 return data.prev == 1 ? Qtrue : Qfalse;
02219 }
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241 void
02242 Init_ISeq(void)
02243 {
02244
02245 rb_cISeq = rb_define_class_under(rb_cRubyVM, "InstructionSequence", rb_cObject);
02246 rb_define_alloc_func(rb_cISeq, iseq_alloc);
02247 rb_define_method(rb_cISeq, "inspect", iseq_inspect, 0);
02248 rb_define_method(rb_cISeq, "disasm", rb_iseq_disasm, 0);
02249 rb_define_method(rb_cISeq, "disassemble", rb_iseq_disasm, 0);
02250 rb_define_method(rb_cISeq, "to_a", iseq_to_a, 0);
02251 rb_define_method(rb_cISeq, "eval", iseq_eval, 0);
02252
02253
02254 rb_define_method(rb_cISeq, "path", iseq_path, 0);
02255 rb_define_method(rb_cISeq, "absolute_path", iseq_absolute_path, 0);
02256 rb_define_method(rb_cISeq, "label", iseq_label, 0);
02257 rb_define_method(rb_cISeq, "base_label", iseq_base_label, 0);
02258 rb_define_method(rb_cISeq, "first_lineno", iseq_first_lineno, 0);
02259
02260 #if 0
02261
02262
02263 rb_define_method(rb_cISeq, "line_trace_all", rb_iseq_line_trace_all, 0);
02264 rb_define_method(rb_cISeq, "line_trace_specify", rb_iseq_line_trace_specify, 2);
02265 #else
02266 (void)rb_iseq_line_trace_all;
02267 (void)rb_iseq_line_trace_specify;
02268 #endif
02269
02270 #if 0
02271 rb_define_private_method(rb_cISeq, "marshal_dump", iseq_marshal_dump, 0);
02272 rb_define_private_method(rb_cISeq, "marshal_load", iseq_marshal_load, 1);
02273 #endif
02274
02275
02276
02277 (void)iseq_s_load;
02278
02279 rb_define_singleton_method(rb_cISeq, "compile", iseq_s_compile, -1);
02280 rb_define_singleton_method(rb_cISeq, "new", iseq_s_compile, -1);
02281 rb_define_singleton_method(rb_cISeq, "compile_file", iseq_s_compile_file, -1);
02282 rb_define_singleton_method(rb_cISeq, "compile_option", iseq_s_compile_option_get, 0);
02283 rb_define_singleton_method(rb_cISeq, "compile_option=", iseq_s_compile_option_set, 1);
02284 rb_define_singleton_method(rb_cISeq, "disasm", iseq_s_disasm, 1);
02285 rb_define_singleton_method(rb_cISeq, "disassemble", iseq_s_disasm, 1);
02286 rb_define_singleton_method(rb_cISeq, "of", iseq_s_of, 1);
02287 }
02288