Arch Decision #2
How should the location of static variables be determined by the compiler?
Added by Phil Garcia about 3 years ago. Updated by Phil Garcia about 3 years ago.
| Status: | Under Discussion | ||
| Assignee: | - |
Problem Description
In other words, how should the compiler emit code that can load/store static variables?
Resolution
Factors
| # | Status | Factors (in order of importance) | |
|---|---|---|---|
| 4 | Validated | ||
Strategies
| # | Rejected? | Short name | Summary | |
|---|---|---|---|---|
| 1 | Use FS or GS registers for pointer to TLS, lookup module base address, and add variable offset | |||
| 2 | Use dedicated register for pointer to TLS, lookup module base address, and add variable offset | |||
| 3 | Use EIP register and compile time determined variable offset | |||
| 4 | Resolve all variable positions in memory by patching the executable at module load | |||
| 5 | Use MMU so static variables use fixed addresses within a process. | |||
Issues
| # | Relation to AD | Status | Redmine Issue or External URL |
|---|
Discussion
Re: How should the location of static variables be determined by the compiler? - Added by Ben Kloosterman about 3 years ago
6. Put up with the same restriction of VMM ie all threads at one time must be the same process and get the context switch to put it at a hard coded location
Re: How should the location of static variables be determined by the compiler? - Added by Michael Fröhlich about 3 years ago
The big question is: Are we going to jit all assemblies or not? If we assume we are jitting all assemblies, I'd vote for a different model: We keep a static data area in memory for a process, which is pointed to by GS. During assembly load, we allocate space in this global heap per module and during JIT we calculate proper GS relative offsets to access global data. Basically this is a mix of #1 and #4.
I know other VMs (Jikes) solve this issue similarly where they keep a per module table of static data with pointers to it. We already support this model through the RuntimeField.Address property. We'd only have to improve the metadata access performance.
Re: How should the location of static variables be determined by the compiler? - Added by Ben Kloosterman about 3 years ago
Im not 100% sure a Jit is viable , since all assemblies must be thoroughly checked to ensure all references & address are valid. At best you get a JIT with cache which is basically the same as a AOT.
The Big issue here is your compiler is trusted and that raises issues on installing shared assemblies and recompiling OS and even compiler assemblies.
I preffer to do the compile at install time thus allowing system specific compilation. Though it will be JIT style eg compiled to a cache thus allowing changes when the compiler is patched.
Anyway this belongs in another discusssion
Re: How should the location of static variables be determined by the compiler? - Added by Ben Kloosterman about 3 years ago
1 and 2 are the same thing just arch dependent.
I kind of favour these for shared data since
1. They are fast
2. The data is frequently needed anyway eg Thread.Current.Id is used in every spinlock. You Also access TLS this way together this could be 100,000- 1000,000 operations ( which could be many cycles /instruction each) per second esp for web servers. Though a CPU intentsive task wouldnt use it rarely.
3. The implementation is Arch dependent hence can be quickly changed to test.
In the case of user static data i would just patch the locations ( only question is to allocate the mem from teh Memory Manager or via the GC but have it fixed) like we need to do anyway for Code. Note this would be done on the x86 code after it is compiled via a map file .
Re: How should the location of static variables be determined by the compiler? - Added by Phil Garcia about 3 years ago
Michael Fröhlich wrote:
The big question is: Are we going to jit all assemblies or not?
For performance, we should AOT the common standard libraries in some cache and leave JIT for first-time (or infrequent) applications.
If we assume we are jitting all assemblies, I'd vote for a different model: We keep a static data area in memory for a process, which is pointed to by GS. During assembly load, we allocate space in this global heap per module and during JIT we calculate proper GS relative offsets to access global data. Basically this is a mix of #1 and #4.
For JIT of applications (not libraries) this makes perfect sense since the compiler can resolve all memory locations are run-time. But I'd opt for AOT with caching in the short term.
I know other VMs (Jikes) solve this issue similarly where they keep a per module table of static data with pointers to it. We already support this model through the RuntimeField.Address property. We'd only have to improve the metadata access performance.
That's similar to the Global Offset Table (GOT) idea, which I favor at the moment since it allows for the great amount of code sharing and cache locality.