Download presentation
Presentation is loading. Please wait.
1
1 סביבת זמן הריצה Aho, Sethi, and Ullman – Chapter 7 Cooper and Torczon – Chapter 6
2
2 גישור בין זמן הידור לזמן ריצה מרכיב חשוב במסגרת הטיפול הסמנטי של המהדר בקוד הקלט רוב הסוגיות קשורות לטיפול בקריאות לפונקציות/פרוצדורות הקריאות – דינאמיות, בזמן ריצה הטיפול – סטאטי, בזמן הידור הקצאת כתובות זכרון לכלל המשתנים כתובות שערכן נקבע ומשתנה בזמן ריצה גישור בין המהדר למערכת הפעלה, מוסכמות linkage, ABI
3
3 למה פונקציה? 1. מרכיב מאד חשוב בהנדסת תוכנה, separation of concerns בלעדיו לא היינו מצליחים לכתוב תוכניות גדולות 2. מרכיב מאד משמעותי לקומפיילר 1. אבסטרקציה של בקרה – קריאה וחזרה מפונקציה הקומפיילר מפרש לאן צריך לקפוץ בפקודת return 2. הגדרת משתנים מקומיים הקומפיילר מזהה את התחום של כל משתנה 3. ממשק בין פונקציות הקומפיילר דואג לקישור פרמטרים ושמירה על מוסכמות
4
4 כשאת/ה אומר/ת x, למה את/ה מתכוון/נת? מה תדפיס התוכנית הבאה? var x: int; function foo(): int isreturn x; function bar(): int isvar x: int; x = 1; return foo(); procedure main() isx = 0; print bar();
5
5 תוצאות אפשריות התוכנית תדפיס 0 C, פסקל, C++, Java ורוב השפות ה"מודרניות" התוכנית תדפיס 1 LISP, APL, Perl (לפעמים),... התוכנית תדפיס הודעת שגיאה PHP
6
6 מה ההבדל? Scoping – איך מחליטים לאיזו כתובת בזכרון מתייחס כל שם dynamic scoping – חריג static scoping – ההכרזה המקיפה הקרובה ביותר main ( ) { int a = 0 ; int b = 0 ; { int b = 1 ; { int a = 2 ; printf (“%d %d\n”, a, b) } { int b = 3 ; printf (“%d %d\n”, a, b) ; } printf (“%d %d\n”, a, b) ; } printf (“%d %d\n”, a, b) ; } B0B0 B1B1 B3B3 B3B3 B2B2
7
7 מימוש dynamic scoping לכל שם יש מחסנית (יתכן ריקה). אפשר לנהל hash table של שמות. כניסה ל-scope שבו מוגדר משתנה: דחיפה של ההגדרה למחסנית. יציאה מ-scope שבו מוגדר משתנה: pop מהמחסנית. גישה למשתנה: לפי ראש המחסנית. האם אפשר לגלות גישות לא חוקיות (למשתנים לא קיימים) בזמן קומפילציה? מה לגבי בדיקות טיפוסים?
8
8 מימוש static scoping המשתנה אליו מתייחס הקוד ידוע בזמן קומפילציה. לכן, ידועה גם הכתובת שבה שוכן המשתנה. הקצאת כתובות למשתנים היא חלק מתהליך הקומפילציה. אין שגיאות זמן-ריצה של "גישה למשתנה לא קיים".
9
9 מימוש static scoping למשל: var x: int; function foo(): int isreturn x; function bar(): int isvar x: int; x = 1; return foo(); procedure main() isx = 0; print bar(); שםכתובת שהוקצתה עבורו x (גלובלי)432234 x (בתוך bar) 432238
10
10 מימוש static scoping רק רגע: מה הכתובת של המשתנה b בדוגמה הבאה? procedure fib(n: int) isvar a: int; var b: int; if (n ≤ 1) return 0; a = fib(n – 1); b = fib(n – 2); return a + b; procedure main() isprint fib(5); שימו לב לכך שהבעיה לא קיימת במקרה של dynamic scoping.
11
11 גורמים המשפיעים על ארגון הזיכרון ע"י המהדר האם פרוצדורות יכולות להיות רקורסיביות? מה קורה לערכים של משתנים מקומיים עם סגירת ההפעלה הנוכחית של הפרוצדורה? האם פרוצדורות יכולות להתייחס למשתנים לא מקומיים? איך מועברים פרמטרים? האם אפשר להעביר פרוצדורות כפרמטרים? האם אפשר להקצות זיכרון באופן דינאמי? האם יש צורך לשחררו באופן דינאמי?
12
12 ארגון הזיכרון (הוירטואלי) code static data stack heap גודל זה ידוע בזמן קומפילציה המחסנית גדלה וקטנה בזמן ריצה. היא מכילה רשומות הפעלה (activation records) הקצאת זיכרון בשליטת התוכנית top of stack → משתנים גלובליים
13
13 הכתובות של משתנים מקומיים בכל כניסה לפרוצדורה, מוסיפים רשומת הפעלה למחסנית בכל יציאה, מסירים רשומת הפעלה משתנים מקומיים הם חלק מרשומת ההפעלה של כל פרוצדורה כתובת של משתנה מקומי: S-a S היא כתובת ראש המחסנית; משתנה בזמן ריצה a היא הכתובת היחסית של המשתנה המקומי הכתובות היחסיות נקבעות בזמן קומפילציה!
14
14 דוגמה: הפעלה של fib … other parts of activation record … n (addr: S-20) a (addr: S-16) b (addr: S-12) … other parts of activation record … n (addr: S-20) a (addr: S-16) b (addr: S-12) … other parts of activation record … n (addr: S-20) a (addr: S-16) b (addr: S-12) … other parts of activation record … פרמטרים הם משתנים מקומיים.
15
15 מה עוד יש ברשומת הפעלה? ערך מוחזר; לעיתים -- רגיסטרreturned value פרמטרים אקטואליים; לעיתים רגיסטריםactual parameters מצביע לרשומת ההפעלה של הפרוצדורה הקוראתoptional control link דרוש לפעמים על מנת להתייחס למשתנים לא מקומיים (display)optional access link מצב המכונה לפני התחלת עבודתה של הפרוצדורה הנוכחיתsaved machine status משתנים מקומייםlocal data ערכי בינייםtemporaries
16
16 מה עוד יש ברשומת הפעלה? ערך החזרה מהפונקציה – במקרים רבים נשמר ברגיסטר ולא על המחסנית בשפות תכנות מסוימות, כתלות בסוג ערך החזרה (int ישמר ברגיסטר, struct לא) הפרמטרים האקטואליים (ערכי הפרמטרים) מוכנסים למחסנית על-ידי הפונקציה הקוראת מצב המכונה – מכיל בעיקר את כתובת החזרה ערכי ביניים – למעשה, משתנים מקומיים שהקומפיילר יצר
17
17 תכנון המבנה של רשומות הפעלה בתחילת הרשומה מקצים מקום לגדלים הידועים בזמן קומפילציה יש לתאם בין רשומות ההפעלה של הפרוצדורה הקוראת לפרוצדורה הנקראת כמות / גודל ה- temporaries נקבעת לעתים רק אחרי תהליך האופטימיזציה... parameters and returned value control link links and saved status temporaries and local data parameters and returned value control link links and saved status temporaries and local data top_sp caller’s responsibility callee’s responsibility caller’s activation record callee’s activation record
18
18 תהליך הקריאה 1. הקורא מחשב את הפרמטרים האקטואליים 2. הקורא שומר את כתובת החזרה ואת ערכו הנוכחי של top_sp 3. הקורא מקדם את top_sp 4. הפרוצדורה הנקראת שומרת את הרגיסטרים ואת שאר ה- status information 5. הפרוצדורה הנקראת מאתחלת את המשתנים ומתחילה לפעול... parameters and returned value control link links and saved status temporaries and local data parameters and returned value control link links and saved status temporaries and local data caller’s responsibility callee’s responsibility 1 top_sp 3 2 4 5
19
19 תהליך החזרה 1. הפרוצדורה הנקראת מאכסנת את הערך המוחזר במקום המתאים 2. הפרוצדורה הנקראת משחזרת את top_sp, את ערכי הרגיסטרים, ואת ה- status information 3. למרות ש- top_sp עודכן, ניתן לגשת לערך המוחזר... parameters and returned value control link links and saved status temporaries and local data parameters and returned value control link links and saved status temporaries and local data caller’s responsibility callee’s responsibility 1 2 2 top_sp,3
20
20 פרוצדורות בתוך פרוצדורות: פסקל בפסקל, תוכנית (program) מוגדרת כאוסף של שגרות (procedure ו/או function) לכל שגרה יכולות להיות תת-שגרות כל תת-שגרה יכולה לגשת לכל מה שהוגדר ב-scopes המכילים אותה
21
21 פרוצדורות בתוך פרוצדורות: פסקל program p; var x: Integer; procedure a var y: Integer; procedure b begin… b … end; function c var z: Integer; procedure d begin… d … end; begin… c …end; begin… a … end; begin… p … end. מה הכתובת של משתנה y מתוך הפרוצדורה d? סדרת קריאות אפשרית: p →a→ a →c→ b →c→d
22
22 פרוצדורות בתוך פרוצדורות: פסקל הפתרון: access links ברשומת ההפעלה כל access link מכיל מחוון לרשומת ההפעלה של רמת הקינון שמעליו למשל, ה-access link של d מכיל מחוונים לרשומת ההפעלה של c. ה-access links נבנים בזמן ריצה מספר ה-links שצריך "לטייל" ידוע בזמן קומפילציה
23
23 פרוצדורות בתוך פרוצדורות: פסקל a a c b c d y y z z
24
24 display הבעיה: ניהול יעיל של ה-access links השיטה: ניהול מערך בעומק הקינון הסטטי ובו מצביע לכל סביבה סטטית כשמופעלת פרוצדורה ברמת קינון i מבצעים את השינוי הבא: שומרים את הערך של d [ i ] ברשומת ההפעלה החדשה מעדכנים את d [ i ] להצביע על רשומת ההפעלה החדשה ביציאה מהפרוצדורה – מבצעים את התהליך ההפוך saved d [ 2 ] q(1, 9) s d [ 1 ] d [ 2 ]
25
25 display הבעיה: ניהול יעיל של ה-access links השיטה: ניהול מערך בעומק הקינון הסטטי ובו מצביע לכל סביבה סטטית כשמופעלת פרוצדורה ברמת קינון i מבצעים את השינוי הבא: שומרים את הערך של d [ i ] ברשומת ההפעלה החדשה מעדכנים את d [ i ] להצביע על רשומת ההפעלה החדשה ביציאה מהפרוצדורה – מבצעים את התהליך ההפוך saved d [ 2 ] q(1, 3) saved d [ 2 ] q(1, 9) s d [ 1 ] d [ 2 ]
26
26 display הבעיה: ניהול יעיל של ה-access links השיטה: ניהול מערך בעומק הקינון הסטטי ובו מצביע לכל סביבה סטטית כשמופעלת פרוצדורה ברמת קינון i מבצעים את השינוי הבא: שומרים את הערך של d [ i ] ברשומת ההפעלה החדשה מעדכנים את d [ i ] להצביע על רשומת ההפעלה החדשה ביציאה מהפרוצדורה – מבצעים את התהליך ההפוך saved d [ 3 ] p(1, 3) saved d [ 2 ] q(1, 3) saved d [ 2 ] q(1, 9) s d [ 1 ] d [ 2 ] d [ 3 ]
27
27 display הבעיה: ניהול יעיל של ה-access links השיטה: ניהול מערך בעומק הקינון הסטטי ובו מצביע לכל סביבה סטטית כשמופעלת פרוצדורה ברמת קינון i מבצעים את השינוי הבא: שומרים את הערך של d [ i ] ברשומת ההפעלה החדשה מעדכנים את d [ i ] להצביע על רשומת ההפעלה החדשה ביציאה מהפרוצדורה – מבצעים את התהליך ההפוך saved d [ 2 ] e(1, 3) saved d [ 3 ] p(1, 3) saved d [ 2 ] q(1, 3) saved d [ 2 ] q(1, 9) s d [ 1 ] d [ 2 ] d [ 3 ]
28
28 העברת פרמטרים – call by value (העברת ה- r-value) הערה: הערך יכול להיות מצביע procedure exchange ( i, j : integer ) ; var x : integer ; begin x := a [ i ] ; a [ i ] := a [ j ] ; a [ j ] := x end
29
29 העברת פרמטרים – call by reference (העברת כתובות) program reference (input, output) ; var a, b : integer ; procedure swap ( var x, y : integer ) ; var temp : integer ; begin temp := x ; x := y ; y := temp end ; begin a := 1 ; b := 2 ; swap (a, b) ; writeln ( ' a = ', a ) ; writeln (' b = ', b ) end. גורם להעברה by reference
30
30 העברת פרמטרים – copy restore מעבירים ערכים; עם החזרה מעתיקים את הערכים החדשים לכתובות המקוריות program copyout ( input, output ) ; var a : integer ; procedure unsafe (var x : integer ) ; begin x := 2 ; a := 0 end ; begin a := 1 ; unsafe ( a ) ; writeln ( a ) end.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.