1/********************************************************************** 2 3 compile.c - ruby node tree -> VM instruction sequence 4 5 $Author: nagachika $ 6 created at: 04/01/01 03:42:15 JST 7 8 Copyright (C) 2004-2007 Koichi Sasada 9 10**********************************************************************/ 11 12#include "ruby/ruby.h" 13#include "internal.h" 14#include <math.h> 15 16#define USE_INSN_STACK_INCREASE 1 17#include "vm_core.h" 18#include "iseq.h" 19#include "insns.inc" 20#include "insns_info.inc" 21 22#define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) 23#define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG)) 24#define FIXNUM_OR(n, i) ((n)|INT2FIX(i)) 25 26typedef struct iseq_link_element { 27 enum { 28 ISEQ_ELEMENT_NONE, 29 ISEQ_ELEMENT_LABEL, 30 ISEQ_ELEMENT_INSN, 31 ISEQ_ELEMENT_ADJUST 32 } type; 33 struct iseq_link_element *next; 34 struct iseq_link_element *prev; 35} LINK_ELEMENT; 36 37typedef struct iseq_link_anchor { 38 LINK_ELEMENT anchor; 39 LINK_ELEMENT *last; 40} LINK_ANCHOR; 41 42typedef struct iseq_label_data { 43 LINK_ELEMENT link; 44 int label_no; 45 int position; 46 int sc_state; 47 int set; 48 int sp; 49} LABEL; 50 51typedef struct iseq_insn_data { 52 LINK_ELEMENT link; 53 enum ruby_vminsn_type insn_id; 54 unsigned int line_no; 55 int operand_size; 56 int sc_state; 57 VALUE *operands; 58} INSN; 59 60typedef struct iseq_adjust_data { 61 LINK_ELEMENT link; 62 LABEL *label; 63 int line_no; 64} ADJUST; 65 66struct ensure_range { 67 LABEL *begin; 68 LABEL *end; 69 struct ensure_range *next; 70}; 71 72struct iseq_compile_data_ensure_node_stack { 73 NODE *ensure_node; 74 struct iseq_compile_data_ensure_node_stack *prev; 75 struct ensure_range *erange; 76}; 77 78/** 79 * debug function(macro) interface depend on CPDEBUG 80 * if it is less than 0, runtime option is in effect. 81 * 82 * debug level: 83 * 0: no debug output 84 * 1: show node type 85 * 2: show node important parameters 86 * ... 87 * 5: show other parameters 88 * 10: show every AST array 89 */ 90 91#ifndef CPDEBUG 92#define CPDEBUG 0 93#endif 94 95#if CPDEBUG >= 0 96#define compile_debug CPDEBUG 97#else 98#define compile_debug iseq->compile_data->option->debug_level 99#endif 100 101#if CPDEBUG 102 103#define compile_debug_print_indent(level) \ 104 ruby_debug_print_indent((level), compile_debug, gl_node_level * 2) 105 106#define debugp(header, value) (void) \ 107 (compile_debug_print_indent(1) && \ 108 ruby_debug_print_value(1, compile_debug, (header), (value))) 109 110#define debugi(header, id) (void) \ 111 (compile_debug_print_indent(1) && \ 112 ruby_debug_print_id(1, compile_debug, (header), (id))) 113 114#define debugp_param(header, value) (void) \ 115 (compile_debug_print_indent(1) && \ 116 ruby_debug_print_value(1, compile_debug, (header), (value))) 117 118#define debugp_verbose(header, value) (void) \ 119 (compile_debug_print_indent(2) && \ 120 ruby_debug_print_value(2, compile_debug, (header), (value))) 121 122#define debugp_verbose_node(header, value) (void) \ 123 (compile_debug_print_indent(10) && \ 124 ruby_debug_print_value(10, compile_debug, (header), (value))) 125 126#define debug_node_start(node) ((void) \ 127 (compile_debug_print_indent(1) && \ 128 (ruby_debug_print_node(1, CPDEBUG, "", (NODE *)(node)), gl_node_level)), \ 129 gl_node_level++) 130 131#define debug_node_end() gl_node_level -- 132 133#else 134 135static inline ID 136r_id(ID id) 137{ 138 return id; 139} 140 141static inline VALUE 142r_value(VALUE value) 143{ 144 return value; 145} 146 147#define debugi(header, id) r_id(id) 148#define debugp(header, value) r_value(value) 149#define debugp_verbose(header, value) r_value(value) 150#define debugp_verbose_node(header, value) r_value(value) 151#define debugp_param(header, value) r_value(value) 152#define debug_node_start(node) ((void)0) 153#define debug_node_end() ((void)0) 154#endif 155 156#if CPDEBUG > 1 || CPDEBUG < 0 157#define debugs if (compile_debug_print_indent(1)) ruby_debug_printf 158#define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs((msg), stderr)), (v)) 159#else 160#define debugs if(0)printf 161#define debug_compile(msg, v) (v) 162#endif 163 164 165/* create new label */ 166#define NEW_LABEL(l) new_label_body(iseq, (l)) 167 168#define iseq_path(iseq) \ 169 (((rb_iseq_t*)DATA_PTR(iseq))->location.path) 170 171#define iseq_absolute_path(iseq) \ 172 (((rb_iseq_t*)DATA_PTR(iseq))->location.absolute_path) 173 174#define NEW_ISEQVAL(node, name, type, line_no) \ 175 new_child_iseq(iseq, (node), (name), 0, (type), (line_no)) 176 177#define NEW_CHILD_ISEQVAL(node, name, type, line_no) \ 178 new_child_iseq(iseq, (node), (name), iseq->self, (type), (line_no)) 179 180/* add instructions */ 181#define ADD_SEQ(seq1, seq2) \ 182 APPEND_LIST((seq1), (seq2)) 183 184/* add an instruction */ 185#define ADD_INSN(seq, line, insn) \ 186 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0)) 187 188/* add an instruction with some operands (1, 2, 3, 5) */ 189#define ADD_INSN1(seq, line, insn, op1) \ 190 ADD_ELEM((seq), (LINK_ELEMENT *) \ 191 new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1))) 192 193/* add an instruction with label operand (alias of ADD_INSN1) */ 194#define ADD_INSNL(seq, line, insn, label) ADD_INSN1(seq, line, insn, label) 195 196#define ADD_INSN2(seq, line, insn, op1, op2) \ 197 ADD_ELEM((seq), (LINK_ELEMENT *) \ 198 new_insn_body(iseq, (line), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2))) 199 200#define ADD_INSN3(seq, line, insn, op1, op2, op3) \ 201 ADD_ELEM((seq), (LINK_ELEMENT *) \ 202 new_insn_body(iseq, (line), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3))) 203 204/* Specific Insn factory */ 205#define ADD_SEND(seq, line, id, argc) \ 206 ADD_SEND_R((seq), (line), (id), (argc), (VALUE)Qfalse, (VALUE)INT2FIX(0)) 207 208#define ADD_CALL_RECEIVER(seq, line) \ 209 ADD_INSN((seq), (line), putself) 210 211#define ADD_CALL(seq, line, id, argc) \ 212 ADD_SEND_R((seq), (line), (id), (argc), (VALUE)Qfalse, (VALUE)INT2FIX(VM_CALL_FCALL)) 213 214#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \ 215 ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL)) 216 217#define ADD_SEND_R(seq, line, id, argc, block, flag) \ 218 ADD_ELEM((seq), (LINK_ELEMENT *) \ 219 new_insn_send(iseq, (line), \ 220 (VALUE)(id), (VALUE)(argc), (VALUE)(block), (VALUE)(flag))) 221 222#define ADD_TRACE(seq, line, event) \ 223 do { \ 224 if ((event) == RUBY_EVENT_LINE && iseq->coverage && \ 225 (line) != iseq->compile_data->last_coverable_line) { \ 226 RARRAY_PTR(iseq->coverage)[(line) - 1] = INT2FIX(0); \ 227 iseq->compile_data->last_coverable_line = (line); \ 228 ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_COVERAGE)); \ 229 } \ 230 if (iseq->compile_data->option->trace_instruction) { \ 231 ADD_INSN1((seq), (line), trace, INT2FIX(event)); \ 232 } \ 233 } while (0) 234 235/* add label */ 236#define ADD_LABEL(seq, label) \ 237 ADD_ELEM((seq), (LINK_ELEMENT *) (label)) 238 239#define APPEND_LABEL(seq, before, label) \ 240 APPEND_ELEM((seq), (before), (LINK_ELEMENT *) (label)) 241 242#define ADD_ADJUST(seq, line, label) \ 243 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), (line))) 244 245#define ADD_ADJUST_RESTORE(seq, label) \ 246 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1)) 247 248#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) \ 249 (rb_ary_push(iseq->compile_data->catch_table_ary, \ 250 rb_ary_new3(5, (type), \ 251 (VALUE)(ls) | 1, (VALUE)(le) | 1, \ 252 (VALUE)(iseqv), (VALUE)(lc) | 1))) 253 254/* compile node */ 255#define COMPILE(anchor, desc, node) \ 256 (debug_compile("== " desc "\n", \ 257 iseq_compile_each(iseq, (anchor), (node), 0))) 258 259/* compile node, this node's value will be popped */ 260#define COMPILE_POPED(anchor, desc, node) \ 261 (debug_compile("== " desc "\n", \ 262 iseq_compile_each(iseq, (anchor), (node), 1))) 263 264/* compile node, which is popped when 'poped' is true */ 265#define COMPILE_(anchor, desc, node, poped) \ 266 (debug_compile("== " desc "\n", \ 267 iseq_compile_each(iseq, (anchor), (node), (poped)))) 268 269#define OPERAND_AT(insn, idx) \ 270 (((INSN*)(insn))->operands[(idx)]) 271 272#define INSN_OF(insn) \ 273 (((INSN*)(insn))->insn_id) 274 275/* error */ 276#define COMPILE_ERROR(strs) \ 277{ \ 278 VALUE tmp = GET_THREAD()->errinfo; \ 279 if (compile_debug) rb_compile_bug strs; \ 280 GET_THREAD()->errinfo = iseq->compile_data->err_info; \ 281 rb_compile_error strs; \ 282 iseq->compile_data->err_info = GET_THREAD()->errinfo; \ 283 GET_THREAD()->errinfo = tmp; \ 284 ret = 0; \ 285 break; \ 286} 287 288#define ERROR_ARGS ruby_sourcefile, nd_line(node), 289 290 291#define COMPILE_OK 1 292#define COMPILE_NG 0 293 294 295/* leave name uninitialized so that compiler warn if INIT_ANCHOR is 296 * missing */ 297#define DECL_ANCHOR(name) \ 298 LINK_ANCHOR *name, name##_body__ = {{0,},} 299#define INIT_ANCHOR(name) \ 300 (name##_body__.last = &name##_body__.anchor, name = &name##_body__) 301 302#define hide_obj(obj) do {OBJ_FREEZE(obj); RBASIC(obj)->klass = 0;} while (0) 303 304#include "optinsn.inc" 305#if OPT_INSTRUCTIONS_UNIFICATION 306#include "optunifs.inc" 307#endif 308 309/* for debug */ 310#if CPDEBUG < 0 311#define ISEQ_ARG iseq, 312#define ISEQ_ARG_DECLARE rb_iseq_t *iseq, 313#else 314#define ISEQ_ARG 315#define ISEQ_ARG_DECLARE 316#endif 317 318#if CPDEBUG 319#define gl_node_level iseq->compile_data->node_level 320#if 0 321static void debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor); 322#endif 323#endif 324 325static void dump_disasm_list(LINK_ELEMENT *elem); 326 327static int insn_data_length(INSN *iobj); 328static int insn_data_line_no(INSN *iobj); 329static int calc_sp_depth(int depth, INSN *iobj); 330 331static INSN *new_insn_body(rb_iseq_t *iseq, int line_no, int insn_id, int argc, ...); 332static LABEL *new_label_body(rb_iseq_t *iseq, long line); 333static ADJUST *new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line); 334 335static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * n, int); 336static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor); 337static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *anchor); 338static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor); 339 340static int iseq_set_local_table(rb_iseq_t *iseq, ID *tbl); 341static int iseq_set_exception_local_table(rb_iseq_t *iseq); 342static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * node); 343 344static int iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor); 345static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor); 346static int iseq_set_exception_table(rb_iseq_t *iseq); 347static int iseq_set_optargs_table(rb_iseq_t *iseq); 348 349/* 350 * To make Array to LinkedList, use link_anchor 351 */ 352 353static void 354verify_list(ISEQ_ARG_DECLARE const char *info, LINK_ANCHOR *anchor) 355{ 356#if CPDEBUG 357 int flag = 0; 358 LINK_ELEMENT *list, *plist; 359 360 if (!compile_debug) return; 361 362 list = anchor->anchor.next; 363 plist = &anchor->anchor; 364 while (list) { 365 if (plist != list->prev) { 366 flag += 1; 367 } 368 plist = list; 369 list = list->next; 370 } 371 372 if (anchor->last != plist && anchor->last != 0) { 373 flag |= 0x70000; 374 } 375 376 if (flag != 0) { 377 rb_bug("list verify error: %08x (%s)", flag, info); 378 } 379#endif 380} 381#if CPDEBUG < 0 382#define verify_list(info, anchor) verify_list(iseq, (info), (anchor)) 383#endif 384 385/* 386 * elem1, elem2 => elem1, elem2, elem 387 */ 388static void 389ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor, LINK_ELEMENT *elem) 390{ 391 elem->prev = anchor->last; 392 anchor->last->next = elem; 393 anchor->last = elem; 394 verify_list("add", anchor); 395} 396 397/* 398 * elem1, before, elem2 => elem1, before, elem, elem2 399 */ 400static void 401APPEND_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor, LINK_ELEMENT *before, LINK_ELEMENT *elem) 402{ 403 elem->prev = before; 404 elem->next = before->next; 405 elem->next->prev = elem; 406 before->next = elem; 407 if (before == anchor->last) anchor->last = elem; 408 verify_list("add", anchor); 409} 410#if CPDEBUG < 0 411#define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, (anchor), (elem)) 412#define APPEND_ELEM(anchor, before, elem) ADD_ELEM(iseq, (anchor), (before), (elem)) 413#endif 414 415static int 416iseq_add_mark_object(rb_iseq_t *iseq, VALUE v) 417{ 418 if (!SPECIAL_CONST_P(v)) { 419 rb_iseq_add_mark_object(iseq, v); 420 } 421 return COMPILE_OK; 422} 423 424#define ruby_sourcefile RSTRING_PTR(iseq->location.path) 425 426static int 427iseq_add_mark_object_compile_time(rb_iseq_t *iseq, VALUE v) 428{ 429 if (!SPECIAL_CONST_P(v)) { 430 rb_ary_push(iseq->compile_data->mark_ary, v); 431 } 432 return COMPILE_OK; 433} 434 435static int 436validate_label(st_data_t name, st_data_t label, st_data_t arg) 437{ 438 rb_iseq_t *iseq = (rb_iseq_t *)arg; 439 LABEL *lobj = (LABEL *)label; 440 if (!lobj->link.next) { 441 do { 442 int ret; 443 COMPILE_ERROR((ruby_sourcefile, lobj->position, 444 "%s: undefined label", rb_id2name((ID)name))); 445 if (ret) break; 446 } while (0); 447 } 448 return ST_CONTINUE; 449} 450 451static void 452validate_labels(rb_iseq_t *iseq, st_table *labels_table) 453{ 454 st_foreach(labels_table, validate_label, (st_data_t)iseq); 455 if (!NIL_P(iseq->compile_data->err_info)) { 456 rb_exc_raise(iseq->compile_data->err_info); 457 } 458} 459 460VALUE 461rb_iseq_compile_node(VALUE self, NODE *node) 462{ 463 DECL_ANCHOR(ret); 464 rb_iseq_t *iseq; 465 INIT_ANCHOR(ret); 466 GetISeqPtr(self, iseq); 467 468 if (node == 0) { 469 COMPILE(ret, "nil", node); 470 iseq_set_local_table(iseq, 0); 471 } 472 else if (nd_type(node) == NODE_SCOPE) { 473 /* iseq type of top, method, class, block */ 474 iseq_set_local_table(iseq, node->nd_tbl); 475 iseq_set_arguments(iseq, ret, node->nd_args); 476 477 switch (iseq->type) { 478 case ISEQ_TYPE_BLOCK: 479 { 480 LABEL *start = iseq->compile_data->start_label = NEW_LABEL(0); 481 LABEL *end = iseq->compile_data->end_label = NEW_LABEL(0); 482 483 ADD_LABEL(ret, start); 484 ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_B_CALL); 485 COMPILE(ret, "block body", node->nd_body); 486 ADD_LABEL(ret, end); 487 ADD_TRACE(ret, nd_line(node), RUBY_EVENT_B_RETURN); 488 489 /* wide range catch handler must put at last */ 490 ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, start); 491 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, end); 492 break; 493 } 494 case ISEQ_TYPE_CLASS: 495 { 496 ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CLASS); 497 COMPILE(ret, "scoped node", node->nd_body); 498 ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END); 499 break; 500 } 501 case ISEQ_TYPE_METHOD: 502 { 503 ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CALL); 504 COMPILE(ret, "scoped node", node->nd_body); 505 ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN); 506 break; 507 } 508 default: { 509 COMPILE(ret, "scoped node", node->nd_body); 510 break; 511 } 512 } 513 } 514 else { 515 switch (iseq->type) { 516 case ISEQ_TYPE_METHOD: 517 case ISEQ_TYPE_CLASS: 518 case ISEQ_TYPE_BLOCK: 519 case ISEQ_TYPE_EVAL: 520 case ISEQ_TYPE_MAIN: 521 case ISEQ_TYPE_TOP: 522 rb_compile_error(ERROR_ARGS "compile/should not be reached: %s:%d", 523 __FILE__, __LINE__); 524 break; 525 case ISEQ_TYPE_RESCUE: 526 iseq_set_exception_local_table(iseq); 527 COMPILE(ret, "rescue", node); 528 break; 529 case ISEQ_TYPE_ENSURE: 530 iseq_set_exception_local_table(iseq); 531 COMPILE_POPED(ret, "ensure", node); 532 break; 533 case ISEQ_TYPE_DEFINED_GUARD: 534 iseq_set_local_table(iseq, 0); 535 COMPILE(ret, "defined guard", node); 536 break; 537 default: 538 rb_bug("unknown scope"); 539 } 540 } 541 542 if (iseq->type == ISEQ_TYPE_RESCUE || iseq->type == ISEQ_TYPE_ENSURE) { 543 ADD_INSN2(ret, 0, getlocal, INT2FIX(2), INT2FIX(0)); 544 ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ ); 545 } 546 else { 547 ADD_INSN(ret, iseq->compile_data->last_line, leave); 548 } 549 550#if SUPPORT_JOKE 551 if (iseq->compile_data->labels_table) { 552 validate_labels(iseq, iseq->compile_data->labels_table); 553 } 554#endif 555 return iseq_setup(iseq, ret); 556} 557 558int 559rb_iseq_translate_threaded_code(rb_iseq_t *iseq) 560{ 561#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE 562 const void * const *table = rb_vm_get_insns_address_table(); 563 unsigned long i; 564 565 iseq->iseq_encoded = ALLOC_N(VALUE, iseq->iseq_size); 566 MEMCPY(iseq->iseq_encoded, iseq->iseq, VALUE, iseq->iseq_size); 567 568 for (i = 0; i < iseq->iseq_size; /* */ ) { 569 int insn = (int)iseq->iseq_encoded[i]; 570 int len = insn_len(insn); 571 iseq->iseq_encoded[i] = (VALUE)table[insn]; 572 i += len; 573 } 574#else 575 iseq->iseq_encoded = iseq->iseq; 576#endif 577 return COMPILE_OK; 578} 579 580/*********************************************/ 581/* definition of data structure for compiler */ 582/*********************************************/ 583 584static void * 585compile_data_alloc(rb_iseq_t *iseq, size_t size) 586{ 587 void *ptr = 0; 588 struct iseq_compile_data_storage *storage = 589 iseq->compile_data->storage_current; 590 591 if (storage->pos + size > storage->size) { 592 unsigned long alloc_size = storage->size * 2; 593 594 retry: 595 if (alloc_size < size) { 596 alloc_size *= 2; 597 goto retry; 598 } 599 storage->next = (void *)ALLOC_N(char, alloc_size + 600 sizeof(struct 601 iseq_compile_data_storage)); 602 storage = iseq->compile_data->storage_current = storage->next; 603 storage->next = 0; 604 storage->pos = 0; 605 storage->size = alloc_size; 606 storage->buff = (char *)(&storage->buff + 1); 607 } 608 609 ptr = (void *)&storage->buff[storage->pos]; 610 storage->pos += size; 611 return ptr; 612} 613 614static INSN * 615compile_data_alloc_insn(rb_iseq_t *iseq) 616{ 617 return (INSN *)compile_data_alloc(iseq, sizeof(INSN)); 618} 619 620static LABEL * 621compile_data_alloc_label(rb_iseq_t *iseq) 622{ 623 return (LABEL *)compile_data_alloc(iseq, sizeof(LABEL)); 624} 625 626static ADJUST * 627compile_data_alloc_adjust(rb_iseq_t *iseq) 628{ 629 return (ADJUST *)compile_data_alloc(iseq, sizeof(ADJUST)); 630} 631 632/* 633 * elem1, elemX => elem1, elem2, elemX 634 */ 635static void 636INSERT_ELEM_NEXT(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2) 637{ 638 elem2->next = elem1->next; 639 elem2->prev = elem1; 640 elem1->next = elem2; 641 if (elem2->next) { 642 elem2->next->prev = elem2; 643 } 644} 645 646#if 0 /* unused */ 647/* 648 * elemX, elem1 => elemX, elem2, elem1 649 */ 650static void 651INSERT_ELEM_PREV(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2) 652{ 653 elem2->prev = elem1->prev; 654 elem2->next = elem1; 655 elem1->prev = elem2; 656 if (elem2->prev) { 657 elem2->prev->next = elem2; 658 } 659} 660#endif 661 662/* 663 * elemX, elem1, elemY => elemX, elem2, elemY 664 */ 665static void 666REPLACE_ELEM(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2) 667{ 668 elem2->prev = elem1->prev; 669 elem2->next = elem1->next; 670 if (elem1->prev) { 671 elem1->prev->next = elem2; 672 } 673 if (elem1->next) { 674 elem1->next->prev = elem2; 675 } 676} 677 678static void 679REMOVE_ELEM(LINK_ELEMENT *elem) 680{ 681 elem->prev->next = elem->next; 682 if (elem->next) { 683 elem->next->prev = elem->prev; 684 } 685} 686 687static LINK_ELEMENT * 688FIRST_ELEMENT(LINK_ANCHOR *anchor) 689{ 690 return anchor->anchor.next; 691} 692 693#if 0 /* unused */ 694static LINK_ELEMENT * 695LAST_ELEMENT(LINK_ANCHOR *anchor) 696{ 697 return anchor->last; 698} 699#endif 700 701static LINK_ELEMENT * 702POP_ELEMENT(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor) 703{ 704 LINK_ELEMENT *elem = anchor->last; 705 anchor->last = anchor->last->prev; 706 anchor->last->next = 0; 707 verify_list("pop", anchor); 708 return elem; 709} 710#if CPDEBUG < 0 711#define POP_ELEMENT(anchor) POP_ELEMENT(iseq, (anchor)) 712#endif 713 714#if 0 /* unused */ 715static LINK_ELEMENT * 716SHIFT_ELEMENT(LINK_ANCHOR *anchor) 717{ 718 LINK_ELEMENT *elem = anchor->anchor.next; 719 if (elem) { 720 anchor->anchor.next = elem->next; 721 } 722 return elem; 723} 724#endif 725 726#if 0 /* unused */ 727static int 728LIST_SIZE(LINK_ANCHOR *anchor) 729{ 730 LINK_ELEMENT *elem = anchor->anchor.next; 731 int size = 0; 732 while (elem) { 733 size += 1; 734 elem = elem->next; 735 } 736 return size; 737} 738#endif 739 740static int 741LIST_SIZE_ZERO(LINK_ANCHOR *anchor) 742{ 743 if (anchor->anchor.next == 0) { 744 return 1; 745 } 746 else { 747 return 0; 748 } 749} 750 751/* 752 * anc1: e1, e2, e3 753 * anc2: e4, e5 754 *#=> 755 * anc1: e1, e2, e3, e4, e5 756 * anc2: e4, e5 (broken) 757 */ 758static void 759APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc1, LINK_ANCHOR *anc2) 760{ 761 if (anc2->anchor.next) { 762 anc1->last->next = anc2->anchor.next; 763 anc2->anchor.next->prev = anc1->last; 764 anc1->last = anc2->last; 765 } 766 verify_list("append", anc1); 767} 768#if CPDEBUG < 0 769#define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2)) 770#endif 771 772/* 773 * anc1: e1, e2, e3 774 * anc2: e4, e5 775 *#=> 776 * anc1: e4, e5, e1, e2, e3 777 * anc2: e4, e5 (broken) 778 */ 779static void 780INSERT_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc1, LINK_ANCHOR *anc2) 781{ 782 if (anc2->anchor.next) { 783 LINK_ELEMENT *first = anc1->anchor.next; 784 anc1->anchor.next = anc2->anchor.next; 785 anc1->anchor.next->prev = &anc1->anchor; 786 anc2->last->next = first; 787 if (first) { 788 first->prev = anc2->last; 789 } 790 else { 791 anc1->last = anc2->last; 792 } 793 } 794 795 verify_list("append", anc1); 796} 797#if CPDEBUG < 0 798#define INSERT_LIST(anc1, anc2) INSERT_LIST(iseq, (anc1), (anc2)) 799#endif 800 801#if 0 /* unused */ 802/* 803 * anc1: e1, e2, e3 804 * anc2: e4, e5 805 *#=> 806 * anc1: e4, e5 807 * anc2: e1, e2, e3 808 */ 809static void 810SWAP_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc1, LINK_ANCHOR *anc2) 811{ 812 LINK_ANCHOR tmp = *anc2; 813 814 /* it has bug */ 815 *anc2 = *anc1; 816 *anc1 = tmp; 817 818 verify_list("swap1", anc1); 819 verify_list("swap2", anc2); 820} 821#if CPDEBUG < 0 822#define SWAP_LIST(anc1, anc2) SWAP_LIST(iseq, (anc1), (anc2)) 823#endif 824 825static LINK_ANCHOR * 826REVERSE_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc) 827{ 828 LINK_ELEMENT *first, *last, *elem, *e; 829 first = &anc->anchor; 830 elem = first->next; 831 last = anc->last; 832 833 if (elem != 0) { 834 anc->anchor.next = last; 835 anc->last = elem; 836 } 837 else { 838 /* null list */ 839 return anc; 840 } 841 while (elem) { 842 e = elem->next; 843 elem->next = elem->prev; 844 elem->prev = e; 845 elem = e; 846 } 847 848 first->next = last; 849 last->prev = first; 850 anc->last->next = 0; 851 852 verify_list("reverse", anc); 853 return anc; 854} 855#if CPDEBUG < 0 856#define REVERSE_LIST(anc) REVERSE_LIST(iseq, (anc)) 857#endif 858#endif 859 860#if CPDEBUG && 0 861static void 862debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor) 863{ 864 LINK_ELEMENT *list = FIRST_ELEMENT(anchor); 865 printf("----\n"); 866 printf("anch: %p, frst: %p, last: %p\n", &anchor->anchor, 867 anchor->anchor.next, anchor->last); 868 while (list) { 869 printf("curr: %p, next: %p, prev: %p, type: %d\n", list, list->next, 870 list->prev, FIX2INT(list->type)); 871 list = list->next; 872 } 873 printf("----\n"); 874 875 dump_disasm_list(anchor->anchor.next); 876 verify_list("debug list", anchor); 877} 878#if CPDEBUG < 0 879#define debug_list(anc) debug_list(iseq, (anc)) 880#endif 881#endif 882 883static LABEL * 884new_label_body(rb_iseq_t *iseq, long line) 885{ 886 LABEL *labelobj = compile_data_alloc_label(iseq); 887 888 labelobj->link.type = ISEQ_ELEMENT_LABEL; 889 labelobj->link.next = 0; 890 891 labelobj->label_no = iseq->compile_data->label_no++; 892 labelobj->sc_state = 0; 893 labelobj->sp = -1; 894 return labelobj; 895} 896 897static ADJUST * 898new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line) 899{ 900 ADJUST *adjust = compile_data_alloc_adjust(iseq); 901 adjust->link.type = ISEQ_ELEMENT_ADJUST; 902 adjust->link.next = 0; 903 adjust->label = label; 904 adjust->line_no = line; 905 return adjust; 906} 907 908static INSN * 909new_insn_core(rb_iseq_t *iseq, int line_no, 910 int insn_id, int argc, VALUE *argv) 911{ 912 INSN *iobj = compile_data_alloc_insn(iseq); 913 /* printf("insn_id: %d, line: %d\n", insn_id, line_no); */ 914 915 iobj->link.type = ISEQ_ELEMENT_INSN; 916 iobj->link.next = 0; 917 iobj->insn_id = insn_id; 918 iobj->line_no = line_no; 919 iobj->operands = argv; 920 iobj->operand_size = argc; 921 iobj->sc_state = 0; 922 return iobj; 923} 924 925static INSN * 926new_insn_body(rb_iseq_t *iseq, int line_no, int insn_id, int argc, ...) 927{ 928 VALUE *operands = 0; 929 va_list argv; 930 if (argc > 0) { 931 int i; 932 va_init_list(argv, argc); 933 operands = (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * argc); 934 for (i = 0; i < argc; i++) { 935 VALUE v = va_arg(argv, VALUE); 936 operands[i] = v; 937 } 938 va_end(argv); 939 } 940 return new_insn_core(iseq, line_no, insn_id, argc, operands); 941} 942 943static rb_call_info_t * 944new_callinfo(rb_iseq_t *iseq, ID mid, int argc, VALUE block, unsigned long flag) 945{ 946 rb_call_info_t *ci = (rb_call_info_t *)compile_data_alloc(iseq, sizeof(rb_call_info_t)); 947 ci->mid = mid; 948 ci->flag = flag; 949 ci->orig_argc = argc; 950 ci->argc = argc; 951 952 if (block) { 953 GetISeqPtr(block, ci->blockiseq); 954 } 955 else { 956 ci->blockiseq = 0; 957 if (!(ci->flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG))) { 958 ci->flag |= VM_CALL_ARGS_SKIP_SETUP; 959 } 960 } 961 ci->vmstat = 0; 962 ci->blockptr = 0; 963 ci->recv = Qundef; 964 ci->call = 0; /* TODO: should set default function? */ 965 966 ci->aux.index = iseq->callinfo_size++; 967 968 return ci; 969} 970 971static INSN * 972new_insn_send(rb_iseq_t *iseq, int line_no, VALUE id, VALUE argc, VALUE block, VALUE flag) 973{ 974 VALUE *operands = (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 1); 975 operands[0] = (VALUE)new_callinfo(iseq, SYM2ID(id), FIX2INT(argc), block, FIX2INT(flag)); 976 return new_insn_core(iseq, line_no, BIN(send), 1, operands); 977} 978 979static VALUE 980new_child_iseq(rb_iseq_t *iseq, NODE *node, 981 VALUE name, VALUE parent, enum iseq_type type, int line_no) 982{ 983 VALUE ret; 984 985 debugs("[new_child_iseq]> ---------------------------------------\n"); 986 ret = rb_iseq_new_with_opt(node, name, 987 iseq_path(iseq->self), iseq_absolute_path(iseq->self), 988 INT2FIX(line_no), parent, type, iseq->compile_data->option); 989 debugs("[new_child_iseq]< ---------------------------------------\n"); 990 iseq_add_mark_object(iseq, ret); 991 return ret; 992} 993 994static int 995iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor) 996{ 997 /* debugs("[compile step 2] (iseq_array_to_linkedlist)\n"); */ 998 999 if (compile_debug > 5) 1000 dump_disasm_list(FIRST_ELEMENT(anchor)); 1001 1002 debugs("[compile step 3.1 (iseq_optimize)]\n"); 1003 iseq_optimize(iseq, anchor); 1004 1005 if (compile_debug > 5) 1006 dump_disasm_list(FIRST_ELEMENT(anchor)); 1007 1008 if (iseq->compile_data->option->instructions_unification) { 1009 debugs("[compile step 3.2 (iseq_insns_unification)]\n"); 1010 iseq_insns_unification(iseq, anchor); 1011 if (compile_debug > 5) 1012 dump_disasm_list(FIRST_ELEMENT(anchor)); 1013 } 1014 1015 if (iseq->compile_data->option->stack_caching) { 1016 debugs("[compile step 3.3 (iseq_set_sequence_stackcaching)]\n"); 1017 iseq_set_sequence_stackcaching(iseq, anchor); 1018 if (compile_debug > 5) 1019 dump_disasm_list(FIRST_ELEMENT(anchor)); 1020 } 1021 1022 debugs("[compile step 4.1 (iseq_set_sequence)]\n"); 1023 iseq_set_sequence(iseq, anchor); 1024 if (compile_debug > 5) 1025 dump_disasm_list(FIRST_ELEMENT(anchor)); 1026 1027 debugs("[compile step 4.2 (iseq_set_exception_table)]\n"); 1028 iseq_set_exception_table(iseq); 1029 1030 debugs("[compile step 4.3 (set_optargs_table)] \n"); 1031 iseq_set_optargs_table(iseq); 1032 1033 debugs("[compile step 5 (iseq_translate_threaded_code)] \n"); 1034 rb_iseq_translate_threaded_code(iseq); 1035 1036 if (compile_debug > 1) { 1037 VALUE str = rb_iseq_disasm(iseq->self); 1038 printf("%s\n", StringValueCStr(str)); 1039 fflush(stdout); 1040 } 1041 debugs("[compile step: finish]\n"); 1042 1043 return 0; 1044} 1045 1046static int 1047iseq_set_exception_local_table(rb_iseq_t *iseq) 1048{ 1049 ID id_dollar_bang; 1050 1051 CONST_ID(id_dollar_bang, "#$!"); 1052 iseq->local_table = (ID *)ALLOC_N(ID, 1); 1053 iseq->local_table_size = 1; 1054 iseq->local_size = iseq->local_table_size + 1; 1055 iseq->local_table[0] = id_dollar_bang; 1056 return COMPILE_OK; 1057} 1058 1059static int 1060get_lvar_level(rb_iseq_t *iseq) 1061{ 1062 int lev = 0; 1063 while (iseq != iseq->local_iseq) { 1064 lev++; 1065 iseq = iseq->parent_iseq; 1066 } 1067 return lev; 1068} 1069 1070static int 1071get_dyna_var_idx_at_raw(rb_iseq_t *iseq, ID id) 1072{ 1073 int i; 1074 1075 for (i = 0; i < iseq->local_table_size; i++) { 1076 if (iseq->local_table[i] == id) { 1077 return i; 1078 } 1079 } 1080 return -1; 1081} 1082 1083static int 1084get_local_var_idx(rb_iseq_t *iseq, ID id) 1085{ 1086 int idx = get_dyna_var_idx_at_raw(iseq->local_iseq, id); 1087 1088 if (idx < 0) { 1089 rb_bug("get_local_var_idx: %d", idx); 1090 } 1091 1092 return idx; 1093} 1094 1095static int 1096get_dyna_var_idx(rb_iseq_t *iseq, ID id, int *level, int *ls) 1097{ 1098 int lv = 0, idx = -1; 1099 1100 while (iseq) { 1101 idx = get_dyna_var_idx_at_raw(iseq, id); 1102 if (idx >= 0) { 1103 break; 1104 } 1105 iseq = iseq->parent_iseq; 1106 lv++; 1107 } 1108 1109 if (idx < 0) { 1110 rb_bug("get_dyna_var_idx: -1"); 1111 } 1112 1113 *level = lv; 1114 *ls = iseq->local_size; 1115 return idx; 1116} 1117 1118static int 1119iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) 1120{ 1121 debugs("iseq_set_arguments: %s\n", node_args ? "" : "0"); 1122 1123 if (node_args) { 1124 struct rb_args_info *args = node_args->nd_ainfo; 1125 ID rest_id = 0; 1126 int last_comma = 0; 1127 ID block_id = 0; 1128 1129 if (nd_type(node_args) != NODE_ARGS) { 1130 rb_bug("iseq_set_arguments: NODE_ARGS is expected, but %s", 1131 ruby_node_name(nd_type(node_args))); 1132 } 1133 1134 1135 iseq->argc = (int)args->pre_args_num; 1136 debugs(" - argc: %d\n", iseq->argc); 1137 1138 rest_id = args->rest_arg; 1139 if (rest_id == 1) { 1140 last_comma = 1; 1141 rest_id = 0; 1142 } 1143 block_id = args->block_arg; 1144 1145 if (args->first_post_arg) { 1146 iseq->arg_post_start = get_dyna_var_idx_at_raw(iseq, args->first_post_arg); 1147 iseq->arg_post_len = args->post_args_num; 1148 } 1149 1150 if (args->opt_args) { 1151 NODE *node = args->opt_args; 1152 LABEL *label; 1153 VALUE labels = rb_ary_tmp_new(1); 1154 int i = 0, j; 1155 1156 while (node) { 1157 label = NEW_LABEL(nd_line(node)); 1158 rb_ary_push(labels, (VALUE)label | 1); 1159 ADD_LABEL(optargs, label); 1160 COMPILE_POPED(optargs, "optarg", node->nd_body); 1161 node = node->nd_next; 1162 i += 1; 1163 } 1164 1165 /* last label */ 1166 label = NEW_LABEL(nd_line(node_args)); 1167 rb_ary_push(labels, (VALUE)label | 1); 1168 ADD_LABEL(optargs, label); 1169 i += 1; 1170 1171 iseq->arg_opts = i; 1172 iseq->arg_opt_table = ALLOC_N(VALUE, i); 1173 MEMCPY(iseq->arg_opt_table, RARRAY_PTR(labels), VALUE, i); 1174 for (j = 0; j < i; j++) { 1175 iseq->arg_opt_table[j] &= ~1; 1176 } 1177 rb_ary_clear(labels); 1178 } 1179 else { 1180 iseq->arg_opts = 0; 1181 } 1182 1183 if (args->kw_args) { 1184 NODE *node = args->kw_args; 1185 VALUE keywords = rb_ary_tmp_new(1); 1186 int i = 0, j; 1187 1188 iseq->arg_keyword = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_vid); 1189 COMPILE(optargs, "kwarg", args->kw_rest_arg); 1190 while (node) { 1191 rb_ary_push(keywords, INT2FIX(node->nd_body->nd_vid)); 1192 COMPILE_POPED(optargs, "kwarg", node); /* nd_type(node) == NODE_KW_ARG */ 1193 node = node->nd_next; 1194 i += 1; 1195 } 1196 iseq->arg_keyword_check = (args->kw_rest_arg->nd_vid & ID_SCOPE_MASK) == ID_JUNK; 1197 iseq->arg_keywords = i; 1198 iseq->arg_keyword_table = ALLOC_N(ID, i); 1199 for (j = 0; j < i; j++) { 1200 iseq->arg_keyword_table[j] = FIX2INT(RARRAY_PTR(keywords)[j]); 1201 } 1202 ADD_INSN(optargs, nd_line(args->kw_args), pop); 1203 } 1204 else if (args->kw_rest_arg) { 1205 iseq->arg_keyword = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_vid); 1206 COMPILE(optargs, "kwarg", args->kw_rest_arg); 1207 ADD_INSN(optargs, nd_line(args->kw_rest_arg), pop); 1208 } 1209 else { 1210 iseq->arg_keyword = -1; 1211 } 1212 1213 if (args->pre_init) { /* m_init */ 1214 COMPILE_POPED(optargs, "init arguments (m)", args->pre_init); 1215 } 1216 if (args->post_init) { /* p_init */ 1217 COMPILE_POPED(optargs, "init arguments (p)", args->post_init); 1218 } 1219 1220 if (rest_id) { 1221 iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, rest_id); 1222 1223 if (iseq->arg_rest == -1) { 1224 rb_bug("arg_rest: -1"); 1225 } 1226 1227 if (iseq->arg_post_start == 0) { 1228 iseq->arg_post_start = iseq->arg_rest + 1; 1229 } 1230 } 1231 1232 if (block_id) { 1233 iseq->arg_block = get_dyna_var_idx_at_raw(iseq, block_id); 1234 } 1235 1236 if (iseq->arg_opts != 0 || iseq->arg_post_len != 0 || 1237 iseq->arg_rest != -1 || iseq->arg_block != -1 || 1238 iseq->arg_keyword != -1) { 1239 iseq->arg_simple = 0; 1240 1241 /* set arg_size: size of arguments */ 1242 if (iseq->arg_keyword != -1) { 1243 iseq->arg_size = iseq->arg_keyword + 1; 1244 } 1245 else if (iseq->arg_block != -1) { 1246 iseq->arg_size = iseq->arg_block + 1; 1247 } 1248 else if (iseq->arg_post_len) { 1249 iseq->arg_size = iseq->arg_post_start + iseq->arg_post_len; 1250 } 1251 else if (iseq->arg_rest != -1) { 1252 iseq->arg_size = iseq->arg_rest + 1; 1253 } 1254 else if (iseq->arg_opts) { 1255 iseq->arg_size = iseq->argc + iseq->arg_opts - 1; 1256 } 1257 else { 1258 iseq->arg_size = iseq->argc; 1259 } 1260 } 1261 else { 1262 iseq->arg_simple = 1; 1263 iseq->arg_size = iseq->argc; 1264 } 1265 1266 if (iseq->type == ISEQ_TYPE_BLOCK) { 1267 if (iseq->arg_opts == 0 && iseq->arg_post_len == 0 && 1268 iseq->arg_rest == -1 && iseq->arg_keyword == -1) { 1269 if (iseq->argc == 1 && last_comma == 0) { 1270 /* {|a|} */ 1271 iseq->arg_simple |= 0x02; 1272 } 1273 } 1274 } 1275 } 1276 else { 1277 iseq->arg_simple = 1; 1278 } 1279 1280 return COMPILE_OK; 1281} 1282 1283static int 1284iseq_set_local_table(rb_iseq_t *iseq, ID *tbl) 1285{ 1286 int size; 1287 1288 if (tbl) { 1289 size = (int)*tbl; 1290 tbl++; 1291 } 1292 else { 1293 size = 0; 1294 } 1295 1296 if (size > 0) { 1297 iseq->local_table = (ID *)ALLOC_N(ID, size); 1298 MEMCPY(iseq->local_table, tbl, ID, size); 1299 } 1300 1301 iseq->local_size = iseq->local_table_size = size; 1302 iseq->local_size += 1; 1303 /* 1304 if (lfp == dfp ) { // top, class, method 1305 dfp[-1]: svar 1306 else { // block 1307 dfp[-1]: cref 1308 } 1309 */ 1310 1311 debugs("iseq_set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size); 1312 return COMPILE_OK; 1313} 1314 1315static int 1316cdhash_cmp(VALUE val, VALUE lit) 1317{ 1318 if (val == lit) return 0; 1319 if (SPECIAL_CONST_P(lit)) { 1320 return val != lit; 1321 } 1322 if (SPECIAL_CONST_P(val) || BUILTIN_TYPE(val) != BUILTIN_TYPE(lit)) { 1323 return -1; 1324 } 1325 if (BUILTIN_TYPE(lit) == T_STRING) { 1326 return rb_str_hash_cmp(lit, val); 1327 } 1328 return !rb_eql(lit, val); 1329} 1330 1331static st_index_t 1332cdhash_hash(VALUE a) 1333{ 1334 if (SPECIAL_CONST_P(a)) return (st_index_t)a; 1335 if (RB_TYPE_P(a, T_STRING)) return rb_str_hash(a); 1336 { 1337 VALUE hval = rb_hash(a); 1338 return (st_index_t)FIX2LONG(hval); 1339 } 1340} 1341 1342static const struct st_hash_type cdhash_type = { 1343 cdhash_cmp, 1344 cdhash_hash, 1345}; 1346 1347struct cdhash_set_label_struct { 1348 VALUE hash; 1349 int pos; 1350 int len; 1351}; 1352 1353static int 1354cdhash_set_label_i(VALUE key, VALUE val, void *ptr) 1355{ 1356 struct cdhash_set_label_struct *data = (struct cdhash_set_label_struct *)ptr; 1357 LABEL *lobj = (LABEL *)(val & ~1); 1358 rb_hash_aset(data->hash, key, INT2FIX(lobj->position - (data->pos+data->len))); 1359 return ST_CONTINUE; 1360} 1361 1362/** 1363 ruby insn object list -> raw instruction sequence 1364 */ 1365static int 1366iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) 1367{ 1368 LABEL *lobj; 1369 INSN *iobj; 1370 struct iseq_line_info_entry *line_info_table; 1371 unsigned int last_line = 0; 1372 LINK_ELEMENT *list; 1373 VALUE *generated_iseq; 1374 1375 int k, pos, sp, stack_max = 0, line = 0; 1376 1377 /* set label position */ 1378 list = FIRST_ELEMENT(anchor); 1379 k = pos = 0; 1380 while (list) { 1381 switch (list->type) { 1382 case ISEQ_ELEMENT_INSN: 1383 { 1384 iobj = (INSN *)list; 1385 line = iobj->line_no; 1386 pos += insn_data_length(iobj); 1387 k++; 1388 break; 1389 } 1390 case ISEQ_ELEMENT_LABEL: 1391 { 1392 lobj = (LABEL *)list; 1393 lobj->position = pos; 1394 lobj->set = TRUE; 1395 break; 1396 } 1397 case ISEQ_ELEMENT_NONE: 1398 { 1399 /* ignore */ 1400 break; 1401 } 1402 case ISEQ_ELEMENT_ADJUST: 1403 { 1404 ADJUST *adjust = (ADJUST *)list; 1405 if (adjust->line_no != -1) { 1406 pos += 2 /* insn + 1 operand */; 1407 k++; 1408 } 1409 break; 1410 } 1411 default: 1412 dump_disasm_list(FIRST_ELEMENT(anchor)); 1413 dump_disasm_list(list); 1414 rb_compile_error(RSTRING_PTR(iseq->location.path), line, 1415 "error: set_sequence"); 1416 break; 1417 } 1418 list = list->next; 1419 } 1420 1421 /* make instruction sequence */ 1422 generated_iseq = ALLOC_N(VALUE, pos); 1423 line_info_table = ALLOC_N(struct iseq_line_info_entry, k); 1424 iseq->ic_entries = ALLOC_N(struct iseq_inline_cache_entry, iseq->ic_size); 1425 MEMZERO(iseq->ic_entries, struct iseq_inline_cache_entry, iseq->ic_size); 1426 iseq->callinfo_entries = ALLOC_N(rb_call_info_t, iseq->callinfo_size); 1427 /* MEMZERO(iseq->callinfo_entries, rb_call_info_t, iseq->callinfo_size); */ 1428 1429 list = FIRST_ELEMENT(anchor); 1430 k = pos = sp = 0; 1431 1432 while (list) { 1433 switch (list->type) { 1434 case ISEQ_ELEMENT_INSN: 1435 { 1436 int j, len, insn; 1437 const char *types; 1438 VALUE *operands; 1439 1440 iobj = (INSN *)list; 1441 1442 /* update sp */ 1443 sp = calc_sp_depth(sp, iobj); 1444 if (sp > stack_max) { 1445 stack_max = sp; 1446 } 1447 1448 /* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */ 1449 operands = iobj->operands; 1450 insn = iobj->insn_id; 1451 generated_iseq[pos] = insn; 1452 types = insn_op_types(insn); 1453 len = insn_len(insn); 1454 1455 /* operand check */ 1456 if (iobj->operand_size != len - 1) { 1457 /* printf("operand size miss! (%d, %d)\n", iobj->operand_size, len); */ 1458 dump_disasm_list(list); 1459 rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no, 1460 "operand size miss! (%d for %d)", 1461 iobj->operand_size, len - 1); 1462 xfree(generated_iseq); 1463 xfree(line_info_table); 1464 return 0; 1465 } 1466 1467 for (j = 0; types[j]; j++) { 1468 char type = types[j]; 1469 /* printf("--> [%c - (%d-%d)]\n", type, k, j); */ 1470 switch (type) { 1471 case TS_OFFSET: 1472 { 1473 /* label(destination position) */ 1474 lobj = (LABEL *)operands[j]; 1475 if (!lobj->set) { 1476 rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no, 1477 "unknown label"); 1478 } 1479 if (lobj->sp == -1) { 1480 lobj->sp = sp; 1481 } 1482 generated_iseq[pos + 1 + j] = lobj->position - (pos + len); 1483 break; 1484 } 1485 case TS_CDHASH: 1486 { 1487 VALUE map = operands[j]; 1488 struct cdhash_set_label_struct data; 1489 data.hash = map; 1490 data.pos = pos; 1491 data.len = len; 1492 rb_hash_foreach(map, cdhash_set_label_i, (VALUE)&data); 1493 1494 hide_obj(map); 1495 generated_iseq[pos + 1 + j] = map; 1496 break; 1497 } 1498 case TS_LINDEX: 1499 case TS_NUM: /* ulong */ 1500 generated_iseq[pos + 1 + j] = FIX2INT(operands[j]); 1501 break; 1502 case TS_ISEQ: /* iseq */ 1503 { 1504 VALUE v = operands[j]; 1505 rb_iseq_t *block = 0; 1506 if (v) { 1507 GetISeqPtr(v, block); 1508 } 1509 generated_iseq[pos + 1 + j] = (VALUE)block; 1510 break; 1511 } 1512 case TS_VALUE: /* VALUE */ 1513 { 1514 VALUE v = operands[j]; 1515 generated_iseq[pos + 1 + j] = v; 1516 /* to mark ruby object */ 1517 iseq_add_mark_object(iseq, v); 1518 break; 1519 } 1520 case TS_IC: /* inline cache */ 1521 { 1522 int ic_index = FIX2INT(operands[j]); 1523 IC ic = &iseq->ic_entries[ic_index]; 1524 if (UNLIKELY(ic_index >= iseq->ic_size)) { 1525 rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->ic_size); 1526 } 1527 generated_iseq[pos + 1 + j] = (VALUE)ic; 1528 break; 1529 } 1530 case TS_CALLINFO: /* call info */ 1531 { 1532 rb_call_info_t *base_ci = (rb_call_info_t *)operands[j]; 1533 rb_call_info_t *ci = &iseq->callinfo_entries[base_ci->aux.index]; 1534 *ci = *base_ci; 1535 1536 if (UNLIKELY(base_ci->aux.index >= iseq->callinfo_size)) { 1537 rb_bug("iseq_set_sequence: ci_index overflow: index: %d, size: %d", base_ci->argc, iseq->callinfo_size); 1538 } 1539 generated_iseq[pos + 1 + j] = (VALUE)ci; 1540 break; 1541 } 1542 case TS_ID: /* ID */ 1543 generated_iseq[pos + 1 + j] = SYM2ID(operands[j]); 1544 break; 1545 case TS_GENTRY: 1546 { 1547 struct rb_global_entry *entry = 1548 (struct rb_global_entry *)(operands[j] & (~1)); 1549 generated_iseq[pos + 1 + j] = (VALUE)entry; 1550 } 1551 break; 1552 default: 1553 rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no, 1554 "unknown operand type: %c", type); 1555 xfree(generated_iseq); 1556 xfree(line_info_table); 1557 return 0; 1558 } 1559 } 1560 if (last_line != iobj->line_no) { 1561 line_info_table[k].line_no = last_line = iobj->line_no; 1562 line_info_table[k].position = pos; 1563 k++; 1564 } 1565 pos += len; 1566 break; 1567 } 1568 case ISEQ_ELEMENT_LABEL: 1569 { 1570 lobj = (LABEL *)list; 1571 if (lobj->sp == -1) { 1572 lobj->sp = sp; 1573 } 1574 else { 1575 sp = lobj->sp; 1576 } 1577 break; 1578 } 1579 case ISEQ_ELEMENT_ADJUST: 1580 { 1581 ADJUST *adjust = (ADJUST *)list; 1582 int orig_sp = sp; 1583 1584 if (adjust->label) { 1585 sp = adjust->label->sp; 1586 } 1587 else { 1588 sp = 0; 1589 } 1590 1591 if (adjust->line_no != -1) { 1592 if (orig_sp - sp > 0) { 1593 if (last_line != (unsigned int)adjust->line_no) { 1594 line_info_table[k].line_no = last_line = adjust->line_no; 1595 line_info_table[k].position = pos; 1596 k++; 1597 } 1598 generated_iseq[pos++] = BIN(adjuststack); 1599 generated_iseq[pos++] = orig_sp - sp; 1600 } 1601 else if (orig_sp - sp == 0) { 1602 /* jump to next insn */ 1603 if (last_line != (unsigned int)adjust->line_no) { 1604 line_info_table[k].line_no = last_line = adjust->line_no; 1605 line_info_table[k].position = pos; 1606 k++; 1607 } 1608 generated_iseq[pos++] = BIN(jump); 1609 generated_iseq[pos++] = 0; 1610 } 1611 else { 1612 rb_bug("iseq_set_sequence: adjust bug"); 1613 } 1614 } 1615 break; 1616 } 1617 default: 1618 /* ignore */ 1619 break; 1620 } 1621 list = list->next; 1622 } 1623 1624#if 0 /* XXX */ 1625 /* this check need dead code elimination */ 1626 if (sp != 1) { 1627 rb_bug("SP is not 0 on %s (%d)\n", RSTRING_PTR(iseq->name), sp); 1628 } 1629#endif 1630 1631 iseq->iseq = (void *)generated_iseq; 1632 iseq->iseq_size = pos; 1633 iseq->stack_max = stack_max; 1634 1635 line_info_table = ruby_xrealloc(line_info_table, k * sizeof(struct iseq_line_info_entry)); 1636 iseq->line_info_table = line_info_table; 1637 iseq->line_info_size = k; 1638 1639 return COMPILE_OK; 1640} 1641 1642static int 1643label_get_position(LABEL *lobj) 1644{ 1645 return lobj->position; 1646} 1647 1648static int 1649label_get_sp(LABEL *lobj) 1650{ 1651 return lobj->sp; 1652} 1653 1654static int 1655iseq_set_exception_table(rb_iseq_t *iseq) 1656{ 1657 VALUE *tptr, *ptr; 1658 int tlen, i; 1659 struct iseq_catch_table_entry *entry; 1660 1661 tlen = (int)RARRAY_LEN(iseq->compile_data->catch_table_ary); 1662 tptr = RARRAY_PTR(iseq->compile_data->catch_table_ary); 1663 1664 iseq->catch_table = tlen ? ALLOC_N(struct iseq_catch_table_entry, tlen) : 0; 1665 iseq->catch_table_size = tlen; 1666 1667 for (i = 0; i < tlen; i++) { 1668 ptr = RARRAY_PTR(tptr[i]); 1669 entry = &iseq->catch_table[i]; 1670 entry->type = (enum catch_type)(ptr[0] & 0xffff); 1671 entry->start = label_get_position((LABEL *)(ptr[1] & ~1)); 1672 entry->end = label_get_position((LABEL *)(ptr[2] & ~1)); 1673 entry->iseq = ptr[3]; 1674 1675 /* register iseq as mark object */ 1676 if (entry->iseq != 0) { 1677 iseq_add_mark_object(iseq, entry->iseq); 1678 } 1679 1680 /* stack depth */ 1681 if (ptr[4]) { 1682 LABEL *lobj = (LABEL *)(ptr[4] & ~1); 1683 entry->cont = label_get_position(lobj); 1684 entry->sp = label_get_sp(lobj); 1685 1686 /* TODO: Dirty Hack! Fix me */ 1687 if (entry->type == CATCH_TYPE_RESCUE || 1688 entry->type == CATCH_TYPE_BREAK || 1689 entry->type == CATCH_TYPE_NEXT) { 1690 entry->sp--; 1691 } 1692 } 1693 else { 1694 entry->cont = 0; 1695 } 1696 } 1697 1698 iseq->compile_data->catch_table_ary = 0; /* free */ 1699 return COMPILE_OK; 1700} 1701 1702/* 1703 * set optional argument table 1704 * def foo(a, b=expr1, c=expr2) 1705 * => 1706 * b: 1707 * expr1 1708 * c: 1709 * expr2 1710 */ 1711static int 1712iseq_set_optargs_table(rb_iseq_t *iseq) 1713{ 1714 int i; 1715 1716 if (iseq->arg_opts != 0) { 1717 for (i = 0; i < iseq->arg_opts; i++) { 1718 iseq->arg_opt_table[i] = 1719 label_get_position((LABEL *)iseq->arg_opt_table[i]); 1720 } 1721 } 1722 return COMPILE_OK; 1723} 1724 1725static LINK_ELEMENT * 1726get_destination_insn(INSN *iobj) 1727{ 1728 LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0); 1729 LINK_ELEMENT *list; 1730 1731 list = lobj->link.next; 1732 while (list) { 1733 if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) { 1734 break; 1735 } 1736 list = list->next; 1737 } 1738 return list; 1739} 1740 1741static LINK_ELEMENT * 1742get_next_insn(INSN *iobj) 1743{ 1744 LINK_ELEMENT *list = iobj->link.next; 1745 1746 while (list) { 1747 if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) { 1748 return list; 1749 } 1750 list = list->next; 1751 } 1752 return 0; 1753} 1754 1755static LINK_ELEMENT * 1756get_prev_insn(INSN *iobj) 1757{ 1758 LINK_ELEMENT *list = iobj->link.prev; 1759 1760 while (list) { 1761 if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) { 1762 return list; 1763 } 1764 list = list->prev; 1765 } 1766 return 0; 1767} 1768 1769static int 1770iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt) 1771{ 1772 INSN *iobj = (INSN *)list; 1773 again: 1774 if (iobj->insn_id == BIN(jump)) { 1775 INSN *niobj, *diobj, *piobj; 1776 /* 1777 * useless jump elimination: 1778 * jump LABEL1 1779 * ... 1780 * LABEL1: 1781 * jump LABEL2 1782 * 1783 * => in this case, first jump instruction should jump to 1784 * LABEL2 directly 1785 */ 1786 diobj = (INSN *)get_destination_insn(iobj); 1787 niobj = (INSN *)get_next_insn(iobj); 1788 1789 if (diobj == niobj) { 1790 /* 1791 * jump LABEL 1792 * LABEL: 1793 * => 1794 * LABEL: 1795 */ 1796 REMOVE_ELEM(&iobj->link); 1797 } 1798 else if (iobj != diobj && diobj->insn_id == BIN(jump)) { 1799 if (OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0)) { 1800 OPERAND_AT(iobj, 0) = OPERAND_AT(diobj, 0); 1801 goto again; 1802 } 1803 } 1804 else if (diobj->insn_id == BIN(leave)) { 1805 /* 1806 * jump LABEL 1807 * ... 1808 * LABEL: 1809 * leave 1810 * => 1811 * leave 1812 * ... 1813 * LABEL: 1814 * leave 1815 */ 1816 INSN *eiobj = new_insn_core(iseq, iobj->line_no, BIN(leave), 1817 diobj->operand_size, diobj->operands); 1818 INSN *popiobj = new_insn_core(iseq, iobj->line_no, 1819 BIN(pop), 0, 0); 1820 /* replace */ 1821 REPLACE_ELEM((LINK_ELEMENT *)iobj, (LINK_ELEMENT *)eiobj); 1822 INSERT_ELEM_NEXT((LINK_ELEMENT *)eiobj, (LINK_ELEMENT *)popiobj); 1823 iobj = popiobj; 1824 } 1825 /* 1826 * useless jump elimination (if/unless destination): 1827 * if L1 1828 * jump L2 1829 * L1: 1830 * ... 1831 * L2: 1832 * 1833 * ==> 1834 * unless L2 1835 * L1: 1836 * ... 1837 * L2: 1838 */ 1839 else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 && 1840 (piobj->insn_id == BIN(branchif) || 1841 piobj->insn_id == BIN(branchunless))) { 1842 if (niobj == (INSN *)get_destination_insn(piobj)) { 1843 piobj->insn_id = (piobj->insn_id == BIN(branchif)) 1844 ? BIN(branchunless) : BIN(branchif); 1845 OPERAND_AT(piobj, 0) = OPERAND_AT(iobj, 0); 1846 REMOVE_ELEM(&iobj->link); 1847 } 1848 } 1849 } 1850 1851 if (iobj->insn_id == BIN(branchif) || 1852 iobj->insn_id == BIN(branchunless)) { 1853 /* 1854 * if L1 1855 * ... 1856 * L1: 1857 * jump L2 1858 * => 1859 * if L2 1860 */ 1861 INSN *nobj = (INSN *)get_destination_insn(iobj); 1862 if (nobj->insn_id == BIN(jump)) { 1863 OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0); 1864 } 1865 } 1866 1867 if (do_tailcallopt && iobj->insn_id == BIN(leave)) { 1868 /* 1869 * send ... 1870 * leave 1871 * => 1872 * send ..., ... | VM_CALL_TAILCALL, ... 1873 * leave # unreachable 1874 */ 1875 INSN *piobj = (INSN *)get_prev_insn((INSN *)list); 1876 1877 if (piobj->insn_id == BIN(send) || piobj->insn_id == BIN(opt_send_simple)) { 1878 rb_call_info_t *ci = (rb_call_info_t *)piobj->operands[0]; 1879 if (ci->blockiseq == 0) { 1880 ci->flag |= VM_CALL_TAILCALL; 1881 } 1882 } 1883 } 1884 return COMPILE_OK; 1885} 1886 1887static int 1888insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id) 1889{ 1890 int old_opsize = iobj->operand_size; 1891 iobj->insn_id = insn_id; 1892 iobj->operand_size = insn_len(insn_id) - 1; 1893 1894 if (iobj->operand_size > old_opsize) { 1895 VALUE *old_operands = iobj->operands; 1896 if (insn_id != BIN(opt_neq)) { 1897 rb_bug("insn_set_specialized_instruction: unknown insn: %d", insn_id); 1898 } 1899 iobj->operands = (VALUE *)compile_data_alloc(iseq, iobj->operand_size * sizeof(VALUE)); 1900 iobj->operands[0] = old_operands[0]; 1901 iobj->operands[1] = (VALUE)new_callinfo(iseq, idEq, 1, 0, 0); 1902 } 1903 1904 return COMPILE_OK; 1905} 1906 1907static int 1908iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj) 1909{ 1910 if (iobj->insn_id == BIN(send)) { 1911 rb_call_info_t *ci = (rb_call_info_t *)OPERAND_AT(iobj, 0); 1912 1913#define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt)) 1914 if (ci->blockiseq == 0 && (ci->flag & ~VM_CALL_ARGS_SKIP_SETUP) == 0) { 1915 switch (ci->orig_argc) { 1916 case 0: 1917 switch (ci->mid) { 1918 case idLength: SP_INSN(length); return COMPILE_OK; 1919 case idSize: SP_INSN(size); return COMPILE_OK; 1920 case idEmptyP: SP_INSN(empty_p);return COMPILE_OK; 1921 case idSucc: SP_INSN(succ); return COMPILE_OK; 1922 case idNot: SP_INSN(not); return COMPILE_OK; 1923 } 1924 break; 1925 case 1: 1926 switch (ci->mid) { 1927 case idPLUS: SP_INSN(plus); return COMPILE_OK; 1928 case idMINUS: SP_INSN(minus); return COMPILE_OK; 1929 case idMULT: SP_INSN(mult); return COMPILE_OK; 1930 case idDIV: SP_INSN(div); return COMPILE_OK; 1931 case idMOD: SP_INSN(mod); return COMPILE_OK; 1932 case idEq: SP_INSN(eq); return COMPILE_OK; 1933 case idNeq: SP_INSN(neq); return COMPILE_OK; 1934 case idLT: SP_INSN(lt); return COMPILE_OK; 1935 case idLE: SP_INSN(le); return COMPILE_OK; 1936 case idGT: SP_INSN(gt); return COMPILE_OK; 1937 case idGE: SP_INSN(ge); return COMPILE_OK; 1938 case idLTLT: SP_INSN(ltlt); return COMPILE_OK; 1939 case idAREF: SP_INSN(aref); return COMPILE_OK; 1940 } 1941 break; 1942 } 1943 } 1944 if (ci->flag & VM_CALL_ARGS_SKIP_SETUP) { 1945 iobj->insn_id = BIN(opt_send_simple); 1946 } 1947 } 1948#undef SP_INSN 1949 1950 return COMPILE_OK; 1951} 1952 1953static int 1954iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *anchor) 1955{ 1956 LINK_ELEMENT *list; 1957 const int do_peepholeopt = iseq->compile_data->option->peephole_optimization; 1958 const int do_tailcallopt = iseq->compile_data->option->tailcall_optimization; 1959 const int do_si = iseq->compile_data->option->specialized_instruction; 1960 const int do_ou = iseq->compile_data->option->operands_unification; 1961 list = FIRST_ELEMENT(anchor); 1962 1963 while (list) { 1964 if (list->type == ISEQ_ELEMENT_INSN) { 1965 if (do_peepholeopt) { 1966 iseq_peephole_optimize(iseq, list, do_tailcallopt); 1967 } 1968 if (do_si) { 1969 iseq_specialized_instruction(iseq, (INSN *)list); 1970 } 1971 if (do_ou) { 1972 insn_operands_unification((INSN *)list); 1973 } 1974 } 1975 list = list->next; 1976 } 1977 return COMPILE_OK; 1978} 1979 1980#if OPT_INSTRUCTIONS_UNIFICATION 1981static INSN * 1982new_unified_insn(rb_iseq_t *iseq, 1983 int insn_id, int size, LINK_ELEMENT *seq_list) 1984{ 1985 INSN *iobj = 0; 1986 LINK_ELEMENT *list = seq_list; 1987 int i, argc = 0; 1988 VALUE *operands = 0, *ptr = 0; 1989 1990 1991 /* count argc */ 1992 for (i = 0; i < size; i++) { 1993 iobj = (INSN *)list; 1994 argc += iobj->operand_size; 1995 list = list->next; 1996 } 1997 1998 if (argc > 0) { 1999 ptr = operands = 2000 (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * argc); 2001 } 2002 2003 /* copy operands */ 2004 list = seq_list; 2005 for (i = 0; i < size; i++) { 2006 iobj = (INSN *)list; 2007 MEMCPY(ptr, iobj->operands, VALUE, iobj->operand_size); 2008 ptr += iobj->operand_size; 2009 list = list->next; 2010 } 2011 2012 return new_insn_core(iseq, iobj->line_no, insn_id, argc, operands); 2013} 2014#endif 2015 2016/* 2017 * This scheme can get more performance if do this optimize with 2018 * label address resolving. 2019 * It's future work (if compile time was bottle neck). 2020 */ 2021static int 2022iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor) 2023{ 2024#if OPT_INSTRUCTIONS_UNIFICATION 2025 LINK_ELEMENT *list; 2026 INSN *iobj, *niobj; 2027 int id, k; 2028 intptr_t j; 2029 2030 list = FIRST_ELEMENT(anchor); 2031 while (list) { 2032 if (list->type == ISEQ_ELEMENT_INSN) { 2033 iobj = (INSN *)list; 2034 id = iobj->insn_id; 2035 if (unified_insns_data[id] != 0) { 2036 const int *const *entry = unified_insns_data[id]; 2037 for (j = 1; j < (intptr_t)entry[0]; j++) { 2038 const int *unified = entry[j]; 2039 LINK_ELEMENT *li = list->next; 2040 for (k = 2; k < unified[1]; k++) { 2041 if (li->type != ISEQ_ELEMENT_INSN || 2042 ((INSN *)li)->insn_id != unified[k]) { 2043 goto miss; 2044 } 2045 li = li->next; 2046 } 2047 /* matched */ 2048 niobj = 2049 new_unified_insn(iseq, unified[0], unified[1] - 1, 2050 list); 2051 2052 /* insert to list */ 2053 niobj->link.prev = (LINK_ELEMENT *)iobj->link.prev; 2054 niobj->link.next = li; 2055 if (li) { 2056 li->prev = (LINK_ELEMENT *)niobj; 2057 } 2058 2059 list->prev->next = (LINK_ELEMENT *)niobj; 2060 list = (LINK_ELEMENT *)niobj; 2061 break; 2062 miss:; 2063 } 2064 } 2065 } 2066 list = list->next; 2067 } 2068#endif 2069 return COMPILE_OK; 2070} 2071 2072#if OPT_STACK_CACHING 2073 2074#define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)] 2075#define SC_NEXT(insn) sc_insn_next[(insn)] 2076 2077#include "opt_sc.inc" 2078 2079static int 2080insn_set_sc_state(rb_iseq_t *iseq, INSN *iobj, int state) 2081{ 2082 int nstate; 2083 int insn_id; 2084 2085 insn_id = iobj->insn_id; 2086 iobj->insn_id = SC_INSN(insn_id, state); 2087 nstate = SC_NEXT(iobj->insn_id); 2088 2089 if (insn_id == BIN(jump) || 2090 insn_id == BIN(branchif) || insn_id == BIN(branchunless)) { 2091 LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0); 2092 2093 if (lobj->sc_state != 0) { 2094 if (lobj->sc_state != nstate) { 2095 dump_disasm_list((LINK_ELEMENT *)iobj); 2096 dump_disasm_list((LINK_ELEMENT *)lobj); 2097 printf("\n-- %d, %d\n", lobj->sc_state, nstate); 2098 rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no, 2099 "insn_set_sc_state error\n"); 2100 return 0; 2101 } 2102 } 2103 else { 2104 lobj->sc_state = nstate; 2105 } 2106 if (insn_id == BIN(jump)) { 2107 nstate = SCS_XX; 2108 } 2109 } 2110 else if (insn_id == BIN(leave)) { 2111 nstate = SCS_XX; 2112 } 2113 2114 return nstate; 2115} 2116 2117static int 2118label_set_sc_state(LABEL *lobj, int state) 2119{ 2120 if (lobj->sc_state != 0) { 2121 if (lobj->sc_state != state) { 2122 state = lobj->sc_state; 2123 } 2124 } 2125 else { 2126 lobj->sc_state = state; 2127 } 2128 2129 return state; 2130} 2131 2132 2133#endif 2134 2135static int 2136iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor) 2137{ 2138#if OPT_STACK_CACHING 2139 LINK_ELEMENT *list; 2140 int state, insn_id; 2141 2142 /* initialize */ 2143 state = SCS_XX; 2144 list = FIRST_ELEMENT(anchor); 2145 /* dump_disasm_list(list); */ 2146 2147 /* for each list element */ 2148 while (list) { 2149 redo_point: 2150 switch (list->type) { 2151 case ISEQ_ELEMENT_INSN: 2152 { 2153 INSN *iobj = (INSN *)list; 2154 insn_id = iobj->insn_id; 2155 2156 /* dump_disasm_list(list); */ 2157 2158 switch (insn_id) { 2159 case BIN(nop): 2160 { 2161 /* exception merge point */ 2162 if (state != SCS_AX) { 2163 INSN *rpobj = 2164 new_insn_body(iseq, 0, BIN(reput), 0); 2165 2166 /* replace this insn */ 2167 REPLACE_ELEM(list, (LINK_ELEMENT *)rpobj); 2168 list = (LINK_ELEMENT *)rpobj; 2169 goto redo_point; 2170 } 2171 break; 2172 } 2173 case BIN(swap): 2174 { 2175 if (state == SCS_AB || state == SCS_BA) { 2176 state = (state == SCS_AB ? SCS_BA : SCS_AB); 2177 2178 REMOVE_ELEM(list); 2179 list = list->next; 2180 goto redo_point; 2181 } 2182 break; 2183 } 2184 case BIN(pop): 2185 { 2186 switch (state) { 2187 case SCS_AX: 2188 case SCS_BX: 2189 state = SCS_XX; 2190 break; 2191 case SCS_AB: 2192 state = SCS_AX; 2193 break; 2194 case SCS_BA: 2195 state = SCS_BX; 2196 break; 2197 case SCS_XX: 2198 goto normal_insn; 2199 default: 2200 rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no, 2201 "unreachable"); 2202 } 2203 /* remove useless pop */ 2204 REMOVE_ELEM(list); 2205 list = list->next; 2206 goto redo_point; 2207 } 2208 default:; 2209 /* none */ 2210 } /* end of switch */ 2211 normal_insn: 2212 state = insn_set_sc_state(iseq, iobj, state); 2213 break; 2214 } 2215 case ISEQ_ELEMENT_LABEL: 2216 { 2217 LABEL *lobj; 2218 lobj = (LABEL *)list; 2219 2220 state = label_set_sc_state(lobj, state); 2221 } 2222 default: 2223 break; 2224 } 2225 list = list->next; 2226 } 2227#endif 2228 return COMPILE_OK; 2229} 2230 2231static int 2232compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int *cntp) 2233{ 2234 NODE *list = node->nd_next; 2235 VALUE lit = node->nd_lit; 2236 int cnt = 0; 2237 2238 debugp_param("nd_lit", lit); 2239 if (!NIL_P(lit)) { 2240 hide_obj(lit); 2241 cnt++; 2242 ADD_INSN1(ret, nd_line(node), putobject, lit); 2243 } 2244 2245 while (list) { 2246 node = list->nd_head; 2247 if (nd_type(node) == NODE_STR) { 2248 hide_obj(node->nd_lit); 2249 ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit); 2250 } 2251 else { 2252 COMPILE(ret, "each string", node); 2253 } 2254 cnt++; 2255 list = list->nd_next; 2256 } 2257 *cntp = cnt; 2258 2259 return COMPILE_OK; 2260} 2261 2262static int 2263compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node) 2264{ 2265 int cnt; 2266 compile_dstr_fragments(iseq, ret, node, &cnt); 2267 ADD_INSN1(ret, nd_line(node), concatstrings, INT2FIX(cnt)); 2268 return COMPILE_OK; 2269} 2270 2271static int 2272compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node) 2273{ 2274 int cnt; 2275 compile_dstr_fragments(iseq, ret, node, &cnt); 2276 ADD_INSN2(ret, nd_line(node), toregexp, INT2FIX(node->nd_cflag), INT2FIX(cnt)); 2277 return COMPILE_OK; 2278} 2279 2280static int 2281compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * cond, 2282 LABEL *then_label, LABEL *else_label) 2283{ 2284 switch (nd_type(cond)) { 2285 case NODE_AND: 2286 { 2287 LABEL *label = NEW_LABEL(nd_line(cond)); 2288 compile_branch_condition(iseq, ret, cond->nd_1st, label, 2289 else_label); 2290 ADD_LABEL(ret, label); 2291 compile_branch_condition(iseq, ret, cond->nd_2nd, then_label, 2292 else_label); 2293 break; 2294 } 2295 case NODE_OR: 2296 { 2297 LABEL *label = NEW_LABEL(nd_line(cond)); 2298 compile_branch_condition(iseq, ret, cond->nd_1st, then_label, 2299 label); 2300 ADD_LABEL(ret, label); 2301 compile_branch_condition(iseq, ret, cond->nd_2nd, then_label, 2302 else_label); 2303 break; 2304 } 2305 case NODE_LIT: /* NODE_LIT is always not true */ 2306 case NODE_TRUE: 2307 case NODE_STR: 2308 /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */ 2309 ADD_INSNL(ret, nd_line(cond), jump, then_label); 2310 break; 2311 case NODE_FALSE: 2312 case NODE_NIL: 2313 /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */ 2314 ADD_INSNL(ret, nd_line(cond), jump, else_label); 2315 break; 2316 default: 2317 COMPILE(ret, "branch condition", cond); 2318 ADD_INSNL(ret, nd_line(cond), branchunless, else_label); 2319 ADD_INSNL(ret, nd_line(cond), jump, then_label); 2320 break; 2321 } 2322 return COMPILE_OK; 2323} 2324 2325enum compile_array_type_t { 2326 COMPILE_ARRAY_TYPE_ARRAY, 2327 COMPILE_ARRAY_TYPE_HASH, 2328 COMPILE_ARRAY_TYPE_ARGS 2329}; 2330 2331static int 2332compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root, 2333 enum compile_array_type_t type, int poped) 2334{ 2335 NODE *node = node_root; 2336 int line = (int)nd_line(node); 2337 int len = 0; 2338 2339 if (nd_type(node) == NODE_ZARRAY) { 2340 if (!poped) { 2341 switch (type) { 2342 case COMPILE_ARRAY_TYPE_ARRAY: ADD_INSN1(ret, line, newarray, INT2FIX(0)); break; 2343 case COMPILE_ARRAY_TYPE_HASH: ADD_INSN1(ret, line, newhash, INT2FIX(0)); break; 2344 case COMPILE_ARRAY_TYPE_ARGS: /* do nothing */ break; 2345 } 2346 } 2347 } 2348 else { 2349 int opt_p = 1; 2350 int first = 1, i; 2351 2352 while (node) { 2353 NODE *start_node = node, *end_node; 2354 NODE *kw = 0; 2355 const int max = 0x100; 2356 DECL_ANCHOR(anchor); 2357 INIT_ANCHOR(anchor); 2358 2359 for (i=0; i<max && node; i++, len++, node = node->nd_next) { 2360 if (CPDEBUG > 0 && nd_type(node) != NODE_ARRAY) { 2361 rb_bug("compile_array: This node is not NODE_ARRAY, but %s", ruby_node_name(nd_type(node))); 2362 } 2363 2364 if (type == COMPILE_ARRAY_TYPE_HASH && !node->nd_head) { 2365 opt_p = 0; 2366 kw = node->nd_next; 2367 node = kw->nd_next; 2368 kw = kw->nd_head; 2369 break; 2370 } 2371 if (opt_p && nd_type(node->nd_head) != NODE_LIT) { 2372 opt_p = 0; 2373 } 2374 2375 COMPILE_(anchor, "array element", node->nd_head, poped); 2376 } 2377 2378 if (opt_p && type != COMPILE_ARRAY_TYPE_ARGS) { 2379 if (!poped) { 2380 VALUE ary = rb_ary_tmp_new(i); 2381 2382 end_node = node; 2383 node = start_node; 2384 2385 while (node != end_node) { 2386 rb_ary_push(ary, node->nd_head->nd_lit); 2387 node = node->nd_next; 2388 } 2389 while (node && nd_type(node->nd_head) == NODE_LIT && 2390 node->nd_next && nd_type(node->nd_next->nd_head) == NODE_LIT) { 2391 rb_ary_push(ary, node->nd_head->nd_lit); 2392 node = node->nd_next; 2393 rb_ary_push(ary, node->nd_head->nd_lit); 2394 node = node->nd_next; 2395 len++; 2396 } 2397 2398 OBJ_FREEZE(ary); 2399 2400 iseq_add_mark_object_compile_time(iseq, ary); 2401 2402 if (first) { 2403 first = 0; 2404 if (type == COMPILE_ARRAY_TYPE_ARRAY) { 2405 ADD_INSN1(ret, line, duparray, ary); 2406 } 2407 else { /* COMPILE_ARRAY_TYPE_HASH */ 2408 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 2409 ADD_INSN1(ret, line, putobject, ary); 2410 ADD_SEND(ret, line, ID2SYM(id_core_hash_from_ary), INT2FIX(1)); 2411 } 2412 } 2413 else { 2414 if (type == COMPILE_ARRAY_TYPE_ARRAY) { 2415 ADD_INSN1(ret, line, putobject, ary); 2416 ADD_INSN(ret, line, concatarray); 2417 } 2418 else { 2419 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 2420 ADD_INSN1(ret, line, putobject, ary); 2421 ADD_SEND(ret, line, ID2SYM(id_core_hash_merge_ary), INT2FIX(1)); 2422 } 2423 } 2424 } 2425 } 2426 else { 2427 if (!poped) { 2428 switch (type) { 2429 case COMPILE_ARRAY_TYPE_ARRAY: 2430 ADD_INSN1(anchor, line, newarray, INT2FIX(i)); 2431 2432 if (first) { 2433 first = 0; 2434 } 2435 else { 2436 ADD_INSN(anchor, line, concatarray); 2437 } 2438 2439 APPEND_LIST(ret, anchor); 2440 break; 2441 case COMPILE_ARRAY_TYPE_HASH: 2442 if (first) { 2443 first = 0; 2444 ADD_INSN1(anchor, line, newhash, INT2FIX(i)); 2445 APPEND_LIST(ret, anchor); 2446 } 2447 else if (i > 0) { 2448 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 2449 ADD_INSN(ret, line, swap); 2450 APPEND_LIST(ret, anchor); 2451 ADD_SEND(ret, line, ID2SYM(id_core_hash_merge_ptr), INT2FIX(i + 1)); 2452 } 2453 if (kw) { 2454 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 2455 ADD_INSN(ret, line, swap); 2456 COMPILE(ret, "keyword splat", kw); 2457 ADD_SEND(ret, line, ID2SYM(id_core_hash_merge_kwd), INT2FIX(2)); 2458 } 2459 break; 2460 case COMPILE_ARRAY_TYPE_ARGS: 2461 APPEND_LIST(ret, anchor); 2462 break; 2463 } 2464 } 2465 else { 2466 /* poped */ 2467 APPEND_LIST(ret, anchor); 2468 } 2469 } 2470 } 2471 } 2472 return len; 2473} 2474 2475static VALUE 2476compile_array(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root, enum compile_array_type_t type) 2477{ 2478 return compile_array_(iseq, ret, node_root, type, 0); 2479} 2480 2481static VALUE 2482case_when_optimizable_literal(NODE * node) 2483{ 2484 switch (nd_type(node)) { 2485 case NODE_LIT: { 2486 VALUE v = node->nd_lit; 2487 double ival; 2488 if (RB_TYPE_P(v, T_FLOAT) && 2489 modf(RFLOAT_VALUE(v), &ival) == 0.0) { 2490 return FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival); 2491 } 2492 if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) { 2493 return v; 2494 } 2495 break; 2496 } 2497 case NODE_STR: 2498 return node->nd_lit; 2499 } 2500 return Qundef; 2501} 2502 2503static int 2504when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, int only_special_literals, VALUE literals) 2505{ 2506 while (vals) { 2507 NODE* val = vals->nd_head; 2508 VALUE lit = case_when_optimizable_literal(val); 2509 2510 if (lit == Qundef) { 2511 only_special_literals = 0; 2512 } 2513 else { 2514 if (rb_hash_lookup(literals, lit) != Qnil) { 2515 rb_compile_warning(RSTRING_PTR(iseq->location.path), nd_line(val), "duplicated when clause is ignored"); 2516 } 2517 else { 2518 rb_hash_aset(literals, lit, (VALUE)(l1) | 1); 2519 } 2520 } 2521 2522 ADD_INSN(cond_seq, nd_line(val), dup); /* dup target */ 2523 2524 if (nd_type(val) == NODE_STR) { 2525 debugp_param("nd_lit", val->nd_lit); 2526 OBJ_FREEZE(val->nd_lit); 2527 ADD_INSN1(cond_seq, nd_line(val), putobject, val->nd_lit); 2528 } 2529 else { 2530 COMPILE(cond_seq, "when cond", val); 2531 } 2532 2533 ADD_INSN1(cond_seq, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); 2534 ADD_INSNL(cond_seq, nd_line(val), branchif, l1); 2535 vals = vals->nd_next; 2536 } 2537 return only_special_literals; 2538} 2539 2540static int 2541compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node) 2542{ 2543 switch (nd_type(node)) { 2544 case NODE_ATTRASGN: { 2545 INSN *iobj; 2546 rb_call_info_t *ci; 2547 VALUE dupidx; 2548 2549 COMPILE_POPED(ret, "masgn lhs (NODE_ATTRASGN)", node); 2550 2551 POP_ELEMENT(ret); /* pop pop insn */ 2552 iobj = (INSN *)POP_ELEMENT(ret); /* pop send insn */ 2553 ci = (rb_call_info_t *)iobj->operands[0]; 2554 ci->orig_argc += 1; ci->argc = ci->orig_argc; 2555 dupidx = INT2FIX(ci->orig_argc); 2556 2557 ADD_INSN1(ret, nd_line(node), topn, dupidx); 2558 ADD_ELEM(ret, (LINK_ELEMENT *)iobj); 2559 ADD_INSN(ret, nd_line(node), pop); /* result */ 2560 ADD_INSN(ret, nd_line(node), pop); /* rhs */ 2561 break; 2562 } 2563 case NODE_MASGN: { 2564 DECL_ANCHOR(anchor); 2565 INIT_ANCHOR(anchor); 2566 COMPILE_POPED(anchor, "nest masgn lhs", node); 2567 REMOVE_ELEM(FIRST_ELEMENT(anchor)); 2568 ADD_SEQ(ret, anchor); 2569 break; 2570 } 2571 default: { 2572 DECL_ANCHOR(anchor); 2573 INIT_ANCHOR(anchor); 2574 COMPILE_POPED(anchor, "masgn lhs", node); 2575 REMOVE_ELEM(FIRST_ELEMENT(anchor)); 2576 ADD_SEQ(ret, anchor); 2577 } 2578 } 2579 2580 return COMPILE_OK; 2581} 2582 2583static void 2584compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *lhsn) 2585{ 2586 if (lhsn) { 2587 compile_massign_opt_lhs(iseq, ret, lhsn->nd_next); 2588 compile_massign_lhs(iseq, ret, lhsn->nd_head); 2589 } 2590} 2591 2592static int 2593compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *ret, 2594 NODE *rhsn, NODE *orig_lhsn) 2595{ 2596 VALUE mem[64]; 2597 const int memsize = numberof(mem); 2598 int memindex = 0; 2599 int llen = 0, rlen = 0; 2600 int i; 2601 NODE *lhsn = orig_lhsn; 2602 2603#define MEMORY(v) { \ 2604 int i; \ 2605 if (memindex == memsize) return 0; \ 2606 for (i=0; i<memindex; i++) { \ 2607 if (mem[i] == (v)) return 0; \ 2608 } \ 2609 mem[memindex++] = (v); \ 2610} 2611 2612 if (rhsn == 0 || nd_type(rhsn) != NODE_ARRAY) { 2613 return 0; 2614 } 2615 2616 while (lhsn) { 2617 NODE *ln = lhsn->nd_head; 2618 switch (nd_type(ln)) { 2619 case NODE_LASGN: 2620 MEMORY(ln->nd_vid); 2621 break; 2622 case NODE_DASGN: 2623 case NODE_DASGN_CURR: 2624 case NODE_IASGN: 2625 case NODE_IASGN2: 2626 case NODE_CVASGN: 2627 MEMORY(ln->nd_vid); 2628 break; 2629 default: 2630 return 0; 2631 } 2632 lhsn = lhsn->nd_next; 2633 llen++; 2634 } 2635 2636 while (rhsn) { 2637 if (llen <= rlen) { 2638 COMPILE_POPED(ret, "masgn val (popped)", rhsn->nd_head); 2639 } 2640 else { 2641 COMPILE(ret, "masgn val", rhsn->nd_head); 2642 } 2643 rhsn = rhsn->nd_next; 2644 rlen++; 2645 } 2646 2647 if (llen > rlen) { 2648 for (i=0; i<llen-rlen; i++) { 2649 ADD_INSN(ret, nd_line(orig_lhsn), putnil); 2650 } 2651 } 2652 2653 compile_massign_opt_lhs(iseq, ret, orig_lhsn); 2654 return 1; 2655} 2656 2657static int 2658compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped) 2659{ 2660 NODE *rhsn = node->nd_value; 2661 NODE *splatn = node->nd_args; 2662 NODE *lhsn = node->nd_head; 2663 int lhs_splat = (splatn && (VALUE)splatn != (VALUE)-1) ? 1 : 0; 2664 2665 if (!poped || splatn || !compile_massign_opt(iseq, ret, rhsn, lhsn)) { 2666 int llen = 0; 2667 DECL_ANCHOR(lhsseq); 2668 2669 INIT_ANCHOR(lhsseq); 2670 2671 while (lhsn) { 2672 compile_massign_lhs(iseq, lhsseq, lhsn->nd_head); 2673 llen += 1; 2674 lhsn = lhsn->nd_next; 2675 } 2676 2677 COMPILE(ret, "normal masgn rhs", rhsn); 2678 2679 if (!poped) { 2680 ADD_INSN(ret, nd_line(node), dup); 2681 } 2682 2683 ADD_INSN2(ret, nd_line(node), expandarray, 2684 INT2FIX(llen), INT2FIX(lhs_splat)); 2685 ADD_SEQ(ret, lhsseq); 2686 2687 if (lhs_splat) { 2688 if (nd_type(splatn) == NODE_POSTARG) { 2689 /*a, b, *r, p1, p2 */ 2690 NODE *postn = splatn->nd_2nd; 2691 NODE *restn = splatn->nd_1st; 2692 int num = (int)postn->nd_alen; 2693 int flag = 0x02 | (((VALUE)restn == (VALUE)-1) ? 0x00 : 0x01); 2694 2695 ADD_INSN2(ret, nd_line(splatn), expandarray, 2696 INT2FIX(num), INT2FIX(flag)); 2697 2698 if ((VALUE)restn != (VALUE)-1) { 2699 compile_massign_lhs(iseq, ret, restn); 2700 } 2701 while (postn) { 2702 compile_massign_lhs(iseq, ret, postn->nd_head); 2703 postn = postn->nd_next; 2704 } 2705 } 2706 else { 2707 /* a, b, *r */ 2708 compile_massign_lhs(iseq, ret, splatn); 2709 } 2710 } 2711 } 2712 return COMPILE_OK; 2713} 2714 2715static int 2716compile_colon2(rb_iseq_t *iseq, NODE * node, 2717 LINK_ANCHOR *pref, LINK_ANCHOR *body) 2718{ 2719 switch (nd_type(node)) { 2720 case NODE_CONST: 2721 debugi("compile_colon2 - colon", node->nd_vid); 2722 ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_vid)); 2723 break; 2724 case NODE_COLON3: 2725 debugi("compile_colon2 - colon3", node->nd_mid); 2726 ADD_INSN(body, nd_line(node), pop); 2727 ADD_INSN1(body, nd_line(node), putobject, rb_cObject); 2728 ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid)); 2729 break; 2730 case NODE_COLON2: 2731 compile_colon2(iseq, node->nd_head, pref, body); 2732 debugi("compile_colon2 - colon2", node->nd_mid); 2733 ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid)); 2734 break; 2735 default: 2736 COMPILE(pref, "const colon2 prefix", node); 2737 break; 2738 } 2739 return COMPILE_OK; 2740} 2741 2742static VALUE 2743compile_cpath(LINK_ANCHOR *ret, rb_iseq_t *iseq, NODE *cpath) 2744{ 2745 if (nd_type(cpath) == NODE_COLON3) { 2746 /* toplevel class ::Foo */ 2747 ADD_INSN1(ret, nd_line(cpath), putobject, rb_cObject); 2748 return Qfalse; 2749 } 2750 else if (cpath->nd_head) { 2751 /* Bar::Foo */ 2752 COMPILE(ret, "nd_else->nd_head", cpath->nd_head); 2753 return Qfalse; 2754 } 2755 else { 2756 /* class at cbase Foo */ 2757 ADD_INSN1(ret, nd_line(cpath), putspecialobject, 2758 INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); 2759 return Qtrue; 2760 } 2761} 2762 2763#define defined_expr defined_expr0 2764static int 2765defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret, 2766 NODE *node, LABEL **lfinish, VALUE needstr) 2767{ 2768 enum defined_type expr_type = 0; 2769 enum node_type type; 2770 2771 switch (type = nd_type(node)) { 2772 2773 /* easy literals */ 2774 case NODE_NIL: 2775 expr_type = DEFINED_NIL; 2776 break; 2777 case NODE_SELF: 2778 expr_type = DEFINED_SELF; 2779 break; 2780 case NODE_TRUE: 2781 expr_type = DEFINED_TRUE; 2782 break; 2783 case NODE_FALSE: 2784 expr_type = DEFINED_FALSE; 2785 break; 2786 2787 case NODE_ARRAY:{ 2788 NODE *vals = node; 2789 2790 do { 2791 defined_expr(iseq, ret, vals->nd_head, lfinish, Qfalse); 2792 2793 if (!lfinish[1]) { 2794 lfinish[1] = NEW_LABEL(nd_line(node)); 2795 } 2796 ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]); 2797 } while ((vals = vals->nd_next) != NULL); 2798 } 2799 case NODE_STR: 2800 case NODE_LIT: 2801 case NODE_ZARRAY: 2802 case NODE_AND: 2803 case NODE_OR: 2804 default: 2805 expr_type = DEFINED_EXPR; 2806 break; 2807 2808 /* variables */ 2809 case NODE_LVAR: 2810 case NODE_DVAR: 2811 expr_type = DEFINED_LVAR; 2812 break; 2813 2814 case NODE_IVAR: 2815 ADD_INSN(ret, nd_line(node), putnil); 2816 ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_IVAR), 2817 ID2SYM(node->nd_vid), needstr); 2818 return 1; 2819 2820 case NODE_GVAR: 2821 ADD_INSN(ret, nd_line(node), putnil); 2822 ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_GVAR), 2823 ID2SYM(node->nd_entry->id), needstr); 2824 return 1; 2825 2826 case NODE_CVAR: 2827 ADD_INSN(ret, nd_line(node), putnil); 2828 ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CVAR), 2829 ID2SYM(node->nd_vid), needstr); 2830 return 1; 2831 2832 case NODE_CONST: 2833 ADD_INSN(ret, nd_line(node), putnil); 2834 ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CONST), 2835 ID2SYM(node->nd_vid), needstr); 2836 return 1; 2837 case NODE_COLON2: 2838 if (!lfinish[1]) { 2839 lfinish[1] = NEW_LABEL(nd_line(node)); 2840 } 2841 defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse); 2842 ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]); 2843 2844 if (rb_is_const_id(node->nd_mid)) { 2845 COMPILE(ret, "defined/colon2#nd_head", node->nd_head); 2846 ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CONST), 2847 ID2SYM(node->nd_mid), needstr); 2848 } 2849 else { 2850 COMPILE(ret, "defined/colon2#nd_head", node->nd_head); 2851 ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_METHOD), 2852 ID2SYM(node->nd_mid), needstr); 2853 } 2854 return 1; 2855 case NODE_COLON3: 2856 ADD_INSN1(ret, nd_line(node), putobject, rb_cObject); 2857 ADD_INSN3(ret, nd_line(node), defined, 2858 INT2FIX(DEFINED_CONST), ID2SYM(node->nd_mid), needstr); 2859 return 1; 2860 2861 /* method dispatch */ 2862 case NODE_CALL: 2863 case NODE_VCALL: 2864 case NODE_FCALL: 2865 case NODE_ATTRASGN:{ 2866 int self = TRUE; 2867 2868 switch (type) { 2869 case NODE_ATTRASGN: 2870 if (node->nd_recv == (NODE *)1) break; 2871 case NODE_CALL: 2872 self = FALSE; 2873 break; 2874 default: 2875 /* through */; 2876 } 2877 if (!lfinish[1]) { 2878 lfinish[1] = NEW_LABEL(nd_line(node)); 2879 } 2880 if (node->nd_args) { 2881 defined_expr(iseq, ret, node->nd_args, lfinish, Qfalse); 2882 ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]); 2883 } 2884 if (!self) { 2885 defined_expr(iseq, ret, node->nd_recv, lfinish, Qfalse); 2886 ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]); 2887 COMPILE(ret, "defined/recv", node->nd_recv); 2888 ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_METHOD), 2889 ID2SYM(node->nd_mid), needstr); 2890 } 2891 else { 2892 ADD_INSN(ret, nd_line(node), putself); 2893 ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_FUNC), 2894 ID2SYM(node->nd_mid), needstr); 2895 } 2896 return 1; 2897 } 2898 2899 case NODE_YIELD: 2900 ADD_INSN(ret, nd_line(node), putnil); 2901 ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_YIELD), 0, 2902 needstr); 2903 return 1; 2904 2905 case NODE_BACK_REF: 2906 case NODE_NTH_REF: 2907 ADD_INSN(ret, nd_line(node), putnil); 2908 ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_REF), 2909 INT2FIX((node->nd_nth << 1) | (type == NODE_BACK_REF)), 2910 needstr); 2911 return 1; 2912 2913 case NODE_SUPER: 2914 case NODE_ZSUPER: 2915 ADD_INSN(ret, nd_line(node), putnil); 2916 ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_ZSUPER), 0, 2917 needstr); 2918 return 1; 2919 2920 case NODE_OP_ASGN1: 2921 case NODE_OP_ASGN2: 2922 case NODE_OP_ASGN_OR: 2923 case NODE_OP_ASGN_AND: 2924 case NODE_MASGN: 2925 case NODE_LASGN: 2926 case NODE_DASGN: 2927 case NODE_DASGN_CURR: 2928 case NODE_GASGN: 2929 case NODE_IASGN: 2930 case NODE_CDECL: 2931 case NODE_CVDECL: 2932 case NODE_CVASGN: 2933 expr_type = DEFINED_ASGN; 2934 break; 2935 } 2936 2937 if (expr_type) { 2938 if (needstr != Qfalse) { 2939 VALUE str = rb_iseq_defined_string(expr_type); 2940 ADD_INSN1(ret, nd_line(node), putobject, str); 2941 } 2942 else { 2943 ADD_INSN1(ret, nd_line(node), putobject, Qtrue); 2944 } 2945 return 1; 2946 } 2947 return 0; 2948} 2949#undef defined_expr 2950 2951static int 2952defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret, 2953 NODE *node, LABEL **lfinish, VALUE needstr) 2954{ 2955 LINK_ELEMENT *lcur = ret->last; 2956 int done = defined_expr0(iseq, ret, node, lfinish, needstr); 2957 if (lfinish[1]) { 2958 int line = nd_line(node); 2959 LABEL *lstart = NEW_LABEL(line); 2960 LABEL *lend = NEW_LABEL(line); 2961 VALUE rescue = NEW_CHILD_ISEQVAL(NEW_NIL(), 2962 rb_str_concat(rb_str_new2 2963 ("defined guard in "), 2964 iseq->location.label), 2965 ISEQ_TYPE_DEFINED_GUARD, 0); 2966 APPEND_LABEL(ret, lcur, lstart); 2967 ADD_LABEL(ret, lend); 2968 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]); 2969 } 2970 return done; 2971} 2972 2973#define BUFSIZE 0x100 2974 2975static VALUE 2976make_name_for_block(rb_iseq_t *iseq) 2977{ 2978 int level = 1; 2979 rb_iseq_t *ip = iseq; 2980 2981 if (iseq->parent_iseq != 0) { 2982 while (ip->local_iseq != ip) { 2983 if (ip->type == ISEQ_TYPE_BLOCK) { 2984 level++; 2985 } 2986 ip = ip->parent_iseq; 2987 } 2988 } 2989 2990 if (level == 1) { 2991 return rb_sprintf("block in %s", RSTRING_PTR(ip->location.label)); 2992 } 2993 else { 2994 return rb_sprintf("block (%d levels) in %s", level, RSTRING_PTR(ip->location.label)); 2995 } 2996} 2997 2998static void 2999push_ensure_entry(rb_iseq_t *iseq, 3000 struct iseq_compile_data_ensure_node_stack *enl, 3001 struct ensure_range *er, NODE *node) 3002{ 3003 enl->ensure_node = node; 3004 enl->prev = iseq->compile_data->ensure_node_stack; /* prev */ 3005 enl->erange = er; 3006 iseq->compile_data->ensure_node_stack = enl; 3007} 3008 3009static void 3010add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange, 3011 LABEL *lstart, LABEL *lend) 3012{ 3013 struct ensure_range *ne = 3014 compile_data_alloc(iseq, sizeof(struct ensure_range)); 3015 3016 while (erange->next != 0) { 3017 erange = erange->next; 3018 } 3019 ne->next = 0; 3020 ne->begin = lend; 3021 ne->end = erange->end; 3022 erange->end = lstart; 3023 3024 erange->next = ne; 3025} 3026 3027static void 3028add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t *iseq, int is_return) 3029{ 3030 struct iseq_compile_data_ensure_node_stack *enlp = 3031 iseq->compile_data->ensure_node_stack; 3032 struct iseq_compile_data_ensure_node_stack *prev_enlp = enlp; 3033 DECL_ANCHOR(ensure); 3034 3035 INIT_ANCHOR(ensure); 3036 while (enlp) { 3037 if (enlp->erange != 0) { 3038 DECL_ANCHOR(ensure_part); 3039 LABEL *lstart = NEW_LABEL(0); 3040 LABEL *lend = NEW_LABEL(0); 3041 INIT_ANCHOR(ensure_part); 3042 3043 add_ensure_range(iseq, enlp->erange, lstart, lend); 3044 3045 iseq->compile_data->ensure_node_stack = enlp->prev; 3046 ADD_LABEL(ensure_part, lstart); 3047 COMPILE_POPED(ensure_part, "ensure part", enlp->ensure_node); 3048 ADD_LABEL(ensure_part, lend); 3049 ADD_SEQ(ensure, ensure_part); 3050 } 3051 else { 3052 if (!is_return) { 3053 break; 3054 } 3055 } 3056 enlp = enlp->prev; 3057 } 3058 iseq->compile_data->ensure_node_stack = prev_enlp; 3059 ADD_SEQ(ret, ensure); 3060} 3061 3062static VALUE 3063setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, VALUE *flag) 3064{ 3065 VALUE argc = INT2FIX(0); 3066 int nsplat = 0; 3067 DECL_ANCHOR(arg_block); 3068 DECL_ANCHOR(args_splat); 3069 3070 INIT_ANCHOR(arg_block); 3071 INIT_ANCHOR(args_splat); 3072 if (argn && nd_type(argn) == NODE_BLOCK_PASS) { 3073 COMPILE(arg_block, "block", argn->nd_body); 3074 *flag |= VM_CALL_ARGS_BLOCKARG; 3075 argn = argn->nd_head; 3076 } 3077 3078 setup_argn: 3079 if (argn) { 3080 switch (nd_type(argn)) { 3081 case NODE_SPLAT: { 3082 COMPILE(args, "args (splat)", argn->nd_head); 3083 argc = INT2FIX(1); 3084 nsplat++; 3085 *flag |= VM_CALL_ARGS_SPLAT; 3086 break; 3087 } 3088 case NODE_ARGSCAT: 3089 case NODE_ARGSPUSH: { 3090 int next_is_array = (nd_type(argn->nd_head) == NODE_ARRAY); 3091 DECL_ANCHOR(tmp); 3092 3093 INIT_ANCHOR(tmp); 3094 COMPILE(tmp, "args (cat: splat)", argn->nd_body); 3095 if (next_is_array && nsplat == 0) { 3096 /* none */ 3097 } 3098 else { 3099 if (nd_type(argn) == NODE_ARGSCAT) { 3100 ADD_INSN1(tmp, nd_line(argn), splatarray, Qfalse); 3101 } 3102 else { 3103 ADD_INSN1(tmp, nd_line(argn), newarray, INT2FIX(1)); 3104 } 3105 } 3106 INSERT_LIST(args_splat, tmp); 3107 nsplat++; 3108 *flag |= VM_CALL_ARGS_SPLAT; 3109 3110 if (next_is_array) { 3111 argc = INT2FIX(compile_array(iseq, args, argn->nd_head, COMPILE_ARRAY_TYPE_ARGS) + 1); 3112 } 3113 else { 3114 argn = argn->nd_head; 3115 goto setup_argn; 3116 } 3117 break; 3118 } 3119 case NODE_ARRAY: { 3120 argc = INT2FIX(compile_array(iseq, args, argn, COMPILE_ARRAY_TYPE_ARGS)); 3121 break; 3122 } 3123 default: { 3124 rb_bug("setup_arg: unknown node: %s\n", ruby_node_name(nd_type(argn))); 3125 } 3126 } 3127 } 3128 3129 if (nsplat > 1) { 3130 int i; 3131 for (i=1; i<nsplat; i++) { 3132 ADD_INSN(args_splat, nd_line(args), concatarray); 3133 } 3134 } 3135 3136 if (!LIST_SIZE_ZERO(args_splat)) { 3137 ADD_SEQ(args, args_splat); 3138 } 3139 3140 if (*flag & VM_CALL_ARGS_BLOCKARG) { 3141 ADD_SEQ(args, arg_block); 3142 } 3143 return argc; 3144} 3145 3146 3147/** 3148 compile each node 3149 3150 self: InstructionSequence 3151 node: Ruby compiled node 3152 poped: This node will be poped 3153 */ 3154static int 3155iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) 3156{ 3157 enum node_type type; 3158 int line; 3159 3160 if (node == 0) { 3161 if (!poped) { 3162 debugs("node: NODE_NIL(implicit)\n"); 3163 ADD_INSN(ret, iseq->compile_data->last_line, putnil); 3164 } 3165 return COMPILE_OK; 3166 } 3167 3168 iseq->compile_data->last_line = line = (int)nd_line(node); 3169 debug_node_start(node); 3170 3171 type = nd_type(node); 3172 3173 if (node->flags & NODE_FL_NEWLINE) { 3174 ADD_TRACE(ret, line, RUBY_EVENT_LINE); 3175 } 3176 3177 switch (type) { 3178 case NODE_BLOCK:{ 3179 while (node && nd_type(node) == NODE_BLOCK) { 3180 COMPILE_(ret, "BLOCK body", node->nd_head, 3181 (node->nd_next == 0 && poped == 0) ? 0 : 1); 3182 node = node->nd_next; 3183 } 3184 if (node) { 3185 COMPILE_(ret, "BLOCK next", node->nd_next, poped); 3186 } 3187 break; 3188 } 3189 case NODE_IF:{ 3190 DECL_ANCHOR(cond_seq); 3191 DECL_ANCHOR(then_seq); 3192 DECL_ANCHOR(else_seq); 3193 LABEL *then_label, *else_label, *end_label; 3194 3195 INIT_ANCHOR(cond_seq); 3196 INIT_ANCHOR(then_seq); 3197 INIT_ANCHOR(else_seq); 3198 then_label = NEW_LABEL(line); 3199 else_label = NEW_LABEL(line); 3200 end_label = NEW_LABEL(line); 3201 3202 compile_branch_condition(iseq, cond_seq, node->nd_cond, 3203 then_label, else_label); 3204 COMPILE_(then_seq, "then", node->nd_body, poped); 3205 COMPILE_(else_seq, "else", node->nd_else, poped); 3206 3207 ADD_SEQ(ret, cond_seq); 3208 3209 ADD_LABEL(ret, then_label); 3210 ADD_SEQ(ret, then_seq); 3211 ADD_INSNL(ret, line, jump, end_label); 3212 3213 ADD_LABEL(ret, else_label); 3214 ADD_SEQ(ret, else_seq); 3215 3216 ADD_LABEL(ret, end_label); 3217 3218 break; 3219 } 3220 case NODE_CASE:{ 3221 NODE *vals; 3222 NODE *tempnode = node; 3223 LABEL *endlabel, *elselabel; 3224 DECL_ANCHOR(head); 3225 DECL_ANCHOR(body_seq); 3226 DECL_ANCHOR(cond_seq); 3227 int only_special_literals = 1; 3228 VALUE literals = rb_hash_new(); 3229 3230 INIT_ANCHOR(head); 3231 INIT_ANCHOR(body_seq); 3232 INIT_ANCHOR(cond_seq); 3233 3234 RHASH_TBL(literals)->type = &cdhash_type; 3235 3236 if (node->nd_head == 0) { 3237 COMPILE_(ret, "when", node->nd_body, poped); 3238 break; 3239 } 3240 COMPILE(head, "case base", node->nd_head); 3241 3242 node = node->nd_body; 3243 type = nd_type(node); 3244 line = nd_line(node); 3245 3246 if (type != NODE_WHEN) { 3247 COMPILE_ERROR((ERROR_ARGS "NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type))); 3248 } 3249 3250 endlabel = NEW_LABEL(line); 3251 elselabel = NEW_LABEL(line); 3252 3253 ADD_SEQ(ret, head); /* case VAL */ 3254 3255 while (type == NODE_WHEN) { 3256 LABEL *l1; 3257 3258 l1 = NEW_LABEL(line); 3259 ADD_LABEL(body_seq, l1); 3260 ADD_INSN(body_seq, line, pop); 3261 COMPILE_(body_seq, "when body", node->nd_body, poped); 3262 ADD_INSNL(body_seq, line, jump, endlabel); 3263 3264 vals = node->nd_head; 3265 if (vals) { 3266 switch (nd_type(vals)) { 3267 case NODE_ARRAY: 3268 only_special_literals = when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals); 3269 break; 3270 case NODE_SPLAT: 3271 case NODE_ARGSCAT: 3272 case NODE_ARGSPUSH: 3273 only_special_literals = 0; 3274 ADD_INSN (cond_seq, nd_line(vals), dup); 3275 COMPILE(cond_seq, "when/cond splat", vals); 3276 ADD_INSN1(cond_seq, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY)); 3277 ADD_INSNL(cond_seq, nd_line(vals), branchif, l1); 3278 break; 3279 default: 3280 rb_bug("NODE_CASE: unknown node (%s)", 3281 ruby_node_name(nd_type(vals))); 3282 } 3283 } 3284 else { 3285 rb_bug("NODE_CASE: must be NODE_ARRAY, but 0"); 3286 } 3287 3288 node = node->nd_next; 3289 if (!node) { 3290 break; 3291 } 3292 type = nd_type(node); 3293 line = nd_line(node); 3294 } 3295 /* else */ 3296 if (node) { 3297 ADD_LABEL(cond_seq, elselabel); 3298 ADD_INSN(cond_seq, line, pop); 3299 COMPILE_(cond_seq, "else", node, poped); 3300 ADD_INSNL(cond_seq, line, jump, endlabel); 3301 } 3302 else { 3303 debugs("== else (implicit)\n"); 3304 ADD_LABEL(cond_seq, elselabel); 3305 ADD_INSN(cond_seq, nd_line(tempnode), pop); 3306 if (!poped) { 3307 ADD_INSN(cond_seq, nd_line(tempnode), putnil); 3308 } 3309 ADD_INSNL(cond_seq, nd_line(tempnode), jump, endlabel); 3310 } 3311 3312 if (only_special_literals) { 3313 iseq_add_mark_object(iseq, literals); 3314 3315 ADD_INSN(ret, nd_line(tempnode), dup); 3316 ADD_INSN2(ret, nd_line(tempnode), opt_case_dispatch, literals, elselabel); 3317 } 3318 3319 ADD_SEQ(ret, cond_seq); 3320 ADD_SEQ(ret, body_seq); 3321 ADD_LABEL(ret, endlabel); 3322 break; 3323 } 3324 case NODE_WHEN:{ 3325 NODE *vals; 3326 NODE *val; 3327 NODE *orig_node = node; 3328 LABEL *endlabel; 3329 DECL_ANCHOR(body_seq); 3330 3331 INIT_ANCHOR(body_seq); 3332 endlabel = NEW_LABEL(line); 3333 3334 while (node && nd_type(node) == NODE_WHEN) { 3335 LABEL *l1 = NEW_LABEL(line = nd_line(node)); 3336 ADD_LABEL(body_seq, l1); 3337 COMPILE_(body_seq, "when", node->nd_body, poped); 3338 ADD_INSNL(body_seq, line, jump, endlabel); 3339 3340 vals = node->nd_head; 3341 if (!vals) { 3342 rb_bug("NODE_WHEN: must be NODE_ARRAY, but 0"); 3343 } 3344 switch (nd_type(vals)) { 3345 case NODE_ARRAY: 3346 while (vals) { 3347 val = vals->nd_head; 3348 COMPILE(ret, "when2", val); 3349 ADD_INSNL(ret, nd_line(val), branchif, l1); 3350 vals = vals->nd_next; 3351 } 3352 break; 3353 case NODE_SPLAT: 3354 case NODE_ARGSCAT: 3355 case NODE_ARGSPUSH: 3356 ADD_INSN(ret, nd_line(vals), putnil); 3357 COMPILE(ret, "when2/cond splat", vals); 3358 ADD_INSN1(ret, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY)); 3359 ADD_INSNL(ret, nd_line(vals), branchif, l1); 3360 break; 3361 default: 3362 rb_bug("NODE_WHEN: unknown node (%s)", 3363 ruby_node_name(nd_type(vals))); 3364 } 3365 node = node->nd_next; 3366 } 3367 /* else */ 3368 COMPILE_(ret, "else", node, poped); 3369 ADD_INSNL(ret, nd_line(orig_node), jump, endlabel); 3370 3371 ADD_SEQ(ret, body_seq); 3372 ADD_LABEL(ret, endlabel); 3373 3374 break; 3375 } 3376 case NODE_OPT_N: 3377 case NODE_WHILE: 3378 case NODE_UNTIL:{ 3379 LABEL *prev_start_label = iseq->compile_data->start_label; 3380 LABEL *prev_end_label = iseq->compile_data->end_label; 3381 LABEL *prev_redo_label = iseq->compile_data->redo_label; 3382 int prev_loopval_popped = iseq->compile_data->loopval_popped; 3383 3384 struct iseq_compile_data_ensure_node_stack enl; 3385 3386 LABEL *next_label = iseq->compile_data->start_label = NEW_LABEL(line); /* next */ 3387 LABEL *redo_label = iseq->compile_data->redo_label = NEW_LABEL(line); /* redo */ 3388 LABEL *break_label = iseq->compile_data->end_label = NEW_LABEL(line); /* break */ 3389 LABEL *end_label = NEW_LABEL(line); 3390 3391 LABEL *next_catch_label = NEW_LABEL(line); 3392 LABEL *tmp_label = NULL; 3393 3394 iseq->compile_data->loopval_popped = 0; 3395 push_ensure_entry(iseq, &enl, 0, 0); 3396 3397 if (type == NODE_OPT_N || node->nd_state == 1) { 3398 ADD_INSNL(ret, line, jump, next_label); 3399 } 3400 else { 3401 tmp_label = NEW_LABEL(line); 3402 ADD_INSNL(ret, line, jump, tmp_label); 3403 } 3404 ADD_INSN(ret, line, putnil); 3405 ADD_LABEL(ret, next_catch_label); 3406 ADD_INSN(ret, line, pop); 3407 ADD_INSNL(ret, line, jump, next_label); 3408 if (tmp_label) ADD_LABEL(ret, tmp_label); 3409 3410 ADD_LABEL(ret, redo_label); 3411 COMPILE_POPED(ret, "while body", node->nd_body); 3412 ADD_LABEL(ret, next_label); /* next */ 3413 3414 if (type == NODE_WHILE) { 3415 compile_branch_condition(iseq, ret, node->nd_cond, 3416 redo_label, end_label); 3417 } 3418 else if (type == NODE_UNTIL) { 3419 /* untile */ 3420 compile_branch_condition(iseq, ret, node->nd_cond, 3421 end_label, redo_label); 3422 } 3423 else { 3424 ADD_CALL_RECEIVER(ret, line); 3425 ADD_CALL(ret, line, ID2SYM(idGets), INT2FIX(0)); 3426 ADD_INSNL(ret, line, branchif, redo_label); 3427 /* opt_n */ 3428 } 3429 3430 ADD_LABEL(ret, end_label); 3431 3432 if (node->nd_state == Qundef) { 3433 /* ADD_INSN(ret, line, putundef); */ 3434 rb_bug("unsupported: putundef"); 3435 } 3436 else { 3437 ADD_INSN(ret, line, putnil); 3438 } 3439 3440 ADD_LABEL(ret, break_label); /* break */ 3441 3442 if (poped) { 3443 ADD_INSN(ret, line, pop); 3444 } 3445 3446 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label, 3447 0, break_label); 3448 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label, 0, 3449 next_catch_label); 3450 ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, 0, 3451 iseq->compile_data->redo_label); 3452 3453 iseq->compile_data->start_label = prev_start_label; 3454 iseq->compile_data->end_label = prev_end_label; 3455 iseq->compile_data->redo_label = prev_redo_label; 3456 iseq->compile_data->loopval_popped = prev_loopval_popped; 3457 iseq->compile_data->ensure_node_stack = iseq->compile_data->ensure_node_stack->prev; 3458 break; 3459 } 3460 case NODE_ITER: 3461 case NODE_FOR:{ 3462 VALUE prevblock = iseq->compile_data->current_block; 3463 LABEL *retry_label = NEW_LABEL(line); 3464 LABEL *retry_end_l = NEW_LABEL(line); 3465 3466 ADD_LABEL(ret, retry_label); 3467 if (nd_type(node) == NODE_FOR) { 3468 COMPILE(ret, "iter caller (for)", node->nd_iter); 3469 3470 iseq->compile_data->current_block = 3471 NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), 3472 ISEQ_TYPE_BLOCK, line); 3473 3474 ADD_SEND_R(ret, line, ID2SYM(idEach), INT2FIX(0), 3475 iseq->compile_data->current_block, INT2FIX(0)); 3476 } 3477 else { 3478 iseq->compile_data->current_block = 3479 NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), 3480 ISEQ_TYPE_BLOCK, line); 3481 COMPILE(ret, "iter caller", node->nd_iter); 3482 } 3483 ADD_LABEL(ret, retry_end_l); 3484 3485 if (poped) { 3486 ADD_INSN(ret, line, pop); 3487 } 3488 3489 iseq->compile_data->current_block = prevblock; 3490 3491 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, 0, retry_end_l); 3492 3493 break; 3494 } 3495 case NODE_BREAK:{ 3496 unsigned long level = 0; 3497 3498 if (iseq->compile_data->redo_label != 0) { 3499 /* while/until */ 3500 LABEL *splabel = NEW_LABEL(0); 3501 ADD_LABEL(ret, splabel); 3502 ADD_ADJUST(ret, line, iseq->compile_data->redo_label); 3503 COMPILE_(ret, "break val (while/until)", node->nd_stts, iseq->compile_data->loopval_popped); 3504 add_ensure_iseq(ret, iseq, 0); 3505 ADD_INSNL(ret, line, jump, iseq->compile_data->end_label); 3506 ADD_ADJUST_RESTORE(ret, splabel); 3507 3508 if (!poped) { 3509 ADD_INSN(ret, line, putnil); 3510 } 3511 } 3512 else if (iseq->type == ISEQ_TYPE_BLOCK) { 3513 break_by_insn: 3514 /* escape from block */ 3515 COMPILE(ret, "break val (block)", node->nd_stts); 3516 ADD_INSN1(ret, line, throw, INT2FIX(level | 0x02) /* TAG_BREAK */ ); 3517 if (poped) { 3518 ADD_INSN(ret, line, pop); 3519 } 3520 } 3521 else if (iseq->type == ISEQ_TYPE_EVAL) { 3522 break_in_eval: 3523 COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with break")); 3524 } 3525 else { 3526 rb_iseq_t *ip = iseq->parent_iseq; 3527 while (ip) { 3528 if (!ip->compile_data) { 3529 ip = 0; 3530 break; 3531 } 3532 3533 level++; 3534 if (ip->compile_data->redo_label != 0) { 3535 level = 0x8000; 3536 if (ip->compile_data->loopval_popped == 0) { 3537 /* need value */ 3538 level |= 0x4000; 3539 } 3540 goto break_by_insn; 3541 } 3542 else if (ip->type == ISEQ_TYPE_BLOCK) { 3543 level <<= 16; 3544 goto break_by_insn; 3545 } 3546 else if (ip->type == ISEQ_TYPE_EVAL) { 3547 goto break_in_eval; 3548 } 3549 3550 ip = ip->parent_iseq; 3551 } 3552 COMPILE_ERROR((ERROR_ARGS "Invalid break")); 3553 } 3554 break; 3555 } 3556 case NODE_NEXT:{ 3557 unsigned long level = 0; 3558 3559 if (iseq->compile_data->redo_label != 0) { 3560 LABEL *splabel = NEW_LABEL(0); 3561 debugs("next in while loop\n"); 3562 ADD_LABEL(ret, splabel); 3563 COMPILE(ret, "next val/valid syntax?", node->nd_stts); 3564 add_ensure_iseq(ret, iseq, 0); 3565 ADD_ADJUST(ret, line, iseq->compile_data->redo_label); 3566 ADD_INSNL(ret, line, jump, iseq->compile_data->start_label); 3567 ADD_ADJUST_RESTORE(ret, splabel); 3568 if (!poped) { 3569 ADD_INSN(ret, line, putnil); 3570 } 3571 } 3572 else if (iseq->compile_data->end_label) { 3573 LABEL *splabel = NEW_LABEL(0); 3574 debugs("next in block\n"); 3575 ADD_LABEL(ret, splabel); 3576 ADD_ADJUST(ret, line, iseq->compile_data->start_label); 3577 COMPILE(ret, "next val", node->nd_stts); 3578 add_ensure_iseq(ret, iseq, 0); 3579 ADD_INSNL(ret, line, jump, iseq->compile_data->end_label); 3580 ADD_ADJUST_RESTORE(ret, splabel); 3581 3582 if (!poped) { 3583 ADD_INSN(ret, line, putnil); 3584 } 3585 } 3586 else if (iseq->type == ISEQ_TYPE_EVAL) { 3587 next_in_eval: 3588 COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with next")); 3589 } 3590 else { 3591 rb_iseq_t *ip; 3592 ip = iseq; 3593 while (ip) { 3594 if (!ip->compile_data) { 3595 ip = 0; 3596 break; 3597 } 3598 3599 level = 0x8000 | 0x4000; 3600 if (ip->compile_data->redo_label != 0) { 3601 /* while loop */ 3602 break; 3603 } 3604 else if (ip->type == ISEQ_TYPE_BLOCK) { 3605 break; 3606 } 3607 else if (ip->type == ISEQ_TYPE_EVAL) { 3608 goto next_in_eval; 3609 } 3610 3611 ip = ip->parent_iseq; 3612 } 3613 if (ip != 0) { 3614 COMPILE(ret, "next val", node->nd_stts); 3615 ADD_INSN1(ret, line, throw, INT2FIX(level | 0x03) /* TAG_NEXT */ ); 3616 3617 if (poped) { 3618 ADD_INSN(ret, line, pop); 3619 } 3620 } 3621 else { 3622 COMPILE_ERROR((ERROR_ARGS "Invalid next")); 3623 } 3624 } 3625 break; 3626 } 3627 case NODE_REDO:{ 3628 if (iseq->compile_data->redo_label) { 3629 LABEL *splabel = NEW_LABEL(0); 3630 debugs("redo in while"); 3631 ADD_LABEL(ret, splabel); 3632 ADD_ADJUST(ret, line, iseq->compile_data->redo_label); 3633 add_ensure_iseq(ret, iseq, 0); 3634 ADD_INSNL(ret, line, jump, iseq->compile_data->redo_label); 3635 ADD_ADJUST_RESTORE(ret, splabel); 3636 if (!poped) { 3637 ADD_INSN(ret, line, putnil); 3638 } 3639 } 3640 else if (iseq->type == ISEQ_TYPE_EVAL) { 3641 redo_in_eval: 3642 COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with redo")); 3643 } 3644 else if (iseq->compile_data->start_label) { 3645 LABEL *splabel = NEW_LABEL(0); 3646 3647 debugs("redo in block"); 3648 ADD_LABEL(ret, splabel); 3649 add_ensure_iseq(ret, iseq, 0); 3650 ADD_ADJUST(ret, line, iseq->compile_data->start_label); 3651 ADD_INSNL(ret, line, jump, iseq->compile_data->start_label); 3652 ADD_ADJUST_RESTORE(ret, splabel); 3653 3654 if (!poped) { 3655 ADD_INSN(ret, line, putnil); 3656 } 3657 } 3658 else { 3659 rb_iseq_t *ip; 3660 unsigned long level; 3661 level = 0x8000 | 0x4000; 3662 ip = iseq; 3663 while (ip) { 3664 if (!ip->compile_data) { 3665 ip = 0; 3666 break; 3667 } 3668 3669 if (ip->compile_data->redo_label != 0) { 3670 break; 3671 } 3672 else if (ip->type == ISEQ_TYPE_BLOCK) { 3673 break; 3674 } 3675 else if (ip->type == ISEQ_TYPE_EVAL) { 3676 goto redo_in_eval; 3677 } 3678 3679 ip = ip->parent_iseq; 3680 } 3681 if (ip != 0) { 3682 ADD_INSN(ret, line, putnil); 3683 ADD_INSN1(ret, line, throw, INT2FIX(level | 0x05) /* TAG_REDO */ ); 3684 3685 if (poped) { 3686 ADD_INSN(ret, line, pop); 3687 } 3688 } 3689 else { 3690 COMPILE_ERROR((ERROR_ARGS "Invalid redo")); 3691 } 3692 } 3693 break; 3694 } 3695 case NODE_RETRY:{ 3696 if (iseq->type == ISEQ_TYPE_RESCUE) { 3697 ADD_INSN(ret, line, putnil); 3698 ADD_INSN1(ret, line, throw, INT2FIX(0x04) /* TAG_RETRY */ ); 3699 3700 if (poped) { 3701 ADD_INSN(ret, line, pop); 3702 } 3703 } 3704 else { 3705 COMPILE_ERROR((ERROR_ARGS "Invalid retry")); 3706 } 3707 break; 3708 } 3709 case NODE_BEGIN:{ 3710 COMPILE_(ret, "NODE_BEGIN", node->nd_body, poped); 3711 break; 3712 } 3713 case NODE_RESCUE:{ 3714 LABEL *lstart = NEW_LABEL(line); 3715 LABEL *lend = NEW_LABEL(line); 3716 LABEL *lcont = NEW_LABEL(line); 3717 VALUE rescue = NEW_CHILD_ISEQVAL( 3718 node->nd_resq, 3719 rb_str_concat(rb_str_new2("rescue in "), iseq->location.label), 3720 ISEQ_TYPE_RESCUE, line); 3721 3722 ADD_LABEL(ret, lstart); 3723 COMPILE(ret, "rescue head", node->nd_head); 3724 ADD_LABEL(ret, lend); 3725 if (node->nd_else) { 3726 ADD_INSN(ret, line, pop); 3727 COMPILE(ret, "rescue else", node->nd_else); 3728 } 3729 ADD_INSN(ret, line, nop); 3730 ADD_LABEL(ret, lcont); 3731 3732 if (poped) { 3733 ADD_INSN(ret, line, pop); 3734 } 3735 3736 /* register catch entry */ 3737 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lcont); 3738 ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, 0, lstart); 3739 break; 3740 } 3741 case NODE_RESBODY:{ 3742 NODE *resq = node; 3743 NODE *narg; 3744 LABEL *label_miss, *label_hit; 3745 3746 while (resq) { 3747 label_miss = NEW_LABEL(line); 3748 label_hit = NEW_LABEL(line); 3749 3750 narg = resq->nd_args; 3751 if (narg) { 3752 switch (nd_type(narg)) { 3753 case NODE_ARRAY: 3754 while (narg) { 3755 ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0)); 3756 COMPILE(ret, "rescue arg", narg->nd_head); 3757 ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); 3758 ADD_INSNL(ret, line, branchif, label_hit); 3759 narg = narg->nd_next; 3760 } 3761 break; 3762 case NODE_SPLAT: 3763 case NODE_ARGSCAT: 3764 case NODE_ARGSPUSH: 3765 ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0)); 3766 COMPILE(ret, "rescue/cond splat", narg); 3767 ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE | VM_CHECKMATCH_ARRAY)); 3768 ADD_INSNL(ret, line, branchif, label_hit); 3769 break; 3770 default: 3771 rb_bug("NODE_RESBODY: unknown node (%s)", 3772 ruby_node_name(nd_type(narg))); 3773 } 3774 } 3775 else { 3776 ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0)); 3777 ADD_INSN1(ret, line, putobject, rb_eStandardError); 3778 ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); 3779 ADD_INSNL(ret, line, branchif, label_hit); 3780 } 3781 ADD_INSNL(ret, line, jump, label_miss); 3782 ADD_LABEL(ret, label_hit); 3783 COMPILE(ret, "resbody body", resq->nd_body); 3784 if (iseq->compile_data->option->tailcall_optimization) { 3785 ADD_INSN(ret, line, nop); 3786 } 3787 ADD_INSN(ret, line, leave); 3788 ADD_LABEL(ret, label_miss); 3789 resq = resq->nd_head; 3790 } 3791 break; 3792 } 3793 case NODE_ENSURE:{ 3794 DECL_ANCHOR(ensr); 3795 VALUE ensure = NEW_CHILD_ISEQVAL(node->nd_ensr, 3796 rb_str_concat(rb_str_new2 3797 ("ensure in "), 3798 iseq->location.label), 3799 ISEQ_TYPE_ENSURE, line); 3800 LABEL *lstart = NEW_LABEL(line); 3801 LABEL *lend = NEW_LABEL(line); 3802 LABEL *lcont = NEW_LABEL(line); 3803 struct ensure_range er; 3804 struct iseq_compile_data_ensure_node_stack enl; 3805 struct ensure_range *erange; 3806 3807 INIT_ANCHOR(ensr); 3808 COMPILE_POPED(ensr, "ensure ensr", node->nd_ensr); 3809 3810 er.begin = lstart; 3811 er.end = lend; 3812 er.next = 0; 3813 push_ensure_entry(iseq, &enl, &er, node->nd_ensr); 3814 3815 ADD_LABEL(ret, lstart); 3816 COMPILE_(ret, "ensure head", node->nd_head, poped); 3817 ADD_LABEL(ret, lend); 3818 if (ensr->anchor.next == 0) { 3819 ADD_INSN(ret, line, nop); 3820 } 3821 else { 3822 ADD_SEQ(ret, ensr); 3823 } 3824 ADD_LABEL(ret, lcont); 3825 3826 erange = iseq->compile_data->ensure_node_stack->erange; 3827 while (erange) { 3828 ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end, 3829 ensure, lcont); 3830 erange = erange->next; 3831 } 3832 3833 iseq->compile_data->ensure_node_stack = enl.prev; 3834 break; 3835 } 3836 3837 case NODE_AND: 3838 case NODE_OR:{ 3839 LABEL *end_label = NEW_LABEL(line); 3840 COMPILE(ret, "nd_1st", node->nd_1st); 3841 if (!poped) { 3842 ADD_INSN(ret, line, dup); 3843 } 3844 if (type == NODE_AND) { 3845 ADD_INSNL(ret, line, branchunless, end_label); 3846 } 3847 else { 3848 ADD_INSNL(ret, line, branchif, end_label); 3849 } 3850 if (!poped) { 3851 ADD_INSN(ret, line, pop); 3852 } 3853 COMPILE_(ret, "nd_2nd", node->nd_2nd, poped); 3854 ADD_LABEL(ret, end_label); 3855 break; 3856 } 3857 3858 case NODE_MASGN:{ 3859 compile_massign(iseq, ret, node, poped); 3860 break; 3861 } 3862 3863 case NODE_LASGN:{ 3864 ID id = node->nd_vid; 3865 int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id); 3866 3867 debugs("lvar: %s idx: %d\n", rb_id2name(id), idx); 3868 COMPILE(ret, "rvalue", node->nd_value); 3869 3870 if (!poped) { 3871 ADD_INSN(ret, line, dup); 3872 } 3873 ADD_INSN2(ret, line, setlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq))); 3874 3875 break; 3876 } 3877 case NODE_DASGN: 3878 case NODE_DASGN_CURR:{ 3879 int idx, lv, ls; 3880 COMPILE(ret, "dvalue", node->nd_value); 3881 debugp_param("dassn id", rb_str_new2(rb_id2name(node->nd_vid) ? rb_id2name(node->nd_vid) : "*")); 3882 3883 if (!poped) { 3884 ADD_INSN(ret, line, dup); 3885 } 3886 3887 idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls); 3888 3889 if (idx < 0) { 3890 rb_bug("NODE_DASGN(_CURR): unknown id (%s)", rb_id2name(node->nd_vid)); 3891 } 3892 3893 ADD_INSN2(ret, line, setlocal, INT2FIX(ls - idx), INT2FIX(lv)); 3894 break; 3895 } 3896 case NODE_GASGN:{ 3897 COMPILE(ret, "lvalue", node->nd_value); 3898 3899 if (!poped) { 3900 ADD_INSN(ret, line, dup); 3901 } 3902 ADD_INSN1(ret, line, setglobal, 3903 ((VALUE)node->nd_entry | 1)); 3904 break; 3905 } 3906 case NODE_IASGN: 3907 case NODE_IASGN2:{ 3908 COMPILE(ret, "lvalue", node->nd_value); 3909 if (!poped) { 3910 ADD_INSN(ret, line, dup); 3911 } 3912 ADD_INSN2(ret, line, setinstancevariable, 3913 ID2SYM(node->nd_vid), INT2FIX(iseq->ic_size++)); 3914 break; 3915 } 3916 case NODE_CDECL:{ 3917 COMPILE(ret, "lvalue", node->nd_value); 3918 3919 if (!poped) { 3920 ADD_INSN(ret, line, dup); 3921 } 3922 3923 if (node->nd_vid) { 3924 ADD_INSN1(ret, line, putspecialobject, 3925 INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); 3926 ADD_INSN1(ret, line, setconstant, ID2SYM(node->nd_vid)); 3927 } 3928 else { 3929 compile_cpath(ret, iseq, node->nd_else); 3930 ADD_INSN1(ret, line, setconstant, ID2SYM(node->nd_else->nd_mid)); 3931 } 3932 break; 3933 } 3934 case NODE_CVASGN:{ 3935 COMPILE(ret, "cvasgn val", node->nd_value); 3936 if (!poped) { 3937 ADD_INSN(ret, line, dup); 3938 } 3939 ADD_INSN1(ret, line, setclassvariable, 3940 ID2SYM(node->nd_vid)); 3941 break; 3942 } 3943 case NODE_OP_ASGN1: { 3944 DECL_ANCHOR(args); 3945 VALUE argc; 3946 VALUE flag = 0; 3947 ID id = node->nd_mid; 3948 int boff = 0; 3949 3950 /* 3951 * a[x] (op)= y 3952 * 3953 * nil # nil 3954 * eval a # nil a 3955 * eval x # nil a x 3956 * dupn 2 # nil a x a x 3957 * send :[] # nil a x a[x] 3958 * eval y # nil a x a[x] y 3959 * send op # nil a x ret 3960 * setn 3 # ret a x ret 3961 * send []= # ret ? 3962 * pop # ret 3963 */ 3964 3965 /* 3966 * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head; 3967 * NODE_OP_ASGN nd_recv 3968 * nd_args->nd_head 3969 * nd_args->nd_body 3970 * nd_mid 3971 */ 3972 3973 if (!poped) { 3974 ADD_INSN(ret, line, putnil); 3975 } 3976 COMPILE(ret, "NODE_OP_ASGN1 recv", node->nd_recv); 3977 switch (nd_type(node->nd_args->nd_head)) { 3978 case NODE_ZARRAY: 3979 argc = INT2FIX(0); 3980 break; 3981 case NODE_BLOCK_PASS: 3982 boff = 1; 3983 default: 3984 INIT_ANCHOR(args); 3985 argc = setup_args(iseq, args, node->nd_args->nd_head, &flag); 3986 ADD_SEQ(ret, args); 3987 } 3988 ADD_INSN1(ret, line, dupn, FIXNUM_INC(argc, 1 + boff)); 3989 ADD_SEND_R(ret, line, ID2SYM(idAREF), argc, Qfalse, LONG2FIX(flag)); 3990 3991 if (id == 0 || id == 1) { 3992 /* 0: or, 1: and 3993 a[x] ||= y 3994 3995 unless/if a[x] 3996 a[x]= y 3997 else 3998 nil 3999 end 4000 */ 4001 LABEL *label = NEW_LABEL(line); 4002 LABEL *lfin = NEW_LABEL(line); 4003 4004 ADD_INSN(ret, line, dup); 4005 if (id == 0) { 4006 /* or */ 4007 ADD_INSNL(ret, line, branchif, label); 4008 } 4009 else { 4010 /* and */ 4011 ADD_INSNL(ret, line, branchunless, label); 4012 } 4013 ADD_INSN(ret, line, pop); 4014 4015 COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body); 4016 if (!poped) { 4017 ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff)); 4018 } 4019 if (flag & VM_CALL_ARGS_SPLAT) { 4020 ADD_INSN1(ret, line, newarray, INT2FIX(1)); 4021 if (boff > 0) { 4022 ADD_INSN1(ret, line, dupn, INT2FIX(3)); 4023 ADD_INSN(ret, line, swap); 4024 ADD_INSN(ret, line, pop); 4025 } 4026 ADD_INSN(ret, line, concatarray); 4027 if (boff > 0) { 4028 ADD_INSN1(ret, line, setn, INT2FIX(3)); 4029 ADD_INSN(ret, line, pop); 4030 ADD_INSN(ret, line, pop); 4031 } 4032 ADD_SEND_R(ret, line, ID2SYM(idASET), 4033 argc, Qfalse, LONG2FIX(flag)); 4034 } 4035 else { 4036 if (boff > 0) 4037 ADD_INSN(ret, line, swap); 4038 ADD_SEND_R(ret, line, ID2SYM(idASET), 4039 FIXNUM_INC(argc, 1), Qfalse, LONG2FIX(flag)); 4040 } 4041 ADD_INSN(ret, line, pop); 4042 ADD_INSNL(ret, line, jump, lfin); 4043 ADD_LABEL(ret, label); 4044 if (!poped) { 4045 ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff)); 4046 } 4047 ADD_INSN1(ret, line, adjuststack, FIXNUM_INC(argc, 2+boff)); 4048 ADD_LABEL(ret, lfin); 4049 } 4050 else { 4051 COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body); 4052 ADD_SEND(ret, line, ID2SYM(id), INT2FIX(1)); 4053 if (!poped) { 4054 ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff)); 4055 } 4056 if (flag & VM_CALL_ARGS_SPLAT) { 4057 ADD_INSN1(ret, line, newarray, INT2FIX(1)); 4058 if (boff > 0) { 4059 ADD_INSN1(ret, line, dupn, INT2FIX(3)); 4060 ADD_INSN(ret, line, swap); 4061 ADD_INSN(ret, line, pop); 4062 } 4063 ADD_INSN(ret, line, concatarray); 4064 if (boff > 0) { 4065 ADD_INSN1(ret, line, setn, INT2FIX(3)); 4066 ADD_INSN(ret, line, pop); 4067 ADD_INSN(ret, line, pop); 4068 } 4069 ADD_SEND_R(ret, line, ID2SYM(idASET), 4070 argc, Qfalse, LONG2FIX(flag)); 4071 } 4072 else { 4073 if (boff > 0) 4074 ADD_INSN(ret, line, swap); 4075 ADD_SEND_R(ret, line, ID2SYM(idASET), 4076 FIXNUM_INC(argc, 1), Qfalse, LONG2FIX(flag)); 4077 } 4078 ADD_INSN(ret, line, pop); 4079 } 4080 4081 break; 4082 } 4083 case NODE_OP_ASGN2:{ 4084 ID atype = node->nd_next->nd_mid; 4085 LABEL *lfin = NEW_LABEL(line); 4086 LABEL *lcfin = NEW_LABEL(line); 4087 /* 4088 class C; attr_accessor :c; end 4089 r = C.new 4090 r.a &&= v # asgn2 4091 4092 eval r # r 4093 dup # r r 4094 eval r.a # r o 4095 4096 # or 4097 dup # r o o 4098 if lcfin # r o 4099 pop # r 4100 eval v # r v 4101 swap # v r 4102 topn 1 # v r v 4103 send a= # v ? 4104 jump lfin # v ? 4105 4106 lcfin: # r o 4107 swap # o r 4108 4109 lfin: # o ? 4110 pop # o 4111 4112 # and 4113 dup # r o o 4114 unless lcfin 4115 pop # r 4116 eval v # r v 4117 swap # v r 4118 topn 1 # v r v 4119 send a= # v ? 4120 jump lfin # v ? 4121 4122 # others 4123 eval v # r o v 4124 send ?? # r w 4125 send a= # w 4126 4127 */ 4128 4129 COMPILE(ret, "NODE_OP_ASGN2#recv", node->nd_recv); 4130 ADD_INSN(ret, line, dup); 4131 ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_vid), 4132 INT2FIX(0)); 4133 4134 if (atype == 0 || atype == 1) { /* 0: OR or 1: AND */ 4135 ADD_INSN(ret, line, dup); 4136 if (atype == 0) { 4137 ADD_INSNL(ret, line, branchif, lcfin); 4138 } 4139 else { 4140 ADD_INSNL(ret, line, branchunless, lcfin); 4141 } 4142 ADD_INSN(ret, line, pop); 4143 COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value); 4144 ADD_INSN(ret, line, swap); 4145 ADD_INSN1(ret, line, topn, INT2FIX(1)); 4146 ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_aid), 4147 INT2FIX(1)); 4148 ADD_INSNL(ret, line, jump, lfin); 4149 4150 ADD_LABEL(ret, lcfin); 4151 ADD_INSN(ret, line, swap); 4152 4153 ADD_LABEL(ret, lfin); 4154 ADD_INSN(ret, line, pop); 4155 if (poped) { 4156 /* we can apply more optimize */ 4157 ADD_INSN(ret, line, pop); 4158 } 4159 } 4160 else { 4161 COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value); 4162 ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_mid), 4163 INT2FIX(1)); 4164 if (!poped) { 4165 ADD_INSN(ret, line, swap); 4166 ADD_INSN1(ret, line, topn, INT2FIX(1)); 4167 } 4168 ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_aid), 4169 INT2FIX(1)); 4170 ADD_INSN(ret, line, pop); 4171 } 4172 break; 4173 } 4174 case NODE_OP_CDECL: { 4175 LABEL *lfin = 0; 4176 LABEL *lassign = 0; 4177 ID mid; 4178 4179 switch (nd_type(node->nd_head)) { 4180 case NODE_COLON3: 4181 ADD_INSN1(ret, line, putobject, rb_cObject); 4182 break; 4183 case NODE_COLON2: 4184 COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head); 4185 break; 4186 default: 4187 do { 4188 COMPILE_ERROR((ERROR_ARGS "%s: invalid node in NODE_OP_CDECL", 4189 ruby_node_name(nd_type(node->nd_head)))); 4190 } while (0); 4191 return COMPILE_NG; 4192 } 4193 mid = node->nd_head->nd_mid; 4194 /* cref */ 4195 if (node->nd_aid == 0) { 4196 lassign = NEW_LABEL(line); 4197 ADD_INSN(ret, line, dup); /* cref cref */ 4198 ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_CONST), 4199 ID2SYM(mid), Qfalse); /* cref bool */ 4200 ADD_INSNL(ret, line, branchunless, lassign); /* cref */ 4201 } 4202 ADD_INSN(ret, line, dup); /* cref cref */ 4203 ADD_INSN1(ret, line, getconstant, ID2SYM(mid)); /* cref obj */ 4204 4205 if (node->nd_aid == 0 || node->nd_aid == 1) { 4206 lfin = NEW_LABEL(line); 4207 if (!poped) ADD_INSN(ret, line, dup); /* cref [obj] obj */ 4208 if (node->nd_aid == 0) 4209 ADD_INSNL(ret, line, branchif, lfin); 4210 else 4211 ADD_INSNL(ret, line, branchunless, lfin); 4212 /* cref [obj] */ 4213 if (!poped) ADD_INSN(ret, line, pop); /* cref */ 4214 if (lassign) ADD_LABEL(ret, lassign); 4215 COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value); 4216 /* cref value */ 4217 if (poped) 4218 ADD_INSN1(ret, line, topn, INT2FIX(1)); /* cref value cref */ 4219 else { 4220 ADD_INSN1(ret, line, dupn, INT2FIX(2)); /* cref value cref value */ 4221 ADD_INSN(ret, line, swap); /* cref value value cref */ 4222 } 4223 ADD_INSN1(ret, line, setconstant, ID2SYM(mid)); /* cref [value] */ 4224 ADD_LABEL(ret, lfin); /* cref [value] */ 4225 if (!poped) ADD_INSN(ret, line, swap); /* [value] cref */ 4226 ADD_INSN(ret, line, pop); /* [value] */ 4227 } 4228 else { 4229 COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value); 4230 /* cref obj value */ 4231 ADD_CALL(ret, line, ID2SYM(node->nd_aid), INT2FIX(1)); 4232 /* cref value */ 4233 ADD_INSN(ret, line, swap); /* value cref */ 4234 if (!poped) { 4235 ADD_INSN1(ret, line, topn, INT2FIX(1)); /* value cref value */ 4236 ADD_INSN(ret, line, swap); /* value value cref */ 4237 } 4238 ADD_INSN1(ret, line, setconstant, ID2SYM(mid)); 4239 } 4240 break; 4241 } 4242 case NODE_OP_ASGN_AND: 4243 case NODE_OP_ASGN_OR:{ 4244 LABEL *lfin = NEW_LABEL(line); 4245 LABEL *lassign; 4246 4247 if (nd_type(node) == NODE_OP_ASGN_OR) { 4248 LABEL *lfinish[2]; 4249 lfinish[0] = lfin; 4250 lfinish[1] = 0; 4251 defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse); 4252 lassign = lfinish[1]; 4253 if (!lassign) { 4254 lassign = NEW_LABEL(line); 4255 } 4256 ADD_INSNL(ret, line, branchunless, lassign); 4257 } 4258 else { 4259 lassign = NEW_LABEL(line); 4260 } 4261 4262 COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head); 4263 ADD_INSN(ret, line, dup); 4264 4265 if (nd_type(node) == NODE_OP_ASGN_AND) { 4266 ADD_INSNL(ret, line, branchunless, lfin); 4267 } 4268 else { 4269 ADD_INSNL(ret, line, branchif, lfin); 4270 } 4271 4272 ADD_INSN(ret, line, pop); 4273 ADD_LABEL(ret, lassign); 4274 COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value); 4275 ADD_LABEL(ret, lfin); 4276 4277 if (poped) { 4278 /* we can apply more optimize */ 4279 ADD_INSN(ret, line, pop); 4280 } 4281 break; 4282 } 4283 case NODE_CALL: 4284 case NODE_FCALL: 4285 case NODE_VCALL:{ /* VCALL: variable or call */ 4286 /* 4287 call: obj.method(...) 4288 fcall: func(...) 4289 vcall: func 4290 */ 4291 DECL_ANCHOR(recv); 4292 DECL_ANCHOR(args); 4293 ID mid = node->nd_mid; 4294 VALUE argc; 4295 VALUE flag = 0; 4296 VALUE parent_block = iseq->compile_data->current_block; 4297 iseq->compile_data->current_block = Qfalse; 4298 4299 INIT_ANCHOR(recv); 4300 INIT_ANCHOR(args); 4301#if SUPPORT_JOKE 4302 if (nd_type(node) == NODE_VCALL) { 4303 ID id_bitblt; 4304 ID id_answer; 4305 4306 CONST_ID(id_bitblt, "bitblt"); 4307 CONST_ID(id_answer, "the_answer_to_life_the_universe_and_everything"); 4308 4309 if (mid == id_bitblt) { 4310 ADD_INSN(ret, line, bitblt); 4311 break; 4312 } 4313 else if (mid == id_answer) { 4314 ADD_INSN(ret, line, answer); 4315 break; 4316 } 4317 } 4318 /* only joke */ 4319 { 4320 ID goto_id; 4321 ID label_id; 4322 4323 CONST_ID(goto_id, "__goto__"); 4324 CONST_ID(label_id, "__label__"); 4325 4326 if (nd_type(node) == NODE_FCALL && 4327 (mid == goto_id || mid == label_id)) { 4328 LABEL *label; 4329 st_data_t data; 4330 st_table *labels_table = iseq->compile_data->labels_table; 4331 ID label_name; 4332 4333 if (!labels_table) { 4334 labels_table = st_init_numtable(); 4335 iseq->compile_data->labels_table = labels_table; 4336 } 4337 if (nd_type(node->nd_args->nd_head) == NODE_LIT && 4338 SYMBOL_P(node->nd_args->nd_head->nd_lit)) { 4339 4340 label_name = SYM2ID(node->nd_args->nd_head->nd_lit); 4341 if (!st_lookup(labels_table, (st_data_t)label_name, &data)) { 4342 label = NEW_LABEL(line); 4343 label->position = line; 4344 st_insert(labels_table, (st_data_t)label_name, (st_data_t)label); 4345 } 4346 else { 4347 label = (LABEL *)data; 4348 } 4349 } 4350 else { 4351 COMPILE_ERROR((ERROR_ARGS "invalid goto/label format")); 4352 } 4353 4354 4355 if (mid == goto_id) { 4356 ADD_INSNL(ret, line, jump, label); 4357 } 4358 else { 4359 ADD_LABEL(ret, label); 4360 } 4361 break; 4362 } 4363 } 4364#endif 4365 /* receiver */ 4366 if (type == NODE_CALL) { 4367 COMPILE(recv, "recv", node->nd_recv); 4368 } 4369 else if (type == NODE_FCALL || type == NODE_VCALL) { 4370 ADD_CALL_RECEIVER(recv, line); 4371 } 4372 4373 /* args */ 4374 if (nd_type(node) != NODE_VCALL) { 4375 argc = setup_args(iseq, args, node->nd_args, &flag); 4376 } 4377 else { 4378 argc = INT2FIX(0); 4379 } 4380 4381 ADD_SEQ(ret, recv); 4382 ADD_SEQ(ret, args); 4383 4384 debugp_param("call args argc", argc); 4385 debugp_param("call method", ID2SYM(mid)); 4386 4387 switch (nd_type(node)) { 4388 case NODE_VCALL: 4389 flag |= VM_CALL_VCALL; 4390 /* VCALL is funcall, so fall through */ 4391 case NODE_FCALL: 4392 flag |= VM_CALL_FCALL; 4393 } 4394 4395 ADD_SEND_R(ret, line, ID2SYM(mid), 4396 argc, parent_block, LONG2FIX(flag)); 4397 4398 if (poped) { 4399 ADD_INSN(ret, line, pop); 4400 } 4401 break; 4402 } 4403 case NODE_SUPER: 4404 case NODE_ZSUPER:{ 4405 DECL_ANCHOR(args); 4406 int argc; 4407 VALUE flag = 0; 4408 VALUE parent_block = iseq->compile_data->current_block; 4409 4410 INIT_ANCHOR(args); 4411 iseq->compile_data->current_block = Qfalse; 4412 if (nd_type(node) == NODE_SUPER) { 4413 VALUE vargc = setup_args(iseq, args, node->nd_args, &flag); 4414 argc = FIX2INT(vargc); 4415 } 4416 else { 4417 /* NODE_ZSUPER */ 4418 int i; 4419 rb_iseq_t *liseq = iseq->local_iseq; 4420 int lvar_level = get_lvar_level(iseq); 4421 4422 argc = liseq->argc; 4423 4424 /* normal arguments */ 4425 for (i = 0; i < liseq->argc; i++) { 4426 int idx = liseq->local_size - i; 4427 ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); 4428 } 4429 4430 if (!liseq->arg_simple) { 4431 if (liseq->arg_opts) { 4432 /* optional arguments */ 4433 int j; 4434 for (j = 0; j < liseq->arg_opts - 1; j++) { 4435 int idx = liseq->local_size - (i + j); 4436 ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); 4437 } 4438 i += j; 4439 argc = i; 4440 } 4441 4442 if (liseq->arg_rest != -1) { 4443 /* rest argument */ 4444 int idx = liseq->local_size - liseq->arg_rest; 4445 ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); 4446 argc = liseq->arg_rest + 1; 4447 flag |= VM_CALL_ARGS_SPLAT; 4448 } 4449 4450 if (liseq->arg_post_len) { 4451 /* post arguments */ 4452 int post_len = liseq->arg_post_len; 4453 int post_start = liseq->arg_post_start; 4454 4455 if (liseq->arg_rest != -1) { 4456 int j; 4457 for (j=0; j<post_len; j++) { 4458 int idx = liseq->local_size - (post_start + j); 4459 ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); 4460 } 4461 ADD_INSN1(args, line, newarray, INT2FIX(j)); 4462 ADD_INSN (args, line, concatarray); 4463 /* argc is setteled at above */ 4464 } 4465 else { 4466 int j; 4467 for (j=0; j<post_len; j++) { 4468 int idx = liseq->local_size - (post_start + j); 4469 ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); 4470 } 4471 argc = post_len + post_start; 4472 } 4473 } 4474 4475 if (liseq->arg_keyword >= 0) { 4476 int local_size = liseq->local_size; 4477 int idx = local_size - liseq->arg_keyword; 4478 argc++; 4479 ADD_INSN1(args, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 4480 ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); 4481 ADD_SEND (args, line, ID2SYM(rb_intern("dup")), INT2FIX(0)); 4482 for (i = 0; i < liseq->arg_keywords; ++i) { 4483 ID id = liseq->arg_keyword_table[i]; 4484 idx = local_size - get_local_var_idx(liseq, id); 4485 ADD_INSN1(args, line, putobject, ID2SYM(id)); 4486 ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); 4487 } 4488 ADD_SEND(args, line, ID2SYM(id_core_hash_merge_ptr), INT2FIX(i * 2 + 1)); 4489 if (liseq->arg_rest != -1) { 4490 ADD_INSN1(args, line, newarray, INT2FIX(1)); 4491 ADD_INSN (args, line, concatarray); 4492 --argc; 4493 } 4494 } 4495 } 4496 } 4497 4498 /* dummy receiver */ 4499 ADD_INSN1(ret, line, putobject, nd_type(node) == NODE_ZSUPER ? Qfalse : Qtrue); 4500 ADD_SEQ(ret, args); 4501 ADD_INSN1(ret, line, invokesuper, new_callinfo(iseq, 0, argc, parent_block, 4502 flag | VM_CALL_SUPER | VM_CALL_FCALL)); 4503 4504 if (poped) { 4505 ADD_INSN(ret, line, pop); 4506 } 4507 break; 4508 } 4509 case NODE_ARRAY:{ 4510 compile_array_(iseq, ret, node, COMPILE_ARRAY_TYPE_ARRAY, poped); 4511 break; 4512 } 4513 case NODE_ZARRAY:{ 4514 if (!poped) { 4515 ADD_INSN1(ret, line, newarray, INT2FIX(0)); 4516 } 4517 break; 4518 } 4519 case NODE_VALUES:{ 4520 NODE *n = node; 4521 while (n) { 4522 COMPILE(ret, "values item", n->nd_head); 4523 n = n->nd_next; 4524 } 4525 ADD_INSN1(ret, line, newarray, INT2FIX(node->nd_alen)); 4526 if (poped) { 4527 ADD_INSN(ret, line, pop); 4528 } 4529 break; 4530 } 4531 case NODE_HASH:{ 4532 DECL_ANCHOR(list); 4533 int type = node->nd_head ? nd_type(node->nd_head) : NODE_ZARRAY; 4534 4535 INIT_ANCHOR(list); 4536 switch (type) { 4537 case NODE_ARRAY: 4538 compile_array(iseq, list, node->nd_head, COMPILE_ARRAY_TYPE_HASH); 4539 ADD_SEQ(ret, list); 4540 break; 4541 4542 case NODE_ZARRAY: 4543 ADD_INSN1(ret, line, newhash, INT2FIX(0)); 4544 break; 4545 4546 default: 4547 rb_bug("can't make hash with this node: %s", ruby_node_name(type)); 4548 } 4549 4550 if (poped) { 4551 ADD_INSN(ret, line, pop); 4552 } 4553 break; 4554 } 4555 case NODE_RETURN:{ 4556 rb_iseq_t *is = iseq; 4557 4558 if (is) { 4559 if (is->type == ISEQ_TYPE_TOP) { 4560 COMPILE_ERROR((ERROR_ARGS "Invalid return")); 4561 } 4562 else { 4563 LABEL *splabel = 0; 4564 4565 if (is->type == ISEQ_TYPE_METHOD) { 4566 splabel = NEW_LABEL(0); 4567 ADD_LABEL(ret, splabel); 4568 ADD_ADJUST(ret, line, 0); 4569 } 4570 4571 COMPILE(ret, "return nd_stts (return val)", node->nd_stts); 4572 4573 if (is->type == ISEQ_TYPE_METHOD) { 4574 add_ensure_iseq(ret, iseq, 1); 4575 ADD_TRACE(ret, line, RUBY_EVENT_RETURN); 4576 ADD_INSN(ret, line, leave); 4577 ADD_ADJUST_RESTORE(ret, splabel); 4578 4579 if (!poped) { 4580 ADD_INSN(ret, line, putnil); 4581 } 4582 } 4583 else { 4584 ADD_INSN1(ret, line, throw, INT2FIX(0x01) /* TAG_RETURN */ ); 4585 if (poped) { 4586 ADD_INSN(ret, line, pop); 4587 } 4588 } 4589 } 4590 } 4591 break; 4592 } 4593 case NODE_YIELD:{ 4594 DECL_ANCHOR(args); 4595 VALUE argc; 4596 VALUE flag = 0; 4597 4598 INIT_ANCHOR(args); 4599 if (iseq->type == ISEQ_TYPE_TOP) { 4600 COMPILE_ERROR((ERROR_ARGS "Invalid yield")); 4601 } 4602 4603 if (node->nd_head) { 4604 argc = setup_args(iseq, args, node->nd_head, &flag); 4605 } 4606 else { 4607 argc = INT2FIX(0); 4608 } 4609 4610 ADD_SEQ(ret, args); 4611 ADD_INSN1(ret, line, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), 0, flag)); 4612 4613 if (poped) { 4614 ADD_INSN(ret, line, pop); 4615 } 4616 break; 4617 } 4618 case NODE_LVAR:{ 4619 if (!poped) { 4620 ID id = node->nd_vid; 4621 int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id); 4622 4623 debugs("id: %s idx: %d\n", rb_id2name(id), idx); 4624 ADD_INSN2(ret, line, getlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq))); 4625 } 4626 break; 4627 } 4628 case NODE_DVAR:{ 4629 int lv, idx, ls; 4630 debugi("nd_vid", node->nd_vid); 4631 if (!poped) { 4632 idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls); 4633 if (idx < 0) { 4634 rb_bug("unknown dvar (%s)", rb_id2name(node->nd_vid)); 4635 } 4636 ADD_INSN2(ret, line, getlocal, INT2FIX(ls - idx), INT2FIX(lv)); 4637 } 4638 break; 4639 } 4640 case NODE_GVAR:{ 4641 ADD_INSN1(ret, line, getglobal, 4642 ((VALUE)node->nd_entry | 1)); 4643 if (poped) { 4644 ADD_INSN(ret, line, pop); 4645 } 4646 break; 4647 } 4648 case NODE_IVAR:{ 4649 debugi("nd_vid", node->nd_vid); 4650 if (!poped) { 4651 ADD_INSN2(ret, line, getinstancevariable, 4652 ID2SYM(node->nd_vid), INT2FIX(iseq->ic_size++)); 4653 } 4654 break; 4655 } 4656 case NODE_CONST:{ 4657 debugi("nd_vid", node->nd_vid); 4658 4659 if (iseq->compile_data->option->inline_const_cache) { 4660 LABEL *lend = NEW_LABEL(line); 4661 int ic_index = iseq->ic_size++; 4662 4663 ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index)); 4664 ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid)); 4665 ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index)); 4666 ADD_LABEL(ret, lend); 4667 } 4668 else { 4669 ADD_INSN(ret, line, putnil); 4670 ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid)); 4671 } 4672 4673 if (poped) { 4674 ADD_INSN(ret, line, pop); 4675 } 4676 break; 4677 } 4678 case NODE_CVAR:{ 4679 if (!poped) { 4680 ADD_INSN1(ret, line, getclassvariable, 4681 ID2SYM(node->nd_vid)); 4682 } 4683 break; 4684 } 4685 case NODE_NTH_REF:{ 4686 if (!poped) { 4687 ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */, 4688 INT2FIX(node->nd_nth << 1)); 4689 } 4690 break; 4691 } 4692 case NODE_BACK_REF:{ 4693 if (!poped) { 4694 ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */, 4695 INT2FIX(0x01 | (node->nd_nth << 1))); 4696 } 4697 break; 4698 } 4699 case NODE_MATCH: 4700 case NODE_MATCH2: 4701 case NODE_MATCH3:{ 4702 DECL_ANCHOR(recv); 4703 DECL_ANCHOR(val); 4704 4705 INIT_ANCHOR(recv); 4706 INIT_ANCHOR(val); 4707 switch (nd_type(node)) { 4708 case NODE_MATCH: 4709 ADD_INSN1(recv, line, putobject, node->nd_lit); 4710 ADD_INSN2(val, line, getspecial, INT2FIX(0), 4711 INT2FIX(0)); 4712 break; 4713 case NODE_MATCH2: 4714 COMPILE(recv, "receiver", node->nd_recv); 4715 COMPILE(val, "value", node->nd_value); 4716 break; 4717 case NODE_MATCH3: 4718 COMPILE(recv, "receiver", node->nd_value); 4719 COMPILE(val, "value", node->nd_recv); 4720 break; 4721 } 4722 4723 if (iseq->compile_data->option->specialized_instruction) { 4724 /* TODO: detect by node */ 4725 if (recv->last == recv->anchor.next && 4726 INSN_OF(recv->last) == BIN(putobject) && 4727 nd_type(node) == NODE_MATCH2) { 4728 ADD_SEQ(ret, val); 4729 ADD_INSN1(ret, line, opt_regexpmatch1, 4730 OPERAND_AT(recv->last, 0)); 4731 } 4732 else { 4733 ADD_SEQ(ret, recv); 4734 ADD_SEQ(ret, val); 4735 ADD_INSN(ret, line, opt_regexpmatch2); 4736 } 4737 } 4738 else { 4739 ADD_SEQ(ret, recv); 4740 ADD_SEQ(ret, val); 4741 ADD_SEND(ret, line, ID2SYM(idEqTilde), INT2FIX(1)); 4742 } 4743 4744 if (poped) { 4745 ADD_INSN(ret, line, pop); 4746 } 4747 break; 4748 } 4749 case NODE_LIT:{ 4750 debugp_param("lit", node->nd_lit); 4751 if (!poped) { 4752 ADD_INSN1(ret, line, putobject, node->nd_lit); 4753 } 4754 break; 4755 } 4756 case NODE_STR:{ 4757 debugp_param("nd_lit", node->nd_lit); 4758 if (!poped) { 4759 OBJ_FREEZE(node->nd_lit); 4760 ADD_INSN1(ret, line, putstring, node->nd_lit); 4761 } 4762 break; 4763 } 4764 case NODE_DSTR:{ 4765 compile_dstr(iseq, ret, node); 4766 4767 if (poped) { 4768 ADD_INSN(ret, line, pop); 4769 } 4770 break; 4771 } 4772 case NODE_XSTR:{ 4773 OBJ_FREEZE(node->nd_lit); 4774 ADD_CALL_RECEIVER(ret, line); 4775 ADD_INSN1(ret, line, putobject, node->nd_lit); 4776 ADD_CALL(ret, line, ID2SYM(idBackquote), INT2FIX(1)); 4777 4778 if (poped) { 4779 ADD_INSN(ret, line, pop); 4780 } 4781 break; 4782 } 4783 case NODE_DXSTR:{ 4784 ADD_CALL_RECEIVER(ret, line); 4785 compile_dstr(iseq, ret, node); 4786 ADD_CALL(ret, line, ID2SYM(idBackquote), INT2FIX(1)); 4787 4788 if (poped) { 4789 ADD_INSN(ret, line, pop); 4790 } 4791 break; 4792 } 4793 case NODE_EVSTR:{ 4794 COMPILE(ret, "nd_body", node->nd_body); 4795 4796 if (poped) { 4797 ADD_INSN(ret, line, pop); 4798 } 4799 else { 4800 ADD_INSN(ret, line, tostring); 4801 } 4802 break; 4803 } 4804 case NODE_DREGX:{ 4805 compile_dregx(iseq, ret, node); 4806 4807 if (poped) { 4808 ADD_INSN(ret, line, pop); 4809 } 4810 break; 4811 } 4812 case NODE_DREGX_ONCE:{ 4813 /* TODO: once? */ 4814 LABEL *lend = NEW_LABEL(line); 4815 int ic_index = iseq->ic_size++; 4816 4817 ADD_INSN2(ret, line, onceinlinecache, lend, INT2FIX(ic_index)); 4818 ADD_INSN(ret, line, pop); 4819 4820 compile_dregx(iseq, ret, node); 4821 4822 ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index)); 4823 ADD_LABEL(ret, lend); 4824 4825 if (poped) { 4826 ADD_INSN(ret, line, pop); 4827 } 4828 break; 4829 } 4830 case NODE_ARGSCAT:{ 4831 if (poped) { 4832 COMPILE(ret, "argscat head", node->nd_head); 4833 ADD_INSN1(ret, line, splatarray, Qfalse); 4834 ADD_INSN(ret, line, pop); 4835 COMPILE(ret, "argscat body", node->nd_body); 4836 ADD_INSN1(ret, line, splatarray, Qfalse); 4837 ADD_INSN(ret, line, pop); 4838 } 4839 else { 4840 COMPILE(ret, "argscat head", node->nd_head); 4841 COMPILE(ret, "argscat body", node->nd_body); 4842 ADD_INSN(ret, line, concatarray); 4843 } 4844 break; 4845 } 4846 case NODE_ARGSPUSH:{ 4847 if (poped) { 4848 COMPILE(ret, "arsgpush head", node->nd_head); 4849 ADD_INSN1(ret, line, splatarray, Qfalse); 4850 ADD_INSN(ret, line, pop); 4851 COMPILE_(ret, "argspush body", node->nd_body, poped); 4852 } 4853 else { 4854 COMPILE(ret, "arsgpush head", node->nd_head); 4855 COMPILE_(ret, "argspush body", node->nd_body, poped); 4856 ADD_INSN1(ret, line, newarray, INT2FIX(1)); 4857 ADD_INSN(ret, line, concatarray); 4858 } 4859 break; 4860 } 4861 case NODE_SPLAT:{ 4862 COMPILE(ret, "splat", node->nd_head); 4863 ADD_INSN1(ret, line, splatarray, Qtrue); 4864 4865 if (poped) { 4866 ADD_INSN(ret, line, pop); 4867 } 4868 break; 4869 } 4870 case NODE_DEFN:{ 4871 VALUE iseqval = NEW_ISEQVAL(node->nd_defn, 4872 rb_str_dup(rb_id2str(node->nd_mid)), 4873 ISEQ_TYPE_METHOD, line); 4874 4875 debugp_param("defn/iseq", iseqval); 4876 4877 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 4878 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); 4879 ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid)); 4880 ADD_INSN1(ret, line, putiseq, iseqval); 4881 ADD_SEND (ret, line, ID2SYM(id_core_define_method), INT2FIX(3)); 4882 4883 if (poped) { 4884 ADD_INSN(ret, line, pop); 4885 } 4886 4887 debugp_param("defn", iseqval); 4888 break; 4889 } 4890 case NODE_DEFS:{ 4891 VALUE iseqval = NEW_ISEQVAL(node->nd_defn, 4892 rb_str_dup(rb_id2str(node->nd_mid)), 4893 ISEQ_TYPE_METHOD, line); 4894 4895 debugp_param("defs/iseq", iseqval); 4896 4897 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 4898 COMPILE(ret, "defs: recv", node->nd_recv); 4899 ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid)); 4900 ADD_INSN1(ret, line, putiseq, iseqval); 4901 ADD_SEND (ret, line, ID2SYM(id_core_define_singleton_method), INT2FIX(3)); 4902 4903 if (poped) { 4904 ADD_INSN(ret, line, pop); 4905 } 4906 break; 4907 } 4908 case NODE_ALIAS:{ 4909 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 4910 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); 4911 COMPILE(ret, "alias arg1", node->u1.node); 4912 COMPILE(ret, "alias arg2", node->u2.node); 4913 ADD_SEND(ret, line, ID2SYM(id_core_set_method_alias), INT2FIX(3)); 4914 4915 if (poped) { 4916 ADD_INSN(ret, line, pop); 4917 } 4918 break; 4919 } 4920 case NODE_VALIAS:{ 4921 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 4922 ADD_INSN1(ret, line, putobject, ID2SYM(node->u1.id)); 4923 ADD_INSN1(ret, line, putobject, ID2SYM(node->u2.id)); 4924 ADD_SEND(ret, line, ID2SYM(id_core_set_variable_alias), INT2FIX(2)); 4925 4926 if (poped) { 4927 ADD_INSN(ret, line, pop); 4928 } 4929 break; 4930 } 4931 case NODE_UNDEF:{ 4932 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 4933 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); 4934 COMPILE(ret, "undef arg", node->u2.node); 4935 ADD_SEND(ret, line, ID2SYM(id_core_undef_method), INT2FIX(2)); 4936 4937 if (poped) { 4938 ADD_INSN(ret, line, pop); 4939 } 4940 break; 4941 } 4942 case NODE_CLASS:{ 4943 VALUE iseqval = 4944 NEW_CHILD_ISEQVAL( 4945 node->nd_body, 4946 rb_sprintf("<class:%s>", rb_id2name(node->nd_cpath->nd_mid)), 4947 ISEQ_TYPE_CLASS, line); 4948 VALUE noscope = compile_cpath(ret, iseq, node->nd_cpath); 4949 int flags = VM_DEFINECLASS_TYPE_CLASS; 4950 if (!noscope) flags |= VM_DEFINECLASS_FLAG_SCOPED; 4951 if (node->nd_super) flags |= VM_DEFINECLASS_FLAG_HAS_SUPERCLASS; 4952 COMPILE(ret, "super", node->nd_super); 4953 ADD_INSN3(ret, line, defineclass, 4954 ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(flags)); 4955 4956 if (poped) { 4957 ADD_INSN(ret, line, pop); 4958 } 4959 break; 4960 } 4961 case NODE_MODULE:{ 4962 VALUE iseqval = NEW_CHILD_ISEQVAL( 4963 node->nd_body, 4964 rb_sprintf("<module:%s>", rb_id2name(node->nd_cpath->nd_mid)), 4965 ISEQ_TYPE_CLASS, line); 4966 4967 VALUE noscope = compile_cpath(ret, iseq, node->nd_cpath); 4968 int flags = VM_DEFINECLASS_TYPE_MODULE; 4969 if (!noscope) flags |= VM_DEFINECLASS_FLAG_SCOPED; 4970 ADD_INSN (ret, line, putnil); /* dummy */ 4971 ADD_INSN3(ret, line, defineclass, 4972 ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(flags)); 4973 if (poped) { 4974 ADD_INSN(ret, line, pop); 4975 } 4976 break; 4977 } 4978 case NODE_SCLASS:{ 4979 ID singletonclass; 4980 VALUE iseqval = 4981 NEW_ISEQVAL(node->nd_body, rb_str_new2("singleton class"), 4982 ISEQ_TYPE_CLASS, line); 4983 4984 COMPILE(ret, "sclass#recv", node->nd_recv); 4985 ADD_INSN (ret, line, putnil); 4986 CONST_ID(singletonclass, "singletonclass"); 4987 ADD_INSN3(ret, line, defineclass, 4988 ID2SYM(singletonclass), iseqval, 4989 INT2FIX(VM_DEFINECLASS_TYPE_SINGLETON_CLASS)); 4990 4991 if (poped) { 4992 ADD_INSN(ret, line, pop); 4993 } 4994 break; 4995 } 4996 case NODE_COLON2:{ 4997 if (rb_is_const_id(node->nd_mid)) { 4998 /* constant */ 4999 LABEL *lend = NEW_LABEL(line); 5000 int ic_index = iseq->ic_size++; 5001 5002 DECL_ANCHOR(pref); 5003 DECL_ANCHOR(body); 5004 5005 INIT_ANCHOR(pref); 5006 INIT_ANCHOR(body); 5007 compile_colon2(iseq, node, pref, body); 5008 if (LIST_SIZE_ZERO(pref)) { 5009 if (iseq->compile_data->option->inline_const_cache) { 5010 ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index)); 5011 } 5012 else { 5013 ADD_INSN(ret, line, putnil); 5014 } 5015 5016 ADD_SEQ(ret, body); 5017 5018 if (iseq->compile_data->option->inline_const_cache) { 5019 ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index)); 5020 ADD_LABEL(ret, lend); 5021 } 5022 } 5023 else { 5024 ADD_SEQ(ret, pref); 5025 ADD_SEQ(ret, body); 5026 } 5027 } 5028 else { 5029 /* function call */ 5030 ADD_CALL_RECEIVER(ret, line); 5031 COMPILE(ret, "colon2#nd_head", node->nd_head); 5032 ADD_CALL(ret, line, ID2SYM(node->nd_mid), 5033 INT2FIX(1)); 5034 } 5035 if (poped) { 5036 ADD_INSN(ret, line, pop); 5037 } 5038 break; 5039 } 5040 case NODE_COLON3:{ 5041 LABEL *lend = NEW_LABEL(line); 5042 int ic_index = iseq->ic_size++; 5043 5044 debugi("colon3#nd_mid", node->nd_mid); 5045 5046 /* add cache insn */ 5047 if (iseq->compile_data->option->inline_const_cache) { 5048 ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index)); 5049 ADD_INSN(ret, line, pop); 5050 } 5051 5052 ADD_INSN1(ret, line, putobject, rb_cObject); 5053 ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_mid)); 5054 5055 if (iseq->compile_data->option->inline_const_cache) { 5056 ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index)); 5057 ADD_LABEL(ret, lend); 5058 } 5059 5060 if (poped) { 5061 ADD_INSN(ret, line, pop); 5062 } 5063 break; 5064 } 5065 case NODE_DOT2: 5066 case NODE_DOT3:{ 5067 VALUE flag = type == NODE_DOT2 ? INT2FIX(0) : INT2FIX(1); 5068 COMPILE(ret, "min", (NODE *) node->nd_beg); 5069 COMPILE(ret, "max", (NODE *) node->nd_end); 5070 if (poped) { 5071 ADD_INSN(ret, line, pop); 5072 ADD_INSN(ret, line, pop); 5073 } 5074 else { 5075 ADD_INSN1(ret, line, newrange, flag); 5076 } 5077 break; 5078 } 5079 case NODE_FLIP2: 5080 case NODE_FLIP3:{ 5081 LABEL *lend = NEW_LABEL(line); 5082 LABEL *lfin = NEW_LABEL(line); 5083 LABEL *ltrue = NEW_LABEL(line); 5084 rb_iseq_t *local_iseq = iseq->local_iseq; 5085 rb_num_t cnt; 5086 VALUE key; 5087 5088 cnt = local_iseq->flip_cnt++ + DEFAULT_SPECIAL_VAR_COUNT; 5089 key = INT2FIX(cnt); 5090 5091 ADD_INSN2(ret, line, getspecial, key, INT2FIX(0)); 5092 ADD_INSNL(ret, line, branchif, lend); 5093 5094 /* *flip == 0 */ 5095 COMPILE(ret, "flip2 beg", node->nd_beg); 5096 ADD_INSN(ret, line, dup); 5097 ADD_INSNL(ret, line, branchunless, lfin); 5098 if (nd_type(node) == NODE_FLIP3) { 5099 ADD_INSN(ret, line, dup); 5100 ADD_INSN1(ret, line, setspecial, key); 5101 ADD_INSNL(ret, line, jump, lfin); 5102 } 5103 else { 5104 ADD_INSN1(ret, line, setspecial, key); 5105 } 5106 5107 /* *flip == 1 */ 5108 ADD_LABEL(ret, lend); 5109 COMPILE(ret, "flip2 end", node->nd_end); 5110 ADD_INSNL(ret, line, branchunless, ltrue); 5111 ADD_INSN1(ret, line, putobject, Qfalse); 5112 ADD_INSN1(ret, line, setspecial, key); 5113 5114 ADD_LABEL(ret, ltrue); 5115 ADD_INSN1(ret, line, putobject, Qtrue); 5116 5117 ADD_LABEL(ret, lfin); 5118 break; 5119 } 5120 case NODE_SELF:{ 5121 if (!poped) { 5122 ADD_INSN(ret, line, putself); 5123 } 5124 break; 5125 } 5126 case NODE_NIL:{ 5127 if (!poped) { 5128 ADD_INSN(ret, line, putnil); 5129 } 5130 break; 5131 } 5132 case NODE_TRUE:{ 5133 if (!poped) { 5134 ADD_INSN1(ret, line, putobject, Qtrue); 5135 } 5136 break; 5137 } 5138 case NODE_FALSE:{ 5139 if (!poped) { 5140 ADD_INSN1(ret, line, putobject, Qfalse); 5141 } 5142 break; 5143 } 5144 case NODE_ERRINFO:{ 5145 if (!poped) { 5146 if (iseq->type == ISEQ_TYPE_RESCUE) { 5147 ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0)); 5148 } 5149 else { 5150 rb_iseq_t *ip = iseq; 5151 int level = 0; 5152 while (ip) { 5153 if (ip->type == ISEQ_TYPE_RESCUE) { 5154 break; 5155 } 5156 ip = ip->parent_iseq; 5157 level++; 5158 } 5159 if (ip) { 5160 ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(level)); 5161 } 5162 else { 5163 ADD_INSN(ret, line, putnil); 5164 } 5165 } 5166 } 5167 break; 5168 } 5169 case NODE_DEFINED:{ 5170 if (poped) break; 5171 if (!node->nd_head) { 5172 VALUE str = rb_iseq_defined_string(DEFINED_NIL); 5173 ADD_INSN1(ret, nd_line(node), putobject, str); 5174 } 5175 else { 5176 LABEL *lfinish[2]; 5177 lfinish[0] = NEW_LABEL(line); 5178 lfinish[1] = 0; 5179 ADD_INSN(ret, line, putnil); 5180 defined_expr(iseq, ret, node->nd_head, lfinish, Qtrue); 5181 ADD_INSN(ret, line, swap); 5182 ADD_INSN(ret, line, pop); 5183 if (lfinish[1]) { 5184 ADD_LABEL(ret, lfinish[1]); 5185 } 5186 ADD_LABEL(ret, lfinish[0]); 5187 } 5188 break; 5189 } 5190 case NODE_POSTEXE:{ 5191 LABEL *lend = NEW_LABEL(line); 5192 VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); 5193 int ic_index = iseq->ic_size++; 5194 5195 ADD_INSN2(ret, line, onceinlinecache, lend, INT2FIX(ic_index)); 5196 ADD_INSN(ret, line, pop); 5197 5198 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 5199 ADD_INSN1(ret, line, putiseq, block); 5200 ADD_SEND (ret, line, ID2SYM(id_core_set_postexe), INT2FIX(1)); 5201 5202 ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index)); 5203 ADD_LABEL(ret, lend); 5204 5205 if (poped) { 5206 ADD_INSN(ret, line, pop); 5207 } 5208 break; 5209 } 5210 case NODE_KW_ARG:{ 5211 LABEL *default_label = NEW_LABEL(line); 5212 LABEL *end_label = NEW_LABEL(line); 5213 int idx, lv, ls; 5214 ID id = node->nd_body->nd_vid; 5215 5216 ADD_INSN(ret, line, dup); 5217 ADD_INSN1(ret, line, putobject, ID2SYM(id)); 5218 ADD_SEND(ret, line, ID2SYM(rb_intern("key?")), INT2FIX(1)); 5219 ADD_INSNL(ret, line, branchunless, default_label); 5220 ADD_INSN(ret, line, dup); 5221 ADD_INSN1(ret, line, putobject, ID2SYM(id)); 5222 ADD_SEND(ret, line, ID2SYM(rb_intern("delete")), INT2FIX(1)); 5223 switch (nd_type(node->nd_body)) { 5224 case NODE_LASGN: 5225 idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id); 5226 ADD_INSN2(ret, line, setlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq))); 5227 break; 5228 case NODE_DASGN: 5229 case NODE_DASGN_CURR: 5230 idx = get_dyna_var_idx(iseq, id, &lv, &ls); 5231 ADD_INSN2(ret, line, setlocal, INT2FIX(ls - idx), INT2FIX(lv)); 5232 break; 5233 default: 5234 rb_bug("iseq_compile_each (NODE_KW_ARG): unknown node: %s", ruby_node_name(nd_type(node->nd_body))); 5235 } 5236 ADD_INSNL(ret, line, jump, end_label); 5237 ADD_LABEL(ret, default_label); 5238 COMPILE_POPED(ret, "keyword default argument", node->nd_body); 5239 ADD_LABEL(ret, end_label); 5240 break; 5241 } 5242 case NODE_DSYM:{ 5243 compile_dstr(iseq, ret, node); 5244 if (!poped) { 5245 ADD_SEND(ret, line, ID2SYM(idIntern), INT2FIX(0)); 5246 } 5247 else { 5248 ADD_INSN(ret, line, pop); 5249 } 5250 break; 5251 } 5252 case NODE_ATTRASGN:{ 5253 DECL_ANCHOR(recv); 5254 DECL_ANCHOR(args); 5255 VALUE flag = 0; 5256 VALUE argc; 5257 5258 INIT_ANCHOR(recv); 5259 INIT_ANCHOR(args); 5260 argc = setup_args(iseq, args, node->nd_args, &flag); 5261 5262 if (node->nd_recv == (NODE *) 1) { 5263 flag |= VM_CALL_FCALL; 5264 ADD_INSN(recv, line, putself); 5265 } 5266 else { 5267 COMPILE(recv, "recv", node->nd_recv); 5268 } 5269 5270 debugp_param("argc", argc); 5271 debugp_param("nd_mid", ID2SYM(node->nd_mid)); 5272 5273 if (!poped) { 5274 ADD_INSN(ret, line, putnil); 5275 ADD_SEQ(ret, recv); 5276 ADD_SEQ(ret, args); 5277 5278 if (flag & VM_CALL_ARGS_BLOCKARG) { 5279 ADD_INSN1(ret, line, topn, INT2FIX(1)); 5280 if (flag & VM_CALL_ARGS_SPLAT) { 5281 ADD_INSN1(ret, line, putobject, INT2FIX(-1)); 5282 ADD_SEND(ret, line, ID2SYM(idAREF), INT2FIX(1)); 5283 } 5284 ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 3)); 5285 ADD_INSN (ret, line, pop); 5286 } 5287 else if (flag & VM_CALL_ARGS_SPLAT) { 5288 ADD_INSN(ret, line, dup); 5289 ADD_INSN1(ret, line, putobject, INT2FIX(-1)); 5290 ADD_SEND(ret, line, ID2SYM(idAREF), INT2FIX(1)); 5291 ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2)); 5292 ADD_INSN (ret, line, pop); 5293 } 5294 else { 5295 ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 1)); 5296 } 5297 } 5298 else { 5299 ADD_SEQ(ret, recv); 5300 ADD_SEQ(ret, args); 5301 } 5302 ADD_SEND_R(ret, line, ID2SYM(node->nd_mid), argc, 0, LONG2FIX(flag)); 5303 ADD_INSN(ret, line, pop); 5304 5305 break; 5306 } 5307 case NODE_PRELUDE:{ 5308 COMPILE_POPED(ret, "prelude", node->nd_head); 5309 COMPILE_(ret, "body", node->nd_body, poped); 5310 break; 5311 } 5312 case NODE_LAMBDA:{ 5313 /* compile same as lambda{...} */ 5314 VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); 5315 VALUE argc = INT2FIX(0); 5316 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); 5317 ADD_CALL_WITH_BLOCK(ret, line, ID2SYM(idLambda), argc, block); 5318 5319 if (poped) { 5320 ADD_INSN(ret, line, pop); 5321 } 5322 break; 5323 } 5324 default: 5325 rb_bug("iseq_compile_each: unknown node: %s", ruby_node_name(type)); 5326 return COMPILE_NG; 5327 } 5328 5329 debug_node_end(); 5330 return COMPILE_OK; 5331} 5332 5333/***************************/ 5334/* instruction information */ 5335/***************************/ 5336 5337static int 5338insn_data_length(INSN *iobj) 5339{ 5340 return insn_len(iobj->insn_id); 5341} 5342 5343static int 5344calc_sp_depth(int depth, INSN *insn) 5345{ 5346 return insn_stack_increase(depth, insn->insn_id, insn->operands); 5347} 5348 5349static int 5350insn_data_line_no(INSN *iobj) 5351{ 5352 return insn_len(iobj->line_no); 5353} 5354 5355static VALUE 5356insn_data_to_s_detail(INSN *iobj) 5357{ 5358 VALUE str = rb_sprintf("%-16s", insn_name(iobj->insn_id)); 5359 5360 if (iobj->operands) { 5361 const char *types = insn_op_types(iobj->insn_id); 5362 int j; 5363 5364 for (j = 0; types[j]; j++) { 5365 char type = types[j]; 5366 printf("str: %"PRIxVALUE", type: %c\n", str, type); 5367 5368 switch (type) { 5369 case TS_OFFSET: /* label(destination position) */ 5370 { 5371 LABEL *lobj = (LABEL *)OPERAND_AT(iobj, j); 5372 rb_str_catf(str, "<L%03d>", lobj->label_no); 5373 break; 5374 } 5375 break; 5376 case TS_ISEQ: /* iseq */ 5377 { 5378 rb_iseq_t *iseq = (rb_iseq_t *)OPERAND_AT(iobj, j); 5379 VALUE val = Qnil; 5380 if (0 && iseq) { /* TODO: invalidate now */ 5381 val = iseq->self; 5382 } 5383 rb_str_concat(str, rb_inspect(val)); 5384 } 5385 break; 5386 case TS_LINDEX: 5387 case TS_NUM: /* ulong */ 5388 case TS_VALUE: /* VALUE */ 5389 { 5390 VALUE v = OPERAND_AT(iobj, j); 5391 rb_str_concat(str, rb_inspect(v)); 5392 break; 5393 } 5394 case TS_ID: /* ID */ 5395 rb_str_concat(str, rb_inspect(OPERAND_AT(iobj, j))); 5396 break; 5397 case TS_GENTRY: 5398 { 5399 struct rb_global_entry *entry = (struct rb_global_entry *) 5400 (OPERAND_AT(iobj, j) & (~1)); 5401 rb_str_cat2(str, rb_id2name(entry->id)); 5402 break; 5403 } 5404 case TS_IC: /* inline cache */ 5405 rb_str_catf(str, "<ic:%d>", FIX2INT(OPERAND_AT(iobj, j))); 5406 break; 5407 case TS_CALLINFO: /* call info */ 5408 { 5409 rb_call_info_t *ci = (rb_call_info_t *)OPERAND_AT(iobj, j); 5410 rb_str_catf(str, "<callinfo:%s, %d>", ci->mid ? rb_id2name(ci->mid) : "", ci->orig_argc); 5411 break; 5412 } 5413 case TS_CDHASH: /* case/when condition cache */ 5414 rb_str_cat2(str, "<ch>"); 5415 break; 5416 default:{ 5417 rb_raise(rb_eSyntaxError, "unknown operand type: %c", type); 5418 } 5419 } 5420 if (types[j + 1]) { 5421 rb_str_cat2(str, ", "); 5422 } 5423 } 5424 } 5425 return str; 5426} 5427 5428static void 5429dump_disasm_list(struct iseq_link_element *link) 5430{ 5431 int pos = 0; 5432 INSN *iobj; 5433 LABEL *lobj; 5434 VALUE str; 5435 5436 printf("-- raw disasm--------\n"); 5437 5438 while (link) { 5439 switch (link->type) { 5440 case ISEQ_ELEMENT_INSN: 5441 { 5442 iobj = (INSN *)link; 5443 str = insn_data_to_s_detail(iobj); 5444 printf("%04d %-65s(%4d)\n", pos, StringValueCStr(str), insn_data_line_no(iobj)); 5445 pos += insn_data_length(iobj); 5446 break; 5447 } 5448 case ISEQ_ELEMENT_LABEL: 5449 { 5450 lobj = (LABEL *)link; 5451 printf("<L%03d>\n", lobj->label_no); 5452 break; 5453 } 5454 case ISEQ_ELEMENT_NONE: 5455 { 5456 printf("[none]\n"); 5457 break; 5458 } 5459 case ISEQ_ELEMENT_ADJUST: 5460 { 5461 ADJUST *adjust = (ADJUST *)link; 5462 printf("adjust: [label: %d]\n", adjust->label->label_no); 5463 break; 5464 } 5465 default: 5466 /* ignore */ 5467 rb_raise(rb_eSyntaxError, "dump_disasm_list error: %ld\n", FIX2LONG(link->type)); 5468 } 5469 link = link->next; 5470 } 5471 printf("---------------------\n"); 5472} 5473 5474const char * 5475rb_insns_name(int i) 5476{ 5477 return insn_name_info[i]; 5478} 5479 5480VALUE 5481rb_insns_name_array(void) 5482{ 5483 VALUE ary = rb_ary_new(); 5484 int i; 5485 for (i = 0; i < numberof(insn_name_info); i++) { 5486 rb_ary_push(ary, rb_obj_freeze(rb_str_new2(insn_name_info[i]))); 5487 } 5488 return rb_obj_freeze(ary); 5489} 5490 5491static LABEL * 5492register_label(rb_iseq_t *iseq, struct st_table *labels_table, VALUE obj) 5493{ 5494 LABEL *label = 0; 5495 st_data_t tmp; 5496 obj = rb_convert_type(obj, T_SYMBOL, "Symbol", "to_sym"); 5497 5498 if (st_lookup(labels_table, obj, &tmp) == 0) { 5499 label = NEW_LABEL(0); 5500 st_insert(labels_table, obj, (st_data_t)label); 5501 } 5502 else { 5503 label = (LABEL *)tmp; 5504 } 5505 return label; 5506} 5507 5508static VALUE 5509get_exception_sym2type(VALUE sym) 5510{ 5511#undef rb_intern 5512#define rb_intern(str) rb_intern_const(str) 5513 VALUE sym_inspect; 5514 static VALUE symRescue, symEnsure, symRetry; 5515 static VALUE symBreak, symRedo, symNext; 5516 5517 if (symRescue == 0) { 5518 symRescue = ID2SYM(rb_intern("rescue")); 5519 symEnsure = ID2SYM(rb_intern("ensure")); 5520 symRetry = ID2SYM(rb_intern("retry")); 5521 symBreak = ID2SYM(rb_intern("break")); 5522 symRedo = ID2SYM(rb_intern("redo")); 5523 symNext = ID2SYM(rb_intern("next")); 5524 } 5525 5526 if (sym == symRescue) return CATCH_TYPE_RESCUE; 5527 if (sym == symEnsure) return CATCH_TYPE_ENSURE; 5528 if (sym == symRetry) return CATCH_TYPE_RETRY; 5529 if (sym == symBreak) return CATCH_TYPE_BREAK; 5530 if (sym == symRedo) return CATCH_TYPE_REDO; 5531 if (sym == symNext) return CATCH_TYPE_NEXT; 5532 sym_inspect = rb_inspect(sym); 5533 rb_raise(rb_eSyntaxError, "invalid exception symbol: %s", 5534 StringValuePtr(sym_inspect)); 5535 return 0; 5536} 5537 5538static int 5539iseq_build_from_ary_exception(rb_iseq_t *iseq, struct st_table *labels_table, 5540 VALUE exception) 5541{ 5542 int i; 5543 5544 for (i=0; i<RARRAY_LEN(exception); i++) { 5545 VALUE v, type, *ptr, eiseqval; 5546 LABEL *lstart, *lend, *lcont; 5547 int sp; 5548 5549 RB_GC_GUARD(v) = rb_convert_type(RARRAY_PTR(exception)[i], T_ARRAY, 5550 "Array", "to_ary"); 5551 if (RARRAY_LEN(v) != 6) { 5552 rb_raise(rb_eSyntaxError, "wrong exception entry"); 5553 } 5554 ptr = RARRAY_PTR(v); 5555 type = get_exception_sym2type(ptr[0]); 5556 if (ptr[1] == Qnil) { 5557 eiseqval = 0; 5558 } 5559 else { 5560 eiseqval = rb_iseq_load(ptr[1], iseq->self, Qnil); 5561 } 5562 5563 lstart = register_label(iseq, labels_table, ptr[2]); 5564 lend = register_label(iseq, labels_table, ptr[3]); 5565 lcont = register_label(iseq, labels_table, ptr[4]); 5566 sp = NUM2INT(ptr[5]); 5567 5568 (void)sp; 5569 5570 ADD_CATCH_ENTRY(type, lstart, lend, eiseqval, lcont); 5571 } 5572 return COMPILE_OK; 5573} 5574 5575static struct st_table * 5576insn_make_insn_table(void) 5577{ 5578 struct st_table *table; 5579 int i; 5580 table = st_init_numtable(); 5581 5582 for (i=0; i<VM_INSTRUCTION_SIZE; i++) { 5583 st_insert(table, ID2SYM(rb_intern(insn_name(i))), i); 5584 } 5585 5586 return table; 5587} 5588 5589static VALUE 5590iseq_build_load_iseq(rb_iseq_t *iseq, VALUE op) 5591{ 5592 VALUE iseqval; 5593 if (RB_TYPE_P(op, T_ARRAY)) { 5594 iseqval = rb_iseq_load(op, iseq->self, Qnil); 5595 } 5596 else if (CLASS_OF(op) == rb_cISeq) { 5597 iseqval = op; 5598 } 5599 else { 5600 rb_raise(rb_eSyntaxError, "ISEQ is required"); 5601 } 5602 iseq_add_mark_object(iseq, iseqval); 5603 return iseqval; 5604} 5605 5606static int 5607iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, 5608 VALUE body, struct st_table *labels_table) 5609{ 5610 /* TODO: body should be frozen */ 5611 VALUE *ptr = RARRAY_PTR(body); 5612 long i, len = RARRAY_LEN(body); 5613 int j; 5614 int line_no = 0; 5615 5616 /* 5617 * index -> LABEL *label 5618 */ 5619 static struct st_table *insn_table; 5620 5621 if (insn_table == 0) { 5622 insn_table = insn_make_insn_table(); 5623 } 5624 5625 for (i=0; i<len; i++) { 5626 VALUE obj = ptr[i]; 5627 5628 if (SYMBOL_P(obj)) { 5629 LABEL *label = register_label(iseq, labels_table, obj); 5630 ADD_LABEL(anchor, label); 5631 } 5632 else if (FIXNUM_P(obj)) { 5633 line_no = NUM2INT(obj); 5634 } 5635 else if (RB_TYPE_P(obj, T_ARRAY)) { 5636 VALUE *argv = 0; 5637 int argc = RARRAY_LENINT(obj) - 1; 5638 st_data_t insn_id; 5639 VALUE insn; 5640 5641 insn = (argc < 0) ? Qnil : RARRAY_PTR(obj)[0]; 5642 if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) { 5643 /* TODO: exception */ 5644 RB_GC_GUARD(insn) = rb_inspect(insn); 5645 rb_compile_error(RSTRING_PTR(iseq->location.path), line_no, 5646 "unknown instruction: %s", RSTRING_PTR(insn)); 5647 } 5648 5649 if (argc != insn_len((VALUE)insn_id)-1) { 5650 rb_compile_error(RSTRING_PTR(iseq->location.path), line_no, 5651 "operand size mismatch"); 5652 } 5653 5654 if (argc > 0) { 5655 argv = compile_data_alloc(iseq, sizeof(VALUE) * argc); 5656 for (j=0; j<argc; j++) { 5657 VALUE op = rb_ary_entry(obj, j+1); 5658 switch (insn_op_type((VALUE)insn_id, j)) { 5659 case TS_OFFSET: { 5660 LABEL *label = register_label(iseq, labels_table, op); 5661 argv[j] = (VALUE)label; 5662 break; 5663 } 5664 case TS_LINDEX: 5665 case TS_NUM: 5666 (void)NUM2INT(op); 5667 argv[j] = op; 5668 break; 5669 case TS_VALUE: 5670 argv[j] = op; 5671 iseq_add_mark_object(iseq, op); 5672 break; 5673 case TS_ISEQ: 5674 { 5675 if (op != Qnil) { 5676 argv[j] = iseq_build_load_iseq(iseq, op); 5677 } 5678 else { 5679 argv[j] = 0; 5680 } 5681 } 5682 break; 5683 case TS_GENTRY: 5684 op = rb_convert_type(op, T_SYMBOL, "Symbol", "to_sym"); 5685 argv[j] = (VALUE)rb_global_entry(SYM2ID(op)); 5686 break; 5687 case TS_IC: 5688 argv[j] = op; 5689 if (NUM2INT(op) >= iseq->ic_size) { 5690 iseq->ic_size = NUM2INT(op) + 1; 5691 } 5692 break; 5693 case TS_CALLINFO: 5694 { 5695 ID mid = 0; 5696 int orig_argc = 0; 5697 VALUE block = 0; 5698 unsigned long flag = 0; 5699 5700 if (!NIL_P(op)) { 5701 VALUE vmid = rb_hash_aref(op, ID2SYM(rb_intern("mid"))); 5702 VALUE vflag = rb_hash_aref(op, ID2SYM(rb_intern("flag"))); 5703 VALUE vorig_argc = rb_hash_aref(op, ID2SYM(rb_intern("orig_argc"))); 5704 VALUE vblock = rb_hash_aref(op, ID2SYM(rb_intern("blockptr"))); 5705 5706 if (!NIL_P(vmid)) mid = SYM2ID(vmid); 5707 if (!NIL_P(vflag)) flag = NUM2ULONG(vflag); 5708 if (!NIL_P(vorig_argc)) orig_argc = FIX2INT(vorig_argc); 5709 if (!NIL_P(vblock)) block = iseq_build_load_iseq(iseq, vblock); 5710 } 5711 argv[j] = (VALUE)new_callinfo(iseq, mid, orig_argc, block, flag); 5712 } 5713 break; 5714 case TS_ID: 5715 argv[j] = rb_convert_type(op, T_SYMBOL, 5716 "Symbol", "to_sym"); 5717 break; 5718 case TS_CDHASH: 5719 { 5720 int i; 5721 op = rb_convert_type(op, T_ARRAY, "Array", "to_ary"); 5722 op = rb_ary_dup(op); 5723 for (i=0; i<RARRAY_LEN(op); i+=2) { 5724 VALUE sym = rb_ary_entry(op, i+1); 5725 LABEL *label = 5726 register_label(iseq, labels_table, sym); 5727 rb_ary_store(op, i+1, (VALUE)label | 1); 5728 } 5729 argv[j] = op; 5730 iseq_add_mark_object_compile_time(iseq, op); 5731 } 5732 break; 5733 default: 5734 rb_raise(rb_eSyntaxError, "unknown operand: %c", insn_op_type((VALUE)insn_id, j)); 5735 } 5736 } 5737 } 5738 ADD_ELEM(anchor, 5739 (LINK_ELEMENT*)new_insn_core(iseq, line_no, 5740 (enum ruby_vminsn_type)insn_id, argc, argv)); 5741 } 5742 else { 5743 rb_raise(rb_eTypeError, "unexpected object for instruction"); 5744 } 5745 } 5746 validate_labels(iseq, labels_table); 5747 st_free_table(labels_table); 5748 iseq_setup(iseq, anchor); 5749 return COMPILE_OK; 5750} 5751 5752#define CHECK_ARRAY(v) rb_convert_type((v), T_ARRAY, "Array", "to_ary") 5753#define CHECK_STRING(v) rb_convert_type((v), T_STRING, "String", "to_str") 5754#define CHECK_SYMBOL(v) rb_convert_type((v), T_SYMBOL, "Symbol", "to_sym") 5755static inline VALUE CHECK_INTEGER(VALUE v) {(void)NUM2LONG(v); return v;} 5756 5757VALUE 5758rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args, 5759 VALUE exception, VALUE body) 5760{ 5761 int i; 5762 ID *tbl; 5763 struct st_table *labels_table = st_init_numtable(); 5764 DECL_ANCHOR(anchor); 5765 INIT_ANCHOR(anchor); 5766 5767 iseq->local_table_size = RARRAY_LENINT(locals); 5768 iseq->local_table = tbl = (ID *)ALLOC_N(ID, iseq->local_table_size); 5769 iseq->local_size = iseq->local_table_size + 1; 5770 5771 for (i=0; i<RARRAY_LEN(locals); i++) { 5772 VALUE lv = RARRAY_PTR(locals)[i]; 5773 tbl[i] = FIXNUM_P(lv) ? (ID)FIX2LONG(lv) : SYM2ID(CHECK_SYMBOL(lv)); 5774 } 5775 5776 /* args */ 5777 if (FIXNUM_P(args)) { 5778 iseq->arg_size = iseq->argc = FIX2INT(args); 5779 iseq->arg_simple = 1; 5780 } 5781 else { 5782 int i = 0; 5783 VALUE argc = CHECK_INTEGER(rb_ary_entry(args, i++)); 5784 VALUE arg_opt_labels = CHECK_ARRAY(rb_ary_entry(args, i++)); 5785 VALUE arg_post_len = CHECK_INTEGER(rb_ary_entry(args, i++)); 5786 VALUE arg_post_start = CHECK_INTEGER(rb_ary_entry(args, i++)); 5787 VALUE arg_rest = CHECK_INTEGER(rb_ary_entry(args, i++)); 5788 VALUE arg_block = CHECK_INTEGER(rb_ary_entry(args, i++)); 5789 VALUE arg_simple = CHECK_INTEGER(rb_ary_entry(args, i++)); 5790 5791 iseq->argc = FIX2INT(argc); 5792 iseq->arg_rest = FIX2INT(arg_rest); 5793 iseq->arg_post_len = FIX2INT(arg_post_len); 5794 iseq->arg_post_start = FIX2INT(arg_post_start); 5795 iseq->arg_block = FIX2INT(arg_block); 5796 iseq->arg_opts = RARRAY_LENINT(arg_opt_labels); 5797 iseq->arg_opt_table = (VALUE *)ALLOC_N(VALUE, iseq->arg_opts); 5798 5799 if (iseq->arg_block != -1) { 5800 iseq->arg_size = iseq->arg_block + 1; 5801 } 5802 else if (iseq->arg_post_len) { 5803 iseq->arg_size = iseq->arg_post_start + iseq->arg_post_len; 5804 } 5805 else if (iseq->arg_rest != -1) { 5806 iseq->arg_size = iseq->arg_rest + 1; 5807 } 5808 else { 5809 iseq->arg_size = iseq->argc + (iseq->arg_opts ? iseq->arg_opts - 1 : 0); 5810 } 5811 5812 for (i=0; i<RARRAY_LEN(arg_opt_labels); i++) { 5813 iseq->arg_opt_table[i] = 5814 (VALUE)register_label(iseq, labels_table, 5815 rb_ary_entry(arg_opt_labels, i)); 5816 } 5817 5818 iseq->arg_simple = NUM2INT(arg_simple); 5819 } 5820 5821 /* exception */ 5822 iseq_build_from_ary_exception(iseq, labels_table, exception); 5823 5824 /* body */ 5825 iseq_build_from_ary_body(iseq, anchor, body, labels_table); 5826 return iseq->self; 5827} 5828 5829/* for parser */ 5830 5831int 5832rb_dvar_defined(ID id) 5833{ 5834 rb_thread_t *th = GET_THREAD(); 5835 rb_iseq_t *iseq; 5836 if (th->base_block && (iseq = th->base_block->iseq)) { 5837 while (iseq->type == ISEQ_TYPE_BLOCK || 5838 iseq->type == ISEQ_TYPE_RESCUE || 5839 iseq->type == ISEQ_TYPE_ENSURE || 5840 iseq->type == ISEQ_TYPE_EVAL || 5841 iseq->type == ISEQ_TYPE_MAIN 5842 ) { 5843 int i; 5844 5845 for (i = 0; i < iseq->local_table_size; i++) { 5846 if (iseq->local_table[i] == id) { 5847 return 1; 5848 } 5849 } 5850 iseq = iseq->parent_iseq; 5851 } 5852 } 5853 return 0; 5854} 5855 5856int 5857rb_local_defined(ID id) 5858{ 5859 rb_thread_t *th = GET_THREAD(); 5860 rb_iseq_t *iseq; 5861 5862 if (th->base_block && th->base_block->iseq) { 5863 int i; 5864 iseq = th->base_block->iseq->local_iseq; 5865 5866 for (i=0; i<iseq->local_table_size; i++) { 5867 if (iseq->local_table[i] == id) { 5868 return 1; 5869 } 5870 } 5871 } 5872 return 0; 5873} 5874 5875int 5876rb_parse_in_eval(void) 5877{ 5878 return GET_THREAD()->parse_in_eval > 0; 5879} 5880 5881int 5882rb_parse_in_main(void) 5883{ 5884 return GET_THREAD()->parse_in_eval < 0; 5885} 5886