3 Predicate Linkage

For the purposes of SPJIT, it is useful to think of three modes in which a predicate p can be:

jitex

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.

cex

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? Directly (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.

wamex

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.



Send feedback on this subject.