I think it should work the other way around. When you want to be able to use proxies everywhere (which can't work btw, because everywhere is just too vague), there should be a switch - a preference with an action - that recompiles all methods with the #== and #class bytescodes disabled except for those methods which have a special pragma preventing such deoptimization.
+1 on the idea; there are a few implementation choices
Guys, your aggressive imagination for how far you could go to to build out "ultimate transparency" is fun, but recompiling the users entire image? So every package in the users image is suddenly dirty then? Maybe I've misunderstood the the idea, but it seems unworkable. What about development while connected to the DB? When a developer changes a method after the recompile, when will it get recompiled again to ignore those bytecodes? What about when I actually want the Proxy's class itself? Plus, like Eliots suggestion, it's only class-specific instead of instance-specifc, so it slows things down even where it didn't need to.
As I'm sure you're aware, singularly pursuing one goal in a complex system can easily and unwittingly knock down other useful and necessary aspects of the system.
Why can't we simply let #privClass be the inlined message and #class return "self privClass"? Then, if we will stop writing code that makes assumptions about implementations everywhere by using #== or an IdentityDictionary's because "I know I'm dealing with a Symbol, so make it 1% faster!!" It seems like these obsessions with optimization have reached a feverish level its becoming detrimental. If we're supposed to be OO masters, delegation to #= and letting it inherit the one in Object is the more proper way to write that.
Besides which, sending inlined messages to a Proxy isn't the whole of the story, there is also the issue of when a Proxy object (with named pointers) gets passed as an argument to a primitive that expects a different class-type (e.g., a Proxy to some Form bytes or something). Magma deals with this by compiling a subclass and generating overrides of all methods with primitive sends. It overrides #xxxClass (which I would be more than happy to rename!) so that equivalence COULD work, if only we had a wrapping message. Like my idea about #privClass...
I'm surprised you didn't mention other special methods like #ifTrue:, #whileTrue:, #repeat:, #to:do:, etc. I think that's because you rarely create proxies for numbers, booleans and blocks.
+1. Again see Marcus’ super cool reification of inlined blocks in Pharo, even if it is slooooow :-)
Then there's no point in my looking at it. I'm seeking a reasonable balance of trade-offs and speed is one I need to keep. This is not just a learning experiment or school project, but real apps for human end users and developers.
Best, Chris
- Chris