Freeze singleton class chain#10245
Conversation
f4f8f51 to
ff2b943
Compare
Right, by "shared singleton class" that's actually only internal CRuby state, i.e., before the singleton class of that class has been needed (e.g. by calling I think it this is a good way to fix the inconsistency shown in https://bugs.ruby-lang.org/issues/20319 |
The following code: ```ruby x = Object.new sc1 = x.singleton_class sc2 = sc1.singleton_class x.freeze ``` Would freeze sc1 but not sc2, even though sc1 would be frozen. Handle this by walking the class pointer chain for the object. If the class is a singleton class, and it isn't frozen, and the attached object for the singleton class is the object, the singleton class should be frozen, and we move to the next iteration. Fixes [Bug #20319]
ff2b943 to
ab8c431
Compare
|
I came up with a revised algorithm for this, which is O(N) instead of O(N^2), where N is the depth of the singleton class chain. Instead of going all the way down the chain back to the original frozen object in every level, we only need to check at each level that the object's class pointer is the singleton class for the current object, by checking the attached object for that class matches. Previously, I wasn't sure about whether the code was correct in all cases. I'm now fairly confident that it is. I've expanded the tests as well. @nobu when you have time, could you please rereview? |
The following code:
Would freeze sc1 but not sc2, even though sc1 would be frozen.
Not freezing the entire singleton class chain is expected, because at a certain point, the singleton class is shared. However, you can walk the the attached object chain for each singleton class, and only freeze if it results in the original object. This way, only non-shared singleton classes are frozen.
Fixes [Bug #20319]