1 /**********************************************************************
7 Copyright (C) 2004-2007 Koichi Sasada
9 **********************************************************************/
11 #include "ruby/ruby.h"
15 iseq_special_block(rb_iseq_t *iseq, void *builder)
18 VALUE parent = Qfalse;
21 if (iseq->argc > 1 || iseq->arg_simple == 0) {
26 if (iseq->cached_special_block_builder) {
27 if (iseq->cached_special_block_builder == builder) {
28 return iseq->cached_special_block;
35 iseq->cached_special_block_builder = (void *)1;
38 if (iseq->parent_iseq) {
39 parent = iseq->parent_iseq->self;
41 iseqval = rb_iseq_new_with_bopt(iseq->node, iseq->name, iseq->filename,
43 GC_GUARDED_PTR(builder));
45 printf("%s\n", RSTRING_PTR(ruby_iseq_disasm(iseqval)));
47 iseq->cached_special_block = iseqval;
48 iseq->cached_special_block_builder = builder;
56 new_block(NODE * head, NODE * tail)
58 head = NEW_BLOCK(head);
59 tail = NEW_BLOCK(tail);
65 new_ary(NODE * head, NODE * tail)
67 head = NEW_ARRAY(head);
73 new_assign(NODE * lnode, NODE * rhs)
75 switch (nd_type(lnode)) {
77 return NEW_NODE(NODE_LASGN, lnode->nd_vid, rhs, lnode->nd_cnt);
78 /* NEW_LASGN(lnode->nd_vid, rhs); */
81 return NEW_GASGN(lnode->nd_vid, rhs);
84 return NEW_DASGN(lnode->nd_vid, rhs);
89 args = NEW_ARRAY(lnode->nd_args->nd_head);
90 args->nd_next = NEW_ARRAY(rhs);
94 args = NEW_ARRAY(rhs);
97 return NEW_ATTRASGN(lnode->nd_recv,
102 rb_bug("unimplemented (block inlining): %s", ruby_node_name(nd_type(lnode)));
108 build_Integer_times_node(rb_iseq_t *iseq, NODE * node, NODE * lnode,
109 VALUE param_vars, VALUE local_vars)
111 /* Special Block for Integer#times
132 CONST_ID(_self, "#_self");
133 if (iseq->argc == 0) {
136 rb_ary_push(param_vars, ID2SYM(e));
137 rb_ary_push(param_vars, ID2SYM(_self));
142 (NEW_DVAR(e), idLT, new_ary(NEW_DVAR(_self), 0)),
143 new_block(NEW_OPTBLOCK(node),
145 NEW_CALL(NEW_DVAR(e), idSucc, 0))),
150 ID e = SYM2ID(rb_ary_entry(param_vars, 0));
154 rb_ary_push(param_vars, ID2SYM(_self));
155 rb_ary_push(local_vars, ID2SYM(_e));
158 if (nd_type(lnode) == NODE_DASGN_CURR) {
159 assign = NEW_DASGN(e, NEW_DVAR(_e));
162 assign = new_assign(lnode, NEW_DVAR(_e));
166 new_block(NEW_DASGN(_e, NEW_DVAR(e)),
169 new_ary(NEW_DVAR(_self), 0)),
171 new_block(NEW_OPTBLOCK(node),
182 invoke_Integer_times_special_block(VALUE num)
184 rb_thread_t *th = GET_THREAD();
185 rb_block_t *orig_block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
187 if (orig_block && BUILTIN_TYPE(orig_block->iseq) != T_NODE) {
188 VALUE tsiseqval = iseq_special_block(orig_block->iseq,
189 build_Integer_times_node);
194 rb_block_t block = *orig_block;
195 GetISeqPtr(tsiseqval, tsiseq);
197 th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
198 argv[0] = INT2FIX(0);
200 val = rb_yield_values(2, argv);
213 build_Range_each_node(rb_iseq_t *iseq, NODE * node, NODE * lnode,
214 VALUE param_vars, VALUE local_vars, ID mid)
216 /* Special Block for Range#each
236 CONST_ID(_last, "#_last");
237 if (iseq->argc == 0) {
240 rb_ary_push(param_vars, ID2SYM(e));
241 rb_ary_push(param_vars, ID2SYM(_last));
245 NEW_WHILE(NEW_CALL(NEW_DVAR(e), mid, new_ary(NEW_DVAR(_last), 0)),
246 new_block(NEW_OPTBLOCK(node),
248 NEW_CALL(NEW_DVAR(e), idSucc, 0))),
253 ID e = SYM2ID(rb_ary_entry(param_vars, 0));
257 rb_ary_push(param_vars, ID2SYM(_last));
258 rb_ary_push(local_vars, ID2SYM(_e));
261 if (nd_type(lnode) == NODE_DASGN_CURR) {
262 assign = NEW_DASGN(e, NEW_DVAR(_e));
265 assign = new_assign(lnode, NEW_DVAR(_e));
269 new_block(NEW_DASGN(_e, NEW_DVAR(e)),
272 new_ary(NEW_DVAR(_last), 0)),
274 new_block(NEW_OPTBLOCK(node),
285 build_Range_each_node_LE(rb_iseq_t *iseq, NODE * node, NODE * lnode,
286 VALUE param_vars, VALUE local_vars)
288 return build_Range_each_node(iseq, node, lnode,
289 param_vars, local_vars, idLE);
293 build_Range_each_node_LT(rb_iseq_t *iseq, NODE * node, NODE * lnode,
294 VALUE param_vars, VALUE local_vars)
296 return build_Range_each_node(iseq, node, lnode,
297 param_vars, local_vars, idLT);
301 invoke_Range_each_special_block(VALUE range,
302 VALUE beg, VALUE end, int excl)
304 rb_thread_t *th = GET_THREAD();
305 rb_block_t *orig_block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
307 if (BUILTIN_TYPE(orig_block->iseq) != T_NODE) {
309 excl ? build_Range_each_node_LT : build_Range_each_node_LE;
310 VALUE tsiseqval = iseq_special_block(orig_block->iseq, builder);
316 rb_block_t block = *orig_block;
317 GetISeqPtr(tsiseqval, tsiseq);
319 th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
322 val = rb_yield_values(2, argv);
336 build_Array_each_node(rb_iseq_t *iseq, NODE * node, NODE * lnode,
337 VALUE param_vars, VALUE local_vars)
339 /* Special block for Array#each
346 while _i < _self.length
361 while _i < _self.length
372 CONST_ID(_self, "#_self");
374 if (iseq->argc == 0) {
377 rb_ary_push(param_vars, ID2SYM(_e));
378 rb_ary_push(param_vars, ID2SYM(_self));
380 rb_ary_push(local_vars, ID2SYM(_i));
383 new_block(NEW_DASGN(_i, NEW_LIT(INT2FIX(0))),
384 NEW_WHILE(NEW_CALL(NEW_DVAR(_i), idLT,
386 (NEW_DVAR(_self), idLength,
388 new_block(NEW_OPTBLOCK(node),
390 NEW_CALL(NEW_DVAR(_i),
395 ID e = SYM2ID(rb_ary_entry(param_vars, 0));
398 rb_ary_push(param_vars, ID2SYM(_self));
400 rb_ary_push(local_vars, ID2SYM(_i));
402 if (nd_type(lnode) == NODE_DASGN_CURR) {
403 assign = NEW_DASGN(e,
404 NEW_CALL(NEW_DVAR(_self), idAREF,
405 new_ary(NEW_DVAR(_i), 0)));
408 assign = new_assign(lnode,
409 NEW_CALL(NEW_DVAR(_self), idAREF,
410 new_ary(NEW_DVAR(_i), 0)));
414 new_block(NEW_DASGN(_i, NEW_LIT(INT2FIX(0))),
415 NEW_WHILE(NEW_CALL(NEW_DVAR(_i), idLT,
417 (NEW_DVAR(_self), idLength,
418 0), 0)), new_block(assign,
435 invoke_Array_each_special_block(VALUE ary)
437 rb_thread_t *th = GET_THREAD();
438 rb_block_t *orig_block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
440 if (BUILTIN_TYPE(orig_block->iseq) != T_NODE) {
441 VALUE tsiseqval = iseq_special_block(orig_block->iseq,
442 build_Array_each_node);
448 rb_block_t block = *orig_block;
449 GetISeqPtr(tsiseqval, tsiseq);
451 th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
454 val = rb_yield_values(2, argv);