3

Calling ObjectSpace.each_object(Class) does not seem to return any eigenclasses. For example, when investigating Ruby metaclasses: why three when defined singleton methods?, I found that while ObjectSpace.count_objects[:T_CLASS] was getting incremented by 3 in the case of defining a new class with a class method, ObjectSpace.each_object(Class).count was only being incremented by one.

Is there any way to enumerate the eigenclasses active in the system?

Community
  • 1
  • 1
Peter Alfvin
  • 28,599
  • 8
  • 68
  • 106

1 Answers1

2

Looking at MRI C code, the function ObjectSpace.each_object tests if the object is an internal object and if it is true the object is removed from the iterator.

The test is made by the following function, which consider the classes internally flagged as singleton as an internal object:

static int
internal_object_p(VALUE obj)
{
    RVALUE *p = (RVALUE *)obj;

    if (p->as.basic.flags) {
    switch (BUILTIN_TYPE(p)) {
      case T_NONE:
      case T_ICLASS:
      case T_NODE:
      case T_ZOMBIE:
        break;
      case T_CLASS:
        if (FL_TEST(p, FL_SINGLETON)) /* Here */
          break;
      default:
        if (!p->as.basic.klass) break;
        return 0;
    }
    }
    return 1;
}

The Ruby EigenClasses are flagged as Singleton, so it will be not returned.

It is important to mention that, the singleton flag used internally by the MRI is different from the Singleton module from standard library.

If you create a class and include the Singleton module on it, it will be returned by the ObjectSpace.each_object method.

Thiago Lewin
  • 2,810
  • 14
  • 18
  • +1 for sharing the code that is implementing this filtering in `each_object`, but still wondering if there is any way to enumerate these. – Peter Alfvin Nov 09 '13 at 06:31
  • Looking at Ruby code we can say that there is no possibility to access the EigenClasses using the `ObjectSpace.each_object` function. – Thiago Lewin Nov 10 '13 at 20:31
  • Sorry, I just adjusted the title to match the actual question (in the last sentence of the body), which is broader than `ObjectSpace`. I'm guessing that may be "no" as well, but hope springs eternal. Worst case, I should be able to create/add an ObjectSpace2 which doesn't have the filter, right? – Peter Alfvin Nov 10 '13 at 20:45
  • Yes, it is possible to create a Ruby C extension that removes the filter. It's better to copy the code of `ObjectSpace`, that is located on `gc.c` file, and remove the test `if (FL_TEST(p, FL_SINGLETON)) ...`, since there are some trick calls. – Thiago Lewin Nov 10 '13 at 21:26