Desain Kompiler - Lingkungan Run-Time
Program sebagai kode sumber hanyalah kumpulan teks (kode, pernyataan, dll.) Dan untuk membuatnya hidup, diperlukan tindakan yang harus dilakukan pada mesin target. Sebuah program membutuhkan sumber daya memori untuk menjalankan instruksi. Sebuah program berisi nama untuk prosedur, pengenal, dll., Yang memerlukan pemetaan dengan lokasi memori aktual saat runtime.
Yang kami maksud dengan runtime adalah program yang sedang dieksekusi. Lingkungan waktu proses adalah keadaan mesin target, yang mungkin mencakup pustaka perangkat lunak, variabel lingkungan, dll., Untuk menyediakan layanan ke proses yang berjalan di sistem.
Sistem pendukung runtime adalah sebuah paket, sebagian besar dihasilkan dengan program yang dapat dieksekusi itu sendiri dan memfasilitasi komunikasi proses antara proses dan lingkungan runtime. Ini menangani alokasi memori dan de-alokasi saat program sedang dijalankan.
Pohon Aktivasi
Program adalah urutan instruksi yang digabungkan menjadi sejumlah prosedur. Instruksi dalam prosedur dijalankan secara berurutan. Sebuah prosedur memiliki awal dan akhir pembatas dan semua yang ada di dalamnya disebut bagian tubuh prosedur. Pengidentifikasi prosedur dan urutan instruksi terbatas di dalamnya membentuk tubuh prosedur.
Eksekusi suatu prosedur disebut aktivasi. Catatan aktivasi berisi semua informasi yang diperlukan untuk memanggil prosedur. Catatan aktivasi mungkin berisi unit-unit berikut (tergantung pada bahasa sumber yang digunakan).
Temporaries | Menyimpan nilai sementara dan menengah dari sebuah ekspresi. |
Data Lokal | Menyimpan data lokal dari prosedur yang dipanggil. |
Status Mesin | Menyimpan status mesin seperti Register, Program Counter, dll., Sebelum prosedur dipanggil. |
Tautan Kontrol | Menyimpan alamat catatan aktivasi prosedur pemanggil. |
Akses Link | Menyimpan informasi data yang berada di luar cakupan lokal. |
Parameter Aktual | Menyimpan parameter aktual, yaitu parameter yang digunakan untuk mengirim input ke prosedur yang dipanggil. |
Nilai Kembali | Menyimpan nilai kembali. |
Setiap kali prosedur dijalankan, catatan aktivasi disimpan di tumpukan, juga dikenal sebagai tumpukan kontrol. Ketika sebuah prosedur memanggil prosedur lain, eksekusi pemanggil ditunda sampai prosedur yang dipanggil menyelesaikan eksekusi. Saat ini, rekaman aktivasi dari prosedur yang dipanggil disimpan di tumpukan.
Kami berasumsi bahwa kontrol program mengalir secara berurutan dan ketika sebuah prosedur dipanggil, kontrolnya ditransfer ke prosedur yang dipanggil. Ketika prosedur yang dipanggil dijalankan, itu mengembalikan kontrol kembali ke pemanggil. Jenis aliran kontrol ini memudahkan untuk merepresentasikan rangkaian aktivasi dalam bentuk pohon, yang dikenal sebagaiactivation tree.
Untuk memahami konsep ini, kami mengambil sepotong kode sebagai contoh:
. . .
printf(“Enter Your Name: “);
scanf(“%s”, username);
show_data(username);
printf(“Press any key to continue…”);
. . .
int show_data(char *user)
{
printf(“Your name is %s”, username);
return 0;
}
. . .
Di bawah ini adalah pohon aktivasi dari kode yang diberikan.
Sekarang kami memahami bahwa prosedur dijalankan secara mendalam pertama, sehingga alokasi tumpukan adalah bentuk penyimpanan yang paling sesuai untuk aktivasi prosedur.
Alokasi Penyimpanan
Lingkungan runtime mengelola persyaratan memori runtime untuk entitas berikut:
Code: Ini dikenal sebagai bagian teks dari program yang tidak berubah saat runtime. Persyaratan memorinya diketahui pada waktu kompilasi.
Procedures: Bagian teksnya statis tetapi dipanggil secara acak. Itulah sebabnya, penyimpanan tumpukan digunakan untuk mengelola panggilan dan aktivasi prosedur.
Variables: Variabel hanya diketahui pada waktu proses, kecuali variabel tersebut global atau konstan. Skema alokasi memori heap digunakan untuk mengelola alokasi dan de-alokasi memori untuk variabel dalam runtime.
Alokasi Statis
Dalam skema alokasi ini, data kompilasi terikat ke lokasi tetap di memori dan tidak berubah saat program dijalankan. Karena persyaratan memori dan lokasi penyimpanan telah diketahui sebelumnya, paket dukungan waktu proses untuk alokasi dan pembatalan alokasi memori tidak diperlukan.
Alokasi Stack
Panggilan prosedur dan aktivasi mereka dikelola melalui alokasi memori tumpukan. Ia bekerja dalam metode last-in-first-out (LIFO) dan strategi alokasi ini sangat berguna untuk panggilan prosedur rekursif.
Alokasi Heap
Variabel lokal ke prosedur dialokasikan dan dialokasikan hanya pada waktu proses. Alokasi heap digunakan untuk mengalokasikan memori secara dinamis ke variabel dan mengklaimnya kembali saat variabel tidak lagi diperlukan.
Kecuali area memori yang dialokasikan secara statis, memori stack dan heap dapat berkembang dan menyusut secara dinamis dan tidak terduga. Oleh karena itu, mereka tidak dapat disediakan dengan jumlah memori yang tetap dalam sistem.
Seperti yang ditunjukkan pada gambar di atas, bagian teks dari kode dialokasikan sejumlah memori tetap. Stack dan heap memory diatur pada batas ekstrim dari total memori yang dialokasikan untuk program. Keduanya menyusut dan tumbuh melawan satu sama lain.
Penerusan Parameter
Media komunikasi antar prosedur dikenal sebagai parameter passing. Nilai variabel dari prosedur pemanggilan ditransfer ke prosedur yang dipanggil dengan beberapa mekanisme. Sebelum melanjutkan, pertama-tama bahas beberapa terminologi dasar yang berkaitan dengan nilai-nilai dalam sebuah program.
nilai r
Nilai ekspresi disebut nilai r-nya. Nilai yang terkandung dalam satu variabel juga menjadi nilai-r jika muncul di sisi kanan operator penugasan. nilai-r selalu dapat diberikan ke beberapa variabel lain.
nilai-l
Lokasi memori (alamat) tempat ekspresi disimpan dikenal sebagai nilai-l ekspresi tersebut. Itu selalu muncul di sisi kiri dari operator penugasan.
Sebagai contoh:
day = 1;
week = day * 7;
month = 1;
year = month * 12;
Dari contoh ini, kami memahami bahwa nilai konstanta seperti 1, 7, 12, dan variabel seperti hari, minggu, bulan, dan tahun, semuanya memiliki nilai r. Hanya variabel yang memiliki nilai-l karena mereka juga mewakili lokasi memori yang ditugaskan padanya.
Sebagai contoh:
7 = x + y;
adalah kesalahan nilai-l, karena konstanta 7 tidak mewakili lokasi memori apa pun.
Parameter Formal
Variabel yang mengambil informasi yang diteruskan oleh prosedur pemanggil disebut parameter formal. Variabel ini dideklarasikan dalam definisi fungsi yang dipanggil.
Parameter Aktual
Variabel yang nilai atau alamatnya diteruskan ke prosedur yang dipanggil disebut parameter aktual. Variabel ini ditentukan dalam pemanggilan fungsi sebagai argumen.
Example:
fun_one()
{
int actual_parameter = 10;
call fun_two(int actual_parameter);
}
fun_two(int formal_parameter)
{
print formal_parameter;
}
Parameter formal menyimpan informasi dari parameter aktual, tergantung pada teknik passing parameter yang digunakan. Bisa berupa nilai atau alamat.
Lewati Nilai
Dalam mekanisme pass by value, prosedur pemanggilan meneruskan nilai-r dari parameter aktual dan kompilator memasukkannya ke dalam catatan aktivasi prosedur yang dipanggil. Parameter formal kemudian menyimpan nilai yang dilewatkan oleh prosedur pemanggilan. Jika nilai yang dipegang oleh parameter formal diubah, itu seharusnya tidak berdampak pada parameter sebenarnya.
Lewati Referensi
Dalam mekanisme referensi lewat, nilai-l dari parameter aktual disalin ke catatan aktivasi dari prosedur yang dipanggil. Dengan cara ini, prosedur yang dipanggil sekarang memiliki alamat (lokasi memori) dari parameter aktual dan parameter formal merujuk ke lokasi memori yang sama. Oleh karena itu, jika nilai yang ditunjukkan oleh parameter formal diubah, dampaknya harus dilihat pada parameter aktual karena harus juga mengarah ke nilai yang sama.
Lewati Copy-restore
Mekanisme penerusan parameter ini bekerja mirip dengan 'pass-by-reference' kecuali bahwa perubahan pada parameter aktual dibuat ketika prosedur yang dipanggil berakhir. Setelah pemanggilan fungsi, nilai parameter aktual disalin dalam catatan aktivasi dari prosedur yang dipanggil. Parameter formal jika dimanipulasi tidak memiliki efek real-time pada parameter aktual (saat nilai l dilewatkan), tetapi ketika prosedur yang dipanggil berakhir, nilai l dari parameter formal disalin ke nilai l dari parameter aktual.
Example:
int y;
calling_procedure()
{
y = 10;
copy_restore(y); //l-value of y is passed
printf y; //prints 99
}
copy_restore(int x)
{
x = 99; // y still has value 10 (unaffected)
y = 0; // y is now 0
}
Ketika fungsi ini berakhir, nilai l dari parameter formal x disalin ke parameter y yang sebenarnya. Bahkan jika nilai y diubah sebelum prosedur berakhir, nilai l dari x disalin ke nilai l dari y membuatnya berperilaku seperti call by reference.
Lewati Nama
Bahasa seperti Algol menyediakan jenis mekanisme penerusan parameter baru yang bekerja seperti preprocessor dalam bahasa C. Dalam mekanisme pass by name, nama prosedur yang dipanggil diganti dengan badan aslinya. Pass-by-name secara tekstual menggantikan ekspresi argumen dalam panggilan prosedur untuk parameter yang sesuai di dalam tubuh prosedur sehingga sekarang dapat bekerja pada parameter aktual, seperti referensi lewat.