Re: [fpc-devel] Status report for "class helpers"
Paul Ishenin schrieb: For some reason the visibility is completely ignored here. I can add a class helper to the strict private or even move it to another unit - it is always visible. IMO class helper methods always should become visible as part of the class, regardless of where they are declared. From the Delphi wiki: "You can define and associate multiple helpers with a single type. However, only zero or one helper applies in any specific location in source code. The helper defined in the nearest scope will apply. Class or record helper scope is determined in the normal Delphi fashion (for example, right to left in the unit's uses clause)." I.e. a single Helper reference (field) in the class definition is sufficient. This field cannot be persistent, instead it has to be initialized for every use case: whenever a helper is found in the compiled unit, or in one of its used units, it overwrites the Helper reference. Adding the helper elements to the class STB is not a valid solution, because another helper can become active at any time, during compilation. The ancestors of the Helper class must be searched as well. Also: "Note that the class helper function MyFunc is called, because the class helper takes precedence over the actual class type." That's bad, because this disallows to treat the helper like an ancestor, accessible in all derived classes :-( Interesting questions: 1) Unit A defines an class helper for TFoo, then uses in the implementation section unit B, which also defines an helper for TFoo. According to the above rules the helper in A should become inaccessible and useless then. 2) Similarly multiple class helpers can be defined in the implementation section, which are used in the immediately following code, until the next helper declaration. 3) What about derived classes? Since derived classes are compiled independently, they never will use a reintroduced method in an class helper. 4) When class helpers are evaluated at compile time, according to the static object types (like properties are), then they could be handled just like the well known typecast hack: type TMyFoo = class(TFoo) end; with following casts of every TFoo reference into TMyFoo. But TFoo derived types must be handled in the same way, so that I see no way around an extended search inside the TFoo STB. 5) What's the meaning of the "ancestor list"? IMO interfaces cannot be added by an class helper, and multiple inheritance is quite unlikely. Will the ancestor list allow to override interface *implementations*? DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 30.01.2011 09:03, Hans-Peter Diettrich wrote: Paul Ishenin schrieb: For some reason the visibility is completely ignored here. I can add a class helper to the strict private or even move it to another unit - it is always visible. IMO class helper methods always should become visible as part of the class, regardless of where they are declared. From the Delphi wiki: "You can define and associate multiple helpers with a single type. However, only zero or one helper applies in any specific location in source code. The helper defined in the nearest scope will apply. Class or record helper scope is determined in the normal Delphi fashion (for example, right to left in the unit's uses clause)." I.e. a single Helper reference (field) in the class definition is sufficient. This field cannot be persistent, instead it has to be initialized for every use case: whenever a helper is found in the compiled unit, or in one of its used units, it overwrites the Helper reference. Adding the helper elements to the class STB is not a valid solution, because another helper can become active at any time, during compilation. The ancestors of the Helper class must be searched as well. Sorry, I don't understand what you want to tell here. I personally expect a class helper that is defined inside a private section of a class not to be available in another unit like I can't access a field or another type defined in there as well. Also: "Note that the class helper function MyFunc is called, because the class helper takes precedence over the actual class type." That's bad, because this disallows to treat the helper like an ancestor, accessible in all derived classes :-( If you want to have a class helper available in a derived class there is only one way to do this: source begin type TFoo = class end; TFooHelper = class helper for TFoo end; // this helper only applies to variables of type TFoo TBar = class(TFoo) end; // No methods of TFooHelper are available for variables of this type TBarHelper = class helper(TFooHelper) for TBar end; // now all methods of TFooHelper (that aren't overriden by TBarHelper) are available for all variables of type TBar as well source end Interesting questions: 1) Unit A defines an class helper for TFoo, then uses in the implementation section unit B, which also defines an helper for TFoo. According to the above rules the helper in A should become inaccessible and useless then. This is indeed something that I need to test. And I hope that Delphi behaves the way you described (because that would be the consistent behavior) 2) Similarly multiple class helpers can be defined in the implementation section, which are used in the immediately following code, until the next helper declaration. Needs to be tested as well, but I hope so. 3) What about derived classes? Since derived classes are compiled independently, they never will use a reintroduced method in an class helper. This is correct. The following does not work in Delphi: source begin type TStringsHelper = class helper for TStrings procedure Test; end; var s: TStringList; begin s.Test; // this won't work TStrings(s).Test // but this does end; source end 4) When class helpers are evaluated at compile time, according to the static object types (like properties are), then they could be handled just like the well known typecast hack: type TMyFoo = class(TFoo) end; with following casts of every TFoo reference into TMyFoo. But TFoo derived types must be handled in the same way, so that I see no way around an extended search inside the TFoo STB. Technically class helpers ARE classes that derive from the extended class (here: TFoo). But there are no casts of TFoo references. When searching for a symbol in a class the last class helper in scope for that class is searched first and then the symbol is searched in the class itself. 5) What's the meaning of the "ancestor list"? IMO interfaces cannot be added by an class helper, and multiple inheritance is quite unlikely. Will the ancestor list allow to override interface *implementations*? I don't know how you come to interfaces now. But basically from the outside class helpers seem to support multiple inheritance, but technically they don't. It works like this: * the extended class is the real parent of the class helper class * if the class helper has a parent ( e.g. class helper(TFooHelper) for TFoo ) this parent is referenced in a mostly unimportant "helperparent" field of tobjectdef and only used when searching for a symbol. At the end the pseudo parent of a class helper tells the compiler to search the symbol table of that class helper as well. Regards, Sven ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 30.01.2011 04:30, Paul Ishenin wrote: 30.01.2011 5:22, Sven Barth wrote: Ok, I have now implemented a set of flags in TSymtable of which one is set when the (global-,static-)symtable contains a class helper (I haven't refactored b_needs_init_final yet). Here are the new results with the search for class helpers enabled (only two runs this time): Run 1: real 2m22.980s user 0m47.140s sys 0m4.333s Run 2: real 2m15.362s user 0m47.274s sys 0m4.140s Imo it works much better now. Only one minute slower in the complete run instead of four. I let you guys decide whether this is good enough ^^ How often is the compiler compiled completly during a make cycle? Regards, Sven ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
30.01.2011 15:45, Sven Barth wrote: Imo it works much better now. Only one minute slower in the complete run instead of four. I let you guys decide whether this is good enough ^^ 2m22.980s - 2m15.362s = 0m7.xxxs - were is a minute? How often is the compiler compiled completly during a make cycle? 3 times. Best regards, Paul Ishenin ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 30.01.2011 09:55, Paul Ishenin wrote: 30.01.2011 15:45, Sven Barth wrote: Imo it works much better now. Only one minute slower in the complete run instead of four. I let you guys decide whether this is good enough ^^ 2m22.980s - 2m15.362s = 0m7.xxxs - were is a minute? That was two runs of the same compiler. I've run it twice, to be sure that the workload of the PC doesn't influence the result to much. The timing of the compiler without class helper search is the one in the older mail: Run 1: real1m7.982s user0m46.024s sys0m4.390s Run 2: real1m8.619s user0m46.104s sys0m4.513s Run 3: real1m10.078s user0m46.290s sys0m4.333s How often is the compiler compiled completly during a make cycle? 3 times. The first run is done by the starting compiler, right (2.4.2 in my case)? So this would mean that roughly half a minute is added by the 2.5.1 compilers using the class helper search (I'll need to verify this assumption of course). Regards, Sven ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 29.01.2011 23:22, Sven Barth wrote: Ok, I have now implemented a set of flags in TSymtable of which one is set when the (global-,static-)symtable contains a class helper (I haven't refactored b_needs_init_final yet). I have commited the changes now as well (I was too tired yesterday), so please fell free to critize them (especially the ones in ppudump) as I need to build on on these changes regarding b_needs_init_final (or should this wait until everything is merged back to trunk?). Regards, Sven ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
30.01.2011 16:22, Sven Barth wrote: I have commited the changes now as well (I was too tired yesterday), so please fell free to critize them (especially the ones in ppudump) as I need to build on on these changes regarding b_needs_init_final (or should this wait until everything is merged back to trunk?). b_needs_init_final should wait I think. Best regards, Paul Ishenin ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
30.01.2011 16:22, Sven Barth wrote: I have commited the changes now as well (I was too tired yesterday), so please fell free to critize them (especially the ones in ppudump). Why do you need ibsymtableoptions ? Best regards, Paul Ishenin ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 30.01.2011 11:30, Paul Ishenin wrote: 30.01.2011 16:22, Sven Barth wrote: I have commited the changes now as well (I was too tired yesterday), so please fell free to critize them (especially the ones in ppudump). Why do you need ibsymtableoptions ? tstoredsymtable stores only definitions and symbols in its own entries, so I felt that its more save to add a new entry instead of having a set floating around in the nirvana of the ppu. Also this can be extended later e.g. for Delphi attributes where everything seems to be able to carry an attribute (I've seen a variable with an attribute already, though I don't know whether this example really works/compiles). And the real reason why I added it: I had problems when I only stored the set (the "more save" from above), but this could be related to the missing "inherited ppuwrite" call in tabstractlocaldef (which I discovered after I had added the entry). Regards, Sven ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 30 Jan 2011, at 09:45, Sven Barth wrote: > Only one minute slower in the complete run instead of four. I let you guys > decide whether this is good enough ^^ It's still a lot of overhead. An alternative solution could be to add a hashtable (tfphaslist) to tmodule whose entries are hashed on the qualified class names (unit$classname, since different units can contain classes with the same name). The value of such an entry would a tfpobjectlist of class helpers, with the last entry the one that is actually used. This list has to be updated whenever a symtablestack.push/pop is performed (you would probably have to wrap those calls, since the symtablestack itself is a fairly low level thing and I don't think it is supposed to know anything about tobjectdefs). The reason for having a list of class helpers rather than only the current class helper, is because you would also have to remove class helpers again when its symtable is removed from the symtable stack, and this way you wouldn't have to search all previous symtables on the stack to see whether they also contained a class helper (simply remove all class helpers from the list whose owner=symtablestack.top). Of course, this won't be free either since you have to scan all pushed symtables for class helpers, and when popping them you have to go through all hashtable items to remove the appropriate ones. I don't know whether overall it will be faster or slower than your current approach. The reason the hashtable would have to be kept per module rather than simply adding the list of class helpers in scope to the tabstractrecorddef of the relevant record/class, is that in the latter case you would get into trouble whenever you switch from parsing one unit to another (which happens a lot while parsing uses-clauses). The reason is that you would have to save/restore the current class helpers in scope for every abstractrecorddef that has been loaded whenever you switched units. Jonas PS: the fact that you can have classes with the same name in different units is something that requires special handling in any case. In Objective-C, there is a global class name space (so all classes with the same name are the same class according to the run time), but you probably need different class helper name mangling in the case of Object Pascal to prevent false collisions.___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
Am 29.01.2011 23:22, schrieb Sven Barth: > > Here are the new results with the search for class helpers enabled (only > two runs this time): > > Run 1: > real2m22.980s > user0m47.140s > sys0m4.333s > > Run 2: > real2m15.362s > user0m47.274s > sys0m4.140s With which times are those comparable? ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
Am 30.01.2011 09:45, schrieb Sven Barth: > On 30.01.2011 04:30, Paul Ishenin wrote: >> 30.01.2011 5:22, Sven Barth wrote: >>> Ok, I have now implemented a set of flags in TSymtable of which one is >>> set when the (global-,static-)symtable contains a class helper (I >>> haven't refactored b_needs_init_final yet). >>> >>> Here are the new results with the search for class helpers enabled >>> (only two runs this time): >>> >>> Run 1: >>> real 2m22.980s >>> user 0m47.140s >>> sys 0m4.333s >>> >>> Run 2: >>> real 2m15.362s >>> user 0m47.274s >>> sys 0m4.140s >> >> Imo it works much better now. > > Only one minute slower in the complete run instead of four. Now I understand the timings :) Actually two times slower, right? > I let you > guys decide whether this is good enough ^^ Actually I think anything about a ten percent slower compiler will people make cry ... And as far as I understand, for projects with a lot of units it will be even worse, right? > > How often is the compiler compiled completly during a make cycle? 2-4 times iirc. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 30.01.2011 12:13, Florian Klämpfl wrote: Am 30.01.2011 09:45, schrieb Sven Barth: On 30.01.2011 04:30, Paul Ishenin wrote: 30.01.2011 5:22, Sven Barth wrote: Ok, I have now implemented a set of flags in TSymtable of which one is set when the (global-,static-)symtable contains a class helper (I haven't refactored b_needs_init_final yet). Here are the new results with the search for class helpers enabled (only two runs this time): Run 1: real 2m22.980s user 0m47.140s sys 0m4.333s Run 2: real 2m15.362s user 0m47.274s sys 0m4.140s Imo it works much better now. Only one minute slower in the complete run instead of four. Now I understand the timings :) Actually two times slower, right? I was a bit bad with explaining my profile results ^^ The complete "make cycle" is two times slower, yes. I let you guys decide whether this is good enough ^^ Actually I think anything about a ten percent slower compiler will people make cry ... And as far as I understand, for projects with a lot of units it will be even worse, right? A huge number of units is not the main cause. The main problem is many units included in the uses clause. A project could have thousand units, but if every unit only used two or three you might not even notice much (a very hypothetic scenario, but to show you where the problem is). That's why I used the compiler as a testcase (though Lazarus might be a good candidate as well...) Regards, Sven ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 30.01.2011 12:06, Jonas Maebe wrote: On 30 Jan 2011, at 09:45, Sven Barth wrote: Only one minute slower in the complete run instead of four. I let you guys decide whether this is good enough ^^ It's still a lot of overhead. Yes and that's why I'm thankful for every suggestion I can get (like your one). An alternative solution could be to add a hashtable (tfphaslist) to tmodule whose entries are hashed on the qualified class names (unit$classname, since different units can contain classes with the same name). The value of such an entry would a tfpobjectlist of class helpers, with the last entry the one that is actually used. This list has to be updated whenever a symtablestack.push/pop is performed (you would probably have to wrap those calls, since the symtablestack itself is a fairly low level thing and I don't think it is supposed to know anything about tobjectdefs). The reason for having a list of class helpers rather than only the current class helper, is because you would also have to remove class helpers again when its symtable is removed from the symtable stack, and this way you wouldn't have to search all previous symtables on the stack to see whether they also contained a class helper (simply remove all class helpers from the list whose owner=symtablestack.top). Of course, this won't be free either since you have to scan all pushed symtables for class helpers, and when popping them you have to go through all hashtable items to remove the appropriate ones. I don't know whether overall it will be faster or slower than your current approach. The need to scan all pushed symtables can be reduced by keeping the flag I introduced and using it for this purpose. The reason the hashtable would have to be kept per module rather than simply adding the list of class helpers in scope to the tabstractrecorddef of the relevant record/class, is that in the latter case you would get into trouble whenever you switch from parsing one unit to another (which happens a lot while parsing uses-clauses). The reason is that you would have to save/restore the current class helpers in scope for every abstractrecorddef that has been loaded whenever you switched units. Thank you for your suggestion. I'll try to implement this to see whether it helps. PS: the fact that you can have classes with the same name in different units is something that requires special handling in any case. In Objective-C, there is a global class name space (so all classes with the same name are the same class according to the run time), but you probably need different class helper name mangling in the case of Object Pascal to prevent false collisions. While I understand the difference between namespaces in case of Objective-C and Object Pascal, I don't understand why I should pay attention to the mangling of class helpers. I might be missing a small puzzle piece here, so would you please explain this? Regards, Sven ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
30.01.2011 15:45, Sven Barth wrote: Only one minute slower in the complete run instead of four. I let you guys decide whether this is good enough ^^ How often is the compiler compiled completly during a make cycle? I still see an ability to optimize your implementation. procedure update_unit_symtable_options; var st: tsymtable; begin st:=owner; while not(st.symtabletype in [globalsymtable,staticsymtable]) do st:=st.defowner.owner; if objecttype in [odt_classhelper,odt_objccategory] then include(st.tableoptions,sto_has_classhelper); end; remove "if objecttype in [odt_classhelper,odt_objccategory] then" from this routine to outside - so you will not need to scan owners in the loop for all object types. Best regards, Paul Ishenin ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On Sunday, 30. January 2011 12.13:21 Florian Klämpfl wrote: > > Actually I think anything about a ten percent slower compiler will > people make cry ... And as far as I understand, for projects with a lot > of units it will be even worse, right? > I cry if FPC doesn't compile at least ten percent *faster* than the previous release... Martin ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
Am 30.01.2011 12:37, schrieb Martin Schreiber: > On Sunday, 30. January 2011 12.13:21 Florian Klämpfl wrote: >> >> Actually I think anything about a ten percent slower compiler will >> people make cry ... And as far as I understand, for projects with a lot >> of units it will be even worse, right? >> > I cry if FPC doesn't compile at least ten percent *faster* than the previous > release... Sven, see ;)? ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 30 Jan 2011, at 12:37, Martin Schreiber wrote: > I cry if FPC doesn't compile at least ten percent *faster* than the previous > release... At least on Mac OS X/i386, we are pretty close to that currently as far as compiling the compiler with itself is concerned: * Compiling it with 2.4.2: user0m7.663s sys 0m0.545s user0m7.540s sys 0m0.535s user0m7.527s sys 0m0.532s * Compiling it with 2.5.1: user0m6.972s sys 0m0.451s user0m6.967s sys 0m0.456s user0m6.966s sys 0m0.456s The reason I'm specifically mentioning the used platform is that there's one new Mac OS X/i386-specific optimization in 2.5.1 (more efficient PIC trampolines, and PIC is enabled by default on that platform), although I cannot imagine that it would be completely (or even largely) responsible for an 8% speedup. Jonas___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 30.01.2011 13:11, Florian Klämpfl wrote: Am 30.01.2011 12:37, schrieb Martin Schreiber: On Sunday, 30. January 2011 12.13:21 Florian Klämpfl wrote: Actually I think anything about a ten percent slower compiler will people make cry ... And as far as I understand, for projects with a lot of units it will be even worse, right? I cry if FPC doesn't compile at least ten percent *faster* than the previous release... Sven, see ;)? Indeed... :) Regards, Sven ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 30.01.2011 12:36, Paul Ishenin wrote: 30.01.2011 15:45, Sven Barth wrote: Only one minute slower in the complete run instead of four. I let you guys decide whether this is good enough ^^ How often is the compiler compiled completly during a make cycle? I still see an ability to optimize your implementation. procedure update_unit_symtable_options; var st: tsymtable; begin st:=owner; while not(st.symtabletype in [globalsymtable,staticsymtable]) do st:=st.defowner.owner; if objecttype in [odt_classhelper,odt_objccategory] then include(st.tableoptions,sto_has_classhelper); end; remove "if objecttype in [odt_classhelper,odt_objccategory] then" from this routine to outside - so you will not need to scan owners in the loop for all object types. Sorry, but I don't understand your intention here. The if-clause is only run after the global- or staticsymtable this class belongs to is reached. Or do you mean something completly different? Regards, Sven ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
In our previous episode, Sven Barth said: > >>> > >>> Actually I think anything about a ten percent slower compiler will > >>> people make cry ... And as far as I understand, for projects with a lot > >>> of units it will be even worse, right? > >>> > >> I cry if FPC doesn't compile at least ten percent *faster* than the > >> previous > >> release... > > > > Sven, see ;)? > > Indeed... :) Don't forget to keep a reign on memory too :-) ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] 2.5.1 doesn't build today
current trunk doesn't build. fails on pxlib - make clean - make all - make zipinstall Platform i-386-win32 OS XP sp3 Bootstrap 2.4.2 --- make[3]: Entering directory `C:/FPC/2.5.1/packages/pxlib' make all LINKSMART=1 CREATESMART=1 make[4]: Entering directory `C:/FPC/2.5.1/packages/pxlib' C:/FPC/2.5.1/compiler/ppc386.exe -XX -CX -Ur -Xs -O2 -n -FuC:/FPC/2.5.1/rtl/units/i386-win32 -FE. -F Uunits/i386-win32 -di386 -dRELEASE src/pxlib.pp make: Interrupt/Exception caught (code = 0xc005, addr = 0x7c90100b) make[3]: *** [fpc_smart] Error 255 make[3]: Leaving directory `C:/FPC/2.5.1/packages/pxlib' make[2]: *** [pxlib_smart] Error 2 make[2]: Leaving directory `C:/FPC/2.5.1/packages' make[1]: *** [packages_smart] Error 2 make[1]: Leaving directory `C:/FPC/2.5.1' make: *** [build-stamp.i386-win32] Error 2 ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
30.01.2011 19:41, Sven Barth wrote: procedure update_unit_symtable_options; var st: tsymtable; begin st:=owner; while not(st.symtabletype in [globalsymtable,staticsymtable]) do st:=st.defowner.owner; if objecttype in [odt_classhelper,odt_objccategory] then include(st.tableoptions,sto_has_classhelper); end; remove "if objecttype in [odt_classhelper,odt_objccategory] then" from this routine to outside - so you will not need to scan owners in the loop for all object types. I still see an ability to optimize your implementation. Sorry, but I don't understand your intention here. procedure update_unit_symtable_options; var st: tsymtable; begin st:=owner; while not(st.symtabletype in [globalsymtable,staticsymtable]) do st:=st.defowner.owner; include(st.tableoptions,sto_has_classhelper); end; if objecttype in [odt_classhelper,odt_objccategory] then update_unit_symtable_options; This will work faster because loop and the function call will run not for all object types. Best regards, Paul Ishenin ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 30.01.2011 15:10, Paul Ishenin wrote: 30.01.2011 19:41, Sven Barth wrote: procedure update_unit_symtable_options; var st: tsymtable; begin st:=owner; while not(st.symtabletype in [globalsymtable,staticsymtable]) do st:=st.defowner.owner; if objecttype in [odt_classhelper,odt_objccategory] then include(st.tableoptions,sto_has_classhelper); end; remove "if objecttype in [odt_classhelper,odt_objccategory] then" from this routine to outside - so you will not need to scan owners in the loop for all object types. I still see an ability to optimize your implementation. Sorry, but I don't understand your intention here. procedure update_unit_symtable_options; var st: tsymtable; begin st:=owner; while not(st.symtabletype in [globalsymtable,staticsymtable]) do st:=st.defowner.owner; include(st.tableoptions,sto_has_classhelper); end; if objecttype in [odt_classhelper,odt_objccategory] then update_unit_symtable_options; This will work faster because loop and the function call will run not for all object types. Now I understand. Thanks for clarification. I've done that change. Timings without that change: Run 1: real1m3.461s user0m45.957s sys 0m4.590s Run 2: real1m10.777s user0m46.204s sys 0m4.696s Run 3: real1m11.596s user0m46.690s sys 0m4.406s Timings with that change: Run 1: real1m8.919s user0m46.597s sys 0m4.166s Run 2: real1m9.359s user0m46.524s sys 0m4.380s Run 3: real1m8.342s user0m46.294s sys 0m4.490s Doesn't change much. For comparison timings without the search for class helpers (if-clause in symtable.pas/searchsym_in_class disabled): Run 1: real1m5.040s user0m46.050s sys 0m4.163s Run 2: real1m4.008s user0m45.784s sys 0m4.343s Run 3: real1m6.074s user0m45.714s sys 0m4.546s It seems that I should have rerun the profiling without class helper search as well after I added the flag yesterday... I'll nevertheless try to implement Jonas' suggestion to see whether this improves timing a bit more (and maybe the flags can be used to optimize the speed for other types of searches a bit more, like Paul suggested :D ) Regards, Sven ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
31.01.2011 0:26, Sven Barth wrote: Timings without that change: Run 1: real1m3.461s user0m45.957s sys0m4.590s Timings with that change: Run 1: real1m8.919s user0m46.597s sys0m4.166s But previously you gave 2 minutes values. Best regards, Paul Ishenin ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
Sven Barth schrieb: Sorry, I don't understand what you want to tell here. Sorry2, I'll retry. I personally expect a class helper that is defined inside a private section of a class not to be available in another unit like I can't access a field or another type defined in there as well. Delphi allows for *at most* one active class helper, determined by the unit search order, just like every other ambiguous identifier is resolved. If you don't want an class helper used in other units, simply move it to the implementation section. Hiding an class helper in a private section of a class IMO is not the right way, and the result may be compiler specific. If you want to have a class helper available in a derived class there is only one way to do this: [...] Okay, now I understand the use of one ancestor, but still not the use of a list of ancestors. 3) What about derived classes? Since derived classes are compiled independently, they never will use a reintroduced method in an class helper. This is correct. The following does not work in Delphi: source begin type TStringsHelper = class helper for TStrings procedure Test; end; var s: TStringList; begin s.Test; // this won't work TStrings(s).Test // but this does end; source end This looks very much like my #4. 4) When class helpers are evaluated at compile time, according to the static object types (like properties are), then they could be handled just like the well known typecast hack: type TMyFoo = class(TFoo) end; with following casts of every TFoo reference into TMyFoo. But TFoo derived types must be handled in the same way, so that I see no way around an extended search inside the TFoo STB. Technically class helpers ARE classes that derive from the extended class (here: TFoo). But there are no casts of TFoo references. When searching for a symbol in a class the last class helper in scope for that class is searched first and then the symbol is searched in the class itself. Then one possible implementation could hide the extended class (TFoo), and use the helper class STB instead. This were the implementation of an implicit type cast. The symtable stack has to be built or modified accordingly, so that searching continues in the proper class ancestors. 5) What's the meaning of the "ancestor list"? IMO interfaces cannot be added by an class helper, and multiple inheritance is quite unlikely. Will the ancestor list allow to override interface *implementations*? I don't know how you come to interfaces now. This is the normal use of a *list* of ancestors. The first ancestor denotes the parent class, all others denote interfaces. But basically from the outside class helpers seem to support multiple inheritance, but technically they don't. It works like this: * the extended class is the real parent of the class helper class * if the class helper has a parent ( e.g. class helper(TFooHelper) for TFoo ) this parent is referenced in a mostly unimportant "helperparent" field of tobjectdef and only used when searching for a symbol. At the end the pseudo parent of a class helper tells the compiler to search the symbol table of that class helper as well. See above. I'd push the extended class onto the symtable stack, then the class helper parents, and finally the class helper itself, and use that stack whenever a reference to a class with a helper class is encounterd. DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
Jonas Maebe schrieb: An alternative solution could be to add a hashtable (tfphaslist) to tmodule whose entries are hashed on the qualified class names (unit$classname, since different units can contain classes with the same name). The value of such an entry would a tfpobjectlist of class helpers, with the last entry the one that is actually used. This list has to be updated whenever a symtablestack.push/pop is performed (you would probably have to wrap those calls, since the symtablestack itself is a fairly low level thing and I don't think it is supposed to know anything about tobjectdefs). IIRC a class symtable is pushed onto the symtable stack, whenever a qualifier is encountered (e.g. "TFoo."). Regardless of the implementation, this makes the symbol search start in TFoo and continue in its ancestors, before the remainder of the stack is searched. It should be possible to extend that mechanism, adding eventual class helpers to the search order. Removal of such a qualified scope, with all contained ancestors, also must have been implemented already, and should not deserve much changing. Of course, this won't be free either since you have to scan all pushed symtables for class helpers, and when popping them you have to go through all hashtable items to remove the appropriate ones. I don't know whether overall it will be faster or slower than your current approach. Is the hashtable *really* rebuilt with every push and pop of another symtable? It would be much easier to have a hashtable per symtable, that deserves no further modifications. When all hashtables use the same hash algorithm, a hash value must be computed only once, and then can be used for lookup in every STB on the stack. DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
On 31-1-2011 2:06, Hans-Peter Diettrich wrote: Jonas Maebe schrieb: Is the hashtable *really* rebuilt with every push and pop of another symtable? It would be much easier to have a hashtable per symtable, that deserves no further modifications. When all hashtables use the same hash algorithm, a hash value must be computed only once, and then can be used for lookup in every STB on the stack. DoDi CRC's are also hashes. isn't that used? ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Status report for "class helpers"
Am Montag, 31. Januar 2011 00:57 schrieb Paul Ishenin: > 31.01.2011 0:26, Sven Barth wrote: > > Timings without that change: > > > > Run 1: > > > > real1m3.461s > > user0m45.957s > > sys0m4.590s > > > > Timings with that change: > > > > Run 1: > > > > real1m8.919s > > user0m46.597s > > sys0m4.166s > > But previously you gave 2 minutes values. > AFAIK, the "real" time is pretty meaningless. It just says how much time passed between prg start and prg end. The "user" time is the interesting one. It says how much processor time the prg used actually doing something instead of waiting to be sheduled by the OS. That's why a multithreaded app on a multi-core can have higher user time than real time. regards Burkhard ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel