diff options
Diffstat (limited to 'include/ruby/internal/fl_type.h')
-rw-r--r-- | include/ruby/internal/fl_type.h | 667 |
1 files changed, 547 insertions, 120 deletions
diff --git a/include/ruby/internal/fl_type.h b/include/ruby/internal/fl_type.h index 1d570c4743..0a05166784 100644 --- a/include/ruby/internal/fl_type.h +++ b/include/ruby/internal/fl_type.h @@ -17,7 +17,7 @@ * 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. + * extension libraries. They could be written in C++98. * @brief Defines enum ::ruby_fl_type. */ #include "ruby/internal/config.h" /* for ENUM_OVER_INT */ @@ -55,46 +55,45 @@ #endif /** @endcond */ -#define FL_SINGLETON RBIMPL_CAST((VALUE)RUBY_FL_SINGLETON) -#define FL_WB_PROTECTED RBIMPL_CAST((VALUE)RUBY_FL_WB_PROTECTED) -#define FL_PROMOTED0 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED0) -#define FL_PROMOTED1 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED1) -#define FL_FINALIZE RBIMPL_CAST((VALUE)RUBY_FL_FINALIZE) -#define FL_TAINT RBIMPL_CAST((VALUE)RUBY_FL_TAINT) -#define FL_SHAREABLE RBIMPL_CAST((VALUE)RUBY_FL_SHAREABLE) -#define FL_UNTRUSTED RBIMPL_CAST((VALUE)RUBY_FL_UNTRUSTED) -#define FL_SEEN_OBJ_ID RBIMPL_CAST((VALUE)RUBY_FL_SEEN_OBJ_ID) -#define FL_EXIVAR RBIMPL_CAST((VALUE)RUBY_FL_EXIVAR) -#define FL_FREEZE RBIMPL_CAST((VALUE)RUBY_FL_FREEZE) - -#define FL_USHIFT RBIMPL_CAST((VALUE)RUBY_FL_USHIFT) - -#define FL_USER0 RBIMPL_CAST((VALUE)RUBY_FL_USER0) -#define FL_USER1 RBIMPL_CAST((VALUE)RUBY_FL_USER1) -#define FL_USER2 RBIMPL_CAST((VALUE)RUBY_FL_USER2) -#define FL_USER3 RBIMPL_CAST((VALUE)RUBY_FL_USER3) -#define FL_USER4 RBIMPL_CAST((VALUE)RUBY_FL_USER4) -#define FL_USER5 RBIMPL_CAST((VALUE)RUBY_FL_USER5) -#define FL_USER6 RBIMPL_CAST((VALUE)RUBY_FL_USER6) -#define FL_USER7 RBIMPL_CAST((VALUE)RUBY_FL_USER7) -#define FL_USER8 RBIMPL_CAST((VALUE)RUBY_FL_USER8) -#define FL_USER9 RBIMPL_CAST((VALUE)RUBY_FL_USER9) -#define FL_USER10 RBIMPL_CAST((VALUE)RUBY_FL_USER10) -#define FL_USER11 RBIMPL_CAST((VALUE)RUBY_FL_USER11) -#define FL_USER12 RBIMPL_CAST((VALUE)RUBY_FL_USER12) -#define FL_USER13 RBIMPL_CAST((VALUE)RUBY_FL_USER13) -#define FL_USER14 RBIMPL_CAST((VALUE)RUBY_FL_USER14) -#define FL_USER15 RBIMPL_CAST((VALUE)RUBY_FL_USER15) -#define FL_USER16 RBIMPL_CAST((VALUE)RUBY_FL_USER16) -#define FL_USER17 RBIMPL_CAST((VALUE)RUBY_FL_USER17) -#define FL_USER18 RBIMPL_CAST((VALUE)RUBY_FL_USER18) -#define FL_USER19 RBIMPL_CAST((VALUE)(unsigned int)RUBY_FL_USER19) - -#define ELTS_SHARED RUBY_ELTS_SHARED -#define RUBY_ELTS_SHARED RUBY_ELTS_SHARED -#define RB_OBJ_FREEZE rb_obj_freeze_inline +#define FL_SINGLETON RBIMPL_CAST((VALUE)RUBY_FL_SINGLETON) /**< @old{RUBY_FL_SINGLETON} */ +#define FL_WB_PROTECTED RBIMPL_CAST((VALUE)RUBY_FL_WB_PROTECTED) /**< @old{RUBY_FL_WB_PROTECTED} */ +#define FL_PROMOTED RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED) /**< @old{RUBY_FL_PROMOTED} */ +#define FL_FINALIZE RBIMPL_CAST((VALUE)RUBY_FL_FINALIZE) /**< @old{RUBY_FL_FINALIZE} */ +#define FL_TAINT RBIMPL_CAST((VALUE)RUBY_FL_TAINT) /**< @old{RUBY_FL_TAINT} */ +#define FL_SHAREABLE RBIMPL_CAST((VALUE)RUBY_FL_SHAREABLE) /**< @old{RUBY_FL_SHAREABLE} */ +#define FL_UNTRUSTED RBIMPL_CAST((VALUE)RUBY_FL_UNTRUSTED) /**< @old{RUBY_FL_UNTRUSTED} */ +#define FL_SEEN_OBJ_ID RBIMPL_CAST((VALUE)RUBY_FL_SEEN_OBJ_ID) /**< @old{RUBY_FL_SEEN_OBJ_ID} */ +#define FL_EXIVAR RBIMPL_CAST((VALUE)RUBY_FL_EXIVAR) /**< @old{RUBY_FL_EXIVAR} */ +#define FL_FREEZE RBIMPL_CAST((VALUE)RUBY_FL_FREEZE) /**< @old{RUBY_FL_FREEZE} */ + +#define FL_USHIFT RBIMPL_CAST((VALUE)RUBY_FL_USHIFT) /**< @old{RUBY_FL_USHIFT} */ + +#define FL_USER0 RBIMPL_CAST((VALUE)RUBY_FL_USER0) /**< @old{RUBY_FL_USER0} */ +#define FL_USER1 RBIMPL_CAST((VALUE)RUBY_FL_USER1) /**< @old{RUBY_FL_USER1} */ +#define FL_USER2 RBIMPL_CAST((VALUE)RUBY_FL_USER2) /**< @old{RUBY_FL_USER2} */ +#define FL_USER3 RBIMPL_CAST((VALUE)RUBY_FL_USER3) /**< @old{RUBY_FL_USER3} */ +#define FL_USER4 RBIMPL_CAST((VALUE)RUBY_FL_USER4) /**< @old{RUBY_FL_USER4} */ +#define FL_USER5 RBIMPL_CAST((VALUE)RUBY_FL_USER5) /**< @old{RUBY_FL_USER5} */ +#define FL_USER6 RBIMPL_CAST((VALUE)RUBY_FL_USER6) /**< @old{RUBY_FL_USER6} */ +#define FL_USER7 RBIMPL_CAST((VALUE)RUBY_FL_USER7) /**< @old{RUBY_FL_USER7} */ +#define FL_USER8 RBIMPL_CAST((VALUE)RUBY_FL_USER8) /**< @old{RUBY_FL_USER8} */ +#define FL_USER9 RBIMPL_CAST((VALUE)RUBY_FL_USER9) /**< @old{RUBY_FL_USER9} */ +#define FL_USER10 RBIMPL_CAST((VALUE)RUBY_FL_USER10) /**< @old{RUBY_FL_USER10} */ +#define FL_USER11 RBIMPL_CAST((VALUE)RUBY_FL_USER11) /**< @old{RUBY_FL_USER11} */ +#define FL_USER12 RBIMPL_CAST((VALUE)RUBY_FL_USER12) /**< @old{RUBY_FL_USER12} */ +#define FL_USER13 RBIMPL_CAST((VALUE)RUBY_FL_USER13) /**< @old{RUBY_FL_USER13} */ +#define FL_USER14 RBIMPL_CAST((VALUE)RUBY_FL_USER14) /**< @old{RUBY_FL_USER14} */ +#define FL_USER15 RBIMPL_CAST((VALUE)RUBY_FL_USER15) /**< @old{RUBY_FL_USER15} */ +#define FL_USER16 RBIMPL_CAST((VALUE)RUBY_FL_USER16) /**< @old{RUBY_FL_USER16} */ +#define FL_USER17 RBIMPL_CAST((VALUE)RUBY_FL_USER17) /**< @old{RUBY_FL_USER17} */ +#define FL_USER18 RBIMPL_CAST((VALUE)RUBY_FL_USER18) /**< @old{RUBY_FL_USER18} */ +#define FL_USER19 RBIMPL_CAST((VALUE)(unsigned int)RUBY_FL_USER19) /**< @old{RUBY_FL_USER19} */ + +#define ELTS_SHARED RUBY_ELTS_SHARED /**< @old{RUBY_ELTS_SHARED} */ +#define RB_OBJ_FREEZE rb_obj_freeze_inline /**< @alias{rb_obj_freeze_inline} */ /** @cond INTERNAL_MACRO */ +#define RUBY_ELTS_SHARED RUBY_ELTS_SHARED #define RB_FL_ABLE RB_FL_ABLE #define RB_FL_ALL RB_FL_ALL #define RB_FL_ALL_RAW RB_FL_ALL_RAW @@ -111,69 +110,139 @@ #define RB_OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW #define RB_OBJ_FROZEN RB_OBJ_FROZEN #define RB_OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW -#define RB_OBJ_INFECT RB_OBJ_INFECT -#define RB_OBJ_INFECT_RAW RB_OBJ_INFECT_RAW -#define RB_OBJ_TAINT RB_OBJ_TAINT -#define RB_OBJ_TAINTABLE RB_OBJ_TAINTABLE -#define RB_OBJ_TAINTED RB_OBJ_TAINTED -#define RB_OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW -#define RB_OBJ_TAINT_RAW RB_OBJ_TAINT_RAW #define RB_OBJ_UNTRUST RB_OBJ_TAINT #define RB_OBJ_UNTRUSTED RB_OBJ_TAINTED /** @endcond */ /** - * @defgroup deprecated_macros deprecated macro APIs + * @defgroup deprecated_macros Deprecated macro APIs * @{ - * These macros are deprecated. Prefer their `RB_`-prefixed versions. + * These macros are deprecated. Prefer their `RB_`-prefixed versions. */ -#define FL_ABLE RB_FL_ABLE -#define FL_ALL RB_FL_ALL -#define FL_ALL_RAW RB_FL_ALL_RAW -#define FL_ANY RB_FL_ANY -#define FL_ANY_RAW RB_FL_ANY_RAW -#define FL_REVERSE RB_FL_REVERSE -#define FL_REVERSE_RAW RB_FL_REVERSE_RAW -#define FL_SET RB_FL_SET -#define FL_SET_RAW RB_FL_SET_RAW -#define FL_TEST RB_FL_TEST -#define FL_TEST_RAW RB_FL_TEST_RAW -#define FL_UNSET RB_FL_UNSET -#define FL_UNSET_RAW RB_FL_UNSET_RAW -#define OBJ_FREEZE RB_OBJ_FREEZE -#define OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW -#define OBJ_FROZEN RB_OBJ_FROZEN -#define OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW -#define OBJ_INFECT RB_OBJ_INFECT -#define OBJ_INFECT_RAW RB_OBJ_INFECT_RAW -#define OBJ_TAINT RB_OBJ_TAINT -#define OBJ_TAINTABLE RB_OBJ_TAINTABLE -#define OBJ_TAINTED RB_OBJ_TAINTED -#define OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW -#define OBJ_TAINT_RAW RB_OBJ_TAINT_RAW -#define OBJ_UNTRUST RB_OBJ_UNTRUST -#define OBJ_UNTRUSTED RB_OBJ_UNTRUSTED +#define FL_ABLE RB_FL_ABLE /**< @old{RB_FL_ABLE} */ +#define FL_ALL RB_FL_ALL /**< @old{RB_FL_ALL} */ +#define FL_ALL_RAW RB_FL_ALL_RAW /**< @old{RB_FL_ALL_RAW} */ +#define FL_ANY RB_FL_ANY /**< @old{RB_FL_ANY} */ +#define FL_ANY_RAW RB_FL_ANY_RAW /**< @old{RB_FL_ANY_RAW} */ +#define FL_REVERSE RB_FL_REVERSE /**< @old{RB_FL_REVERSE} */ +#define FL_REVERSE_RAW RB_FL_REVERSE_RAW /**< @old{RB_FL_REVERSE_RAW} */ +#define FL_SET RB_FL_SET /**< @old{RB_FL_SET} */ +#define FL_SET_RAW RB_FL_SET_RAW /**< @old{RB_FL_SET_RAW} */ +#define FL_TEST RB_FL_TEST /**< @old{RB_FL_TEST} */ +#define FL_TEST_RAW RB_FL_TEST_RAW /**< @old{RB_FL_TEST_RAW} */ +#define FL_UNSET RB_FL_UNSET /**< @old{RB_FL_UNSET} */ +#define FL_UNSET_RAW RB_FL_UNSET_RAW /**< @old{RB_FL_UNSET_RAW} */ +#define OBJ_FREEZE RB_OBJ_FREEZE /**< @old{RB_OBJ_FREEZE} */ +#define OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW /**< @old{RB_OBJ_FREEZE_RAW} */ +#define OBJ_FROZEN RB_OBJ_FROZEN /**< @old{RB_OBJ_FROZEN} */ +#define OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW /**< @old{RB_OBJ_FROZEN_RAW} */ +#define OBJ_INFECT RB_OBJ_INFECT /**< @old{RB_OBJ_INFECT} */ +#define OBJ_INFECT_RAW RB_OBJ_INFECT_RAW /**< @old{RB_OBJ_INFECT_RAW} */ +#define OBJ_TAINT RB_OBJ_TAINT /**< @old{RB_OBJ_TAINT} */ +#define OBJ_TAINTABLE RB_OBJ_TAINTABLE /**< @old{RB_OBJ_TAINT_RAW} */ +#define OBJ_TAINTED RB_OBJ_TAINTED /**< @old{RB_OBJ_TAINTED} */ +#define OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW /**< @old{RB_OBJ_TAINTED_RAW} */ +#define OBJ_TAINT_RAW RB_OBJ_TAINT_RAW /**< @old{RB_OBJ_TAINT_RAW} */ +#define OBJ_UNTRUST RB_OBJ_UNTRUST /**< @old{RB_OBJ_TAINT} */ +#define OBJ_UNTRUSTED RB_OBJ_UNTRUSTED /**< @old{RB_OBJ_TAINTED} */ /** @} */ -/* This is an enum because GDB wants it (rather than a macro) */ -enum ruby_fl_ushift { RUBY_FL_USHIFT = 12 }; +/** + * This is an enum because GDB wants it (rather than a macro). People need not + * bother. + */ +enum ruby_fl_ushift { + /** + * Number of bits in ::ruby_fl_type that are _not_ open to users. This is + * an implementation detail. Please ignore. + */ + RUBY_FL_USHIFT = 12 +}; /* > The expression that defines the value of an enumeration constant shall be * > an integer constant expression that has a value representable as an `int`. * * -- ISO/IEC 9899:2018 section 6.7.2.2 * - * So ENUM_OVER_INT situation is an extension to the standard. Note however + * So ENUM_OVER_INT situation is an extension to the standard. Note however * that we do not support 16 bit `int` environment. */ RB_GNUC_EXTENSION +/** + * The flags. Each ruby objects have their own characteristics apart from + * their classes. For instance whether an object is frozen or not is not + * controlled by its class. This is the type that represents such properties. + * + * @note About the `FL_USER` terminology: the "user" here does not necessarily + * mean only you. For instance struct ::RString instances use these + * bits to cache their encodings etc. Devs discussed about this topic, + * reached their consensus that ::RUBY_T_DATA is the only valid data + * structure that can use these bits; other data structures including + * ::RUBY_T_OBJECT use these bits for their own purpose. See also + * https://bugs.ruby-lang.org/issues/18059 + */ enum RBIMPL_ATTR_FLAG_ENUM() ruby_fl_type { + + /** + * @deprecated This flag once was a thing back in the old days, but makes + * no sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @internal + * + * The reality is our GC no longer remembers write barriers inside of each + * objects, to use dedicated bitmap instead. But this flag is still used + * internally. The current usages of this flag should be something + * different, which is unclear to @shyouhei. + */ RUBY_FL_WB_PROTECTED = (1<<5), - RUBY_FL_PROMOTED0 = (1<<5), - RUBY_FL_PROMOTED1 = (1<<6), - RUBY_FL_PROMOTED = RUBY_FL_PROMOTED0 | RUBY_FL_PROMOTED1, + + /** + * Ruby objects are "generational". There are young objects & old objects. + * Young objects are prone to die & monitored relatively extensively by the + * garbage collector. Old objects tend to live longer & are monitored less + * frequently. When an object survives a GC, its age is incremented. When + * age is equal to RVALUE_OLD_AGE, the object becomes Old. This flag is set + * when an object becomes old, and is used by the write barrier to check if + * an old object should be considered for marking more frequently - as old + * objects that have references added between major GCs need to be remarked + * to prevent the referred object being mistakenly swept. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ + RUBY_FL_PROMOTED = (1<<5), + + /** + * This flag is no longer in use + * + * @internal + */ + RUBY_FL_UNUSED6 = (1<<6), + + /** + * This flag has something to do with finalisers. A ruby object can have + * its finaliser, which is another object that evaluates when the target + * object is about to die. This flag is used to denote that there is an + * attached finaliser. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ RUBY_FL_FINALIZE = (1<<7), + + /** + * @deprecated This flag once was a thing back in the old days, but makes + * no sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + */ RUBY_FL_TAINT #if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) @@ -182,8 +251,25 @@ ruby_fl_type { # pragma deprecated(RUBY_FL_TAINT) #endif - = (1<<8), + = 0, + + /** + * This flag has something to do with Ractor. Multiple Ractors run without + * protecting each other. Sharing an object among Ractors are basically + * dangerous, disabled by default. This flag is used to bypass that + * restriction. Of course, you have to manually prevent race conditions + * then. + * + * This flag needs deep understanding of multithreaded programming. You + * would better not use it. + */ RUBY_FL_SHAREABLE = (1<<8), + + /** + * @deprecated This flag once was a thing back in the old days, but makes + * no sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + */ RUBY_FL_UNTRUSTED #if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) @@ -192,44 +278,132 @@ ruby_fl_type { # pragma deprecated(RUBY_FL_UNTRUSTED) #endif - = (1<<8), + = 0, + + /** + * This flag has something to do with object IDs. Unlike in the old days, + * an object's object ID (that a user can query using `Object#object_id`) + * is no longer its physical address represented using Ruby level integers. + * It is now a monotonic-increasing integer unrelated to the underlying + * memory arrangement. Object IDs are assigned when necessary; objects are + * born without one, and will eventually have such property when queried. + * The interpreter has to manage which one is which. This is the flag that + * helps the management. Objects with this flag set are the ones with + * object IDs assigned. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ RUBY_FL_SEEN_OBJ_ID = (1<<9), + + /** + * This flag has something to do with instance variables. 3rd parties need + * not know, but there are several ways to store an object's instance + * variables. Objects with this flag use so-called "generic" backend + * storage. This distinction is purely an implementation detail. People + * need not be aware of this working behind-the-scene. + * + * @internal + * + * As of writing everything except ::RObject and RModule use this scheme. + */ RUBY_FL_EXIVAR = (1<<10), + + /** + * This flag has something to do with data immutability. When this flag is + * set an object is considered "frozen". No modification are expected to + * happen beyond that point for the particular object. Immutability is + * basically considered to be a good property these days. Library authors + * are expected to obey. Test this bit before you touch a data structure. + * + * @see rb_check_frozen() + */ RUBY_FL_FREEZE = (1<<11), +/** (@shyouhei doesn't know how to excude this macro from doxygen). */ #define RBIMPL_FL_USER_N(n) RUBY_FL_USER##n = (1<<(RUBY_FL_USHIFT+n)) - RBIMPL_FL_USER_N(0), - RBIMPL_FL_USER_N(1), - RBIMPL_FL_USER_N(2), - RBIMPL_FL_USER_N(3), - RBIMPL_FL_USER_N(4), - RBIMPL_FL_USER_N(5), - RBIMPL_FL_USER_N(6), - RBIMPL_FL_USER_N(7), - RBIMPL_FL_USER_N(8), - RBIMPL_FL_USER_N(9), - RBIMPL_FL_USER_N(10), - RBIMPL_FL_USER_N(11), - RBIMPL_FL_USER_N(12), - RBIMPL_FL_USER_N(13), - RBIMPL_FL_USER_N(14), - RBIMPL_FL_USER_N(15), - RBIMPL_FL_USER_N(16), - RBIMPL_FL_USER_N(17), - RBIMPL_FL_USER_N(18), + RBIMPL_FL_USER_N(0), /**< User-defined flag. */ + RBIMPL_FL_USER_N(1), /**< User-defined flag. */ + RBIMPL_FL_USER_N(2), /**< User-defined flag. */ + RBIMPL_FL_USER_N(3), /**< User-defined flag. */ + RBIMPL_FL_USER_N(4), /**< User-defined flag. */ + RBIMPL_FL_USER_N(5), /**< User-defined flag. */ + RBIMPL_FL_USER_N(6), /**< User-defined flag. */ + RBIMPL_FL_USER_N(7), /**< User-defined flag. */ + RBIMPL_FL_USER_N(8), /**< User-defined flag. */ + RBIMPL_FL_USER_N(9), /**< User-defined flag. */ + RBIMPL_FL_USER_N(10), /**< User-defined flag. */ + RBIMPL_FL_USER_N(11), /**< User-defined flag. */ + RBIMPL_FL_USER_N(12), /**< User-defined flag. */ + RBIMPL_FL_USER_N(13), /**< User-defined flag. */ + RBIMPL_FL_USER_N(14), /**< User-defined flag. */ + RBIMPL_FL_USER_N(15), /**< User-defined flag. */ + RBIMPL_FL_USER_N(16), /**< User-defined flag. */ + RBIMPL_FL_USER_N(17), /**< User-defined flag. */ + RBIMPL_FL_USER_N(18), /**< User-defined flag. */ #ifdef ENUM_OVER_INT - RBIMPL_FL_USER_N(19), + RBIMPL_FL_USER_N(19), /**< User-defined flag. */ #else # define RUBY_FL_USER19 (RBIMPL_VALUE_ONE<<(RUBY_FL_USHIFT+19)) #endif #undef RBIMPL_FL_USER_N #undef RBIMPL_WIDER_ENUM + /** + * This flag has something to do with data structures. Over time, ruby + * evolved to reduce memory footprints. One of such attempt is so-called + * copy-on-write, which delays duplication of resources until ultimately + * necessary. Some data structures share this scheme. For example + * multiple instances of struct ::RArray could point identical memory + * region in common, as long as they don't differ. As people favour + * immutable style of programming than before, this situation is getting + * more and more common. Because such "shared" memory regions have nuanced + * ownership by nature, each structures need special care for them. This + * flag is used to distinguish such shared constructs. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ RUBY_ELTS_SHARED = RUBY_FL_USER2, - RUBY_FL_SINGLETON = RUBY_FL_USER0, + + /** + * This flag has something to do with an object's class. There are kind of + * classes called "singleton class", each of which have exactly one + * instance. What is interesting about singleton classes is that they are + * created _after_ their instance were instantiated, like this: + * + * ```ruby + * foo = Object.new # foo is an instance of Object... + * bar = foo.singleton_class # foo is now an instance of bar. + * ``` + * + * Here as you see `bar` is a singleton class of `foo`, which is injected + * into `foo`'s inheritance tree in a different statement (== distinct + * sequence point). In order to achieve this property singleton classes + * are special-cased in the interpreter. There is one bit flag that + * distinguishes if a class is a singleton class or not, and this is it. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ + RUBY_FL_SINGLETON = RUBY_FL_USER1, }; enum { + /** + * @deprecated This flag once was a thing back in the old days, but makes + * no sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + */ RUBY_FL_DUPPED #if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) @@ -238,19 +412,34 @@ enum { # pragma deprecated(RUBY_FL_DUPPED) #endif - = RUBY_T_MASK | RUBY_FL_EXIVAR + = (int)RUBY_T_MASK | (int)RUBY_FL_EXIVAR }; #undef RBIMPL_HAVE_ENUM_ATTRIBUTE RBIMPL_SYMBOL_EXPORT_BEGIN() -void rb_obj_infect(VALUE victim, VALUE carrier); +/** + * This is an implementation detail of #RB_OBJ_FREEZE(). People don't use it + * directly. + * + * @param[out] klass A singleton class. + * @post `klass` gets frozen. + */ void rb_freeze_singleton_class(VALUE klass); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_FORCEINLINE() +/** + * Checks if the object is flaggable. There are some special cases (most + * notably ::RUBY_Qfalse) where appending a flag to an object is not possible. + * This function can detect that. + * + * @param[in] obj Object in question + * @retval true It is flaggable. + * @retval false No it isn't. + */ static bool RB_FL_ABLE(VALUE obj) { @@ -267,6 +456,15 @@ RB_FL_ABLE(VALUE obj) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implementation detail of RB_FL_TEST(). 3rd parties need not use + * this. Just always use RB_FL_TEST(). + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @pre The object must not be an enum ::ruby_special_consts. + * @return `obj`'s flags, masked by `flags`. + */ static inline VALUE RB_FL_TEST_RAW(VALUE obj, VALUE flags) { @@ -276,6 +474,23 @@ RB_FL_TEST_RAW(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() +/** + * Tests if the given flag(s) are set or not. You can pass multiple flags at + * once: + * + * ```CXX + * auto obj = rb_eval_string("..."); + * if (RB_FL_TEST(obj, RUBY_FL_FREEZE | RUBY_FL_SHAREABLE)) { + * printf("Ractor ready!\n"); + * } + * ``` + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @return `obj`'s flags, masked by `flags`. + * @note It is intentional for this function to return ::VALUE. The + * return value could be passed to RB_FL_STE() etc. + */ static inline VALUE RB_FL_TEST(VALUE obj, VALUE flags) { @@ -289,6 +504,16 @@ RB_FL_TEST(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implementation detail of RB_FL_ANY(). 3rd parties need not use + * this. Just always use RB_FL_ANY(). + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @retval true The object has any of the flags set. + * @retval false No it doesn't at all. + * @pre The object must not be an enum ::ruby_special_consts. + */ static inline bool RB_FL_ANY_RAW(VALUE obj, VALUE flags) { @@ -297,6 +522,14 @@ RB_FL_ANY_RAW(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() +/** + * Identical to RB_FL_TEST(), except it returns bool. + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @retval true The object has any of the flags set. + * @retval false No it doesn't at all. + */ static inline bool RB_FL_ANY(VALUE obj, VALUE flags) { @@ -305,6 +538,16 @@ RB_FL_ANY(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implementation detail of RB_FL_ALL(). 3rd parties need not use + * this. Just always use RB_FL_ALL(). + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @retval true The object has all of the flags set. + * @retval false The object lacks any of the flags. + * @pre The object must not be an enum ::ruby_special_consts. + */ static inline bool RB_FL_ALL_RAW(VALUE obj, VALUE flags) { @@ -313,6 +556,14 @@ RB_FL_ALL_RAW(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() +/** + * Identical to RB_FL_ANY(), except it mandates all passed flags be set. + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @retval true The object has all of the flags set. + * @retval false The object lacks any of the flags. + */ static inline bool RB_FL_ALL(VALUE obj, VALUE flags) { @@ -321,6 +572,21 @@ RB_FL_ALL(VALUE obj, VALUE flags) RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_ARTIFICIAL() +/** + * @private + * + * This is an implementation detail of RB_FL_SET(). 3rd parties need not use + * this. Just always use RB_FL_SET(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` set. + * + * @internal + * + * This is function is here to annotate a part of RB_FL_SET_RAW() as + * `__declspec(noalias)`. + */ static inline void rbimpl_fl_set_raw_raw(struct RBasic *obj, VALUE flags) { @@ -328,6 +594,14 @@ rbimpl_fl_set_raw_raw(struct RBasic *obj, VALUE flags) } RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implementation detail of RB_FL_SET(). 3rd parties need not use + * this. Just always use RB_FL_SET(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` set. + */ static inline void RB_FL_SET_RAW(VALUE obj, VALUE flags) { @@ -336,6 +610,18 @@ RB_FL_SET_RAW(VALUE obj, VALUE flags) } RBIMPL_ATTR_ARTIFICIAL() +/** + * Sets the given flag(s). + * + * ```CXX + * auto v = rb_eval_string("..."); + * RB_FL_SET(v, RUBY_FL_FREEZE); + * ``` + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` set. + */ static inline void RB_FL_SET(VALUE obj, VALUE flags) { @@ -346,6 +632,21 @@ RB_FL_SET(VALUE obj, VALUE flags) RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_ARTIFICIAL() +/** + * @private + * + * This is an implementation detail of RB_FL_UNSET(). 3rd parties need not use + * this. Just always use RB_FL_UNSET(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` cleared. + * + * @internal + * + * This is function is here to annotate a part of RB_FL_UNSET_RAW() as + * `__declspec(noalias)`. + */ static inline void rbimpl_fl_unset_raw_raw(struct RBasic *obj, VALUE flags) { @@ -353,6 +654,14 @@ rbimpl_fl_unset_raw_raw(struct RBasic *obj, VALUE flags) } RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implementation detail of RB_FL_UNSET(). 3rd parties need not use + * this. Just always use RB_FL_UNSET(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` cleared. + */ static inline void RB_FL_UNSET_RAW(VALUE obj, VALUE flags) { @@ -361,6 +670,13 @@ RB_FL_UNSET_RAW(VALUE obj, VALUE flags) } RBIMPL_ATTR_ARTIFICIAL() +/** + * Clears the given flag(s). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` cleard. + */ static inline void RB_FL_UNSET(VALUE obj, VALUE flags) { @@ -371,6 +687,21 @@ RB_FL_UNSET(VALUE obj, VALUE flags) RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_ARTIFICIAL() +/** + * @private + * + * This is an implementation detail of RB_FL_REVERSE(). 3rd parties need not + * use this. Just always use RB_FL_REVERSE(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` reversed. + * + * @internal + * + * This is function is here to annotate a part of RB_FL_REVERSE_RAW() as + * `__declspec(noalias)`. + */ static inline void rbimpl_fl_reverse_raw_raw(struct RBasic *obj, VALUE flags) { @@ -378,6 +709,14 @@ rbimpl_fl_reverse_raw_raw(struct RBasic *obj, VALUE flags) } RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implementation detail of RB_FL_REVERSE(). 3rd parties need not + * use this. Just always use RB_FL_REVERSE(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` cleared. + */ static inline void RB_FL_REVERSE_RAW(VALUE obj, VALUE flags) { @@ -386,6 +725,14 @@ RB_FL_REVERSE_RAW(VALUE obj, VALUE flags) } RBIMPL_ATTR_ARTIFICIAL() +/** + * Reverses the flags. This function is here mainly for symmetry on set/unset. + * Rarely used in practice. + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` reversed. + */ static inline void RB_FL_REVERSE(VALUE obj, VALUE flags) { @@ -397,67 +744,141 @@ RB_FL_REVERSE(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return false always. + */ static inline bool RB_OBJ_TAINTABLE(VALUE obj) { + (void)obj; return false; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return false always. + */ static inline VALUE RB_OBJ_TAINTED_RAW(VALUE obj) { + (void)obj; return false; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return false always. + */ static inline bool RB_OBJ_TAINTED(VALUE obj) { + (void)obj; return false; } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + */ static inline void RB_OBJ_TAINT_RAW(VALUE obj) { + (void)obj; return; } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + */ static inline void RB_OBJ_TAINT(VALUE obj) { + (void)obj; return; } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] dst Victim object. + * @param[in] src Infectant object. + */ static inline void RB_OBJ_INFECT_RAW(VALUE dst, VALUE src) { + (void)dst; + (void)src; return; } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] dst Victim object. + * @param[in] src Infectant object. + */ static inline void RB_OBJ_INFECT(VALUE dst, VALUE src) { + (void)dst; + (void)src; return; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() -/* It is intentional not to return bool here. There is a place in ruby core - * (namely class.c:singleton_class_of()) where return value of this function is - * verbatimly passed to RB_FL_SET_RAW. */ +/** + * This is an implementation detail of RB_OBJ_FROZEN(). 3rd parties need not + * use this. Just always use RB_OBJ_FROZEN(). + * + * @param[in] obj Object in question. + * @retval RUBY_FL_FREEZE Yes it is. + * @retval 0 No it isn't. + * + * @internal + * + * It is intentional not to return bool here. There is a place in ruby core + * (namely `class.c:singleton_class_of()`) where return value of this function + * is passed to RB_FL_SET_RAW(). + */ static inline VALUE RB_OBJ_FROZEN_RAW(VALUE obj) { @@ -466,6 +887,13 @@ RB_OBJ_FROZEN_RAW(VALUE obj) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() +/** + * Checks if an object is frozen. + * + * @param[in] obj Object in question. + * @retval true Yes it is. + * @retval false No it isn't. + */ static inline bool RB_OBJ_FROZEN(VALUE obj) { @@ -477,22 +905,21 @@ RB_OBJ_FROZEN(VALUE obj) } } +RUBY_SYMBOL_EXPORT_BEGIN +void rb_obj_freeze_inline(VALUE obj); +RUBY_SYMBOL_EXPORT_END + RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implementation detail of RB_OBJ_FREEZE(). 3rd parties need not + * use this. Just always use RB_OBJ_FREEZE(). + * + * @param[out] obj Object in question. + */ static inline void RB_OBJ_FREEZE_RAW(VALUE obj) { - RB_FL_SET_RAW(obj, RUBY_FL_FREEZE); -} - -static inline void -rb_obj_freeze_inline(VALUE x) -{ - if (RB_FL_ABLE(x)) { - RB_OBJ_FREEZE_RAW(x); - if (RBASIC_CLASS(x) && !(RBASIC(x)->flags & RUBY_FL_SINGLETON)) { - rb_freeze_singleton_class(x); - } - } + rb_obj_freeze_inline(obj); } #endif /* RBIMPL_FL_TYPE_H */ |