tpunt / phactor

An implementation of the Actor model for PHP
BSD 3-Clause "New" or "Revised" License
61 stars 5 forks source link

Avoid realloc call in context switching #2

Closed tpunt closed 6 years ago

tpunt commented 6 years ago

Currently, realloc is invoked every time the machine stack is saved. If two variables were used to keep track of the allocated machine stack size and the currently used stack size, then a realloc call would only need to be incurred if used_stack_size > allocated_stack_size.

A POC can be seen below, but it does not work (I haven't had time to debug why, yet):

diff --git a/src/ph_context.c b/src/ph_context.c
index e3088ee9e2..4e7e47543f 100644
--- a/src/ph_context.c
+++ b/src/ph_context.c
@@ -23,11 +23,12 @@
 void ph_mcontext_init(ph_mcontext_t *mc, void (*cb)(void))
 {
 #ifdef PH_FIXED_STACK_SIZE
-    mc->stack_size = PH_FIXED_STACK_SIZE;
-    mc->stack_space = calloc(1, mc->stack_size + STACK_ALIGNMENT - 1);
+    mc->allocated_stack_size = PH_FIXED_STACK_SIZE;
+    mc->stack_space = calloc(1, mc->allocated_stack_size + STACK_ALIGNMENT - 1);
     mc->aligned_stack_space = (void *)((uintptr_t)mc->stack_space + (STACK_ALIGNMENT - 1) & ~(STACK_ALIGNMENT - 1));
 #else
-    mc->stack_size = 0;
+    mc->allocated_stack_size = 0;
+    mc->used_stack_size = 0;
     mc->stack_space = NULL;
 #endif
     mc->cb = cb;
@@ -43,8 +44,8 @@ void ph_mcontext_reset(ph_mcontext_t *mc)
     mc->started = 0;

     // assumes the stack always grows downwards
-    mc->rbp = mc->aligned_stack_space + mc->stack_size;
-    mc->rsp = mc->aligned_stack_space + mc->stack_size;
+    mc->rbp = mc->aligned_stack_space + mc->allocated_stack_size;
+    mc->rsp = mc->aligned_stack_space + mc->allocated_stack_size;
 #endif
 }

diff --git a/src/ph_context.h b/src/ph_context.h
index d494c577da..875cd409ad 100644
--- a/src/ph_context.h
+++ b/src/ph_context.h
@@ -35,8 +35,10 @@ typedef struct _ph_mcontext_t {
     void *r15; // 80
     void *stack_space; // 88
     void (*cb)(void); // 96
-    int stack_size; // 104
-#ifdef PH_FIXED_STACK_SIZE
+    int allocated_stack_size; // 104
+#ifndef PH_FIXED_STACK_SIZE
+    int used_stack_size; // 108
+#else
     int started; // 108
     void *aligned_stack_space; // 112
 #endif
diff --git a/src/ph_context_switch.S b/src/ph_context_switch.S
index 1f5bdc09e6..ccf9b80cf9 100644
--- a/src/ph_context_switch.S
+++ b/src/ph_context_switch.S
@@ -256,11 +256,11 @@ FN(ph_mcontext_resume)
     movq %r15, 80(%rdi)

     ## restore the old context
-    subq 104(%rsi), %rsp
+    subq 108(%rsi), %rsp

     movq %rsp, %rdi
     movq %rsi, %rbx
-    movq 104(%rsi), %rdx
+    movq 108(%rsi), %rdx
     movq 88(%rsi), %rsi
     callq CALL(memcpy)
     movq %rbx, %rsi
@@ -285,23 +285,28 @@ FN(ph_mcontext_interrupt)
     pushq %rbp
     movq %rsp, %rbp

-    movq 16(%rsi), %rax      ## calculate stack size (old_rsp - current_rsp)
+    movq 16(%rsi), %rax      ## calculate used stack size (old_rsp - current_rsp)
     subq %rsp, %rax
-    movq %rax, 104(%rdi)
+    movq %rax, 108(%rdi)

     pushq %rdi
     pushq %rsi

-    movq 104(%rdi), %rsi
+    cmpq 104(%rdi), %rax     ## if (used_stack_size > allocated_stack_size)
+    jg L6
+
+    movq 108(%rdi), %rsi
+    movq %rsi, 104(%rdi)     ## allocated_stack_size = used_stack_size
     movq 88(%rdi), %rdi
     callq CALL(realloc)
     movq 0(%rsp), %rsi
     movq 8(%rsp), %rdi
     movq %rax, 88(%rdi)

+L6:
     movq %rsp, %rsi
     addq $16, %rsi           ## skip past 2 pushes onto stack
-    movq 104(%rdi), %rdx
+    movq 108(%rdi), %rdx
     movq 88(%rdi), %rdi
     callq CALL(memcpy)