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