There is only one activate function now.

This commit is contained in:
Rafael Ávila de Espíndola 2011-05-24 17:00:45 -04:00
parent 2e8afc7b47
commit 0fc91b6ecc
8 changed files with 105 additions and 113 deletions

View File

@ -33,6 +33,8 @@ RUNTIME_CS := rt/sync/timer.cpp \
RUNTIME_LL := rt/new_exit.ll
RUNTIME_S := rt/activate_glue.s
RUNTIME_HDR := rt/globals.h \
rt/rust.h \
rt/rust_dwarf.h \
@ -65,7 +67,7 @@ RUNTIME_HDR := rt/globals.h \
RUNTIME_DEF := rt/rustrt$(CFG_DEF_SUFFIX)
RUNTIME_INCS := -I $(S)src/rt/isaac -I $(S)src/rt/uthash
RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o) $(RUNTIME_LL:.ll=.o)
RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o) $(RUNTIME_LL:.ll=.o) $(RUNTIME_S:.s=.o)
RUNTIME_LIBS := $(CFG_GCCISH_POST_LIB_FLAGS)
@ -73,6 +75,10 @@ rt/%.o: rt/%.cpp $(MKFILES)
@$(call E, compile: $@)
$(Q)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $<
rt/%.o: rt/%.s $(MKFILES)
@$(call E, compile: $@)
$(Q)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $<
rt/%.o: rt/%.ll $(MKFILES)
@$(call E, llc: $@)
$(Q)$(LLC) -filetype=obj -relocation-model=pic -march=x86 -o $@ $<

View File

@ -99,10 +99,6 @@ fn native_glue_name(int n, native_glue_type ngt) -> str {
ret prefix + util::common::istr(n);
}
fn activate_glue_name() -> str {
ret "rust_activate_glue";
}
fn yield_glue_name() -> str {
ret "rust_yield_glue";
}

View File

@ -87,92 +87,6 @@ fn store_esp_to_runtime_sp_second_arg() -> vec[str] {
}
/*
* This is a bit of glue-code. It should be emitted once per
* compilation unit.
*
* - save regs on C stack
* - align sp on a 16-byte boundary
* - 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 ]
*/
fn rust_activate_glue() -> vec[str] {
ret ["movl 4(%esp), %ecx # ecx = rust_task"]
+ save_callee_saves()
+ store_esp_to_runtime_sp_first_arg()
+ load_esp_from_rust_sp_first_arg()
/*
* 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, " + wstr(abi::task_field_rust_sp) + "(%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"]
+ restore_callee_saves()
+ ["ret"];
}
/* More glue code, this time the 'bottom half' of yielding.
*
* We arrived here because an native call decided to deschedule the
@ -306,12 +220,8 @@ fn get_module_asm() -> str {
auto glues =
[decl_glue(align, prefix,
abi::activate_glue_name(),
rust_activate_glue()),
decl_glue(align, prefix,
abi::yield_glue_name(),
rust_yield_glue())]
abi::yield_glue_name(),
rust_yield_glue())]
+ vec::init_fn[str](bind decl_native_glue(align, prefix,
abi::ngt_rust, _), (abi::n_native_glues + 1) as uint)

View File

@ -55,8 +55,7 @@ state obj namegen(mutable int i) {
type derived_tydesc_info = rec(ValueRef lltydesc, bool escapes);
type glue_fns = rec(ValueRef activate_glue,
ValueRef yield_glue,
type glue_fns = rec(ValueRef yield_glue,
vec[ValueRef] native_glues_rust,
vec[ValueRef] native_glues_pure_rust,
vec[ValueRef] native_glues_cdecl,
@ -7661,9 +7660,6 @@ fn create_crate_constant(ValueRef crate_ptr, @glue_fns glues) {
let ValueRef crate_addr = p2i(crate_ptr);
let ValueRef activate_glue_off =
llvm::LLVMConstSub(p2i(glues.activate_glue), crate_addr);
let ValueRef yield_glue_off =
llvm::LLVMConstSub(p2i(glues.yield_glue), crate_addr);
@ -7674,7 +7670,7 @@ fn create_crate_constant(ValueRef crate_ptr, @glue_fns glues) {
C_null(T_int()), // size_t debug_abbrev_sz
C_null(T_int()), // ptrdiff_t debug_info_off
C_null(T_int()), // size_t debug_info_sz
activate_glue_off, // size_t activate_glue_off
C_null(T_int()), // size_t pad
yield_glue_off, // size_t yield_glue_off
C_null(T_int()), // size_t unwind_glue_off
C_null(T_int()), // size_t gc_glue_off
@ -8030,8 +8026,7 @@ fn trans_vec_append_glue(@local_ctxt cx, &ast::span sp) {
fn make_glues(ModuleRef llmod, &type_names tn) -> @glue_fns {
ret @rec(activate_glue = decl_glue(llmod, tn, abi::activate_glue_name()),
yield_glue = decl_glue(llmod, tn, abi::yield_glue_name()),
ret @rec(yield_glue = decl_glue(llmod, tn, abi::yield_glue_name()),
native_glues_rust =
vec::init_fn[ValueRef](bind decl_native_glue(llmod, tn,

89
src/rt/activate_glue.s Normal file
View File

@ -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

View File

@ -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);

View File

@ -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");

View File

@ -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;