summaryrefslogtreecommitdiff
path: root/include/ruby/internal/core/rbasic.h
blob: a1477e260073b3e60131186857faf5e3111d929b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#ifndef RBIMPL_RBASIC_H                              /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RBASIC_H
/**
 * @file
 * @author     Ruby developers <ruby-core@ruby-lang.org>
 * @copyright  This  file  is   a  part  of  the   programming  language  Ruby.
 *             Permission  is hereby  granted,  to  either redistribute  and/or
 *             modify this file, provided that  the conditions mentioned in the
 *             file COPYING are met.  Consult the file for details.
 * @warning    Symbols   prefixed  with   either  `RBIMPL`   or  `rbimpl`   are
 *             implementation details.   Don't take  them as canon.  They could
 *             rapidly appear then vanish.  The name (path) of this header file
 *             is also an  implementation detail.  Do not expect  it to persist
 *             at the place it is now.  Developers are free to move it anywhere
 *             anytime at will.
 * @note       To  ruby-core:  remember  that   this  header  can  be  possibly
 *             recursively included  from extension  libraries written  in C++.
 *             Do not  expect for  instance `__VA_ARGS__` is  always available.
 *             We assume C99  for ruby itself but we don't  assume languages of
 *             extension libraries.  They could be written in C++98.
 * @brief      Defines struct ::RBasic.
 */
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/attr/constexpr.h"
#include "ruby/internal/attr/forceinline.h"
#include "ruby/internal/attr/noalias.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/special_consts.h"
#include "ruby/internal/value.h"
#include "ruby/assert.h"

/**
 * Convenient casting macro.
 *
 * @param   obj  Arbitrary Ruby object.
 * @return  The passed object casted to ::RBasic.
 */
#define RBASIC(obj)                 RBIMPL_CAST((struct RBasic *)(obj))
/** @cond INTERNAL_MACRO */
#define RBASIC_CLASS                RBASIC_CLASS
#define RBIMPL_RVALUE_EMBED_LEN_MAX 3
#define RVALUE_EMBED_LEN_MAX        RVALUE_EMBED_LEN_MAX
#define RBIMPL_EMBED_LEN_MAX_OF(T) \
    RBIMPL_CAST((int)(sizeof(VALUE[RBIMPL_RVALUE_EMBED_LEN_MAX]) / (sizeof(T))))
/** @endcond */

/**
 * This is an enum because GDB wants it (rather than a macro).  People need not
 * bother.
 */
enum ruby_rvalue_flags {
    /** Max possible number of objects that can be embedded. */
    RVALUE_EMBED_LEN_MAX = RBIMPL_RVALUE_EMBED_LEN_MAX
};

/**
 * Ruby object's base components. All Ruby objects have them in common.
 */
struct
RUBY_ALIGNAS(SIZEOF_VALUE)
RBasic {

    /**
     * Per-object flags.   Each Ruby object  has its own  characteristics apart
     * from its class.  For instance, whether an object is frozen or not is not
     * controlled by its class.  This is where such properties are stored.
     *
     * @see enum ::ruby_fl_type
     *
     * @note  This is ::VALUE rather than  an enum for alignment purposes.  Back
     *        in the 1990s there were no such thing like `_Alignas` in C.
     */
    VALUE flags;

    /**
     * Class of an object.  Every object has its class.  Also, everything is an
     * object  in Ruby.   This means  classes are  also objects.   Classes have
     * their own classes,  classes  of classes have their classes too,  and  it
     * recursively continues forever.
     *
     * Also note the `const` qualifier.  In Ruby, an object cannot "change" its
     * class.
     */
    const VALUE klass;

#ifdef __cplusplus
  public:
    RBIMPL_ATTR_CONSTEXPR(CXX11)
    RBIMPL_ATTR_ARTIFICIAL()
    RBIMPL_ATTR_FORCEINLINE()
    RBIMPL_ATTR_NOALIAS()
    /**
     * We need to define this explicit constructor because the field `klass` is
     * const-qualified above,  which effectively  defines the  implicit default
     * constructor as "deleted"  (as of C++11) --  No way but to  define one by
     * ourselves.
     */
    RBasic() :
        flags(RBIMPL_VALUE_NULL),
        klass(RBIMPL_VALUE_NULL)
    {
    }
#endif
};

RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
 * Make the object invisible from Ruby code.
 *
 * It is  useful to let  Ruby's GC manage your  internal data structure  -- The
 * object keeps being managed by GC, but `ObjectSpace.each_object` never yields
 * the object.
 *
 * Note that the object also lose a way to call a method on it.
 *
 * @param[out]  obj  A Ruby object.
 * @return      The passed object.
 * @post        The object is destructively modified to be invisible.
 * @see         rb_obj_reveal
 */
VALUE rb_obj_hide(VALUE obj);

/**
 * Make a hidden object visible again.
 *
 * It is  the caller's  responsibility to  pass the  right `klass`  which `obj`
 * originally used to belong to.
 *
 * @param[out]  obj    A Ruby object.
 * @param[in]   klass  Class of `obj`.
 * @return      Passed `obj`.
 * @pre         `obj` was previously hidden.
 * @post        `obj`'s class is `klass`.
 * @see         rb_obj_hide
 */
VALUE rb_obj_reveal(VALUE obj, VALUE klass); /* do not use this API to change klass information */
RBIMPL_SYMBOL_EXPORT_END()

RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
 * Queries the class of an object.
 *
 * @param[in]  obj  An object.
 * @return     Its class.
 */
static inline VALUE
RBASIC_CLASS(VALUE obj)
{
    RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj));
    return RBASIC(obj)->klass;
}

#endif /* RBIMPL_RBASIC_H */