Ruby: include/ruby/internal/core/rarray.h Source File

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

rarray.h
Go to the documentation of this file.
1#ifndef RBIMPL_RARRAY_H /*-*-C++-*-vi:se ft=cpp:*/
2#define RBIMPL_RARRAY_H
23#include "ruby/internal/arithmetic/long.h"
24#include "ruby/internal/attr/artificial.h"
25#include "ruby/internal/attr/constexpr.h"
26#include "ruby/internal/attr/maybe_unused.h"
27#include "ruby/internal/attr/pure.h"
28#include "ruby/internal/cast.h"
29#include "ruby/internal/core/rbasic.h"
30#include "ruby/internal/dllexport.h"
31#include "ruby/internal/fl_type.h"
32#include "ruby/internal/rgengc.h"
33#include "ruby/internal/stdbool.h"
34#include "ruby/internal/value.h"
35#include "ruby/internal/value_type.h"
36#include "ruby/assert.h"
37
38#ifndef USE_TRANSIENT_HEAP
39# define USE_TRANSIENT_HEAP 1
40#endif
41
42#define RARRAY(obj) RBIMPL_CAST((struct RArray *)(obj))
43#define RARRAY_EMBED_FLAG RARRAY_EMBED_FLAG
44#define RARRAY_EMBED_LEN_MASK RARRAY_EMBED_LEN_MASK
45#define RARRAY_EMBED_LEN_MAX RARRAY_EMBED_LEN_MAX
46#define RARRAY_EMBED_LEN_SHIFT RARRAY_EMBED_LEN_SHIFT
47#if USE_TRANSIENT_HEAP
48# define RARRAY_TRANSIENT_FLAG RARRAY_TRANSIENT_FLAG
49#else
50# define RARRAY_TRANSIENT_FLAG 0
51#endif
52#define RARRAY_LEN rb_array_len
53#define RARRAY_CONST_PTR rb_array_const_ptr
54#define RARRAY_CONST_PTR_TRANSIENT rb_array_const_ptr_transient
55
57#if defined(__fcc__) || defined(__fcc_version) || \
58 defined(__FCC__) || defined(__FCC_VERSION)
59/* workaround for old version of Fujitsu C Compiler (fcc) */
60# define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x))
61#else
62# define FIX_CONST_VALUE_PTR(x) (x)
63#endif
64
65#define RARRAY_EMBED_LEN RARRAY_EMBED_LEN
66#define RARRAY_LENINT RARRAY_LENINT
67#define RARRAY_TRANSIENT_P RARRAY_TRANSIENT_P
68#define RARRAY_ASET RARRAY_ASET
69#define RARRAY_PTR RARRAY_PTR
72 enum ruby_rarray_flags {
73 RARRAY_EMBED_FLAG = RUBY_FL_USER1,
74 /* RUBY_FL_USER2 is for ELTS_SHARED */
75 RARRAY_EMBED_LEN_MASK = RUBY_FL_USER4 | RUBY_FL_USER3
76#if USE_TRANSIENT_HEAP
77 ,
78 RARRAY_TRANSIENT_FLAG = RUBY_FL_USER13
79#endif
80};
81
82 enum ruby_rarray_consts {
83 RARRAY_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 3,
84 RARRAY_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE)
85};
86
87 struct RArray {
88 struct RBasic basic;
89 union {
90 struct {
91 long len;
92 union {
93 long capa;
94#if defined(__clang__) /* <- clang++ is sane */ || \
95 !defined(__cplusplus) /* <- C99 is sane */ || \
96 (__cplusplus > 199711L) /* <- C++11 is sane */
97 const
98#endif
99 VALUE shared_root;
100 } aux;
101 const VALUE *ptr;
102 } heap;
103 const VALUE ary[RARRAY_EMBED_LEN_MAX];
104 } as;
105};
106
107 RBIMPL_SYMBOL_EXPORT_BEGIN()
108 VALUE *rb_ary_ptr_use_start(VALUE ary);
109void rb_ary_ptr_use_end(VALUE a);
110#if USE_TRANSIENT_HEAP
111void rb_ary_detransient(VALUE a);
112#endif
113 RBIMPL_SYMBOL_EXPORT_END()
114
115 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
116 RBIMPL_ATTR_ARTIFICIAL()
117static inline long
118RARRAY_EMBED_LEN(VALUE ary)
119{
120 RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
121 RBIMPL_ASSERT_OR_ASSUME(RB_FL_ANY_RAW(ary, RARRAY_EMBED_FLAG));
122
123 VALUE f = RBASIC(ary)->flags;
124 f &= RARRAY_EMBED_LEN_MASK;
125 f >>= RARRAY_EMBED_LEN_SHIFT;
126 return RBIMPL_CAST((long)f);
127}
128
129 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
130static inline long
131rb_array_len(VALUE a)
132{
133 RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
134
135 if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) {
136 return RARRAY_EMBED_LEN(a);
137 }
138 else {
139 return RARRAY(a)->as.heap.len;
140 }
141}
142
143 RBIMPL_ATTR_ARTIFICIAL()
144static inline int
145RARRAY_LENINT(VALUE ary)
146{
147 return rb_long2int(RARRAY_LEN(ary));
148}
149
150 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
151 RBIMPL_ATTR_ARTIFICIAL()
152static inline bool
153RARRAY_TRANSIENT_P(VALUE ary)
154{
155 RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
156
157#if USE_TRANSIENT_HEAP
158 return RB_FL_ANY_RAW(ary, RARRAY_TRANSIENT_FLAG);
159#else
160 return false;
161#endif
162}
163
164 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
165/* internal function. do not use this function */
166static inline const VALUE *
167rb_array_const_ptr_transient(VALUE a)
168{
169 RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
170
171 if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) {
172 return FIX_CONST_VALUE_PTR(RARRAY(a)->as.ary);
173 }
174 else {
175 return FIX_CONST_VALUE_PTR(RARRAY(a)->as.heap.ptr);
176 }
177}
178
179#if ! USE_TRANSIENT_HEAP
180 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
181#endif
182/* internal function. do not use this function */
183static inline const VALUE *
184rb_array_const_ptr(VALUE a)
185{
186 RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
187
188#if USE_TRANSIENT_HEAP
189 if (RARRAY_TRANSIENT_P(a)) {
190 rb_ary_detransient(a);
191 }
192#endif
193 return rb_array_const_ptr_transient(a);
194}
195
196/* internal function. do not use this function */
197static inline VALUE *
198rb_array_ptr_use_start(VALUE a,
199 RBIMPL_ATTR_MAYBE_UNUSED()
200 int allow_transient)
201{
202 RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
203
204#if USE_TRANSIENT_HEAP
205 if (!allow_transient) {
206 if (RARRAY_TRANSIENT_P(a)) {
207 rb_ary_detransient(a);
208 }
209 }
210#endif
211
212 return rb_ary_ptr_use_start(a);
213}
214
215/* internal function. do not use this function */
216static inline void
217rb_array_ptr_use_end(VALUE a,
218 RBIMPL_ATTR_MAYBE_UNUSED()
219 int allow_transient)
220{
221 RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
222 rb_ary_ptr_use_end(a);
223}
224
225#define RBIMPL_RARRAY_STMT(flag, ary, var, expr) do { \
226 RBIMPL_ASSERT_TYPE((ary), RUBY_T_ARRAY); \
227 const VALUE rbimpl_ary = (ary); \
228 VALUE *var = rb_array_ptr_use_start(rbimpl_ary, (flag)); \
229 expr; \
230 rb_array_ptr_use_end(rbimpl_ary, (flag)); \
231} while (0)
232
233#define RARRAY_PTR_USE_START(a) rb_array_ptr_use_start(a, 0)
234#define RARRAY_PTR_USE_END(a) rb_array_ptr_use_end(a, 0)
235#define RARRAY_PTR_USE(ary, ptr_name, expr) \
236 RBIMPL_RARRAY_STMT(0, ary, ptr_name, expr)
237
238#define RARRAY_PTR_USE_START_TRANSIENT(a) rb_array_ptr_use_start(a, 1)
239#define RARRAY_PTR_USE_END_TRANSIENT(a) rb_array_ptr_use_end(a, 1)
240#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr) \
241 RBIMPL_RARRAY_STMT(1, ary, ptr_name, expr)
242
243static inline VALUE *
244RARRAY_PTR(VALUE ary)
245{
246 RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
247
248 VALUE tmp = RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary);
249 return RBIMPL_CAST((VALUE *)RARRAY_CONST_PTR(tmp));
250}
251
252static inline void
253RARRAY_ASET(VALUE ary, long i, VALUE v)
254{
255 RARRAY_PTR_USE_TRANSIENT(ary, ptr,
256 RB_OBJ_WRITE(ary, &ptr[i], v));
257}
258
259/*
260 * :FIXME: we want to convert RARRAY_AREF into an inline function (to add rooms
261 * for more sanity checks). However there were situations where the address of
262 * this macro is taken i.e. &RARRAY_AREF(...). They cannot be possible if this
263 * is not a macro. Such usages are abuse, and we eliminated them internally.
264 * However we are afraid of similar things to remain in the wild. This macro
265 * remains as it is due to that. If we could warn such usages we can set a
266 * transition path, but currently no way is found to do so.
267 */
268#define RARRAY_AREF(a, i) RARRAY_CONST_PTR_TRANSIENT(a)[i]
269
270#endif /* RBIMPL_RARRAY_H */
rb_ary_detransient
void rb_ary_detransient(VALUE ary)
Definition: array.c:432
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
FIX_CONST_VALUE_PTR
#define FIX_CONST_VALUE_PTR(x)
Definition: bigdecimal.h:116
cast.h
Defines RBIMPL_CAST.
constexpr.h
RBIMPL_ATTR_CONSTEXPR.
ptr
struct RIMemo * ptr
Definition: debug.c:88
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
fl_type.h
Defines enum ruby_fl_type.
RUBY_FL_USHIFT
@ RUBY_FL_USHIFT
Definition: fl_type.h:150
long.h
Arithmetic conversion between C's long and Ruby's.
rb_long2int
#define rb_long2int
Definition: long.h:62
maybe_unused.h
Defines RBIMPL_ATTR_MAYBE_UNUSED.
RBIMPL_ATTR_MAYBE_UNUSED
#define RBIMPL_ATTR_MAYBE_UNUSED()
Wraps (or simulates) [[maybe_unused]]
Definition: maybe_unused.h:35
pure.h
Defines RBIMPL_ATTR_PURE.
RBIMPL_ATTR_PURE_UNLESS_DEBUG
#define RBIMPL_ATTR_PURE_UNLESS_DEBUG()
Enables RBIMPL_ATTR_PURE iff.
Definition: pure.h:38
RARRAY_EMBED_FLAG
#define RARRAY_EMBED_FLAG
Definition: rarray.h:43
RARRAY_TRANSIENT_FLAG
#define RARRAY_TRANSIENT_FLAG
Definition: rarray.h:50
RARRAY_LEN
#define RARRAY_LEN
Definition: rarray.h:52
RARRAY
#define RARRAY(obj)
Definition: rarray.h:42
rb_ary_ptr_use_end
void rb_ary_ptr_use_end(VALUE a)
Definition: array.c:252
rb_ary_ptr_use_start
VALUE * rb_ary_ptr_use_start(VALUE ary)
Definition: array.c:243
ruby_rarray_flags
ruby_rarray_flags
Definition: rarray.h:72
RARRAY_EMBED_LEN_SHIFT
#define RARRAY_EMBED_LEN_SHIFT
Definition: rarray.h:46
RARRAY_EMBED_LEN_MAX
#define RARRAY_EMBED_LEN_MAX
Definition: rarray.h:45
ruby_rarray_consts
ruby_rarray_consts
Definition: rarray.h:82
RARRAY_EMBED_LEN_MASK
#define RARRAY_EMBED_LEN_MASK
Definition: rarray.h:44
RARRAY_PTR_USE_TRANSIENT
#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr)
Definition: rarray.h:240
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR
Definition: rarray.h:53
rbasic.h
Defines struct RBasic.
RBASIC
#define RBASIC(obj)
Definition: rbasic.h:34
rgengc.h
RGENGC write-barrier APIs.
RB_OBJ_WRITE
#define RB_OBJ_WRITE(a, slot, b)
WB for new reference from ‘a’ to ‘b’.
Definition: rgengc.h:107
RB_OBJ_WB_UNPROTECT_FOR
#define RB_OBJ_WB_UNPROTECT_FOR(type, obj)
Definition: rgengc.h:123
f
#define f
stdbool.h
C99 shim for <stdbool.h>
const
#define const
Definition: strftime.c:108
RArray
Definition: rarray.h:87
RArray::basic
struct RBasic basic
Definition: rarray.h:88
RArray::shared_root
const VALUE shared_root
Definition: rarray.h:99
RArray::capa
long capa
Definition: rarray.h:93
RArray::len
long len
Definition: rarray.h:91
RArray::as
union RArray::@95 as
RArray::ptr
const VALUE * ptr
Definition: rarray.h:101
RBasic
Definition: rbasic.h:47
value.h
Defines VALUE and ID.
VALUE
unsigned long VALUE
Definition: value.h:38
value_type.h
Defines enum ruby_value_type.
RUBY_T_ARRAY
@ RUBY_T_ARRAY
Definition: value_type.h:119