From 91d640f90f23a79f10cde0a4e70bd86ab8cf5378 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 25 Aug 2010 16:21:50 -0700 Subject: [PATCH] Merge obj-drop and closure-drop code, handles freeing bound exteriors now. --- src/Makefile | 1 + src/boot/me/semant.ml | 13 +++-- src/boot/me/trans.ml | 83 ++++++++++++++++-------------- src/test/run-pass/bind-exterior.rs | 8 +++ 4 files changed, 61 insertions(+), 44 deletions(-) create mode 100644 src/test/run-pass/bind-exterior.rs diff --git a/src/Makefile b/src/Makefile index 672c1d79d4f..5d7b9dc9b2f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -435,6 +435,7 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \ basic.rs \ basic-1.rs \ basic-2.rs \ + bind-exterior.rs \ bind-obj-ctor.rs \ bind-thunk.rs \ bind-trivial.rs \ diff --git a/src/boot/me/semant.ml b/src/boot/me/semant.ml index 8a7d6aa015a..be777bc68b9 100644 --- a/src/boot/me/semant.ml +++ b/src/boot/me/semant.ml @@ -1918,19 +1918,24 @@ let rec closure_box_rty let rc = word_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 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 p t = Il.AddrTy t in let sp t = s (p t) in let r rtys = Il.StructTy rtys 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 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_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_tag ttag -> tag ttag diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml index a37ed460809..f0483e6e7bc 100644 --- a/src/boot/me/trans.ml +++ b/src/boot/me/trans.ml @@ -2604,56 +2604,59 @@ let trans_visitor match ty with - 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_fn _ | Ast.TY_obj _ -> - note_drop_step ty "drop_ty: obj path"; - let binding = get_element_ptr cell Abi.obj_field_box in - let null_jmp = null_check binding in - 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 + note_drop_step ty "drop_ty: obj/fn path"; + let box_ptr = + get_element_ptr cell Abi.binding_field_bound_data in - let null_dtor_jmp = null_check dtor in - (* Call any dtor, if present. *) - note_drop_step ty "drop_ty: calling obj dtor"; - trans_call_dynamic_glue - tydesc - Abi.tydesc_field_obj_drop_glue - None - [| binding |] - (Some binding); - patch null_dtor_jmp; - (* Drop the body. *) - note_drop_step ty "drop_ty: dropping obj body"; + let _ = check_box_rty box_ptr in + let null_jmp = null_check box_ptr in + let rc_jmp = drop_refcount_and_cmp box_ptr in + let box = deref box_ptr in + let body = get_element_ptr box Abi.box_rc_field_body in + let tydesc = get_element_ptr body Abi.obj_body_elt_tydesc in + let fields = + match ty with + Ast.TY_fn _ -> + get_element_ptr body Abi.closure_body_elt_bound_args + | _ -> + 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 tydesc Abi.tydesc_field_drop_glue None - [| ty_params; alias body |] + [| ty_params; alias fields |] None; (* FIXME: this will fail if the user has lied about the * state-ness of their obj. We need to store state-ness in the * captured tydesc, and use that. *) - note_drop_step ty "drop_ty: freeing obj body"; - trans_free binding (type_has_state ty); - mov binding zero; + note_drop_step ty "drop_ty: freeing obj/fn body"; + trans_free box_ptr (type_has_state ty); + mov box_ptr zero; patch rc_jmp; patch null_jmp; note_drop_step ty "drop_ty: done obj path"; diff --git a/src/test/run-pass/bind-exterior.rs b/src/test/run-pass/bind-exterior.rs new file mode 100644 index 00000000000..c3fc2e7c361 --- /dev/null +++ b/src/test/run-pass/bind-exterior.rs @@ -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); +}