Runtime Organization
A compiler contains many phases:
- Front-end phases: Lexical analysis, parsing, semantic analysis.
- Back-end phases: Code generation, optimization.
- The resultant object files are linked against external libraries, creating a final executable.
After the compiler has done its job, the program is executed by the runtime system.A loader loads the program into memory, creating a program address space. This contains the code, stack and data segment. Next, the loader will pass control to the program's entry point.
1. Variables
There are many different types of variables:
- Primitives may require different amounts of memory. For optimal access, we should align variables to boundaries / PCIE bandwidth.
- Records are key-value pairs. They can be different types and sizes, and are typically allocated consecutively in memory, for easy access (addressing) and memory efficiency.
- Arrays are groups of variables with the same data type. They are also allocated consecutively in memory, and can be accessed using a base address and an offset.
- Objects are more complex. They are referenced by a pointer, and contain a pointer to a method lookup table, as well raw values for the data fields.
2. Objects
To access data fields on objects, we can use an address offset. To call a method, we pass the object reference as a hidden parameter. On Intel IA-32:
1mov eax, <b> ; Load contents of b into eax 2push eax ; Push object ref as a hidden inner parameter 3mov eax, [eax] ; Load address of method lookup table into `eax` 4call [eax + 4] ; Call the method at offset 4
For inheritance and overriding, a new method lookup table is created, with a pointer to the parent's method lookup table. This allows for dynamic dispatch.
Dynamic binding also can be done, by copying an object's reference.
3. Variable Scope
- Local variables persist only for the duration of the method call. They are located in the stack segment of the program address space. They are accessed with the help of a frame pointer register (pointing to the base of the stack frame) and an offset.
- Static/Global variables persist for the duration of the program. They are located in the data segment (static area) of the program address space. They are accessed directly using the base memory address - no frame pointer registers required.
- Dynamic variables persist until garbage collection. They are located in the data segment (heap area) of the program address space.