From 7796d519f95305fca9cec9d92d361e3df0dd999c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 29 Aug 2013 17:46:33 -0700 Subject: [PATCH] librustc: Don't use garbage-collected closures to store cleanups. --- src/librustc/middle/trans/_match.rs | 2 +- src/librustc/middle/trans/base.rs | 2 +- src/librustc/middle/trans/common.rs | 141 +++++++++++++++++++++++----- 3 files changed, 121 insertions(+), 24 deletions(-) diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 464bcfee48e..0de01bced1f 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -1191,7 +1191,7 @@ trait CustomFailureHandler { struct DynamicFailureHandler { bcx: @mut Block, - sp: span, + sp: Span, msg: @str, finished: @mut Option, } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 441cc1bfae2..67aee43bc46 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1320,7 +1320,7 @@ pub fn trans_block_cleanups_(bcx: @mut Block, // Some types don't need to be cleaned up during // landing pads because they can be freed en mass later if cleanup_type == normal_exit_and_unwind || !is_lpad { - bcx = cfn(bcx); + bcx = cfn.clean(bcx); } } } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index b659a93f5f0..377144b38e7 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -294,9 +294,85 @@ pub enum cleantype { normal_exit_and_unwind } +// Cleanup functions + +/// A cleanup function: a built-in destructor. +pub trait CleanupFunction { + fn clean(&self, block: @mut Block) -> @mut Block; +} + +/// A cleanup function that calls the "drop glue" (destructor function) on +/// a typed value. +pub struct TypeDroppingCleanupFunction { + val: ValueRef, + t: ty::t, +} + +impl CleanupFunction for TypeDroppingCleanupFunction { + fn clean(&self, block: @mut Block) -> @mut Block { + glue::drop_ty(block, self.val, self.t) + } +} + +/// A cleanup function that calls the "drop glue" (destructor function) on +/// an immediate typed value. +pub struct ImmediateTypeDroppingCleanupFunction { + val: ValueRef, + t: ty::t, +} + +impl CleanupFunction for ImmediateTypeDroppingCleanupFunction { + fn clean(&self, block: @mut Block) -> @mut Block { + glue::drop_ty_immediate(block, self.val, self.t) + } +} + +/// A cleanup function that releases a write guard, returning a value to +/// mutable status. +pub struct WriteGuardReleasingCleanupFunction { + root_key: root_map_key, + frozen_val_ref: ValueRef, + bits_val_ref: ValueRef, + filename_val: ValueRef, + line_val: ValueRef, +} + +impl CleanupFunction for WriteGuardReleasingCleanupFunction { + fn clean(&self, bcx: @mut Block) -> @mut Block { + write_guard::return_to_mut(bcx, + self.root_key, + self.frozen_val_ref, + self.bits_val_ref, + self.filename_val, + self.line_val) + } +} + +/// A cleanup function that frees some memory in the garbage-collected heap. +pub struct GCHeapFreeingCleanupFunction { + ptr: ValueRef, +} + +impl CleanupFunction for GCHeapFreeingCleanupFunction { + fn clean(&self, bcx: @mut Block) -> @mut Block { + glue::trans_free(bcx, self.ptr) + } +} + +/// A cleanup function that frees some memory in the exchange heap. +pub struct ExchangeHeapFreeingCleanupFunction { + ptr: ValueRef, +} + +impl CleanupFunction for ExchangeHeapFreeingCleanupFunction { + fn clean(&self, bcx: @mut Block) -> @mut Block { + glue::trans_exchange_free(bcx, self.ptr) + } +} + pub enum cleanup { - clean(@fn(@mut Block) -> @mut Block, cleantype), - clean_temp(ValueRef, @fn(@mut Block) -> @mut Block, cleantype), + clean(@CleanupFunction, cleantype), + clean_temp(ValueRef, @CleanupFunction, cleantype), } // Can't use deriving(Clone) because of the managed closure. @@ -337,13 +413,19 @@ pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype { } pub fn add_clean(bcx: @mut Block, val: ValueRef, t: ty::t) { - if !ty::type_needs_drop(bcx.tcx(), t) { return; } + if !ty::type_needs_drop(bcx.tcx(), t) { + return + } debug!("add_clean(%s, %s, %s)", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx())); let cleanup_type = cleanup_type(bcx.tcx(), t); do in_scope_cx(bcx, None) |scope_info| { - scope_info.cleanups.push(clean(|a| glue::drop_ty(a, val, t), cleanup_type)); + scope_info.cleanups.push(clean(@TypeDroppingCleanupFunction { + val: val, + t: t, + } as @CleanupFunction, + cleanup_type)); grow_scope_clean(scope_info); } } @@ -355,9 +437,12 @@ pub fn add_clean_temp_immediate(cx: @mut Block, val: ValueRef, ty: ty::t) { ty.repr(cx.tcx())); let cleanup_type = cleanup_type(cx.tcx(), ty); do in_scope_cx(cx, None) |scope_info| { - scope_info.cleanups.push( - clean_temp(val, |a| glue::drop_ty_immediate(a, val, ty), - cleanup_type)); + scope_info.cleanups.push(clean_temp(val, + @ImmediateTypeDroppingCleanupFunction { + val: val, + t: ty, + } as @CleanupFunction, + cleanup_type)); grow_scope_clean(scope_info); } } @@ -381,7 +466,12 @@ pub fn add_clean_temp_mem_in_scope_(bcx: @mut Block, scope_id: Option { - let f: @fn(@mut Block) -> @mut Block = |a| glue::trans_free(a, ptr); - f - } - heap_exchange | heap_exchange_closure => { - let f: @fn(@mut Block) -> @mut Block = |a| glue::trans_exchange_free(a, ptr); - f - } + heap_managed | heap_managed_unique => { + @GCHeapFreeingCleanupFunction { + ptr: ptr, + } as @CleanupFunction + } + heap_exchange | heap_exchange_closure => { + @ExchangeHeapFreeingCleanupFunction { + ptr: ptr, + } as @CleanupFunction + } }; do in_scope_cx(cx, None) |scope_info| { - scope_info.cleanups.push(clean_temp(ptr, free_fn, - normal_exit_and_unwind)); + scope_info.cleanups.push(clean_temp(ptr, + free_fn, + normal_exit_and_unwind)); grow_scope_clean(scope_info); } }