Run-Time Storage Management and Activation Records: Managing Procedure Calls
Learn about run-time storage management and activation records (stack frames), crucial for managing procedure calls and program state. This guide explains how activation records are created and managed on the runtime stack, covering static and dynamic allocation methods.
Run-Time Storage Management and Activation Records
Activation Records and Procedure Calls
When a procedure (function or subroutine) is called during program execution, a block of memory called an activation record (or stack frame) is created to store information related to that specific procedure call. This record holds data essential for the procedure's execution and is crucial for managing the program’s state, particularly for nested or recursive functions. Activation records are dynamically allocated on a runtime stack (or control stack) as procedures are called and deallocated when the procedures return. The stack's structure helps to keep track of function calls. When a function calls another function, a new activation record is added on top of the stack; when a function returns, its activation record is removed.
Addressing in Target Code
There are different ways to manage memory addresses for activation records:
- Static Allocation: The memory location for each activation record is fixed at compile time. This is simpler but less flexible.
- Stack Allocation: Activation records are dynamically allocated and deallocated on a stack. This is more flexible and allows for handling nested function calls but adds complexity.
Run-Time Memory Areas
During program execution, memory is typically divided into different areas:
- Code: The program's instructions.
- Static Data: Global and static variables.
- Stack: Used for activation records and local variables.
Static Allocation: Implementing Call, Return, and Halt
In static allocation, the memory location for an activation record is known at compile time. Here's how basic operations are implemented:
1. Call Statement:
Call Statement (Assembly-like)
MOV #here + 20, callee.static_area // Save return address
GOTO callee.code_area // Jump to called procedure
2. Return Statement:
Return Statement (Assembly-like)
GOTO *callee.static_area // Jump to return address
3. Halt Statement:
Halt Statement (Assembly-like)
HALT // Terminate execution
The `Action` statement is a placeholder for other instructions.
Stack Allocation: Implementing Call and Return
Stack allocation provides dynamic memory management for activation records. It utilizes a stack data structure for allocating and deallocating these records. The stack pointer (SP) keeps track of the current top of the stack.
1. Stack Initialization:
Stack Initialization (Assembly-like)
MOV #stackstart, SP // Initialize stack pointer
HALT // Halt execution
2. Call Statement:
Call Statement (Stack Allocation - Assembly-like)
ADD #caller.recordsize, SP // Increment stack pointer
MOV #here + 16, *SP // Save return address
GOTO callee.code_area // Jump to called procedure
3. Return Statement:
Return Statement (Stack Allocation - Assembly-like)
GOTO *0(SP) // Return to caller
SUB #caller.recordsize, SP // Decrement stack pointer