Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 סביבת זמן הריצה. 2 כשאת אומרת x, למה את מתכוונת? מה תדפיס התוכנית הבאה? var x: int; function foo(): int isreturn x; function bar(): int isvar x:int;

Similar presentations


Presentation on theme: "1 סביבת זמן הריצה. 2 כשאת אומרת x, למה את מתכוונת? מה תדפיס התוכנית הבאה? var x: int; function foo(): int isreturn x; function bar(): int isvar x:int;"— Presentation transcript:

1 1 סביבת זמן הריצה

2 2 כשאת אומרת 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();

3 3 תוצאות אפשריות התוכנית תדפיס 0 C, פסקל, C++, Java ורוב השפות ה"מודרניות" התוכנית תדפיס 1 LISP, APL, Perl (לפעמים),... התוכנית תדפיס הודעת שגיאה PHP

4 4 מה ההבדל? 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

5 5 מימוש dynamic scoping לכל שם יש מחסנית (ריקה בפוטנציה). אפשר לנהל hash table של שמות. כניסה ל-scope שבו מוגדר משתנה: דחיפה של ההגדרה למחסנית. יציאה מ-scope שבו מוגדר משתנה: pop מהמחסנית. גישה למשתנה: לפי ראש המחסנית. האם אפשר לגלות גישות לא חוקיות (למשתנים לא קיימים) בזמן קומפילציה? מה לגבי בדיקות טיפוסים?

6 6 מימוש static scoping המשתנה אליו מתייחס הקוד ידוע בזמן קומפילציה. לכן, ידועה גם הכתובת שבה שוכן המשתנה. הקצאת כתובות למשתנים היא חלק מתהליך הקומפילציה. אין שגיאות זמן-ריצה של "גישה למשתנה לא קיים".

7 7 מימוש 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

8 8 מימוש 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.

9 9 גורמים המשפיעים על ארגון הזיכרון ע"י המהדר האם פרוצדורות יכולות להיות רקורסיביות? מה קורה לערכים של משתנים מקומיים עם סגירת ההפעלה הנוכחית של הפרוצדורה? האם פרוצדורות יכולות להתייחס למשתנים לא מקומיים? איך מועברים פרמטרים? האם אפשר להעביר פרוצדורות כפרמטרים? האם אפשר להקצות זיכרון באופן דינאמי? האם יש צורך לשחררו באופן דינאמי?

10 10 ארגון הזיכרון code static data stack   heap גודל זה ידוע בזמן קומפילציה המחסנית גדלה וקטנה בזמן ריצה. היא מכילה רשומות הפעלה (activation records) הקצאת זיכרון בשליטת התוכנית top of stack → משתנים גלובליים

11 11 הכתובות של משתנים מקומיים בכל כניסה לפרוצדורה, מוסיפים רשומת הפעלה למחסנית בכל יציאה, מסירים רשומת הפעלה משתנים מקומיים הם חלק מרשומת ההפעלה של כל פרוצדורה כתובת של משתנה מקומי: S-a S היא כתובת ראש המחסנית a היא הכתובת היחסית של המשתנה המקומי הכתובות היחסיות נקבעות בזמן קומפילציה!

12 12 דוגמה: הפעלה של 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 … פרמטרים הם משתנים מקומיים.

13 13 מה עוד יש ברשומת הפעלה? ערך מוחזר; לעיתים -- רגיסטרreturned value פרמטרים אקטואליים; לעיתים רגיסטריםactual parameters מצביע לרשומת ההפעלה של הפרוצדורה הקוראתoptional control link דרוש לפעמים על מנת להתייחס למשתנים לא מקומיים (display)optional access link מצב המכונה לפני התחלת עבודתה של הפרוצדורה הנוכחיתsaved machine status משתים מקומייםlocal data ערכי בינייםtemporaries

14 14 מה עוד יש ברשומת הפעלה? ערך החזרה מהפונקציה – במקרים רבים נשמר ברגיסטר ולא על המחסנית בשפות תכנות מסוימות, כתלות בסוג ערך החזרה (int ישמר ברגיסטר, struct לא) הפרמטרים האקטואליים (ערכי הפרמטרים) מוכנסים למחסנית על-ידי הפונקציה הקוראת מצב המכונה – מכיל בעיקר את כתובת החזרה ערכי ביניים – למעשה, משתנים מקומיים שהקומפיילר יצר

15 15 מי יוצר את רשומת ההפעלה? רשומת ההפעלה נוצרת בחלקה על-ידי הצד הקורא... ובחלקה על-ידי הצד הנקרא רשומת ההפעלה מוסרת מהזכרון בחלקה על-ידי הצד הנקרא... ובחלקה על-ידי הצד הקורא האם באופן סימטרי? כלומר, האם כל צד מסיר מהזכרון את מה שהוא יצר?

16 16 פרוצדורות בתוך פרוצדורות: פסקל בפסקל, תוכנית (program) מוגדרת כאוסף של שגרות (procedure ו/או function) לכל שגרה יכולות להיות תת-שגרות כל תת-שגרה יכולה לגשת לכל מה שהוגדר ב-scopes המכילים אותה הרעיון: תכנון תוכנה מתבצע top-down בשיטת stepwise refinement Niklaus Wirth, “Program Development by Stepwise Refinement”, Communications of the ACM, April 1971.

17 17 פרוצדורות בתוך פרוצדורות: פסקל So, naturalists observe, a flea Hath smaller fleas that on him prey; And these have smaller fleas to bite 'em And so proceed ad infinitium Jonathan Swift (1667-1745)

18 18 פרוצדורות בתוך פרוצדורות: פסקל 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

19 19 פרוצדורות בתוך פרוצדורות: פסקל הפתרון: access links ברשומת ההפעלה כל access link מכיל מחוון לרשומת ההפעלה של רמת הקינון שמעליו למשל, ה-access link של d מכיל מחוונים לרשומת ההפעלה של c. ה-access links נבנים בזמן ריצה מספר ה-links שצריך "לטייל" ידוע בזמן קומפילציה

20 20 פרוצדורות בתוך פרוצדורות: פסקל a a c b c d y y z z

21 21 בעיות מודרניות: תכנות מונחה-עצמים class A { virtual void foo() { print “A”; } } class B extends A { virtual void foo(){ print “B”; } } main() { A myA = (…) ? new A() : new B(); myA.foo(); } לאיזו כתובת פונה הקריאה הזו?

22 22 Dynamic Binding בשפות "רגילות", הקישור בין קריאה לפונקציה לבין כתובת הפונקציה ידוע בזמן קומפילציה static binding בשפות מונחות-עצמים, הקישור (עבור פונקציות המכונות "מתודות וירטואליות") מתבצע בזמן ריצה. מנגנון זה נקרא dynamic binding, והוא חלק ממנגנון המכונה פולימורפיזם. פולימורפיזם מאפשר למשתנה להיות, בזמן ריצה, שייך לאחד מכמה טיפוסים שונים. לכל הטיפוסים הללו יש "אב קדמון" משותף, שהוא הטיפוס בו הוגדר המשתנה האמור.

23 23 למה זה טוב? class Shape { int x; int y; virtual moveBy(dX, dY) { … }; virtual draw(); } class Square extends Shape { int size; virtual draw() { … } } class Circle extends Shape { int radius; virtual draw() { … } } function animate(Shape s) { for (int i = 0 ; i < 10; i++) s.moveBy(1,1); s.draw(); } }

24 24 מימוש dynamic binding אפשר לחשוב על אובייקט כעל רשומה הרשומה מכילה שדות עם נתונים בכל רשומה, הערך של שדה מסוים (למשל x או y) נמצא בהיסט קבוע מתחילת הרשומה בזכרון האובייקט הוא רשומה המכילה גם מחוונים לפונקציות בכל אובייקט, המחוון לפונקציה מסוימת נמצא בהיסט קבוע מתחילת האובייקט בזכרון.

25 25 מימוש dynamic binding אובייקטים בזמן ריצה קוד (בזכרון בזמן ריצה, כתובות ידועות כבר בזמן קומפילציה) Shape::moveBy Circle::drawSquare::draw Circle x : int = 17 y : int = 24 draw : addr moveBy : addr radius : int = 9 Square x : int = 76 y : int = 39 draw : addr moveBy : addr size : int = 23 Circle x : int = 73 y : int = 5 draw : addr moveBy : addr radius : int = 76

26 26 מימוש מעשי יותר: VMT המימוש הנאיבי מאוד בזבזני בזכרון כל Circle מכיל את אותה טבלה בדיוק הטבלה יכולה להיות ענקית (המון מתודות) מימוש יעיל יותר: Virtual Method Table טבלה אחת המשותפת לכל האובייקטים מכל סוג כל אובייקט רק מצביע לטבלה הרלוונטית לטיפוס שלו מה המחיר?

27 27 מימוש dynamic binding על-ידי VMT אובייקטים בזמן ריצה קוד (בזכרון בזמן ריצה, כתובות ידועות כבר בזמן קומפילציה) Shape::moveBy Circle::drawSquare::draw Circle VMT x : int = 17 y : int = 24 radius : int = 9 Square VMT x : int = 76 y : int = 39 size : int = 23 Circle VMT x : int = 73 y : int = 5 radius : int = 76 Circle VMT draw : addr moveBy : addr Square VMT draw : addr moveBy : addr

28 28 אופטימיזציות מתי ניתן להחליף dynamic binding ב-static binding? מדוע זה כדאי?


Download ppt "1 סביבת זמן הריצה. 2 כשאת אומרת x, למה את מתכוונת? מה תדפיס התוכנית הבאה? var x: int; function foo(): int isreturn x; function bar(): int isvar x:int;"

Similar presentations


Ads by Google