diff options
author | samuel <samuel@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-11-20 09:59:10 +0000 |
---|---|---|
committer | samuel <samuel@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-11-20 09:59:10 +0000 |
commit | 07a324a0f6464f31765ee4bc5cfc23a99d426705 (patch) | |
tree | dd928b5cc16b6b44c9d7a1c68346da8061b0573a /coroutine/arm64 | |
parent | 27665e5134582bf58fb196268d659cc19df39f61 (diff) | |
download | ruby-07a324a0f6464f31765ee4bc5cfc23a99d426705.tar.gz |
Native implementation of coroutines to improve performance of fibers
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65834 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'coroutine/arm64')
-rw-r--r-- | coroutine/arm64/Context.h | 60 | ||||
-rw-r--r-- | coroutine/arm64/Context.s | 58 |
2 files changed, 118 insertions, 0 deletions
diff --git a/coroutine/arm64/Context.h b/coroutine/arm64/Context.h new file mode 100644 index 0000000000..8dc010d982 --- /dev/null +++ b/coroutine/arm64/Context.h @@ -0,0 +1,60 @@ +// +// amd64.h +// File file is part of the "Coroutine" project and released under the MIT License. +// +// Created by Samuel Williams on 10/5/2018. +// Copyright, 2018, by Samuel Williams. All rights reserved. +// + +#pragma once + +#include <assert.h> +#include <string.h> + +#if __cplusplus +extern "C" { +#endif + +#define COROUTINE void + +const size_t COROUTINE_REGISTERS = 0xb0 / 8; + +// The fiber context (stack pointer). +typedef struct +{ + void **stack_pointer; +} coroutine_context; + +// The initialization function. +typedef void(* coroutine_start)(coroutine_context *from, coroutine_context *self); + +inline void coroutine_initialize( + coroutine_context *context, + coroutine_start start, + void *stack_pointer, + size_t stack_size +) { + /* Force 16-byte alignment */ + context->stack_pointer = (void**)((uintptr_t)stack_pointer & ~0xF); + + if (!start) { + assert(!context->stack_pointer); + /* We are main coroutine for this thread */ + return; + } + + context->stack_pointer -= COROUTINE_REGISTERS; + memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); + + context->stack_pointer[0xa0 / 8] = (void*)start; +} + +coroutine_context * coroutine_transfer(coroutine_context * current, coroutine_context * target); + +inline void coroutine_destroy(coroutine_context * context) +{ +} + +#if __cplusplus +} +#endif diff --git a/coroutine/arm64/Context.s b/coroutine/arm64/Context.s new file mode 100644 index 0000000000..f8d76e82c4 --- /dev/null +++ b/coroutine/arm64/Context.s @@ -0,0 +1,58 @@ +## +## arm64.s +## File file is part of the "Coroutine" project and released under the MIT License. +## +## Created by Samuel Williams on 10/5/2018. +## Copyright, 2018, by Samuel Williams. All rights reserved. +## + +.text +.align 2 +.global coroutine_transfer +coroutine_transfer: + # Make space on the stack for caller registers + sub sp, sp, 0xb0 + + # Save caller registers + stp d8, d9, [sp, 0x00] + stp d10, d11, [sp, 0x10] + stp d12, d13, [sp, 0x20] + stp d14, d15, [sp, 0x30] + stp x19, x20, [sp, 0x40] + stp x21, x22, [sp, 0x50] + stp x23, x24, [sp, 0x60] + stp x25, x26, [sp, 0x70] + stp x27, x28, [sp, 0x80] + stp x29, x30, [sp, 0x90] + + # Save return address + str x30, [sp, 0xa0] + + # Save stack pointer to x0 (first argument) + mov x2, sp + str x2, [x0, 0] + + # Load stack pointer from x1 (second argument) + ldr x3, [x1, 0] + mov sp, x3 + + # Restore caller registers + ldp d8, d9, [sp, 0x00] + ldp d10, d11, [sp, 0x10] + ldp d12, d13, [sp, 0x20] + ldp d14, d15, [sp, 0x30] + ldp x19, x20, [sp, 0x40] + ldp x21, x22, [sp, 0x50] + ldp x23, x24, [sp, 0x60] + ldp x25, x26, [sp, 0x70] + ldp x27, x28, [sp, 0x80] + ldp x29, x30, [sp, 0x90] + + # Load return address into x4 + ldr x4, [sp, 0xa0] + + # Pop stack frame + add sp, sp, 0xb0 + + # Jump to return address (in x4) + ret x4 |