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

Ruby 3.2.5p208 (2024-07-26 revision 31d0f1a2e7dbfb60731d1f05b868e1d578cda493)

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
46#ifndef USE_TRANSIENT_HEAP
47# define USE_TRANSIENT_HEAP 1
48#endif
49
56#define RARRAY(obj) RBIMPL_CAST((struct RArray *)(obj))
58#define RARRAY_EMBED_FLAG RARRAY_EMBED_FLAG
59#define RARRAY_EMBED_LEN_MASK RARRAY_EMBED_LEN_MASK
60#define RARRAY_EMBED_LEN_MAX RARRAY_EMBED_LEN_MAX
61#define RARRAY_EMBED_LEN_SHIFT RARRAY_EMBED_LEN_SHIFT
62#if USE_TRANSIENT_HEAP
63# define RARRAY_TRANSIENT_FLAG RARRAY_TRANSIENT_FLAG
64#else
65# define RARRAY_TRANSIENT_FLAG 0
66#endif
68#define RARRAY_LEN rb_array_len
69#define RARRAY_CONST_PTR rb_array_const_ptr
70#define RARRAY_CONST_PTR_TRANSIENT rb_array_const_ptr_transient
73#if defined(__fcc__) || defined(__fcc_version) || \
74 defined(__FCC__) || defined(__FCC_VERSION)
75/* workaround for old version of Fujitsu C Compiler (fcc) */
76# define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x))
77#else
78# define FIX_CONST_VALUE_PTR(x) (x)
79#endif
80
81#define RARRAY_EMBED_LEN RARRAY_EMBED_LEN
82#define RARRAY_LENINT RARRAY_LENINT
83#define RARRAY_TRANSIENT_P RARRAY_TRANSIENT_P
84#define RARRAY_ASET RARRAY_ASET
85#define RARRAY_PTR RARRAY_PTR
101enum ruby_rarray_flags {
119 RARRAY_EMBED_FLAG = RUBY_FL_USER1,
120
121 /* RUBY_FL_USER2 is for ELTS_SHARED */
122
133#if USE_RVARGC
134 RARRAY_EMBED_LEN_MASK = RUBY_FL_USER9 | RUBY_FL_USER8 | RUBY_FL_USER7 | RUBY_FL_USER6 |
135 RUBY_FL_USER5 | RUBY_FL_USER4 | RUBY_FL_USER3
136#else
137 RARRAY_EMBED_LEN_MASK = RUBY_FL_USER4 | RUBY_FL_USER3
138#endif
139
140#if USE_TRANSIENT_HEAP
141 ,
142
155 RARRAY_TRANSIENT_FLAG = RUBY_FL_USER13
156#endif
157};
158
163 enum ruby_rarray_consts {
165 RARRAY_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 3
166
167#if !USE_RVARGC
168 ,
169
171 RARRAY_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE)
172#endif
173};
174
176 struct RArray {
177
179 struct RBasic basic;
180
182 union {
183
188 struct {
189
191 long len;
192
194 union {
195
201 long capa;
202
209#if defined(__clang__) /* <- clang++ is sane */ || \
210 !defined(__cplusplus) /* <- C99 is sane */ || \
211 (__cplusplus > 199711L) /* <- C++11 is sane */
212 const
213#endif
214 VALUE shared_root;
215 } aux;
216
223 const VALUE *ptr;
224 } heap;
225
231#if USE_RVARGC
232 /* This is a length 1 array because:
233 * 1. GCC has a bug that does not optimize C flexible array members
234 * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
235 * 2. Zero length arrays are not supported by all compilers
236 */
237 const VALUE ary[1];
238#else
239 const VALUE ary[RARRAY_EMBED_LEN_MAX];
240#endif
241 } as;
242};
243
244 RBIMPL_SYMBOL_EXPORT_BEGIN()
254 VALUE *rb_ary_ptr_use_start(VALUE ary);
255
265void rb_ary_ptr_use_end(VALUE a);
266
267#if USE_TRANSIENT_HEAP
275void rb_ary_detransient(VALUE a);
276#endif
277 RBIMPL_SYMBOL_EXPORT_END()
278
279 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
280 RBIMPL_ATTR_ARTIFICIAL()
296static inline long
297RARRAY_EMBED_LEN(VALUE ary)
298{
299 RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
300 RBIMPL_ASSERT_OR_ASSUME(RB_FL_ANY_RAW(ary, RARRAY_EMBED_FLAG));
301
302 VALUE f = RBASIC(ary)->flags;
303 f &= RARRAY_EMBED_LEN_MASK;
304 f >>= RARRAY_EMBED_LEN_SHIFT;
305 return RBIMPL_CAST((long)f);
306}
307
308 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
316static inline long
317rb_array_len(VALUE a)
318{
319 RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
320
321 if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) {
322 return RARRAY_EMBED_LEN(a);
323 }
324 else {
325 return RARRAY(a)->as.heap.len;
326 }
327}
328
329 RBIMPL_ATTR_ARTIFICIAL()
342static inline int
343RARRAY_LENINT(VALUE ary)
344{
345 return rb_long2int(RARRAY_LEN(ary));
346}
347
348 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
349 RBIMPL_ATTR_ARTIFICIAL()
363static inline bool
364RARRAY_TRANSIENT_P(VALUE ary)
365{
366 RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
367
368#if USE_TRANSIENT_HEAP
369 return RB_FL_ANY_RAW(ary, RARRAY_TRANSIENT_FLAG);
370#else
371 return false;
372#endif
373}
374
375 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
385static inline const VALUE *
386rb_array_const_ptr_transient(VALUE a)
387{
388 RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
389
390 if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) {
391 return FIX_CONST_VALUE_PTR(RARRAY(a)->as.ary);
392 }
393 else {
394 return FIX_CONST_VALUE_PTR(RARRAY(a)->as.heap.ptr);
395 }
396}
397
398#if ! USE_TRANSIENT_HEAP
399 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
400#endif
411static inline const VALUE *
412rb_array_const_ptr(VALUE a)
413{
414 RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
415
416#if USE_TRANSIENT_HEAP
417 if (RARRAY_TRANSIENT_P(a)) {
418 rb_ary_detransient(a);
419 }
420#endif
421 return rb_array_const_ptr_transient(a);
422}
423
435static inline VALUE *
436rb_array_ptr_use_start(VALUE a,
437 RBIMPL_ATTR_MAYBE_UNUSED()
438 int allow_transient)
439{
440 RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
441
442#if USE_TRANSIENT_HEAP
443 if (!allow_transient) {
444 if (RARRAY_TRANSIENT_P(a)) {
445 rb_ary_detransient(a);
446 }
447 }
448#endif
449
450 return rb_ary_ptr_use_start(a);
451}
452
462static inline void
463rb_array_ptr_use_end(VALUE a,
464 RBIMPL_ATTR_MAYBE_UNUSED()
465 int allow_transient)
466{
467 RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
468 rb_ary_ptr_use_end(a);
469}
470
477#define RBIMPL_RARRAY_STMT(flag, ary, var, expr) do { \
478 RBIMPL_ASSERT_TYPE((ary), RUBY_T_ARRAY); \
479 const VALUE rbimpl_ary = (ary); \
480 VALUE *var = rb_array_ptr_use_start(rbimpl_ary, (flag)); \
481 expr; \
482 rb_array_ptr_use_end(rbimpl_ary, (flag)); \
483} while (0)
484
491#define RARRAY_PTR_USE_END(a) rb_array_ptr_use_end(a, 0)
492
518#define RARRAY_PTR_USE(ary, ptr_name, expr) \
519 RBIMPL_RARRAY_STMT(0, ary, ptr_name, expr)
520
528#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr) \
529 RBIMPL_RARRAY_STMT(1, ary, ptr_name, expr)
530
545static inline VALUE *
546RARRAY_PTR(VALUE ary)
547{
548 RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
549
550 VALUE tmp = RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary);
551 return RBIMPL_CAST((VALUE *)RARRAY_CONST_PTR(tmp));
552}
553
565static inline void
566RARRAY_ASET(VALUE ary, long i, VALUE v)
567{
568 RARRAY_PTR_USE_TRANSIENT(ary, ptr,
569 RB_OBJ_WRITE(ary, &ptr[i], v));
570}
571
583#define RARRAY_AREF(a, i) RARRAY_CONST_PTR_TRANSIENT(a)[i]
584
585#endif /* RBIMPL_RARRAY_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
constexpr.h
RBIMPL_ATTR_CONSTEXPR.
dllexport.h
Tweaking visibility of C variables/functions.
RBIMPL_SYMBOL_EXPORT_END
#define RBIMPL_SYMBOL_EXPORT_END()
Counterpart of RBIMPL_SYMBOL_EXPORT_BEGIN.
Definition dllexport.h:106
RBIMPL_SYMBOL_EXPORT_BEGIN
#define RBIMPL_SYMBOL_EXPORT_BEGIN()
Shortcut macro equivalent to RUBY_SYMBOL_EXPORT_BEGIN extern "C" {.
Definition dllexport.h:97
fl_type.h
Defines enum ruby_fl_type.
RUBY_FL_USHIFT
@ RUBY_FL_USHIFT
Number of bits in ruby_fl_type that are not open to users.
Definition fl_type.h:167
RB_FL_ANY_RAW
static bool RB_FL_ANY_RAW(VALUE obj, VALUE flags)
This is an implenentation detail of RB_FL_ANY().
Definition fl_type.h:550
RUBY_FL_USER9
@ RUBY_FL_USER9
User-defined flag.
Definition fl_type.h:369
RUBY_FL_USER8
@ RUBY_FL_USER8
User-defined flag.
Definition fl_type.h:368
RUBY_FL_USER5
@ RUBY_FL_USER5
User-defined flag.
Definition fl_type.h:365
RUBY_FL_USER3
@ RUBY_FL_USER3
User-defined flag.
Definition fl_type.h:363
RUBY_FL_USER7
@ RUBY_FL_USER7
User-defined flag.
Definition fl_type.h:367
RUBY_FL_USER6
@ RUBY_FL_USER6
User-defined flag.
Definition fl_type.h:366
RUBY_FL_USER4
@ RUBY_FL_USER4
User-defined flag.
Definition fl_type.h:364
RUBY_FL_USER1
@ RUBY_FL_USER1
User-defined flag.
Definition fl_type.h:361
RUBY_FL_USER13
@ RUBY_FL_USER13
User-defined flag.
Definition fl_type.h:373
RB_OBJ_WRITE
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition rgengc.h:220
long.h
Arithmetic conversion between C's long and Ruby's.
rb_long2int
#define rb_long2int
Just another name of rb_long2int_inline.
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 if and only if.
Definition pure.h:38
RARRAY_LEN
#define RARRAY_LEN
Just another name of rb_array_len.
Definition rarray.h:68
RARRAY_EMBED_LEN
static long RARRAY_EMBED_LEN(VALUE ary)
Queries the length of the array.
Definition rarray.h:297
rb_array_len
static long rb_array_len(VALUE a)
Queries the length of the array.
Definition rarray.h:317
RARRAY
#define RARRAY(obj)
Convenient casting macro.
Definition rarray.h:56
RARRAY_TRANSIENT_P
static bool RARRAY_TRANSIENT_P(VALUE ary)
Queries if the array is a transient array.
Definition rarray.h:364
RARRAY_LENINT
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
Definition rarray.h:343
RARRAY_ASET
static void RARRAY_ASET(VALUE ary, long i, VALUE v)
Assigns an object in an array.
Definition rarray.h:566
RARRAY_PTR
static VALUE * RARRAY_PTR(VALUE ary)
Wild use of a C pointer.
Definition rarray.h:546
ruby_rarray_consts
ruby_rarray_consts
This is an enum because GDB wants it (rather than a macro).
Definition rarray.h:163
RARRAY_EMBED_LEN_MAX
@ RARRAY_EMBED_LEN_MAX
Max possible number elements that can be embedded.
Definition rarray.h:171
RARRAY_EMBED_LEN_SHIFT
@ RARRAY_EMBED_LEN_SHIFT
Where RARRAY_EMBED_LEN_MASK resides.
Definition rarray.h:165
RARRAY_PTR_USE_TRANSIENT
#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr)
Identical to RARRAY_PTR_USE, except the pointer can be a transient one.
Definition rarray.h:528
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
Definition rarray.h:69
rbasic.h
Defines struct RBasic.
RBASIC
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
rgengc.h
RGENGC write-barrier APIs.
RB_OBJ_WB_UNPROTECT_FOR
#define RB_OBJ_WB_UNPROTECT_FOR(type, obj)
Identical to RB_OBJ_WB_UNPROTECT(), except it can also assert that the given object is of given type.
Definition rgengc.h:260
stdbool.h
C99 shim for <stdbool.h>
RArray
Ruby's array.
Definition rarray.h:176
RArray::basic
struct RBasic basic
Basic part, including flags and class.
Definition rarray.h:179
RArray::as
union RArray::@44 as
Array's specific fields.
RArray::shared_root
const VALUE shared_root
Parent of the array.
Definition rarray.h:214
RArray::capa
long capa
Capacity of *ptr.
Definition rarray.h:201
RArray::len
long len
Number of elements of the array.
Definition rarray.h:191
RArray::ptr
const VALUE * ptr
Pointer to the C array that holds the elements of the array.
Definition rarray.h:223
RBasic
Ruby's object's, base components.
Definition rbasic.h:64
value.h
Defines VALUE and ID.
VALUE
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
value_type.h
Defines enum ruby_value_type.
RUBY_T_ARRAY
@ RUBY_T_ARRAY
Definition value_type.h:121