aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2010-12-31 13:01:45 -0800
committerGraydon Hoare <[email protected]>2010-12-31 13:01:45 -0800
commitbd536ba85fb1daaa81f5467ef2a0413a77446f4b (patch)
tree4b75847cb5014a01513c5632c0391328928857e3 /src
parentReplace arg Load with load_non_structural in obj ctor. (diff)
downloadrust-bd536ba85fb1daaa81f5467ef2a0413a77446f4b.tar.xz
rust-bd536ba85fb1daaa81f5467ef2a0413a77446f4b.zip
Free objects by indirectly dropping fields via enclosed tydesc first.
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/trans.rs51
1 files changed, 49 insertions, 2 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 18a3a950..115ef1f2 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -399,9 +399,11 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef {
mtys += T_ptr(mty);
}
let TypeRef vtbl = T_struct(mtys);
+ let TypeRef body = T_struct(vec(T_ptr(T_tydesc()),
+ T_nil()));
let TypeRef pair =
T_struct(vec(T_ptr(vtbl),
- T_ptr(T_box(T_nil()))));
+ T_ptr(T_box(body))));
auto abs_pair = llvm.LLVMResolveTypeHandle(th.llth);
llvm.LLVMRefineType(abs_pair, pair);
abs_pair = llvm.LLVMResolveTypeHandle(th.llth);
@@ -775,6 +777,50 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result {
T_int(), C_int(0));
}
+ case (ty.ty_obj(_)) {
+ fn hit_zero(@block_ctxt cx, ValueRef v) -> result {
+
+ // Call through the obj's own fields-drop glue first.
+ auto body =
+ cx.build.GEP(v,
+ vec(C_int(0),
+ C_int(abi.box_rc_field_body)));
+
+ auto fields =
+ cx.build.GEP(body,
+ vec(C_int(0),
+ C_int(abi.obj_body_elt_fields)));
+ auto llrawptr = cx.build.BitCast(fields, T_ptr(T_i8()));
+
+ auto tydescptr =
+ cx.build.GEP(body,
+ vec(C_int(0),
+ C_int(abi.obj_body_elt_tydesc)));
+ auto tydesc = cx.build.Load(tydescptr);
+ auto llfnptr =
+ cx.build.GEP(tydesc,
+ vec(C_int(0),
+ C_int(abi.tydesc_field_drop_glue_off)));
+ auto llfn = cx.build.Load(llfnptr);
+ cx.build.FastCall(llfn, vec(cx.fcx.lltaskptr, llrawptr));
+
+ // Then free the body.
+ // FIXME: switch gc/non-gc on layer of the type.
+ ret trans_non_gc_free(cx, v);
+ }
+ auto box_cell =
+ cx.build.GEP(v,
+ vec(C_int(0),
+ C_int(abi.obj_field_box)));
+
+ auto boxptr = cx.build.Load(box_cell);
+
+ ret decr_refcnt_and_if_zero(cx, boxptr,
+ bind hit_zero(_, boxptr),
+ "free obj",
+ T_int(), C_int(0));
+ }
+
case (_) {
if (ty.type_is_structural(t)) {
ret iter_structural_ty(cx, v, t,
@@ -2651,7 +2697,8 @@ impure fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid,
C_int(abi.obj_field_box)));
bcx.build.Store(vtbl, pair_vtbl);
- let TypeRef llbox_ty = T_ptr(T_box(T_nil()));
+ let TypeRef llbox_ty = T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc()),
+ T_nil()))));
if (_vec.len[ty.arg](arg_tys) == 0u) {
// Store null into pair, if no args.
bcx.build.Store(C_null(llbox_ty), pair_box);