Jump to content

Mahdi Safsafi

Members
  • Content Count

    383
  • Joined

  • Last visited

  • Days Won

    10

Posts posted by Mahdi Safsafi


  1. @dummzeuch 

    Quote

    How did you come up with this @Mahdi Safsafi ?

    Go to DoShowException entry point and then go to the end of that function(on the right panel, I made some pseudo pascal code for clarification) :
    https://i.ibb.co/zZd5spY/Dbg.png

     

    Quote

    edit3: It's not the computer, it's the Delphi version. Delphi 2007 works with the test project but not with the unit test project. Delphi 10.2 works with both. At least I can now reproduce it on my GExperts development computer, not that it helps much.

    Can you give a simple DUnit test ? Basically when an exception occurs and you click continue, the RTL tries to find a handler for that exception and executes it. So stopping at the end of procedure is weird!


    I'm not very familiar with D2007 but was DUnit shipped with Delphi 2007 at that time ?


    I guess, either DUnit is doing something behind the scene ! Otherwise why under D2007, it worked with a simple test project and failed on DUnit project . Why it just worked fine under 10.2 for both project ? Or there is something with D2007 RTL. Can you confirm if the same behavior occurs without hooking (disabling GExpert) ?
     

    Also, I suggest that you disable GExpert for DUnit on D2007(make sure there is no hook is installed as well), put a break point on DoShowException, run a dummy project that raise exception and try to follow until the function returns. See whether a call to PostDebugMessage was made or not.

     

    50 minutes ago, Kas Ob. said:

    @dummzeuch Hold on that PostDebugMessage.

     

    Mahdi tried to extract it right but missed one thing, i assume he is familiar with reversing and tracking code generated by C/C++ compiler but here we are talking Delphi with no StdCall, that PostDebugMessage is 5 parameters function not 2 !

     

    Let me dig more and see if i can do it, though i think Mahdi can extract it right after this note.

    100% sure its 3 param !


  2. 10 minutes ago, Stefan Glienke said:

    Just to make sure you don't misunderstand:

    The common way of compilers (check it for yourself using compiler explorer) to write while x do is to turn it into if x then repeat until not x (simply said). The code you posted could get rid of the check at the bottom because there was nothing else to do after the check for '0' which results in a result true so that basically serves as this loop breaking check.

    The first check makes sure the loop is even entered at all, otherwise it jumps over it (0 iterations) - the "real" loop condition is at the bottom of the loop body.

     

    What is usually not good is to only put the loop condition at the bottom and statically jump over the loop body (because the duplicated condition at the top is missing). Thats two unnecessary jumps for the common case of "at least 1 iteration".

    Yeah Stefan, I clearly understand you. But the same thing you described can be achieved by branch prediction. So compiler should not generate such code unless you are targeting an old cpu. 


  3. 7 minutes ago, Stefan Glienke said:

    Here it is clearly not - but I was referring to the fact that mostly it is the way to do - see this exhaustive answer.

    But what you typically don't do is to statically jump over the loop body to the condition at the bottom to then conditionally jump back up because the loop runs at least once.

    Either the compiler restructures the loop or simply puts the loop condition as if ontop of the loop as well (sometimes dcc even does it)

    Today no high end compiler is doing that because it affects an important optimization part OoOE. Delphi uses a very old code generator that is not up to date.


  4. @Stefan Glienke 

    Quote

    Well - I did not - lets see - gcc and clang both generate this (so does vc++ I guess):

    As I said before, MSVC is somehow far behind gcc and clang. In fact, it used 8-bit registers heavily which are known to be slow as they require internal manipulation by the CPU:

    00241000 8A 0D 10 21 24 00    mov         cl,byte ptr [string "test" (0242110h)]  
    00241006 B8 10 21 24 00       mov         eax,offset string "test" (0242110h)  
    0024100B 0F 1F 44 00 00       nop         dword ptr [eax+eax]  
    00241010 40                   inc         eax  
    00241011 80 F9 30             cmp         cl,30h  
    00241014 74 09                je          test1+1Fh (024101Fh)  
    00241016 8A 08                mov         cl,byte ptr [eax]  
    00241018 84 C9                test        cl,cl  
    0024101A 75 F4                jne         test1+10h (0241010h)  
    0024101C 32 C0                xor         al,al  
    0024101E C3                   ret  
    0024101F B0 01                mov         al,1  
    00241021 C3                   ret  

    For Delphi, output of Test1 and Test2 is very close. In fact if you change to PChar, you may find that unlike Test1, Test2 is using add reg, imm instruction.

    Quote

    What we can see is that the Delphi compiler is clearly not clever but rather sticks to some hardcoded behavior such as that it is addicted to put loop conditions after the body (which usually is a good pattern)

    No its not a good pattern :  

    0041BD92 EB09             jmp $0041bd9d  // unecessary relative branch.
    0041BD94 80F930           cmp cl,$30     // suppose this was a load op => bad for OoOE.
    0041BD97 7503             jnz $0041bd9c   
    0041BD99 B001             mov al,$01  
    0041BD9B C3               ret 

     

    Quote

    At least regarding life expectancy 😉

    Just hope for better.

     


  5. 6 minutes ago, Anders Melander said:

    I wouldn't say the future looks good when you're on life support. Naturally Cobol will die for good some day, when the systems using it are finally retired, but I'm pretty sure it will outlive for example JavaScript. Of course this doesn't mean that we should all drop what we're doing and learn Cobol instead. What I meant was that this statement:

    appears to assume that it's the popularity among "young people" that decides if a language thrives. There's some truth in that, but it's not the whole story. It's ultimately "the grown ups" that decides what tools to use to get the job done. That's why we don't have to rewrite EVERYTHING every few years when a new shiny toy appears.

    Yeah it makes very sense.


  6. 18 minutes ago, Anders Melander said:

    So I'm guessing the asm it generates uses indexed addressing rather that indirect addressing. Right?

    No

    mov         cl,byte ptr [eax]  

    At CPU level indexed addressing = indirect addressing. The only difference is that an indexed addressing can have an expression inside []. Sometime this could be just good for alignment purpose. [eax] = [eax+0x00].
    But Stefan was referring to something else register usage for each load instruction.

    • Thanks 1

  7. 1 hour ago, Anders Melander said:

    My experience is that in some cases indexed access can be much faster than incrementing a pointer, so I guess "it depends".

    I'm afraid I can't remember any specific cases.

    It even depends on your compiler. If your compiler is smart enough, it will generate better code sometime better than using pointer because compiler can understand better integer behavior than pointer. Using MSVC (which is not really smart enough) to compile those two function, generates EXACTLY the SAME opcodes for both !

    __declspec(noinline)
    bool test1(const char* str) {
    	int i = 0;
    	while (str[i]) if ('0' == str[i++]) return true;
    	return false;
    }
    
    __declspec(noinline)
    bool test2(const char* str) {
    	char* p = (char*)&str[0];
    	while (*p) if ('0'  == *p++ ) 	return true;
    	return false;
    }

     


  8. 1 hour ago, Anders Melander said:

    There are more developers than there are developer jobs. Some will have to take what they can get and use the tools that the job require.

    That's just the way the world works. Otherwise we would all be astronauts or firemen.

    Yes I understand that but would we be able to assume that the future for that language is good ?


  9. 3 hours ago, Stefan Glienke said:

    No, because if you are doing something with whatever is at x[ i ] its faster to use a pointer that starts at @x[ 0 ] and just inc that rather than having a loop which then has 2 counter variables (they like to count down to zero while maintaining the upwards counting i). And on x86 that is a precious register that can be used for something else.

    Yes, you're absolutely right.


  10. 3 minutes ago, Mike Torrettinni said:

    Here I am thinking if increasing char pointer is faster than using integer iterator, while you guys are discussing condition branching and using stack and full set of registries 🙂

    On x86, sizeof(pointer) = sizeof(integer) so its much likely you are going to have the same performance.

    On x64, sizeof(pointer) = sizeof(int64) so using integer could be some how better.

    This was just a general rule, but does not apply always as it depends on the way you're using your code.


  11. 18 minutes ago, Sherlock said:

    Yeah, all the cool kids want to JavaScript, while banks and insurance companies are going out of their way to pay regal salaries to those old COBOL geezers. COBOL delivers, where JS just looks shiny.

    Exactly, you hit the nail on the head. 


  12. @Kas Ob. I noticed that you take optimization very seriously. That's really good but just as an advice from someone that did, don't be driven too much. Behind that optimization door resides the evil ! In fact, I spent much time reading Intel doc/books, comparing different compilers (gcc, clang, ...). At the end I become more obsessional and less productive as I started paying much attention to my codes than what is required like taking some time to decide whether I should write if a = b or if a <> b.

    • Like 2

  13. 45 minutes ago, Rollo62 said:

     Sorry Mahdi Safsafi, I think this is same issue as above.

    This very same text line is from 1995 too, please update that as well to a more modern version.

    Nothing last for ever. its just a question of time. COBOL developers are old by now and the time they go for retiring, No one would be there to fill that gap as the language is unable to attract young developers. A programming language that is unable to attract young people would likely to have no future.

    Its hard to me to declare the above statements but that's the reality -whether we liked or not-.


  14. 50 minutes ago, Lars Fosdal said:

    A language dies when it is no longer in use. COBOL is alive and kicking, but good luck finding young COBOL programmers.

    Soon or later current COBOL developers are going to retire. So if its not died ... its dying.


  15. 27 minutes ago, Attila Kovacs said:

    Looking into the Move() implementation, wth is happened to rep movs*? Is it too slow nowadays?

    AFAIK it gets a little bit better on modern CPU. However it's getting abandoned on favor of SIMD instructions.

    IMO, I think that the RTL Move routine should be implemented as an intrinsic (not a function) in that way the compiler can generate a much better code. 


  16. 57 minutes ago, Mike Torrettinni said:

    I wish I was wrong and we have a generation of new Delphi developers, but perhaps Community edition, Academy and other activities could slowly add a few of them.

    Its much complex than offering a community edition and an academy. 

    In the last decade the market was bload up with new programming languages(thanks to LLVM). Those languages are very easy and very attractive for young people. Moreover they're free and have a wide community support(thanks to the big tech behind them). Delphi on the other hand is an old language and is no longer considered as the easiest language. Today developers are not like old developers. Today developers tend to seek for easy and fast solution without much complexity(i.e : GC).

    Quote

    but their main focus doesn't seem to be new developers.

    A language is considered dead when its no longer able to attract young people. Delphi can't compete with those languages. Not because its bad ... but because is not able to satisfy a particular range of new developers. I believe EMB understood clearly this. that's why it focuses on old developers, on compatibility and does not spend much on resources.  


  17. For me I'd go with AddObject as its better than using Pair<Name, Value>. However you can either set CheckListBox1.Style to lbVirtual and then handle all data event. Or simply set Style to lbOwnerDrawFixed and owner draw your control:

    // CheckListBox1.Style := lbOwnerDrawFixed;
    
    procedure TMain.CheckListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
    var
      Flags: Longint;
      Data: String;
      FCanvas: TCanvas;
      CheckListBox: TCheckListBox;
    begin
      CheckListBox := TCheckListBox(Control);
      FCanvas := CheckListBox.Canvas;
      FCanvas.FillRect(Rect);
      if Index < CheckListBox.Count then
      begin
        Flags := DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX);
        if not UseRightToLeftAlignment then
          Inc(Rect.Left, 2)
        else
          Dec(Rect.Right, 2);
        Data := CheckListBox.Items.Names[Index];
    
        DrawText(FCanvas.Handle, Data, Length(Data), Rect, Flags);
      end;
    end;

    EDIT:

    Removed ExtractName function.

    • Thanks 1

  18. 22 minutes ago, Dalija Prasnikar said:

    I literally just started typing same sentence.

     

    Delphi devs always complain all logic is dumped in form (event handlers), Android devs always complain all logic is dumped in Activity (Delphi form equivalent), iOs devs always complain all logic is dumped in ViewController (again Delphi form equivalent)...

    That reminded me about a nice quote :

    Quote

    “There are only two kinds of languages: the ones people complain about and the ones nobody uses.” ― Bjarne Stroustrup.

     

    • Like 5
    • Haha 3

  19. 1 hour ago, David Heffernan said:

     

    I can't reconcile these two statements. 

    Quote

    Not always a bad code

    If I meant it to be a good practice, I'd say its not a bad code.

    My point was that no one should rely on the object after a call has been made to free regardless whether an exception occurred or not ... and I still retain that position. For that point, I gave some example just for explanation but never considered it as a good practice. A good practice from my point of view is to expect the worse not to expect all people are following the good practice.

    BTW, those destructors for the VCL/RTL (the way are implemented) are not safe.

    Hope that this explicit statement clarify things for you. 

×