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
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.
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
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.