PageRenderTime 65ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 1ms

/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

Large files files are truncated, but you can click here to view the full file

  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. i

Large files files are truncated, but you can click here to view the full file