Avoiding Copy Operations for Managed Records
This is an alternative to !861 (closed). For a rational behind this, see the old MR. This MR, instead of adding a new user defined management operator, handles the move operation transparently.
Basically when assigning a value from a temporary variable, such as the function return, the compiler will not perform a full copy using the COPY management operator, but instead do a transparent move. The move operation is basically implemented as:
procedure MoveManaged(var src, dst);
begin
{ Will be overwritten, so "clear" it first }
Finalize(dst);
{ Overwrite with new data }
Move(src,dst,sizeof(dst));
{ So when src is destroyed it does not finalize
the data, clear without finalization }
Initialize(src);
end;
For example, applied to dynamic arrays, what would happen is that first the refcount in the dynamic array referenced by dst is decreased, then the pointer of dst will be changed to point to the data from src, and then src will be overwritten with nil to ensure that when it is freed, the data dst now points to is not freed.
With this change, now the assignment of function results will not trigger copy operations, but only this more efficient move operation.
In addition to this change, two new functions are added to the RTL (SysUtils unit), Extract and Swap.
Extract will take the data from one object and move it into the function result. This allows moving data from one variable to another without triggering copy operations:
myrec := specialize Extract<TMyRec>(oldrec);
How it works is basically by performing the move operation described above manually. The function result of Extract then will be a temporary object and the assignment will not trigger another copy operation. So taking the example of a dynamic array again, after Extract, oldrec will be nil, myrec will be oldrec, without ever touching the reference counter of oldrec.
The other function Swap, will swap to variables, without involvement of any management operations.