PageRenderTime 77ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/compile.c

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