summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gc.c18
-rw-r--r--include/ruby/internal/core/rdata.h9
-rw-r--r--include/ruby/internal/core/rtypeddata.h26
3 files changed, 28 insertions, 25 deletions
diff --git a/gc.c b/gc.c
index 3f5bc5cea5..96a32fbc23 100644
--- a/gc.c
+++ b/gc.c
@@ -1064,7 +1064,7 @@ rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FU
{
RUBY_ASSERT_ALWAYS(dfree != (RUBY_DATA_FUNC)1);
if (klass) rb_data_object_check(klass);
- return newobj_of(GET_RACTOR(), klass, T_DATA, (VALUE)dmark, (VALUE)dfree, (VALUE)datap, !dmark, sizeof(struct RTypedData));
+ return newobj_of(GET_RACTOR(), klass, T_DATA, (VALUE)dmark, (VALUE)datap, (VALUE)dfree, !dmark, sizeof(struct RTypedData));
}
VALUE
@@ -1081,7 +1081,7 @@ typed_data_alloc(VALUE klass, VALUE typed_flag, void *datap, const rb_data_type_
RBIMPL_NONNULL_ARG(type);
if (klass) rb_data_object_check(klass);
bool wb_protected = (type->flags & RUBY_FL_WB_PROTECTED) || !type->function.dmark;
- return newobj_of(GET_RACTOR(), klass, T_DATA, (VALUE)type, 1 | typed_flag, (VALUE)datap, wb_protected, size);
+ return newobj_of(GET_RACTOR(), klass, T_DATA, ((VALUE)type) | IS_TYPED_DATA | typed_flag, (VALUE)datap, 0, wb_protected, size);
}
VALUE
@@ -1177,8 +1177,8 @@ rb_data_free(void *objspace, VALUE obj)
void (*dfree)(void *);
if (RTYPEDDATA_P(obj)) {
- free_immediately = (RTYPEDDATA(obj)->type->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0;
- dfree = RTYPEDDATA(obj)->type->function.dfree;
+ free_immediately = (RTYPEDDATA_TYPE(obj)->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0;
+ dfree = RTYPEDDATA_TYPE(obj)->function.dfree;
}
else {
dfree = RDATA(obj)->dfree;
@@ -2660,7 +2660,7 @@ rb_gc_mark_roots(void *objspace, const char **categoryp)
#undef MARK_CHECKPOINT
}
-#define TYPED_DATA_REFS_OFFSET_LIST(d) (size_t *)(uintptr_t)RTYPEDDATA(d)->type->function.dmark
+#define TYPED_DATA_REFS_OFFSET_LIST(d) (size_t *)(uintptr_t)RTYPEDDATA_TYPE(d)->function.dmark
void
rb_gc_mark_children(void *objspace, VALUE obj)
@@ -2780,7 +2780,7 @@ rb_gc_mark_children(void *objspace, VALUE obj)
void *const ptr = RTYPEDDATA_P(obj) ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);
if (ptr) {
- if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(RTYPEDDATA(obj)->type)) {
+ if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) {
size_t *offset_list = TYPED_DATA_REFS_OFFSET_LIST(obj);
for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) {
@@ -2789,7 +2789,7 @@ rb_gc_mark_children(void *objspace, VALUE obj)
}
else {
RUBY_DATA_FUNC mark_func = RTYPEDDATA_P(obj) ?
- RTYPEDDATA(obj)->type->function.dmark :
+ RTYPEDDATA_TYPE(obj)->function.dmark :
RDATA(obj)->dmark;
if (mark_func) (*mark_func)(ptr);
}
@@ -3717,7 +3717,7 @@ rb_gc_update_object_references(void *objspace, VALUE obj)
{
void *const ptr = RTYPEDDATA_P(obj) ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);
if (ptr) {
- if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(RTYPEDDATA(obj)->type)) {
+ if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) {
size_t *offset_list = TYPED_DATA_REFS_OFFSET_LIST(obj);
for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) {
@@ -3726,7 +3726,7 @@ rb_gc_update_object_references(void *objspace, VALUE obj)
}
}
else if (RTYPEDDATA_P(obj)) {
- RUBY_DATA_FUNC compact_func = RTYPEDDATA(obj)->type->function.dcompact;
+ RUBY_DATA_FUNC compact_func = RTYPEDDATA_TYPE(obj)->function.dcompact;
if (compact_func) (*compact_func)(ptr);
}
}
diff --git a/include/ruby/internal/core/rdata.h b/include/ruby/internal/core/rdata.h
index e4c146a716..cab412af72 100644
--- a/include/ruby/internal/core/rdata.h
+++ b/include/ruby/internal/core/rdata.h
@@ -133,6 +133,12 @@ struct RData {
*/
RUBY_DATA_FUNC dmark;
+ /** Pointer to the actual C level struct that you want to wrap.
+ * This is in between dmark and dfree to allow DATA_PTR to continue
+ * to work for both RData and non-embedded RTypedData.
+ */
+ void *data;
+
/**
* This function is called when the object is no longer used. You need to
* do whatever necessary to avoid memory leaks.
@@ -141,9 +147,6 @@ struct RData {
* impossible at that moment (that is why GC runs).
*/
RUBY_DATA_FUNC dfree;
-
- /** Pointer to the actual C level struct that you want to wrap. */
- void *data;
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
diff --git a/include/ruby/internal/core/rtypeddata.h b/include/ruby/internal/core/rtypeddata.h
index 6c19576c20..b576be779f 100644
--- a/include/ruby/internal/core/rtypeddata.h
+++ b/include/ruby/internal/core/rtypeddata.h
@@ -114,7 +114,10 @@
#define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1
/** @endcond */
-#define TYPED_DATA_EMBEDDED 2
+#define IS_TYPED_DATA ((VALUE)1)
+#define TYPED_DATA_EMBEDDED ((VALUE)2)
+#define TYPED_DATA_PTR_FLAGS ((VALUE)3)
+#define TYPED_DATA_PTR_MASK (~TYPED_DATA_PTR_FLAGS)
/**
* @private
@@ -353,18 +356,16 @@ struct RTypedData {
struct RBasic basic;
/**
+ * This is a `const rb_data_type_t *const` value, with the low bits set:
+ *
+ * 1: Always set, to differentiate RTypedData from RData.
+ * 2: Set if object is embedded.
+ *
* This field stores various information about how Ruby should handle a
* data. This roughly resembles a Ruby level class (apart from method
* definition etc.)
*/
- const rb_data_type_t *const type;
-
- /**
- * This has to be always 1.
- *
- * @internal
- */
- const VALUE typed_flag;
+ const VALUE type;
/** Pointer to the actual C level struct that you want to wrap. */
void *data;
@@ -525,7 +526,7 @@ RTYPEDDATA_EMBEDDED_P(VALUE obj)
}
#endif
- return RTYPEDDATA(obj)->typed_flag & TYPED_DATA_EMBEDDED;
+ return (RTYPEDDATA(obj)->type) & TYPED_DATA_EMBEDDED;
}
static inline void *
@@ -561,8 +562,7 @@ RBIMPL_ATTR_ARTIFICIAL()
static inline bool
rbimpl_rtypeddata_p(VALUE obj)
{
- VALUE typed_flag = RTYPEDDATA(obj)->typed_flag;
- return typed_flag != 0 && typed_flag <= 3;
+ return RTYPEDDATA(obj)->type & IS_TYPED_DATA;
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
@@ -608,7 +608,7 @@ RTYPEDDATA_TYPE(VALUE obj)
}
#endif
- return RTYPEDDATA(obj)->type;
+ return (const struct rb_data_type_struct *)(RTYPEDDATA(obj)->type & TYPED_DATA_PTR_MASK);
}
/**