1

Le compilateur LDC D pour LLVM peut mettre en ligne des appels de fonction indirects dans certaines circonstances s'il peut prouver que la cible est connue statiquement. Voici un exemple de jouet (en D) où cela pourrait se produire:Quels compilateurs peuvent intégrer des appels de fonction indirects?

void main() { 
    uint num; 

    void incNum() { 
     num++; 
    } 

    auto myDelegate = &incNum; 
    myDelegate(); 
} 

Dans ce cas, même si l'appel myDelegate() est théoriquement un appel indirect, la cible est évidente à un lecteur humain et flux de LLVM/LDC analyse, de sorte qu'il devient inline.

À quel point une fonctionnalité est-elle la capacité d'intégrer des appels de fonction indirects à des cibles statiquement identifiables dans des compilateurs modernes? Est-ce que LLVM est le seul compilateur à l'avance capable de faire cela? Est-ce plus commun avec les compilateurs JIT?

Répondre

1

Je ne serais pas surpris si la plupart des compilateurs C++ faisaient ce genre d'optimisation, au moins quelques variations de celui-ci. C'est très spécifique à la langue et au compilateur, en fait.

Je ne peux pas parler pour le langage D, mais pour C/C++, ce type d'optimisation ci-dessus peut être difficile à faire à cause de l'arithmétique du pointeur. Par exemple, pouvez-vous optimiser le code si c'est quelque chose comme ça à la place? Il dépend si fortement du type myDelegate. Ce qui précède peut être valide en C/C++, mais inlining myDelegate() peut ne pas être quelque chose que le compilateur peut garantir.

D'autres langages (par exemple, Java, C#, etc.) n'ont pas d'arithmétique de pointeur, donc plus d'hypothèses peuvent être faites. La JVM Sun, par exemple, peut convertir des appels indirects et polymorphes en appels directs, ce qui est plutôt cool, à mon humble avis. Exemple:

public class A2 { 
     private final B2 b; 
     public A2(B2 b) { 
     this.b = b; 
     } 
     public void run() { 
     b.f(); 
     } 
    } 

    public interface B2 { 
     public void f(); 
    } 

    public class C2 implements B2 { 
     public void f() { 
     } 
    } 

A2 a2 = new A2(new C2()); peuvent effectivement être optimisés, et la machine virtuelle Java de Sun peut prendre cela.

J'ai obtenu cet exemple du Java Specialists newletter 157, que je recommande de lire pour en savoir plus sur ce genre de chose WRT Java.

0

Je suppose que la plupart des compiles optimisant bien peuvent faire quelque chose comme ça (étant donné qu'ils font toutes sortes d'analyses de flux de toute façon).

Les compilateurs Jit peuvent parfois aller encore plus loin et intégrer des appels indirects pour lesquels ils ne peuvent pas prouver que la cible est statiquement connue (ou qu'elle ne l'est tout simplement pas). Dans ce cas, ils insèrent un test si la cible est celle attendue avant l'appel de la fonction et n'utilisent l'appel indirect que si ce n'est pas le cas (et rejettent en fonction de la fréquence à laquelle chaque chemin a été pris). IIRC le .Net Jit fait cela et je suppose que Java le fait aussi.