### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: [SOLVED] Using high instead of length in rtl/objpas/typinfo.pp  (Read 842 times)

#### lagprogramming

• Sr. Member
• Posts: 376
##### [SOLVED] Using high instead of length in rtl/objpas/typinfo.pp
« on: May 26, 2023, 08:49:40 pm »
rtl/objpas/typinfo.pp has
Function IndexOfEnumeratedAliases(aTypeInfo : PTypeInfo) : integer;
procedure RemoveEnumElementAliases(aTypeInfo: PTypeInfo);
function GetEnumeratedAliasValue(aTypeInfo: PTypeInfo; const aName: string): Integer;

In these routines values like Length(array)-1 are assigned to variables.
The following patch modifies the file to use High instead of Length.

Code: Pascal  [Select][+][-]
1. diff --git a/rtl/objpas/typinfo.pp b/rtl/objpas/typinfo.pp
2. index da6a889b08..2e6b903465 100644
3. --- a/rtl/objpas/typinfo.pp
4. +++ b/rtl/objpas/typinfo.pp
5. @@ -3666,7 +3666,7 @@   TEnumeratedAliases = record
6.  Function IndexOfEnumeratedAliases(aTypeInfo : PTypeInfo) : integer;
7.
8.  begin
9. -  Result:=Length(EnumeratedAliases)-1;
10. +  Result:=High(EnumeratedAliases);
11.    while (Result>=0) and (EnumeratedAliases[Result].TypeInfo<>aTypeInfo) do
12.      Dec(Result);
13.  end;
14. @@ -3709,7 +3709,7 @@ procedure RemoveEnumElementAliases(aTypeInfo: PTypeInfo);
15.    A:=EnumeratedAliases[i];
16.    A.Aliases:=Nil;
17.    A.TypeInfo:=Nil;
18. -  L:=Length(EnumeratedAliases)-1;
19. +  L:=High(EnumeratedAliases);
20.    EnumeratedAliases[i]:=EnumeratedAliases[L];
21.    EnumeratedAliases[L]:=A;
22.    SetLength(EnumeratedAliases,L);
23. @@ -3775,7 +3775,7 @@ function GetEnumeratedAliasValue(aTypeInfo: PTypeInfo; const aName: string): Int
24.    Aliases:=GetEnumeratedAliases(aTypeInfo);
25.    if (Aliases=Nil) then
26.      Exit;
27. -  I:=Length(Aliases^)-1;
28. +  I:=High(Aliases^);
29.    While (Result=-1) and (I>=0) do
30.      begin
31.      if SameText(Aliases^[I].Alias, aName) then
« Last Edit: May 27, 2023, 07:51:06 pm by lagprogramming »

#### PascalDragon

• Hero Member
• Posts: 5210
• Compiler Developer
##### Re: Using high instead of length in rtl/objpas/typinfo.pp
« Reply #1 on: May 26, 2023, 10:21:27 pm »

#### BrunoK

• Sr. Member
• Posts: 446
• Retired programmer
##### Re: Using high instead of length in rtl/objpas/typinfo.pp
« Reply #2 on: May 27, 2023, 02:14:53 pm »
FPC 3.2.2 x86_64

What is the purpose of the change, is it to gain a few bytes of memory ?

It seems that Length(Array) - 1 generates inline assembly code without any call whereas high(Array) calls <fpc_dynarray_high>

#### lagprogramming

• Sr. Member
• Posts: 376
##### Re: Using high instead of length in rtl/objpas/typinfo.pp
« Reply #3 on: May 27, 2023, 03:52:23 pm »
FPC 3.2.2 x86_64

What is the purpose of the change, is it to gain a few bytes of memory ?

It seems that Length(Array) - 1 generates inline assembly code without any call whereas high(Array) calls <fpc_dynarray_high>

EDIT:
I've made a confusion between the assembly of the original code and the assembly of the modified code, most likely due to wrong editor tabs.
In the initial post I've presented the assembly of the original code as the assembly produced for the modified code. I'm updating the text.

Following your post, using a recent FPC development version I've looked at the code produced for the ORIGINAL procedure RemoveEnumElementAliases(aTypeInfo: PTypeInfo);
Code: Pascal  [Select][+][-]
1. 00000000004F5ED0 53                       push rbx
2. 00000000004F5ED1 4154                     push r12
3. 00000000004F5ED3 488D642488               lea rsp,[rsp-\$78]
4. 00000000004F5ED8 4889FB                   mov rbx,rdi
5. 00000000004F5EDB 4889E7                   mov rdi,rsp
6. 00000000004F5EDE 488D35D3193400           lea rsi,[rip+\$003419D3]
7. 00000000004F5EE5 E8B6C6F3FF               call -\$000C394A    # \$00000000004325A0 fpc_initialize
8. 00000000004F5EEA 488D542410               lea rdx,[rsp+\$10]
9. 00000000004F5EEF 488D742428               lea rsi,[rsp+\$28]
10. 00000000004F5EF4 BF01000000               mov edi,\$00000001
11. 00000000004F5EF9 E882A2F3FF               call -\$000C5D7E    # \$0000000000430180 fpc_pushexceptaddr
12. 00000000004F5EFE 4889C7                   mov rdi,rax
13. 00000000004F5F01 E80A81F2FF               call -\$000D7EF6    # \$000000000041E010 fpc_setjmp
14. 00000000004F5F06 89442468                 mov [rsp+\$68],eax
15. 00000000004F5F0A 85C0                     test eax,eax
16. 00000000004F5F0C 0F85FE000000             jnz +\$000000FE    # \$00000000004F6010 TYPINFO_\$\$_REMOVEENUMELEMENTALIASES\$PTYPEINFO+320
17. 00000000004F5F12 4889DF                   mov rdi,rbx
18. 00000000004F5F15 E8C6FEFFFF               call -\$0000013A    # \$00000000004F5DE0 TYPINFO_\$\$_INDEXOFENUMERATEDALIASES\$PTYPEINFO\$\$LONGINT
19. 00000000004F5F1A 89C3                     mov ebx,eax
20. 00000000004F5F1C 83F8FF                   cmp eax,\$FF
21. 00000000004F5F1F 0F840B010000             jz +\$0000010B    # \$00000000004F6030 TYPINFO_\$\$_REMOVEENUMELEMENTALIASES\$PTYPEINFO+352
22. 00000000004F5F25 4889E6                   mov rsi,rsp
23. 00000000004F5F28 488D05D14E6300           lea rax,[rip+\$00634ED1]
24. 00000000004F5F2F 488B10                   mov rdx,[rax]
25. 00000000004F5F32 4863C3                   movsxd rax,ebx
26. 00000000004F5F35 48C1E004                 shl rax,\$04
27. 00000000004F5F39 488D3C02                 lea rdi,[rax+rdx]
28. 00000000004F5F3D 488D1574193400           lea rdx,[rip+\$00341974]
29. 00000000004F5F44 E8D7C9F3FF               call -\$000C3629    # \$0000000000432920 FPC_COPY
30. 00000000004F5F49 48C744247000000000       mov qword ptr [rsp+\$70],\$00000000
31. 00000000004F5F52 488D4C2470               lea rcx,[rsp+\$70]
32. 00000000004F5F57 488D3512193400           lea rsi,[rip+\$00341912]
33. 00000000004F5F5E 488D7C2408               lea rdi,[rsp+\$08]
34. 00000000004F5F63 BA01000000               mov edx,\$00000001
35. 00000000004F5F68 E87371F3FF               call -\$000C8E8D    # \$000000000042D0E0 fpc_dynarray_setlength
36. 00000000004F5F6D 48C7042400000000         mov qword ptr [rsp],\$00000000
37. 00000000004F5F75 488D05844E6300           lea rax,[rip+\$00634E84]
38. 00000000004F5F7C 4C8B20                   mov r12,[rax]
39. 00000000004F5F7F 4D85E4                   test r12,r12
40. 00000000004F5F82 7409                     jz +\$09    # \$00000000004F5F8D TYPINFO_\$\$_REMOVEENUMELEMENTALIASES\$PTYPEINFO+189
41. 00000000004F5F84 4D8B6424F8               mov r12,[r12-\$08]
43. 00000000004F5F8D 4983EC01                 sub r12,\$01
44. 00000000004F5F91 488D05684E6300           lea rax,[rip+\$00634E68]
45. 00000000004F5F98 488B00                   mov rax,[rax]
46. 00000000004F5F9B 4863DB                   movsxd rbx,ebx
47. 00000000004F5F9E 48C1E304                 shl rbx,\$04
48. 00000000004F5FA2 488D3418                 lea rsi,[rbx+rax]
49. 00000000004F5FA6 488D05534E6300           lea rax,[rip+\$00634E53]
51. 00000000004F5FB0 4963C4                   movsxd rax,r12d
52. 00000000004F5FB3 48C1E004                 shl rax,\$04
53. 00000000004F5FB7 488D3C02                 lea rdi,[rax+rdx]
54. 00000000004F5FBB 488D15F6183400           lea rdx,[rip+\$003418F6]
55. 00000000004F5FC2 E859C9F3FF               call -\$000C36A7    # \$0000000000432920 FPC_COPY
56. 00000000004F5FC7 488D05324E6300           lea rax,[rip+\$00634E32]
57. 00000000004F5FCE 488B10                   mov rdx,[rax]
58. 00000000004F5FD1 4963C4                   movsxd rax,r12d
59. 00000000004F5FD4 48C1E004                 shl rax,\$04
60. 00000000004F5FD8 488D3402                 lea rsi,[rax+rdx]
61. 00000000004F5FDC 4889E7                   mov rdi,rsp
62. 00000000004F5FDF 488D15D2183400           lea rdx,[rip+\$003418D2]
63. 00000000004F5FE6 E835C9F3FF               call -\$000C36CB    # \$0000000000432920 FPC_COPY
64. 00000000004F5FEB 4D63E4                   movsxd r12,r12d
65. 00000000004F5FEE 4C89642470               mov [rsp+\$70],r12
66. 00000000004F5FF3 488D4C2470               lea rcx,[rsp+\$70]
67. 00000000004F5FF8 488D3511193400           lea rsi,[rip+\$00341911]
68. 00000000004F5FFF 488D3DFA4D6300           lea rdi,[rip+\$00634DFA]
69. 00000000004F6006 BA01000000               mov edx,\$00000001
70. 00000000004F600B E8D070F3FF               call -\$000C8F30    # \$000000000042D0E0 fpc_dynarray_setlength
71. 00000000004F6010 E8ABA4F3FF               call -\$000C5B55    # \$00000000004304C0 fpc_popaddrstack
72. 00000000004F6015 4889E7                   mov rdi,rsp
73. 00000000004F6018 488D3599183400           lea rsi,[rip+\$00341899]
74. 00000000004F601F E86CC6F3FF               call -\$000C3994    # \$0000000000432690 FPC_FINALIZE
75. 00000000004F6024 837C246800               cmp dword ptr [rsp+\$68],\$00
76. 00000000004F6029 740F                     jz +\$0F    # \$00000000004F603A TYPINFO_\$\$_REMOVEENUMELEMENTALIASES\$PTYPEINFO+362
77. 00000000004F602B E840A6F3FF               call -\$000C59C0    # \$0000000000430670 FPC_RERAISE
78. 00000000004F6030 C744246800000000         mov [rsp+\$68],\$00000000
79. 00000000004F6038 EBD6                     jmp -\$2A    # \$00000000004F6010 TYPINFO_\$\$_REMOVEENUMELEMENTALIASES\$PTYPEINFO+320
80. 00000000004F603A 488D642478               lea rsp,[rsp+\$78]
81. 00000000004F603F 415C                     pop r12
82. 00000000004F6041 5B                       pop rbx
83. 00000000004F6042 C3                       ret
The number of call instructions didn't changed but I've noticed that the modified code is smaller. Looking for the most likely problem I've noticed the following lines in the ORIGINAL assembly code:
Code: Pascal  [Select][+][-]
1. 00000000004F5F75 488D05844E6300           lea rax,[rip+\$00634E84]
2. 00000000004F5F7C 4C8B20                   mov r12,[rax]
3. 00000000004F5F7F 4D85E4                   test r12,r12
4. 00000000004F5F82 7409                     jz +\$09    # \$00000000004F5F8D TYPINFO_\$\$_REMOVEENUMELEMENTALIASES\$PTYPEINFO+189
5. 00000000004F5F84 4D8B6424F8               mov r12,[r12-\$08]
7. 00000000004F5F8D 4983EC01                 sub r12,\$01
8. 00000000004F5F91 488D05684E6300           lea rax,[rip+\$00634E68]
Those add & sub instructions look strange. I don't know what's the best way to continue, a bugtracker entry!?
« Last Edit: May 27, 2023, 07:46:12 pm by lagprogramming »

#### runewalsh

• Jr. Member
• Posts: 55
##### Re: Using high instead of length in rtl/objpas/typinfo.pp
« Reply #4 on: May 27, 2023, 07:37:16 pm »
high generates better code because internally, dynamic array lengths in dynamic array headers store high value directly, not length. Both involve a branch anyway, to check for empty array. (And at least in trunk, seems as if none of them ever call fpc_dynarray_high on i386 and x86_64.)

#### lagprogramming

• Sr. Member
• Posts: 376
##### Re: Using high instead of length in rtl/objpas/typinfo.pp
« Reply #5 on: May 27, 2023, 07:50:48 pm »
high generates better code because internally, dynamic array lengths in dynamic array headers store high value directly, not length. Both involve a branch anyway, to check for empty array. (And at least in trunk, seems as if none of them ever call fpc_dynarray_high on i386 and x86_64.)
I've updated my last post. There was a confusion. I mark the subject [SOLVED] but I think somebody should consider if it's necessary to fill a bug report regarding those add and sub instructions. They were found in the original Pascal code, the one that used Length.

Quote
Code: Pascal  [Select][+][-]
1.     00000000004F5F75 488D05844E6300           lea rax,[rip+\$00634E84]
2.     00000000004F5F7C 4C8B20                   mov r12,[rax]
3.     00000000004F5F7F 4D85E4                   test r12,r12
4.     00000000004F5F82 7409                     jz +\$09    # \$00000000004F5F8D TYPINFO_\$\$_REMOVEENUMELEMENTALIASES\$PTYPEINFO+189
5.     00000000004F5F84 4D8B6424F8               mov r12,[r12-\$08]