28 January 2022
Αθανάσιος Ανδρούτσος

5' read


 

Πολλές φορές ξεκινώντας να διδάξουμε ή να διδαχθούμε μία γλώσσα προγραμματισμού αναφερόμαστε στη διαδικασία της μεταγλώττισης ως μία διαδικασία μετατροπής του πηγαίου κώδικα (source code) σε γλώσσα εκτελέσιμη από το μηχάνημα προορισμού (target machine), χωρίς όμως να παρουσίαζουμε περισσότερες λεπτομέρειες της διαδικασίας αυτής.

Ας δούμε σε αυτό το ποστ το πλαίσιο λειτουργίας των σύγχρονων μεταγλωττιστών.

 

Τρόποι Μεταγλώττισης

Υπάρχουν δύο βασικοί τρόποι μεταγλώττισης:

1. Μεταγλώττιση και παραγωγή ενός αρχείου τελικού εκτελέσιμου κώδικα σε ένα βήμα, οπότε και δημιουργείται ένα εκτελέσιμο αρχείο (π.χ. .exe σε Windows, a.out σε συστήματα Linux//UNIX) όπως συμβαίνει στις γλώσσες C, C++. Το εκτελέσιμο, εκτελείται γρήγορα αλλά δεν είναι φορητό. Δεν μπορεί δηλαδή να μεταφερθεί σε άλλες πλατφόρμες και να εκτελεστεί. Για να εκτελεστεί σε άλλο Λειτουργικό Σύστημα θα πρέπει το αρχείο πηγαίου κώδικα να ξαναμεταγλωττιστεί.

2. Μεταγλώττιση σε δύο βήματα. Στο 1ο βήμα το αρχείο πηγής μεταγλωττίζεται σε ενδιάμεσο κώδικα (Intermediate Representation - IR), όπως για παράδειγμα στην Java τα  αρχεία .class. ή στην C# τα αρχεία .dll. Στη συνέχεια, στο 2ο βήμα τα αρχεία ενδιάμεσου κώδικα εκτελούνται από το περιβάλλον εκτέλεσης (Virtual Machine (VM) στην Java, Kotlin, Scala, Groovy ή Common Language Runtime (CLR) στις .NET γλώσσες όπως η C# .NET Core). Κατα τη φάση εκτέλεσης, ο ενδιάμεσος κώδικας διερμηνεύεται (interpreted) δηλαδή μεταγλωττίζεται σε γλώσσα μηχανής και εκτελείται χωρίς την παραγωγή τελικού αρχείου. Η διαδικασία αυτή μεταγλώττισης και εκτέλεσης είναι πιο αργή αλλά είναι φορητή. Ο ενδιάμεσος κώδικας μπορεί να εκτελεστεί οπουδήποτε υπάρχει εγκατεστημένο το Runtime (write once, run anywhere), χωρίς το πρόγραμμα να χρειάζεται να ξαναμεταγλωττιστεί. 

 

Διερμήνευση (Interpretation)

Πολλές φορές χαρακτηρίζουμε κάποιες γλώσσσες, όπως η Python, JavaScript, κλπ. ως διερμηνευόμενες επειδή εκτελούνται χωρίς να δημιουργηθεί τελικό εκτελέσιμο αρχείο. Στην πραγματικότητα οι γλώσσες αυτές χρησιμοποιούν μεταγλώττιση δύο φάσεων, απλά στην 1η φάση δημιουργείται ενδιάμεσος κώδικας χωρίς όμως να δημιουργείται αρχείο ενδιάμεσου κώδικα. Ο ενδιάμεσος κώδικας δημιουργείται εσωτερικά κατά τη φάση της μεταγλώττισης και εκτελείται αμέσως μετά από το Runtime. 

 

Just-In-Time Compilation

Επειδή, όπως αναφέραμε η διαδικασία μεταγλώττισης δύο φάσεων -όπου στη 2η φάση γίνεται διερμήνευση- είναι σχετικά αργή σε σχέση με την μεταγλώττιση μίας φάσης χρησιμοποιούμε τεχνικές για να βελτιωθεί η ταχύτητα εκτέλεσης των διερμηνευόμενων προγραμμάτων. Μία τέτοια τεχνική είναι το Just-In-Time Compilation. Χωρίς τον Jitter, οπως είπαμε ο ενδιάμεσος κώδικας διερμηνεύεται, δηλαδή μεταγλωττίζεται σε γλώσσα μηχανής και εκτελείται ταυτόχρονα. Ο Jitter αντί να διερμηνεύει μπορεί και αναγνωρίζει ποια κομμάτια κώδικα (μέθοδοι) καλούνται αρκετά συχνά και τα προ-μεταγλωττίζει, από την ενδιάμεση γλώσσα σε τελικό κώδικα. Έτσι, όταν έρθει η στιγμή να εκτελεστούν δεν χρειάζεται να διερμηνευτούν, αλλά εκτελούνται άμεσα τα προ-μεταγλωττισμένα κομμάτια κώδικα. Πρόκειται δηλαδή για μία τεχνική βελτιστοποίησης κατά το χρόνο εκτέλεσης. Με τη χρήση Jitter για παράδειγμα δουλεύει ο Chrome με την V8 Engine,  που είναι ένα περιβάλλον μεταγλώττισης και εκτέλεσης προγραμμάτων JavaScript.  

 

Συμπερασματικά,

Εάν σας αρέσει ο τρόπος που δουλεύουν οι μεταγλωττιστές και οι γλώσσες προγραμματισμού και έχετε την περιέργεια να μάθετε πως μπορείτε να αναπτύσετε χρήσιμες εφαρμογές και λογισμικό, τότε η καριέρα στο χώρο του προγραμματισμού θα ήταν μία καλή επιλογή για εσάς!