summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gdbinit19
-rw-r--r--NEWS.md16
-rw-r--r--encoding.c2
-rw-r--r--error.c7
-rw-r--r--ext/json/lib/json/version.rb2
-rw-r--r--ext/json/parser/parser.c6
-rw-r--r--ext/objspace/objspace_dump.c2
-rw-r--r--gc.c97
-rw-r--r--include/ruby/internal/core/rdata.h287
-rw-r--r--include/ruby/internal/core/rtypeddata.h53
-rw-r--r--include/ruby/internal/value_type.h22
-rw-r--r--include/ruby/random.h1
-rw-r--r--misc/lldb_rb/utils.py37
-rw-r--r--ractor.c2
-rw-r--r--spec/ruby/optional/capi/ext/rubyspec.h4
-rw-r--r--spec/ruby/optional/capi/ext/typed_data_spec.c9
-rw-r--r--spec/ruby/optional/capi/typed_data_spec.rb18
-rw-r--r--test/json/json_ryu_fallback_test.rb8
-rw-r--r--test/rubygems/test_gem_safe_yaml.rb6
-rw-r--r--zjit/src/cruby_bindings.inc.rs1
20 files changed, 137 insertions, 462 deletions
diff --git a/.gdbinit b/.gdbinit
index 0d585beef9..4457f6f12b 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -185,19 +185,14 @@ define rp
print (struct RBasic *)($arg0)
else
if ($flags & RUBY_T_MASK) == RUBY_T_DATA
- if ($flags & RUBY_TYPED_FL_IS_TYPED_DATA)
- set $data = (struct RTypedData *)($arg0)
- set $type = (const rb_data_type_t *)($data->type & ~1)
- printf "%sT_DATA%s(%s): ", $color_type, $color_end, $type->wrap_struct_name
- print *$type
- if ($data->type & 1)
- print (void *)&$data->data
- else
- print $data
- end
+ set $data = (struct RTypedData *)($arg0)
+ set $type = (const rb_data_type_t *)($data->type & ~1)
+ printf "%sT_DATA%s(%s): ", $color_type, $color_end, $type->wrap_struct_name
+ print *$type
+ if ($data->type & 1)
+ print (void *)&$data->data
else
- printf "%sT_DATA%s: ", $color_type, $color_end
- print *(struct RData *)($arg0)
+ print $data
end
else
if ($flags & RUBY_T_MASK) == RUBY_T_MATCH
diff --git a/NEWS.md b/NEWS.md
index 327742f544..bc7e59914f 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -82,7 +82,7 @@ releases.
* 6.0.1 to [v6.0.1.1][erb-v6.0.1.1], [v6.0.2][erb-v6.0.2], [v6.0.3][erb-v6.0.3], [v6.0.4][erb-v6.0.4]
* ipaddr 1.2.9
* 1.2.8 to [v1.2.9][ipaddr-v1.2.9]
-* json 2.19.6
+* json 2.19.7
* 2.18.0 to [v2.18.1][json-v2.18.1], [v2.19.0][json-v2.19.0], [v2.19.1][json-v2.19.1], [v2.19.2][json-v2.19.2], [v2.19.3][json-v2.19.3], [v2.19.4][json-v2.19.4], [v2.19.5][json-v2.19.5], [v2.19.6][json-v2.19.6]
* openssl 4.0.2
* 4.0.0 to [v4.0.1][openssl-v4.0.1], [v4.0.2][openssl-v4.0.2]
@@ -161,6 +161,19 @@ Ruby 4.0 bundled RubyGems and Bundler version 4. see the following links for det
[[Feature #21861]]
+### Removed APIs
+
+The following APIs, which have been deprecated for many years, are removed.
+[[Feature #21768]]
+
+* old postponed job functions,
+* untyped data object type/functions,
+* old APIs to allocate a data object,
+* taintedness/trustedness enums/macros,
+* `rb_gc_force_recycle` function,
+* `rb_iterate` function,
+* and some functions and constants for internal use.
+
## Implementation improvements
### Ractor
@@ -172,6 +185,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable.
[Feature #8948]: https://bugs.ruby-lang.org/issues/8948
[Feature #15330]: https://bugs.ruby-lang.org/issues/15330
[Feature #21390]: https://bugs.ruby-lang.org/issues/21390
+[Feature #21768]: https://bugs.ruby-lang.org/issues/21768
[Feature #21785]: https://bugs.ruby-lang.org/issues/21785
[Feature #21796]: https://bugs.ruby-lang.org/issues/21796
[Feature #21853]: https://bugs.ruby-lang.org/issues/21853
diff --git a/encoding.c b/encoding.c
index 8bb393b471..73fad8f1a6 100644
--- a/encoding.c
+++ b/encoding.c
@@ -126,7 +126,7 @@ static const rb_data_type_t encoding_data_type = {
};
#define is_encoding_type(obj) (RTYPEDDATA_TYPE(obj) == &encoding_data_type)
-#define is_data_encoding(obj) (rbimpl_rtypeddata_p(obj) && is_encoding_type(obj))
+#define is_data_encoding(obj) is_encoding_type(obj)
#define is_obj_encoding(obj) (rbimpl_obj_typeddata_p(obj) && is_encoding_type(obj))
int
diff --git a/error.c b/error.c
index ed7394dbf5..7a08fd2b9e 100644
--- a/error.c
+++ b/error.c
@@ -1364,8 +1364,7 @@ rb_check_type(VALUE x, int t)
rb_bug(UNDEF_LEAKED);
}
- xt = TYPE(x);
- if (xt != t || (xt == T_DATA && rbimpl_rtypeddata_p(x))) {
+ if (t == T_DATA) {
/*
* Typed data is not simple `T_DATA`, but in a sense an
* extension of `struct RVALUE`, which are incompatible with
@@ -1374,6 +1373,10 @@ rb_check_type(VALUE x, int t)
* So it is not enough to just check `T_DATA`, it must be
* identified by its `type` using `Check_TypedStruct` instead.
*/
+ rb_unexpected_object_type(x, builtin_types[t]);
+ }
+ xt = TYPE(x);
+ if (xt != t) {
unexpected_type(x, xt, t);
}
}
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
index 7ea306656b..a69590ff9c 100644
--- a/ext/json/lib/json/version.rb
+++ b/ext/json/lib/json/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module JSON
- VERSION = '2.19.6'
+ VERSION = '2.19.7'
end
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c
index fc16f727fe..363f109d3a 100644
--- a/ext/json/parser/parser.c
+++ b/ext/json/parser/parser.c
@@ -1202,7 +1202,11 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig
raise_parse_error_at("invalid number: %s", state, start);
}
- exponent = negative_exponent ? -abs_exponent : abs_exponent;
+ if (RB_UNLIKELY(exponent_digits >= 20 || abs_exponent > (uint64_t)INT64_MAX)) {
+ exponent = negative_exponent ? INT64_MIN : INT64_MAX;
+ } else {
+ exponent = negative_exponent ? -(int64_t)abs_exponent : (int64_t)abs_exponent;
+ }
}
if (integer) {
diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c
index b644c489b8..68ada01af3 100644
--- a/ext/objspace/objspace_dump.c
+++ b/ext/objspace/objspace_dump.c
@@ -573,7 +573,7 @@ dump_object(VALUE obj, struct dump_config *dc)
break;
case T_DATA:
- if (RTYPEDDATA_P(obj)) {
+ {
const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
dump_append(dc, ", \"struct\":\"");
dump_append(dc, type->wrap_struct_name);
diff --git a/gc.c b/gc.c
index 30502b9640..9eb7232940 100644
--- a/gc.c
+++ b/gc.c
@@ -337,8 +337,10 @@ rb_gc_shutdown_call_finalizer_p(VALUE obj)
{
switch (BUILTIN_TYPE(obj)) {
case T_DATA:
- if (!ruby_free_at_exit_p() && !DATA_PTR(obj)) return false;
- if (!ruby_free_at_exit_p() && !RTYPEDDATA_P(obj) && !RDATA(obj)->dfree) return false;
+ if (!ruby_free_at_exit_p()) {
+ if (!RDATA(obj)->type) return false;
+ if (!rbimpl_typeddata_embedded_p(obj) && !RTYPEDDATA(obj)->data) return false;
+ }
if (rb_obj_is_thread(obj)) return false;
if (rb_obj_is_mutex(obj)) return false;
if (rb_obj_is_fiber(obj)) return false;
@@ -374,7 +376,6 @@ void rb_vm_update_references(void *ptr);
#define rb_setjmp(env) RUBY_SETJMP(env)
#define rb_jmp_buf rb_jmpbuf_t
-#undef rb_data_object_wrap
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
@@ -1138,33 +1139,6 @@ rb_data_object_check(VALUE klass)
}
}
-VALUE
-rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
-{
- RUBY_ASSERT_ALWAYS(dfree != (RUBY_DATA_FUNC)1);
- if (klass) rb_data_object_check(klass);
- VALUE obj = rb_newobj(GET_EC(), klass, T_DATA, ROOT_SHAPE_ID, !dmark, sizeof(struct RData));
-
- rb_gc_register_pinning_obj(obj);
-
- struct RData *data = (struct RData *)obj;
- data->fields_obj = 0;
- data->_reserved = 0;
- data->data = datap;
- data->dmark = dmark;
- data->dfree = dfree;
-
- return obj;
-}
-
-VALUE
-rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
-{
- VALUE obj = rb_data_object_wrap(klass, 0, dmark, dfree);
- DATA_PTR(obj) = xcalloc(1, size);
- return obj;
-}
-
#define RTYPEDDATA_EMBEDDED_P rbimpl_typeddata_embedded_p
#define RB_DATA_TYPE_EMBEDDABLE_P(type) ((type)->flags & RUBY_TYPED_EMBEDDABLE)
#define RTYPEDDATA_EMBEDDABLE_P(obj) RB_DATA_TYPE_EMBEDDABLE_P(RTYPEDDATA_TYPE(obj))
@@ -1175,7 +1149,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;
- VALUE obj = rb_newobj(GET_EC(), klass, T_DATA | RUBY_TYPED_FL_IS_TYPED_DATA, ROOT_SHAPE_ID, wb_protected, size);
+ VALUE obj = rb_newobj(GET_EC(), klass, T_DATA, ROOT_SHAPE_ID, wb_protected, size);
rb_gc_register_pinning_obj(obj);
@@ -1237,18 +1211,16 @@ static size_t
rb_objspace_data_type_memsize(VALUE obj)
{
size_t size = 0;
- if (RTYPEDDATA_P(obj)) {
- const void *ptr = RTYPEDDATA_GET_DATA(obj);
+ const void *ptr = RTYPEDDATA_GET_DATA(obj);
- if (ptr) {
- if (RTYPEDDATA_EMBEDDABLE_P(obj) && !RTYPEDDATA_EMBEDDED_P(obj)) {
- size += ruby_xmalloc_usable_size((void *)ptr);
- }
+ if (ptr) {
+ if (RTYPEDDATA_EMBEDDABLE_P(obj) && !RTYPEDDATA_EMBEDDED_P(obj)) {
+ size += ruby_xmalloc_usable_size((void *)ptr);
+ }
- const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
- if (type->function.dsize) {
- size += type->function.dsize(ptr);
- }
+ const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
+ if (type->function.dsize) {
+ size += type->function.dsize(ptr);
}
}
@@ -1258,12 +1230,7 @@ rb_objspace_data_type_memsize(VALUE obj)
const char *
rb_objspace_data_type_name(VALUE obj)
{
- if (RTYPEDDATA_P(obj)) {
- return RTYPEDDATA_TYPE(obj)->wrap_struct_name;
- }
- else {
- return 0;
- }
+ return RTYPEDDATA_TYPE(obj)->wrap_struct_name;
}
void
@@ -1285,7 +1252,7 @@ rb_gc_handle_weak_references(VALUE obj)
{
switch (BUILTIN_TYPE(obj)) {
case T_DATA:
- if (RTYPEDDATA_P(obj)) {
+ {
const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
if (type->function.handle_weak_references) {
@@ -1298,9 +1265,6 @@ rb_gc_handle_weak_references(VALUE obj)
);
}
}
- else {
- rb_bug("rb_gc_handle_weak_references: unknown T_DATA");
- }
break;
case T_IMEMO: {
@@ -1423,7 +1387,7 @@ rb_gc_obj_needs_cleanup_p(VALUE obj)
return false;
case T_DATA:
- if (flags & RUBY_TYPED_FL_IS_TYPED_DATA) {
+ {
uintptr_t type = (uintptr_t)RTYPEDDATA(obj)->type;
if (type & TYPED_DATA_EMBEDDED) {
RUBY_DATA_FUNC dfree = ((const rb_data_type_t *)(type & TYPED_DATA_PTR_MASK))->function.dfree;
@@ -1485,22 +1449,17 @@ make_io_zombie(void *objspace, VALUE obj)
static bool
rb_data_free(void *objspace, VALUE obj)
{
- void *data = RTYPEDDATA_P(obj) ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);
+ void *data = RTYPEDDATA_GET_DATA(obj);
if (data) {
int free_immediately = false;
void (*dfree)(void *);
- if (RTYPEDDATA_P(obj)) {
- free_immediately = (RTYPEDDATA_TYPE(obj)->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0;
- dfree = RTYPEDDATA_TYPE(obj)->function.dfree;
- }
- else {
- dfree = RDATA(obj)->dfree;
- }
+ free_immediately = (RTYPEDDATA_TYPE(obj)->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0;
+ dfree = RTYPEDDATA_TYPE(obj)->function.dfree;
if (dfree) {
if (dfree == RUBY_DEFAULT_FREE) {
- if (!RTYPEDDATA_P(obj) || !RTYPEDDATA_EMBEDDED_P(obj)) {
+ if (!RTYPEDDATA_EMBEDDED_P(obj)) {
xfree(data);
RB_DEBUG_COUNTER_INC(obj_data_xfree);
}
@@ -3512,13 +3471,12 @@ rb_gc_mark_children(void *objspace, VALUE obj)
break;
case T_DATA: {
- bool typed_data = RTYPEDDATA_P(obj);
- void *const ptr = typed_data ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);
+ void *const ptr = RTYPEDDATA_GET_DATA(obj);
gc_mark_internal(RTYPEDDATA(obj)->fields_obj);
if (ptr) {
- if (typed_data && gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) {
+ if (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++) {
@@ -3526,9 +3484,7 @@ rb_gc_mark_children(void *objspace, VALUE obj)
}
}
else {
- RUBY_DATA_FUNC mark_func = typed_data ?
- RTYPEDDATA_TYPE(obj)->function.dmark :
- RDATA(obj)->dmark;
+ RUBY_DATA_FUNC mark_func = RTYPEDDATA_TYPE(obj)->function.dmark;
if (mark_func) (*mark_func)(ptr);
}
}
@@ -4460,13 +4416,12 @@ rb_gc_update_object_references(void *objspace, VALUE obj)
case T_DATA:
/* Call the compaction callback, if it exists */
{
- bool typed_data = RTYPEDDATA_P(obj);
- void *const ptr = typed_data ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);
+ void *const ptr = RTYPEDDATA_GET_DATA(obj);
UPDATE_IF_MOVED(objspace, RTYPEDDATA(obj)->fields_obj);
if (ptr) {
- if (typed_data && gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) {
+ if (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++) {
@@ -4474,7 +4429,7 @@ rb_gc_update_object_references(void *objspace, VALUE obj)
*ref = gc_location_internal(objspace, *ref);
}
}
- else if (typed_data) {
+ else {
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 5ebeb2473e..d0a4dc7c83 100644
--- a/include/ruby/internal/core/rdata.h
+++ b/include/ruby/internal/core/rdata.h
@@ -42,31 +42,9 @@
#endif
#define RBIMPL_DATA_FUNC(f) RBIMPL_CAST((void (*)(void *))(f))
-#define RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() \
- RBIMPL_ATTR_WARNING(("untyped Data is unsafe; use TypedData instead")) \
- RBIMPL_ATTR_DEPRECATED(("by TypedData"))
-
-#define RBIMPL_MACRO_SELECT(x, y) x ## y
-#define RUBY_MACRO_SELECT(x, y) RBIMPL_MACRO_SELECT(x, y)
/** @endcond */
/**
- * Convenient casting macro.
- *
- * @param obj An object, which is in fact an ::RData.
- * @return The passed object casted to ::RData.
- */
-#define RDATA(obj) RBIMPL_CAST((struct RData *)(obj))
-
-/**
- * Convenient getter macro.
- *
- * @param obj An object, which is in fact an ::RData.
- * @return The passed object's ::RData::data field.
- */
-#define DATA_PTR(obj) RDATA(obj)->data
-
-/**
* This is a value you can set to ::RData::dfree. Setting this means the data
* was allocated using ::ruby_xmalloc() (or variants), and shall be freed using
* ::ruby_xfree().
@@ -85,19 +63,6 @@
#define RUBY_NEVER_FREE RBIMPL_DATA_FUNC(0)
/**
- * @private
- *
- * @deprecated This macro 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.
- */
-#define RUBY_UNTYPED_DATA_FUNC(f) f RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
-
-/*
-#define RUBY_DATA_FUNC(func) ((void (*)(void*))(func))
-*/
-
-/**
* This is the type of callbacks registered to ::RData. The argument is the
* `data` field.
*/
@@ -106,264 +71,16 @@ typedef void (*RUBY_DATA_FUNC)(void*);
/**
* @deprecated
*
- * Old "untyped" user data. It has roughly the same usage as struct
- * ::RTypedData, but lacked several features such as support for compaction GC.
- * Use of this struct is not recommended any longer. If it is dead necessary,
- * please inform the core devs about your usage.
- *
- * @internal
- *
- * @shyouhei tried to add RBIMPL_ATTR_DEPRECATED for this type but that yielded
- * too many warnings in the core. Maybe we want to retry later... Just add
- * deprecated document for now.
- *
- * RData shares its initial fields with struct ::RTypedData so the VM can handle
- * per-object fields without checking whether a T_DATA object is typed or legacy.
+ * DO NOT USE: Obsolete "untyped" user data, that is remained only for
+ * the backward compatibility for some wrapper generator gems.
*/
struct RData {
-
- /** Basic part, including flags and class. */
struct RBasic basic;
-
- /** @internal Direct reference to the slots that hold instance variables, if any. */
VALUE fields_obj;
-
- /** @internal Padding where ::RTypedData stores its type, so both structs place data at the same offset. */
VALUE _reserved;
-
- /** Pointer to the actual C level struct that you want to wrap. */
void *data;
-
- /**
- * This function is called when the object is experiencing GC marks. If it
- * contains references to other Ruby objects, you need to mark them also.
- * Otherwise GC will smash your data.
- *
- * @see rb_gc_mark()
- * @warning This is called during GC runs. Object allocations are
- * impossible at that moment (that is why GC runs).
- */
RUBY_DATA_FUNC dmark;
-
- /**
- * This function is called when the object is no longer used. You need to
- * do whatever necessary to avoid memory leaks.
- *
- * @warning This is called during GC runs. Object allocations are
- * impossible at that moment (that is why GC runs).
- */
RUBY_DATA_FUNC dfree;
};
-RBIMPL_SYMBOL_EXPORT_BEGIN()
-
-/**
- * This is the primitive way to wrap an existing C struct into ::RData.
- *
- * @param[in] klass Ruby level class of the returning object.
- * @param[in] datap Pointer to the target C struct.
- * @param[in] dmark Mark function.
- * @param[in] dfree Free function.
- * @exception rb_eTypeError `klass` is not a class.
- * @exception rb_eNoMemError Out of memory.
- * @return An allocated object that wraps `datap`.
- */
-VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree);
-
-/**
- * Identical to rb_data_object_wrap(), except it allocates a new data region
- * internally instead of taking an existing one. The allocation is done using
- * ruby_calloc(). Hence it makes no sense to pass anything other than
- * ::RUBY_DEFAULT_FREE to the last argument.
- *
- * @param[in] klass Ruby level class of the returning object.
- * @param[in] size Requested size of memory to allocate.
- * @param[in] dmark Mark function.
- * @param[in] dfree Free function.
- * @exception rb_eTypeError `klass` is not a class.
- * @exception rb_eNoMemError Out of memory.
- * @return An allocated object that wraps a new `size` byte region.
- */
-VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree);
-
-RBIMPL_SYMBOL_EXPORT_END()
-
-/**
- * Converts sval, a pointer to your struct, into a Ruby object.
- *
- * @param klass A ruby level class.
- * @param mark Mark function.
- * @param free Free function.
- * @param sval A pointer to your struct.
- * @exception rb_eTypeError `klass` is not a class.
- * @exception rb_eNoMemError Out of memory.
- * @return A created Ruby object.
- */
-#define Data_Wrap_Struct(klass, mark, free, sval) \
- rb_data_object_wrap( \
- (klass), \
- (sval), \
- RBIMPL_DATA_FUNC(mark), \
- RBIMPL_DATA_FUNC(free))
-
-/**
- * @private
- *
- * This is an implementation detail of #Data_Make_Struct. People don't use it
- * directly.
- *
- * @param result Variable name of created Ruby object.
- * @param klass Ruby level class of the object.
- * @param type Type name of the C struct.
- * @param size Size of the C struct.
- * @param mark Mark function.
- * @param free Free function.
- * @param sval Variable name of created C struct.
- */
-#define Data_Make_Struct0(result, klass, type, size, mark, free, sval) \
- VALUE result = rb_data_object_zalloc( \
- (klass), \
- (size), \
- RBIMPL_DATA_FUNC(mark), \
- RBIMPL_DATA_FUNC(free)); \
- (sval) = RBIMPL_CAST((type *)DATA_PTR(result)); \
- RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval))
-
-/**
- * Identical to #Data_Wrap_Struct, except it allocates a new data region
- * internally instead of taking an existing one. The allocation is done using
- * ruby_calloc(). Hence it makes no sense to pass anything other than
- * ::RUBY_DEFAULT_FREE to the `free` argument.
- *
- * @param klass Ruby level class of the returning object.
- * @param type Type name of the C struct.
- * @param mark Mark function.
- * @param free Free function.
- * @param sval Variable name of created C struct.
- * @exception rb_eTypeError `klass` is not a class.
- * @exception rb_eNoMemError Out of memory.
- * @return A created Ruby object.
- */
-#ifdef HAVE_STMT_AND_DECL_IN_EXPR
-#define Data_Make_Struct(klass, type, mark, free, sval) \
- RB_GNUC_EXTENSION({ \
- Data_Make_Struct0( \
- data_struct_obj, \
- klass, \
- type, \
- sizeof(type), \
- mark, \
- free, \
- sval); \
- data_struct_obj; \
- })
-#else
-#define Data_Make_Struct(klass, type, mark, free, sval) \
- rb_data_object_make( \
- (klass), \
- RBIMPL_DATA_FUNC(mark), \
- RBIMPL_DATA_FUNC(free), \
- RBIMPL_CAST((void **)&(sval)), \
- sizeof(type))
-#endif
-
-/**
- * Obtains a C struct from inside of a wrapper Ruby object.
- *
- * @param obj An instance of ::RData.
- * @param type Type name of the C struct.
- * @param sval Variable name of obtained C struct.
- * @return Unwrapped C struct that `obj` holds.
- */
-#define Data_Get_Struct(obj, type, sval) \
- ((sval) = RBIMPL_CAST((type*)rb_data_object_get(obj)))
-
-RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
-/**
- * @private
- *
- * This is an implementation detail of rb_data_object_wrap(). People don't use
- * it directly.
- *
- * @param[in] klass Ruby level class of the returning object.
- * @param[in] ptr Pointer to the target C struct.
- * @param[in] mark Mark function.
- * @param[in] free Free function.
- * @exception rb_eTypeError `klass` is not a class.
- * @exception rb_eNoMemError Out of memory.
- * @return An allocated object that wraps `datap`.
- */
-static inline VALUE
-rb_data_object_wrap_warning(VALUE klass, void *ptr, RUBY_DATA_FUNC mark, RUBY_DATA_FUNC free)
-{
- return rb_data_object_wrap(klass, ptr, mark, free);
-}
-
-/**
- * @private
- *
- * This is an implementation detail of #Data_Get_Struct. People don't use it
- * directly.
- *
- * @param[in] obj An instance of ::RData.
- * @return Unwrapped C struct that `obj` holds.
- */
-static inline void *
-rb_data_object_get(VALUE obj)
-{
- Check_Type(obj, RUBY_T_DATA);
- return DATA_PTR(obj);
-}
-
-RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
-/**
- * @private
- *
- * This is an implementation detail of #Data_Get_Struct. People don't use it
- * directly.
- *
- * @param[in] obj An instance of ::RData.
- * @return Unwrapped C struct that `obj` holds.
- */
-static inline void *
-rb_data_object_get_warning(VALUE obj)
-{
- return rb_data_object_get(obj);
-}
-
-/**
- * This is an implementation detail of #Data_Make_Struct. People don't use it
- * directly.
- *
- * @param[in] klass Ruby level class of the returning object.
- * @param[in] mark_func Mark function.
- * @param[in] free_func Free function.
- * @param[in] datap Variable of created C struct.
- * @param[in] size Requested size of allocation.
- * @exception rb_eTypeError `klass` is not a class.
- * @exception rb_eNoMemError Out of memory.
- * @return A created Ruby object.
- * @post `*datap` holds the created C struct.
- */
-static inline VALUE
-rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_func, void **datap, size_t size)
-{
- Data_Make_Struct0(result, klass, void, size, mark_func, free_func, *datap);
- return result;
-}
-
-/** @cond INTERNAL_MACRO */
-#define rb_data_object_wrap_0 rb_data_object_wrap
-#define rb_data_object_wrap_1 rb_data_object_wrap_warning
-#define rb_data_object_wrap_2 rb_data_object_wrap_ /* Used here vvvv */
-#define rb_data_object_wrap RUBY_MACRO_SELECT(rb_data_object_wrap_2, RUBY_UNTYPED_DATA_WARNING)
-#define rb_data_object_get_0 rb_data_object_get
-#define rb_data_object_get_1 rb_data_object_get_warning
-#define rb_data_object_get_2 rb_data_object_get_ /* Used here vvvv */
-#define rb_data_object_get RUBY_MACRO_SELECT(rb_data_object_get_2, RUBY_UNTYPED_DATA_WARNING)
-#define rb_data_object_make_0 rb_data_object_make
-#define rb_data_object_make_1 rb_data_object_make_warning
-#define rb_data_object_make_2 rb_data_object_make_ /* Used here vvvv */
-#define rb_data_object_make RUBY_MACRO_SELECT(rb_data_object_make_2, RUBY_UNTYPED_DATA_WARNING)
-/** @endcond */
#endif /* RBIMPL_RDATA_H */
diff --git a/include/ruby/internal/core/rtypeddata.h b/include/ruby/internal/core/rtypeddata.h
index 0b189c7ef8..eb8313f180 100644
--- a/include/ruby/internal/core/rtypeddata.h
+++ b/include/ruby/internal/core/rtypeddata.h
@@ -206,11 +206,6 @@ rbimpl_typeddata_flags {
RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */
/**
- * This flag is used to distinguish RTypedData from deprecated RData objects.
- */
- RUBY_TYPED_FL_IS_TYPED_DATA = RUBY_FL_USERPRIV0,
-
- /**
* This flag determines whether marking and compaction should be carried out
* using the dmark/dcompact callback functions or whether we should mark
* declaratively using a list of references defined inside the data struct we're wrapping
@@ -409,6 +404,22 @@ RBIMPL_STATIC_ASSERT(fields_obj_in_rdata, offsetof(struct RData, fields_obj) ==
RBIMPL_STATIC_ASSERT(data_in_rtypeddata, offsetof(struct RData, data) == offsetof(struct RTypedData, data));
#endif
+/**
+ * Convenient casting macro for backward compatibility.
+ *
+ * @param obj An object, which is in fact an ::RData.
+ * @return The passed object casted to ::RData.
+ */
+#define RDATA(obj) RTYPEDDATA(obj)
+
+/**
+ * Convenient casting macro for backward compatibility.
+ *
+ * @param obj An object, which is in fact an ::RData.
+ * @return The passed object's ::RTypedData::data field.
+ */
+#define DATA_PTR(obj) RTYPEDDATA_DATA(obj)
+
RBIMPL_SYMBOL_EXPORT_BEGIN()
RBIMPL_ATTR_NONNULL((3))
/**
@@ -621,27 +632,7 @@ RBIMPL_ATTR_ARTIFICIAL()
/**
* @private
*
- * This is an implementation detail of Check_Type(). People don't use it
- * directly.
- *
- * @param[in] obj Object in question
- * @retval true `obj` is an instance of ::RTypedData.
- * @retval false `obj` is an instance of ::RData.
- * @pre `obj` must be a Ruby object of ::RUBY_T_DATA.
- */
-static inline bool
-rbimpl_rtypeddata_p(VALUE obj)
-{
- return FL_TEST_RAW(obj, RUBY_TYPED_FL_IS_TYPED_DATA);
-}
-
-RBIMPL_ATTR_PURE()
-RBIMPL_ATTR_ARTIFICIAL()
-/**
- * @private
- *
- * Identical to rbimpl_rtypeddata_p(), except it is allowed to call on non-data
- * objects.
+ * Checks whether the passed object is ::RTypedData.
*
* This is an implementation detail of inline functions defined in this file.
* People don't use it directly.
@@ -653,17 +644,16 @@ RBIMPL_ATTR_ARTIFICIAL()
static inline bool
rbimpl_obj_typeddata_p(VALUE obj)
{
- return RB_TYPE_P(obj, RUBY_T_DATA) && rbimpl_rtypeddata_p(obj);
+ return RB_TYPE_P(obj, RUBY_T_DATA);
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
- * Checks whether the passed object is ::RTypedData or ::RData.
+ * Checks whether the passed object is ::RTypedData.
*
* @param[in] obj Object in question
- * @retval true `obj` is an instance of ::RTypedData.
- * @retval false `obj` is an instance of ::RData.
+ * @retval true
* @pre `obj` must be a Ruby object of ::RUBY_T_DATA.
*/
static inline bool
@@ -671,7 +661,7 @@ RTYPEDDATA_P(VALUE obj)
{
RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false));
- return rbimpl_rtypeddata_p(obj);
+ return true;
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
@@ -752,7 +742,6 @@ static inline VALUE
rbimpl_check_external_typeddata(VALUE obj)
{
RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false));
- RUBY_ASSERT(rbimpl_obj_typeddata_p(obj));
RUBY_ASSERT(!rbimpl_typeddata_embedded_p(obj));
return obj;
}
diff --git a/include/ruby/internal/value_type.h b/include/ruby/internal/value_type.h
index b47d8afb97..77cb38bc7d 100644
--- a/include/ruby/internal/value_type.h
+++ b/include/ruby/internal/value_type.h
@@ -410,14 +410,6 @@ RB_TYPE_P(VALUE obj, enum ruby_value_type t)
#endif
/** @endcond */
-RBIMPL_ATTR_PURE()
-RBIMPL_ATTR_ARTIFICIAL()
-/**
- * @private
- * Defined in ruby/internal/core/rtypeddata.h
- */
-static inline bool rbimpl_rtypeddata_p(VALUE obj);
-
RBIMPL_ATTR_ARTIFICIAL()
/**
* Identical to RB_TYPE_P(), except it raises exceptions on predication
@@ -432,19 +424,11 @@ RBIMPL_ATTR_ARTIFICIAL()
static inline void
Check_Type(VALUE v, enum ruby_value_type t)
{
+ /* Typed data is not simple `T_DATA`, see `rb_check_type` */
+ RUBY_ASSERT_ALWAYS(t != RUBY_T_DATA);
if (RB_UNLIKELY(! RB_TYPE_P(v, t))) {
- goto unexpected_type;
+ rb_unexpected_type(v, RBIMPL_CAST((int)t));
}
- else if (t == RUBY_T_DATA && rbimpl_rtypeddata_p(v)) {
- /* Typed data is not simple `T_DATA`, see `rb_check_type` */
- goto unexpected_type;
- }
- else {
- return;
- }
-
- unexpected_type:
- rb_unexpected_type(v, RBIMPL_CAST((int)t));
}
#endif /* RBIMPL_VALUE_TYPE_H */
diff --git a/include/ruby/random.h b/include/ruby/random.h
index 740be6bdad..3b63a23334 100644
--- a/include/ruby/random.h
+++ b/include/ruby/random.h
@@ -333,7 +333,6 @@ static inline const rb_random_interface_t *
rb_rand_if(VALUE obj)
{
RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P(obj, T_DATA));
- RBIMPL_ASSERT_OR_ASSUME(RTYPEDDATA_P(obj));
RUBY_ASSERT(rb_typeddata_is_kind_of(obj, &rb_random_data_type));
const struct rb_data_type_struct *t = RTYPEDDATA_TYPE(obj);
const void *ret = t->data;
diff --git a/misc/lldb_rb/utils.py b/misc/lldb_rb/utils.py
index e0cb609b1a..a2bcedc328 100644
--- a/misc/lldb_rb/utils.py
+++ b/misc/lldb_rb/utils.py
@@ -236,29 +236,20 @@ class RbInspector(LLDBInterface):
elif rval.is_type("RUBY_T_DATA"):
tRTypedData = self.target.FindFirstType("struct RTypedData").GetPointerType()
val = val.Cast(tRTypedData)
- is_typed_data = self.ruby_globals.get("RUBY_TYPED_FL_IS_TYPED_DATA", None)
- if is_typed_data:
- typed = rval.flags & is_typed_data
- else:
- typed = val.GetValueForExpressionPath("->typed_flag").GetValueAsUnsigned() == 1
-
- if typed:
- type = val.GetValueForExpressionPath("->type").GetValueAsUnsigned()
- embed = (type & 1)
- if embed:
- flaginfo += "[EMBED] "
- type = self.frame.EvaluateExpression("(rb_data_type_t *)%0#x" % (type & ~1))
- print("T_DATA: %s%s" %
- (flaginfo, type.GetValueForExpressionPath("->wrap_struct_name")),
- file=self.result)
- print("%s", type.Dereference(), file=self.result)
- ptr = val.GetValueForExpressionPath("->data")
- if embed:
- ptr = ptr.AddressOf()
- self._append_expression("(void *)%0#x" % ptr.GetValueAsUnsigned())
- else:
- print("T_DATA:", file=self.result)
- self._append_expression("*(struct RData *) %0#x" % val.GetValueAsUnsigned())
+
+ type = val.GetValueForExpressionPath("->type").GetValueAsUnsigned()
+ embed = (type & 1)
+ if embed:
+ flaginfo += "[EMBED] "
+ type = self.frame.EvaluateExpression("(rb_data_type_t *)%0#x" % (type & ~1))
+ print("T_DATA: %s%s" %
+ (flaginfo, type.GetValueForExpressionPath("->wrap_struct_name")),
+ file=self.result)
+ print("%s", type.Dereference(), file=self.result)
+ ptr = val.GetValueForExpressionPath("->data")
+ if embed:
+ ptr = ptr.AddressOf()
+ self._append_expression("(void *)%0#x" % ptr.GetValueAsUnsigned())
elif rval.is_type("RUBY_T_IMEMO"):
imemo_type = ((rval.flags >> self.ruby_globals["RUBY_FL_USHIFT"])
diff --git a/ractor.c b/ractor.c
index 8fe4b15044..d611ca97c2 100644
--- a/ractor.c
+++ b/ractor.c
@@ -1451,7 +1451,7 @@ allow_frozen_shareable_p(VALUE obj)
if (!RB_TYPE_P(obj, T_DATA)) {
return true;
}
- else if (RTYPEDDATA_P(obj)) {
+ else {
const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
if (type->flags & RUBY_TYPED_FROZEN_SHAREABLE) {
return true;
diff --git a/spec/ruby/optional/capi/ext/rubyspec.h b/spec/ruby/optional/capi/ext/rubyspec.h
index 7107bead90..5a92645785 100644
--- a/spec/ruby/optional/capi/ext/rubyspec.h
+++ b/spec/ruby/optional/capi/ext/rubyspec.h
@@ -35,6 +35,10 @@
(RUBY_API_VERSION_MAJOR == (major) && RUBY_API_VERSION_MINOR < (minor)))
#define RUBY_VERSION_SINCE(major,minor) (!RUBY_VERSION_BEFORE(major, minor))
+#if RUBY_VERSION_SINCE(4, 1)
+#define RUBY_VERSION_IS_4_1
+#endif
+
#if RUBY_VERSION_SINCE(4, 0)
#define RUBY_VERSION_IS_4_0
#endif
diff --git a/spec/ruby/optional/capi/ext/typed_data_spec.c b/spec/ruby/optional/capi/ext/typed_data_spec.c
index 221f1c8ac4..c6fcfa3bc8 100644
--- a/spec/ruby/optional/capi/ext/typed_data_spec.c
+++ b/spec/ruby/optional/capi/ext/typed_data_spec.c
@@ -106,6 +106,7 @@ VALUE sws_typed_wrap_struct(VALUE self, VALUE val) {
return TypedData_Wrap_Struct(rb_cObject, &sample_typed_wrapped_struct_data_type, bar);
}
+#ifndef RUBY_VERSION_IS_4_1
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
VALUE sws_untyped_wrap_struct(VALUE self, VALUE val) {
@@ -113,6 +114,7 @@ VALUE sws_untyped_wrap_struct(VALUE self, VALUE val) {
*data = FIX2INT(val);
return Data_Wrap_Struct(rb_cObject, NULL, free, data);
}
+#endif
VALUE sws_typed_get_struct(VALUE self, VALUE obj) {
struct sample_typed_wrapped_struct* bar;
@@ -173,9 +175,11 @@ VALUE sws_typed_rb_check_typeddata_different_type(VALUE self, VALUE obj) {
return rb_check_typeddata(obj, &sample_typed_wrapped_struct_other_data_type) == DATA_PTR(obj) ? Qtrue : Qfalse;
}
+#ifndef RUBY_VERSION_IS_4_1
VALUE sws_typed_RTYPEDDATA_P(VALUE self, VALUE obj) {
return RTYPEDDATA_P(obj) ? Qtrue : Qfalse;
}
+#endif
void Init_typed_data_spec(void) {
VALUE cls = rb_define_class("CApiAllocTypedSpecs", rb_cObject);
@@ -183,7 +187,9 @@ void Init_typed_data_spec(void) {
rb_define_method(cls, "typed_wrapped_data", sdaf_typed_get_struct, 0);
cls = rb_define_class("CApiWrappedTypedStructSpecs", rb_cObject);
rb_define_method(cls, "typed_wrap_struct", sws_typed_wrap_struct, 1);
+#ifndef RUBY_VERSION_IS_4_1
rb_define_method(cls, "untyped_wrap_struct", sws_untyped_wrap_struct, 1);
+#endif
rb_define_method(cls, "typed_get_struct", sws_typed_get_struct, 1);
rb_define_method(cls, "typed_get_struct_other", sws_typed_get_struct_different_type, 1);
rb_define_method(cls, "typed_get_struct_parent", sws_typed_get_struct_parent_type, 1);
@@ -194,10 +200,11 @@ void Init_typed_data_spec(void) {
rb_define_method(cls, "rb_check_typeddata_same_type", sws_typed_rb_check_typeddata_same_type, 1);
rb_define_method(cls, "rb_check_typeddata_same_type_parent", sws_typed_rb_check_typeddata_same_type_parent, 1);
rb_define_method(cls, "rb_check_typeddata_different_type", sws_typed_rb_check_typeddata_different_type, 1);
+#ifndef RUBY_VERSION_IS_4_1
rb_define_method(cls, "RTYPEDDATA_P", sws_typed_RTYPEDDATA_P, 1);
+#endif
}
#ifdef __cplusplus
}
#endif
-
diff --git a/spec/ruby/optional/capi/typed_data_spec.rb b/spec/ruby/optional/capi/typed_data_spec.rb
index 8eaf7751ba..376cfe417f 100644
--- a/spec/ruby/optional/capi/typed_data_spec.rb
+++ b/spec/ruby/optional/capi/typed_data_spec.rb
@@ -86,15 +86,17 @@ describe "CApiWrappedTypedStruct" do
end
end
- describe "RTYPEDDATA_P" do
- it "returns true for a typed data" do
- a = @s.typed_wrap_struct(1024)
- @s.RTYPEDDATA_P(a).should == true
- end
+ ruby_version_is ""..."4.1" do
+ describe "RTYPEDDATA_P" do
+ it "returns true for a typed data" do
+ a = @s.typed_wrap_struct(1024)
+ @s.RTYPEDDATA_P(a).should == true
+ end
- it "returns false for an untyped data object" do
- a = @s.untyped_wrap_struct(1024)
- @s.RTYPEDDATA_P(a).should == false
+ it "returns false for an untyped data object" do
+ a = @s.untyped_wrap_struct(1024)
+ @s.RTYPEDDATA_P(a).should == false
+ end
end
end
end
diff --git a/test/json/json_ryu_fallback_test.rb b/test/json/json_ryu_fallback_test.rb
index 152de7e360..a61b3e668d 100644
--- a/test/json/json_ryu_fallback_test.rb
+++ b/test/json/json_ryu_fallback_test.rb
@@ -179,5 +179,13 @@ class JSONRyuFallbackTest < Test::Unit::TestCase
assert_equal(-0.0, JSON.parse("-99999999999999999e-4294967296"))
assert_equal(-Float::INFINITY, JSON.parse("-1e4294967295"))
assert_equal(-Float::INFINITY, JSON.parse("-1e4294967297"))
+
+ assert_equal(Float::INFINITY, JSON.parse("1e9223372036854775808"))
+ assert_equal(Float::INFINITY, JSON.parse("1e9999999999999999999"))
+ assert_equal(Float::INFINITY, JSON.parse("1e18446744073709551616"))
+ assert_equal(Float::INFINITY, JSON.parse("1e10000000000000000000"))
+ assert_equal(Float::INFINITY, JSON.parse("1e184467440737095516160"))
+ assert_equal 0.0, JSON.parse("1e-18446744073709551615")
+ assert_equal 0.0, JSON.parse("1e-9223372036854775809")
end
end
diff --git a/test/rubygems/test_gem_safe_yaml.rb b/test/rubygems/test_gem_safe_yaml.rb
index ce2c690fc1..8d0ac63c41 100644
--- a/test/rubygems/test_gem_safe_yaml.rb
+++ b/test/rubygems/test_gem_safe_yaml.rb
@@ -138,7 +138,11 @@ class TestGemSafeYAML < Gem::TestCase
depth = Gem::YAMLSerializer::Parser::MAX_NESTING_DEPTH + 1
yaml = "x: " + ("[" * depth) + "a" + ("]" * depth) + "\n"
- assert_raise(Psych::SyntaxError) do
+ expected = [Psych::SyntaxError]
+ # JRuby's JVM stack overflows before the Ruby-level nesting cap fires.
+ expected << ::Java::JavaLang::StackOverflowError if RUBY_ENGINE == "jruby"
+
+ assert_raise(*expected) do
Gem::YAMLSerializer.load(yaml, permitted_classes: [])
end
end
diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs
index dad29087be..f6f43fd5e2 100644
--- a/zjit/src/cruby_bindings.inc.rs
+++ b/zjit/src/cruby_bindings.inc.rs
@@ -347,7 +347,6 @@ pub const RUBY_TYPED_FREE_IMMEDIATELY: rbimpl_typeddata_flags = 1;
pub const RUBY_TYPED_EMBEDDABLE: rbimpl_typeddata_flags = 2;
pub const RUBY_TYPED_FROZEN_SHAREABLE: rbimpl_typeddata_flags = 256;
pub const RUBY_TYPED_WB_PROTECTED: rbimpl_typeddata_flags = 32;
-pub const RUBY_TYPED_FL_IS_TYPED_DATA: rbimpl_typeddata_flags = 64;
pub const RUBY_TYPED_DECL_MARKING: rbimpl_typeddata_flags = 16384;
pub type rbimpl_typeddata_flags = u32;
pub type rb_event_flag_t = u32;