Description
Before OTP 27, cover
worked by inserting code to do counters:add(CRef, LineIndex, 1)
around any significant code. The CRef
is a counter for the original module's coverage, so Horus only needed to preserve those instructions in the standalone module in order to have the function's coverage count for the original module.
OTP 27 introduces "native" coverage (introduced in erlang/otp#7856). The compiler now emits executable_line
instructions when passed the force_line_counters
(or line_coverage
option, depending on the system's code:get_coverage_mode/0
). The JIT turns that that instruction into an atomic add or literal mov that updates a section of the BeamCodeHeader
's coverage
buffer (see x86, arm). BeamCodeHeader
is a member of each module instance (erl_module_instance
) and the BIF that cover
uses to read coverage information when native coverage is enabled reads from this new buffer from the current module. (As a consequence, old coverage is now no longer accessible after upgrading/reloading a module.)
The old cover
code is still around for architectures that use the emulator but we can't turn off native coverage on a JIT-enabled build of OTP.
Since coverage information is now attached to module instances, I don't believe we can trick cover
into counting executions of horus functions anymore.