Skip to content

Commit 7796d51

Browse files
committed
librustc: Don't use garbage-collected closures to store cleanups.
1 parent 16e87cb commit 7796d51

File tree

3 files changed

+121
-24
lines changed

3 files changed

+121
-24
lines changed

src/librustc/middle/trans/_match.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,7 @@ trait CustomFailureHandler {
11911191

11921192
struct DynamicFailureHandler {
11931193
bcx: @mut Block,
1194-
sp: span,
1194+
sp: Span,
11951195
msg: @str,
11961196
finished: @mut Option<BasicBlockRef>,
11971197
}

src/librustc/middle/trans/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1320,7 +1320,7 @@ pub fn trans_block_cleanups_(bcx: @mut Block,
13201320
// Some types don't need to be cleaned up during
13211321
// landing pads because they can be freed en mass later
13221322
if cleanup_type == normal_exit_and_unwind || !is_lpad {
1323-
bcx = cfn(bcx);
1323+
bcx = cfn.clean(bcx);
13241324
}
13251325
}
13261326
}

src/librustc/middle/trans/common.rs

Lines changed: 119 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,85 @@ pub enum cleantype {
294294
normal_exit_and_unwind
295295
}
296296

297+
// Cleanup functions
298+
299+
/// A cleanup function: a built-in destructor.
300+
pub trait CleanupFunction {
301+
fn clean(&self, block: @mut Block) -> @mut Block;
302+
}
303+
304+
/// A cleanup function that calls the "drop glue" (destructor function) on
305+
/// a typed value.
306+
pub struct TypeDroppingCleanupFunction {
307+
val: ValueRef,
308+
t: ty::t,
309+
}
310+
311+
impl CleanupFunction for TypeDroppingCleanupFunction {
312+
fn clean(&self, block: @mut Block) -> @mut Block {
313+
glue::drop_ty(block, self.val, self.t)
314+
}
315+
}
316+
317+
/// A cleanup function that calls the "drop glue" (destructor function) on
318+
/// an immediate typed value.
319+
pub struct ImmediateTypeDroppingCleanupFunction {
320+
val: ValueRef,
321+
t: ty::t,
322+
}
323+
324+
impl CleanupFunction for ImmediateTypeDroppingCleanupFunction {
325+
fn clean(&self, block: @mut Block) -> @mut Block {
326+
glue::drop_ty_immediate(block, self.val, self.t)
327+
}
328+
}
329+
330+
/// A cleanup function that releases a write guard, returning a value to
331+
/// mutable status.
332+
pub struct WriteGuardReleasingCleanupFunction {
333+
root_key: root_map_key,
334+
frozen_val_ref: ValueRef,
335+
bits_val_ref: ValueRef,
336+
filename_val: ValueRef,
337+
line_val: ValueRef,
338+
}
339+
340+
impl CleanupFunction for WriteGuardReleasingCleanupFunction {
341+
fn clean(&self, bcx: @mut Block) -> @mut Block {
342+
write_guard::return_to_mut(bcx,
343+
self.root_key,
344+
self.frozen_val_ref,
345+
self.bits_val_ref,
346+
self.filename_val,
347+
self.line_val)
348+
}
349+
}
350+
351+
/// A cleanup function that frees some memory in the garbage-collected heap.
352+
pub struct GCHeapFreeingCleanupFunction {
353+
ptr: ValueRef,
354+
}
355+
356+
impl CleanupFunction for GCHeapFreeingCleanupFunction {
357+
fn clean(&self, bcx: @mut Block) -> @mut Block {
358+
glue::trans_free(bcx, self.ptr)
359+
}
360+
}
361+
362+
/// A cleanup function that frees some memory in the exchange heap.
363+
pub struct ExchangeHeapFreeingCleanupFunction {
364+
ptr: ValueRef,
365+
}
366+
367+
impl CleanupFunction for ExchangeHeapFreeingCleanupFunction {
368+
fn clean(&self, bcx: @mut Block) -> @mut Block {
369+
glue::trans_exchange_free(bcx, self.ptr)
370+
}
371+
}
372+
297373
pub enum cleanup {
298-
clean(@fn(@mut Block) -> @mut Block, cleantype),
299-
clean_temp(ValueRef, @fn(@mut Block) -> @mut Block, cleantype),
374+
clean(@CleanupFunction, cleantype),
375+
clean_temp(ValueRef, @CleanupFunction, cleantype),
300376
}
301377

302378
// 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 {
337413
}
338414

339415
pub fn add_clean(bcx: @mut Block, val: ValueRef, t: ty::t) {
340-
if !ty::type_needs_drop(bcx.tcx(), t) { return; }
416+
if !ty::type_needs_drop(bcx.tcx(), t) {
417+
return
418+
}
341419

342420
debug!("add_clean(%s, %s, %s)", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
343421

344422
let cleanup_type = cleanup_type(bcx.tcx(), t);
345423
do in_scope_cx(bcx, None) |scope_info| {
346-
scope_info.cleanups.push(clean(|a| glue::drop_ty(a, val, t), cleanup_type));
424+
scope_info.cleanups.push(clean(@TypeDroppingCleanupFunction {
425+
val: val,
426+
t: t,
427+
} as @CleanupFunction,
428+
cleanup_type));
347429
grow_scope_clean(scope_info);
348430
}
349431
}
@@ -355,9 +437,12 @@ pub fn add_clean_temp_immediate(cx: @mut Block, val: ValueRef, ty: ty::t) {
355437
ty.repr(cx.tcx()));
356438
let cleanup_type = cleanup_type(cx.tcx(), ty);
357439
do in_scope_cx(cx, None) |scope_info| {
358-
scope_info.cleanups.push(
359-
clean_temp(val, |a| glue::drop_ty_immediate(a, val, ty),
360-
cleanup_type));
440+
scope_info.cleanups.push(clean_temp(val,
441+
@ImmediateTypeDroppingCleanupFunction {
442+
val: val,
443+
t: ty,
444+
} as @CleanupFunction,
445+
cleanup_type));
361446
grow_scope_clean(scope_info);
362447
}
363448
}
@@ -381,7 +466,12 @@ pub fn add_clean_temp_mem_in_scope_(bcx: @mut Block, scope_id: Option<ast::NodeI
381466
t.repr(bcx.tcx()));
382467
let cleanup_type = cleanup_type(bcx.tcx(), t);
383468
do in_scope_cx(bcx, scope_id) |scope_info| {
384-
scope_info.cleanups.push(clean_temp(val, |a| glue::drop_ty(a, val, t), cleanup_type));
469+
scope_info.cleanups.push(clean_temp(val,
470+
@TypeDroppingCleanupFunction {
471+
val: val,
472+
t: t,
473+
} as @CleanupFunction,
474+
cleanup_type));
385475
grow_scope_clean(scope_info);
386476
}
387477
}
@@ -405,29 +495,36 @@ pub fn add_clean_return_to_mut(bcx: @mut Block,
405495
bcx.val_to_str(frozen_val_ref),
406496
bcx.val_to_str(bits_val_ref));
407497
do in_scope_cx(bcx, Some(scope_id)) |scope_info| {
408-
scope_info.cleanups.push(
409-
clean_temp(
498+
scope_info.cleanups.push(clean_temp(
410499
frozen_val_ref,
411-
|bcx| write_guard::return_to_mut(bcx, root_key, frozen_val_ref, bits_val_ref,
412-
filename_val, line_val),
500+
@WriteGuardReleasingCleanupFunction {
501+
root_key: root_key,
502+
frozen_val_ref: frozen_val_ref,
503+
bits_val_ref: bits_val_ref,
504+
filename_val: filename_val,
505+
line_val: line_val,
506+
} as @CleanupFunction,
413507
normal_exit_only));
414508
grow_scope_clean(scope_info);
415509
}
416510
}
417511
pub fn add_clean_free(cx: @mut Block, ptr: ValueRef, heap: heap) {
418512
let free_fn = match heap {
419-
heap_managed | heap_managed_unique => {
420-
let f: @fn(@mut Block) -> @mut Block = |a| glue::trans_free(a, ptr);
421-
f
422-
}
423-
heap_exchange | heap_exchange_closure => {
424-
let f: @fn(@mut Block) -> @mut Block = |a| glue::trans_exchange_free(a, ptr);
425-
f
426-
}
513+
heap_managed | heap_managed_unique => {
514+
@GCHeapFreeingCleanupFunction {
515+
ptr: ptr,
516+
} as @CleanupFunction
517+
}
518+
heap_exchange | heap_exchange_closure => {
519+
@ExchangeHeapFreeingCleanupFunction {
520+
ptr: ptr,
521+
} as @CleanupFunction
522+
}
427523
};
428524
do in_scope_cx(cx, None) |scope_info| {
429-
scope_info.cleanups.push(clean_temp(ptr, free_fn,
430-
normal_exit_and_unwind));
525+
scope_info.cleanups.push(clean_temp(ptr,
526+
free_fn,
527+
normal_exit_and_unwind));
431528
grow_scope_clean(scope_info);
432529
}
433530
}

0 commit comments

Comments
 (0)