The problem
In a recent blog post, Dalija Prasnikar talks about how hard it would be to optimize ARC code,
because most ARC object references will be passed by value, but not as const
. Passing as const
would
eliminate the need for an implicit __ObjAddRef()
call each time the object is passed (and an __ObjRelease()
call when the routine
with the parameter ends).
OK, ARC (automatic reference counting) has been used for many types already, most of
all strings, dynamic arrays and interfaces. Code passing strings and dynarrays is generally
optimized already, by specifying such parameters as const
. There are probably only a few exceptions.
It is also customary to do it with interfaces, and the few exceptions probably don't make a big
difference in performance. But it is far from customary to do this for objects. Until ARC, it
didn't matter if you passed an object as const
or not. But these days, in ARC, it can make a big
difference. And objects are passed around a lot, e.g. the Sender
parameter of events, etc.
Note that most runtime and FMX code doesn't use const
to pass objects either, nor do any of the
third parties. Dalija notes that it is not hard to add const
to each object parameter, but that it would
break huge amounts of code, not only Embarcadero's, but everyone's.
Switch?
I read that and have been thinking about it a little. I first thought of introducing a switch
(sound familiar?) in the new ARC compilers, that would make const
optional and reduce compiler
complaints about interface changes, to make this transition easier. But that would still
require a huge amount of code changes, even if it could perhaps be done at a slower pace.
Const by default?
But then I thought of something else. If an object is passed as call-by-value, to a method or function, inside that method or function, you very seldom change the reference by assigning a new object to it. In other words, inside such a method or function, you hardly ever do something like:
ObjectParam.Free; // necessary in non-ARC, optional in ARC ObjectParam := TSomeObject.Create;
Yes, you often change the state of the object by setting properties or by calling methods, but that can
be done on a const
reference as well. Const
means you can't change the reference,
not that you can't change the state of the object it refers to.
For almost all practical purposes, such objects passed can be treated as if they were passed as
const
already. So it would perhaps make sense, in a new version of the ARC compilers, to treat
every pass-by-value as const
. This would make the code compatible with
the non-ARC compilers, while still avoiding a truckload of reference counting calls. This would
probably optimize ARC code quite a lot. Of course code already using const
would be
compatible too. And it would not apply to code using var
or out
, only to plain
pass-by-value object reference parameters.
And the very few methods that do actually re-use a parameter like above should simply be rewritten to use a (new) local variable for the new object. I doubt there is lot of code that does this anyway, so this change would not break a lot of code at all.
So making all passed-by-value objects const
by default would probably break very little code, and
optimize a lot of ARC code. It would not affect non-ARC code.
As for the old compilers: they would remain non-optimized, but their code would not have to be changed. A simple recompile (and the occasional change) would suffice.
I'd love to hear about your thoughts.