1
Fork 0

Merge obj-drop and closure-drop code, handles freeing bound exteriors now.

This commit is contained in:
Graydon Hoare 2010-08-25 16:21:50 -07:00
parent 8e0f486ea6
commit 91d640f90f
4 changed files with 61 additions and 44 deletions

View file

@ -435,6 +435,7 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
basic.rs \ basic.rs \
basic-1.rs \ basic-1.rs \
basic-2.rs \ basic-2.rs \
bind-exterior.rs \
bind-obj-ctor.rs \ bind-obj-ctor.rs \
bind-thunk.rs \ bind-thunk.rs \
bind-trivial.rs \ bind-trivial.rs \

View file

@ -1918,19 +1918,24 @@ let rec closure_box_rty
let rc = word_rty word_bits in let rc = word_rty word_bits in
let tydesc = sp (tydesc_rty word_bits) in let tydesc = sp (tydesc_rty word_bits) in
let targ = fn_rty word_bits in let targ = fn_rty true word_bits in
let bound_args = r (Array.map (slot_referent_type word_bits) bs) in let bound_args = r (Array.map (slot_referent_type word_bits) bs) in
r [| rc; r [| tydesc; targ; bound_args |] |] r [| rc; r [| tydesc; targ; bound_args |] |]
and fn_rty (word_bits:Il.bits) : Il.referent_ty = and fn_rty (opaque_box_body:bool) (word_bits:Il.bits) : Il.referent_ty =
let s t = Il.ScalarTy t in let s t = Il.ScalarTy t in
let p t = Il.AddrTy t in let p t = Il.AddrTy t in
let sp t = s (p t) in let sp t = s (p t) in
let r rtys = Il.StructTy rtys in let r rtys = Il.StructTy rtys in
let word = word_rty word_bits in let word = word_rty word_bits in
let box_ptr = sp (Il.StructTy [| word; Il.OpaqueTy |]) in let box =
if opaque_box_body
then r [| word; Il.OpaqueTy |]
else closure_box_rty word_bits [||]
in
let box_ptr = sp box in
let code_ptr = sp Il.CodeTy in let code_ptr = sp Il.CodeTy in
r [| code_ptr; box_ptr |] r [| code_ptr; box_ptr |]
@ -1985,7 +1990,7 @@ and referent_type (word_bits:Il.bits) (t:Ast.ty) : Il.referent_ty =
| Ast.TY_tup tt -> tup tt | Ast.TY_tup tt -> tup tt
| Ast.TY_rec tr -> tup (Array.map snd tr) | Ast.TY_rec tr -> tup (Array.map snd tr)
| Ast.TY_fn _ -> fn_rty word_bits | Ast.TY_fn _ -> fn_rty false word_bits
| Ast.TY_obj _ -> obj_rty word_bits | Ast.TY_obj _ -> obj_rty word_bits
| Ast.TY_tag ttag -> tag ttag | Ast.TY_tag ttag -> tag ttag

View file

@ -2604,56 +2604,59 @@ let trans_visitor
match ty with match ty with
Ast.TY_fn _ -> Ast.TY_fn _
note_drop_step ty "drop_ty: fn path";
let box = get_element_ptr cell Abi.fn_field_box in
let null_jmp = null_check box in
(* Drop non-null bindings. *)
(* FIXME (issue #58): this is completely wrong, Closures need to
* carry tydescs like objs. For now this only works by accident,
* and will leak closures with box substructure.
*)
drop_ty ty_params box (Ast.TY_box Ast.TY_int) curr_iso;
patch null_jmp;
note_drop_step ty "drop_ty: done fn path";
| Ast.TY_obj _ -> | Ast.TY_obj _ ->
note_drop_step ty "drop_ty: obj path"; note_drop_step ty "drop_ty: obj/fn path";
let binding = get_element_ptr cell Abi.obj_field_box in let box_ptr =
let null_jmp = null_check binding in get_element_ptr cell Abi.binding_field_bound_data
let rc_jmp = drop_refcount_and_cmp binding in
let obj_box = deref binding in
let obj = get_element_ptr obj_box Abi.box_rc_field_body in
let tydesc = get_element_ptr obj Abi.obj_body_elt_tydesc in
let body = get_element_ptr obj Abi.obj_body_elt_fields in
let ty_params = get_tydesc_params ty_params tydesc in
let dtor =
get_element_ptr (deref tydesc) Abi.tydesc_field_obj_drop_glue
in in
let null_dtor_jmp = null_check dtor in let _ = check_box_rty box_ptr in
(* Call any dtor, if present. *) let null_jmp = null_check box_ptr in
note_drop_step ty "drop_ty: calling obj dtor"; let rc_jmp = drop_refcount_and_cmp box_ptr in
trans_call_dynamic_glue let box = deref box_ptr in
tydesc let body = get_element_ptr box Abi.box_rc_field_body in
Abi.tydesc_field_obj_drop_glue let tydesc = get_element_ptr body Abi.obj_body_elt_tydesc in
None let fields =
[| binding |] match ty with
(Some binding); Ast.TY_fn _ ->
patch null_dtor_jmp; get_element_ptr body Abi.closure_body_elt_bound_args
(* Drop the body. *) | _ ->
note_drop_step ty "drop_ty: dropping obj body"; get_element_ptr body Abi.obj_body_elt_fields
in
let ty_params = get_tydesc_params ty_params tydesc in
begin
match ty with
Ast.TY_obj _ ->
let dtor =
get_element_ptr (deref tydesc)
Abi.tydesc_field_obj_drop_glue
in
let null_dtor_jmp = null_check dtor in
(* Call any dtor, if present. *)
note_drop_step ty "drop_ty: calling obj/fn dtor";
trans_call_dynamic_glue
tydesc
Abi.tydesc_field_obj_drop_glue
None
[| box_ptr |]
(Some box_ptr);
patch null_dtor_jmp;
| _ -> ()
end;
(* Drop the fields. *)
note_drop_step ty "drop_ty: dropping obj/fn fields";
trans_call_dynamic_glue trans_call_dynamic_glue
tydesc tydesc
Abi.tydesc_field_drop_glue Abi.tydesc_field_drop_glue
None None
[| ty_params; alias body |] [| ty_params; alias fields |]
None; None;
(* FIXME: this will fail if the user has lied about the (* FIXME: this will fail if the user has lied about the
* state-ness of their obj. We need to store state-ness in the * state-ness of their obj. We need to store state-ness in the
* captured tydesc, and use that. *) * captured tydesc, and use that. *)
note_drop_step ty "drop_ty: freeing obj body"; note_drop_step ty "drop_ty: freeing obj/fn body";
trans_free binding (type_has_state ty); trans_free box_ptr (type_has_state ty);
mov binding zero; mov box_ptr zero;
patch rc_jmp; patch rc_jmp;
patch null_jmp; patch null_jmp;
note_drop_step ty "drop_ty: done obj path"; note_drop_step ty "drop_ty: done obj path";

View file

@ -0,0 +1,8 @@
fn foo(@int a, @int b) -> int {
ret a+b;
}
fn main() {
auto f1 = bind foo(@10, @12);
check(f1() == 22);
}