ruby--ruby/include/ruby/internal/fl_type.h

949 lines
34 KiB
C++

#ifndef RBIMPL_FL_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_FL_TYPE_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 enum ::ruby_fl_type.
*/
#include "ruby/internal/config.h" /* for ENUM_OVER_INT */
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/attr/deprecated.h"
#include "ruby/internal/attr/flag_enum.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/compiler_since.h"
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/has/extension.h"
#include "ruby/internal/special_consts.h"
#include "ruby/internal/stdbool.h"
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
#include "ruby/assert.h"
#include "ruby/defines.h"
/** @cond INTERNAL_MACRO */
#if RBIMPL_HAS_EXTENSION(enumerator_attributes)
# define RBIMPL_HAVE_ENUM_ATTRIBUTE 1
#elif RBIMPL_COMPILER_SINCE(GCC, 6, 0, 0)
# define RBIMPL_HAVE_ENUM_ATTRIBUTE 1
#endif
#ifdef ENUM_OVER_INT
# define RBIMPL_WIDER_ENUM 1
#elif SIZEOF_INT * CHAR_BIT > 12+19+1
# define RBIMPL_WIDER_ENUM 1
#else
# define RBIMPL_WIDER_ENUM 0
#endif
/** @endcond */
#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_PROMOTED0 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED0) /**< @old{RUBY_FL_PROMOTED0} */
#define FL_PROMOTED1 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED1) /**< @old{RUBY_FL_PROMOTED1} */
#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
#define RB_FL_ANY RB_FL_ANY
#define RB_FL_ANY_RAW RB_FL_ANY_RAW
#define RB_FL_REVERSE RB_FL_REVERSE
#define RB_FL_REVERSE_RAW RB_FL_REVERSE_RAW
#define RB_FL_SET RB_FL_SET
#define RB_FL_SET_RAW RB_FL_SET_RAW
#define RB_FL_TEST RB_FL_TEST
#define RB_FL_TEST_RAW RB_FL_TEST_RAW
#define RB_FL_UNSET RB_FL_UNSET
#define RB_FL_UNSET_RAW RB_FL_UNSET_RAW
#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
* @{
* These macros are deprecated. Prefer their `RB_`-prefixed versions.
*/
#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). 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
* 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),
/**
* This flag has something to do with our garbage collector. These days
* ruby objects are "generational". There are those who are young and
* those who are old. Young objects are prone to die; monitored relatively
* extensively by the garbage collector. OTOH old objects tend to live
* longer. They are relatively rarely considered. This flag is set when a
* object experienced promotion i.e. survived a garbage collection.
*
* @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_PROMOTED0 = (1<<5),
/**
* This flag has something to do with our garbage collector. These days
* ruby objects are "generational". There are those who are young and
* those who are old. Young objects are prone to die; monitored relatively
* extensively by the garbage collector. OTOH old objects tend to live
* longer. They are relatively rarely considered. This flag is set when a
* object experienced two promotions i.e. survived garbage collections
* twice.
*
* @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_PROMOTED1 = (1<<6),
/**
* This flag has something to do with our garbage collector. These days
* ruby objects are "generational". There are those who are young and
* those who are old. Young objects are prone to die; monitored relatively
* extensively by the garbage collector. OTOH old objects tend to live
* longer. They are relatively rarely considered. This flag is set when a
* object experienced promotions i.e. survived more than one garbage
* collections.
*
* @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 = RUBY_FL_PROMOTED0 | RUBY_FL_PROMOTED1,
/**
* 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)
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
#elif defined(_MSC_VER)
# pragma deprecated(RUBY_FL_TAINT)
#endif
= (1<<8),
/**
* 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)
RBIMPL_ATTR_DEPRECATED(("trustedness turned out to be a wrong idea."))
#elif defined(_MSC_VER)
# pragma deprecated(RUBY_FL_UNTRUSTED)
#endif
= (1<<8),
/**
* 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), /**< 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), /**< 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,
/**
* 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_USER0,
};
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)
RBIMPL_ATTR_DEPRECATED(("It seems there is no actual usage of this enum."))
#elif defined(_MSC_VER)
# pragma deprecated(RUBY_FL_DUPPED)
#endif
= (int)RUBY_T_MASK | (int)RUBY_FL_EXIVAR
};
#undef RBIMPL_HAVE_ENUM_ATTRIBUTE
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
* 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)
{
if (RB_SPECIAL_CONST_P(obj)) {
return false;
}
else if (RB_TYPE_P(obj, RUBY_T_NODE)) {
return false;
}
else {
return true;
}
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* This is an implenentation 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)
{
RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj));
return RBASIC(obj)->flags & 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)
{
if (RB_FL_ABLE(obj)) {
return RB_FL_TEST_RAW(obj, flags);
}
else {
return RBIMPL_VALUE_NULL;
}
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* This is an implenentation 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)
{
return RB_FL_TEST_RAW(obj, 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)
{
return RB_FL_TEST(obj, flags);
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* This is an implenentation 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)
{
return RB_FL_TEST_RAW(obj, flags) == 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)
{
return RB_FL_TEST(obj, flags) == flags;
}
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_ARTIFICIAL()
/**
* @private
*
* This is an implenentation 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)
{
obj->flags |= flags;
}
RBIMPL_ATTR_ARTIFICIAL()
/**
* This is an implenentation 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)
{
RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj));
rbimpl_fl_set_raw_raw(RBASIC(obj), 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)
{
if (RB_FL_ABLE(obj)) {
RB_FL_SET_RAW(obj, flags);
}
}
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_ARTIFICIAL()
/**
* @private
*
* This is an implenentation 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)
{
obj->flags &= ~flags;
}
RBIMPL_ATTR_ARTIFICIAL()
/**
* This is an implenentation 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)
{
RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj));
rbimpl_fl_unset_raw_raw(RBASIC(obj), 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)
{
if (RB_FL_ABLE(obj)) {
RB_FL_UNSET_RAW(obj, flags);
}
}
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_ARTIFICIAL()
/**
* @private
*
* This is an implenentation 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)
{
obj->flags ^= flags;
}
RBIMPL_ATTR_ARTIFICIAL()
/**
* This is an implenentation 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)
{
RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj));
rbimpl_fl_reverse_raw_raw(RBASIC(obj), 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)
{
if (RB_FL_ABLE(obj)) {
RB_FL_REVERSE_RAW(obj, 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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
return;
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* This is an implenentation 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)
{
return RB_FL_TEST_RAW(obj, RUBY_FL_FREEZE);
}
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)
{
if (! RB_FL_ABLE(obj)) {
return true;
}
else {
return RB_OBJ_FROZEN_RAW(obj);
}
}
RBIMPL_ATTR_ARTIFICIAL()
/**
* This is an implenentation 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);
}
RUBY_SYMBOL_EXPORT_BEGIN
void rb_obj_freeze_inline(VALUE obj);
RUBY_SYMBOL_EXPORT_END
#endif /* RBIMPL_FL_TYPE_H */