Re: [fpc-devel] (ref types / circles) Re: Defer keyword

2021-05-08 Thread Ryan Joseph via fpc-devel


> On May 8, 2021, at 7:59 AM, Sven Barth via fpc-devel 
>  wrote:
> 
> It has the exact same problems that my branch had (especially the interaction 
> of reference counted instances with non-reference counted ones).
> 
> Using a variable/parameter/field based approach (like the idea with managed 
> records and default fields) is the more flexible one compared to the type or 
> instance based one and thus it's more favorable.

I still don't understand how the record approach is that much different from a 
managed class type which calls the same set of management operators.  Can we 
make a pros-cons list to clear this up and give an example of "especially the 
interaction of reference counted instances with non-reference counted ones"?

Here's the most recent things we brought up:

- Records can't be cast in a way that would break reference counting (like a 
managed class being cast to TObject would).
- Generic records would create a proliferation of new types for all classes you 
wanted managed, so instead of using TFPGList you're using 
TManagedSomeObjectList or TManaged>, or worse yet 
"specialize TManaged>"

Otherwise the same set of circular references exists but I'm not sure about 
your concern about mixing managed types yet.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-08 Thread Ryan Joseph via fpc-devel


> On May 8, 2021, at 8:05 AM, Sven Barth  wrote:
> 
>> a := TArray.Create([1,2,3]).AutoRelease;
>> 
>> We can't do this in Pascal because the AutoRelease functions return type is 
>> not compatible with the type of the caller. Could we add something like an 
>> "Any" return type to Pascal which is a type that is compatible with any 
>> class? This relies on an event loop that can capture this garbage and 
>> dispose of it but it goes a LONG way in helping with common memory 
>> management problems.
> 
> Dynamic arrays are reference counted, thus you don't need to do any manual 
> memory management on them.

That was a bad example. It's for ANY class really.

o := TObject.Create.AutoRelease;

Then next event cycle the autorelease pool frees all the objects added to it. 
Very simple but effective however we can't do this in Pascal without a new 
permissive return type. 

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-08 Thread Sven Barth via fpc-devel

Am 22.04.2021 um 17:52 schrieb Ryan Joseph via fpc-devel:



On Apr 16, 2021, at 11:35 AM, Ryan Joseph  wrote:

Got this all integrated and put up the changes to 
https://bugs.freepascal.org/view.php?id=35261. Now I'm waiting for another 
final review. :)

The next thing to do now is to handle a memory leak. From the bug tracker:


You essentially need to make sure the symbols become part of the specialization 
that is picked in the end (cause you create the symbols in make_param_list only 
once, but you might use them for multiple generic overloads of which at most 
one will be picked).
What you might be able to do is the following (have not looked at it in detail 
yet):
- those symbols you directly add to genericparams you ensure that their owner 
is the specialization right away (after generate_specialization_phase1)
- those symbols you add to callerparams you'll probably have to bubble up to 
htypechk and have that somehow add these syms to the final specialization if it 
is picked and free them otherwise


My response:


I looked at this again and it looks like there is just one place where we can 
leak memory now and that's those lines from create_unamed_typesym.

   newtype:=ctypesym.create(def.typename,def);
   newtype.owner:=def.owner;

I set the owner of the new typesym to the target def but what does that even 
do? I think you're saying I need to set the owner of that symbol to be a 
procdef but I don't see how the helps the memory get freed. I would think when 
the specialization is freed we could check some flag in the generic params and 
if they are not owned then we free them then.

And with that I'm stuck. :) I don't know how the symbols in the compiler are memory 
managed but I don't see setting their owner is helping them get freed. I've tried setting 
their owner to the procdef.owner being specialized but that does't do anything either. I 
guess I don't understand what adding them to "the final specialization" means 
so please clarify.

My naive assumption would be to add them to a list in tspecializationcontext 
and free them when the content is freed because I don't think the symbols are 
used after the implicit specialization is finished and a proc def is produced, 
but I may be wrong about that.


You need to use ChangeOwner as well, but as I wrote you need to pay 
attention for which created symbol you do it at what time.


The ones you create in is_possible_specialization you need to add to the 
specialization you do in the following generate_implicit_specialization 
as those are only created for that specific specialization (though you 
also need to free it if you leave is_possible_specialization with False 
which you currently don't do).


The ones you create in make_param_list you need to pass back to htypechk 
so that they can either be added to the final specialization (if 
selected out of multiple ones) or to be freed if none of the ones 
created by that invocation to try_implicit_specialization is picked. 
That is because they would be shared by all the specializations.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] (ref types / circles) Re: Defer keyword

2021-05-08 Thread Sven Barth via fpc-devel

Am 08.05.2021 um 18:23 schrieb Ryan Joseph via fpc-devel:



On May 8, 2021, at 7:59 AM, Sven Barth via fpc-devel 
 wrote:

It has the exact same problems that my branch had (especially the interaction 
of reference counted instances with non-reference counted ones).

Using a variable/parameter/field based approach (like the idea with managed 
records and default fields) is the more flexible one compared to the type or 
instance based one and thus it's more favorable.

I still don't understand how the record approach is that much different from a managed 
class type which calls the same set of management operators.  Can we make a pros-cons 
list to clear this up and give an example of "especially the interaction of 
reference counted instances with non-reference counted ones"?

Here's the most recent things we brought up:

- Records can't be cast in a way that would break reference counting (like a 
managed class being cast to TObject would).
- Generic records would create a proliferation of new types for all classes you wanted managed, so instead of using 
TFPGList you're using TManagedSomeObjectList or TManaged>, or 
worse yet "specialize TManaged>"

Otherwise the same set of circular references exists but I'm not sure about 
your concern about mixing managed types yet.
It's not about reference counted classes vs. managed records, but about 
whether it's *per type* or *per variable*, the implementation details 
are completely irrelevant for now.


And the problems are assigning a reference counted class instance to a 
non-reference counted variable or parameter. Also casting such a 
reference counted class to a non-reference counted one (e.g. to 
TObject). Allowing these kind of operations would either need to be 
forbidden which would restrict the usability of such classes or they 
could potentially lead to memory leaks or premature freeing. Not to 
mention how calling the destructor would react if the reference count 
isn't 0.


By using a mechanism based on the variable/field/parameter type you have 
a much more fine grained control and if one leaves out the implicit 
assignment from the wrapped class type to the non-wrapped one then one 
needs to do an explicit conversion.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-08 Thread Sven Barth via fpc-devel

Am 06.05.2021 um 17:33 schrieb Ryan Joseph via fpc-devel:

I found something sneaky I'd like to confirm before I decide what to do about 
it.

1) "T" in TAnyClass is specialized as Integer from the first parameter with 
TSomeClass (which is TAnyClass).
2) "U" is getting specialized as String by looking at the parameters in Compare() in 
which "U"(the second generic parameter) is String.

This specializes the procedure correctly but it uses a very sneaky method which is very hard to 
discern. I feel like that if a generic parameter is already used (like T in specialize 
TCallback) then no further attempt should be made to look at the parameters and in 
the example below "U" would not be found and the function would fail to implicitly 
specialize.
There is nothing sneaky if one defines that the parameters are evaluated 
left to right and those that are already found and used later on (like 
T) are simply fixed then thus in the example it uses the already found 
type. But if the picked type wouldn't mach, for example if TCallback<,> 
would be declared as TCallback instead then trying to 
specialize the function would simply fail.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] (ref types / circles) Re: Defer keyword

2021-05-08 Thread Ryan Joseph via fpc-devel


> On May 8, 2021, at 11:18 AM, Sven Barth  wrote:
> 
> It's not about reference counted classes vs. managed records, but about 
> whether it's *per type* or *per variable*, the implementation details are 
> completely irrelevant for now.

So the biggest concern you see if that classes are easier to assign to 
non-reference counted classes? The only difference between classes and records 
in this regard is that records give errors unless you assign directly to the 
same record type, where classes can be assigned to super-classes which may not 
be managed.

As you say there would need to be at least a warning if you cast a managed 
class to another class type or make it forbidden completely. I don't see that 
as a deal breaker personally but you seem to feel pretty strongly about it.

Anyways I wrote up a little wiki with some potential implementation notes about 
a default property (which overlaps on the "defaults implements" as traits 
stuff). Important points are restricting what types can be default properties 
(classes and maybe/probably typed pointers) and limiting hoisting to 
subscripting, so it's kind of like the -> operator overload in C++.

https://github.com/genericptr/freepascal/wiki/Default-property

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-08 Thread Ryan Joseph via fpc-devel


> On May 8, 2021, at 12:04 PM, Sven Barth  wrote:
> 
> You need to use ChangeOwner as well, but as I wrote you need to pay attention 
> for which created symbol you do it at what time.

Ok, maybe this is what I got wrong didn't use ChangeOwner. When you say "add 
to" what exactly do you mean? Please post a single line code snippet even. 
Thanks.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-08 Thread Jonas Maebe via fpc-devel
On 07/05/2021 07:26, Sven Barth via fpc-devel wrote:
> Trunk also supports POSIX exceptions on selected *nix based systems,
> though I haven't looked in depth yet in how far they incur a runtime
> penalty (also they need to be enabled by enabling them in the compiler
> and then recompiling everything, cause they're still experimental).

They're not POSIX, but DWARF-EH. They don't incur any cost except if an
exception is triggered (but then the cost is quite high).

They're also the only supported exception type when using the LLVM
backend (which is why adding Windows-support is more work than adding
support for other platforms to the LLVM backend, as even at the LLVM IR
level Windows exceptions are modeled differently).


Jonas
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-08 Thread Jonas Maebe via fpc-devel
On 07/05/2021 18:41, Ryan Joseph via fpc-devel wrote:
> Does that mean if you disable implicit exceptions then ALL ref counted types 
> leak memory?

Only if an exception occurs.


Jonas
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] (ref types / circles) Re: Defer keyword

2021-05-08 Thread Sven Barth via fpc-devel

Am 07.05.2021 um 23:16 schrieb Ryan Joseph via fpc-devel:



On May 7, 2021, at 2:52 PM, Sven Barth  wrote:

As said the main problem of reference counting on object instances, especially 
if enabled by default like the Delphi NextGen compiler did, will lead to 
problems in *existing* code and thus is a no-go.


What did you think about me other email that had ideas to add compiler directives like 
$M+? The way record management operators are implemented is that if you include any of 
the operators then the type becomes "managed" in the same way other ref counted 
types are handled.

For classes this is different because there is a hierarchy which is now altered 
but the compiler could still insert a hidden super class above it and use that 
to store the extra data. Indeed this would mean that existing classes (like the 
RTL) would not be eligible for reference counting unless it was compiled using 
said directive.

For example the follow class:

{$RETAINED+}
type
  TMyObject = class(TBaseClass)
  end;
{$RETAINED-}

would become:

type
  TMyObject_RefCounted = class abstract(TBaseClass)
   strict private
 refCount: LongInt;
  end;
  TMyObject = class(TMyObject_RefCounted)
  end;

and now "TMyObject" is a managed type and Initialize/Finalize/AddRef/Copy will 
be called. It occurs to me now though that the ref counting would be tied to the type so 
if you cast the class to TObject and passed it around then ref counting wouldn't happen. 
Not sure if that's a deal breaker or not but it could easily cause hard to fix memory 
leaks just like normal classes. :)


It has the exact same problems that my branch had (especially the 
interaction of reference counted instances with non-reference counted ones).


Using a variable/parameter/field based approach (like the idea with 
managed records and default fields) is the more flexible one compared to 
the type or instance based one and thus it's more favorable.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-08 Thread Sven Barth via fpc-devel

Am 07.05.2021 um 17:40 schrieb Benito van der Zander via fpc-devel:
The introduction of generics and their abundant use in Delphi has 
noticably slowed down the compiler and increased binary sizes. To my 
dismay, compile times of 20 seconds up to 2 minutes have become not 
uncommon in Delphi. Something almmost unthinkable in D7 days. 


With these generics they copied all the problems of C++. One of the 
worst ways of doing that


It would have been better to implement them like dynamic arrays. The 
generic code gets RTTI, the specialization does not generate any code, 
and just avoids explicit casting.


That would also be a much less flexible approach. The way it is now 
allows for much more functionality to be covered with generics.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-08 Thread Sven Barth via fpc-devel

Am 07.05.2021 um 17:57 schrieb Ryan Joseph via fpc-devel:



On May 7, 2021, at 2:46 AM, Sven Barth via fpc-devel 
 wrote:

I cannot speak for others, but I think 90% of potential use cases for ref 
counting
would be covered like this in my code: objects that only live inside a
procedure.

I think the same.

There's also a function which returns dynamically allocated memory but doesn't intend for you to 
keep it around very long. Cocoa/Objective-C has a good system for this which is an 
"autorelease pool" and while it's not language construct but rather a runtime system it 
does rely on an "Any" type (called id in Objective-C) so that methods can be chained 
together  like this:

a := TArray.Create([1,2,3]).AutoRelease;

We can't do this in Pascal because the AutoRelease functions return type is not 
compatible with the type of the caller. Could we add something like an "Any" 
return type to Pascal which is a type that is compatible with any class? This relies on 
an event loop that can capture this garbage and dispose of it but it goes a LONG way in 
helping with common memory management problems.


Dynamic arrays are reference counted, thus you don't need to do any 
manual memory management on them.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel