9. Implementing Subprogram
Recap: Subprograms
- Parameters
def compute_pay(income, exemptions = 1, tax_rate):
...
return
- Positional binding
pay = compute_pay(20000.0, tax_rate = 0.15)
Formal parameters: income, exemptions, tax-rate
Actual parameters: 20000.0, 0.15
Default value
Binding by keyword parameters
Parameter passing methods
Semantics models
in mode, out mode, inout mode
Implementation models
Pass-by-value
Pass-by-reference
Pass-by-value-result
Pass-by-name
Pass-by-assignment
Two types of subprograms
Procedures: does not return
Can change variable
Functions: return value
No side effect ideally
Parameter that are subprograms
Shallow/deep/ad hoc binding
Overloaded subprograms
[Issue 1] Coercion is allowed?
[Issue 2] The same parameter but different return types
Generic subprograms
Ad hoc/subtype/parametric polymorphism
[Issue 1] Type checking functionโs protocol
[Issue 2] If nested referencing environment
Closures: function returned by a function
Function is also object
Function can be nested
Subprogram can be called in other place
Remembers the referencing environment
def addNumber(fixedNum):
def add(number):
return fixedNum + number
return add
# ===============================
func = addNumber(10)
func(20) # 30
func(30) # 40
- Coroutines
- Coroutines are more equitable
- Coroutines can have multiple entry points
- Only one coroutine is actually in execution at a given time
- quasi-concurrency
- Related to the way multiprogramming operating systems
Implementing Subprogram
General semantics of calls and returns
โSimpleโ subprograms
Subprograms with stack-dynamic local variables
Nested subprograms
Blocks
Dynamic scoping
Implementation of subprograms
How subprogram linkage works?
Subprogram์ ํธ์ถํ๊ณ ์คํํ๋ ๊ณผ์ ์์ ํ์ํ ๋ฉ๋ชจ๋ฆฌ ํ ๋น, ์ธ์ ์ ๋ฌ, ๋ณต๊ท ์ฃผ์ ๊ด๋ฆฌ ๋ฑ์ ์ฒ๋ฆฌํ๋ ๊ณผ์
ํธ์ถํ ๋ ํ์ํ ์ ๋ณด(๋งค๊ฐ๋ณ์, ์ง์ญ๋ณ์, ๋ณต๊ท์ฃผ์ ๋ฑ)๋ฅผ Activation Record๋ก ์คํ์ ์ ์ฅ
ํจ์ ์คํ ํ ๋ณต๊ท ์ Activation Record๋ฅผ ์ ๊ฑฐํ๊ณ ๋ณต๊ตฌ
Simplest: no nested with only local static variable
Static variable์ ์คํ(stack)์ด ์๋๋ผ ๊ณ ์ ๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ(static data area) ์ ์ ์ฅ
ํธ์ถํ ๋๋ง๋ค ์๋ก ์์ฑํ๊ฑฐ๋ ์ ๊ฑฐํ ํ์ ์์
Activation Record๋ ๋งค์ฐ ๋จ์ํด์ง
๋ณต๊ท ์ฃผ์ (Return address)๋ง ์ ์ฅํ๋ฉด ๋๊ณ
์ง์ญ๋ณ์ ๊ณต๊ฐ์ ์ด๋ฏธ ๋ฐ๋ก ์์ผ๋ฏ๋ก ์คํ์ ์ ์ฅํ ํ์ ์์
int counter() {
static int cnt = 0; // static local variable
cnt++;
return cnt;
}
int main() {
int a = counter(); // a == 1
int b = counter(); // b == 2
return 0;
}
Challenges with
Stack-dynamic local variable
์ง์ญ๋ณ์๊ฐ ํจ์ ํธ์ถ ์์ ์ ๋ง๋ค์ด์ง
ํจ์ ๋๋๋ฉด ์คํ์์ ์๋ ์๋ฉธ
ํฌ๊ธฐ๊ฐ ๊ฐ๋ณ์ ์ธ ๊ฒฝ์ฐ (ex: ๊ฐ๋ณ ๋ฐฐ์ด) ๋ ์ฃผ์ํด์ผ ํจ
Nested subprograms
ํจ์ ์์ ๋ ๋ค๋ฅธ ํจ์๋ฅผ ์ ์ํ ์ ์์ (ex: Pascal, Ada, ์ผ๋ถ Python lambda)
๋ด๋ถ ํจ์๊ฐ ์ธ๋ถ ํจ์์ ๋ณ์์ ์ ๊ทผํด์ผ ํ ์๋ ์์
Nonlocal access with static scope
์ค์ฒฉ ํจ์๊ฐ ์์ ํจ์์ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ ๋
์์ ํจ์์ Activation Record๋ก ์ ๊ทผ ๋ฐฉ๋ฒ ํ์ (Static Link)
Block and dynamic scope
scope ๊ท์น์ ๋ฐ๋ผ, ๋ฐํ์์ ์ฐพ๋ ๋ฐฉ๋ฒ(static vs dynamic)์ด ๋ฌ๋ผ ์ง
General Semantics of Calls and Returns
Subprogram linkage: subprogram call and return operations
Implementation should be based on semantic of subprogram linkage
Subprogram call
Must include parameter-passing method
Allocation and binding for stack-dynamic local variable
Execution status should be saved
Everything needed to resume execution of the calling program unit
Register value, CPU status bits, environment pointer (EP)
Arrange to transfer control to the code of the subprogram
After execution is completed, transfer control should be returned proper place
For nested subprograms, mechanism for accessing nonlocal variables are needed
Subprogram return
In out mode and inout mode, formal parameters are returned to the actual parameters
Deallocate of stack-dynamic local variables in subprograms
Restore the execution status of the calling program
Returning control to the caller
Code Example:
// [C++]
int g = 0;
int func(int first, int second) {
int sum = 0;
sum = first + second;
return sum;
}
void main() {
int x = 1;
int y = 2;
func(x,y);
return;
}
- Component Layout & Concepts:
- Parameters Where parameters are stored
- Local variable Where local variables in subprograms are stored
- Where we return Where we return after the subprogram call
- Stack
- Heap
- Registers
- โฆ
- Environment pointer (EP)
- Data
- Program counter (PC)
- Code
โSimpleโ Subprograms
- No nested and all local variables are static (or no recursion)
- Semantic of call
- Create an activation record instance
- Save the execution status of the current program unit. (done by caller or callee)
- Compute and pass the parameters. (done by caller)
- Pass the return address to the called. (done by caller)
- Transfer control to the called. (done by caller)
Allocation and binding for stack-dynamic local variables
Mechanism for nonlocal variable for nested subprograms
Semantic of return
- For out-mode parameters, the values of those parameters are moved to the corresponding actual parameters. (done by callee)
- If the subprogram is a function, the functional value is moved to a place accessible to the caller. (done by callee)
- The execution status of the caller is restored. (done by caller or callee)
- Control is transferred back to the caller. (done by callee)
Deallocate of stack-dynamic local variables in subprograms
Simple subprogram code example:
// [C++]
int func(int first, int second) {
static int sum = 0;
sum = first + second;
return sum; // โก
}
void main() {
static int x = 1;
static int y = 2;
// โ
func(x,y);
return;
}
- An activation record for simple subprograms
- โ Caller action
- Create an activation record instance.
- Save the execution status of the current program unit.
- Compute and pass the parameters.
- Pass the return address to the called.
- Transfer control to the called.
- โก Callee action
- Epilogue (end of execution)
- For out-mode parameters, the values of values of those parameters are moved to the corresponding actual parameters.
- If the subprogram is a function, the functional value is moved to a place accessible to the caller.
- Restore the execution status of the caller.
- Transfer control back to the caller.
์ฌ๊ท ์์ ํ๋์ ์๋ธํ๋ก๊ทธ๋จ๋ง ์คํ์ ์ฌ๋ผ๊ฐ์ ์คํ ์ค
The call and return actions require storage for the following:
Status information about the caller
Parameters
Return address
Return value for functions
Temporaries used by the code of the subprograms
Linkage action of callee can occur at two different times
Prologue: beginning of its execution (Caller action)
Epilogue: end of its execution (Callee action)
-Prologue (beginning of execution)
-Epilogue (end of execution)
Consists of two separate parts:
Actual codes (constant)
์๋ธํ๋ก๊ทธ๋จ์ ์ค์ ๊ธฐ๊ณ์ด ๋ช ๋ น์ด๋ค
ํ๋ก๊ทธ๋จ ์์ฑ ์ ์ด๋ฏธ ๊ณ ์ ๋ Constant
์คํ ์ค์ ๋ณ๊ฒฝ๋์ง ์์
Non-code: local variable and data (can change)
์ง์ญ ๋ณ์(Local variables), ์์ ๊ฐ(Temporary values), ๋งค๊ฐ๋ณ์(Parameters) ๋ฑ
์คํ ์ค์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ์ ์์
Fixed size in simple subprogram
์ค์ฒฉ์ด ์๊ณ , ์ง์ญ ๋ณ์์ ๋งค๊ฐ๋ณ์์ ํฌ๊ธฐ๊ฐ ๊ณ ์ ๋์ด ์์ผ๋ฉด ์๋ธํ๋ก๊ทธ๋จ๋ง๋ค ํ์ํ Non-Code ์์ญ์ ํฌ๊ธฐ๊ฐ ๊ณ ์ (fixed)
ํธ์ถํ ๋๋ง๋ค ์ด ํฌ๊ธฐ๋งํผ ์คํ์ ๊ณต๊ฐ์ ์ก์ผ๋ฉด ๋จ
Activation record (non-code):
Format, or layout, of the noncode part of a subprogram
Activation Record๋ Non-Code ๋ถ๋ถ์ ๋ ์ด์์์ ์ ์
์๋ธํ๋ก๊ทธ๋จ์ ํธ์ถํ ๋ ์คํ์ ์์ด๋ ํ๋ ์์ ๊ตฌ์กฐ
Activation Record๊ฐ ํฌํจํ๋ ๊ฒ๋ค ์์:
๋งค๊ฐ๋ณ์(Parameter values)
์ง์ญ ๋ณ์(Local variables)
๋ณต๊ท ์ฃผ์(Return address)
๋์ ๋งํฌ(Dynamic link, caller์ frame pointer)
์ ์ ๋งํฌ(Static link, ์์ lexical scope๋ก ์ ๊ทผํ๋ ํฌ์ธํฐ)
์์ ์ ์ฅ๊ณต๊ฐ(Temporary storage)
ARI (Activation record instance): Instance created according to this format
Activation Record์ ์ค์ ์ธ์คํด์ค
AR ํฌ๋งท์ ๋ฐ๋ผ ์ค์ ๋ก ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋๋ ์คํ ํ๋ ์์ด ARI
ARI of simple subprogram has fixed size can be statically allocated and attached to code part
No recursion only one ARI is active
Single activation record per subprogram
Code Example for Code and Non-Code mapping:
int add(int a, int b) {
int sum = a + b;
return sum;
}
int main() {
int result = add(3, 5);
}
Actual Code:
add ํจ์์ ์ปดํ์ผ๋ ๋ช ๋ น์ด๋ค (ex. ๋ง์ ๋ช ๋ น, ๋ฐํ ๋ช ๋ น ๋ฑ)
ํ๋ก๊ทธ๋จ ์์ ๋ ๋ฉ๋ชจ๋ฆฌ์ ๊ณ ์
Non-Code (Activation Record Format):
๋งค๊ฐ๋ณ์ a, b
์ง์ญ๋ณ์ sum
๋ณต๊ท ์ฃผ์
[EX] Main program with three subprograms A, B and C
Simple Subprogram ํ๊ฒฝ์์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ์น(๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ) ๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ์์
Data ์์ญ๊ณผ Code ์์ญ ๋ ๋ถ๋ถ์ผ๋ก ๋๋จ
Data ์์ญ (์์ชฝ):
๊ฐ ์๋ธํ๋ก๊ทธ๋จ (MAIN, A, B, C)์ ๋ํด Activation Record (AR) ๊ฐ ๋ฏธ๋ฆฌ(static) ์ค๋น๋์ด ์์
์ด Activation Record๋ค์ ํ๋ก๊ทธ๋จ์ด ์์ํ ๋ ๊ณ ์ ๋ ๋ฉ๋ชจ๋ฆฌ(Data Segment)์ ํ ๋น๋๊ณ , ํจ์ ํธ์ถ ์๋ง๋ค ์๋ก ๋ง๋ค์ง ์๊ณ ์ฌ์ฌ์ฉ
Code ์์ญ (์๋์ชฝ)
MAIN, A, B, C ์๋ธํ๋ก๊ทธ๋จ์ ๊ธฐ๊ณ์ด ์ฝ๋(๋ช ๋ น์ด) ๊ฐ ์ ์ฅ๋ ์์ญ
Code๋ ๋ณ๊ฒฝ๋์ง ์๊ณ ํ๋ก๊ทธ๋จ ๋ด๋ด ๊ณ ์
์ปดํ์ผ๋ ๋ช ๋ น์ด๋ค์ ํ๋ก๊ทธ๋จ ์คํ ์ ๊ทธ๋๋ก ์ฌ์ฉ
Format of AR is static
Activation Record์ ๋ ์ด์์์ด ์ปดํ์ผ ์์ ์ ๊ณ ์ ๋์ด ์์
๋ฐํ์์ ํฌ๊ธฐ๊ฐ ๋ณํ์ง ์์
Each program can be compiled at different time
MAIN, A, B, C ๊ฐ๊ฐ ๋ฐ๋ก AR์ด ์กด์ฌ ๊ฐ๊ฐ์ ์๋ธํ๋ก๊ทธ๋จ(MAIN, A, B, C)์ ๋ ๋ฆฝ์ ์ผ๋ก ์ปดํ์ผํ ์ ์์
Linker can put together
์ดํ Linker๊ฐ ์ด ์ปดํ์ผ ๊ฒฐ๊ณผ๋ค์ ํ๋๋ก ํฉ์นจ
Subprograms with Stack-Dynamic Local Variables
Stack-Dynamic Local Variable
Advantage of stack-dynamic local variable
Support for recursion
๊ฐ ํจ์ ํธ์ถ๋ง๋ค ์๋ก์ด Activation Record(์คํ ํ๋ ์)๋ฅผ ๋ง๋ค์ด ์ ์ฅํ ์ ์์
์ฌ๊ท ํธ์ถ ์, ํจ์์ ๋ค๋ฅธ ํธ์ถ๋ค์ด ์๋ก ๋ ๋ฆฝ์ ์ธ ์ง์ญ๋ณ์ ์งํฉ์ ๊ฐ์ง ์ ์์
๊ฒฐ๊ณผ์ ์ผ๋ก ํ ์๋ธํ๋ก๊ทธ๋จ์ด ๋์์ ์ฌ๋ฌ activation์ ๊ฐ์ง ์ ์์
But, more complex activation records
Compiler generates code for implicit allocation/deallocation for local variables
Activation Record๊ฐ ๋จ์ํ "๊ณ ์ ๋ ๋ฉ๋ชจ๋ฆฌ"๊ฐ ์๋๋ผ, ๋งค ํธ์ถ๋ง๋ค ์๋ก ๋ง๋ค์ด์ผ ํจ
์ปดํ์ผ๋ฌ๋ ์ง์ญ๋ณ์๋ค์ ํจ์ ์ง์ ์ ์๋์ผ๋ก ์์ฑ(allocate), ํจ์ ์ข ๋ฃ ์ ์๋์ผ๋ก ์๋ฉธ(deallocate) ํ๋ ์ฝ๋๋ฅผ ์๋ ์ฝ์ ํด์ผ ํจ
Multiple simultaneous activations of subprograms (limited by memory size)
Usually, format of an activation record is known at compile time
Activation record instances (ARI) must be created dynamically
Return address, dynamic link and parameters are placed in ARI by caller
Return address: usually consists of point to instruction following the call
Dynamic link: pointer to the base of the activation record instance of the caller
Statically-scoped languages โ used for debugging
Dynamically-scoped languages โ also used to find variables in scope
Actual parameters: values or addresses provided by the caller
Local variable
Scalar variables are bound to storage within ARI
Structure variables are allocated elsewhere (pointer is in ARI)
ARI ์์ฑ๊ณผ์
- Caller
Return address, Dynamic link, Actual parameters๋ฅผ ๋จผ์ ARI์ ์ฑ์
- Callee
Local variables (์ง์ญ ๋ณ์)์ ARI์ ์ฑ์ฐ๊ฑฐ๋ ์ด๊ธฐํ
| ๊ตฌ์ฑ ์์ | ์ค๋ช | ๋๊ฐ ์ค์ ํ๋๊ฐ |
|---|---|---|
| Return address | ํธ์ถ์ด ๋๋๋ฉด ๋ณต๊ทํ ์ฝ๋์ ์ฃผ์ (ํธ์ถํ ๋ค์ ๋ช ๋ น์ด ์์น) | Caller |
| Dynamic link | Caller์ ARI๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ | Caller |
| Actual parameters | ์ธ์ ๊ฐ ๋๋ ์ธ์ ์ฃผ์ (๊ฐ ํธ์ถ pass-by-value or ์ฃผ์ ํธ์ถ pass-by-reference) | Caller |
| Local variables | ์ง์ญ ๋ณ์ ๊ณต๊ฐ (์ด๊ธฐํ๋ ํ์์ ๋ฐ๋ผ) | Callee |
- Example of C code and corresponding ARI
- ARI is created on run-time stack
- Run-time stack provides separate copies of the parameters, local variables, and return address
void sub(float total, int part) {
int list[5];
float sum;
...
}
Environment pointer (EP) is required to control execution of subprogram
Point current activation record base (initially main programโs ARโs base)
ํ์ฌ ์คํ ์ค์ธ ์๋ธํ๋ก๊ทธ๋จ์ Activation Record (ARI) ์ ๊ธฐ์ค(base) ์์น๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
When subprogram is called, current EP is saved in the new ARI as dynamic link
Then, EP is set to point at base of new ARI
Upon return from subprogram, stack top EP - 1
EP is set to dynamic link in executed ARI
ํธ์ถ ์ ํจ์์ ARI๋ฅผ ๋ค์ ๊ฐ๋ฆฌํค๋๋ก
New actions in linkage process
// [C++]
int func(int first, int second) {
// โก
int sum = 0;
sum = first + second;
return sum; // โข
}
void main() {
int x = 1;
int y = 2;
// โ
func(x,y);
return;
}
- โ Caller action
- Create an activation record instance.
- Save the execution status of the current program unit.
- Compute and pass the parameters.
- Pass the return address to the called.
- Transfer control to the called.
- (โก โข) Callee action
- โก Prologue (beginning of execution)
- Save the old EP in the stack as the dynamic link and create the new value.
- Allocate local variables.
- โข Epilogue (end of execution)
- For out-mode parameters, the values of values of those parameters are moved to the corresponding actual parameters.
- If the subprogram is a function, the functional value is moved to a place accessible to the caller.
- Restore the stack pointer by setting it to the value of the current EP minus one and set the EP to the old dynamic link.
- Restore the execution status of the caller.
- Transfer control back to the caller.
Example without recursion
P1, ARI for main and fun1
P2, ARI for fun2 is added
P3. ARI for fun3 is added
Dynamic chain (call chain): collection of dynamic links
Local offset: distance from beginning of ARI
Determined in compile time
[EX] local offset of s is 3, t is 4
Example with recursion
Functional value๋ ์๋ธํ๋ก๊ทธ๋จ(ํนํ ํจ์)์ด ๋ฐํํ ๊ฐ(return value) ์ ์์๋ก ์ ์ฅํด๋๋ ๊ณต๊ฐ
Activation record for factorial
Figure show position 1 in each call
Functional value undefined
First callโs return address is main
Other callโs return address is factorial
Figure shows position2 for each execution
Code Example & Memory Analysis:
// [C++]
#include <iostream>
using namespace std;
int g = 0;
int func1(int first, int second) {
int sum = 0;
cout << "Address of first: " << &first << endl;
cout << "Address of second: " << &second << endl;
cout << "Address of sum: " << &sum << endl;
g = g + 1;
sum = first + second;
return sum;
}
void func2(int first, int second) {
func1(first,second);
return;
}
int main() {
int x = 1;
int y = 2;
cout << "Address of g: " << &g << endl;
func1(x,y);
cout << "Address of g: " << &g << endl;
func1(x,y);
cout << "Address of g: " << &g << endl;
func2(x,y);
cout << "Address of g: " << &g << endl;
return 0;
}
Outputs/Addresses:
Address of first: 0x7ffcb9dc19bc
Address of second: 0x7ffcb9dc19b8
Address of sum: 0x7ffcb9dc19cc
Address of first: 0x7ffcb9dc199c
Address of second: 0x7ffcb9dc1998
Address of sum: 0x7ffcb9dc19ac
// Address of g: 0x404194
// Address of g: 0x404194
// Address of g: 0x404194
// Address of g: 0x404194
Stack Visualization:
Sum (0xโฆcc)
โฆ
First (0xโฆbc)
Second (0xโฆb8)
โฆ
(func2)
Sum (0xโฆac)
โฆ
First (0xโฆ9c)
Second (0xโฆ98)
Nested subprograms
For nested subprograms, two steps are required for access
First, find ARI in stack in which the variable is allocated
ํ์ฌ ์คํ ์์ ์์ธ ARI๋ค ์ค์์ ๋ณ์๊ฐ ์ค์ ๋ก ์ ์ธ๋ Activation Record๋ฅผ ์ฐพ์์ผ ํจ
Second, use local offset of the variable
Finding correct ARI is more interesting
Only static ancestor scopes are visible (accessible)
A subprogram is callable only when all of its static ancestor subprograms are active
Need to find all ARI from the closely nested one
Static chains
Chain of static links
Static link is added in ARI
Called as a static scope pointer
Located below parameters in ARI
Point to bottom of ARI of static parent
Used to implement the accesses to nonlocal variables in static-scoped languages
Static depth
How deeply it is nested in the outermost scope
Nesting depth (chain offset)
Length of static chain needed to reach correct ARI
# Global scope ...
# Static depth of the global, f1, f2 and f3 are 0,1, 2 and 3, respectively
def f1():
def f2():
# f3 refer f1 โ chain offset is 2
def f3():
# f3 refer f2 โ chain offset is 1
...
# end of f3 โฆ
# end of f2
...
# end of f1
Nonlocal access using static chains
In position 1
Reference to A (local variable A in Sub1): chain_offset/local_offset (0,3)
why local_offset is 3?, because A is the first local variable
Reference to B (nonlocal variable B in Bigsub): chain_offset/local_offset (1,4)
Reference to C (nonlocal variable C in Bigsub): chain_offset/local_offset (1,5)
Variable B in Sub2 is not accessible
After Sub1 complete, control returns to Sub3
In position 2
Reference to E (local variable E in Sub3): chain_offset/local_offset (0,4)
Reference to B (nonlocal variable B in Sub2): chain_offset/local_offset (1,4)
why local_offset is 4?, because B is the first local variable, but Sub2 has one parameter
Reference to A (nonlocal variable A in Bigsub): chain_offset/local_offset (2,3)
After Sub3 complete, control returns to Sub2
In position 3
Reference to A (nonlocal variable A in Bigsub): chain_offset/local_offset (1,3)
Reference to D static semantic error because there is no visible D
Reference to E (local variable E in Sub2): chain_offset/local_offset (0,5)
For variable A
Position 1: (0,3) local
Position 2: (2,3) two levels away
Position 3: (1,3) one level away
When return, ARI at top of stack is removed.
When call, how to decide static link?
Can use dynamic link to find until static parent of called program
Perform search
Or when Sub3 call Sub1, static parent of Sub1 is Bigsub and if compiler decide that Sub3 is two-level inside Bigsub find second static link from Sub3
Execution traces:
Bigsub calls A
A calls C
C calls B
Criticism
Referencing nonlocal variable beyond static parent: more cost required
For time-critical program, it is difficult to estimate costs
Static Chain์ ๋ฌธ์ ์ : ๋ถ๋ชจ ํจ์์ ๊ฐ๊น์ด ๋ณ์๋ ๋น ๋ฅด๊ฒ ์ฐพ์ง๋ง, ์กฐ์ ํจ์(Static Grandparent)๊น์ง ์ฌ๋ฌ ๋จ๊ณ ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ์ผ ํ๋ฉด ๋น์ฉ ์ฆ๊ฐ (Static Link jump ๋ง์์ง)
Display: ๊ฐ Static Level๋ง๋ค ํ์ฌ ํ์ฑํ๋ Activation Record์ ํฌ์ธํฐ๋ฅผ ํ ์ด๋ธ(๋ฐฐ์ด) ํํ๋ก ์ ์ฅํ๋ ๋ฐฉ๋ฒ ํ ๋ฒ์ ๋ฐ๋ก ์ ๊ทผ
์๊ฐ์ ์กฐ์ ๋ธ๋ก ๋ณ์ ์ ๊ทผ ๊ฐ๋ฅ (ํ ๋ฒ์ table lookup)
ํนํ ์ค์ฒฉ์ด ๊น์ ํ๋ก๊ทธ๋จ์์ ๋ณ์ ์ ๊ทผ ๋น์ฉ์ด ํ ์ค์ด๋ฆ
Real-time ์์คํ (์๊ฐ ์์ธก์ด ํ์ํ ํ๋ก๊ทธ๋จ)์๋ ์ ๋ฆฌ
Blocks
User-specified local scopes
Advantage: cannot interfere with any other variable with the same name
๋ค๋ฅธ ์ด๋ฆ์ด ๊ฐ์ ๋ณ์๋ค๊ณผ ์ถฉ๋์ ํผํ ์ ์์
Treated as parameterless subprograms and called from the same place
subprogram์ฒ๋ผ "ํธ์ถ"๋๋ ๊ฒ ์๋๋ผ, "๊ทธ ์๋ฆฌ์" ์คํ๋จ (์์ฐจ์คํ)
Every block has an activation record
{
int temp;
temp = list[upper];
list[upper] = list[lower];
list[lower] = temp;
}
- ๋์ ํ๋ฆ
{๋ฅผ ๋ง๋๋ฉด
- ์๋ก์ด Activation Record๊ฐ ๋ง๋ค์ด์ง.
- ์ด Activation Record์๋ temp ๋ฅผ ์ํ ๊ณต๊ฐ์ด ํฌํจ.
- ๋ธ๋ก ๋ด๋ถ ์ฝ๋ ์คํ.
}๋ฅผ ๋ง๋๋ฉด
์ด Activation Record๊ฐ ์คํ์์ ์ ๊ฑฐ๋๋ค.
Function(subprogram) vs block
| ๊ตฌ๋ถ | ํจ์ ํธ์ถ (Function Call) | ๋ธ๋ก ์ค์ฝํ (Block Scope) |
|---|---|---|
| Local variables | ์์ | ์์ |
| Parameters | ์์ | ์์ (๋งค๊ฐ๋ณ์ ์์) |
| Dynamic link | ์์ (๋ค์ ํธ์ถ์ ์ํด) | ์์ ์๋ ์์ (์ค์ฒฉ๋ ๋ธ๋ก์์ ์์ ๋ธ๋ก ์ฐธ์กฐ) |
| Return address | ํญ์ ์์ (ํธ์ถ ์ดํ ๋ณต๊ท๋ฅผ ์ํด) | ๊ฑฐ์ ์์ (๋ธ๋ก์ "ํธ์ถ"์ด ์๋๋ผ "์์ฐจ ์คํ"์ด๋ผ ํ์ ์์) |
- Blocks can be implemented somewhat simpler and more efficient way
- Allocated after the local variables
- Block variables can be addressed exactly as if they were local variables
- The maximum amount of storage required for block variables can be statically determined f and g occupy the same memory locations as a and b, because a and b are popped off the stack when their block is exited (before f and g are allocated)c
- Static Chain of block
- ๋ธ๋ก์ด๋ ํจ์ ์์์ ๋ฐ๊นฅ์ชฝ์ ์๋ ๋ณ์๋ฅผ ์ฌ์ฉํ ๋ Static Link๋ฅผ ํ๊ณ ์ฐพ์๊ฐ
void main() {
int x, y, z; // main locals
while (...) {
int a, b, c; // block1 locals
while (...) {
int d, e; // block2 locals
...
a = d + 1; // block2์์ block1์ a์ ์ ๊ทผ
}
}
}
- ํ์ฌ ์์น: block2 (d, e)
- ์ ๊ทผํ๋ ค๋ ๋ณ์: block1์ ์๋ a
- ๊ณผ์ :
- block2์ Activation Record์์ ์์
- Static Link๋ฅผ ๋ฐ๋ผ block1์ Activation Record๋ก ์ด๋
- block1 ARI ์์์ a ๋ฅผ local offset์ผ๋ก ์ฐพ์์ ์ ๊ทผ
Dynamic Scoping
Deep access and shallow access
Not concepts related to deep and shallow binding
Deep Access / Shallow Access๋ "๋ณ์์ ์ ๊ทผ(access)"ํ ๋ ๋ฉ๋ชจ๋ฆฌ์์ ์ด๋ป๊ฒ ์ฐพ๋๊ฐ์ ๊ด๋ จ.
Deep Binding / Shallow Binding์ "subprogram์ ํธ์ถ(call)"ํ ๋ ํ๊ฒฝ(environment) ์ ์ด๋ป๊ฒ ๋ฌถ๋๊ฐ์ ๊ด๋ จ
Deep and shallow accesses do not result in different semantics
์ต์ข ์ ์ผ๋ก ์ฐพ์์ ์ฝ๋ ๋ณ์๋ ๋์ผ
๋ฌ๋ผ์ง๋ ๊ฒ์ ์ฑ๋ฅ(performance)
Deep access
Searching through the ARI of active subprogram from most recently activated
Dynamic chain is used
Access may require searches deep into stack
No static link
Reference to x in Sub3 searching for all ARI in stack (follow 4 dynamic links, examine 10 variable)
Reference to v in Sub3 found in recent Sub1
Deep access (two differences from static scope)
There is no way to determine at compile time the length of the chain
Slower execution speeds than static-scoped languages
Activation records must store the names of variables for the search
| ํญ๋ชฉ | ์ค๋ช |
|---|---|
| ๊ฒ์ ๋์ | ํ์ฌ ํ์ฑํ๋ ARI๋ค |
| ๊ฒ์ ๋ฐฉํฅ | ์ต๊ทผ ํ์ฑํ๋ ARI ์ค๋๋ ARI ์์ |
| ๋งํฌ ๊ตฌ์กฐ | Dynamic Chain ์ฌ์ฉ |
| ๊ฒ์ ๋น์ฉ | ๋ณ์ ์์น์ ๋ฐ๋ผ ๋งํผ ๊ฑธ๋ฆผ |
| ๋ฉ๋ชจ๋ฆฌ ์ค๋ฒํค๋ | ์์ (์ถ๊ฐ ํ ์ด๋ธ ํ์ ์์) |
| Semantics ๋ณํ | ์์ (์ฐพ๋ ๊ฒฝ๋ก๋ง ๋ค๋ฅผ ๋ฟ ๊ฒฐ๊ณผ๋ ๊ฐ์) |
Shallow access
Semantics of deep access and shallow access are identical
Variables declared in subprograms are not stored in the ARI of those subprograms
Have a separate stack for each variable name
์ต๊ทผ์ ํ ๋น๋ ๊ฐ์ ๋น ๋ฅด๊ฒ ์ฐพ์ ์ฐ๋ ๋ฐฉ์
Fast references to variables
But maintaining the stacks at the entrances and exits of subprograms is costly
๋ณ์ ์ ์ฅ ์์น ๋ณ์ ์ด๋ฆ๋ง๋ค ๋ณ๋์ ์คํ
ํ์ฑํ๋ ๊ฐ ์คํ์ ์ต์๋จ(top)์ ์กด์ฌ
์๋ก์ด subprogram ํธ์ถ ์ ํ์ํ ๋ณ์ ์ด๋ฆ ์คํ์ ์๋ก์ด ๊ฐ์ push
subprogram ์ข ๋ฃ ์ ๋ณ์ ์ด๋ฆ ์คํ์์ ๊ฐ์ pop
๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๋ณ์ ์ด๋ฆ๋ณ๋ก ๋ณ๋๋ก ๊ด๋ฆฌ
Deep access: fast subprogram linkage but costly for nonlocal referencing
Shallow access: faster references to nonlocals but costly in terms of subprogram linkage
| ํญ๋ชฉ | Deep Access | Shallow Access |
|---|---|---|
| ์ ๊ทผ ๊ฒฝ๋ก | Dynamic Link ํ๊ณ ์ฌ๋ผ๊ฐ | ๋ณ์ ์ด๋ฆ๋ณ ๋ณ๋ ์คํ ์ต์๋จ |
| ์ ๊ทผ ์๊ฐ | ||
| ํ๋ก๊ทธ๋จ ๊ตฌ์กฐ ๋ณต์ก๋ | ๋จ์ | ๋ณต์ก (๊ฐ ๋ณ์๋ง๋ค ์คํ ํ์) |
| ์๋ธํ๋ก๊ทธ๋จ ๊ด๋ฆฌ ๋น์ฉ | ์์ | ํผ (stack push/pop ํ์) |
| Semantics ๋ณํ | ์์ (๋์์ ๋์ผ) | ์์ (๋์์ ๋์ผ) |

