Ruby  2.5.0dev(2017-10-22revision60238)
vm_insnhelper.h
Go to the documentation of this file.
1 /**********************************************************************
2 
3  insnhelper.h - helper macros to implement each instructions
4 
5  $Author$
6  created at: 04/01/01 15:50:34 JST
7 
8  Copyright (C) 2004-2007 Koichi Sasada
9 
10 **********************************************************************/
11 
12 #ifndef RUBY_INSNHELPER_H
13 #define RUBY_INSNHELPER_H
14 
16 
21 
23 
24 #if VM_COLLECT_USAGE_DETAILS
25 #define COLLECT_USAGE_INSN(insn) vm_collect_usage_insn(insn)
26 #define COLLECT_USAGE_OPERAND(insn, n, op) vm_collect_usage_operand((insn), (n), ((VALUE)(op)))
27 
28 #define COLLECT_USAGE_REGISTER(reg, s) vm_collect_usage_register((reg), (s))
29 #else
30 #define COLLECT_USAGE_INSN(insn) /* none */
31 #define COLLECT_USAGE_OPERAND(insn, n, op) /* none */
32 #define COLLECT_USAGE_REGISTER(reg, s) /* none */
33 #endif
34 
35 /**********************************************************/
36 /* deal with stack */
37 /**********************************************************/
38 
39 #define PUSH(x) (SET_SV(x), INC_SP(1))
40 #define TOPN(n) (*(GET_SP()-(n)-1))
41 #define POPN(n) (DEC_SP(n))
42 #define POP() (DEC_SP(1))
43 #define STACK_ADDR_FROM_TOP(n) (GET_SP()-(n))
44 
45 #define GET_TOS() (tos) /* dummy */
46 
47 /**********************************************************/
48 /* deal with registers */
49 /**********************************************************/
50 
51 #define VM_REG_CFP (reg_cfp)
52 #define VM_REG_PC (VM_REG_CFP->pc)
53 #define VM_REG_SP (VM_REG_CFP->sp)
54 #define VM_REG_EP (VM_REG_CFP->ep)
55 
56 #define RESTORE_REGS() do { \
57  VM_REG_CFP = th->ec.cfp; \
58 } while (0)
59 
60 #define REG_A reg_a
61 #define REG_B reg_b
62 
70 };
74 };
75 
76 #if VM_COLLECT_USAGE_DETAILS
77 #define COLLECT_USAGE_REGISTER_HELPER(a, b, v) \
78  (COLLECT_USAGE_REGISTER((VM_REGAN_##a), (VM_REGAN_ACT_##b)), (v))
79 #else
80 #define COLLECT_USAGE_REGISTER_HELPER(a, b, v) (v)
81 #endif
82 
83 /* PC */
84 #define GET_PC() (COLLECT_USAGE_REGISTER_HELPER(PC, GET, VM_REG_PC))
85 #define SET_PC(x) (VM_REG_PC = (COLLECT_USAGE_REGISTER_HELPER(PC, SET, (x))))
86 #define GET_CURRENT_INSN() (*GET_PC())
87 #define GET_OPERAND(n) (GET_PC()[(n)])
88 #define ADD_PC(n) (SET_PC(VM_REG_PC + (n)))
89 #define JUMP(dst) (VM_REG_PC += (dst))
90 
91 /* frame pointer, environment pointer */
92 #define GET_CFP() (COLLECT_USAGE_REGISTER_HELPER(CFP, GET, VM_REG_CFP))
93 #define GET_EP() (COLLECT_USAGE_REGISTER_HELPER(EP, GET, VM_REG_EP))
94 #define SET_EP(x) (VM_REG_EP = (COLLECT_USAGE_REGISTER_HELPER(EP, SET, (x))))
95 #define GET_LEP() (VM_EP_LEP(GET_EP()))
96 
97 /* SP */
98 #define GET_SP() (COLLECT_USAGE_REGISTER_HELPER(SP, GET, VM_REG_SP))
99 #define SET_SP(x) (VM_REG_SP = (COLLECT_USAGE_REGISTER_HELPER(SP, SET, (x))))
100 #define INC_SP(x) (VM_REG_SP += (COLLECT_USAGE_REGISTER_HELPER(SP, SET, (x))))
101 #define DEC_SP(x) (VM_REG_SP -= (COLLECT_USAGE_REGISTER_HELPER(SP, SET, (x))))
102 #define SET_SV(x) (*GET_SP() = (x))
103  /* set current stack value as x */
104 
105 #define GET_SP_COUNT() (VM_REG_SP - th->ec.vm_stack)
106 
107 /* instruction sequence C struct */
108 #define GET_ISEQ() (GET_CFP()->iseq)
109 
110 /**********************************************************/
111 /* deal with variables */
112 /**********************************************************/
113 
114 #define GET_PREV_EP(ep) ((VALUE *)((ep)[VM_ENV_DATA_INDEX_SPECVAL] & ~0x03))
115 
116 #define GET_GLOBAL(entry) rb_gvar_get((struct rb_global_entry*)(entry))
117 #define SET_GLOBAL(entry, val) rb_gvar_set((struct rb_global_entry*)(entry), (val))
118 
119 #define GET_CONST_INLINE_CACHE(dst) ((IC) * (GET_PC() + (dst) + 2))
120 
121 /**********************************************************/
122 /* deal with values */
123 /**********************************************************/
124 
125 #define GET_SELF() (COLLECT_USAGE_REGISTER_HELPER(SELF, GET, GET_CFP()->self))
126 
127 /**********************************************************/
128 /* deal with control flow 2: method/iterator */
129 /**********************************************************/
130 
131 #define CALL_METHOD(calling, ci, cc) do { \
132  VALUE v = (*(cc)->call)(th, GET_CFP(), (calling), (ci), (cc)); \
133  if (v == Qundef) { \
134  RESTORE_REGS(); \
135  NEXT_INSN(); \
136  } \
137  else { \
138  val = v; \
139  } \
140 } while (0)
141 
142 /* set fastpath when cached method is *NOT* protected
143  * because inline method cache does not care about receiver.
144  */
145 
146 #ifndef OPT_CALL_FASTPATH
147 #define OPT_CALL_FASTPATH 1
148 #endif
149 
150 #if OPT_CALL_FASTPATH
151 #define CI_SET_FASTPATH(cc, func, enabled) do { \
152  if (LIKELY(enabled)) ((cc)->call = (func)); \
153 } while (0)
154 #else
155 #define CI_SET_FASTPATH(ci, func, enabled) /* do nothing */
156 #endif
157 
158 #define GET_BLOCK_HANDLER() (GET_LEP()[VM_ENV_DATA_INDEX_SPECVAL])
159 
160 /**********************************************************/
161 /* deal with control flow 3: exception */
162 /**********************************************************/
163 
164 
165 /**********************************************************/
166 /* others */
167 /**********************************************************/
168 
169 /* optimize insn */
170 #define FIXNUM_2_P(a, b) ((a) & (b) & 1)
171 #if USE_FLONUM
172 #define FLONUM_2_P(a, b) (((((a)^2) | ((b)^2)) & 3) == 0) /* (FLONUM_P(a) && FLONUM_P(b)) */
173 #else
174 #define FLONUM_2_P(a, b) 0
175 #endif
176 #define FLOAT_HEAP_P(x) (!SPECIAL_CONST_P(x) && RBASIC_CLASS(x) == rb_cFloat)
177 #define FLOAT_INSTANCE_P(x) (FLONUM_P(x) || FLOAT_HEAP_P(x))
178 
179 #ifndef USE_IC_FOR_SPECIALIZED_METHOD
180 #define USE_IC_FOR_SPECIALIZED_METHOD 1
181 #endif
182 
183 #define CALL_SIMPLE_METHOD(recv_) do { \
184  struct rb_calling_info calling; \
185  calling.block_handler = VM_BLOCK_HANDLER_NONE; \
186  calling.argc = ci->orig_argc; \
187  vm_search_method(ci, cc, calling.recv = (recv_)); \
188  CALL_METHOD(&calling, ci, cc); \
189 } while (0)
190 
191 #define NEXT_CLASS_SERIAL() (++ruby_vm_class_serial)
192 #define GET_GLOBAL_METHOD_STATE() (ruby_vm_global_method_state)
193 #define INC_GLOBAL_METHOD_STATE() (++ruby_vm_global_method_state)
194 #define GET_GLOBAL_CONSTANT_STATE() (ruby_vm_global_constant_state)
195 #define INC_GLOBAL_CONSTANT_STATE() (++ruby_vm_global_constant_state)
196 
197 static VALUE make_no_method_exception(VALUE exc, VALUE format, VALUE obj,
198  int argc, const VALUE *argv, int priv);
199 
200 static inline struct vm_throw_data *
201 THROW_DATA_NEW(VALUE val, const rb_control_frame_t *cf, VALUE st)
202 {
203  return (struct vm_throw_data *)rb_imemo_new(imemo_throw_data, val, (VALUE)cf, st, 0);
204 }
205 
206 static inline VALUE
207 THROW_DATA_VAL(const struct vm_throw_data *obj)
208 {
209  VM_ASSERT(THROW_DATA_P(obj));
210  return obj->throw_obj;
211 }
212 
213 static inline const rb_control_frame_t *
214 THROW_DATA_CATCH_FRAME(const struct vm_throw_data *obj)
215 {
216  VM_ASSERT(THROW_DATA_P(obj));
217  return obj->catch_frame;
218 }
219 
220 static inline int
221 THROW_DATA_STATE(const struct vm_throw_data *obj)
222 {
223  VM_ASSERT(THROW_DATA_P(obj));
224  return (int)obj->throw_state;
225 }
226 
227 static inline int
228 THROW_DATA_CONSUMED_P(const struct vm_throw_data *obj)
229 {
230  VM_ASSERT(THROW_DATA_P(obj));
231  return obj->flags & THROW_DATA_CONSUMED;
232 }
233 
234 static inline void
235 THROW_DATA_CATCH_FRAME_SET(struct vm_throw_data *obj, const rb_control_frame_t *cfp)
236 {
237  VM_ASSERT(THROW_DATA_P(obj));
238  obj->catch_frame = cfp;
239 }
240 
241 static inline void
242 THROW_DATA_STATE_SET(struct vm_throw_data *obj, int st)
243 {
244  VM_ASSERT(THROW_DATA_P(obj));
245  obj->throw_state = (VALUE)st;
246 }
247 
248 static inline void
249 THROW_DATA_CONSUMED_SET(struct vm_throw_data *obj)
250 {
251  if (THROW_DATA_P(obj) &&
252  THROW_DATA_STATE(obj) == TAG_BREAK) {
253  obj->flags |= THROW_DATA_CONSUMED;
254  }
255 }
256 
257 #endif /* RUBY_INSNHELPER_H */
vm_regan_regtype
Definition: vm_insnhelper.h:63
VALUE throw_state
Definition: internal.h:900
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
Definition: gc.c:2020
#define THROW_DATA_P(err)
Definition: internal.h:903
#define THROW_DATA_CONSUMED
Definition: internal.h:892
RUBY_SYMBOL_EXPORT_BEGIN VALUE ruby_vm_const_missing_count
Definition: vm.c:319
#define val
rb_serial_t ruby_vm_global_method_state
Definition: vm.c:323
VALUE flags
Definition: internal.h:896
THROW_DATA.
Definition: internal.h:895
const VALUE throw_obj
Definition: internal.h:898
int argc
Definition: ruby.c:187
rb_serial_t ruby_vm_class_serial
Definition: vm.c:325
unsigned long rb_serial_t
Definition: internal.h:751
#define VM_ASSERT(expr)
Definition: vm_core.h:53
#define RUBY_SYMBOL_EXPORT_END
Definition: missing.h:49
unsigned long VALUE
Definition: ruby.h:85
#define RUBY_SYMBOL_EXPORT_BEGIN
Definition: missing.h:48
const struct rb_control_frame_struct * catch_frame
Definition: internal.h:899
vm_regan_acttype
Definition: vm_insnhelper.h:71
#define TAG_BREAK
Definition: vm_core.h:166
rb_serial_t ruby_vm_global_constant_state
Definition: vm.c:324
char ** argv
Definition: ruby.c:188