Re: [fpc-devel] Defer keyword
On 5/11/2021 4:09 AM, Ryan Joseph via fpc-devel wrote: On May 10, 2021, at 5:59 PM, Kostas Michalopoulos via fpc-devel wrote: You do not need any special language feature for that, you can simply do something like ReleaseLater(TObject.Create) yes but we can't get back the reference. It's a small thing but making this possible as return type means we can chain the calls together and make it a one line statement. It's just a nice thing from Objective-C which we use heavily to manage memory and it works very well. How about function ReleaseLater(Obj: TObject): TObject that simply returns Obj? (though TBH i can't say i am a fan of these chains from a readability perspective). Kostas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] Defer keyword
> On May 10, 2021, at 5:59 PM, Kostas Michalopoulos via fpc-devel > wrote: > > You do not need any special language feature for that, you can simply do > something like > >ReleaseLater(TObject.Create) yes but we can't get back the reference. It's a small thing but making this possible as return type means we can chain the calls together and make it a one line statement. It's just a nice thing from Objective-C which we use heavily to manage memory and it works very well. 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
On 5/8/2021 8:27 PM, Ryan Joseph via fpc-devel wrote: 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. You do not need any special language feature for that, you can simply do something like ReleaseLater(TObject.Create) and have ReleaseLater and ReleaseQueuedObjects procedures in a shared unit like procedure ReleaseLater(Obj: TObject); procedure ReleaseQueuedObjects; and have ReleaseQueuedObjects called on app idle. LCL already has something like that with TApplication.ReleaseComponent but, as the name implies, it is only for TComponent instances. However nothing prevents you from making your own, it is just a few lines of code and certainly an app with flow complex enough to need such a construct wont be bothered by a few additional lines for this. You could even use type helpers to make it look like a method :-P. Kostas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] Defer keyword
> 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] Defer keyword
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
Re: [fpc-devel] Defer keyword
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
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
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
[fpc-devel] Defer keyword
07.05.2021, 06:09, "Michael Van Canneyt via fpc-devel" :On Fri, 7 May 2021, Sven Barth via fpc-devel wrote: I thought it was agreed at the time that this was the most viable way forward ? As far as I remember there wasn't really any agreement.Can be, I was not sure... I remember this path was investigated. IIRC there was also the proposal that this could be done automatically using a keyword: varSomeClass : TSomeClass; dispose; The compiler can internally create the management record with a single default field and the needed management operator, so the user does not need to create all that. I'm not aboard with such a keyword. The compiler should provide the necessary language mechanisms (default field, operator hoisting) and then there should be a default implementation as part of the RTL. There is no need to hide this behind a keyword, attribute or whatever.There is:Using a keyword, the compiler could also optimize things by simply initializingand freeing the instance if the usage of the object in the procedure allows it;it would allow to skip the record and operators and whatnot.I'm not proposing to abolish the record approach, just an additional automatismthat will use it, but allows to skip it for simple enough cases which areprobably the largest use-case.Don't forget that the record/management operator approach will again blow upbinary size; for every variable declared like this you risk creating a new type.The introduction of generics and their abundant use in Delphi has noticablyslowed down the compiler and increased binary sizes.To my dismay, compile times of 20 seconds up to 2 minutes have become notuncommon in Delphi. Something almmost unthinkable in D7 days.If that can be avoided by use of a keyword for 90% of use cases,I think it is worth thinking about it and not dismissing it offhand.Michael.___fpc-devel maillist - fpc-devel@lists.freepascal.orghttps://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-develI would love to see defer keyword in free pascal, but i think that at some degree we already can emulate it, see: program project2; {$mode objfpc}{$modeswitch advancedrecords} type TDeferedProc = procedure of object; TDefer = record fProc: TDeferedProc; public procedure Enqueue(aProc: TDeferedProc); class operator finalize(var aDefered: TDefer); end; { TSampleObj1 } TSampleObj1 = class procedure Echo; destructor Destroy; override; end; TSampleObj2 = class(TSampleObj1); function Defer: TDefer;begin Result.fProc:= nil;end; { TDefer } procedure TDefer.Enqueue(aProc: TDeferedProc);begin fProc:= aProc;end; class operator TDefer.finalize(var aDefered: TDefer);begin aDefered.fProc();end; { TSampleObj1 } procedure TSampleObj1.Echo;begin WriteLn('Echo from ', ClassName);end; destructor TSampleObj1.Destroy;begin Writeln('Freeing ', ClassName); inherited;end; procedure MyProc;var Obj1: TSampleObj1; Obj2: TSampleObj2;begin Obj1:= TSampleObj1.Create; Obj2:= TSampleObj2.Create; WriteLn('Objects created'); Defer.Enqueue(@Obj1.Free); Defer.Enqueue(@Obj2.Free); WriteLn('Objects freed defered'); Obj1.Echo; Obj2.Echo; WriteLn('End of MyProc');end; begin MyProc;end. -- Luis Lima___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] Defer keyword
> On May 6, 2021, at 11:40 PM, Sven Barth wrote: > > There is no "finalization" section. It's really just an implicit try ... > finally block that the compiler inserts. Look for "cs_implicit_exceptions" > and "pi_needs_implicit_finally" if you want to learn more. Does that mean if you disable implicit exceptions then ALL ref counted types leak memory? I could swear there was some post-routine code did all the cleanup stuff and called finalization* on different types. That's how record operators worked I thought and so i thought a defer keyword could simply hook into that system. >> Either way looking at the programming language landscape the better way >> forward seems to be some opt-in ARC for TObject but I don't know if the >> compiler team is receptive to that (Sven made some attempt years ago but >> abandoned it). it's kind of frustrating that we have ref counted types but >> that isn't extended to classes. Hopefully that's something we can tackle one >> of these days... > The problem is that the whole class tree needs to support it for it to work > correctly even if it's not the whole hierarchy that has as it enabled. That > means at least one additional field inside TObject that a) controls that > behavior and b) contains the reference count. This means that *all* class > instances increase by a LongInt. This might not sound like much, but FPC also > allows to work on smaller systems (and I don't mean the really small embedded > ones as those don't have TObject enabled anyway) and there an additional > LongInt for each instance might be critical. That can never be an option to blow up TObject. I figured there could be something like a $M+ switch that would compile a class with ref counting. Then in the RTTI units we would simply have an entry for this new class type which had initialize/finalize/addref etc... functions. I saw this for record operators and dynamic arrays so I thought the system could be extended to classes. > > If the reference count feature is optional (in addition to the above) then an > open question is what would happen if such a reference counted instance is > assigned to a non-reference counted one. This would need to take into account > all ways such an instance or type can be used including TClass. That doesn't sound like a problem to me but I haven't thought about it deeply. If it was confusing there could be a new var section to denote ARC objects: var someClass: TMyObject; retained someClass: TMyObject; begin end; {$RETAINED+} type TMyObject = class private someClass: TMyObject; public retained someClass: TMyObject; otherClass: TObject; // this would give an error because class is not compiled for ARC end; {$RETAINED-} 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
> On May 7, 2021, at 9:40 AM, Benito van der Zander via fpc-devel > wrote: > > the classic Delphi way was to use an interface for freeing. It only requires > one type and nothing blows up. > That's clever but even try..finally is less overhead. 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
> 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. 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
Hi, Don't forget that the record/management operator approach will again blow up binary size; for every variable declared like this you risk creating a new type. the classic Delphi way was to use an interface for freeing. It only requires one type and nothing blows up. type TDefer = class(TInterfacedObject) toDefer: TObject; constructor Create(anobject: tobject); destructor destroy; override; end; constructor TDefer.Create(anobject: tobject); begin toDefer := anobject; end; destructor TDefer.destroy; begin toDefer.free; inherited destroy; end; function deferedFree(obj: TObject): IUnknown; begin result := TDefer.Create(obj); end; Then it can be used as: procedure test; var sl: TStringList; begin sl := TStringList.Create; deferedFree(sl); writeln(sl.count); end; Unfortunately it fails in FreePascal because the interface is released too soon. At worst, one could use a temporary variable in Delphi: procedure test; var sl: TStringList; begin sl := TStringList.Create; var temp := deferedFree(sl); writeln(sl.count); end; 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. Cheers, Benito On 07.05.21 11:08, Michael Van Canneyt via fpc-devel wrote: On Fri, 7 May 2021, Sven Barth via fpc-devel wrote: I thought it was agreed at the time that this was the most viable way forward ? As far as I remember there wasn't really any agreement. Can be, I was not sure... I remember this path was investigated. IIRC there was also the proposal that this could be done automatically using a keyword: var SomeClass : TSomeClass; dispose; The compiler can internally create the management record with a single default field and the needed management operator, so the user does not need to create all that. I'm not aboard with such a keyword. The compiler should provide the necessary language mechanisms (default field, operator hoisting) and then there should be a default implementation as part of the RTL. There is no need to hide this behind a keyword, attribute or whatever. There is: Using a keyword, the compiler could also optimize things by simply initializing and freeing the instance if the usage of the object in the procedure allows it; it would allow to skip the record and operators and whatnot. I'm not proposing to abolish the record approach, just an additional automatism that will use it, but allows to skip it for simple enough cases which are probably the largest use-case. Don't forget that the record/management operator approach will again blow up binary size; for every variable declared like this you risk creating a new type. 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. If that can be avoided by use of a keyword for 90% of use cases, I think it is worth thinking about it and not dismissing it offhand. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] Defer keyword
> On May 7, 2021, at 3:08 AM, Michael Van Canneyt via fpc-devel > wrote: > > 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. Is it badly optimized or just overused? I don't have any way to compare but FPC seems pretty good with generics (Sven will know if there are any optimizations that could be made). Implicit function specialization will appear (at least at first) without any optimizations but I'll fix that later. > > If that can be avoided by use of a keyword for 90% of use cases, I think it > is worth thinking about it and not dismissing it offhand. I already raised the idea of an "auto" keyword some years ago already and it got rejected in favor of record operators. 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
On Fri, 7 May 2021, Sven Barth via fpc-devel wrote: I thought it was agreed at the time that this was the most viable way forward ? As far as I remember there wasn't really any agreement. Can be, I was not sure... I remember this path was investigated. IIRC there was also the proposal that this could be done automatically using a keyword: var SomeClass : TSomeClass; dispose; The compiler can internally create the management record with a single default field and the needed management operator, so the user does not need to create all that. I'm not aboard with such a keyword. The compiler should provide the necessary language mechanisms (default field, operator hoisting) and then there should be a default implementation as part of the RTL. There is no need to hide this behind a keyword, attribute or whatever. There is: Using a keyword, the compiler could also optimize things by simply initializing and freeing the instance if the usage of the object in the procedure allows it; it would allow to skip the record and operators and whatnot. I'm not proposing to abolish the record approach, just an additional automatism that will use it, but allows to skip it for simple enough cases which are probably the largest use-case. Don't forget that the record/management operator approach will again blow up binary size; for every variable declared like this you risk creating a new type. 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. If that can be avoided by use of a keyword for 90% of use cases, I think it is worth thinking about it and not dismissing it offhand. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] Defer keyword
Michael Van Canneyt via fpc-devel schrieb am Fr., 7. Mai 2021, 08:14: > > > On Fri, 7 May 2021, Sven Barth via fpc-devel wrote: > > > > > In my opinion the better solution is to continue the road that Maciej > > started and to implement that "default field" concept together with > > operator hoistening so that records with management operators can be > > used as containers. This is essentially the way it's done in C++ as well > > (e.g. we use that extensively at work), but it needs some questions > > solved for the default field functionality. This way the functionality > > is definitely optional and can be controlled per-instance instead of > > per-type. What it wouldn't solve however would be the assignment > > problems ("wrapped" to non-"wrapped" instance) though that could be > > probably be more or less solved by only allowing an explicit conversion > > to the non-"wrapped" instance. > > I thought it was agreed at the time that this was the most viable way > forward ? > As far as I remember there wasn't really any agreement. > IIRC there was also the proposal that this could be done automatically > using > a keyword: > > var >SomeClass : TSomeClass; dispose; > > The compiler can internally create the management record with a single > default > field and the needed management operator, so the user does not need > to create all that. > I'm not aboard with such a keyword. The compiler should provide the necessary language mechanisms (default field, operator hoisting) and then there should be a default implementation as part of the RTL. There is no need to hide this behind a keyword, attribute or whatever. > 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. 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
On Fri, 7 May 2021, Sven Barth via fpc-devel wrote: In my opinion the better solution is to continue the road that Maciej started and to implement that "default field" concept together with operator hoistening so that records with management operators can be used as containers. This is essentially the way it's done in C++ as well (e.g. we use that extensively at work), but it needs some questions solved for the default field functionality. This way the functionality is definitely optional and can be controlled per-instance instead of per-type. What it wouldn't solve however would be the assignment problems ("wrapped" to non-"wrapped" instance) though that could be probably be more or less solved by only allowing an explicit conversion to the non-"wrapped" instance. I thought it was agreed at the time that this was the most viable way forward ? IIRC there was also the proposal that this could be done automatically using a keyword: var SomeClass : TSomeClass; dispose; The compiler can internally create the management record with a single default field and the needed management operator, so the user does not need to create all that. 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. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] Defer keyword
Am 07.05.2021 um 00:32 schrieb Ryan Joseph via fpc-devel: On May 6, 2021, at 4:26 PM, J. Gareth Moreton via fpc-devel wrote: There is a performance penalty when using them, which one reason why the compiler sources don't use them. There's probably other reasons too. There might be some speed-up potential where standard Exit calls are concerned, but I'm not sure. I just did a search and I did indeed see a few try..finally blocks but not many. As I understand it there is a "finalization" section of each procedure which is used for ref counted objects so I assumed the statement was merely moved to that location but I guess there's some concerns over exceptions. There is no "finalization" section. It's really just an implicit try ... finally block that the compiler inserts. Look for "cs_implicit_exceptions" and "pi_needs_implicit_finally" if you want to learn more. Either way looking at the programming language landscape the better way forward seems to be some opt-in ARC for TObject but I don't know if the compiler team is receptive to that (Sven made some attempt years ago but abandoned it). it's kind of frustrating that we have ref counted types but that isn't extended to classes. Hopefully that's something we can tackle one of these days... The problem is that the whole class tree needs to support it for it to work correctly even if it's not the whole hierarchy that has as it enabled. That means at least one additional field inside TObject that a) controls that behavior and b) contains the reference count. This means that *all* class instances increase by a LongInt. This might not sound like much, but FPC also allows to work on smaller systems (and I don't mean the really small embedded ones as those don't have TObject enabled anyway) and there an additional LongInt for each instance might be critical. If the reference count feature is optional (in addition to the above) then an open question is what would happen if such a reference counted instance is assigned to a non-reference counted one. This would need to take into account all ways such an instance or type can be used including TClass. If the reference count would be enabled by default for *all* instance (like Delphi did in its platform compilers but which they abandoned now) then you'd have a huge backwards compatibility problem, because there definitely are cycles out there and thus this option would be an absolute no-no. In my opinion the better solution is to continue the road that Maciej started and to implement that "default field" concept together with operator hoistening so that records with management operators can be used as containers. This is essentially the way it's done in C++ as well (e.g. we use that extensively at work), but it needs some questions solved for the default field functionality. This way the functionality is definitely optional and can be controlled per-instance instead of per-type. What it wouldn't solve however would be the assignment problems ("wrapped" to non-"wrapped" instance) though that could be probably be more or less solved by only allowing an explicit conversion to the non-"wrapped" instance. 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
Am 07.05.2021 um 00:17 schrieb Ryan Joseph via fpc-devel: On May 6, 2021, at 4:05 PM, Sven Barth via fpc-devel wrote: Other than that, you're right and what Ryan is trying to do is definitely the intended purpose of try ... finally. Is there any runtime code involved with try..finally or does it just reorganize the code to run at the end of the block? My understanding of the defer keyword is that is was just a fancy way to move some code into a block which always gets run with a function exits. It depends on the platform. In general FPC uses setjmp/longjmp based exception handling, thus there is a slight penalty in setting up the exception frame (no matter if "finally" or "except"). In case of Win32 and Win64 the OS' Structured Exception Handling functionality is used. On i386-win32 there is still a runtime overhead due to how exceptions are managed, but on x86_64-win64 and aarch64-win64 (and in theory also arm-wince and arm-win32, but we have no ARM support for SEH yet (and arm-win32 isn't implemented yet :P )) this is done through meta data located in the PE file (the .pdata and .xdata sections) which allows for an implicit setup of the frames and thus there'll only be a penalty if an exception occurrs (cause the OS and the exception handling code will have to parse that data). 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). 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
Hi, 07.05.2021 1:32, Ryan Joseph via fpc-devel: [...] it's kind of frustrating that we have ref counted types but that isn't extended to classes. Indeed. However, unfortunately classes are substantially different in that they can cause reference circles, which then cause damage to ref counting, unless some severe complications are implemented, and then it will probably get close to garbage collection. Well, AFAIU. Regards, Nikolai 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
> On May 6, 2021, at 4:26 PM, J. Gareth Moreton via fpc-devel > wrote: > > There is a performance penalty when using them, which one reason why the > compiler sources don't use them. There's probably other reasons too. There > might be some speed-up potential where standard Exit calls are concerned, but > I'm not sure. I just did a search and I did indeed see a few try..finally blocks but not many. As I understand it there is a "finalization" section of each procedure which is used for ref counted objects so I assumed the statement was merely moved to that location but I guess there's some concerns over exceptions. Either way looking at the programming language landscape the better way forward seems to be some opt-in ARC for TObject but I don't know if the compiler team is receptive to that (Sven made some attempt years ago but abandoned it). it's kind of frustrating that we have ref counted types but that isn't extended to classes. Hopefully that's something we can tackle one of these days... 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
There is some special handling involved in that the code inside the try part (I think) is effectively a nested procedure. It's important in the context of stack unwinding when an exception occurs. There is a performance penalty when using them, which one reason why the compiler sources don't use them. There's probably other reasons too. There might be some speed-up potential where standard Exit calls are concerned, but I'm not sure. Gareth aka. Kit On 06/05/2021 23:17, Ryan Joseph via fpc-devel wrote: On May 6, 2021, at 4:05 PM, Sven Barth via fpc-devel wrote: Other than that, you're right and what Ryan is trying to do is definitely the intended purpose of try ... finally. Is there any runtime code involved with try..finally or does it just reorganize the code to run at the end of the block? My understanding of the defer keyword is that is was just a fancy way to move some code into a block which always gets run with a function exits. Regards, Ryan Joseph ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel -- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] Defer keyword
> On May 6, 2021, at 4:05 PM, Sven Barth via fpc-devel > wrote: > > Other than that, you're right and what Ryan is trying to do is definitely the > intended purpose of try ... finally. > Is there any runtime code involved with try..finally or does it just reorganize the code to run at the end of the block? My understanding of the defer keyword is that is was just a fancy way to move some code into a block which always gets run with a function exits. 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
J. Gareth Moreton via fpc-devel schrieb am Do., 6. Mai 2021, 20:03: > The rule with try...finally is that, outside of something completely > catastrophic that destroys the program flow, is that once you enter the > try part, the finally part is guaranteed to be executed no matter how > you leave it. > There are two exceptions (pun not intended :P ): - Halt (or any other OS function that never returns and terminates the process) - LongJmp (because that knows nothing about exception handlers) Other than that, you're right and what Ryan is trying to do is definitely the intended purpose of try ... finally. 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
The rule with try...finally is that, outside of something completely catastrophic that destroys the program flow, is that once you enter the try part, the finally part is guaranteed to be executed no matter how you leave it. Gareth aka. Kit On 06/05/2021 18:53, Ryan Joseph via fpc-devel wrote: On May 6, 2021, at 11:39 AM, J. Gareth Moreton via fpc-devel wrote: In the example given: obj := TObject.Create; defer objects.Free; What's wrong with Pascal's existing functionality? obj := TObject.Create; try ... finally objects.Free; end; If there's a concern about performance penalty, maybe the compiler can work something out for simple finally blocks and just copy the code to any Exit nodes found rather than calling the pseudo-procedure that a try...finally block creates. I didn't know try..finally even worked like that. :) I thought it was just for exceptions but I see it captures exit also. The defer keyword is nicer on the eyes I would say because it don't require wrapping the entire function in a big block of code. So never mind then I guess. I'll start using try..finally and see how that works for me. Regards, Ryan Joseph ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel -- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] Defer keyword
> On May 6, 2021, at 11:39 AM, J. Gareth Moreton via fpc-devel > wrote: > > In the example given: > > obj := TObject.Create; > defer objects.Free; > > What's wrong with Pascal's existing functionality? > > obj := TObject.Create; > try >... > finally >objects.Free; > end; > > If there's a concern about performance penalty, maybe the compiler can work > something out for simple finally blocks and just copy the code to any Exit > nodes found rather than calling the pseudo-procedure that a try...finally > block creates. I didn't know try..finally even worked like that. :) I thought it was just for exceptions but I see it captures exit also. The defer keyword is nicer on the eyes I would say because it don't require wrapping the entire function in a big block of code. So never mind then I guess. I'll start using try..finally and see how that works for me. 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
In the example given: obj := TObject.Create; defer objects.Free; What's wrong with Pascal's existing functionality? obj := TObject.Create; try ... finally objects.Free; end; If there's a concern about performance penalty, maybe the compiler can work something out for simple finally blocks and just copy the code to any Exit nodes found rather than calling the pseudo-procedure that a try...finally block creates. Gareth aka. Kit On 06/05/2021 18:11, Ryan Joseph via fpc-devel wrote: On May 6, 2021, at 10:44 AM, Marco van de Voort via fpc-devel wrote: But those types have refcounting built-in and always active. Things like defer don't, which makes that all objects gets refcounting overhead in case somebody needs it for "defer". Contrary to Pascal both the language you reference have garbage collectors, so their objects are already managed anyway, The idea of defer isn't necessarily about memory management but rather literally just deferring a statements execution until a predicable point in execution (end of a block or function). Those articles mentioned using them for file IO also so that you can be sure you're going to close the open file handle even if the function returns before. Memory management is just one obvious use case since we have this problem in Pascal often. I don't think this even affects ref counting of existing types because it all it does it move the statement to the end of the block. Maybe I'm not understanding your point though. Regards, Ryan Joseph ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel -- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] Defer keyword
> On May 6, 2021, at 10:44 AM, Marco van de Voort via fpc-devel > wrote: > > But those types have refcounting built-in and always active. Things like > defer don't, which makes that all objects gets refcounting overhead in case > somebody needs it for "defer". > > Contrary to Pascal both the language you reference have garbage collectors, > so their objects are already managed anyway, The idea of defer isn't necessarily about memory management but rather literally just deferring a statements execution until a predicable point in execution (end of a block or function). Those articles mentioned using them for file IO also so that you can be sure you're going to close the open file handle even if the function returns before. Memory management is just one obvious use case since we have this problem in Pascal often. I don't think this even affects ref counting of existing types because it all it does it move the statement to the end of the block. Maybe I'm not understanding your point though. 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
Op 2021-05-06 om 17:38 schreef Ryan Joseph via fpc-devel: Something which annoys me about Pascal is cleanup in which a function exits in multiple places but there is no formal way to free memory which may be used in the current scope. I say ultimately Pascal needs some opt-in automatic reference counting for TObject but the "defer" keyword would be helpful alternative to what we have now, which is nothing. The concept is very easy to understand and should be easy to implement by simply making a "defer" statement node which is added to a list and then called during function finalization like the other ref counted objects (dynamic array, interfaces etc). But those types have refcounting built-in and always active. Things like defer don't, which makes that all objects gets refcounting overhead in case somebody needs it for "defer". Contrary to Pascal both the language you reference have garbage collectors, so their objects are already managed anyway, ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
[fpc-devel] Defer keyword
Something which annoys me about Pascal is cleanup in which a function exits in multiple places but there is no formal way to free memory which may be used in the current scope. I say ultimately Pascal needs some opt-in automatic reference counting for TObject but the "defer" keyword would be helpful alternative to what we have now, which is nothing. The concept is very easy to understand and should be easy to implement by simply making a "defer" statement node which is added to a list and then called during function finalization like the other ref counted objects (dynamic array, interfaces etc). I've seen it appear in multiple languages already and it's a sound idea in my opinion. Is this something worth perusing for Pascal? https://www.hackingwithswift.com/example-code/language/how-to-delay-execution-of-code-using-the-defer-keyword https://www.geeksforgeeks.org/defer-keyword-in-golang/ procedure DoStuff; begin obj := TObject.Create; defer objects.Free; while true do begin // don't worry, obj will be freed safely if not obj.TrySomething then exit; end; end; Regards, Ryan Joseph ___ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel