~ubuntu-branches/ubuntu/intrepid/ruby1.9/intrepid-updates

« back to all changes in this revision

Viewing changes to compile.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-09-04 16:01:17 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20070904160117-i15zckg2nhxe9fyw
Tags: 1.9.0+20070830-2ubuntu1
* Sync from Debian; remaining changes:
  - Add -g to CFLAGS.
* Fixes build failure on ia64.
* Fixes build failure with gcc-4.2 on lpia.
* Robustify check for target_os, fixing build failure on lpia.
* Set Ubuntu maintainer address.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**********************************************************************
2
2
 
3
 
  compile.c - ruby node tree -> yarv instruction sequence
 
3
  compile.c - ruby node tree -> VM instruction sequence
4
4
 
5
5
  $Author: ko1 $
6
 
  $Date: 2007-06-06 10:51:45 +0900 (水, 06  6月 2007) $
 
6
  $Date: 2007-08-25 08:55:16 +0900 (土, 25  8月 2007) $
7
7
  created at: 04/01/01 03:42:15 JST
8
8
 
9
9
  Copyright (C) 2004-2006 Koichi Sasada
10
10
 
11
11
**********************************************************************/
12
12
 
13
 
#include "ruby.h"
14
 
#include "node.h"
 
13
#include "ruby/ruby.h"
 
14
#include "ruby/node.h"
15
15
 
16
 
#include "yarvcore.h"
 
16
#define USE_INSN_STACK_INCREASE 1
 
17
#include "vm_core.h"
17
18
#include "compile.h"
18
19
#include "insns.inc"
19
20
#include "insns_info.inc"
20
21
 
21
 
 
22
22
#ifdef HAVE_STDARG_PROTOTYPES
23
23
#include <stdarg.h>
24
24
#define va_init_list(a,b) va_start(a,b)
27
27
#define va_init_list(a,b) va_start(a)
28
28
#endif
29
29
 
 
30
/* iseq.c */
30
31
VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt);
31
32
 
 
33
/* vm.c */
 
34
VALUE vm_eval(void *);
 
35
 
32
36
/* types */
33
37
 
34
38
#define ISEQ_ELEMENT_NONE  INT2FIX(0x00)
77
81
    struct ensure_range *erange;
78
82
};
79
83
 
 
84
#include "optinsn.inc"
 
85
#if OPT_INSTRUCTIONS_UNIFICATION
 
86
#include "optunifs.inc"
 
87
#endif
80
88
 
81
89
/* for debug */
82
90
#if CPDEBUG > 0
83
91
static long gl_node_level = 0;
84
 
static long gl_tmp = 0;
85
92
static void debug_list(LINK_ANCHOR *anchor);
86
93
#endif
87
94
 
90
97
static int insn_data_length(INSN *iobj);
91
98
static int insn_data_line_no(INSN *iobj);
92
99
static int calc_sp_depth(int depth, INSN *iobj);
93
 
static int insn_ret_num(int insn);
94
100
 
95
101
static void ADD_ELEM(LINK_ANCHOR *anchor, LINK_ELEMENT *elem);
96
102
 
97
 
static INSN *new_insn_body(rb_iseq_t *iseq, int line_no,
98
 
                           int insn_id, int argc, ...);
 
103
static INSN *new_insn_body(rb_iseq_t *iseq, int line_no, int insn_id, int argc, ...);
99
104
static LABEL *new_label_body(rb_iseq_t *iseq, int line);
100
105
 
101
 
static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *anchor,
102
 
                             NODE * n, int);
 
106
static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * n, int);
103
107
static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
104
 
 
105
108
static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
106
109
static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
107
 
static int set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
108
 
static int set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
109
 
 
110
 
static int set_exception_table(rb_iseq_t *iseq);
111
 
static int set_local_table(rb_iseq_t *iseq, ID *tbl);
112
 
static int set_local_table_eval(rb_iseq_t *iseq, ID *tbl);
113
 
static int set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * node);
114
 
static NODE *set_block_local_tbl(rb_iseq_t *iseq, NODE * node,
115
 
                                 LINK_ANCHOR *anchor);
116
 
static int set_exception_tbl(rb_iseq_t *iseq);
117
 
static int set_optargs_table(rb_iseq_t *iseq);
 
110
 
 
111
static int iseq_set_local_table(rb_iseq_t *iseq, ID *tbl);
 
112
static int iseq_set_exception_local_table(rb_iseq_t *iseq);
 
113
static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * node);
 
114
 
 
115
static int iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
 
116
static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
 
117
static int iseq_set_exception_table(rb_iseq_t *iseq);
 
118
static int iseq_set_optargs_table(rb_iseq_t *iseq);
118
119
 
119
120
static int
120
121
iseq_add_mark_object(rb_iseq_t *iseq, VALUE v)
121
122
{
122
 
    rb_ary_push(iseq->iseq_mark_ary, v);
 
123
    if (!SPECIAL_CONST_P(v)) {
 
124
        rb_ary_push(iseq->mark_ary, v);
 
125
    }
123
126
    return COMPILE_OK;
124
127
}
125
128
 
126
129
static int
127
130
iseq_add_mark_object_compile_time(rb_iseq_t *iseq, VALUE v)
128
131
{
129
 
    rb_ary_push(iseq->compile_data->mark_ary, v);
 
132
    if (!SPECIAL_CONST_P(v)) {
 
133
        rb_ary_push(iseq->compile_data->mark_ary, v);
 
134
    }
130
135
    return COMPILE_OK;
131
136
}
132
137
 
133
 
 
134
 
#include "optinsn.inc"
135
 
 
136
 
#if OPT_INSTRUCTIONS_UNIFICATION
137
 
#include "optunifs.inc"
138
 
#endif
139
 
 
140
138
VALUE
141
 
rb_iseq_compile(VALUE self, NODE *node)
 
139
iseq_compile(VALUE self, NODE *node)
142
140
{
143
141
    DECL_ANCHOR(ret);
144
142
    rb_iseq_t *iseq;
 
143
    INIT_ANCHOR(ret);
145
144
    GetISeqPtr(self, iseq);
146
145
 
147
146
    if (node == 0) {
149
148
    }
150
149
    else if (nd_type(node) == NODE_SCOPE) {
151
150
        /* iseq type of top, method, class, block */
152
 
        set_local_table(iseq, node->nd_tbl);
153
 
        set_arguments(iseq, ret, node->nd_args);
 
151
        iseq_set_local_table(iseq, node->nd_tbl);
 
152
        iseq_set_arguments(iseq, ret, node->nd_args);
154
153
 
155
 
        if (iseq->type == ISEQ_TYPE_BLOCK) {
 
154
        switch (iseq->type) {
 
155
          case ISEQ_TYPE_BLOCK: {
156
156
            LABEL *start = iseq->compile_data->start_label = NEW_LABEL(0);
157
157
            LABEL *end = iseq->compile_data->end_label = NEW_LABEL(0);
158
158
 
163
163
            /* wide range catch handler must put at last */
164
164
            ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, start);
165
165
            ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, end);
166
 
        }
167
 
        else {
168
 
            if (iseq->type == ISEQ_TYPE_CLASS) {
169
 
                ADD_TRACE(ret, nd_line(node), RUBY_EVENT_CLASS);
170
 
                COMPILE(ret, "scoped node", node->nd_body);
171
 
                ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END);
172
 
            }
173
 
            else if (iseq->type == ISEQ_TYPE_METHOD) {
174
 
                ADD_TRACE(ret, nd_line(node), RUBY_EVENT_CALL);
175
 
                COMPILE(ret, "scoped node", node->nd_body);
176
 
                ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN);
177
 
            }
178
 
            else {
179
 
                COMPILE(ret, "scoped node", node->nd_body);
180
 
            }
 
166
            break;
 
167
          }
 
168
          case ISEQ_TYPE_CLASS: {
 
169
            ADD_TRACE(ret, nd_line(node), RUBY_EVENT_CLASS);
 
170
            COMPILE(ret, "scoped node", node->nd_body);
 
171
            ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END);
 
172
            break;
 
173
          }
 
174
          case ISEQ_TYPE_METHOD: {
 
175
            ADD_TRACE(ret, nd_line(node), RUBY_EVENT_CALL);
 
176
            COMPILE(ret, "scoped node", node->nd_body);
 
177
            ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN);
 
178
            break;
 
179
          }
 
180
          default: {
 
181
            COMPILE(ret, "scoped node", node->nd_body);
 
182
            break;
 
183
          }
181
184
        }
182
185
    }
183
186
    else {
184
 
        if (iseq->type == ISEQ_TYPE_METHOD ||
185
 
            iseq->type == ISEQ_TYPE_CLASS  ||
186
 
            iseq->type == ISEQ_TYPE_BLOCK  ||
187
 
            iseq->type == ISEQ_TYPE_EVAL   ||
188
 
            iseq->type == ISEQ_TYPE_TOP) {
189
 
            dpn(node);
190
 
            rb_bug("compile/should not be reached: %s:%d", __FILE__, __LINE__);
191
 
        }
192
 
        else if (iseq->type == ISEQ_TYPE_RESCUE) {
193
 
            set_exception_tbl(iseq);
 
187
        switch (iseq->type) {
 
188
          case ISEQ_TYPE_METHOD:
 
189
          case ISEQ_TYPE_CLASS:
 
190
          case ISEQ_TYPE_BLOCK:
 
191
          case ISEQ_TYPE_EVAL:
 
192
          case ISEQ_TYPE_TOP:
 
193
            rb_compile_error(ERROR_ARGS "compile/should not be reached: %s:%d",
 
194
                             __FILE__, __LINE__);
 
195
            break;
 
196
          case ISEQ_TYPE_RESCUE:
 
197
            iseq_set_exception_local_table(iseq);
194
198
            COMPILE(ret, "rescue", node);
195
 
        }
196
 
        else if (iseq->type == ISEQ_TYPE_ENSURE) {
197
 
            set_exception_tbl(iseq);
 
199
            break;
 
200
          case ISEQ_TYPE_ENSURE:
 
201
            iseq_set_exception_local_table(iseq);
198
202
            COMPILE_POPED(ret, "ensure", node);
199
 
        }
200
 
        else if (iseq->type == ISEQ_TYPE_DEFINED_GUARD) {
 
203
            break;
 
204
          case ISEQ_TYPE_DEFINED_GUARD:
201
205
            COMPILE(ret, "defined guard", node);
202
 
        }
203
 
        else {
 
206
            break;
 
207
          default:
204
208
            rb_bug("unknown scope");
205
209
        }
206
210
    }
207
211
 
208
 
    GC_CHECK();
209
 
 
210
212
    if (iseq->type == ISEQ_TYPE_RESCUE || iseq->type == ISEQ_TYPE_ENSURE) {
211
213
        ADD_INSN2(ret, 0, getdynamic, INT2FIX(1), INT2FIX(0));
212
214
        ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ );
218
220
    return iseq_setup(iseq, ret);
219
221
}
220
222
 
221
 
VALUE th_eval(void *);
222
 
 
223
 
static int
224
 
iseq_translate_direct_threaded_code(rb_iseq_t *iseq)
 
223
int
 
224
iseq_translate_threaded_code(rb_iseq_t *iseq)
225
225
{
226
226
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
227
227
 
228
228
#if OPT_DIRECT_THREADED_CODE
229
 
    void **table = (void **)th_eval(0);
 
229
    const void *const *table = (const void **)vm_eval(0);
230
230
#else
231
 
    extern void **insns_address_table();
232
 
    void **table = get_insns_address_table();
 
231
    extern const void *const *get_insns_address_table();
 
232
    const void *const *table = get_insns_address_table();
233
233
#endif
234
234
    int i;
235
235
 
236
 
    iseq->iseq_encoded = ALLOC_N(VALUE, iseq->size);
237
 
    MEMCPY(iseq->iseq_encoded, iseq->iseq, VALUE, iseq->size);
 
236
    iseq->iseq_encoded = ALLOC_N(VALUE, iseq->iseq_size);
 
237
    MEMCPY(iseq->iseq_encoded, iseq->iseq, VALUE, iseq->iseq_size);
238
238
 
239
 
    for (i = 0; i < iseq->size; /* */ ) {
 
239
    for (i = 0; i < iseq->iseq_size; /* */ ) {
240
240
        int insn = iseq->iseq_encoded[i];
241
241
        int len = insn_len(insn);
242
242
        iseq->iseq_encoded[i] = (VALUE)table[insn];
353
353
}
354
354
#endif
355
355
 
 
356
#if 0 /* unused */
356
357
/*
357
358
 * elemX, elem1 => elemX, elem2, elem1
358
359
 */
366
367
        elem2->prev->next = elem2;
367
368
    }
368
369
}
 
370
#endif
 
371
 
369
372
/*******************************************/
370
373
 
371
374
/*
417
420
    return elem;
418
421
}
419
422
 
 
423
#if 0 /* unused */
420
424
static LINK_ELEMENT *
421
425
SHIFT_ELEMENT(LINK_ANCHOR *anchor)
422
426
{
426
430
    }
427
431
    return elem;
428
432
}
 
433
#endif
429
434
 
 
435
#if 0 /* unused */
430
436
static int
431
437
LIST_SIZE(LINK_ANCHOR *anchor)
432
438
{
438
444
    }
439
445
    return size;
440
446
}
 
447
#endif
441
448
 
442
449
static int
443
450
LIST_SIZE_ZERO(LINK_ANCHOR *anchor)
651
658
{
652
659
    /* debugs("[compile step 2] (iseq_array_to_linkedlist)\n"); */
653
660
 
654
 
    GC_CHECK();
655
661
    if (CPDEBUG > 5)
656
662
        dump_disasm_list(FIRST_ELEMENT(anchor));
657
 
    GC_CHECK();
658
663
 
659
664
    debugs("[compile step 3.1 (iseq_optimize)]\n");
660
665
    iseq_optimize(iseq, anchor);
661
666
 
662
667
    if (CPDEBUG > 5)
663
668
        dump_disasm_list(FIRST_ELEMENT(anchor));
664
 
    GC_CHECK();
665
669
 
666
670
    if (iseq->compile_data->option->instructions_unification) {
667
671
        debugs("[compile step 3.2 (iseq_insns_unification)]\n");
668
672
        iseq_insns_unification(iseq, anchor);
669
673
        if (CPDEBUG > 5)
670
 
          dump_disasm_list(FIRST_ELEMENT(anchor));
671
 
        GC_CHECK();
 
674
            dump_disasm_list(FIRST_ELEMENT(anchor));
672
675
    }
673
676
 
674
677
    if (iseq->compile_data->option->stack_caching) {
675
 
        debugs("[compile step 3.3 (set_sequence_stackcaching)]\n");
676
 
        set_sequence_stackcaching(iseq, anchor);
 
678
        debugs("[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
 
679
        iseq_set_sequence_stackcaching(iseq, anchor);
677
680
        if (CPDEBUG > 5)
678
 
          dump_disasm_list(FIRST_ELEMENT(anchor));
679
 
        GC_CHECK();
 
681
            dump_disasm_list(FIRST_ELEMENT(anchor));
680
682
    }
681
683
 
682
 
    debugs("[compile step 4.1 (set_sequence)]\n");
683
 
    set_sequence(iseq, anchor);
 
684
    debugs("[compile step 4.1 (iseq_set_sequence)]\n");
 
685
    iseq_set_sequence(iseq, anchor);
684
686
    if (CPDEBUG > 5)
685
687
        dump_disasm_list(FIRST_ELEMENT(anchor));
686
 
    GC_CHECK();
687
688
 
688
 
    GC_CHECK();
689
 
    debugs("[compile step 4.2 (set_exception_table)]\n");
690
 
    set_exception_table(iseq);
 
689
    debugs("[compile step 4.2 (iseq_set_exception_table)]\n");
 
690
    iseq_set_exception_table(iseq);
691
691
 
692
692
    debugs("[compile step 4.3 (set_optargs_table)] \n");
693
 
    set_optargs_table(iseq);
 
693
    iseq_set_optargs_table(iseq);
694
694
 
695
 
    debugs("[compile step 5 (iseq_translate_direct_threaded_code)] \n");
696
 
    iseq_translate_direct_threaded_code(iseq);
697
 
    GC_CHECK();
 
695
    debugs("[compile step 5 (iseq_translate_threaded_code)] \n");
 
696
    iseq_translate_threaded_code(iseq);
698
697
 
699
698
    if (CPDEBUG > 1) {
700
699
        VALUE str = ruby_iseq_disasm(iseq->self);
706
705
    return 0;
707
706
}
708
707
 
709
 
VALUE
710
 
iseq_assemble_setup(VALUE self, VALUE args, VALUE locals, VALUE insn_ary)
711
 
{
712
 
    /* unsupported */
713
 
    return Qnil;
714
 
}
715
 
 
716
 
int
717
 
set_exception_tbl(rb_iseq_t *iseq)
 
708
static int
 
709
iseq_set_exception_local_table(rb_iseq_t *iseq)
718
710
{
719
711
    static ID id_dollar_bang;
720
712
 
745
737
{
746
738
    int idx = get_dyna_var_idx_at_raw(iseq->local_iseq, id);
747
739
 
748
 
    if (idx == -1) {
749
 
        dpi(id);
750
 
        rb_bug("get_local_var_idx: -1");
 
740
    if (idx < 0) {
 
741
        rb_bug("get_local_var_idx: %d", idx);
751
742
    }
752
743
 
753
744
    return idx;
756
747
static int
757
748
get_dyna_var_idx(rb_iseq_t *iseq, ID id, int *level, int *ls)
758
749
{
759
 
    int lv = 0, idx;
 
750
    int lv = 0, idx = -1;
760
751
 
761
752
    while (iseq) {
762
 
        if ((idx = get_dyna_var_idx_at_raw(iseq, id)) >= 0) {
763
 
            *level = lv;
764
 
            *ls = iseq->local_size;
765
 
            return idx;
 
753
        idx = get_dyna_var_idx_at_raw(iseq, id);
 
754
        if (idx >= 0) {
 
755
            break;
766
756
        }
767
757
        iseq = iseq->parent_iseq;
768
758
        lv++;
769
759
    }
770
760
 
771
 
    rb_bug("get_dyna_var_idx: -1");
772
 
    return -1;
 
761
    if (idx < 0) {
 
762
        rb_bug("get_dyna_var_idx: -1");
 
763
    }
 
764
 
 
765
    *level = lv;
 
766
    *ls = iseq->local_size;
 
767
    return idx;
773
768
}
774
769
 
775
770
static int
776
 
set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
 
771
iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
777
772
{
778
 
    debugs("set_arguments: %s\n", node_args ? "" : "0");
 
773
    debugs("iseq_set_arguments: %s\n", node_args ? "" : "0");
779
774
 
780
775
    if (node_args) {
781
776
        NODE *node_aux = node_args->nd_next;
782
 
        int mandatory_len = 0;
783
777
        NODE *node_opt = node_args->nd_opt;
784
778
        ID rest_id = 0;
 
779
        int last_comma = 0;
785
780
        ID block_id = 0;
786
 
        ID post_start_id = 0;
787
 
        int post_len = 0;
788
781
        NODE *node_init = 0;
789
 
        int d = iseq->local_size - iseq->local_table_size;
790
782
 
791
783
        if (nd_type(node_args) != NODE_ARGS) {
792
 
            rb_bug("set_arguments: NODE_ARGS is expected, but %s",
 
784
            rb_bug("iseq_set_arguments: NODE_ARGS is expected, but %s",
793
785
                   ruby_node_name(nd_type(node_args)));
794
786
        }
795
787
 
796
788
        /*
797
789
         * new argument infromation:
798
 
         *   NODE_ARGS     [m: int, o: NODE_OPT_ARG, ->]
799
 
         *   NODE_ARGS_AUX [r: ID, b: ID, ->]
800
 
         *   NODE_ARGS_AUX [Pst: id, Plen: int, init: NODE*]
 
790
         *   NODE_ARGS     [m: int,  o: NODE_OPT_ARG, ->]
 
791
         *   NODE_ARGS_AUX [r: ID,   b: ID,           ->]
 
792
         *   NODE_ARGS_AUX [Pst: id, Plen: int,       init: NODE*]
801
793
         *  optarg information:
802
 
         *   NODE_OPT_ARGS [idx, expr, ->]
 
794
         *   NODE_OPT_ARGS [idx,     expr,            next ->]
803
795
         *  init arg:
804
796
         *   NODE_AND(m_init, p_init)
 
797
         *  if "r" is 1, it's means "{|x,|}" type block parameter.
805
798
         */
806
799
 
807
800
        iseq->argc = node_args->nd_frml;
809
802
 
810
803
        if (node_aux) {
811
804
            rest_id = node_aux->nd_rest;
 
805
            if (rest_id == 1) {
 
806
                last_comma = 1;
 
807
                rest_id = 0;
 
808
            }
812
809
            block_id = (ID)node_aux->nd_body;
813
810
            node_aux = node_aux->nd_next;
814
811
 
815
812
            if (node_aux) {
816
 
                post_start_id = node_aux->nd_pid;
817
 
                post_len = node_aux->nd_plen;
 
813
                ID post_start_id = node_aux->nd_pid;
 
814
                iseq->arg_post_start = get_dyna_var_idx_at_raw(iseq, post_start_id);
 
815
                iseq->arg_post_len = node_aux->nd_plen;
818
816
                node_init = node_aux->nd_next;
819
817
            }
820
818
        }
841
839
            i += 1;
842
840
 
843
841
            iseq->arg_opts = i;
844
 
            iseq->arg_opt_tbl = ALLOC_N(VALUE, i);
845
 
            MEMCPY(iseq->arg_opt_tbl, RARRAY_PTR(labels), VALUE, i);
 
842
            iseq->arg_opt_table = ALLOC_N(VALUE, i);
 
843
            MEMCPY(iseq->arg_opt_table, RARRAY_PTR(labels), VALUE, i);
846
844
            for (j = 0; j < i; j++) {
847
 
                iseq->arg_opt_tbl[j] &= ~1;
 
845
                iseq->arg_opt_table[j] &= ~1;
848
846
            }
849
847
        }
850
848
        else {
861
859
        }
862
860
 
863
861
        if (rest_id) {
864
 
            iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, rest_id) + d;
 
862
            iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, rest_id);
865
863
 
866
864
            if (iseq->arg_rest == -1) {
867
865
                rb_bug("arg_rest: -1");
868
866
            }
869
867
 
870
 
            if (post_len) {
871
 
                /*
872
 
                 * if rest.length < post_len
873
 
                 *   raise ArgumentError
874
 
                 * end
875
 
                 * post1 = rest.shift
876
 
                 * post2 = rest.shift
877
 
                 * ...
878
 
                 *
879
 
                 * #=> yarv insns
880
 
                 *   push rest
881
 
                 *   call :length
882
 
                 *   put 1
883
 
                 *   call :<
884
 
                 *   branchunless :success
885
 
                 *   put ArgumentsError
886
 
                 *   put "wrong number of arugments (%d of %d)"
887
 
                 *   call :new, 1
888
 
                 *   call :raise
889
 
                 * success:
890
 
                 *   push rest
891
 
                 *   call :shift
892
 
                 *   set post1
893
 
                 *   push rest
894
 
                 *   call :shift
895
 
                 *   set post2
896
 
                 *   ...
897
 
                 */
898
 
                LABEL *lsuccess = NEW_LABEL(nd_line(node_args));
899
 
                int i;
900
 
 
901
 
#define GET_LOCAL(idx) do { \
902
 
    if (iseq->type == ISEQ_TYPE_METHOD) { \
903
 
        ADD_INSN1(optargs, nd_line(node_args), getlocal, INT2FIX(iseq->local_size - (idx) + 1)); \
904
 
    } \
905
 
    else { \
906
 
        ADD_INSN2(optargs, nd_line(node_args), getdynamic, INT2FIX(iseq->local_size - (idx)), INT2FIX(0)); \
907
 
    } \
908
 
} while (0)
909
 
 
910
 
#define SET_LOCAL(idx) do { \
911
 
    if (iseq->type == ISEQ_TYPE_METHOD) { \
912
 
        ADD_INSN1(optargs, nd_line(node_args), setlocal, INT2FIX(iseq->local_size - (idx) + 1)); \
913
 
    } \
914
 
    else { \
915
 
        ADD_INSN2(optargs, nd_line(node_args), setdynamic, INT2FIX(iseq->local_size - (idx)), INT2FIX(0)); \
916
 
    } \
917
 
} while (0)
918
 
 
919
 
                GET_LOCAL(iseq->arg_rest);
920
 
                ADD_SEND (optargs, nd_line(node_args), ID2SYM(idLength), INT2FIX(0));
921
 
                ADD_INSN1(optargs, nd_line(node_args), putobject, INT2FIX(1));
922
 
                ADD_SEND (optargs, nd_line(node_args), ID2SYM(idLT), INT2FIX(1));
923
 
                ADD_INSNL(optargs, nd_line(node_args), branchunless, lsuccess);
924
 
                ADD_CALL_RECEIVER(optargs, nd_line(node_args));
925
 
 
926
 
                /* error */
927
 
                ADD_INSN1(optargs, nd_line(node_args), putobject, rb_eArgError);
928
 
                ADD_INSN1(optargs, nd_line(node_args), putstring, rb_str_new2("wrong number of arguments"));
929
 
                ADD_SEND (optargs, nd_line(node_args), ID2SYM(rb_intern("new")), INT2FIX(1));
930
 
                ADD_CALL (optargs, nd_line(node_args), ID2SYM(rb_intern("raise")), INT2FIX(1));
931
 
                ADD_INSN (optargs, nd_line(node_args), pop); /* dummy */
932
 
 
933
 
                ADD_LABEL(optargs, lsuccess);
934
 
 
935
 
                for (i=0; i<post_len; i++) {
936
 
                    GET_LOCAL(iseq->arg_rest);
937
 
                    ADD_SEND (optargs, nd_line(node_args), ID2SYM(rb_intern("pop")),
938
 
                              INT2FIX(0));
939
 
                    SET_LOCAL(iseq->arg_rest + i + 1);
940
 
                }
941
 
 
942
 
                iseq->arg_post_len = post_len;
 
868
            if (iseq->arg_post_start == 0) {
 
869
                iseq->arg_post_start = iseq->arg_rest + 1;
943
870
            }
944
 
#undef GET_LOCAL
945
 
#undef SET_LOCAL
946
871
        }
947
872
 
948
873
        if (block_id) {
949
 
            iseq->arg_block = get_dyna_var_idx_at_raw(iseq, block_id) + d;
 
874
            iseq->arg_block = get_dyna_var_idx_at_raw(iseq, block_id);
950
875
        }
951
876
 
952
 
        if (iseq->arg_opts != 0 || iseq->arg_rest != -1 || iseq->arg_block != -1) {
 
877
        if (iseq->arg_opts != 0 || iseq->arg_post_len != 0 ||
 
878
            iseq->arg_rest != -1 || iseq->arg_block != -1) {
953
879
            iseq->arg_simple = 0;
 
880
 
 
881
            /* set arg_size: size of arguments */
 
882
            if (iseq->arg_block != -1) {
 
883
                iseq->arg_size = iseq->arg_block + 1;
 
884
            }
 
885
            else if (iseq->arg_post_len) {
 
886
                iseq->arg_size = iseq->arg_post_start + iseq->arg_post_len;
 
887
            }
 
888
            else if (iseq->arg_rest != -1) {
 
889
                iseq->arg_size = iseq->arg_rest + 1;
 
890
            }
 
891
            else if (iseq->arg_opts) {
 
892
                iseq->arg_size = iseq->argc + iseq->arg_opts - 1;
 
893
            }
 
894
            else {
 
895
                iseq->arg_size = iseq->argc;
 
896
            }
954
897
        }
955
898
        else {
956
899
            iseq->arg_simple = 1;
957
 
        }
958
 
    }
 
900
            iseq->arg_size = iseq->argc;
 
901
        }
 
902
 
 
903
        if (iseq->type == ISEQ_TYPE_BLOCK) {
 
904
            if (iseq->arg_opts == 0 && iseq->arg_post_len == 0 && iseq->arg_rest == -1) {
 
905
                if (iseq->argc == 1 && last_comma == 0) {
 
906
                    /* {|a|} */
 
907
                    iseq->arg_simple |= 0x02;
 
908
                }
 
909
            }
 
910
        }
 
911
    }
 
912
    else {
 
913
        iseq->arg_simple = 1;
 
914
    }
 
915
 
959
916
    return COMPILE_OK;
960
917
}
961
918
 
962
919
static int
963
 
set_local_table(rb_iseq_t *iseq, ID *tbl)
 
920
iseq_set_local_table(rb_iseq_t *iseq, ID *tbl)
964
921
{
965
922
    int size;
966
923
 
985
942
        iseq->local_size += 1 /* svar */;
986
943
    }
987
944
 
988
 
    debugs("set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size);
989
 
    return COMPILE_OK;
990
 
}
991
 
 
992
 
static int
993
 
set_local_table_eval(rb_iseq_t *iseq, ID *tbl)
994
 
{
995
 
    int size;
996
 
    if (tbl) {
997
 
        size = *tbl;
998
 
    }
999
 
    else {
1000
 
        size = 0;
1001
 
    }
1002
 
    if (tbl) {
1003
 
        iseq->local_table = (ID *)ALLOC_N(ID *, size);
1004
 
        MEMCPY(iseq->local_table, tbl + 1, ID *, size);
1005
 
    }
1006
 
    iseq->local_table_size = iseq->local_size = size;
 
945
    debugs("iseq_set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size);
1007
946
    return COMPILE_OK;
1008
947
}
1009
948
 
1011
950
  ruby insn object array -> raw instruction sequence
1012
951
 */
1013
952
static int
1014
 
set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 
953
iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
1015
954
{
1016
955
    LABEL *lobj;
1017
956
    INSN *iobj;
1018
 
    struct insn_info_struct *insn_info_tbl;
 
957
    struct iseq_insn_info_entry *insn_info_table;
1019
958
    LINK_ELEMENT *list;
1020
959
    VALUE *generated_iseq;
1021
960
 
1022
 
    int k, pos, sp, stack_max = 0;
1023
 
 
1024
 
    GC_CHECK();
 
961
    int k, pos, sp, stack_max = 0, line = 0;
1025
962
 
1026
963
    /* set label position */
1027
964
    list = FIRST_ELEMENT(anchor);
1032
969
            {
1033
970
                iobj = (INSN *)list;
1034
971
                pos += insn_data_length(iobj);
 
972
                line = iobj->line_no;
1035
973
 
1036
974
                k += 1;
1037
975
                break;
1051
989
          default:
1052
990
            dump_disasm_list(FIRST_ELEMENT(anchor));
1053
991
            dump_disasm_list(list);
1054
 
            rb_bug("error: set_sequence");
 
992
            rb_compile_error(RSTRING_PTR(iseq->filename), line,
 
993
                             "error: set_sequence");
1055
994
            break;
1056
995
        }
1057
996
        list = list->next;
1059
998
 
1060
999
    /* make instruction sequence */
1061
1000
    generated_iseq = ALLOC_N(VALUE, pos);
1062
 
    insn_info_tbl = ALLOC_N(struct insn_info_struct, k);
1063
 
 
1064
 
    GC_CHECK();
 
1001
    insn_info_table = ALLOC_N(struct iseq_insn_info_entry, k);
1065
1002
 
1066
1003
    list = FIRST_ELEMENT(anchor);
1067
1004
    k = pos = sp = 0;
1097
1034
                /* operand check */
1098
1035
                if (iobj->operand_size != len - 1) {
1099
1036
                    dump_disasm_list(list);
1100
 
                    rb_bug("operand size miss! (%d for %d)",
1101
 
                           iobj->operand_size, len - 1);
 
1037
                    rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no,
 
1038
                                     "operand size miss! (%d for %d)",
 
1039
                                     iobj->operand_size, len - 1);
1102
1040
                    return 0;
1103
1041
                }
1104
1042
 
1111
1049
                            /* label(destination position) */
1112
1050
                            lobj = (LABEL *)operands[j];
1113
1051
                            if (lobj->set != Qtrue) {
1114
 
                                rb_bug("unknown label");
 
1052
                                rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no,
 
1053
                                                 "unknown label");
1115
1054
                            }
1116
1055
                            if (lobj->sp == -1) {
1117
1056
                                lobj->sp = sp;
1135
1074
                                lobj = (LABEL *)(lv & ~1);
1136
1075
 
1137
1076
                                if (lobj->set != Qtrue) {
1138
 
                                    rb_bug("unknown label");
 
1077
                                    rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no,
 
1078
                                                     "unknown label");
1139
1079
                                }
1140
 
                                rb_hash_aset(map, obj,
1141
 
                                             INT2FIX(lobj->position - (pos+len)));
 
1080
                                rb_hash_aset(map, obj, INT2FIX(lobj->position - (pos+len)));
1142
1081
                            }
1143
1082
                            generated_iseq[pos + 1 + j] = map;
1144
1083
                            iseq_add_mark_object(iseq, map);
1164
1103
                            VALUE v = operands[j];
1165
1104
                            generated_iseq[pos + 1 + j] = v;
1166
1105
                            /* to mark ruby object */
1167
 
                            if (!SPECIAL_CONST_P(v)) {
1168
 
                                iseq_add_mark_object(iseq, v);
1169
 
                            }
 
1106
                            iseq_add_mark_object(iseq, v);
1170
1107
                            break;
1171
1108
                        }
1172
1109
                      case TS_IC: /* inline cache */
1187
1124
                        }
1188
1125
                        break;
1189
1126
                      default:
1190
 
                        rb_bug("unknown operand type: %c", type);
 
1127
                        rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no,
 
1128
                                         "unknown operand type: %c", type);
1191
1129
                        return 0;
1192
1130
                    }
1193
1131
                }
1194
 
                insn_info_tbl[k].line_no = iobj->line_no;
1195
 
                insn_info_tbl[k].position = pos;
 
1132
                insn_info_table[k].line_no = iobj->line_no;
 
1133
                insn_info_table[k].position = pos;
1196
1134
                pos += len;
1197
1135
                k++;
1198
1136
                break;
1215
1153
        list = list->next;
1216
1154
    }
1217
1155
 
1218
 
    {
1219
 
        iseq->iseq = (void *)generated_iseq;
1220
 
        iseq->size = pos;
1221
 
        iseq->insn_info_tbl = insn_info_tbl;
1222
 
        iseq->insn_info_size = k;
1223
 
        iseq->stack_max = stack_max;
 
1156
#if 0
 
1157
    /* this check need dead code elimination */
 
1158
    if (sp != 0) {
 
1159
        rb_bug("SP is not 0 on %s (%d)\n", RSTRING_PTR(iseq->name), sp);
1224
1160
    }
 
1161
#endif
 
1162
 
 
1163
    iseq->iseq = (void *)generated_iseq;
 
1164
    iseq->iseq_size = pos;
 
1165
    iseq->insn_info_table = insn_info_table;
 
1166
    iseq->insn_info_size = k;
 
1167
    iseq->stack_max = stack_max;
 
1168
 
1225
1169
    return COMPILE_OK;
1226
1170
}
1227
1171
 
1238
1182
}
1239
1183
 
1240
1184
static int
1241
 
set_exception_table(rb_iseq_t *iseq)
 
1185
iseq_set_exception_table(rb_iseq_t *iseq)
1242
1186
{
1243
1187
    VALUE *tptr, *ptr;
1244
1188
    int tlen, i;
1245
 
    struct catch_table_entry *entry;
 
1189
    struct iseq_catch_table_entry *entry;
1246
1190
 
1247
1191
    tlen = RARRAY_LEN(iseq->compile_data->catch_table_ary);
1248
1192
    tptr = RARRAY_PTR(iseq->compile_data->catch_table_ary);
1249
1193
 
1250
 
    iseq->catch_table = ALLOC_N(struct catch_table_entry, tlen);
 
1194
    iseq->catch_table = ALLOC_N(struct iseq_catch_table_entry, tlen);
1251
1195
    iseq->catch_table_size = tlen;
1252
1196
 
1253
1197
    for (i = 0; i < tlen; i++) {
1296
1240
 *      expr2
1297
1241
 */
1298
1242
static int
1299
 
set_optargs_table(rb_iseq_t *iseq)
 
1243
iseq_set_optargs_table(rb_iseq_t *iseq)
1300
1244
{
1301
1245
    int i;
1302
1246
 
1303
1247
    if (iseq->arg_opts != 0) {
1304
1248
        for (i = 0; i < iseq->arg_opts; i++) {
1305
 
            iseq->arg_opt_tbl[i] =
1306
 
                label_get_position((LABEL *)iseq->arg_opt_tbl[i]);
 
1249
            iseq->arg_opt_table[i] =
 
1250
                label_get_position((LABEL *)iseq->arg_opt_table[i]);
1307
1251
        }
1308
1252
    }
1309
1253
    return COMPILE_OK;
1383
1327
            REMOVE_ELEM(&iobj->link);
1384
1328
        }
1385
1329
        else if (iobj != diobj && diobj->insn_id == BIN(jump)) {
1386
 
            OPERAND_AT(iobj, 0) = OPERAND_AT(diobj, 0);
1387
 
            goto again;
 
1330
            if (OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0)) {
 
1331
                OPERAND_AT(iobj, 0) = OPERAND_AT(diobj, 0);
 
1332
                goto again;
 
1333
            }
1388
1334
        }
1389
1335
        else if (diobj->insn_id == BIN(leave)) {
1390
1336
            /*
1536
1482
            }
1537
1483
        }
1538
1484
 
1539
 
        if (mid == idSend || mid == id__send__ || mid == id__send ||
1540
 
                 mid == idFuncall || mid == id__send_bang) {
 
1485
        if (mid == idSend || mid == id__send ||
 
1486
            mid == idSendBang || mid == id__send_bang ||
 
1487
            mid == id__send__ ) {
1541
1488
            OPERAND_AT(iobj, 3) |= INT2FIX(VM_CALL_SEND_BIT);
1542
1489
        }
1543
1490
    }
1670
1617
#include "opt_sc.inc"
1671
1618
 
1672
1619
static int
1673
 
insn_set_sc_state(INSN *iobj, int state)
 
1620
insn_set_sc_state(rb_iseq_t *iseq, INSN *iobj, int state)
1674
1621
{
1675
1622
    int nstate;
1676
1623
    int insn_id;
1688
1635
                dump_disasm_list((LINK_ELEMENT *)iobj);
1689
1636
                dump_disasm_list((LINK_ELEMENT *)lobj);
1690
1637
                printf("\n-- %d, %d\n", lobj->sc_state, nstate);
1691
 
                rb_bug("insn_set_sc_state error\n");
 
1638
                rb_compile_error(RSTRING_PTR(iseq->filename), iobj->lineno,
 
1639
                                 "insn_set_sc_state error\n");
1692
1640
                return 0;
1693
1641
            }
1694
1642
        }
1725
1673
#endif
1726
1674
 
1727
1675
static int
1728
 
set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 
1676
iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
1729
1677
{
1730
1678
#if OPT_STACK_CACHING
1731
1679
    LINK_ELEMENT *list;
1789
1737
                          case SCS_XX:
1790
1738
                            goto normal_insn;
1791
1739
                          default:
1792
 
                            rb_bug("unreachable");
 
1740
                            rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no,
 
1741
                                             "unreachable");
1793
1742
                        }
1794
1743
                        /* remove useless pop */
1795
1744
                        REMOVE_ELEM(list);
1800
1749
                    /* none */
1801
1750
                }               /* end of switch */
1802
1751
              normal_insn:
1803
 
                state = insn_set_sc_state(iobj, state);
 
1752
                state = insn_set_sc_state(iseq, iobj, state);
1804
1753
                break;
1805
1754
            }
1806
1755
          case ISEQ_ELEMENT_LABEL:
1892
1841
}
1893
1842
 
1894
1843
static int
1895
 
compile_array(rb_iseq_t *iseq,
1896
 
              LINK_ANCHOR *ret, NODE * node_root, VALUE opt_p)
 
1844
compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root,
 
1845
               VALUE opt_p, int poped)
1897
1846
{
1898
1847
    NODE *node = node_root;
1899
1848
    int len = node->nd_alen, line = nd_line(node), i=0;
1900
1849
    DECL_ANCHOR(anchor);
1901
1850
 
1902
 
    while (node) {
1903
 
        if (nd_type(node) != NODE_ARRAY) {
1904
 
            rb_bug("compile_array: This node is not NODE_ARRAY, but %s",
1905
 
                   ruby_node_name(nd_type(node)));
1906
 
        }
 
1851
    INIT_ANCHOR(anchor);
 
1852
    if (nd_type(node) != NODE_ZARRAY) {
 
1853
        while (node) {
 
1854
            if (nd_type(node) != NODE_ARRAY) {
 
1855
                rb_bug("compile_array: This node is not NODE_ARRAY, but %s",
 
1856
                       ruby_node_name(nd_type(node)));
 
1857
            }
1907
1858
 
1908
 
        i++;
1909
 
        if (opt_p && nd_type(node->nd_head) != NODE_LIT) {
1910
 
            opt_p = Qfalse;
 
1859
            i++;
 
1860
            if (opt_p && nd_type(node->nd_head) != NODE_LIT) {
 
1861
                opt_p = Qfalse;
 
1862
            }
 
1863
            COMPILE_(anchor, "array element", node->nd_head, poped);
 
1864
            node = node->nd_next;
1911
1865
        }
1912
 
        COMPILE(anchor, "array element", node->nd_head);
1913
 
        node = node->nd_next;
1914
1866
    }
1915
1867
 
1916
1868
    if (len != i) {
1917
 
        if (0) rb_bug("node error: compile_array (%d: %d-%d)",
1918
 
                      nd_line(node_root), len, i);
 
1869
        if (0) {
 
1870
            rb_bug("node error: compile_array (%d: %d-%d)",
 
1871
                   (int)nd_line(node_root), len, i);
 
1872
        }
1919
1873
        len = i;
1920
1874
    }
1921
1875
 
1922
1876
    if (opt_p == Qtrue) {
1923
 
        VALUE ary = rb_ary_new();
1924
 
        node = node_root;
1925
 
        while (node) {
1926
 
            rb_ary_push(ary, node->nd_head->nd_lit);
1927
 
            node = node->nd_next;
1928
 
        }
 
1877
        if (!poped) {
 
1878
            VALUE ary = rb_ary_new();
 
1879
            node = node_root;
 
1880
            while (node) {
 
1881
                rb_ary_push(ary, node->nd_head->nd_lit);
 
1882
                node = node->nd_next;
 
1883
            }
1929
1884
 
1930
 
        iseq_add_mark_object_compile_time(iseq, ary);
1931
 
        ADD_INSN1(ret, nd_line(node_root), duparray, ary);
 
1885
            iseq_add_mark_object_compile_time(iseq, ary);
 
1886
            ADD_INSN1(ret, nd_line(node_root), duparray, ary);
 
1887
        }
1932
1888
    }
1933
1889
    else {
1934
 
        ADD_INSN1(anchor, line, newarray, INT2FIX(len));
 
1890
        if (!poped) {
 
1891
            ADD_INSN1(anchor, line, newarray, INT2FIX(len));
 
1892
        }
1935
1893
        APPEND_LIST(ret, anchor);
1936
1894
    }
1937
1895
    return len;
1938
1896
}
1939
1897
 
1940
1898
static VALUE
 
1899
compile_array(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root, VALUE opt_p)
 
1900
{
 
1901
    return compile_array_(iseq, ret, node_root, opt_p, 0);
 
1902
}
 
1903
 
 
1904
static VALUE
1941
1905
case_when_optimizable_literal(NODE * node)
1942
1906
{
1943
 
    if (nd_type(node) == NODE_LIT) {
 
1907
    switch (nd_type(node)) {
 
1908
      case NODE_LIT: {
1944
1909
        VALUE v = node->nd_lit;
1945
1910
        if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) {
1946
1911
            return v;
1947
1912
        }
1948
 
    }
1949
 
    else if (nd_type(node) == NODE_STR) {
 
1913
        break;
 
1914
      }
 
1915
      case NODE_STR:
1950
1916
        return node->nd_lit;
1951
1917
    }
1952
1918
    return Qfalse;
1980
1946
}
1981
1947
 
1982
1948
static int
1983
 
make_masgn_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node)
 
1949
compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
1984
1950
{
1985
 
 
1986
1951
    switch (nd_type(node)) {
1987
 
      case NODE_ATTRASGN:{
 
1952
      case NODE_ATTRASGN: {
1988
1953
        INSN *iobj;
1989
1954
        VALUE dupidx;
1990
1955
 
2002
1967
        ADD_INSN(ret, nd_line(node), pop);      /* rhs    */
2003
1968
        break;
2004
1969
      }
2005
 
 
2006
 
      case NODE_MASGN:
2007
 
        COMPILE_POPED(ret, "nest masgn lhs", node);
 
1970
      case NODE_MASGN: {
 
1971
        DECL_ANCHOR(anchor);
 
1972
        INIT_ANCHOR(anchor);
 
1973
        COMPILE_POPED(anchor, "nest masgn lhs", node);
 
1974
        REMOVE_ELEM(FIRST_ELEMENT(anchor));
 
1975
        ADD_SEQ(ret, anchor);
2008
1976
        break;
2009
 
 
2010
 
      default:
2011
 
        {
2012
 
            DECL_ANCHOR(anchor);
2013
 
            COMPILE_POPED(anchor, "masgn lhs", node);
2014
 
            /* dump_disasm_list(FIRST_ELEMENT(anchor)); */
2015
 
            REMOVE_ELEM(FIRST_ELEMENT(anchor));
2016
 
            /* dump_disasm_list(FIRST_ELEMENT(anchor)); */
2017
 
            ADD_SEQ(ret, anchor);
2018
 
            /* ADD_ELEM(ret, LAST_ELEMENT(anchor)); */
2019
 
        }
 
1977
      }
 
1978
      default: {
 
1979
        DECL_ANCHOR(anchor);
 
1980
        INIT_ANCHOR(anchor);
 
1981
        COMPILE_POPED(anchor, "masgn lhs", node);
 
1982
        REMOVE_ELEM(FIRST_ELEMENT(anchor));
 
1983
        ADD_SEQ(ret, anchor);
 
1984
      }
2020
1985
    }
2021
1986
 
2022
1987
    return COMPILE_OK;
2023
1988
}
2024
1989
 
 
1990
static void
 
1991
compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *lhsn)
 
1992
{
 
1993
    if (lhsn) {
 
1994
        compile_massign_opt_lhs(iseq, ret, lhsn->nd_next);
 
1995
        compile_massign_lhs(iseq, ret, lhsn->nd_head);
 
1996
    }
 
1997
}
 
1998
 
2025
1999
static int
2026
 
compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret,
2027
 
                NODE * rhsn, NODE * splatn, NODE * lhsn, int llen)
 
2000
compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *ret,
 
2001
                    NODE *rhsn, NODE *orig_lhsn)
2028
2002
{
2029
 
    if (lhsn != 0) {
2030
 
        compile_massign(iseq, ret, rhsn, splatn, lhsn->nd_next, llen + 1);
2031
 
        make_masgn_lhs(iseq, ret, lhsn->nd_head);
 
2003
    int memsize = 64;
 
2004
    int memindex = 0;
 
2005
    VALUE *mem = ALLOCA_N(VALUE, memsize);
 
2006
    int llen = 0, rlen = 0;
 
2007
    int i;
 
2008
    NODE *lhsn = orig_lhsn;
 
2009
 
 
2010
#define MEMORY(v) { \
 
2011
    int i; \
 
2012
    if (memindex == memsize) return 0; \
 
2013
    for (i=0; i<memindex; i++) { \
 
2014
        if (mem[i] == (v)) return 0; \
 
2015
    } \
 
2016
    mem[memindex++] = (v); \
 
2017
}
 
2018
 
 
2019
    if (rhsn == 0 || nd_type(rhsn) != NODE_ARRAY) {
 
2020
        return 0;
2032
2021
    }
2033
 
    else {
2034
 
        int lhs_splat = 0;
2035
2022
 
2036
 
        if (splatn && (VALUE)splatn != -1) {
2037
 
            lhs_splat = 1;
 
2023
    while (lhsn) {
 
2024
        NODE *ln = lhsn->nd_head;
 
2025
        switch (nd_type(ln)) {
 
2026
          case NODE_LASGN:
 
2027
            MEMORY(ln->nd_vid);
 
2028
            break;
 
2029
          case NODE_DASGN:
 
2030
          case NODE_DASGN_CURR:
 
2031
          case NODE_IASGN:
 
2032
          case NODE_IASGN2:
 
2033
          case NODE_CVASGN:
 
2034
            MEMORY(ln->nd_vid);
 
2035
            break;
 
2036
          default:
 
2037
            return 0;
2038
2038
        }
2039
 
 
2040
 
        if (rhsn) {
2041
 
            switch (nd_type(rhsn)) {
2042
 
              case NODE_ARRAY:{
2043
 
                int rlen = rhsn->nd_alen;
2044
 
                int max = rlen > llen ? rlen : llen;
2045
 
                int i, si = 0;
2046
 
 
2047
 
                for (i = 0; i < max; i++) {
2048
 
                    if (i < rlen && i < llen) {
2049
 
                        /* a, b = c, d */
2050
 
                        COMPILE(ret, "masgn val1", rhsn->nd_head);
2051
 
                        rhsn = rhsn->nd_next;
2052
 
                    }
2053
 
                    else if (i < rlen) {
2054
 
                        if (lhs_splat) {
2055
 
                            while (rhsn) {
2056
 
                                /* a, *b = x, y, z */
2057
 
                                si++;
2058
 
                                COMPILE(ret, "masgn rhs for lhs splat",
2059
 
                                        rhsn->nd_head);
2060
 
                                rhsn = rhsn->nd_next;
2061
 
                            }
2062
 
                            break;
2063
 
                        }
2064
 
                        else {
2065
 
                            /* a, b = c, d, e */
2066
 
                            COMPILE_POPED(ret, "masgn rhs (popped)",
2067
 
                                          rhsn->nd_head);
2068
 
                            rhsn = rhsn->nd_next;
2069
 
                        }
2070
 
                    }
2071
 
                    else if (i < llen) {
2072
 
                        /* a, b, c = c, d */
2073
 
                        ADD_INSN(ret, 0, putnil);
2074
 
                    }
2075
 
                }
2076
 
 
2077
 
                if (lhs_splat) {
2078
 
                    ADD_INSN1(ret, 0, newarray, INT2FIX(si));
2079
 
                }
2080
 
                break;
2081
 
              }
2082
 
              case NODE_TO_ARY:
2083
 
                COMPILE(ret, "rhs to ary", rhsn->nd_head);
2084
 
                ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen),
2085
 
                          INT2FIX(lhs_splat));
2086
 
                break;
2087
 
 
2088
 
              case NODE_SPLAT:
2089
 
                COMPILE(ret, "rhs to ary (splat)", rhsn->nd_head);
2090
 
                ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen),
2091
 
                          INT2FIX(lhs_splat));
2092
 
                break;
2093
 
 
2094
 
              case NODE_ARGSCAT:
2095
 
                COMPILE(ret, "rhs to argscat", rhsn);
2096
 
                ADD_INSN2(ret, nd_line(rhsn), expandarray,
2097
 
                          INT2FIX(llen), INT2FIX(lhs_splat));
2098
 
                break;
2099
 
              default:
2100
 
                COMPILE(ret, "rhs to ary (splat/default)", rhsn);
2101
 
                ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen),
2102
 
                          INT2FIX(lhs_splat));
2103
 
                /* rb_bug("unknown rhs: %s", ruby_node_name(nd_type(rhsn))); */
2104
 
            }
 
2039
        lhsn = lhsn->nd_next;
 
2040
        llen++;
 
2041
    }
 
2042
 
 
2043
    while (rhsn) {
 
2044
        if (llen <= rlen) {
 
2045
            COMPILE_POPED(ret, "masgn val (poped)", rhsn->nd_head);
2105
2046
        }
2106
2047
        else {
2107
 
            /* nested massign */
2108
 
            ADD_INSN2(ret, 0, expandarray, INT2FIX(llen), INT2FIX(lhs_splat));
2109
 
        }
 
2048
            COMPILE(ret, "masgn val", rhsn->nd_head);
 
2049
        }
 
2050
        rhsn = rhsn->nd_next;
 
2051
        rlen++;
 
2052
    }
 
2053
 
 
2054
    if (llen > rlen) {
 
2055
        for (i=0; i<llen-rlen; i++) {
 
2056
            ADD_INSN(ret, nd_line(orig_lhsn), putnil);
 
2057
        }
 
2058
    }
 
2059
 
 
2060
    compile_massign_opt_lhs(iseq, ret, orig_lhsn);
 
2061
    return 1;
 
2062
}
 
2063
 
 
2064
static int
 
2065
compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped)
 
2066
{
 
2067
    NODE *rhsn = node->nd_value;
 
2068
    NODE *splatn = node->nd_args;
 
2069
    NODE *lhsn = node->nd_head;
 
2070
    int lhs_splat = (splatn && (VALUE)splatn != (VALUE)-1) ? 1 : 0;
 
2071
 
 
2072
    if (!poped || splatn || !compile_massign_opt(iseq, ret, rhsn, lhsn)) {
 
2073
        int llen = 0;
 
2074
        DECL_ANCHOR(lhsseq);
 
2075
 
 
2076
        INIT_ANCHOR(lhsseq);
 
2077
 
 
2078
        while (lhsn) {
 
2079
            compile_massign_lhs(iseq, lhsseq, lhsn->nd_head);
 
2080
            llen += 1;
 
2081
            lhsn = lhsn->nd_next;
 
2082
        }
 
2083
 
 
2084
        COMPILE(ret, "normal masgn rhs", rhsn);
 
2085
 
 
2086
        if (!poped) {
 
2087
            ADD_INSN(ret, nd_line(node), dup);
 
2088
        }
 
2089
 
 
2090
        ADD_INSN2(ret, nd_line(node), expandarray,
 
2091
                  INT2FIX(llen), INT2FIX(lhs_splat));
 
2092
        ADD_SEQ(ret, lhsseq);
2110
2093
 
2111
2094
        if (lhs_splat) {
2112
 
            make_masgn_lhs(iseq, ret, splatn);
 
2095
            if (nd_type(splatn) == NODE_POSTARG) {
 
2096
                /*a, b, *r, p1, p2 */
 
2097
                NODE *postn = splatn->nd_2nd;
 
2098
                NODE *restn = splatn->nd_1st;
 
2099
                int num = postn->nd_alen;
 
2100
                int flag = 0x02 | (((VALUE)restn == (VALUE)-1) ? 0x00 : 0x01);
 
2101
 
 
2102
                ADD_INSN2(ret, nd_line(splatn), expandarray,
 
2103
                          INT2FIX(num), INT2FIX(flag));
 
2104
 
 
2105
                if ((VALUE)restn != (VALUE)-1) {
 
2106
                    compile_massign_lhs(iseq, ret, restn);
 
2107
                }
 
2108
                while (postn) {
 
2109
                    compile_massign_lhs(iseq, ret, postn->nd_head);
 
2110
                    postn = postn->nd_next;
 
2111
                }
 
2112
            }
 
2113
            else {
 
2114
                /* a, b, *r */
 
2115
                compile_massign_lhs(iseq, ret, splatn);
 
2116
            }
2113
2117
        }
2114
2118
    }
2115
2119
    return COMPILE_OK;
2145
2149
static int
2146
2150
compile_cpath(LINK_ANCHOR *ret, rb_iseq_t *iseq, NODE *cpath)
2147
2151
{
2148
 
    if(cpath->nd_head) {
 
2152
    if (cpath->nd_head) {
2149
2153
        COMPILE(ret, "nd_else->nd_head", cpath->nd_head);
2150
2154
    }
2151
2155
    else if (nd_type(cpath) == NODE_COLON2) {
2185
2189
        NODE *vals = node;
2186
2190
 
2187
2191
        do {
2188
 
            NODE *val = vals->nd_head;
2189
2192
            defined_expr(iseq, ret, vals->nd_head, lfinish, Qfalse);
 
2193
 
2190
2194
            if (lfalse) {
2191
2195
                ADD_INSNL(ret, nd_line(node), branchunless, lfalse);
2192
2196
            }
2193
2197
            else {
2194
2198
                LABEL *lcont = NEW_LABEL(nd_line(node));
 
2199
                lfalse = NEW_LABEL(nd_line(node));
2195
2200
                ADD_INSNL(ret, nd_line(node), branchif, lcont);
2196
 
                lfalse = NEW_LABEL(nd_line(node));
2197
2201
                ADD_LABEL(ret, lfalse);
2198
2202
                ADD_INSN(ret, nd_line(node), putnil);
2199
2203
                ADD_INSNL(ret, nd_line(node), jump, lfinish);
2200
2204
                ADD_LABEL(ret, lcont);
2201
2205
            }
2202
 
        } while (vals = vals->nd_next);
 
2206
        } while ((vals = vals->nd_next) != NULL);
2203
2207
      }
2204
2208
      case NODE_STR:
2205
2209
      case NODE_LIT:
2284
2288
          case NODE_CALL:
2285
2289
            self = Qfalse;
2286
2290
            break;
 
2291
          default:
 
2292
            /* through */;
2287
2293
        }
2288
2294
        if (node->nd_args) {
2289
2295
            lfalse = NEW_LABEL(nd_line(node));
2381
2387
 
2382
2388
        ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, lstart, lend, ensure, lfinish);
2383
2389
        return 1;
2384
 
        /* rb_bug("unimplemented defined: %s", ruby_node_name(nd_type(node))); */
2385
 
      }                 /* end of default */
 
2390
      } /* end of default */
2386
2391
    }
2387
2392
 
2388
2393
    if (estr != 0) {
2404
2409
static VALUE
2405
2410
make_name_for_block(rb_iseq_t *iseq)
2406
2411
{
2407
 
    char buf[BUFSIZE];
2408
2412
    if (iseq->parent_iseq == 0) {
2409
 
        snprintf(buf, BUFSIZE, "block in %s", RSTRING_PTR(iseq->name));
 
2413
        return rb_sprintf("block in %s", RSTRING_PTR(iseq->name));
2410
2414
    }
2411
2415
    else {
2412
2416
        int level = 1;
2413
2417
        rb_iseq_t *ip = iseq;
2414
 
        while (1) {
2415
 
            if (ip->local_iseq != ip) {
2416
 
                ip = ip->parent_iseq;
2417
 
            }
2418
 
            else {
2419
 
                break;
2420
 
            }
 
2418
        while (ip->local_iseq != ip) {
 
2419
            ip = ip->parent_iseq;
2421
2420
            level++;
2422
2421
        }
2423
 
        snprintf(buf, BUFSIZE, "block (%d levels) in %s", level,
2424
 
                 RSTRING_PTR(ip->name));
 
2422
        return rb_sprintf("block (%d levels) in %s", level, RSTRING_PTR(ip->name));
2425
2423
    }
2426
 
    return rb_str_new2(buf);
2427
 
}
2428
 
 
2429
 
static VALUE
2430
 
make_name_with_str(const char *fmt, const char *str)
2431
 
{
2432
 
    char buf[BUFSIZE];
2433
 
    snprintf(buf, BUFSIZE, fmt, str);
2434
 
    return rb_str_new2(buf);
2435
2424
}
2436
2425
 
2437
2426
static void
2460
2449
    struct iseq_compile_data_ensure_node_stack *prev_enlp = enlp;
2461
2450
    DECL_ANCHOR(ensure);
2462
2451
 
 
2452
    INIT_ANCHOR(ensure);
2463
2453
    while (enlp) {
2464
2454
        DECL_ANCHOR(ensure_part);
2465
2455
        LABEL *lstart = NEW_LABEL(0);
2466
2456
        LABEL *lend = NEW_LABEL(0);
 
2457
 
 
2458
        INIT_ANCHOR(ensure_part);
2467
2459
        add_ensure_range(iseq, enlp->erange, lstart, lend);
2468
2460
 
2469
2461
        iseq->compile_data->ensure_node_stack = enlp->prev;
2479
2471
}
2480
2472
 
2481
2473
static VALUE
2482
 
setup_arg(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *node, VALUE *flag)
 
2474
setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, unsigned long *flag)
2483
2475
{
2484
2476
    VALUE argc = INT2FIX(0);
2485
 
    NODE *argn = node->nd_args;
2486
2477
    int nsplat = 0;
2487
2478
    DECL_ANCHOR(arg_block);
2488
2479
    DECL_ANCHOR(args_splat);
2489
2480
 
 
2481
    INIT_ANCHOR(arg_block);
 
2482
    INIT_ANCHOR(args_splat);
2490
2483
    if (argn && nd_type(argn) == NODE_BLOCK_PASS) {
2491
2484
        COMPILE(arg_block, "block", argn->nd_body);
2492
2485
        *flag |= VM_CALL_ARGS_BLOCKARG_BIT;
2499
2492
          case NODE_SPLAT: {
2500
2493
            COMPILE(args, "args (splat)", argn->nd_head);
2501
2494
            argc = INT2FIX(1);
 
2495
            nsplat++;
2502
2496
            *flag |= VM_CALL_ARGS_SPLAT_BIT;
2503
2497
            break;
2504
2498
          }
2507
2501
            int next_is_array = (nd_type(argn->nd_head) == NODE_ARRAY);
2508
2502
            DECL_ANCHOR(tmp);
2509
2503
 
 
2504
            INIT_ANCHOR(tmp);
2510
2505
            COMPILE(tmp, "args (cat: splat)", argn->nd_body);
2511
2506
            if (next_is_array && nsplat == 0) {
2512
2507
                /* none */
2539
2534
            break;
2540
2535
          }
2541
2536
          default: {
2542
 
            rb_bug("setup_arg: unknown node: %s\n", ruby_node_name(nd_type(node)));
 
2537
            rb_bug("setup_arg: unknown node: %s\n", ruby_node_name(nd_type(argn)));
2543
2538
          }
2544
2539
        }
2545
2540
    }
2572
2567
static int
2573
2568
iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
2574
2569
{
2575
 
    int type;
2576
 
 
2577
 
    GC_CHECK();
 
2570
    enum node_type type;
2578
2571
 
2579
2572
    if (node == 0) {
2580
2573
        if (!poped) {
2581
 
            debug_nodeprint("NODE_NIL(implicit)");
2582
 
            debug_nodeprint_close();
2583
 
            ADD_INSN(ret, 0, putnil);
2584
 
            return COMPILE_OK;
 
2574
            debugs("node: NODE_NIL(implicit)\n");
 
2575
            ADD_INSN(ret, iseq->compile_data->last_line, putnil);
2585
2576
        }
2586
2577
        return COMPILE_OK;
2587
2578
    }
2588
2579
 
2589
2580
    iseq->compile_data->last_line = nd_line(node);
2590
 
    debug_nodeprint(node);
 
2581
    debug_node_start(node);
2591
2582
 
2592
2583
    type = nd_type(node);
2593
2584
 
2596
2587
    }
2597
2588
 
2598
2589
    switch (type) {
2599
 
 
2600
 
      case NODE_METHOD:{
2601
 
        /* OK */
2602
 
        bp();
2603
 
        COMPILE_ERROR(("BUG: unknown node: NODE_METHOD"));
2604
 
        break;
2605
 
      }
2606
 
      case NODE_FBODY:{
2607
 
        /* OK */
2608
 
        COMPILE_ERROR(("BUG: unknown node: NODE_FBODY"));
2609
 
        break;
2610
 
      }
2611
 
      case NODE_CFUNC:{
2612
 
        /* OK */
2613
 
        COMPILE_ERROR(("BUG: unknown node: NODE_CFUNC"));
2614
 
        break;
2615
 
      }
2616
 
      case NODE_SCOPE:{
2617
 
        /* OK */
2618
 
        COMPILE_ERROR(("BUG: shouldn't reach: NODE_SCOPE"));
2619
 
        break;
2620
 
      }
2621
2590
      case NODE_BLOCK:{
2622
2591
        while (node && nd_type(node) == NODE_BLOCK) {
2623
2592
            COMPILE_(ret, "BLOCK body", node->nd_head,
2635
2604
        DECL_ANCHOR(else_seq);
2636
2605
        LABEL *then_label, *else_label, *end_label;
2637
2606
 
 
2607
        INIT_ANCHOR(cond_seq);
 
2608
        INIT_ANCHOR(then_seq);
 
2609
        INIT_ANCHOR(else_seq);
2638
2610
        then_label = NEW_LABEL(nd_line(node));
2639
2611
        else_label = NEW_LABEL(nd_line(node));
2640
2612
        end_label = NEW_LABEL(nd_line(node));
2666
2638
        DECL_ANCHOR(cond_seq);
2667
2639
        VALUE special_literals = rb_ary_new();
2668
2640
 
 
2641
        INIT_ANCHOR(head);
 
2642
        INIT_ANCHOR(body_seq);
 
2643
        INIT_ANCHOR(cond_seq);
2669
2644
        if (node->nd_head == 0) {
2670
2645
            COMPILE_(ret, "when", node->nd_body, poped);
2671
2646
            break;
2676
2651
        type = nd_type(node);
2677
2652
 
2678
2653
        if (type != NODE_WHEN) {
2679
 
            COMPILE_ERROR(("NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type)));
 
2654
            COMPILE_ERROR((ERROR_ARGS "NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type)));
2680
2655
        }
2681
2656
 
2682
2657
        endlabel = NEW_LABEL(nd_line(node));
2712
2687
                    ADD_INSNL(cond_seq, nd_line(val), branchif, l1);
2713
2688
                }
2714
2689
                else {
2715
 
                    rb_bug("NODE_CASAE: unknown node (%s)", ruby_node_name(nd_type(vals)));
 
2690
                    rb_bug("NODE_CASAE: unknown node (%s)",
 
2691
                           ruby_node_name(nd_type(vals)));
2716
2692
                }
2717
2693
            }
2718
2694
            else {
2719
 
                rb_bug("NODE_CASAE: must be NODE_ARRAY, but 0\n");
 
2695
                rb_bug("NODE_CASAE: must be NODE_ARRAY, but 0");
2720
2696
            }
2721
2697
 
2722
2698
            node = node->nd_next;
2761
2737
        LABEL *endlabel;
2762
2738
        DECL_ANCHOR(body_seq);
2763
2739
 
 
2740
        INIT_ANCHOR(body_seq);
2764
2741
        endlabel = NEW_LABEL(nd_line(node));
2765
2742
 
2766
2743
        while (node && nd_type(node) == NODE_WHEN) {
2859
2836
        ADD_LABEL(ret, end_label);
2860
2837
 
2861
2838
        if (node->nd_state == Qundef) {
2862
 
            ADD_INSN(ret, nd_line(node), putundef);
 
2839
            /* ADD_INSN(ret, nd_line(node), putundef); */
 
2840
            rb_bug("unsupported: putundef");
2863
2841
        }
2864
2842
        else {
2865
2843
            ADD_INSN(ret, nd_line(node), putnil);
2903
2881
            mid = idEach;
2904
2882
            ADD_SEND_R(ret, nd_line(node), ID2SYM(idEach), INT2FIX(0),
2905
2883
                       iseq->compile_data->current_block, INT2FIX(0));
2906
 
            if (poped) {
2907
 
                ADD_INSN(ret, nd_line(node), pop);
2908
 
            }
2909
2884
        }
2910
2885
        else {
2911
2886
            iseq->compile_data->current_block =
2912
2887
                NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq),
2913
2888
                                  ISEQ_TYPE_BLOCK);
2914
 
            COMPILE_(ret, "iter caller", node->nd_iter, poped);
 
2889
            COMPILE(ret, "iter caller", node->nd_iter);
2915
2890
        }
2916
2891
        ADD_LABEL(ret, retry_end_l);
 
2892
 
 
2893
        if (poped) {
 
2894
            ADD_INSN(ret, nd_line(node), pop);
 
2895
        }
 
2896
 
2917
2897
        iseq->compile_data->current_block = prevblock;
2918
2898
 
2919
 
        ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, retry_label, retry_end_l, 0,
2920
 
                        retry_label);
 
2899
        ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, retry_label, retry_end_l, 0, retry_label);
 
2900
        ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, 0, retry_end_l);
 
2901
 
2921
2902
        break;
2922
2903
      }
2923
2904
      case NODE_BREAK:{
2939
2920
                      INT2FIX(level | 0x02) /* TAG_BREAK */ );
2940
2921
        }
2941
2922
        else if (iseq->type == ISEQ_TYPE_EVAL) {
2942
 
            COMPILE_ERROR(("Can't escape from eval with break"));
 
2923
            COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with break"));
2943
2924
        }
2944
2925
        else {
2945
2926
            rb_iseq_t *ip = iseq->parent_iseq;
2959
2940
                }
2960
2941
                ip = ip->parent_iseq;
2961
2942
            }
2962
 
            COMPILE_ERROR(("Illegal break"));
 
2943
            COMPILE_ERROR((ERROR_ARGS "Illegal break"));
2963
2944
        }
2964
2945
        break;
2965
2946
      }
2966
2947
      case NODE_NEXT:{
2967
2948
        unsigned long level = 0;
 
2949
        int pop_after_throw = 0;
2968
2950
 
2969
2951
        if (iseq->compile_data->redo_label != 0) {
2970
 
            add_ensure_iseq(ret, iseq);
2971
 
            ADD_INSNL(ret, nd_line(node), jump,
2972
 
                      iseq->compile_data->start_label);
 
2952
            /* next in while loop */
 
2953
            debugs("next in while\n");
 
2954
            pop_after_throw = 1;
 
2955
            goto next_by_throw;
2973
2956
        }
2974
2957
        else if (iseq->compile_data->end_label) {
 
2958
            debugs("next in block\n");
 
2959
            ADD_INSN (ret, nd_line(node), emptstack);
2975
2960
            COMPILE(ret, "next val", node->nd_stts);
2976
2961
            add_ensure_iseq(ret, iseq);
2977
2962
            ADD_INSNL(ret, nd_line(node), jump,
2978
2963
                      iseq->compile_data->end_label);
2979
2964
        }
2980
2965
        else if (iseq->type == ISEQ_TYPE_EVAL) {
2981
 
            COMPILE_ERROR(("Can't escape from eval with next"));
 
2966
            COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with next"));
2982
2967
        }
2983
2968
        else {
2984
 
            rb_iseq_t *ip = iseq->parent_iseq;
 
2969
            rb_iseq_t *ip;
 
2970
          next_by_throw:
 
2971
            ip = iseq;
2985
2972
            while (ip) {
2986
2973
                level = 0x8000;
2987
 
                if (ip->type == ISEQ_TYPE_BLOCK) {
 
2974
                if (ip->compile_data->redo_label != 0) {
 
2975
                    /* while loop */
 
2976
                    break;
 
2977
                }
 
2978
                else if (ip->type == ISEQ_TYPE_BLOCK) {
2988
2979
                    level |= 0x4000;
2989
2980
                    break;
2990
2981
                }
2991
 
                else if (ip->compile_data->redo_label != 0) {
2992
 
                    break;
2993
 
                }
2994
2982
                ip = ip->parent_iseq;
2995
2983
            }
2996
2984
            if (ip != 0) {
2997
2985
                COMPILE(ret, "next val", node->nd_stts);
2998
 
                add_ensure_iseq(ret, iseq);
2999
2986
                ADD_INSN1(ret, nd_line(node), throw,
3000
2987
                          INT2FIX(level | 0x03) /* TAG_NEXT */ );
 
2988
                if (pop_after_throw) {
 
2989
                    ADD_INSN(ret, nd_line(node), pop);
 
2990
                }
3001
2991
            }
3002
2992
            else {
3003
 
                COMPILE_ERROR(("Illegal next"));
 
2993
                COMPILE_ERROR((ERROR_ARGS "Illegal next"));
3004
2994
            }
3005
2995
        }
3006
2996
        break;
3007
2997
      }
3008
2998
      case NODE_REDO:{
 
2999
        int pop_after_throw = 0;
3009
3000
        if (iseq->compile_data->redo_label) {
 
3001
            debugs("redo in while");
 
3002
#if 1
 
3003
            pop_after_throw = 1;
 
3004
            goto redo_by_throw;
 
3005
#else
3010
3006
            add_ensure_iseq(ret, iseq);
3011
3007
            ADD_INSNL(ret, nd_line(node), jump,
3012
3008
                      iseq->compile_data->redo_label);
3013
3009
            if (!poped) { /* for stack consistency */
3014
3010
                ADD_INSN(ret, nd_line(node), putnil);
3015
3011
            }
 
3012
#endif
3016
3013
        }
3017
3014
        else if (iseq->type == ISEQ_TYPE_EVAL) {
3018
 
            COMPILE_ERROR(("Can't escape from eval with redo"));
 
3015
            COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with redo"));
3019
3016
        }
3020
3017
        else if (iseq->compile_data->start_label) {
 
3018
            ADD_INSN (ret, nd_line(node), emptstack);
 
3019
            add_ensure_iseq(ret, iseq);
3021
3020
            ADD_INSNL(ret, nd_line(node), jump,
3022
3021
                      iseq->compile_data->start_label);
3023
3022
            if (!poped) { /* for stack consistency */
3025
3024
            }
3026
3025
        }
3027
3026
        else {
3028
 
            rb_iseq_t *ip = iseq->parent_iseq;
3029
 
            unsigned long level = 0x8000 | 0x4000;
 
3027
            rb_iseq_t *ip;
 
3028
            unsigned long level;
 
3029
          redo_by_throw:
 
3030
            level = 0x8000 | 0x4000;
 
3031
            ip = iseq;
3030
3032
            while (ip) {
3031
 
                if (ip->type == ISEQ_TYPE_BLOCK) {
 
3033
                if (ip->compile_data->redo_label != 0) {
 
3034
                    break;
 
3035
                }
 
3036
                else if (ip->type == ISEQ_TYPE_BLOCK) {
3032
3037
                    break;
3033
3038
                }
3034
3039
                else if (ip->type == ISEQ_TYPE_EVAL) {
3035
 
                    COMPILE_ERROR(("Can't escape from eval with redo"));
3036
 
                }
3037
 
                else if (ip->compile_data->redo_label != 0) {
3038
 
                    break;
 
3040
                    COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with redo"));
3039
3041
                }
3040
3042
                ip = ip->parent_iseq;
3041
3043
            }
3042
3044
            if (ip != 0) {
3043
 
                add_ensure_iseq(ret, iseq);
3044
3045
                ADD_INSN1(ret, nd_line(node), throw,
3045
3046
                          INT2FIX(level | 0x05) /* TAG_REDO */ );
 
3047
 
 
3048
                if (pop_after_throw) {
 
3049
                    ADD_INSN(ret, nd_line(node), pop);
 
3050
                }
3046
3051
            }
3047
3052
            else {
3048
 
                COMPILE_ERROR(("Illegal redo"));
 
3053
                COMPILE_ERROR((ERROR_ARGS "Illegal redo"));
3049
3054
            }
3050
3055
        }
3051
3056
        break;
3058
3063
                      INT2FIX(0x04) /* TAG_RETRY */ );
3059
3064
        }
3060
3065
        else {
3061
 
            COMPILE_ERROR(("Illegal retry"));
 
3066
            COMPILE_ERROR((ERROR_ARGS "Illegal retry"));
3062
3067
        }
3063
3068
        break;
3064
3069
      }
3124
3129
            ADD_INSNL(ret, nd_line(node), jump, label_miss);
3125
3130
            ADD_LABEL(ret, label_hit);
3126
3131
            COMPILE(ret, "resbody body", resq->nd_body);
 
3132
            if (iseq->compile_data->option->tailcall_optimization) {
 
3133
                ADD_INSN(ret, nd_line(node), nop);
 
3134
            }
3127
3135
            ADD_INSN(ret, nd_line(node), leave);
3128
3136
            ADD_LABEL(ret, label_miss);
3129
3137
            resq = resq->nd_head;
3140
3148
        LABEL *lstart = NEW_LABEL(nd_line(node));
3141
3149
        LABEL *lend = NEW_LABEL(nd_line(node));
3142
3150
        LABEL *lcont = NEW_LABEL(nd_line(node));
3143
 
        struct ensure_range er = { lstart, lend, 0 };
3144
 
        struct iseq_compile_data_ensure_node_stack enl = {
3145
 
            node->nd_ensr,
3146
 
            iseq->compile_data->ensure_node_stack,      /* prev */
3147
 
            &er,
3148
 
        };
 
3151
        struct ensure_range er = { 0 };
 
3152
        struct iseq_compile_data_ensure_node_stack enl;
3149
3153
        struct ensure_range *erange;
3150
3154
 
 
3155
        INIT_ANCHOR(ensr);
 
3156
        er.begin = lstart;
 
3157
        er.end = lend;
 
3158
        enl.ensure_node = node->nd_ensr;
 
3159
        enl.prev = iseq->compile_data->ensure_node_stack;       /* prev */
 
3160
        enl.erange = &er;
3151
3161
        COMPILE_POPED(ensr, "ensure ensr", node->nd_ensr);
3152
3162
 
3153
3163
        iseq->compile_data->ensure_node_stack = &enl;
3203
3213
      }
3204
3214
 
3205
3215
      case NODE_MASGN:{
3206
 
        compile_massign(iseq, ret,
3207
 
                        node->nd_value, /* rhsn  */
3208
 
                        node->nd_args,  /* splat */
3209
 
                        node->nd_head,  /* lhsn  */
3210
 
                        0);
3211
 
        if (!poped) {
3212
 
            ADD_INSN1(ret, nd_line(node), putobject, Qtrue);
3213
 
        }
3214
 
        break;
 
3216
          compile_massign(iseq, ret, node, poped);
 
3217
          break;
3215
3218
      }
3216
3219
 
3217
3220
      case NODE_LASGN:{
3232
3235
      case NODE_DASGN_CURR:{
3233
3236
        int idx, lv, ls;
3234
3237
        COMPILE(ret, "dvalue", node->nd_value);
3235
 
        debugp_param("dassn id", rb_str_new2(rb_id2name(node->nd_vid)));
 
3238
        debugp_param("dassn id", rb_str_new2(rb_id2name(node->nd_vid) ? rb_id2name(node->nd_vid) : "*"));
3236
3239
 
3237
3240
        if (!poped) {
3238
3241
            ADD_INSN(ret, nd_line(node), dup);
3241
3244
        idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
3242
3245
 
3243
3246
        if (idx < 0) {
3244
 
            debugi("unknown id", node->nd_vid);
3245
 
            COMPILE_ERROR(("NODE_DASGN error"));
 
3247
            rb_bug("NODE_DASGN(_CURR): unknown id (%s)", rb_id2name(node->nd_vid));
3246
3248
        }
 
3249
 
3247
3250
        ADD_INSN2(ret, nd_line(node), setdynamic,
3248
3251
                  INT2FIX(ls - idx), INT2FIX(lv));
3249
3252
        break;
3321
3324
         *              nd_mid
3322
3325
         */
3323
3326
 
 
3327
        INIT_ANCHOR(args);
3324
3328
        COMPILE(ret, "NODE_OP_ASGN1 recv", node->nd_recv);
3325
3329
        argc = compile_array(iseq, args, node->nd_args->nd_body, Qfalse);
3326
3330
        POP_ELEMENT(args);
3509
3513
        DECL_ANCHOR(args);
3510
3514
        ID mid = node->nd_mid;
3511
3515
        VALUE argc;
3512
 
        VALUE flag = 0;
 
3516
        unsigned long flag = 0;
3513
3517
        VALUE parent_block = iseq->compile_data->current_block;
3514
3518
        iseq->compile_data->current_block = Qfalse;
3515
3519
 
 
3520
        INIT_ANCHOR(recv);
 
3521
        INIT_ANCHOR(args);
3516
3522
#if SUPPORT_JOKE
3517
3523
        if (nd_type(node) == NODE_VCALL) {
3518
3524
            if (mid == idBitblt) {
3574
3580
 
3575
3581
        /* args */
3576
3582
        if (nd_type(node) != NODE_VCALL) {
3577
 
            argc = setup_arg(iseq, args, node, &flag);
 
3583
            argc = setup_args(iseq, args, node->nd_args, &flag);
3578
3584
        }
3579
3585
        else {
3580
3586
            argc = INT2FIX(0);
3595
3601
        }
3596
3602
 
3597
3603
        ADD_SEND_R(ret, nd_line(node), ID2SYM(mid),
3598
 
                   argc, parent_block, INT2FIX(flag));
 
3604
                   argc, parent_block, LONG2FIX(flag));
3599
3605
 
3600
3606
        if (poped) {
3601
3607
            ADD_INSN(ret, nd_line(node), pop);
3606
3612
      case NODE_ZSUPER:{
3607
3613
        DECL_ANCHOR(args);
3608
3614
        VALUE argc;
3609
 
        VALUE flag = 0;
 
3615
        unsigned long flag = 0;
3610
3616
        VALUE parent_block = iseq->compile_data->current_block;
 
3617
 
 
3618
        INIT_ANCHOR(args);
3611
3619
        iseq->compile_data->current_block = Qfalse;
3612
 
 
3613
3620
        if (nd_type(node) == NODE_SUPER) {
3614
 
            argc = setup_arg(iseq, args, node, &flag);
 
3621
            argc = setup_args(iseq, args, node->nd_args, &flag);
3615
3622
        }
3616
3623
        else {
3617
3624
            /* NODE_ZSUPER */
3632
3639
                    int j;
3633
3640
                    for (j = 0; j < liseq->arg_opts - 1; j++) {
3634
3641
                        int idx = liseq->local_size - (i + j);
3635
 
                        ADD_INSN1(args, nd_line(node), getlocal,
3636
 
                                  INT2FIX(idx));
 
3642
                        ADD_INSN1(args, nd_line(node), getlocal, INT2FIX(idx));
3637
3643
                    }
3638
3644
                    i += j;
3639
3645
                    argc = INT2FIX(i);
3640
3646
                }
3641
3647
 
3642
 
                if (liseq->arg_rest) {
3643
 
                    /* rest arguments */
3644
 
 
3645
 
                    if (liseq->arg_rest == -1) {
3646
 
                        /* TODO */
 
3648
                if (liseq->arg_rest != -1) {
 
3649
                    /* rest argument */
 
3650
                    int idx = liseq->local_size - liseq->arg_rest;
 
3651
                    ADD_INSN1(args, nd_line(node), getlocal, INT2FIX(idx));
 
3652
                    argc = INT2FIX(liseq->arg_rest + 1);
 
3653
                    flag |= VM_CALL_ARGS_SPLAT_BIT;
 
3654
                }
 
3655
 
 
3656
                if (liseq->arg_post_len) {
 
3657
                    /* post arguments */
 
3658
                    int post_len = liseq->arg_post_len;
 
3659
                    int post_start = liseq->arg_post_start;
 
3660
 
 
3661
                    if (liseq->arg_rest != -1) {
 
3662
                        int j;
 
3663
                        for (j=0; j<post_len; j++) {
 
3664
                            int idx = liseq->local_size - (post_start + j);
 
3665
                            ADD_INSN1(args, nd_line(node), getlocal, INT2FIX(idx));
 
3666
                    }
 
3667
                        ADD_INSN1(args, nd_line(node), newarray, INT2FIX(j));
 
3668
                        ADD_INSN (args, nd_line(node), concatarray);
 
3669
                        /* argc is setteled at above */
3647
3670
                    }
3648
3671
                    else {
3649
 
                        int idx = liseq->local_size - liseq->arg_rest + 1;
3650
 
                        ADD_INSN1(args, nd_line(node), getlocal,
3651
 
                                  INT2FIX(idx));
3652
 
                        argc = INT2FIX(liseq->arg_rest);
3653
 
                        flag |= VM_CALL_ARGS_SPLAT_BIT;
 
3672
                        int j;
 
3673
                        for (j=0; j<post_len; j++) {
 
3674
                            int idx = liseq->local_size - (post_start + j);
 
3675
                            ADD_INSN1(args, nd_line(node), getlocal, INT2FIX(idx));
3654
3676
                    }
 
3677
                        argc = INT2FIX(post_len + post_start);
3655
3678
                }
3656
3679
            }
3657
3680
        }
 
3681
        }
3658
3682
 
3659
3683
        /* dummy reciever */
3660
3684
        ADD_INSN1(ret, nd_line(node), putobject,
3661
3685
                  nd_type(node) == NODE_ZSUPER ? Qfalse : Qtrue);
3662
3686
        ADD_SEQ(ret, args);
3663
3687
        ADD_INSN3(ret, nd_line(node), invokesuper,
3664
 
                  argc, parent_block, INT2FIX(flag));
 
3688
                  argc, parent_block, LONG2FIX(flag));
3665
3689
 
3666
3690
        if (poped) {
3667
3691
            ADD_INSN(ret, nd_line(node), pop);
3669
3693
        break;
3670
3694
      }
3671
3695
      case NODE_ARRAY:{
3672
 
        compile_array(iseq, ret, node, Qtrue);
3673
 
        if (poped) {
3674
 
            ADD_INSN(ret, nd_line(node), pop);
3675
 
        }
 
3696
        compile_array_(iseq, ret, node, Qtrue, poped);
3676
3697
        break;
3677
3698
      }
3678
3699
      case NODE_ZARRAY:{
3698
3719
        VALUE size = 0;
3699
3720
        int type = node->nd_head ? nd_type(node->nd_head) : NODE_ZARRAY;
3700
3721
 
 
3722
        INIT_ANCHOR(list);
3701
3723
        switch (type) {
3702
3724
          case NODE_ARRAY:{
3703
3725
            compile_array(iseq, list, node->nd_head, Qfalse);
3725
3747
 
3726
3748
        while (is) {
3727
3749
            if (is->type == ISEQ_TYPE_TOP || is->type == ISEQ_TYPE_CLASS) {
3728
 
                COMPILE_ERROR(("Illegal return"));
 
3750
                COMPILE_ERROR((ERROR_ARGS "Illegal return"));
3729
3751
                break;
3730
3752
            }
3731
3753
            else {
3733
3755
                    ADD_INSN(ret, nd_line(node), emptstack);
3734
3756
                }
3735
3757
 
3736
 
                COMPILE(ret, "return nd_stts (return val)",
3737
 
                        node->nd_stts);
 
3758
                COMPILE(ret, "return nd_stts (return val)", node->nd_stts);
3738
3759
 
3739
3760
                if (is->type == ISEQ_TYPE_METHOD) {
3740
3761
                    add_ensure_iseq(ret, iseq);
3752
3773
      }
3753
3774
      case NODE_YIELD:{
3754
3775
        DECL_ANCHOR(args);
3755
 
        int argc;
 
3776
        VALUE argc;
3756
3777
        unsigned long flag = 0;
3757
3778
 
 
3779
        INIT_ANCHOR(args);
3758
3780
        if (iseq->type == ISEQ_TYPE_TOP || iseq->type == ISEQ_TYPE_CLASS) {
3759
 
            COMPILE_ERROR(("Illegal yield"));
 
3781
            COMPILE_ERROR((ERROR_ARGS "Illegal yield"));
3760
3782
        }
3761
3783
 
3762
3784
        if (node->nd_head) {
3763
 
            if (nd_type(node->nd_head) == NODE_ARRAY) {
3764
 
                NODE *p;
3765
 
 
3766
 
                argc = node->nd_head->nd_alen;
3767
 
                compile_array(iseq, args, node->nd_head, Qfalse);
3768
 
                POP_ELEMENT(args);
3769
 
                debugs("argc: %d\n", argc);
3770
 
            }
3771
 
            else {
3772
 
                if (nd_type(node->nd_head) == NODE_ARGSCAT) {
3773
 
                    if (node->nd_state == Qtrue) {
3774
 
                        flag |= VM_CALL_ARGS_SPLAT_BIT;
3775
 
                    }
3776
 
 
3777
 
                    argc = node->nd_head->nd_head->nd_alen + 1;
3778
 
                    compile_array(iseq, args, node->nd_head->nd_head, Qfalse);
3779
 
                    POP_ELEMENT(args);
3780
 
 
3781
 
                    COMPILE(args, "args(cat: splat)",
3782
 
                            node->nd_head->nd_body);
3783
 
                }
3784
 
                else if (nd_type(node->nd_head) == NODE_SPLAT) {
3785
 
                    if (node->nd_state == Qtrue) {
3786
 
                        flag |= VM_CALL_ARGS_SPLAT_BIT;
3787
 
                    }
3788
 
 
3789
 
                    argc = 1;
3790
 
                    COMPILE(args, "splat", node->nd_head->nd_head);
3791
 
                }
3792
 
                else {
3793
 
                    COMPILE(args, "nd_head(1)", node->nd_head);
3794
 
                    argc = 1;
3795
 
                }
3796
 
            }
 
3785
            argc = setup_args(iseq, args, node->nd_head, &flag);
3797
3786
        }
3798
3787
        else {
3799
 
            argc = 0;
 
3788
            argc = INT2FIX(0);
3800
3789
        }
 
3790
 
3801
3791
        ADD_SEQ(ret, args);
3802
 
        ADD_INSN2(ret, nd_line(node), invokeblock, INT2FIX(argc),
3803
 
                  INT2FIX(flag));
 
3792
        ADD_INSN2(ret, nd_line(node), invokeblock, argc, LONG2FIX(flag));
3804
3793
 
3805
3794
        if (poped) {
3806
3795
            ADD_INSN(ret, nd_line(node), pop);
3878
3867
        break;
3879
3868
      }
3880
3869
      case NODE_NTH_REF:{
3881
 
        ADD_INSN2(ret, nd_line(node), getspecial, INT2FIX(1) /* '~'  */,
3882
 
                  INT2FIX(node->nd_nth << 1));
 
3870
        if (!poped) {
 
3871
            ADD_INSN2(ret, nd_line(node), getspecial, INT2FIX(1) /* '~'  */,
 
3872
                      INT2FIX(node->nd_nth << 1));
 
3873
        }
3883
3874
        break;
3884
3875
      }
3885
3876
      case NODE_BACK_REF:{
3886
 
        ADD_INSN2(ret, nd_line(node), getspecial, INT2FIX(1) /* '~' */,
3887
 
                  INT2FIX(0x01 | (node->nd_nth << 1)));
 
3877
        if (!poped) {
 
3878
            ADD_INSN2(ret, nd_line(node), getspecial, INT2FIX(1) /* '~' */,
 
3879
                      INT2FIX(0x01 | (node->nd_nth << 1)));
 
3880
        }
3888
3881
        break;
3889
3882
      }
3890
3883
      case NODE_MATCH:
3893
3886
        DECL_ANCHOR(recv);
3894
3887
        DECL_ANCHOR(val);
3895
3888
 
 
3889
        INIT_ANCHOR(recv);
 
3890
        INIT_ANCHOR(val);
3896
3891
        switch(nd_type(node)) {
3897
3892
          case NODE_MATCH:
3898
3893
            ADD_INSN1(recv, nd_line(node), putobject, node->nd_lit);
3998
3993
        break;
3999
3994
      }
4000
3995
      case NODE_DREGX_ONCE:{
4001
 
        /* fix me: once? */
 
3996
        /* TODO: once? */
4002
3997
        LABEL *lstart = NEW_LABEL(nd_line(node));
4003
3998
        LABEL *lend = NEW_LABEL(nd_line(node));
4004
3999
 
4018
4013
        }
4019
4014
        break;
4020
4015
      }
4021
 
      case NODE_ARGS:{
4022
 
        /* OK */
4023
 
        COMPILE_ERROR(("BUG: should not reach here: compile_each#NODE_ARGS"));
4024
 
        break;
4025
 
      }
4026
4016
      case NODE_ARGSCAT:{
4027
4017
        COMPILE(ret, "argscat head", node->nd_head);
4028
4018
        COMPILE(ret, "argscat body", node->nd_body);
4037
4027
        break;
4038
4028
      }
4039
4029
      case NODE_SPLAT:{
4040
 
        COMPILE(ret, "splat", node->nd_head);
4041
 
        ADD_INSN1(ret, nd_line(node), splatarray, Qfalse);
4042
 
        break;
4043
 
      }
4044
 
      case NODE_TO_ARY:{
4045
 
        /* OK */
4046
 
        COMPILE_ERROR(("BUG: unknown node: NODE_TO_ARY"));
4047
 
        break;
4048
 
      }
4049
 
      case NODE_BLOCK_PASS:{
4050
 
        /* OK */
4051
 
        COMPILE_ERROR(("BUG: unknown node: NODE_BLOCK_PASS"));
4052
 
        break;
 
4030
          COMPILE(ret, "splat", node->nd_head);
 
4031
          ADD_INSN1(ret, nd_line(node), splatarray, Qfalse);
 
4032
 
 
4033
          if (poped) {
 
4034
              ADD_INSN(ret, nd_line(node), pop);
 
4035
          }
 
4036
          break;
4053
4037
      }
4054
4038
      case NODE_DEFN:{
4055
4039
        VALUE iseqval = NEW_ISEQVAL(node->nd_defn,
4122
4106
        VALUE iseqval =
4123
4107
            NEW_CHILD_ISEQVAL(
4124
4108
                node->nd_body,
4125
 
                make_name_with_str("<class:%s>",
4126
 
                                   rb_id2name(node->nd_cpath->nd_mid)),
 
4109
                rb_sprintf("<class:%s>", rb_id2name(node->nd_cpath->nd_mid)),
4127
4110
                ISEQ_TYPE_CLASS);
4128
4111
        compile_cpath(ret, iseq, node->nd_cpath);
4129
4112
        COMPILE(ret, "super", node->nd_super);
4136
4119
        break;
4137
4120
      }
4138
4121
      case NODE_MODULE:{
4139
 
        VALUE iseqval = NEW_CHILD_ISEQVAL(node->nd_body,
4140
 
                                          make_name_with_str
4141
 
                                          ("<module:%s>",
4142
 
                                           rb_id2name(node->nd_cpath->
4143
 
                                                      nd_mid)),
4144
 
                                          ISEQ_TYPE_CLASS);
 
4122
        VALUE iseqval = NEW_CHILD_ISEQVAL(
 
4123
            node->nd_body,
 
4124
            rb_sprintf("<module:%s>", rb_id2name(node->nd_cpath->nd_mid)),
 
4125
            ISEQ_TYPE_CLASS);
4145
4126
 
4146
4127
        COMPILE(ret, "mbase", node->nd_cpath->nd_head);
4147
4128
        ADD_INSN (ret, nd_line(node), putnil); /* dummy */
4175
4156
            DECL_ANCHOR(pref);
4176
4157
            DECL_ANCHOR(body);
4177
4158
 
 
4159
            INIT_ANCHOR(pref);
 
4160
            INIT_ANCHOR(body);
4178
4161
            compile_colon2(iseq, node, pref, body);
4179
4162
            if (LIST_SIZE_ZERO(pref)) {
4180
4163
                if (iseq->compile_data->option->inline_const_cache) {
4236
4219
        }
4237
4220
        break;
4238
4221
      }
4239
 
      case NODE_CREF:{
4240
 
        /* OK */
4241
 
        COMPILE_ERROR(("BUG: unknown node: NODE_CREF"));
4242
 
        break;
4243
 
      }
4244
4222
      case NODE_DOT2:
4245
4223
      case NODE_DOT3:{
4246
4224
        int flag = type == NODE_DOT2 ? INT2FIX(0) : INT2FIX(1);
4260
4238
        LABEL *lend = NEW_LABEL(nd_line(node));
4261
4239
        LABEL *lfin = NEW_LABEL(nd_line(node));
4262
4240
        LABEL *ltrue = NEW_LABEL(nd_line(node));
 
4241
        VALUE key = rb_sprintf("flipflag/%s-%p-%d",
 
4242
                               RSTRING_PTR(iseq->name), iseq,
 
4243
                               iseq->compile_data->flip_cnt++);
4263
4244
 
4264
 
        ADD_INSN2(ret, nd_line(node), getspecial, INT2FIX(node->nd_cnt),
4265
 
                  INT2FIX(0));
 
4245
        iseq_add_mark_object_compile_time(iseq, key);
 
4246
        ADD_INSN2(ret, nd_line(node), getspecial, key, INT2FIX(0));
4266
4247
        ADD_INSNL(ret, nd_line(node), branchif, lend);
4267
4248
 
4268
4249
        /* *flip == 0 */
4271
4252
        ADD_INSNL(ret, nd_line(node), branchunless, lfin);
4272
4253
        if (nd_type(node) == NODE_FLIP3) {
4273
4254
            ADD_INSN(ret, nd_line(node), dup);
4274
 
            ADD_INSN1(ret, nd_line(node), setspecial, INT2FIX(node->nd_cnt));
 
4255
            ADD_INSN1(ret, nd_line(node), setspecial, key);
4275
4256
            ADD_INSNL(ret, nd_line(node), jump, lfin);
4276
4257
        }
4277
4258
        else {
4278
 
            ADD_INSN1(ret, nd_line(node), setspecial, INT2FIX(node->nd_cnt));
 
4259
            ADD_INSN1(ret, nd_line(node), setspecial, key);
4279
4260
        }
4280
4261
 
4281
4262
        /* *flip == 1 */
4283
4264
        COMPILE(ret, "flip2 end", node->nd_end);
4284
4265
        ADD_INSNL(ret, nd_line(node), branchunless, ltrue);
4285
4266
        ADD_INSN1(ret, nd_line(node), putobject, Qfalse);
4286
 
        ADD_INSN1(ret, nd_line(node), setspecial, INT2FIX(node->nd_cnt));
 
4267
        ADD_INSN1(ret, nd_line(node), setspecial, key);
4287
4268
 
4288
4269
        ADD_LABEL(ret, ltrue);
4289
4270
        ADD_INSN1(ret, nd_line(node), putobject, Qtrue);
4291
4272
        ADD_LABEL(ret, lfin);
4292
4273
        break;
4293
4274
      }
4294
 
      case NODE_ATTRSET:{
4295
 
        /* OK */
4296
 
        COMPILE_ERROR(("BUG: unknown node: NODE_ATTRSET"));
4297
 
        break;
4298
 
      }
4299
4275
      case NODE_SELF:{
4300
4276
        if (!poped) {
4301
4277
            ADD_INSN(ret, nd_line(node), putself);
4302
4278
        }
4303
 
 
4304
4279
        break;
4305
4280
      }
4306
4281
      case NODE_NIL:{
4364
4339
        }
4365
4340
        break;
4366
4341
      }
4367
 
#ifdef C_ALLOCA
4368
 
      case NODE_ALLOCA:{
4369
 
        /* OK */
4370
 
        COMPILE_ERROR(("BUG: unknown node: NODE_ALLOCA"));
4371
 
        break;
4372
 
      }
4373
 
#endif
4374
 
      case NODE_BMETHOD:{
4375
 
        /* block method, OK */
4376
 
        COMPILE_ERROR(("BUG: unknown node: NODE_BMETHOD"));
4377
 
        break;
4378
 
      }
4379
 
      case NODE_MEMO:{
4380
 
        /* OK */
4381
 
        COMPILE_ERROR(("BUG: unknown node: NODE_MEMO"));
4382
 
        break;
4383
 
      }
4384
 
      case NODE_IFUNC:{
4385
 
        /* OK */
4386
 
        COMPILE_ERROR(("BUG: unknown node: NODE_IFUNC"));
4387
 
        break;
4388
 
      }
4389
4342
      case NODE_DSYM:{
4390
4343
        compile_dstr(iseq, ret, node);
4391
4344
        if (!poped) {
4399
4352
      case NODE_ATTRASGN:{
4400
4353
        DECL_ANCHOR(recv);
4401
4354
        DECL_ANCHOR(args);
4402
 
        VALUE flag = 0;
 
4355
        unsigned long flag = 0;
4403
4356
        VALUE argc;
4404
4357
 
4405
 
        argc = setup_arg(iseq, args, node, &flag);
 
4358
        INIT_ANCHOR(recv);
 
4359
        INIT_ANCHOR(args);
 
4360
        argc = setup_args(iseq, args, node->nd_args, &flag);
4406
4361
 
4407
4362
        if (node->nd_recv == (NODE *) 1) {
 
4363
            flag |= VM_CALL_FCALL_BIT;
4408
4364
            ADD_INSN(recv, nd_line(node), putself);
4409
4365
        }
4410
4366
        else {
4418
4374
            ADD_INSN(ret, nd_line(node), putnil);
4419
4375
            ADD_SEQ(ret, recv);
4420
4376
            ADD_SEQ(ret, args);
 
4377
 
 
4378
            if (flag & VM_CALL_ARGS_BLOCKARG_BIT) {
 
4379
                ADD_INSN1(ret, nd_line(node), topn, INT2FIX(1));
 
4380
                ADD_INSN1(ret, nd_line(node), setn, INT2FIX(FIX2INT(argc) + 3));
 
4381
                ADD_INSN (ret, nd_line(node), pop);
 
4382
            }
 
4383
            else {
4421
4384
            ADD_INSN1(ret, nd_line(node), setn, INT2FIX(FIX2INT(argc) + 1));
4422
4385
        }
 
4386
        }
4423
4387
        else {
4424
4388
            ADD_SEQ(ret, recv);
4425
4389
            ADD_SEQ(ret, args);
4426
4390
        }
4427
 
        ADD_SEND_R(ret, nd_line(node), ID2SYM(node->nd_mid), argc, 0, INT2FIX(flag));
 
4391
        ADD_SEND_R(ret, nd_line(node), ID2SYM(node->nd_mid), argc, 0, LONG2FIX(flag));
4428
4392
        ADD_INSN(ret, nd_line(node), pop);
4429
4393
 
4430
4394
        break;
4461
4425
        break;
4462
4426
      }
4463
4427
      default:
4464
 
        COMPILE_ERROR(("BUG: unknown node (default): %s", ruby_node_name(type)));
 
4428
        rb_bug("iseq_compile_each: unknown node: %s", ruby_node_name(type));
4465
4429
        return Qnil;
4466
4430
    }
4467
4431
 
4468
 
    debug_nodeprint_close();
 
4432
    debug_node_end();
4469
4433
    return COMPILE_OK;
4470
4434
}
4471
4435
 
4495
4459
insn_data_to_s_detail(INSN *iobj)
4496
4460
{
4497
4461
    VALUE str = rb_str_new(0, 0);
4498
 
    char buff[0x100];
4499
4462
 
4500
 
    snprintf(buff, sizeof(buff), "%-16s", insn_name(iobj->insn_id));
4501
 
    rb_str_cat2(str, buff);
 
4463
    str = rb_sprintf("%-16s", insn_name(iobj->insn_id));
4502
4464
    if (iobj->operands) {
4503
4465
        char *types = insn_op_types(iobj->insn_id);
4504
4466
        int j;
4548
4510
                rb_str_cat2(str, "<ch>");
4549
4511
                break;
4550
4512
              default:{
4551
 
                  rb_bug("unknown operand type: %c", type);
 
4513
                rb_raise(rb_eSyntaxError, "unknown operand type: %c", type);
4552
4514
              }
4553
4515
            }
4554
4516
            if (types[j + 1]) {
4593
4555
            }
4594
4556
          default:
4595
4557
            /* ignore */
4596
 
            printf("%ld\n", FIX2LONG(link->type));
4597
 
            rb_bug("dump_disasm_list error");
 
4558
            rb_raise(rb_eSyntaxError, "dump_disasm_list error: %ld\n", FIX2LONG(link->type));
4598
4559
        }
4599
4560
        link = link->next;
4600
4561
    }
4601
4562
    printf("---------------------\n");
4602
4563
}
4603
4564
 
4604
 
int
4605
 
nd_line_debug(NODE * n)
4606
 
{
4607
 
    return nd_line(n);
4608
 
}
4609
 
 
4610
4565
VALUE
4611
4566
insns_name_array(void)
4612
4567
{
4622
4577
register_label(rb_iseq_t *iseq, struct st_table *labels_table, VALUE obj)
4623
4578
{
4624
4579
    LABEL *label = 0;
 
4580
    st_data_t tmp;
4625
4581
    obj = rb_convert_type(obj, T_SYMBOL, "Symbol", "to_sym");
4626
4582
 
4627
 
    if (st_lookup(labels_table, obj, (st_data_t *)&label) == 0) {
 
4583
    if (st_lookup(labels_table, obj, &tmp) == 0) {
4628
4584
        label = NEW_LABEL(0);
4629
4585
        st_insert(labels_table, obj, (st_data_t)label);
4630
4586
    }
 
4587
    else {
 
4588
        label = (LABEL *)tmp;
 
4589
    }
4631
4590
    return label;
4632
4591
}
4633
4592
 
4652
4611
    if (sym == symBreak)  return CATCH_TYPE_BREAK;
4653
4612
    if (sym == symRedo)   return  CATCH_TYPE_REDO;
4654
4613
    if (sym == symNext)   return CATCH_TYPE_NEXT;
4655
 
    rb_bug("get_exception_sym2type");
 
4614
    rb_raise(rb_eSyntaxError, "invalid exception symbol: %s",
 
4615
             RSTRING_PTR(rb_inspect(sym)));
4656
4616
    return 0;
4657
4617
}
4658
4618
 
4663
4623
    int i;
4664
4624
 
4665
4625
    for (i=0; i<RARRAY_LEN(exception); i++) {
4666
 
        VALUE v = rb_ary_entry(exception, i);
4667
 
        VALUE *ptr = RARRAY_PTR(v);
4668
 
        VALUE type = get_exception_sym2type(ptr[0]);
4669
 
        VALUE eiseqval;
 
4626
        VALUE v, type, *ptr, eiseqval;
4670
4627
        LABEL *lstart, *lend, *lcont;
4671
4628
        int sp;
4672
4629
 
 
4630
        RB_GC_GUARD(v) = rb_convert_type(RARRAY_PTR(exception)[i], T_ARRAY,
 
4631
                                         "Array", "to_ary");
 
4632
        if (RARRAY_LEN(v) != 6) {
 
4633
            rb_raise(rb_eSyntaxError, "wrong exception entry");
 
4634
        }
 
4635
        ptr  = RARRAY_PTR(v);
 
4636
        type = get_exception_sym2type(ptr[0]);
4673
4637
        if (ptr[1] == Qnil) {
4674
4638
            eiseqval = 0;
4675
4639
        }
4687
4651
    return COMPILE_OK;
4688
4652
}
4689
4653
 
4690
 
 
4691
4654
struct st_table *insn_make_insn_table(void);
4692
4655
 
4693
4656
static int
4694
4657
iseq_build_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor,
4695
 
                VALUE body, VALUE line, struct st_table *labels_table)
 
4658
                VALUE body, struct st_table *labels_table)
4696
4659
{
4697
4660
    /* TODO: body should be freezed */
4698
4661
    VALUE *ptr = RARRAY_PTR(body);
4722
4685
            VALUE *argv = 0;
4723
4686
            int argc = RARRAY_LEN(obj) - 1;
4724
4687
            VALUE insn_id;
 
4688
            VALUE insn;
4725
4689
 
4726
 
            if (st_lookup(insn_table, rb_ary_entry(obj, 0), &insn_id) == 0) {
 
4690
            insn = (argc < 0) ? Qnil : RARRAY_PTR(obj)[0];
 
4691
            if (st_lookup(insn_table, insn, &insn_id) == 0) {
4727
4692
                /* TODO: exception */
4728
 
                rb_bug("unknown instruction: ");
 
4693
                RB_GC_GUARD(insn) = rb_inspect(insn);
 
4694
                rb_compile_error(RSTRING_PTR(iseq->filename), line_no,
 
4695
                                 "unknown instruction: %s", RSTRING_PTR(insn));
4729
4696
            }
4730
4697
 
4731
4698
            if (argc != insn_len(insn_id)-1) {
4732
 
                rb_bug("operand size mismatch");
 
4699
                rb_compile_error(RSTRING_PTR(iseq->filename), line_no,
 
4700
                                 "operand size mismatch");
4733
4701
            }
4734
4702
 
4735
4703
            if (argc > 0) {
4738
4706
                    VALUE op = rb_ary_entry(obj, j+1);
4739
4707
                    switch (insn_op_type(insn_id, j)) {
4740
4708
                      case TS_OFFSET: {
4741
 
                          LABEL *label = register_label(iseq, labels_table, op);
4742
 
                          argv[j] = (VALUE)label;
4743
 
                          break;
 
4709
                        LABEL *label = register_label(iseq, labels_table, op);
 
4710
                        argv[j] = (VALUE)label;
 
4711
                        break;
4744
4712
                      }
4745
4713
                      case TS_LINDEX:
4746
4714
                      case TS_DINDEX:
4749
4717
                        break;
4750
4718
                      case TS_VALUE:
4751
4719
                        argv[j] = op;
4752
 
                        if (!SPECIAL_CONST_P(op)) {
4753
 
                            iseq_add_mark_object(iseq, op);
4754
 
                        }
 
4720
                        iseq_add_mark_object(iseq, op);
4755
4721
                        break;
4756
4722
                      case TS_ISEQ:
4757
4723
                        {
4758
4724
                            if (op != Qnil) {
4759
4725
                                if (TYPE(op) == T_ARRAY) {
4760
 
                                    argv[j] =
4761
 
                                      iseq_load(0, op, iseq->self, Qnil);
 
4726
                                    argv[j] = iseq_load(0, op, iseq->self, Qnil);
4762
4727
                                }
4763
4728
                                else if (CLASS_OF(op) == rb_cISeq) {
4764
4729
                                    argv[j] = op;
4765
4730
                                }
4766
4731
                                else {
4767
 
                                    /* TODO: exception */
4768
 
                                    rb_bug("not an iseq");
 
4732
                                    rb_raise(rb_eSyntaxError, "ISEQ is required");
4769
4733
                                }
4770
4734
                                iseq_add_mark_object(iseq, argv[j]);
4771
4735
                            }
4800
4764
                        }
4801
4765
                        break;
4802
4766
                      default:
4803
 
                        rb_bug("unknown operand: %c", insn_op_type(insn_id, j));
 
4767
                        rb_raise(rb_eSyntaxError, "unknown operand: %c", insn_op_type(insn_id, j));
4804
4768
                    }
4805
4769
                }
4806
4770
            }
4817
4781
    return COMPILE_OK;
4818
4782
}
4819
4783
 
 
4784
#define CHECK_ARRAY(v)   rb_convert_type(v, T_ARRAY, "Array", "to_ary")
 
4785
#define CHECK_STRING(v)  rb_convert_type(v, T_STRING, "String", "to_str")
 
4786
#define CHECK_SYMBOL(v)  rb_convert_type(v, T_SYMBOL, "Symbol", "to_sym")
 
4787
#define CHECK_INTEGER(v) (NUM2LONG(v), v)
 
4788
 
4820
4789
VALUE
4821
 
iseq_build_from_ary(rb_iseq_t *iseq, VALUE line,
4822
 
                    VALUE locals, VALUE args, VALUE exception, VALUE body)
 
4790
iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args,
 
4791
                    VALUE exception, VALUE body)
4823
4792
{
4824
4793
    int i;
4825
4794
    int opt = 0;
4828
4797
 
4829
4798
    DECL_ANCHOR(anchor);
4830
4799
 
 
4800
    INIT_ANCHOR(anchor);
4831
4801
    if (iseq->type == ISEQ_TYPE_METHOD ||
4832
4802
        iseq->type == ISEQ_TYPE_TOP ||
4833
4803
        iseq->type == ISEQ_TYPE_CLASS) {
4834
4804
        opt = 1;
4835
4805
    }
4836
4806
 
4837
 
    iseq->local_size = opt + RARRAY_LEN(locals);
4838
 
    iseq->local_table_size = iseq->local_size;
4839
 
    iseq->local_table = (ID *)ALLOC_N(ID *, iseq->local_size);
4840
 
    tbl = iseq->local_table + opt;
 
4807
    iseq->local_table_size = opt + RARRAY_LEN(locals);
 
4808
    iseq->local_table = tbl = (ID *)ALLOC_N(ID *, iseq->local_table_size);
 
4809
    iseq->local_size = opt + iseq->local_table_size;
4841
4810
 
4842
4811
    for (i=0; i<RARRAY_LEN(locals); i++) {
4843
 
        tbl[i] = SYM2ID(RARRAY_PTR(locals)[i]);
 
4812
        VALUE lv = RARRAY_PTR(locals)[i];
 
4813
        tbl[i] = FIXNUM_P(lv) ? FIX2INT(lv) : SYM2ID(CHECK_SYMBOL(lv));
4844
4814
    }
4845
4815
 
4846
4816
    /* args */
4847
4817
    if (FIXNUM_P(args)) {
4848
 
        iseq->argc = FIX2INT(args);
 
4818
        iseq->arg_size = iseq->argc = FIX2INT(args);
4849
4819
        iseq->arg_simple = 1;
4850
4820
    }
4851
4821
    else {
4852
 
        /*
4853
 
         * [argc,                 # argc
4854
 
         *  opts,                 # opts
4855
 
         *  [label1, label2, ...] # opt labels
4856
 
         *  rest_iex,
4857
 
         *  block_idx,
4858
 
         * ]
4859
 
         * or
4860
 
         *  argc (Fixnum) # arg_simple
4861
 
         */
4862
4822
        int i = 0;
4863
 
        VALUE argc  = rb_ary_entry(args, i++);
4864
 
        VALUE arg_opts = rb_ary_entry(args, i++);
4865
 
        VALUE arg_opt_labels = rb_ary_entry(args, i++);
4866
 
        VALUE arg_rest = rb_ary_entry(args, i++);
4867
 
        VALUE arg_block = rb_ary_entry(args, i++);
 
4823
        VALUE argc = CHECK_INTEGER(rb_ary_entry(args, i++));
 
4824
        VALUE arg_opts = CHECK_INTEGER(rb_ary_entry(args, i++));
 
4825
        VALUE arg_opt_labels = CHECK_ARRAY(rb_ary_entry(args, i++));
 
4826
        VALUE arg_post_len = CHECK_INTEGER(rb_ary_entry(args, i++));
 
4827
        VALUE arg_post_start = CHECK_INTEGER(rb_ary_entry(args, i++));
 
4828
        VALUE arg_rest = CHECK_INTEGER(rb_ary_entry(args, i++));
 
4829
        VALUE arg_block = CHECK_INTEGER(rb_ary_entry(args, i++));
4868
4830
 
4869
4831
        iseq->argc = FIX2INT(argc);
4870
4832
        iseq->arg_opts = FIX2INT(arg_opts);
4871
4833
        iseq->arg_rest = FIX2INT(arg_rest);
 
4834
        iseq->arg_post_len = FIX2INT(arg_post_len);
 
4835
        iseq->arg_post_start = FIX2INT(arg_post_start);
4872
4836
        iseq->arg_block = FIX2INT(arg_block);
 
4837
        iseq->arg_opt_table = (VALUE *)ALLOC_N(VALUE, iseq->arg_opts);
4873
4838
 
4874
 
        iseq->arg_opt_tbl = (VALUE *)ALLOC_N(VALUE, iseq->arg_opts);
 
4839
        if (iseq->arg_block != -1) {
 
4840
            iseq->arg_size = iseq->arg_block + 1;
 
4841
        }
 
4842
        else if (iseq->arg_post_len) {
 
4843
            iseq->arg_size = iseq->arg_post_start + iseq->arg_post_len;
 
4844
        }
 
4845
        else if (iseq->arg_rest != -1) {
 
4846
            iseq->arg_size = iseq->arg_rest + 1;
 
4847
        }
 
4848
        else {
 
4849
            iseq->arg_size = iseq->argc + iseq->arg_opts;
 
4850
        }
4875
4851
 
4876
4852
        for (i=0; i<RARRAY_LEN(arg_opt_labels); i++) {
4877
 
            iseq->arg_opt_tbl[i] =
 
4853
            iseq->arg_opt_table[i] =
4878
4854
              (VALUE)register_label(iseq, labels_table,
4879
4855
                                    rb_ary_entry(arg_opt_labels, i));
4880
4856
        }
4884
4860
    iseq_build_exception(iseq, labels_table, exception);
4885
4861
 
4886
4862
    /* body */
4887
 
    iseq_build_body(iseq, anchor, body, line, labels_table);
 
4863
    iseq_build_body(iseq, anchor, body, labels_table);
4888
4864
    return iseq->self;
4889
4865
}