Autor Téma: Prekladac mproblemy s prekladem inferovaneho typu polozky generickeho open array  (Přečteno 1564 krát)

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2600
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Nekdy v listopadu jsem se ptal, zda nekdo nema nejaky napad, jak implementovat serializer/deserializer viz zde.

Tenkrat jsem to implementoval, napsal k tomu unit testy a vse fungovalo. Ted jsem se k projektu vratil, ze budu pokracovat a zacal jsem spusteni tech unit testu, z nichz mi nektere neprosly.

Kdyz jsem patral, co se deje, tak jsem zjistil, ze Delphi 10.2 Tokyo 32bit spatne preklada predani hodnoty polozky z generickeho open array, konkretne u typu int64/uint64. Pro kod
Kód: Delphi [Vybrat]
  1. for idx := 0 to Length(AArray) - 1 do
  2.   PutInt64(AStream, PInt64(@AArray[idx])^);
prelozi chybne predani polozky pole jako (eax adresa 1. elementu pole, edx je index polozy idx):
Kód: ASM [Vybrat]
  1. push dword ptr [eax+edx*2+$04]
  2. push dword ptr [eax+edx*2]

pricemz spravne ma byt
Kód: ASM [Vybrat]
  1. push dword ptr [eax+edx*8+$04]
  2. push dword ptr [eax+edx*8]

Tak jsem sel vyrobit SSCCE v podobe console application, a tam je preklad spravne, stejne jako v inverzni funkci GetArray<T> v aplikaci. U ostatnich typu se zda, ze Delphi typ inferuje spravne i to spravne prelozi tj. bere edx*sizeof(T)

Ale co je nejhorsi, ze kdyz jsem se v tom zacal hrabat, tak to Delphi najednou zacal prekladat spatne jeste jinak jako  :o
Kód: ASM [Vybrat]
  1. push dword ptr [eax+edx+$04]
  2. push dword ptr [eax+edx]

Co je jeste divnejsi, kdyz zmenim implementaci toho cyklu s uzitim ukazatele na pole int64, tak to v aplikaci prelozi stejne blbe se (sizeof<T>=1), zatimco v SSCCE je to prelozene spravne.
Kód: Delphi [Vybrat]
  1. p64a := @AArray[0];
  2. for idx := 0 to Length(AArray) - 1 do
  3.   PutInt64(AStream, p64a^[idx]);

Nakonec jsem se uchylil k "rucnimu" prekladu tech cyklu:
Kód: Delphi [Vybrat]
  1. p64 := @AArray[0];
  2. for idx := 0 to Length(AArray) - 1 do
  3. begin
  4.   PutInt64(AStream, p64^);
  5.   inc(p64, 1);
  6. end;

Ale nemam z toho dobry pocit, protoze ta puvodni implementace fungovala v listopadu taky dobre.

--

Nevidi nekdo, jestli nepracuju s nejakymi mylnymi predpoklady? Nebo co muze byt pricinou toho, ze Delphi preklad je ovlivnen vetrem na Marsu.
Poslal bych dotaz na SO, kde je prece jenom vetsi auditorium, ale tam by urcite chteli SSCCE a ten se mi nedari vytvorit resp. v opravdu minimalni verzi se chyba nezopakuje.

Online Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 2362
  • Karma: 102
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Takovy hloupy dotaz, neni to ve funkci, ktera má více parametrů (> 3).
Embarcadero MVP - Czech republic

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2600
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Takovy hloupy dotaz, neni to ve funkci, ktera má více parametrů (> 3).
nevim, jestli rozumim dotazu, ale signatura metody, ktera dostane to genericke open array vypada:
Kód: Delphi [Vybrat]
  1. class procedure PutSimpleArray<T>(AStream: TStream; const AArray: array of T);
  2. class function GetSimpleArray<T>(AStream: TStream): TArray<T>;

a pro kazdy typ na zaklade introspekce se volaji metody se dvema parametry, napr.
Kód: Delphi [Vybrat]
  1. class procedure PutUInt64(AStream: TStream; AValue: qword);
  2. class function GetUInt64(AStream: TStream): qword;
  3.  

s tim, ze jak jsem psal, u Get se to neprojevuje a preklad vypada OK.


Online Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 2362
  • Karma: 102
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
A nemuzes vytvořit konzolovou aplikaci s tou tvoji jednotkou serializace misto nového SSCCE?
Nebo tam se to taky neprojevuje?
Embarcadero MVP - Czech republic

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2600
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
A nemuzes vytvořit konzolovou aplikaci s tou tvoji jednotkou serializace misto nového SSCCE?
No pro sebe ji vytvorit muzu, protoze to zacne chtit dalsi basalni jednotky z frameworku. Ale pak z toho udelat SSCCE, ktery by se dal publikovat by byla asi dost alchymie...

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2600
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
A nemuzes vytvořit konzolovou aplikaci s tou tvoji jednotkou serializace misto nového SSCCE?
Tak jsem presunul vse podstatne ze serializeru do consolove aplikace a chybu se povedlo zopakovat, shodou okolnosti taky jednou prelozeno jako eax+edx+..., jindy jako eax+edx*2+.... A dokonce to jednou prelozilo i spravne. Zkratka vitr na Marsu. Ze to nefunguje poznas tak, ze si nechas zobrazit obsah pole arrayOfQWords,h (hexadecimalne) a/nebo ze vtrasujes dovnitr PutSimpleArray a na volani PutUInt64 si zobrazis CPU okno. Spravne prelozene to ma byt:
Kód: Delphi [Vybrat]
  1. push dword ptr [eax+edx*8+$04]
  2. push dword ptr [eax+edx*8]

Consolovku jsem chtel pripojit, ale nedovoli to .dproj  ani zpravu delsi jak 20000 znaku, kdyz jsem to chtel dat do code >:(

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4472
  • Karma: 39
    • Verze Delphi: XE7 professional
Skús ju dať na úložisko. Možno si ju stiahnu. Aj keď tomu veľmi neverím.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2600
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Skús ju dať na úložisko. Možno si ju stiahnu. Aj keď tomu veľmi neverím.
Pribalil jsem ji jako .zip


Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 786
  • Karma: 43
    • Verze Delphi: 10.3
Pribalil jsem ji jako .zip

Jenže tam chybí .dpr ;-)

Online Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 2362
  • Karma: 102
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Pribalil jsem ji jako .zip

Jenže tam chybí .dpr ;-)

Resp. je tam jen dproj
Embarcadero MVP - Czech republic

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2600
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Pribalil jsem ji jako .zip
Jenže tam chybí .dpr ;-)
Sorry, tak snad ted.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2600
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Porad jsem premital, jak je mozne, ze Delphi vypocet adresy polozky pole preklada natvrdo tj. eax+edx*8+... a zjistil jsem, ze zrejme z duvodu rychlosti vytvari pro kazde T vlastni preklad. Kdyz napisu dummy metodu:
Kód: Delphi [Vybrat]
  1. class procedure TAny.DoSometing<T>(const AArray: array of T);
  2. var
  3.   Idx: integer;
  4.   v: T;
  5. begin
  6.   for Idx := 0 to length(AArray)-1 do
  7.     v := AArray[idx];
  8. end;
  9.  
a pak ji zavolam napr.
Kód: Delphi [Vybrat]
  1. TAny.DoSometing<int64>(arrayOfInt64s);
  2. TAny.DoSometing<int16>(arrayOfInt16s);
  3.  
a vtrasuju dovnitr, tak v prvnim pripade se dostanu na preklad:
Kód: ASM [Vybrat]
  1. SSCCE_ArrayOfInt64.dpr.26: v := AArray[idx];
  2. 004D102F 8B45F8           mov eax,[ebp-$08]
  3. 004D1032 8B55F0           mov edx,[ebp-$10]
  4. 004D1035 8B0CD0           mov ecx,[eax+edx*8]
  5. 004D1038 894DE8           mov [ebp-$18],ecx
  6. 004D103B 8B4CD004         mov ecx,[eax+edx*8+$04]
  7. 004D103F 894DEC           mov [ebp-$14],ecx
  8. 004D1042 FF45F0           inc dword ptr [ebp-$10]
resp. v pripade int16 na
Kód: ASM [Vybrat]
  1. SSCCE_ArrayOfInt64.dpr.26: v := AArray[idx];
  2. 004D1073 8B45F8           mov eax,[ebp-$08]
  3. 004D1076 8B55F0           mov edx,[ebp-$10]
  4. 004D1079 668B0450         mov ax,[eax+edx*2]
  5. 004D107D 668945EE         mov [ebp-$12],ax
  6. 004D1081 FF45F0           inc dword ptr [ebp-$10]

viz rozdilne hodnoty adres kodu v pameti. Preklady jsou spravne a z toho mi vychazi, ze by to mela byt v Delphi legalni konstrukce, takze nechci po Delphi nemozne, akorat v pripade te metody s case se jim preklad nekdy nejak nepovede...
« Poslední změna: 15-01-2019, 13:41:36 od pf1957 »

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2600
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Na zaklade poznatku, ze Delphi preklada samostatne kazde T jeste musim zkontrolovat, jestli preklad neni v poradku, ale spatne to urci, jakou metodu to ma zavolat.
Tak ne, vola to spravnou alternativu prekladu, ale ta pro int64 je chybna
« Poslední změna: 15-01-2019, 13:29:06 od pf1957 »

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 786
  • Karma: 43
    • Verze Delphi: 10.3
Tak v Delphi 10.3 to je taky špatně:
Kód: Delphi [Vybrat]
  1. 004D6992 FF741004         push dword ptr [eax+edx+$04]
  2. 004D6996 FF3410           push dword ptr [eax+edx]

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 786
  • Karma: 43
    • Verze Delphi: 10.3
Na zaklade poznatku, ze Delphi preklada samostatne kazde T jeste musim zkontrolovat, jestli preklad neni v poradku, ale spatne to urci, jakou metodu to ma zavolat.

sizeof(AArray[0]) tam vrací 8.