[LLVMdev] Should LLVM JIT default to lazy or non-lazy?
Török Edwin
edwintorok at gmail.com
Fri Oct 30 02:15:58 PDT 2009
On 2009-10-29 23:55, Jeffrey Yasskin wrote:
> On Thu, Oct 29, 2009 at 2:30 PM, Nicolas Geoffray
> <nicolas.geoffray at lip6.fr> wrote:
>
>> Hi Jeffrey,
>>
>> Jeffrey Yasskin wrote:
>>
>>> Cool, I'll start implementing it.
>>>
>>>
>> Great! Thanks.
>>
>> Just to clarify things: on my end, it doesn't really matter what is the
>> default behavior, as long as vmkit can continue to have the existing
>> behavior of lazy compilation. With Chris' solution, I was wondering how you
>> would implement the getPointerToFunction{Eager, Lazy} functions when the
>> getPointerToFunction is called by the JIT, not the user. For example, when
>> Function F calls Function G and the JIT needs an address for G (either a
>> callback or the function address), how will it know if it must call
>> getPointerToFunctionEager or getPointerToFunctionLazy? Do you plan on
>> continuing having a flag that enables/disables lazy compilation and poll
>> this flag on each function call? How is that different than the existing
>> system?
>>
>
> Semantically, I'll thread the flag through all the calls that may
> eventually need to recursively call getPointerToFunction. To implement
> that without having to modify lots of calls, I'll probably replace the
> current public default eager/lazy setting with a private flag with
> values {Unknown, Lazy, Eager}, set it on entry and exit of
> getPointerToFunction, and check it on each internal recursive call.
> The difference with the current system is that the user is forced to
> set the flag to their desired value whenever they call into the JIT,
> rather than relying on a default. That choice then propagates through
> the whole recursive tree of codegens, without affecting the next tree.
>
> Note that I'm using getPointerToFunction as an abbreviation for the
> 3ish public functions that'll need to take this option.
The documentation should also be updated
(http://llvm.org/docs/ProgrammersManual.html#threading) to reflect what
one needs to do,
to ensure thread-safe JITing.
Also does every JIT target support non-lazy JITing now? See PR4816,
last time I checked (r83242) it only worked on X86, and failed on PPC;
so I had to keep lazy JITing enabled even if its not what I want for
many reasons.
Also perhaps the lazy compilation stub should spin waiting on a lock
(implemented using atomics), and the compilation callback should
execute while holding the lock just before patching the callsite, so it
would look like this in pseudocode:
callsite_patch_state = 0;// for each callsite one byte of memory
callsite:
if (atomic_load(&callsite_patch_state) == 2) {
//fast-path: already compiled and patched
patchsite:
jmp <nop nop nop nop nop nop nop nop> // will be patched
}
// not yet patched, it may already be compiling
if (atomic_test_and_set(&callsite_patch_state, 0, 1) == 0) {
// not yet compiling, set state to compiling, and start compiling
call CompilationCallBack
// set state to patched
atomic_set(&callsite_patch_state, 2)
}
// wait for patched state
while (atomic_load(&callsite_patch_state) != 2) {
waitJIT();
}
// serialize
CPUID
patchsite2:
// execute new code
jmp <nop nop nop nop nop nop nop nop> // will be patched
waitJIT:
jitLock()
jitUnlock()
^This should be consistent with the Intel Manual's requirements on XMC,
which has a similar algorithm, except for the fast-path.
CompilationCallBack:
jitLock();
if (isJITed(F)) {jitUnlock(); return;}
JIT function
patch_callsite(&patchsite, compiledFunctionAddress);
patch_callsite(&patchsite2, compiledFunctionAddress);
setJITed(F, true);
jitUnlock();
This way once it is compiled the callsite will only execute:
atomic_load(&callsite_patch_state)
== 2
jmp compiledFunctionAddress
Best regards,
--Edwin
More information about the llvm-dev
mailing list