For the purposes of SPJIT, it is useful to think of three modes in which a predicate p can be:
p has been JIT compiled and does not have a breakpoint, block declaration or the like. Calls from other jitex predicates to p stay in native code.
p is implemented by a C function and does not have a breakpoint,
block declaration or the like. Calls from jitex predicates to
p go to the C function [PERM: “go to the C function” means what?
Direcly (not via native_c
? If so, how are
breakpoints/redefinitions to C functions triggered when called from
jitted code_].
Such predicates are never subject to JIT compilation.
All other cases. Calls from jitex predicates to p are routed via the WAM emulator. The transfer of control is implemented by returning from the JIT runtime system with the value 2.
When SICStus starts, no jitex predicates exist, but start to appear as emulated predicates get JIT compiled.
Note that setting a breakpoint on a jitex predicate changes its state to wamex. Removing the breakpoint changes the state back to jitex. Redefining a jitex predicate also changes its state to wamex.
For a predicate p whose struct definition *
pointer is
def
, def->jit
is either NULL or points at the JIT code
generated for p, whereas def->proc.native
contains a
lead-in sequence of machine instructions. The JIT compiler translates a
call from p to q into a call to q’s lead-in sequence,
no matter what type of predicate q is or whether it is even
defined.
[PERM: Do mod_def.proxies
definitions need some special treatment?]
If p is jitex, then the lead-in sequence calls the kernel
subroutine native_shunt_link
, which patches the caller to
directly call the JIT code the next time around. If p is
cex, then the lead-in sequence calls the kernel subroutine
native_c
, which routes the call to the C function. If p is
wamex, then the lead-in sequence calls the kernel subroutine
native_nonjit
, which arranges for the call to be handled by the
WAM emulator.
If the state of p changes from jitex to wamex, then
a prefix of def->jit
is modified to an instruction sequence
that calls the kernel subroutine native_restore_link
, which
patches the caller to call the lead-in sequence the next time around.
If the state of p changes from cex to wamex because
a breakpoint was set, then def->jit
is not relevant (because
such predicates are not jitted).
If the state of p changes from wamex back to jitex
because a breakpoint was removed, then the prefix of def->jit
is
repaired to contain the original JIT instructions for p.
If p was first JIT compiled and then redefined, then
def->jit
cannot be freed entirely, because there may be dangling
references to it created by native_shunt_link
. Thus, its prefix,
which calls native_restore_link
, must be preserved. This small
memory leak is not expected to be noticeable in a production setting.
The exact layout of these code sequences is back-end dependent and is explained in the following sections.
• Code Outline Lead-In and Prefix Sequences for x86: | ||
• Code Outline Lead-In and Prefix Sequences for x86_64: | ||
• Code Outline Lead-In and Prefix Sequences for PPC64: | ||
• WAM-JIT Interface: |