update comment.
[ruby-svn.git] / vm.h
blobc485cae80b28ac3781919e90d5305a4997d11b75
1 /**********************************************************************
3 vm.h -
5 $Author$
6 created at: 04/01/01 16:56:59 JST
8 Copyright (C) 2004-2007 Koichi Sasada
10 **********************************************************************/
12 #ifndef RUBY_VM_H
13 #define RUBY_VM_H
15 typedef long OFFSET;
16 typedef unsigned long lindex_t;
17 typedef unsigned long dindex_t;
18 typedef rb_num_t GENTRY;
19 typedef rb_iseq_t *ISEQ;
21 extern VALUE rb_cEnv;
22 extern VALUE ruby_vm_global_state_version;
23 extern VALUE ruby_vm_redefined_flag;
26 /**
27 * VM Debug Level
29 * debug level:
30 * 0: no debug output
31 * 1: show instruction name
32 * 2: show stack frame when control stack frame is changed
33 * 3: show stack status
34 * 4: show register
35 * 5:
36 * 10: gc check
40 #ifndef VMDEBUG
41 #define VMDEBUG 0
42 #endif
44 #if 0
45 #undef VMDEBUG
46 #define VMDEBUG 3
47 #endif
49 #ifdef COLLECT_USAGE_ANALYSIS
50 #define USAGE_ANALYSIS_INSN(insn) vm_analysis_insn(insn)
51 #define USAGE_ANALYSIS_OPERAND(insn, n, op) vm_analysis_operand(insn, n, (VALUE)op)
52 #define USAGE_ANALYSIS_REGISTER(reg, s) vm_analysis_register(reg, s)
53 #else
54 #define USAGE_ANALYSIS_INSN(insn) /* none */
55 #define USAGE_ANALYSIS_OPERAND(insn, n, op) /* none */
56 #define USAGE_ANALYSIS_REGISTER(reg, s) /* none */
57 #endif
59 #ifdef __GCC__
60 /* TODO: machine dependent prefetch instruction */
61 #define PREFETCH(pc)
62 #else
63 #define PREFETCH(pc)
64 #endif
66 #if VMDEBUG > 0
67 #define debugs printf
68 #define DEBUG_ENTER_INSN(insn) \
69 debug_print_pre(th, GET_CFP());
71 #if OPT_STACK_CACHING
72 #define SC_REGS() , reg_a, reg_b
73 #else
74 #define SC_REGS()
75 #endif
77 #define DEBUG_END_INSN() \
78 debug_print_post(th, GET_CFP() SC_REGS());
80 #else
82 #define debugs
83 #define DEBUG_ENTER_INSN(insn)
84 #define DEBUG_END_INSN()
85 #endif
87 #define throwdebug if(0)printf
88 /* #define throwdebug printf */
90 #define SDR2(cfp) vm_stack_dump_raw(GET_THREAD(), (cfp))
93 /************************************************/
94 #if DISPATCH_XXX
95 error !
96 /************************************************/
97 #elif OPT_CALL_THREADED_CODE
99 #define LABEL(x) insn_func_##x
100 #define ELABEL(x)
101 #define LABEL_PTR(x) &LABEL(x)
103 #define INSN_ENTRY(insn) \
104 static rb_control_frame_t * \
105 FUNC_FASTCALL(LABEL(insn))(rb_thread_t *th, rb_control_frame_t *reg_cfp) {
107 #define END_INSN(insn) return reg_cfp;}
109 #define NEXT_INSN() return reg_cfp;
111 /************************************************/
112 #elif OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
113 /* threaded code with gcc */
115 #define LABEL(x) INSN_LABEL_##x
116 #define ELABEL(x) INSN_ELABEL_##x
117 #define LABEL_PTR(x) &&LABEL(x)
119 #define INSN_ENTRY_SIG(insn)
122 #define INSN_DISPATCH_SIG(insn)
124 #define INSN_ENTRY(insn) \
125 LABEL(insn): \
126 INSN_ENTRY_SIG(insn); \
128 /* dispather */
129 #if __GNUC__ && (__i386__ || __x86_64__) && __GNUC__ == 3
130 #define DISPATCH_ARCH_DEPEND_WAY(addr) \
131 asm volatile("jmp *%0;\t# -- inseted by vm.h\t[length = 2]" : : "r" (addr))
133 #else
134 #define DISPATCH_ARCH_DEPEND_WAY(addr) \
135 /* do nothing */
137 #endif
140 /**********************************/
141 #if OPT_DIRECT_THREADED_CODE
143 /* for GCC 3.4.x */
144 #define TC_DISPATCH(insn) \
145 INSN_DISPATCH_SIG(insn); \
146 goto *GET_CURRENT_INSN(); \
149 #else
150 /* token threade code */
152 #define TC_DISPATCH(insn) \
153 DISPATCH_ARCH_DEPEND_WAY(insns_address_table[GET_CURRENT_INSN()]); \
154 INSN_DISPATCH_SIG(insn); \
155 goto *insns_address_table[GET_CURRENT_INSN()]; \
156 rb_bug("tc error");
159 #endif /* DISPATCH_DIRECT_THREADED_CODE */
161 #define END_INSN(insn) \
162 DEBUG_END_INSN(); \
163 TC_DISPATCH(insn); \
165 #define INSN_DISPATCH() \
166 TC_DISPATCH(__START__) \
169 #define END_INSNS_DISPATCH() \
170 rb_bug("unknown insn: %ld", GET_CURRENT_INSN()); \
171 } /* end of while loop */ \
173 #define NEXT_INSN() TC_DISPATCH(__NEXT_INSN__)
175 /************************************************/
176 #else /* no threaded code */
177 /* most common method */
179 #define INSN_ENTRY(insn) \
180 case BIN(insn):
182 #define END_INSN(insn) \
183 DEBUG_END_INSN(); \
184 break;
187 #define INSN_DISPATCH() \
188 while(1){ \
189 switch(GET_CURRENT_INSN()){
191 #define END_INSNS_DISPATCH() \
192 default: \
193 SDR(); \
194 rb_bug("unknown insn: %ld", GET_CURRENT_INSN()); \
195 } /* end of switch */ \
196 } /* end of while loop */ \
198 #define NEXT_INSN() goto first
200 #endif
203 /************************************************/
204 /************************************************/
206 #define VM_CFP_CNT(th, cfp) \
207 ((rb_control_frame_t *)(th->stack + th->stack_size) - (rb_control_frame_t *)(cfp))
208 #define VM_SP_CNT(th, sp) ((sp) - (th)->stack)
211 env{
212 env[0] // special (block or prev env)
213 env[1] // env object
214 env[2] // prev env val
218 #define ENV_IN_HEAP_P(th, env) \
219 (!((th)->stack < (env) && (env) < ((th)->stack + (th)->stack_size)))
220 #define ENV_VAL(env) ((env)[1])
222 #if OPT_CALL_THREADED_CODE
223 #define THROW_EXCEPTION(exc) do { \
224 th->errinfo = (VALUE)(exc); \
225 return 0; \
226 } while (0)
227 #else
228 #define THROW_EXCEPTION(exc) return (VALUE)(exc)
229 #endif
231 #define SCREG(r) (reg_##r)
233 /* VM state version */
235 #define GET_VM_STATE_VERSION() (ruby_vm_global_state_version)
236 #define INC_VM_STATE_VERSION() \
237 (ruby_vm_global_state_version = (ruby_vm_global_state_version+1) & 0x8fffffff)
239 #define BOP_PLUS 0x01
240 #define BOP_MINUS 0x02
241 #define BOP_MULT 0x04
242 #define BOP_DIV 0x08
243 #define BOP_MOD 0x10
244 #define BOP_EQ 0x20
245 #define BOP_LT 0x40
246 #define BOP_LE 0x80
247 #define BOP_LTLT 0x100
248 #define BOP_AREF 0x200
249 #define BOP_ASET 0x400
250 #define BOP_LENGTH 0x800
251 #define BOP_SUCC 0x1000
252 #define BOP_GT 0x2000
253 #define BOP_GE 0x4000
254 #define BOP_NOT 0x8000
255 #define BOP_NEQ 0x10000
257 #endif /* RUBY_VM_H */