| ============================== |
| FaultMaps and implicit checks |
| ============================== |
| |
| .. contents:: |
| :local: |
| :depth: 2 |
| |
| Motivation |
| ========== |
| |
| Code generated by managed language runtimes tend to have checks that |
| are required for safety but never fail in practice. In such cases, it |
| is profitable to make the non-failing case cheaper even if it makes |
| the failing case significantly more expensive. This asymmetry can be |
| exploited by folding such safety checks into operations that can be |
| made to fault reliably if the check would have failed, and recovering |
| from such a fault by using a signal handler. |
| |
| For example, Java requires null checks on objects before they are read |
| from or written to. If the object is ``null`` then a |
| ``NullPointerException`` has to be thrown, interrupting normal |
| execution. In practice, however, dereferencing a ``null`` pointer is |
| extremely rare in well-behaved Java programs, and typically the null |
| check can be folded into a nearby memory operation that operates on |
| the same memory location. |
| |
| The Fault Map Section |
| ===================== |
| |
| Information about implicit checks generated by LLVM are put in a |
| special "fault map" section. On Darwin this section is named |
| ``__llvm_faultmaps``. |
| |
| The format of this section is |
| |
| .. code-block:: none |
| |
| Header { |
| uint8 : Fault Map Version (current version is 1) |
| uint8 : Reserved (expected to be 0) |
| uint16 : Reserved (expected to be 0) |
| } |
| uint32 : NumFunctions |
| FunctionInfo[NumFunctions] { |
| uint64 : FunctionAddress |
| uint32 : NumFaultingPCs |
| uint32 : Reserved (expected to be 0) |
| FunctionFaultInfo[NumFaultingPCs] { |
| uint32 : FaultKind = FaultMaps::FaultingLoad (only legal value currently) |
| uint32 : FaultingPCOffset |
| uint32 : handlerPCOffset |
| } |
| } |