Permalink
Browse files

Restructure how fiber stacks are allocated

  • Loading branch information...
evanphx committed Jan 7, 2012
1 parent 73ff4b6 commit e38045b65a3801402b468fe32c13a10305c1f1a7
Showing with 355 additions and 113 deletions.
  1. +26 −78 vm/builtin/fiber.cpp
  2. +7 −30 vm/builtin/fiber.hpp
  3. +48 −0 vm/fiber_data.cpp
  4. +108 −0 vm/fiber_data.hpp
  5. +76 −0 vm/fiber_stack.cpp
  6. +70 −0 vm/fiber_stack.hpp
  7. +12 −4 vm/gc/gc.cpp
  8. +1 −1 vm/gc/gc.hpp
  9. +7 −0 vm/vm.hpp
View
@@ -20,20 +20,11 @@
#include "on_stack.hpp"
-#ifdef FIBER_NATIVE
+namespace rubinius {
-#if defined(FIBER_ASM_X8664)
+#ifdef FIBER_ENABLED
-struct fiber_context_t {
- void* rip;
- void* rsp;
- void* rbp;
- void* rbx;
- void* r12;
- void* r13;
- void* r14;
- void* r15;
-};
+#if defined(FIBER_ASM_X8664)
static void fiber_wrap_main(void) {
__asm__ __volatile__ ("\tmovq %r13, %rdi\n\tjmpq *%r12\n");
@@ -76,13 +67,6 @@ static void fiber_makectx(fiber_context_t* ctx, void* func, void** stack_bottom,
#elif defined(FIBER_ASM_X8632)
-struct fiber_context_t {
- void* eip;
- void* esp;
- void* ebp;
- void* ebx;
-};
-
static inline void fiber_switch(fiber_context_t* from, fiber_context_t* to) {
__asm__ __volatile__ (
"call 1f\n" "1:\tpopl %%eax\n\t" "addl $(2f-1b),%%eax\n\t"
@@ -111,15 +95,9 @@ static void fiber_makectx(fiber_context_t* ctx, void* func, void** stack_bottom,
}
#endif
-#else // FIBER_NATIVE
-
-#ifndef FIBER_ENABLED
-struct fiber_context_t {
- int dummy;
-}
#endif
-#endif
+}
namespace rubinius {
@@ -149,14 +127,8 @@ namespace rubinius {
fib->root_ = true;
fib->status_ = Fiber::eRunning;
fib->vm_ = state->vm();
- fib->stack_size_ = state->vm()->stack_size();
- fib->stack_ = state->vm()->stack_start();
-#ifdef FIBER_NATIVE
- fib->context_ = new fiber_context_t;
-#else
- fib->context_ = new ucontext_t;
-#endif
+ fib->data_ = new FiberData;
state->memory()->needs_finalization(fib, (FinalizerFunction)&Fiber::finalize);
@@ -206,17 +178,14 @@ namespace rubinius {
}
}
+ fib->data_->orphan(&state);
+
dest->run();
dest->value(&state, result);
state.vm()->set_current_fiber(dest);
-#ifdef FIBER_NATIVE
fiber_context_t dummy;
fiber_switch(&dummy, dest->ucontext());
-#else
- if(setcontext(dest->ucontext()) != 0)
- assert(0 && "fatal swapcontext() error");
-#endif
assert(0 && "fatal start_on_stack error");
#else
@@ -242,28 +211,10 @@ namespace rubinius {
fib->root_ = false;
fib->vm_ = 0;
fib->status_ = Fiber::eSleeping;
- fib->stack_size_ = stack_size;
- fib->stack_ = malloc(stack_size);
-
- state->memory()->needs_finalization(fib, (FinalizerFunction)&Fiber::finalize);
-#ifdef FIBER_NATIVE
- fib->context_ = new fiber_context_t;
- fiber_makectx(fib->ucontext(), (void*)start_on_stack, (void**)fib->stack_,
- stack_size);
-#else
- fib->context_ = new ucontext_t;
- ucontext_t* ctx = fib->ucontext();
-
- if(getcontext(ctx) != 0) assert(0 && "fatal getcontext() error");
+ fib->data_ = new FiberData;
- ctx->uc_link = 0;
- ctx->uc_stack.ss_sp = (char *) fib->stack_;
- ctx->uc_stack.ss_size = stack_size;
- ctx->uc_stack.ss_flags = 0;
-
- makecontext(ctx, start_on_stack, 0);
-#endif
+ state->memory()->needs_finalization(fib, (FinalizerFunction)&Fiber::finalize);
return fib;
#else
@@ -287,17 +238,24 @@ namespace rubinius {
Fiber* cur = Fiber::current(state);
prev(state, cur);
+ if(data_->uninitialized_p()) {
+ FiberStack* stack = data_->allocate_stack(state);
+
+ data_->take_stack(state);
+
+ fiber_makectx(ucontext(), (void*)start_on_stack,
+ (void**)stack->address(),
+ stack->size());
+ } else {
+ data_->take_stack(state);
+ }
+
cur->sleep(calling_environment);
run();
state->vm()->set_current_fiber(this);
-#ifdef FIBER_NATIVE
- fiber_switch(cur->ucontext(), context_);
-#else
- if(swapcontext(cur->ucontext(), context_) != 0)
- assert(0 && "fatal swapcontext() error");
-#endif
+ fiber_switch(cur->ucontext(), ucontext());
// Back here when someone yields back to us!
// Beware here, because the GC has probably run so GC pointers on the C++ stack
@@ -345,12 +303,7 @@ namespace rubinius {
run();
state->vm()->set_current_fiber(this);
-#ifdef FIBER_NATIVE
- fiber_switch(cur->ucontext(), context_);
-#else
- if(swapcontext(cur->ucontext(), context_) != 0)
- assert(0 && "fatal swapcontext() error");
-#endif
+ fiber_switch(cur->ucontext(), ucontext());
// Back here when someone transfers back to us!
// Beware here, because the GC has probably run so GC pointers on the C++ stack
@@ -399,12 +352,7 @@ namespace rubinius {
dest_fib->run();
state->vm()->set_current_fiber(dest_fib);
-#ifdef FIBER_NATIVE
fiber_switch(cur->ucontext(), dest_fib->ucontext());
-#else
- if(swapcontext(cur->ucontext(), dest_fib->ucontext()) != 0)
- assert(0 && "fatal swapcontext() error");
-#endif
// Back here when someone yields back to us!
// Beware here, because the GC has probably run so GC pointers on the C++ stack
@@ -429,8 +377,8 @@ namespace rubinius {
void Fiber::finalize(STATE, Fiber* fib) {
#ifdef FIBER_ENABLED
- delete fib->context_;
- if(fib->stack_ && !fib->root_) free(fib->stack_);
+ delete fib->data_;
+ // if(fib->stack_ && !fib->root_) free(fib->stack_);
#endif
}
@@ -441,7 +389,7 @@ namespace rubinius {
Fiber* fib = (Fiber*)obj;
if(CallFrame* cf = fib->call_frame()) {
- mark.gc->walk_call_frame(cf);
+ mark.gc->walk_call_frame(cf, fib->data_->data_offset());
}
}
}
View
@@ -1,36 +1,15 @@
#ifndef RBX_BUILTIN_FIBER
#define RBX_BUILTIN_FIBER
-#include "vm/config.h"
-
-#if defined(IS_X86)
-#define FIBER_ENABLED
-#define FIBER_NATIVE
-#define FIBER_ASM_X8632
-struct fiber_context_t;
-
-#elif defined(IS_X8664)
-#define FIBER_ENABLED
-#define FIBER_NATIVE
-#define FIBER_ASM_X8664
-struct fiber_context_t;
-
-#elif defined(HAS_UCONTEXT)
-#define FIBER_ENABLED
-#include <ucontext.h>
-typedef ucontext_t fiber_context_t;
-
-#else
-struct fiber_context_t;
-#endif
-
-
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
+#include "prelude.hpp"
#include "builtin/object.hpp"
+#include "fiber_data.hpp"
+
namespace rubinius {
class Fiber : public Object {
public:
@@ -50,10 +29,8 @@ namespace rubinius {
VM* vm_;
bool root_;
- void* stack_;
- int stack_size_;
- fiber_context_t* context_;
+ FiberData* data_;
public:
attr_accessor(starter, Object);
attr_accessor(value, Array);
@@ -75,19 +52,19 @@ namespace rubinius {
}
fiber_context_t* ucontext() {
- return context_;
+ return data_->machine();
}
VM* vm() {
return vm_;
}
void* stack() {
- return stack_;
+ return data_->stack_address();
}
int stack_size() {
- return stack_size_;
+ return data_->stack_size();
}
public:
View
@@ -0,0 +1,48 @@
+#include "vm/vm.hpp"
+#include "vm/fiber_data.hpp"
+
+namespace rubinius {
+ void FiberData::take_stack(STATE) {
+ assert(stack_);
+
+ assert(status_ != eDead);
+
+ if(status_ == eOnStack || status_ == eRunning) return;
+
+ if(stack_->shared_p()) stack_->flush(state);
+ stack_->set_user(this);
+
+ if(status_ == eOnHeap) {
+ memcpy(stack_bottom(), heap_, heap_size_);
+ }
+
+ status_ = eOnStack;
+ }
+
+ void FiberData::copy_to_heap(STATE) {
+ heap_size_ = (uintptr_t)stack_->top_address() - (uintptr_t)stack_bottom();
+ if(heap_capacity_ < heap_size_) {
+ // Round to nearest 1k
+ heap_capacity_ = (heap_size_ + 1023) & ~1023;
+
+ if(heap_) free(heap_);
+ heap_ = malloc(heap_capacity_);
+ }
+
+ memcpy(heap_, stack_bottom(), heap_size_);
+
+ status_ = eOnHeap;
+ }
+
+ FiberStack* FiberData::allocate_stack(STATE) {
+ assert(!stack_);
+ stack_ = state->vm()->allocate_fiber_stack();
+ return stack_;
+ }
+
+ void FiberData::orphan(STATE) {
+ status_ = eDead;
+ stack_->orphan(state, this);
+ stack_ = 0;
+ }
+}
Oops, something went wrong.

0 comments on commit e38045b

Please sign in to comment.