diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 8b153b7..4c418c0 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -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);