From 0fc91b6ecc975bf508ec631a9fe3ea19e8df4579 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?=
 <respindola@mozilla.com>
Date: Tue, 24 May 2011 17:00:45 -0400
Subject: [PATCH] There is only one activate function now.

---
 mk/rt.mk                 |  8 +++-
 src/comp/back/abi.rs     |  4 --
 src/comp/back/x86.rs     | 94 +---------------------------------------
 src/comp/middle/trans.rs | 11 ++---
 src/rt/activate_glue.s   | 89 +++++++++++++++++++++++++++++++++++++
 src/rt/rust_crate.cpp    |  5 ---
 src/rt/rust_dom.cpp      |  6 ++-
 src/rt/rust_internal.h   |  1 -
 8 files changed, 105 insertions(+), 113 deletions(-)
 create mode 100644 src/rt/activate_glue.s

diff --git a/mk/rt.mk b/mk/rt.mk
index f65fa99ee9d..d858fec0976 100644
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -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 $@ $<
diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs
index 54f800c1667..b508309e1a2 100644
--- a/src/comp/back/abi.rs
+++ b/src/comp/back/abi.rs
@@ -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";
 }
diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs
index 839851c4968..7d32a21caa3 100644
--- a/src/comp/back/x86.rs
+++ b/src/comp/back/x86.rs
@@ -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)
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index b29af974fee..880187df458 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -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,
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;