|
@@ -835,45 +835,23 @@ for collector plugins which implement reference counting or a shadow stack.
|
|
|
|
|
|
.. _init-roots:
|
|
.. _init-roots:
|
|
|
|
|
|
-Initializing roots to null: ``InitRoots``
|
|
|
|
------------------------------------------
|
|
|
|
-
|
|
|
|
-.. code-block:: c++
|
|
|
|
-
|
|
|
|
- MyGC::MyGC() {
|
|
|
|
- InitRoots = true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-When set, LLVM will automatically initialize each root to ``null`` upon entry to
|
|
|
|
-the function. This prevents the GC's sweep phase from visiting uninitialized
|
|
|
|
-pointers, which will almost certainly cause it to crash. This initialization
|
|
|
|
-occurs before custom lowering, so the two may be used together.
|
|
|
|
-
|
|
|
|
-Since LLVM does not yet compute liveness information, there is no means of
|
|
|
|
-distinguishing an uninitialized stack root from an initialized one. Therefore,
|
|
|
|
-this feature should be used by all GC plugins. It is enabled by default.
|
|
|
|
|
|
+Initializing roots to null
|
|
|
|
+---------------------------
|
|
|
|
|
|
-Custom lowering of intrinsics: ``CustomRoots``, ``CustomReadBarriers``, and ``CustomWriteBarriers``
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
|
|
+It is recommended that frontends initialize roots explicitly to avoid
|
|
|
|
+potentially confusing the optimizer. This prevents the GC from visiting
|
|
|
|
+uninitialized pointers, which will almost certainly cause it to crash.
|
|
|
|
|
|
-For GCs which use barriers or unusual treatment of stack roots, these
|
|
|
|
-flags allow the collector to perform arbitrary transformations of the
|
|
|
|
-LLVM IR:
|
|
|
|
|
|
+As a fallback, LLVM will automatically initialize each root to ``null``
|
|
|
|
+upon entry to the function. Support for this mode in code generation is
|
|
|
|
+largely a legacy detail to keep old collector implementations working.
|
|
|
|
|
|
-.. code-block:: c++
|
|
|
|
-
|
|
|
|
- class MyGC : public GCStrategy {
|
|
|
|
- public:
|
|
|
|
- MyGC() {
|
|
|
|
- CustomRoots = true;
|
|
|
|
- CustomReadBarriers = true;
|
|
|
|
- CustomWriteBarriers = true;
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
|
|
+Custom lowering of intrinsics
|
|
|
|
+------------------------------
|
|
|
|
|
|
-If any of these flags are set, LLVM suppresses its default lowering for
|
|
|
|
-the corresponding intrinsics. Instead, you must provide a custom Pass
|
|
|
|
-which lowers the intrinsics as desired. If you have opted in to custom
|
|
|
|
|
|
+For GCs which use barriers or unusual treatment of stack roots, the
|
|
|
|
+implementor is responsibly for providing a custom pass to lower the
|
|
|
|
+intrinsics with the desired semantics. If you have opted in to custom
|
|
lowering of a particular intrinsic your pass **must** eliminate all
|
|
lowering of a particular intrinsic your pass **must** eliminate all
|
|
instances of the corresponding intrinsic in functions which opt in to
|
|
instances of the corresponding intrinsic in functions which opt in to
|
|
your GC. The best example of such a pass is the ShadowStackGC and it's
|
|
your GC. The best example of such a pass is the ShadowStackGC and it's
|
|
@@ -884,62 +862,14 @@ without building a custom copy of LLVM.
|
|
|
|
|
|
.. _safe-points:
|
|
.. _safe-points:
|
|
|
|
|
|
-Generating safe points: ``NeededSafePoints``
|
|
|
|
---------------------------------------------
|
|
|
|
-
|
|
|
|
-LLVM can compute four kinds of safe points:
|
|
|
|
-
|
|
|
|
-.. code-block:: c++
|
|
|
|
-
|
|
|
|
- namespace GC {
|
|
|
|
- /// PointKind - The type of a collector-safe point.
|
|
|
|
- ///
|
|
|
|
- enum PointKind {
|
|
|
|
- Loop, //< Instr is a loop (backwards branch).
|
|
|
|
- Return, //< Instr is a return instruction.
|
|
|
|
- PreCall, //< Instr is a call instruction.
|
|
|
|
- PostCall //< Instr is the return address of a call.
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-A collector can request any combination of the four by setting the
|
|
|
|
-``NeededSafePoints`` mask:
|
|
|
|
-
|
|
|
|
-.. code-block:: c++
|
|
|
|
-
|
|
|
|
- MyGC::MyGC() {
|
|
|
|
- NeededSafePoints = 1 << GC::Loop
|
|
|
|
- | 1 << GC::Return
|
|
|
|
- | 1 << GC::PreCall
|
|
|
|
- | 1 << GC::PostCall;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-It can then use the following routines to access safe points.
|
|
|
|
-
|
|
|
|
-.. code-block:: c++
|
|
|
|
-
|
|
|
|
- for (iterator I = begin(), E = end(); I != E; ++I) {
|
|
|
|
- GCFunctionInfo *MD = *I;
|
|
|
|
- size_t PointCount = MD->size();
|
|
|
|
-
|
|
|
|
- for (GCFunctionInfo::iterator PI = MD->begin(),
|
|
|
|
- PE = MD->end(); PI != PE; ++PI) {
|
|
|
|
- GC::PointKind PointKind = PI->Kind;
|
|
|
|
- unsigned PointNum = PI->Num;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-Almost every collector requires ``PostCall`` safe points, since these correspond
|
|
|
|
-to the moments when the function is suspended during a call to a subroutine.
|
|
|
|
-
|
|
|
|
-Threaded programs generally require ``Loop`` safe points to guarantee that the
|
|
|
|
-application will reach a safe point within a bounded amount of time, even if it
|
|
|
|
-is executing a long-running loop which contains no function calls.
|
|
|
|
|
|
+Generating safe points
|
|
|
|
+-----------------------
|
|
|
|
|
|
-Threaded collectors may also require ``Return`` and ``PreCall`` safe points to
|
|
|
|
-implement "stop the world" techniques using self-modifying code, where it is
|
|
|
|
-important that the program not exit the function without reaching a safe point
|
|
|
|
-(because only the topmost function has been patched).
|
|
|
|
|
|
+LLVM provides support for associating stackmaps with the return address of
|
|
|
|
+a call. Any loop or return safepoints required by a given collector design
|
|
|
|
+can be modeled via calls to runtime routines, or potentially patchable call
|
|
|
|
+sequences. Using gcroot, all call instructions are inferred to be possible
|
|
|
|
+safepoints and will thus have an associated stackmap.
|
|
|
|
|
|
.. _assembly:
|
|
.. _assembly:
|
|
|
|
|