Use a trampoline if musttail not available
All checks were successful
Tests / Clang total: 4452, passed: 4452
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / 64 bit versions total: 4452, passed: 4452
Tests / Debug total: 4450, passed: 4450
Tests / SIMD fallback total: 4452, passed: 4452
Tests / Release [gcc] total: 4452, passed: 4452
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 3313, passed: 3313
Tests / Coverage total: 3347, passed: 3347
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 99.07% (2021/2040) * Branch Coverage: 64.20% (1655/2578) * Complexity Density: 0.00 * Lines of Code: 2040 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good

For the previous approach to work, we would have had to lock in the
generated code for every function that needs to make tail calls in
assembly.
This commit is contained in:
2024-10-10 17:30:16 -07:00
parent 1faeb220d5
commit 2018fa277c

View File

@@ -3260,35 +3260,28 @@ struct CheckContext {
ConflictSet::Result *results;
int64_t started;
ReadContext *tls;
#if !__has_attribute(musttail)
CheckJob *job;
bool done;
#endif
};
#if __has_attribute(musttail)
FLATTEN PRESERVE_NONE void keepGoing(CheckJob *job, CheckContext *context) {
#if __has_attribute(musttail)
job = job->next;
MUSTTAIL return job->continuation(job, context);
#else
context->job = job->next;
return;
#endif
}
#else
static_assert(offsetof(CheckJob, next) == 0x38);
static_assert(offsetof(CheckJob, continuation) == 0x28);
extern "C" void keepGoing(CheckJob *, CheckContext *);
#if defined(__x86_64__)
asm("keepGoing:\n"
" mov 0x38(%rdi),%rdi\n"
" jmp *0x28(%rdi)\n");
#elif defined(__aarch64__)
asm("keepGoing:\n"
" ldr x0, [x0, #0x38]\n"
" ldr x16, [x0, #0x28]\n"
" br x16\n");
#else
#error "Only x64 and aarch64 are supported"
#endif
#endif
FLATTEN PRESERVE_NONE void complete(CheckJob *job, CheckContext *context) {
if (context->started == context->count) {
if (job->prev == job) {
#if !__has_attribute(musttail)
context->done = true;
#endif
return;
}
job->prev->next = job->next;
@@ -3495,9 +3488,17 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
inProgress[0].prev = inProgress + started - 1;
inProgress[started - 1].next = inProgress;
#if __has_attribute(musttail)
// Kick off the sequence of tail calls that finally returns once all jobs
// are done
inProgress->continuation(inProgress, &context);
#else
context.job = inProgress;
context.done = false;
while (!context.done) {
context.job->continuation(context.job, &context);
}
#endif
for (int i = 0; i < count; ++i) {
assert(reads[i].readVersion >= 0);