PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 2ms

/compile.c

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