I am writing a non-invasive conservative GC in C, and I have some doubts about the correctness of its stack scan phase.
In particular, in the absence of compiler optimizations, it works fine, because each local variable (which points to an object) is "predictably" allocated on the stack. In -O3 GC skips some valid references, which, in my opinion, are related to the fact that the compiler prefers to use registers (instead of the stack that the GC scans) for some variables and arguments of the function argument, and GC is not (yet) programmed to this is. (If you suspect that this should still not happen and that I am misinterpreting the source of the problem, please let me know.)
In addition to some basic requirements (using GC_malloc instead of malloc for GC objects, not pointing to a GC heap from a non-GC heap and, of course, not explicitly calling free ), GC should not have more requirements from client code or compiler. Therefore, no additional special patterns from client code are required. Similarly, compulsory programs that use this GC to compile with special compiler flags (which suppress stack optimization) should, at best, be the last option. With these two aside, here is building up my question.
I am trying to find a way to make the GC handle the -O3 case (with stack optimization) without problems. Here is my train of thought (assumptions, more precisely):
- No matter how much GCC (or any virtual compiler) goes with optimizations, it has not gone so far as to compromise the correctness of the program.
- If [1] holds, I believe that (at least in practical C implementations), if the reachable (allocated as local at any call level) variable to remain accessible at all, it should be either on the stack or in the current set case , but not elsewhere.
- If [2] is executed, this should mean that simply flushing all the registers onto the stack when the GC cycle starts ensures that subsequent stack scanning will now find previously skipped links.
- In addition, if [1] and [2] are executed, then if the compiler allows you to overwrite any variables (mainly based on registers), this means that it has performed some level of code analysis, and that this variable is not used anywhere in this function. So, in this sense, if we do not see the variable on the stack or in the register dump, although it is still in the field (theoretically), this should not be a cause for alarm (for me), because the compiler has just helped the GC, getting rid of from a dead link.
Question No. 1: Are all 4 of my assumptions correct?
Question No. 2:. What is the most portable way to force a registry reset? I found several sources claiming that a simple setjmp call would have this effect. Is it correct?
Theodoros Chatzigiannakis
source share