Assuming that we continue to use GC'd storage as extensively throughout the VM and the Flash Player as we currently are using it, it is almost certainly the case that we will forever be scanning C++ stack frames conservatively. (The alternative would be some combination of system-wide iron discipline and behind-the-scenes tracking of pointers in GCRefs, and perhaps mandatory GCRef use. I just don't see it being cost-effective or practical.) So how can we reduce the impact of that conservative scanning? Some obvious examples: - rewrite C++ code as AS3 code to sidestep the issue - jit-compile what are now C++ helpers whose frames appear inbetween jit frames, so that we can control those frame layouts - make a distinction between "harmless" C++ frames (frames that don't need to be scanned (at all, or conservatively) because they obey the necessary iron discipline, eg by explicitly enregistering all pointers to GC storage) and "unknown" frames that must be scanned conservatively, and try to postpone stack scanning if the stack has just a few "unknown" frames on it in the hope that they will be popped soon. ("Postponing" can be made affordable by starting to check for a good scanning point earlier than we would if we were following current GC policy strictly.) - static analysis of C++ frames may allow us to create exact tracers for those frames, but obviously this is platform-dependent and brittle. The platforms that matter are all mobile, sometimes with highly optimizing non-GCC compilers, sometimes with unusual operating systems. - avoid alloca() by moving to other temp-memory mechanisms, eg, temp-memory managers attached to a GC might work well in practice. That is, reduce the amount of C++ stack memory that must be scanned conservatively as much as possible, and then start thinking about how to not scan the stack when there is any stack memory that must be scanned conservatively.
Another problem is that we recognize pointers to the interior of objects from conservatively scanned stack frames. That's necessary because some compilers will construct part objects of larger objects with only a pointer to the part object in a register or on the stack. If our allocation protocol could guarantee that the pointer to the object itself would be maintained somewhere we could avoid recognizing interior pointers, which would reduce false retention. It's not clear what it would take to construct such a protocol, as it would have to be somewhat opaque to the optimizer to avoid a store being optimized away or reordered. (RVCT is the one that came up, but we had some issues with StringIterator and MSVC that were papered over with the use of volatile, so the problem may be more general.)
Iron discipline will never happen, but iron enforcement via static analysis just might work. Early versions of the avm didn't use conservative stack scanning and the rule was "you must pin your object with this API if your code can result in an allocation happening before your reference is written into the heap somewhere". That was a tricky rule to follow. One thing that could mitigate this whole issue pretty effectively is our ability to do GC work on the edges where we don't need to scan the stack at all. We could beef up that up. We could also tighten up the entry/exit code in the player, ie so that we enter/exit the GC multiple times per frame as we go through the various subsystems. Of course AIR and background threads won't have the same setup as the player.
Any thoughts on how frame boundaries will be found? the options I can think of are: a) unwind the stack using the platform stack conventions. Some (PPC, ARM, maybe more) may require inspecting compiler-generated records to do this b) rely on MethodFrame locations and boundaries. MF's form a linked list, but dont record the full bounds of the jit stack frame. (they could). this would divide the stack into known and unknown segments. For JIT generated helpers we can also record enough data to support unwinding those frames.
Assignee: lhansen → nobody
Status: ASSIGNED → NEW
Priority: -- → P3
Target Milestone: Future → flash10.x-Serrano
Its worth noting that strict implementation of safegc would give us a way to track the lifetimes of stack pointers via the GCRef object. Probably not useful for implementation purposes but might be good for "iron adherence" checking or data gathering.
You need to log in before you can comment on or make changes to this bug.