summaryrefslogtreecommitdiff
path: root/include/ruby/internal/core/robject.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/ruby/internal/core/robject.h')
-rw-r--r--include/ruby/internal/core/robject.h142
1 files changed, 142 insertions, 0 deletions
diff --git a/include/ruby/internal/core/robject.h b/include/ruby/internal/core/robject.h
new file mode 100644
index 0000000000..99f6470ac1
--- /dev/null
+++ b/include/ruby/internal/core/robject.h
@@ -0,0 +1,142 @@
+#ifndef RBIMPL_ROBJECT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ROBJECT_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 ::RObject.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/deprecated.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/fl_type.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/value_type.h"
+
+/**
+ * Convenient casting macro.
+ *
+ * @param obj An object, which is in fact an ::RObject.
+ * @return The passed object casted to ::RObject.
+ */
+#define ROBJECT(obj) RBIMPL_CAST((struct RObject *)(obj))
+/** @cond INTERNAL_MACRO */
+#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX
+#define ROBJECT_HEAP ROBJECT_HEAP
+#define ROBJECT_FIELDS_CAPACITY ROBJECT_FIELDS_CAPACITY
+#define ROBJECT_FIELDS ROBJECT_FIELDS
+/** @endcond */
+
+/**
+ * @private
+ *
+ * Bits that you can set to ::RBasic::flags.
+ */
+enum ruby_robject_flags {
+ /**
+ * This flag marks that the object's instance variables are stored in an
+ * external heap buffer.
+ * Normally, instance variable references are stored inside the object slot,
+ * but if it overflow, Ruby may have to allocate a separate buffer and spills
+ * the instance variables there.
+ * This flag denotes that situation.
+ *
+ * @warning This bit has to be considered read-only. Setting/clearing
+ * this bit without corresponding fix up must cause immediate
+ * SEGV. Also, internal structures of an object change
+ * dynamically and transparently throughout of its lifetime.
+ * Don't assume it being persistent.
+ *
+ * @internal
+ *
+ * 3rd parties must not be aware that there even is more than one way to
+ * store instance variables. Might better be hidden.
+ */
+ ROBJECT_HEAP = RUBY_FL_USER4
+};
+
+struct st_table;
+
+/**
+ * Ruby's ordinal objects. Unless otherwise special cased, all predefined and
+ * user-defined classes share this struct to hold their instances.
+ */
+struct RObject {
+
+ /** Basic part, including flags and class. */
+ struct RBasic basic;
+
+ /** Object's specific fields. */
+ union {
+
+ /**
+ * Object that use separated memory region for instance variables use
+ * this pattern.
+ */
+ struct {
+ /** Pointer to a C array that holds instance variables. */
+ VALUE *fields;
+ } heap;
+
+ /* Embedded instance variables. When an object is small enough, it
+ * uses this area to store the instance variables.
+ *
+ * This is a length 1 array because:
+ * 1. GCC has a bug that does not optimize C flexible array members
+ * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
+ * 2. Zero length arrays are not supported by all compilers
+ */
+ VALUE ary[1];
+ } as;
+};
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries the instance variables.
+ *
+ * @param[in] obj Object in question.
+ * @return Its instance variables, in C array.
+ * @pre `obj` must be an instance of ::RObject.
+ *
+ * @internal
+ *
+ * @shyouhei finds no reason for this to be visible from extension libraries.
+ */
+static inline VALUE *
+ROBJECT_FIELDS(VALUE obj)
+{
+ RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
+
+ struct RObject *const ptr = ROBJECT(obj);
+
+ if (RB_UNLIKELY(RB_FL_ANY_RAW(obj, ROBJECT_HEAP))) {
+ return ptr->as.heap.fields;
+ }
+ else {
+ return ptr->as.ary;
+ }
+}
+
+#endif /* RBIMPL_ROBJECT_H */