Ruby: include/ruby/internal/value_type.h Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

value_type.h
Go to the documentation of this file.
1#ifndef RBIMPL_VALUE_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/
2#define RBIMPL_VALUE_TYPE_H
23#include "ruby/internal/assume.h"
24#include "ruby/internal/attr/artificial.h"
25#include "ruby/internal/attr/cold.h"
26#include "ruby/internal/attr/enum_extensibility.h"
27#include "ruby/internal/attr/forceinline.h"
28#include "ruby/internal/attr/pure.h"
29#include "ruby/internal/cast.h"
30#include "ruby/internal/constant_p.h"
31#include "ruby/internal/core/rbasic.h"
32#include "ruby/internal/dllexport.h"
33#include "ruby/internal/has/builtin.h"
34#include "ruby/internal/special_consts.h"
35#include "ruby/internal/stdbool.h"
36#include "ruby/internal/value.h"
37#include "ruby/assert.h"
38
39#if defined(T_DATA)
40/*
41 * :!BEWARE!: (Recent?) Solaris' <nfs/nfs.h> have conflicting definition of
42 * T_DATA. Let us stop here. Please have a workaround like this:
43 *
44 * ```C
45 * #include <ruby/ruby.h> // <- Include this one first.
46 * #undef T_DATA // <- ... and stick to RUBY_T_DATA forever.
47 * #include <nfs/nfs.h> // <- OS-provided T_DATA introduced.
48 * ```
49 *
50 * See also [ruby-core:4261]
51 */
52# error Bail out due to conflicting definition of T_DATA.
53#endif
54
55#define T_ARRAY RUBY_T_ARRAY
56#define T_BIGNUM RUBY_T_BIGNUM
57#define T_CLASS RUBY_T_CLASS
58#define T_COMPLEX RUBY_T_COMPLEX
59#define T_DATA RUBY_T_DATA
60#define T_FALSE RUBY_T_FALSE
61#define T_FILE RUBY_T_FILE
62#define T_FIXNUM RUBY_T_FIXNUM
63#define T_FLOAT RUBY_T_FLOAT
64#define T_HASH RUBY_T_HASH
65#define T_ICLASS RUBY_T_ICLASS
66#define T_IMEMO RUBY_T_IMEMO
67#define T_MASK RUBY_T_MASK
68#define T_MATCH RUBY_T_MATCH
69#define T_MODULE RUBY_T_MODULE
70#define T_MOVED RUBY_T_MOVED
71#define T_NIL RUBY_T_NIL
72#define T_NODE RUBY_T_NODE
73#define T_NONE RUBY_T_NONE
74#define T_OBJECT RUBY_T_OBJECT
75#define T_RATIONAL RUBY_T_RATIONAL
76#define T_REGEXP RUBY_T_REGEXP
77#define T_STRING RUBY_T_STRING
78#define T_STRUCT RUBY_T_STRUCT
79#define T_SYMBOL RUBY_T_SYMBOL
80#define T_TRUE RUBY_T_TRUE
81#define T_UNDEF RUBY_T_UNDEF
82#define T_ZOMBIE RUBY_T_ZOMBIE
83
84#define BUILTIN_TYPE RB_BUILTIN_TYPE
85#define DYNAMIC_SYM_P RB_DYNAMIC_SYM_P
86#define RB_INTEGER_TYPE_P rb_integer_type_p
87#define SYMBOL_P RB_SYMBOL_P
88#define rb_type_p RB_TYPE_P
89
91#define RB_BUILTIN_TYPE RB_BUILTIN_TYPE
92#define RB_DYNAMIC_SYM_P RB_DYNAMIC_SYM_P
93#define RB_FLOAT_TYPE_P RB_FLOAT_TYPE_P
94#define RB_SYMBOL_P RB_SYMBOL_P
95#define RB_TYPE_P RB_TYPE_P
96#define Check_Type Check_Type
97
98#if !RUBY_DEBUG
99# define RBIMPL_ASSERT_TYPE(v, t) RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P((v), (t)))
100#else
101# define RBIMPL_ASSERT_TYPE Check_Type
102#endif
105#define TYPE(_) RBIMPL_CAST((int)rb_type(_))
106
108 enum
109 RBIMPL_ATTR_ENUM_EXTENSIBILITY(closed)
110 ruby_value_type {
111 RUBY_T_NONE = 0x00,
113 RUBY_T_OBJECT = 0x01,
114 RUBY_T_CLASS = 0x02,
115 RUBY_T_MODULE = 0x03,
116 RUBY_T_FLOAT = 0x04,
117 RUBY_T_STRING = 0x05,
118 RUBY_T_REGEXP = 0x06,
119 RUBY_T_ARRAY = 0x07,
120 RUBY_T_HASH = 0x08,
121 RUBY_T_STRUCT = 0x09,
122 RUBY_T_BIGNUM = 0x0a,
123 RUBY_T_FILE = 0x0b,
124 RUBY_T_DATA = 0x0c,
125 RUBY_T_MATCH = 0x0d,
126 RUBY_T_COMPLEX = 0x0e,
127 RUBY_T_RATIONAL = 0x0f,
129 RUBY_T_NIL = 0x11,
130 RUBY_T_TRUE = 0x12,
131 RUBY_T_FALSE = 0x13,
132 RUBY_T_SYMBOL = 0x14,
133 RUBY_T_FIXNUM = 0x15,
134 RUBY_T_UNDEF = 0x16,
136 RUBY_T_IMEMO = 0x1a,
137 RUBY_T_NODE = 0x1b,
138 RUBY_T_ICLASS = 0x1c,
139 RUBY_T_ZOMBIE = 0x1d,
140 RUBY_T_MOVED = 0x1e,
142 RUBY_T_MASK = 0x1f
143};
144
145 RBIMPL_SYMBOL_EXPORT_BEGIN()
146 RBIMPL_ATTR_COLD()
147void rb_check_type(VALUE obj, int t);
148 RBIMPL_SYMBOL_EXPORT_END()
149
150 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
151 RBIMPL_ATTR_ARTIFICIAL()
152static inline enum ruby_value_type
153RB_BUILTIN_TYPE(VALUE obj)
154{
155 RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj));
156
157 VALUE ret = RBASIC(obj)->flags & RUBY_T_MASK;
158 return RBIMPL_CAST((enum ruby_value_type)ret);
159}
160
161 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
162static inline bool
163rb_integer_type_p(VALUE obj)
164{
165 if (RB_FIXNUM_P(obj)) {
166 return true;
167 }
168 else if (RB_SPECIAL_CONST_P(obj)) {
169 return false;
170 }
171 else {
172 return RB_BUILTIN_TYPE(obj) == RUBY_T_BIGNUM;
173 }
174}
175
176 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
177static inline enum ruby_value_type
178rb_type(VALUE obj)
179{
180 if (! RB_SPECIAL_CONST_P(obj)) {
181 return RB_BUILTIN_TYPE(obj);
182 }
183 else if (obj == RUBY_Qfalse) {
184 return RUBY_T_FALSE;
185 }
186 else if (obj == RUBY_Qnil) {
187 return RUBY_T_NIL;
188 }
189 else if (obj == RUBY_Qtrue) {
190 return RUBY_T_TRUE;
191 }
192 else if (obj == RUBY_Qundef) {
193 return RUBY_T_UNDEF;
194 }
195 else if (RB_FIXNUM_P(obj)) {
196 return RUBY_T_FIXNUM;
197 }
198 else if (RB_STATIC_SYM_P(obj)) {
199 return RUBY_T_SYMBOL;
200 }
201 else {
202 RBIMPL_ASSUME(RB_FLONUM_P(obj));
203 return RUBY_T_FLOAT;
204 }
205}
206
207 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
208 RBIMPL_ATTR_ARTIFICIAL()
209static inline bool
210RB_FLOAT_TYPE_P(VALUE obj)
211{
212 if (RB_FLONUM_P(obj)) {
213 return true;
214 }
215 else if (RB_SPECIAL_CONST_P(obj)) {
216 return false;
217 }
218 else {
219 return RB_BUILTIN_TYPE(obj) == RUBY_T_FLOAT;
220 }
221}
222
223 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
224 RBIMPL_ATTR_ARTIFICIAL()
225static inline bool
226RB_DYNAMIC_SYM_P(VALUE obj)
227{
228 if (RB_SPECIAL_CONST_P(obj)) {
229 return false;
230 }
231 else {
232 return RB_BUILTIN_TYPE(obj) == RUBY_T_SYMBOL;
233 }
234}
235
236 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
237 RBIMPL_ATTR_ARTIFICIAL()
238static inline bool
239RB_SYMBOL_P(VALUE obj)
240{
241 return RB_STATIC_SYM_P(obj) || RB_DYNAMIC_SYM_P(obj);
242}
243
244 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
245 RBIMPL_ATTR_ARTIFICIAL()
246 RBIMPL_ATTR_FORCEINLINE()
247static bool
248rbimpl_RB_TYPE_P_fastpath(VALUE obj, enum ruby_value_type t)
249{
250 if (t == RUBY_T_TRUE) {
251 return obj == RUBY_Qtrue;
252 }
253 else if (t == RUBY_T_FALSE) {
254 return obj == RUBY_Qfalse;
255 }
256 else if (t == RUBY_T_NIL) {
257 return obj == RUBY_Qnil;
258 }
259 else if (t == RUBY_T_UNDEF) {
260 return obj == RUBY_Qundef;
261 }
262 else if (t == RUBY_T_FIXNUM) {
263 return RB_FIXNUM_P(obj);
264 }
265 else if (t == RUBY_T_SYMBOL) {
266 return RB_SYMBOL_P(obj);
267 }
268 else if (t == RUBY_T_FLOAT) {
269 return RB_FLOAT_TYPE_P(obj);
270 }
271 else if (RB_SPECIAL_CONST_P(obj)) {
272 return false;
273 }
274 else if (t == RB_BUILTIN_TYPE(obj)) {
275 return true;
276 }
277 else {
278 return false;
279 }
280}
281
282 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
283 RBIMPL_ATTR_ARTIFICIAL()
284static inline bool
285RB_TYPE_P(VALUE obj, enum ruby_value_type t)
286{
287 if (RBIMPL_CONSTANT_P(t)) {
288 return rbimpl_RB_TYPE_P_fastpath(obj, t);
289 }
290 else {
291 return t == rb_type(obj);
292 }
293}
294
296/* Clang, unlike GCC, cannot propagate __builtin_constant_p beyond function
297 * boundary. */
298#if defined(__clang__)
299# undef RB_TYPE_P
300# define RB_TYPE_P(obj, t) \
301 (RBIMPL_CONSTANT_P(t) ? \
302 rbimpl_RB_TYPE_P_fastpath((obj), (t)) : \
303 (RB_TYPE_P)((obj), (t)))
304#endif
305
306/* clang 3.x (4.2 compatible) can't eliminate CSE of RB_BUILTIN_TYPE
307 * in inline function and caller function
308 * See also 8998c06461ea0bef11b3aeb30b6d2ab71c8762ba
309 */
310#if RBIMPL_COMPILER_BEFORE(Clang, 4, 0, 0)
311# undef rb_integer_type_p
312# define rb_integer_type_p(obj) \
313 __extension__ ({ \
314 const VALUE integer_type_obj = (obj); \
315 (RB_FIXNUM_P(integer_type_obj) || \
316 (!RB_SPECIAL_CONST_P(integer_type_obj) && \
317 RB_BUILTIN_TYPE(integer_type_obj) == RUBY_T_BIGNUM)); \
318 })
319#endif
322 RBIMPL_ATTR_PURE()
323 RBIMPL_ATTR_ARTIFICIAL()
324/* Defined in ruby/internal/core/rtypeddata.h */
325static inline bool rbimpl_rtypeddata_p(VALUE obj);
326
327 RBIMPL_ATTR_ARTIFICIAL()
328static inline void
329Check_Type(VALUE v, enum ruby_value_type t)
330{
331 if (RB_UNLIKELY(! RB_TYPE_P(v, t))) {
332 goto slowpath;
333 }
334 else if (t != RUBY_T_DATA) {
335 goto fastpath;
336 }
337 else if (rbimpl_rtypeddata_p(v)) {
338 /* The intention itself is not necessarily clear to me, but at least it
339 * is intentional to rule out typed data here. See commit
340 * a7c32bf81d3391cfb78cfda278f469717d0fb794. */
341 goto slowpath;
342 }
343 else {
344 goto fastpath;
345 }
346
347 fastpath:
348 return;
349
350 slowpath: /* <- :TODO: mark this label as cold. */
351 rb_check_type(v, t);
352}
353
354#endif /* RBIMPL_VALUE_TYPE_H */
artificial.h
Defines RBIMPL_ATTR_ARTIFICIAL.
RBIMPL_ATTR_ARTIFICIAL
#define RBIMPL_ATTR_ARTIFICIAL()
Wraps (or simulates) __attribute__((artificial))
Definition: artificial.h:43
assert.h
RBIMPL_ASSERT_OR_ASSUME
#define RBIMPL_ASSERT_OR_ASSUME(expr)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
Definition: assert.h:229
RB_UNLIKELY
#define RB_UNLIKELY(x)
Definition: assume.h:40
cast.h
Defines RBIMPL_CAST.
cold.h
Defines RBIMPL_ATTR_COLD.
RBIMPL_ATTR_COLD
#define RBIMPL_ATTR_COLD()
Wraps (or simulates) __attribute__((cold))
Definition: cold.h:34
constant_p.h
Defines RBIMPL_CONSTANT_P.
RBIMPL_CONSTANT_P
#define RBIMPL_CONSTANT_P(expr)
Definition: constant_p.h:34
dllexport.h
Tewaking visibility of C variables/functions.
RBIMPL_SYMBOL_EXPORT_END
#define RBIMPL_SYMBOL_EXPORT_END()
Counterpart of RBIMPL_SYMBOL_EXPORT_BEGIN.
Definition: dllexport.h:86
RBIMPL_SYMBOL_EXPORT_BEGIN
#define RBIMPL_SYMBOL_EXPORT_BEGIN()
Shortcut macro equivalent to RUBY_SYMBOL_EXPORT_BEGIN extern "C" {.
Definition: dllexport.h:77
enum_extensibility.h
RBIMPL_ATTR_ENUM_EXTENSIBILITY.
RBIMPL_ATTR_ENUM_EXTENSIBILITY
#define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_)
Wraps (or simulates) __attribute__((enum_extensibility))
Definition: enum_extensibility.h:29
forceinline.h
Defines RBIMPL_ATTR_FORCEINLINE.
RBIMPL_ATTR_FORCEINLINE
#define RBIMPL_ATTR_FORCEINLINE()
Wraps (or simulates) __forceinline.
Definition: forceinline.h:37
rb_check_type
void rb_check_type(VALUE obj, int t)
Definition: error.c:972
builtin.h
Defines RBIMPL_HAS_BUILTIN.
assume.h
Defines RBIMPL_ASSUME / RBIMPL_UNREACHABLE.
RBIMPL_ASSUME
#define RBIMPL_ASSUME(_)
Wraps (or simulates) __builtin_unreachable.
Definition: assume.h:79
pure.h
Defines RBIMPL_ATTR_PURE.
RBIMPL_ATTR_PURE
#define RBIMPL_ATTR_PURE()
Wraps (or simulates) __attribute__((pure))
Definition: pure.h:33
RBIMPL_ATTR_PURE_UNLESS_DEBUG
#define RBIMPL_ATTR_PURE_UNLESS_DEBUG()
Enables RBIMPL_ATTR_PURE iff.
Definition: pure.h:38
rbasic.h
Defines struct RBasic.
RBASIC
#define RBASIC(obj)
Definition: rbasic.h:34
special_consts.h
Defines enum ruby_special_consts.
RUBY_Qtrue
@ RUBY_Qtrue
Definition: special_consts.h:88
RUBY_Qnil
@ RUBY_Qnil
Definition: special_consts.h:89
RUBY_Qundef
@ RUBY_Qundef
Definition: special_consts.h:90
RUBY_Qfalse
@ RUBY_Qfalse
Definition: special_consts.h:87
stdbool.h
C99 shim for <stdbool.h>
t
#define t
Definition: symbol.c:253
value.h
Defines VALUE and ID.
VALUE
unsigned long VALUE
Definition: value.h:38
ruby_value_type
ruby_value_type
C-level type of an object.
Definition: value_type.h:110
RUBY_T_SYMBOL
@ RUBY_T_SYMBOL
Definition: value_type.h:132
RUBY_T_MATCH
@ RUBY_T_MATCH
Definition: value_type.h:125
RUBY_T_MODULE
@ RUBY_T_MODULE
Definition: value_type.h:115
RUBY_T_ICLASS
@ RUBY_T_ICLASS
Hidden classes known as IClasses.
Definition: value_type.h:138
RUBY_T_MOVED
@ RUBY_T_MOVED
Definition: value_type.h:140
RUBY_T_FIXNUM
@ RUBY_T_FIXNUM
Integers formerly known as Fixnums.
Definition: value_type.h:133
RUBY_T_IMEMO
@ RUBY_T_IMEMO
Definition: value_type.h:136
RUBY_T_NODE
@ RUBY_T_NODE
Definition: value_type.h:137
RUBY_T_OBJECT
@ RUBY_T_OBJECT
Definition: value_type.h:113
RUBY_T_DATA
@ RUBY_T_DATA
Definition: value_type.h:124
RUBY_T_FALSE
@ RUBY_T_FALSE
Definition: value_type.h:131
RUBY_T_UNDEF
@ RUBY_T_UNDEF
Definition: value_type.h:134
RUBY_T_COMPLEX
@ RUBY_T_COMPLEX
Definition: value_type.h:126
RUBY_T_STRING
@ RUBY_T_STRING
Definition: value_type.h:117
RUBY_T_HASH
@ RUBY_T_HASH
Definition: value_type.h:120
RUBY_T_NIL
@ RUBY_T_NIL
Definition: value_type.h:129
RUBY_T_CLASS
@ RUBY_T_CLASS
Definition: value_type.h:114
RUBY_T_ARRAY
@ RUBY_T_ARRAY
Definition: value_type.h:119
RUBY_T_MASK
@ RUBY_T_MASK
Definition: value_type.h:142
RUBY_T_RATIONAL
@ RUBY_T_RATIONAL
Definition: value_type.h:127
RUBY_T_ZOMBIE
@ RUBY_T_ZOMBIE
Definition: value_type.h:139
RUBY_T_BIGNUM
@ RUBY_T_BIGNUM
Definition: value_type.h:122
RUBY_T_TRUE
@ RUBY_T_TRUE
Definition: value_type.h:130
RUBY_T_FLOAT
@ RUBY_T_FLOAT
Definition: value_type.h:116
RUBY_T_STRUCT
@ RUBY_T_STRUCT
Definition: value_type.h:121
RUBY_T_NONE
@ RUBY_T_NONE
Non-object (sweeped etc.)
Definition: value_type.h:111
RUBY_T_REGEXP
@ RUBY_T_REGEXP
Definition: value_type.h:118
RUBY_T_FILE
@ RUBY_T_FILE
Definition: value_type.h:123