about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2010-12-10 16:13:52 -0800
committerPatrick Walton <pcwalton@mimiga.net>2010-12-10 16:14:06 -0800
commite37c032eb07680914dc5f1cae70390e6e2c15b6a (patch)
tree7d8d7f1af42c45947f4391842ed041d9f8e6bbd6
parent865c06c1f9766495dafc519c0d4b8160f0b12df8 (diff)
rustc: Move refcount incrementing out of line too
-rw-r--r--src/comp/middle/trans.rs86
1 files changed, 48 insertions, 38 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index e37d2c28b04..483ba7f382f 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -54,7 +54,7 @@ type tag_info = rec(type_handle th,
                     mutable vec[tup(ast.def_id,arity)] variants,
                     mutable uint size);
 
-type ty_info = rec(ValueRef drop_glue);
+type ty_info = rec(ValueRef take_glue, ValueRef drop_glue);
 
 state type crate_ctxt = rec(session.session sess,
                             ModuleRef llmod,
@@ -520,25 +520,6 @@ fn trans_malloc(@block_ctxt cx, @typeck.ty t) -> result {
 }
 
 
-fn incr_refcnt(@block_ctxt cx, ValueRef box_ptr) -> result {
-    auto rc_ptr = cx.build.GEP(box_ptr, vec(C_int(0),
-                                            C_int(abi.box_rc_field_refcnt)));
-    auto rc = cx.build.Load(rc_ptr);
-
-    auto rc_adj_cx = new_sub_block_ctxt(cx, "rc++");
-    auto next_cx = new_sub_block_ctxt(cx, "next");
-
-    auto const_test = cx.build.ICmp(lib.llvm.LLVMIntEQ,
-                                    C_int(abi.const_refcount as int), rc);
-    cx.build.CondBr(const_test, next_cx.llbb, rc_adj_cx.llbb);
-
-    rc = rc_adj_cx.build.Add(rc, C_int(1));
-    rc_adj_cx.build.Store(rc, rc_ptr);
-    rc_adj_cx.build.Br(next_cx.llbb);
-
-    ret res(next_cx, C_nil());
-}
-
 // Glue and referent count twiddling
 
 fn get_ty_info(@crate_ctxt cx, @typeck.ty ty) -> @ty_info {
@@ -549,10 +530,15 @@ fn get_ty_info(@crate_ctxt cx, @typeck.ty ty) -> @ty_info {
 }
 
 fn make_ty_info(@crate_ctxt cx, @typeck.ty ty) {
-    cx.types.insert(ty, @rec(drop_glue=make_drop_glue(cx, ty)));
+    auto tg = make_take_glue;
+    auto take_glue = make_generic_glue(cx, ty, "take", tg);
+    auto dg = make_drop_glue;
+    auto drop_glue = make_generic_glue(cx, ty, "drop", dg);
+    cx.types.insert(ty, @rec(take_glue=take_glue, drop_glue=drop_glue));
 }
 
-fn make_drop_glue(@crate_ctxt cx, @typeck.ty t) -> ValueRef {
+fn make_generic_glue(@crate_ctxt cx, @typeck.ty t, str name,
+                     val_and_ty_fn helper) -> ValueRef {
     auto arg_t;
     if (typeck.type_is_structural(t)) {
         arg_t = T_ptr(type_of(cx, t));
@@ -561,7 +547,7 @@ fn make_drop_glue(@crate_ctxt cx, @typeck.ty t) -> ValueRef {
     }
     auto llfnty = T_fn(vec(T_taskptr(), arg_t), T_void());
 
-    auto fn_name = cx.names.next("_rust_drop") + "." + typeck.ty_to_str(t);
+    auto fn_name = cx.names.next("_rust_" + name) + "." + typeck.ty_to_str(t);
     fn_name = sanitize(fn_name);
     auto llfn = decl_fastcall_fn(cx.llmod, fn_name, llfnty);
 
@@ -569,14 +555,47 @@ fn make_drop_glue(@crate_ctxt cx, @typeck.ty t) -> ValueRef {
     auto bcx = new_top_block_ctxt(fcx);
 
     auto llval = llvm.LLVMGetParam(llfn, 1u);
-    auto res = make_drop_glue_inner(bcx, llval, t);
 
-    res.bcx.build.RetVoid();
+    auto res = helper(bcx, llval, t);
 
+    res.bcx.build.RetVoid();
     ret llfn;
 }
 
-fn make_drop_glue_inner(@block_ctxt cx, ValueRef v, @typeck.ty t) -> result {
+fn make_take_glue(@block_ctxt cx, ValueRef v, @typeck.ty t) -> result {
+    if (typeck.type_is_boxed(t)) {
+        ret incr_refcnt_of_boxed(cx, v);
+
+    } else if (typeck.type_is_binding(t)) {
+        cx.fcx.ccx.sess.unimpl("binding type in trans.incr_all_refcnts");
+
+    } else if (typeck.type_is_structural(t)) {
+        ret iter_structural_ty(cx, v, t,
+                               bind incr_all_refcnts(_, _, _));
+    }
+    ret res(cx, C_nil());
+}
+
+fn incr_refcnt_of_boxed(@block_ctxt cx, ValueRef box_ptr) -> result {
+    auto rc_ptr = cx.build.GEP(box_ptr, vec(C_int(0),
+                                            C_int(abi.box_rc_field_refcnt)));
+    auto rc = cx.build.Load(rc_ptr);
+
+    auto rc_adj_cx = new_sub_block_ctxt(cx, "rc++");
+    auto next_cx = new_sub_block_ctxt(cx, "next");
+
+    auto const_test = cx.build.ICmp(lib.llvm.LLVMIntEQ,
+                                    C_int(abi.const_refcount as int), rc);
+    cx.build.CondBr(const_test, next_cx.llbb, rc_adj_cx.llbb);
+
+    rc = rc_adj_cx.build.Add(rc, C_int(1));
+    rc_adj_cx.build.Store(rc, rc_ptr);
+    rc_adj_cx.build.Br(next_cx.llbb);
+
+    ret res(next_cx, C_nil());
+}
+
+fn make_drop_glue(@block_ctxt cx, ValueRef v, @typeck.ty t) -> result {
     alt (t.struct) {
         case (typeck.ty_str) {
             ret decr_refcnt_and_if_zero(cx, v,
@@ -870,17 +889,8 @@ fn iter_sequence(@block_ctxt cx,
 fn incr_all_refcnts(@block_ctxt cx,
                     ValueRef v,
                     @typeck.ty t) -> result {
-
-    if (typeck.type_is_boxed(t)) {
-        ret incr_refcnt(cx, v);
-
-    } else if (typeck.type_is_binding(t)) {
-        cx.fcx.ccx.sess.unimpl("binding type in trans.incr_all_refcnts");
-
-    } else if (typeck.type_is_structural(t)) {
-        ret iter_structural_ty(cx, v, t,
-                               bind incr_all_refcnts(_, _, _));
-    }
+    cx.build.FastCall(get_ty_info(cx.fcx.ccx, t).take_glue,
+                      vec(cx.fcx.lltaskptr, v));
     ret res(cx, C_nil());
 }
 
@@ -936,7 +946,7 @@ fn copy_ty(@block_ctxt cx,
         cx.fcx.ccx.sess.unimpl("binding type in trans.copy_ty");
 
     } else if (typeck.type_is_boxed(t)) {
-        auto r = incr_refcnt(cx, src);
+        auto r = incr_all_refcnts(cx, src, t);
         if (! is_init) {
             r = drop_ty(r.bcx, r.bcx.build.Load(dst), t);
         }