Hello,
Je regardais un peu la tronche du code généré par DMD (v2.064), compilé en release, avec infos de debug.
Au niveau des options de compilation, j'ai testé avec et sans "Run optimizer", avec et sans "Expand inline functions", et le résultat est le même.
Et il y a deux / trois trucs que je comprends pas vraiment
Code D : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 class Foo { // ... public static auto table() { static auto t = makeTable!(Foo, "data1", "data2")(); return t; } } immutable(SqlTable!T) makeTable(T, Q...)() { SqlColumn!T[] columns; foreach(arg; Q) { columns ~= makeColumn!(T, arg)(); } return new SqlTable!T(T.stringof, columns); }
En D, toute les fonctions sont virtuelles par défaut et le compilo se débrouille (pour simplifier la vie du développeur et normalement parce qu' le compilo sait mieux que nous si une doit être virtuelle ou pas).
Aucune classe ne dérive de Foo, il n'y à aucune utilité à avoir Foo.table() virtuelle, et vu la fonction elle "devrait" donc être inline.
Ici elle n'est pas virtuelle, mais pas inlinée.
DMD génère ceci :Pourquoi générer une fonction pour ça ?
Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 _TEXT:004020A8 ; sqlite3@SqlTable!(Foo)@SqlTable *__pascal main_Foo_table() _TEXT:004020A8 main@Foo@table proc near ; CODE XREF: sqlite3@SqliteDB@insert__class_main@Foo_@insert+7p _TEXT:004020A8 ; sqlite3@SqliteDB@prepareStatement__class_main@Foo_@prepareStatement+5p ... _TEXT:004020A8 mov eax, ds:main@Foo@table@ _TEXT:004020AD retn _TEXT:004020AD main@Foo@table endp
Dans l'exe on retrouve aussi la fonction makeTable, qui n'est jamais appelée (et rien n'y fait référence), quelle peut être la raison d'inclure du code inutile ?
Concernant la fonction Foo.table(), en la changeant de
Code D : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 public static auto table() { static auto t = makeTable!(Foo, "data1", "data2")(); return t; } // à public static auto table() { return makeTable!(Foo, "data1", "data2")(); }
DMD génère
Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 _TEXT:00402068 ; sqlite3@SqlTable!(Foo)@SqlTable *__pascal main_Foo_table() _TEXT:00402068 main@Foo@table proc near ; CODE XREF: sqlite3@SqliteDB@insert__class_main@Foo_@insert+7p _TEXT:00402068 ; sqlite3@SqliteDB@prepareStatement__class_main@Foo_@prepareStatement+5p ... _TEXT:00402068 push eax _TEXT:00402069 call sqlite3@makeTable__class_main@Foo__immutable_char_____data1_c__immutable_char_____data2_c_@makeTable _TEXT:0040206E pop ecx _TEXT:0040206F retn _TEXT:0040206F main@Foo@table endp
On retrouve ici un appel à makeTable, mais encore une fois, pourquoi elle n'est pas inliné ? Et pourquoi cela génère un appel à makeTable ? Le fait d'avoir des données immutable ne devrait pas rendre cet appel inutile ?
L'optimisation prématurée c'est mal, mais j'aimerai juste comprendre pourquoi le code généré est ainsi.
Partager