Tu parles des perfs, et tu utilises Java ? :-)
Il parait que le problème de transtypage a été résolu, et que
Java a aussi des templates aujourd'hui. Mais c'était
effectivement un problème dans le temps.
Tu parles des perfs, et tu utilises Java ? :-)
Il parait que le problème de transtypage a été résolu, et que
Java a aussi des templates aujourd'hui. Mais c'était
effectivement un problème dans le temps.
Tu parles des perfs, et tu utilises Java ? :-)
Il parait que le problème de transtypage a été résolu, et que
Java a aussi des templates aujourd'hui. Mais c'était
effectivement un problème dans le temps.
Jean-Marc Bourguet wrote on 23/09/2006 07:55:je suis plutôt de l'avis de Alain, tester le cas
d'auto-affectation me parait même indispensable pour a) ne
pas risquer de perdre les données,
Si le test est nécessaire pour éviter de perdre des données
dans le cas de l'auto-affectation, il y a de gros risques
que le code en fait ne soit pas robustes en présence
d'exceptions.
les 2 peuvent être vrai sans être liés.
....et devrait être
...
(les if pouvant être mieux utilisés, ce n'est pas le point)
j'aurais peut-être du mettre la remarque précédente en gras
plutôt qu'entre parenthèse.Pourquoi pas tout simplement:
if (other.ref) other.ref->addRef();
if (ref) ref->release();
ref = other.ref;
les if pouvaient être différents de ceux écrits, il reste et
tu le confirmes que pour ne pas faire un if (*this == other)
tu fais 2 if sur le membre 'ref'.
Jean-Marc Bourguet wrote on 23/09/2006 07:55:
je suis plutôt de l'avis de Alain, tester le cas
d'auto-affectation me parait même indispensable pour a) ne
pas risquer de perdre les données,
Si le test est nécessaire pour éviter de perdre des données
dans le cas de l'auto-affectation, il y a de gros risques
que le code en fait ne soit pas robustes en présence
d'exceptions.
les 2 peuvent être vrai sans être liés.
....
et devrait être
...
(les if pouvant être mieux utilisés, ce n'est pas le point)
j'aurais peut-être du mettre la remarque précédente en gras
plutôt qu'entre parenthèse.
Pourquoi pas tout simplement:
if (other.ref) other.ref->addRef();
if (ref) ref->release();
ref = other.ref;
les if pouvaient être différents de ceux écrits, il reste et
tu le confirmes que pour ne pas faire un if (*this == other)
tu fais 2 if sur le membre 'ref'.
Jean-Marc Bourguet wrote on 23/09/2006 07:55:je suis plutôt de l'avis de Alain, tester le cas
d'auto-affectation me parait même indispensable pour a) ne
pas risquer de perdre les données,
Si le test est nécessaire pour éviter de perdre des données
dans le cas de l'auto-affectation, il y a de gros risques
que le code en fait ne soit pas robustes en présence
d'exceptions.
les 2 peuvent être vrai sans être liés.
....et devrait être
...
(les if pouvant être mieux utilisés, ce n'est pas le point)
j'aurais peut-être du mettre la remarque précédente en gras
plutôt qu'entre parenthèse.Pourquoi pas tout simplement:
if (other.ref) other.ref->addRef();
if (ref) ref->release();
ref = other.ref;
les if pouvaient être différents de ceux écrits, il reste et
tu le confirmes que pour ne pas faire un if (*this == other)
tu fais 2 if sur le membre 'ref'.
Tu n'as pas l'air d'avoir compris. Il faut, dans tous les cas,
deux if, un sur l'addRef, et un sur le release. En revanche,
fait comme l'a fait Jean-Marc, le test sur l'auto-affectation
devient inutile. Ce qui est quand même ce dont on parle, non ?
Tu n'as pas l'air d'avoir compris. Il faut, dans tous les cas,
deux if, un sur l'addRef, et un sur le release. En revanche,
fait comme l'a fait Jean-Marc, le test sur l'auto-affectation
devient inutile. Ce qui est quand même ce dont on parle, non ?
Tu n'as pas l'air d'avoir compris. Il faut, dans tous les cas,
deux if, un sur l'addRef, et un sur le release. En revanche,
fait comme l'a fait Jean-Marc, le test sur l'auto-affectation
devient inutile. Ce qui est quand même ce dont on parle, non ?
James Kanze wrote on 23/09/2006 23:14:Tu n'as pas l'air d'avoir compris. Il faut, dans tous les cas,
deux if, un sur l'addRef, et un sur le release. En revanche,
fait comme l'a fait Jean-Marc, le test sur l'auto-affectation
devient inutile. Ce qui est quand même ce dont on parle, non ?
tu as vu mon post correctif donc tu sais que "j'ai compris".
mon erreur (au delà de la réponse rapide) était de vouloir
donner un "contre-exemple" (je cite ici Fabien), alors que
copie+swap ne supportent aucun contre-exemple théorique ...
(sauf évidemment les objets non copiables).
comme conclu dans une autre branche du fil, je reste convaincu
(par la pratique)
James Kanze wrote on 23/09/2006 23:14:
Tu n'as pas l'air d'avoir compris. Il faut, dans tous les cas,
deux if, un sur l'addRef, et un sur le release. En revanche,
fait comme l'a fait Jean-Marc, le test sur l'auto-affectation
devient inutile. Ce qui est quand même ce dont on parle, non ?
tu as vu mon post correctif donc tu sais que "j'ai compris".
mon erreur (au delà de la réponse rapide) était de vouloir
donner un "contre-exemple" (je cite ici Fabien), alors que
copie+swap ne supportent aucun contre-exemple théorique ...
(sauf évidemment les objets non copiables).
comme conclu dans une autre branche du fil, je reste convaincu
(par la pratique)
James Kanze wrote on 23/09/2006 23:14:Tu n'as pas l'air d'avoir compris. Il faut, dans tous les cas,
deux if, un sur l'addRef, et un sur le release. En revanche,
fait comme l'a fait Jean-Marc, le test sur l'auto-affectation
devient inutile. Ce qui est quand même ce dont on parle, non ?
tu as vu mon post correctif donc tu sais que "j'ai compris".
mon erreur (au delà de la réponse rapide) était de vouloir
donner un "contre-exemple" (je cite ici Fabien), alors que
copie+swap ne supportent aucun contre-exemple théorique ...
(sauf évidemment les objets non copiables).
comme conclu dans une autre branche du fil, je reste convaincu
(par la pratique)
Il parait que le problème de transtypage a été résolu, et que
Java a aussi des templates aujourd'hui. Mais c'était
effectivement un problème dans le temps.
Ah non pas du tout. Il y a les templates certes depuis Java
5.0, mais qu'est-ce que ça veut dire en Java ? Ca veut dire
que tu n'as plus à écrire les transtypages toi même. Mais
voilà. .. les transtypages sont toujours effectués sous le
manteau :-(
Il parait que le problème de transtypage a été résolu, et que
Java a aussi des templates aujourd'hui. Mais c'était
effectivement un problème dans le temps.
Ah non pas du tout. Il y a les templates certes depuis Java
5.0, mais qu'est-ce que ça veut dire en Java ? Ca veut dire
que tu n'as plus à écrire les transtypages toi même. Mais
voilà. .. les transtypages sont toujours effectués sous le
manteau :-(
Il parait que le problème de transtypage a été résolu, et que
Java a aussi des templates aujourd'hui. Mais c'était
effectivement un problème dans le temps.
Ah non pas du tout. Il y a les templates certes depuis Java
5.0, mais qu'est-ce que ça veut dire en Java ? Ca veut dire
que tu n'as plus à écrire les transtypages toi même. Mais
voilà. .. les transtypages sont toujours effectués sous le
manteau :-(
Parce qu'on ne peut pas modifier le JVM, je sais. Mais est-ce
que ce transtypages-là ne sont plus qu'une question de
performances ? J'aurais au moins espérer que si je déclare
qu'une collection ne contient que des types T, que le
compilateur l'enforce ; que les transtypages de
l'implémentation ne peuvent pas échouer
(et que potentiellement,
une bonne JVM saurait reconnaître le cas, et remplacer
l'équivalent d'un dynamic_cast par l'équivalent d'un
static_cast).
Parce qu'on ne peut pas modifier le JVM, je sais. Mais est-ce
que ce transtypages-là ne sont plus qu'une question de
performances ? J'aurais au moins espérer que si je déclare
qu'une collection ne contient que des types T, que le
compilateur l'enforce ; que les transtypages de
l'implémentation ne peuvent pas échouer
(et que potentiellement,
une bonne JVM saurait reconnaître le cas, et remplacer
l'équivalent d'un dynamic_cast par l'équivalent d'un
static_cast).
Parce qu'on ne peut pas modifier le JVM, je sais. Mais est-ce
que ce transtypages-là ne sont plus qu'une question de
performances ? J'aurais au moins espérer que si je déclare
qu'une collection ne contient que des types T, que le
compilateur l'enforce ; que les transtypages de
l'implémentation ne peuvent pas échouer
(et que potentiellement,
une bonne JVM saurait reconnaître le cas, et remplacer
l'équivalent d'un dynamic_cast par l'équivalent d'un
static_cast).
Parce qu'on ne peut pas modifier le JVM, je sais. Mais est-ce
que ce transtypages-là ne sont plus qu'une question de
performances ? J'aurais au moins espérer que si je déclare
qu'une collection ne contient que des types T, que le
compilateur l'enforce ; que les transtypages de
l'implémentation ne peuvent pas échouer
En principe ça ne peut plus échouer, c'est déjà un progrès.
(et que potentiellement,
une bonne JVM saurait reconnaître le cas, et remplacer
l'équivalent d'un dynamic_cast par l'équivalent d'un
static_cast).
Une bonne JVM dis tu ?
Autant que je sache le transtypage est toujours dynamique.
Quand tu fais vector<int>, il y a transtypage en Integer, ils
appellent ça le boxing maintenant, mais c'ets pareil que ce
que tu aurais fait à la maint avant et quand tu veux récupèrer
une valeur int il y a ce qu'ils appellent le unboxing, qui
fait pour toi le_int.intValue(); , le_int étant une instance
de Integer donc. (beurk)
Parce qu'on ne peut pas modifier le JVM, je sais. Mais est-ce
que ce transtypages-là ne sont plus qu'une question de
performances ? J'aurais au moins espérer que si je déclare
qu'une collection ne contient que des types T, que le
compilateur l'enforce ; que les transtypages de
l'implémentation ne peuvent pas échouer
En principe ça ne peut plus échouer, c'est déjà un progrès.
(et que potentiellement,
une bonne JVM saurait reconnaître le cas, et remplacer
l'équivalent d'un dynamic_cast par l'équivalent d'un
static_cast).
Une bonne JVM dis tu ?
Autant que je sache le transtypage est toujours dynamique.
Quand tu fais vector<int>, il y a transtypage en Integer, ils
appellent ça le boxing maintenant, mais c'ets pareil que ce
que tu aurais fait à la maint avant et quand tu veux récupèrer
une valeur int il y a ce qu'ils appellent le unboxing, qui
fait pour toi le_int.intValue(); , le_int étant une instance
de Integer donc. (beurk)
Parce qu'on ne peut pas modifier le JVM, je sais. Mais est-ce
que ce transtypages-là ne sont plus qu'une question de
performances ? J'aurais au moins espérer que si je déclare
qu'une collection ne contient que des types T, que le
compilateur l'enforce ; que les transtypages de
l'implémentation ne peuvent pas échouer
En principe ça ne peut plus échouer, c'est déjà un progrès.
(et que potentiellement,
une bonne JVM saurait reconnaître le cas, et remplacer
l'équivalent d'un dynamic_cast par l'équivalent d'un
static_cast).
Une bonne JVM dis tu ?
Autant que je sache le transtypage est toujours dynamique.
Quand tu fais vector<int>, il y a transtypage en Integer, ils
appellent ça le boxing maintenant, mais c'ets pareil que ce
que tu aurais fait à la maint avant et quand tu veux récupèrer
une valeur int il y a ce qu'ils appellent le unboxing, qui
fait pour toi le_int.intValue(); , le_int étant une instance
de Integer donc. (beurk)
Et que tu as une erreur du compilateur quand tu essaies
d'insérer ou d'extraire le mauvais type d'une collection.
Formellement. Mais c'est comme la machine abstracte de C++ ; tu
peux faire tout ce que tu veux, pourvu que le résultat soit bon.
Les bonnes VM, aujourd'hui,
D'après ce que j'ai compris (mais je n'ai pas suivi en détail,
du tout), les règles ont été conçues exprès d'une façon de
permettre à la VM de découvrir d'une façon assez simple qu'il
s'agit au fond d'un tableau d'un type de base, et de générer le
code en conséquence.
De même, s'ils l'ont fait bien, la VM doit
pouvoir « découvrir » que tous les objets qui sont mis dans le
Object[] (qui se trouve à la base de l'implémentation de la
collection) sont en fait des MaClasse, et remplacer le
transtypage dynamique à MaClasse en sortie par un transtypage
statique.
En principe, en tout cas. Dans la pratique, c'est sans doute
comme la principe que le compilateur voit tout ce qui se passe
dans les fonctions inline de std::vector, et que donc, ce n'est
pas la peine d'extraire la fonction end() de la boucle, parce
que le compilateur le fera automatiquement lui-même.
Et que tu as une erreur du compilateur quand tu essaies
d'insérer ou d'extraire le mauvais type d'une collection.
Formellement. Mais c'est comme la machine abstracte de C++ ; tu
peux faire tout ce que tu veux, pourvu que le résultat soit bon.
Les bonnes VM, aujourd'hui,
D'après ce que j'ai compris (mais je n'ai pas suivi en détail,
du tout), les règles ont été conçues exprès d'une façon de
permettre à la VM de découvrir d'une façon assez simple qu'il
s'agit au fond d'un tableau d'un type de base, et de générer le
code en conséquence.
De même, s'ils l'ont fait bien, la VM doit
pouvoir « découvrir » que tous les objets qui sont mis dans le
Object[] (qui se trouve à la base de l'implémentation de la
collection) sont en fait des MaClasse, et remplacer le
transtypage dynamique à MaClasse en sortie par un transtypage
statique.
En principe, en tout cas. Dans la pratique, c'est sans doute
comme la principe que le compilateur voit tout ce qui se passe
dans les fonctions inline de std::vector, et que donc, ce n'est
pas la peine d'extraire la fonction end() de la boucle, parce
que le compilateur le fera automatiquement lui-même.
Et que tu as une erreur du compilateur quand tu essaies
d'insérer ou d'extraire le mauvais type d'une collection.
Formellement. Mais c'est comme la machine abstracte de C++ ; tu
peux faire tout ce que tu veux, pourvu que le résultat soit bon.
Les bonnes VM, aujourd'hui,
D'après ce que j'ai compris (mais je n'ai pas suivi en détail,
du tout), les règles ont été conçues exprès d'une façon de
permettre à la VM de découvrir d'une façon assez simple qu'il
s'agit au fond d'un tableau d'un type de base, et de générer le
code en conséquence.
De même, s'ils l'ont fait bien, la VM doit
pouvoir « découvrir » que tous les objets qui sont mis dans le
Object[] (qui se trouve à la base de l'implémentation de la
collection) sont en fait des MaClasse, et remplacer le
transtypage dynamique à MaClasse en sortie par un transtypage
statique.
En principe, en tout cas. Dans la pratique, c'est sans doute
comme la principe que le compilateur voit tout ce qui se passe
dans les fonctions inline de std::vector, et que donc, ce n'est
pas la peine d'extraire la fonction end() de la boucle, parce
que le compilateur le fera automatiquement lui-même.
Formellement. Mais c'est comme la machine abstracte de C++ ; tu
peux faire tout ce que tu veux, pourvu que le résultat soit bon.
Les bonnes VM, aujourd'hui,
Les bonnes. Faut une avoir une....
Tiens je ne sais pas si tu as vu, Sun nous dit que dans sa dernière JVM
1.5.0_07 je crois, ils ont corrigé un memory leak qui se produit à la
fermeture d'un JFrame. Ce memory leak là, je crois bien qu'on le voit
depuis que JFrame existe....
D'après ce que j'ai compris (mais je n'ai pas suivi en détail,
du tout), les règles ont été conçues exprès d'une façon de
permettre à la VM de découvrir d'une façon assez simple qu'il
s'agit au fond d'un tableau d'un type de base, et de générer le
code en conséquence.
Ben non hélas. cf bout de code ci-dessus
De même, s'ils l'ont fait bien, la VM doit
pouvoir « découvrir » que tous les objets qui sont mis dans le
Object[] (qui se trouve à la base de l'implémentation de la
collection) sont en fait des MaClasse, et remplacer le
transtypage dynamique à MaClasse en sortie par un transtypage
statique.
Ben non, toujours pas. D'ailleurs soit dit en passant les tableaux ne
fonctionnent pas avec les génériques.
Voici le byte code pour la fin du code ci-dessus:
63: new #2; //class java/util/Vector
66: dup
67: invokespecial #3; //Method java/util/Vector."<init>":()V
70: astore 5
72: aload 5
74: new #17; //class testgeneric/Generic
77: dup
78: iload_1
79: invokespecial #18; //Method "<init>":(I)V
82: invokevirtual #5; //Method
java/util/Vector.add:(Ljava/lang/Object;)Z
85: pop
86: aload 5
88: iconst_0
89: invokevirtual #6; //Method
java/util/Vector.get:(I)Ljava/lang/Object;
92: checkcast #17; //class testgeneric/Generic
95: astore 6
97: return
Comme tu vois c'est un Object qui est mis dans le tableau et
un Object qui en sort.
Puis le transtypage est fait ou plutôt vérifié
dynamiquement avec checkcast, bien qu'il ait été déjà validé à la
compilation.... :-(
(voir les spec de checkcast là
http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc2 .html)
Bref les génériques en java c'est plus de l'ordre du sucre
syntaxique qu'autre chose et on est bien loin de C++
Formellement. Mais c'est comme la machine abstracte de C++ ; tu
peux faire tout ce que tu veux, pourvu que le résultat soit bon.
Les bonnes VM, aujourd'hui,
Les bonnes. Faut une avoir une....
Tiens je ne sais pas si tu as vu, Sun nous dit que dans sa dernière JVM
1.5.0_07 je crois, ils ont corrigé un memory leak qui se produit à la
fermeture d'un JFrame. Ce memory leak là, je crois bien qu'on le voit
depuis que JFrame existe....
D'après ce que j'ai compris (mais je n'ai pas suivi en détail,
du tout), les règles ont été conçues exprès d'une façon de
permettre à la VM de découvrir d'une façon assez simple qu'il
s'agit au fond d'un tableau d'un type de base, et de générer le
code en conséquence.
Ben non hélas. cf bout de code ci-dessus
De même, s'ils l'ont fait bien, la VM doit
pouvoir « découvrir » que tous les objets qui sont mis dans le
Object[] (qui se trouve à la base de l'implémentation de la
collection) sont en fait des MaClasse, et remplacer le
transtypage dynamique à MaClasse en sortie par un transtypage
statique.
Ben non, toujours pas. D'ailleurs soit dit en passant les tableaux ne
fonctionnent pas avec les génériques.
Voici le byte code pour la fin du code ci-dessus:
63: new #2; //class java/util/Vector
66: dup
67: invokespecial #3; //Method java/util/Vector."<init>":()V
70: astore 5
72: aload 5
74: new #17; //class testgeneric/Generic
77: dup
78: iload_1
79: invokespecial #18; //Method "<init>":(I)V
82: invokevirtual #5; //Method
java/util/Vector.add:(Ljava/lang/Object;)Z
85: pop
86: aload 5
88: iconst_0
89: invokevirtual #6; //Method
java/util/Vector.get:(I)Ljava/lang/Object;
92: checkcast #17; //class testgeneric/Generic
95: astore 6
97: return
Comme tu vois c'est un Object qui est mis dans le tableau et
un Object qui en sort.
Puis le transtypage est fait ou plutôt vérifié
dynamiquement avec checkcast, bien qu'il ait été déjà validé à la
compilation.... :-(
(voir les spec de checkcast là
http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc2 .html)
Bref les génériques en java c'est plus de l'ordre du sucre
syntaxique qu'autre chose et on est bien loin de C++
Formellement. Mais c'est comme la machine abstracte de C++ ; tu
peux faire tout ce que tu veux, pourvu que le résultat soit bon.
Les bonnes VM, aujourd'hui,
Les bonnes. Faut une avoir une....
Tiens je ne sais pas si tu as vu, Sun nous dit que dans sa dernière JVM
1.5.0_07 je crois, ils ont corrigé un memory leak qui se produit à la
fermeture d'un JFrame. Ce memory leak là, je crois bien qu'on le voit
depuis que JFrame existe....
D'après ce que j'ai compris (mais je n'ai pas suivi en détail,
du tout), les règles ont été conçues exprès d'une façon de
permettre à la VM de découvrir d'une façon assez simple qu'il
s'agit au fond d'un tableau d'un type de base, et de générer le
code en conséquence.
Ben non hélas. cf bout de code ci-dessus
De même, s'ils l'ont fait bien, la VM doit
pouvoir « découvrir » que tous les objets qui sont mis dans le
Object[] (qui se trouve à la base de l'implémentation de la
collection) sont en fait des MaClasse, et remplacer le
transtypage dynamique à MaClasse en sortie par un transtypage
statique.
Ben non, toujours pas. D'ailleurs soit dit en passant les tableaux ne
fonctionnent pas avec les génériques.
Voici le byte code pour la fin du code ci-dessus:
63: new #2; //class java/util/Vector
66: dup
67: invokespecial #3; //Method java/util/Vector."<init>":()V
70: astore 5
72: aload 5
74: new #17; //class testgeneric/Generic
77: dup
78: iload_1
79: invokespecial #18; //Method "<init>":(I)V
82: invokevirtual #5; //Method
java/util/Vector.add:(Ljava/lang/Object;)Z
85: pop
86: aload 5
88: iconst_0
89: invokevirtual #6; //Method
java/util/Vector.get:(I)Ljava/lang/Object;
92: checkcast #17; //class testgeneric/Generic
95: astore 6
97: return
Comme tu vois c'est un Object qui est mis dans le tableau et
un Object qui en sort.
Puis le transtypage est fait ou plutôt vérifié
dynamiquement avec checkcast, bien qu'il ait été déjà validé à la
compilation.... :-(
(voir les spec de checkcast là
http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc2 .html)
Bref les génériques en java c'est plus de l'ordre du sucre
syntaxique qu'autre chose et on est bien loin de C++
Ce n'est pas de la VM, ça. C'est un problème dans la
bibliothèque.
(Et je ne sais pas si c'est la même, mais je sais
qu'il y avait des fuites de mémoire quand on fermait une JFrame
déjà quand je faisait du Java. Il y a plus de cinq ans.)
Mais justement, une bonne VM analyse le code, fait des
suppositions, et...
Voici le byte code pour la fin du code ci-dessus:63: new #2; //class java/util/Vector
66: dup
67: invokespecial #3; //Method java/util/Vector."<init>":()V
70: astore 5
72: aload 5
74: new #17; //class testgeneric/Generic
Donc, type connu...
77: dup
78: iload_1
79: invokespecial #18; //Method "<init>":(I)V
82: invokevirtual #5; //Method
java/util/Vector.add:(Ljava/lang/Object;)Z
Sauf qu'une bonne VM va plus loin ici. Elle entre dans la
fonction, voit ce qu'elle fait, etc. Et note quelque part,
optimistiquement, que le tableut que contient l'objet ne
contient en fait que des type #17. Chaque fois qu'elle compile
un bout de code, elle vérifie (ou essaie) que cette
post-condition tient avec le bout du code qu'elle a compilée.
85: pop
86: aload 5
88: iconst_0
89: invokevirtual #6; //Method
java/util/Vector.get:(I)Ljava/lang/Object;
92: checkcast #17; //class testgeneric/Generic
95: astore 6
97: return
Et quand elle compile ce bout du code, elle entre dans
Vector.get assez pour voir que la valeur de retour vient bien
d'un tableau d'objet, et si le type est effectivement noté pour
ce tableau, et c'est #17, elle remplace le checkcast par
l'équivalent d'un static_cast (en fait, un no-op si #17 est une
classe, et non une interface). Et évidemment, elle génère une
pré-condition pour ce bout du code qui assure que le type dans
le tableau n'a pas changé.
Selon certains experts avec qui j'ai parlé, c'est en principe
plus facile d'optimiser lors de l'exécution dans un VM que dans
un compilateur classique. Parce que dans la VM, tu as accès réel
du profiling du programme en cours,
Comme tu vois c'est un Object qui est mis dans le tableau et
un Object qui en sort.
Mais la VM peut voir plus loins.
Certes, mais pour d'autres raisons -- je ne crois pas qu'il y a
des paramètres non-type, ni des spécialisations explicites, par
exemple.
Ce n'est pas de la VM, ça. C'est un problème dans la
bibliothèque.
(Et je ne sais pas si c'est la même, mais je sais
qu'il y avait des fuites de mémoire quand on fermait une JFrame
déjà quand je faisait du Java. Il y a plus de cinq ans.)
Mais justement, une bonne VM analyse le code, fait des
suppositions, et...
Voici le byte code pour la fin du code ci-dessus:
63: new #2; //class java/util/Vector
66: dup
67: invokespecial #3; //Method java/util/Vector."<init>":()V
70: astore 5
72: aload 5
74: new #17; //class testgeneric/Generic
Donc, type connu...
77: dup
78: iload_1
79: invokespecial #18; //Method "<init>":(I)V
82: invokevirtual #5; //Method
java/util/Vector.add:(Ljava/lang/Object;)Z
Sauf qu'une bonne VM va plus loin ici. Elle entre dans la
fonction, voit ce qu'elle fait, etc. Et note quelque part,
optimistiquement, que le tableut que contient l'objet ne
contient en fait que des type #17. Chaque fois qu'elle compile
un bout de code, elle vérifie (ou essaie) que cette
post-condition tient avec le bout du code qu'elle a compilée.
85: pop
86: aload 5
88: iconst_0
89: invokevirtual #6; //Method
java/util/Vector.get:(I)Ljava/lang/Object;
92: checkcast #17; //class testgeneric/Generic
95: astore 6
97: return
Et quand elle compile ce bout du code, elle entre dans
Vector.get assez pour voir que la valeur de retour vient bien
d'un tableau d'objet, et si le type est effectivement noté pour
ce tableau, et c'est #17, elle remplace le checkcast par
l'équivalent d'un static_cast (en fait, un no-op si #17 est une
classe, et non une interface). Et évidemment, elle génère une
pré-condition pour ce bout du code qui assure que le type dans
le tableau n'a pas changé.
Selon certains experts avec qui j'ai parlé, c'est en principe
plus facile d'optimiser lors de l'exécution dans un VM que dans
un compilateur classique. Parce que dans la VM, tu as accès réel
du profiling du programme en cours,
Comme tu vois c'est un Object qui est mis dans le tableau et
un Object qui en sort.
Mais la VM peut voir plus loins.
Certes, mais pour d'autres raisons -- je ne crois pas qu'il y a
des paramètres non-type, ni des spécialisations explicites, par
exemple.
Ce n'est pas de la VM, ça. C'est un problème dans la
bibliothèque.
(Et je ne sais pas si c'est la même, mais je sais
qu'il y avait des fuites de mémoire quand on fermait une JFrame
déjà quand je faisait du Java. Il y a plus de cinq ans.)
Mais justement, une bonne VM analyse le code, fait des
suppositions, et...
Voici le byte code pour la fin du code ci-dessus:63: new #2; //class java/util/Vector
66: dup
67: invokespecial #3; //Method java/util/Vector."<init>":()V
70: astore 5
72: aload 5
74: new #17; //class testgeneric/Generic
Donc, type connu...
77: dup
78: iload_1
79: invokespecial #18; //Method "<init>":(I)V
82: invokevirtual #5; //Method
java/util/Vector.add:(Ljava/lang/Object;)Z
Sauf qu'une bonne VM va plus loin ici. Elle entre dans la
fonction, voit ce qu'elle fait, etc. Et note quelque part,
optimistiquement, que le tableut que contient l'objet ne
contient en fait que des type #17. Chaque fois qu'elle compile
un bout de code, elle vérifie (ou essaie) que cette
post-condition tient avec le bout du code qu'elle a compilée.
85: pop
86: aload 5
88: iconst_0
89: invokevirtual #6; //Method
java/util/Vector.get:(I)Ljava/lang/Object;
92: checkcast #17; //class testgeneric/Generic
95: astore 6
97: return
Et quand elle compile ce bout du code, elle entre dans
Vector.get assez pour voir que la valeur de retour vient bien
d'un tableau d'objet, et si le type est effectivement noté pour
ce tableau, et c'est #17, elle remplace le checkcast par
l'équivalent d'un static_cast (en fait, un no-op si #17 est une
classe, et non une interface). Et évidemment, elle génère une
pré-condition pour ce bout du code qui assure que le type dans
le tableau n'a pas changé.
Selon certains experts avec qui j'ai parlé, c'est en principe
plus facile d'optimiser lors de l'exécution dans un VM que dans
un compilateur classique. Parce que dans la VM, tu as accès réel
du profiling du programme en cours,
Comme tu vois c'est un Object qui est mis dans le tableau et
un Object qui en sort.
Mais la VM peut voir plus loins.
Certes, mais pour d'autres raisons -- je ne crois pas qu'il y a
des paramètres non-type, ni des spécialisations explicites, par
exemple.