Guys, it looks like i found an elegant solution.
Please check the new-finalization-auto.2.cs, which i uploaded to http://bugs.squeak.org/view.php?id=7473.
It adds just a few things:
initTestPair TestItem := WeakFinalizerItem new list: TestList object: Object new.
checkTestPair HasNewFinalization := TestList swapWithNil notNil.
These two method is then sent from within WeakArray's finalization process:
finalizationProcess [true] whileTrue: [ WeakFinalizationRegistry initTestPair. FinalizationSemaphore wait. FinalizationLock critical: [ WeakFinalizationRegistry checkTestPair. FinalizationDependents do: [:weakDependent | weakDependent ifNotNil: [weakDependent finalizeValues]]] ifError: [:msg :rcvr | rcvr error: msg]. ].
And so, at each GC cycle, a new registry it knows exactly if it allowed to do a shortcut, or not.
And if not, then it behaves in same way as old registry - it starts scanning the whole dictionary to clean graveyard.
So, in summary: running on older VMs , a WeakFinalizationRegistry will behave exactly as old WeakRegistry. While on VMs, which supporting new finalization, it will do a shortcut.
This is at cost of extra 2 objects, allocated per GC cycle, to detect if new finalization is supported.
P.S. oops, actually it could be just one object.. just need to change two methods at WeakFinalizationRegistry class side:
initialize TestList := WeakFinalizationList new. TestItem := WeakFinalizerItem new.
initTestPair TestList swapWithNil. "make sure list is empty" TestItem list: TestList object: Object new.