summaryrefslogtreecommitdiff
path: root/class.c
diff options
context:
space:
mode:
authorYusuke Endoh <mame@ruby-lang.org>2021-11-05 09:36:44 +0900
committerYusuke Endoh <mame@ruby-lang.org>2021-11-09 16:11:10 +0900
commit64007fc57f360eab4b18b26389719a85f45b25c3 (patch)
tree849f02c825aa3b3010f8da025cb335a2b29600ad /class.c
parent037da5066619e083b4770dc97cf6435892e2bebe (diff)
class.c (Class#descendants): Ingore subclasses created after estimation
It is theoretically possible if a finalizer creates a subclass.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5070
Diffstat (limited to 'class.c')
-rw-r--r--class.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/class.c b/class.c
index fc79c415b3..a22bb756a5 100644
--- a/class.c
+++ b/class.c
@@ -1340,6 +1340,7 @@ struct subclass_traverse_data
{
VALUE *buffer;
long count;
+ long maxcount;
};
static void
@@ -1348,7 +1349,7 @@ class_descendants_recursive(VALUE klass, VALUE v)
struct subclass_traverse_data *data = (struct subclass_traverse_data *) v;
if (BUILTIN_TYPE(klass) == T_CLASS && !FL_TEST(klass, FL_SINGLETON)) {
- if (data->buffer) {
+ if (data->buffer && (data->count < data->maxcount || data->maxcount == -1)) {
data->buffer[data->count] = klass;
}
data->count++;
@@ -1377,13 +1378,14 @@ class_descendants_recursive(VALUE klass, VALUE v)
VALUE
rb_class_descendants(VALUE klass)
{
- struct subclass_traverse_data data = { NULL, 0 };
+ struct subclass_traverse_data data = { NULL, 0, -1 };
// estimate the count of subclasses
rb_class_foreach_subclass(klass, class_descendants_recursive, (VALUE) &data);
// this allocation may cause GC which may reduce the subclasses
data.buffer = ALLOC_N(VALUE, data.count);
+ data.maxcount = data.count;
data.count = 0;
// enumerate subclasses