From bd536ba85fb1daaa81f5467ef2a0413a77446f4b Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 31 Dec 2010 13:01:45 -0800 Subject: [PATCH] Free objects by indirectly dropping fields via enclosed tydesc first. --- src/comp/middle/trans.rs | 51 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 18a3a950ff6..115ef1f24b9 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);