diff options
| author | Rafael Ávila de Espíndola <respindola@mozilla.com> | 2011-05-24 17:00:45 -0400 |
|---|---|---|
| committer | Rafael Ávila de Espíndola <respindola@mozilla.com> | 2011-05-24 17:00:45 -0400 |
| commit | 0fc91b6ecc975bf508ec631a9fe3ea19e8df4579 (patch) | |
| tree | 81be13418125f2b093da0a6554ed1ab1364bcb1c /src/rt | |
| parent | 2e8afc7b471e7a455d27e02079d7950d41a4c020 (diff) | |
There is only one activate function now.
Diffstat (limited to 'src/rt')
| -rw-r--r-- | src/rt/activate_glue.s | 89 | ||||
| -rw-r--r-- | src/rt/rust_crate.cpp | 5 | ||||
| -rw-r--r-- | src/rt/rust_dom.cpp | 6 | ||||
| -rw-r--r-- | src/rt/rust_internal.h | 1 |
4 files changed, 93 insertions, 8 deletions
diff --git a/src/rt/activate_glue.s b/src/rt/activate_glue.s new file mode 100644 index 00000000000..5b55f568880 --- /dev/null +++ b/src/rt/activate_glue.s @@ -0,0 +1,89 @@ +/* + * This is a bit of glue-code. + * + * - save regs on C stack + * - save sp to task.runtime_sp (runtime_sp is thus always aligned) + * - load saved task sp (switch stack) + * - restore saved task regs + * - return to saved task pc + * + * Our incoming stack looks like this: + * + * *esp+4 = [arg1 ] = task ptr + * *esp = [retpc ] + */ + + .globl new_rust_activate_glue + .balign 4 +new_rust_activate_glue: + movl 4(%esp), %ecx # ecx = rust_task + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + movl %esp, 12(%ecx) + movl 16(%ecx), %esp + + /* + * There are two paths we can arrive at this code from: + * + * + * 1. We are activating a task for the first time. When we switch + * into the task stack and 'ret' to its first instruction, we'll + * start doing whatever the first instruction says. Probably + * saving registers and starting to establish a frame. Harmless + * stuff, doesn't look at task->rust_sp again except when it + * clobbers it during a later native call. + * + * + * 2. We are resuming a task that was descheduled by the yield glue + * below. When we switch into the task stack and 'ret', we'll be + * ret'ing to a very particular instruction: + * + * "esp <- task->rust_sp" + * + * this is the first instruction we 'ret' to after this glue, + * because it is the first instruction following *any* native + * call, and the task we are activating was descheduled + * mid-native-call. + * + * Unfortunately for us, we have already restored esp from + * task->rust_sp and are about to eat the 5 words off the top of + * it. + * + * + * | ... | <-- where esp will be once we restore + ret, below, + * | retpc | and where we'd *like* task->rust_sp to wind up. + * | ebp | + * | edi | + * | esi | + * | ebx | <-- current task->rust_sp == current esp + * + * + * This is a problem. If we return to "esp <- task->rust_sp" it + * will push esp back down by 5 words. This manifests as a rust + * stack that grows by 5 words on each yield/reactivate. Not + * good. + * + * So what we do here is just adjust task->rust_sp up 5 words as + * well, to mirror the movement in esp we're about to + * perform. That way the "esp <- task->rust_sp" we 'ret' to below + * will be a no-op. Esp won't move, and the task's stack won't + * grow. + */ + addl $20, 16(%ecx) + + /* + * In most cases, the function we're returning to (activating) + * will have saved any caller-saves before it yielded via native call, + * so no work to do here. With one exception: when we're initially + * activating, the task needs to be in the fastcall 2nd parameter + * expected by the rust main function. That's edx. + */ + mov %ecx, %edx + + popl %ebx + popl %esi + popl %edi + popl %ebp + ret diff --git a/src/rt/rust_crate.cpp b/src/rt/rust_crate.cpp index 6f1889ffc02..410f2bd0be9 100644 --- a/src/rt/rust_crate.cpp +++ b/src/rt/rust_crate.cpp @@ -11,11 +11,6 @@ rust_crate::get_relocation_diff() const { return ((uintptr_t)this - self_addr); } -activate_glue_ty -rust_crate::get_activate_glue() const { - return (activate_glue_ty) ((uintptr_t)this + activate_glue_off); -} - uintptr_t rust_crate::get_unwind_glue() const { return ((uintptr_t)this + unwind_glue_off); diff --git a/src/rt/rust_dom.cpp b/src/rt/rust_dom.cpp index d5187ca7480..e3bbfe39449 100644 --- a/src/rt/rust_dom.cpp +++ b/src/rt/rust_dom.cpp @@ -48,10 +48,13 @@ rust_dom::~rust_dom() { } } +extern "C" void new_rust_activate_glue(rust_task *) + asm("new_rust_activate_glue"); + void rust_dom::activate(rust_task *task) { curr_task = task; - root_crate->get_activate_glue()(task); + new_rust_activate_glue(task); curr_task = NULL; } @@ -262,7 +265,6 @@ rust_dom::start_main_loop() { rust_timer timer(this); DLOG(this, dom, "started domain loop"); - DLOG(this, dom, "activate glue: " PTR, root_crate->get_activate_glue()); while (number_of_live_tasks() > 0) { A(this, kernel->is_deadlocked() == false, "deadlock"); diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h index 213c724e7ce..cb6dd162594 100644 --- a/src/rt/rust_internal.h +++ b/src/rt/rust_internal.h @@ -247,7 +247,6 @@ public: uintptr_t get_image_base() const; ptrdiff_t get_relocation_diff() const; - activate_glue_ty get_activate_glue() const; uintptr_t get_yield_glue() const; uintptr_t get_unwind_glue() const; uintptr_t get_gc_glue() const; |
