Skip to content

Commit 1351117

Browse files
committed
avoid rooting @ptrs that live in immutable, stable memory
1 parent a628f7f commit 1351117

File tree

1 file changed

+50
-30
lines changed

1 file changed

+50
-30
lines changed

src/rustc/middle/borrowck/preserve.rs

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@ impl public_methods for borrowck_ctxt {
1616
self.preserve(cmt, opt_scope_id)
1717
}
1818
cat_local(_) {
19-
// This should never happen. Local variables are always lendable,
20-
// so either `loan()` should be called or there must be some
21-
// intermediate @ or &---they are not lendable but do not recurse.
22-
self.tcx.sess.span_bug(
23-
cmt.span,
24-
"preserve() called with local");
19+
// Normally, local variables are lendable, and so this
20+
// case should never trigged. However, if we are
21+
// preserving an expression like a.b where the field `b`
22+
// has @ type, then it will recurse to ensure that the `a`
23+
// is stable to try and avoid rooting the value `a.b`. In
24+
// this case, opt_scope_id will be none.
25+
if opt_scope_id.is_some() {
26+
self.tcx.sess.span_bug(
27+
cmt.span,
28+
"preserve() called with local and non-none opt_scope_id");
29+
}
30+
ok(())
2531
}
2632
cat_arg(_) {
2733
// This can happen as not all args are lendable (e.g., &&
@@ -37,11 +43,11 @@ impl public_methods for borrowck_ctxt {
3743
// type never changes.
3844
self.preserve(cmt_base, opt_scope_id)
3945
}
40-
cat_comp(cmt1, comp_variant) {
41-
self.require_imm(cmt, cmt1, opt_scope_id, err_mut_variant)
46+
cat_comp(cmt_base, comp_variant) {
47+
self.require_imm(cmt, cmt_base, opt_scope_id, err_mut_variant)
4248
}
43-
cat_deref(cmt1, _, uniq_ptr) {
44-
self.require_imm(cmt, cmt1, opt_scope_id, err_mut_uniq)
49+
cat_deref(cmt_base, _, uniq_ptr) {
50+
self.require_imm(cmt, cmt_base, opt_scope_id, err_mut_uniq)
4551
}
4652
cat_deref(_, _, region_ptr) {
4753
// References are always "stable" by induction (when the
@@ -54,23 +60,18 @@ impl public_methods for borrowck_ctxt {
5460
ok(())
5561
}
5662
cat_deref(base, derefs, gc_ptr) {
57-
// GC'd pointers of type @MT: always stable because we can
58-
// inc the ref count or keep a GC root as necessary. We
59-
// need to insert this id into the root_map, however.
60-
alt opt_scope_id {
61-
some(scope_id) {
62-
#debug["Inserting root map entry for %s: \
63-
node %d:%u -> scope %d",
64-
self.cmt_to_repr(cmt), base.id,
65-
derefs, scope_id];
66-
67-
let rk = {id: base.id, derefs: derefs};
68-
self.root_map.insert(rk, scope_id);
69-
ok(())
70-
}
71-
none {
72-
err({cmt:cmt, code:err_preserve_gc})
73-
}
63+
// GC'd pointers of type @MT: if this pointer lives in
64+
// immutable, stable memory, then everything is fine. But
65+
// otherwise we have no guarantee the pointer will stay
66+
// live, so we must root the pointer (i.e., inc the ref
67+
// count) for the duration of the loan.
68+
if base.mutbl == m_imm {
69+
alt self.preserve(base, none) {
70+
ok(()) {ok(())}
71+
err(_) {self.attempt_root(cmt, opt_scope_id, base, derefs)}
72+
}
73+
} else {
74+
self.attempt_root(cmt, opt_scope_id, base, derefs)
7475
}
7576
}
7677
cat_discr(base, alt_id) {
@@ -138,14 +139,33 @@ impl public_methods for borrowck_ctxt {
138139

139140
impl private_methods for borrowck_ctxt {
140141
fn require_imm(cmt: cmt,
141-
cmt1: cmt,
142+
cmt_base: cmt,
142143
opt_scope_id: option<ast::node_id>,
143144
code: bckerr_code) -> bckres<()> {
144145
// Variant contents and unique pointers: must be immutably
145146
// rooted to a preserved address.
146-
alt cmt1.mutbl {
147+
alt cmt_base.mutbl {
147148
m_mutbl | m_const { err({cmt:cmt, code:code}) }
148-
m_imm { self.preserve(cmt1, opt_scope_id) }
149+
m_imm { self.preserve(cmt_base, opt_scope_id) }
150+
}
151+
}
152+
153+
fn attempt_root(cmt: cmt, opt_scope_id: option<ast::node_id>,
154+
base: cmt, derefs: uint) -> bckres<()> {
155+
alt opt_scope_id {
156+
some(scope_id) {
157+
#debug["Inserting root map entry for %s: \
158+
node %d:%u -> scope %d",
159+
self.cmt_to_repr(cmt), base.id,
160+
derefs, scope_id];
161+
162+
let rk = {id: base.id, derefs: derefs};
163+
self.root_map.insert(rk, scope_id);
164+
ok(())
165+
}
166+
none {
167+
err({cmt:cmt, code:err_preserve_gc})
168+
}
149169
}
150170
}
151171
}

0 commit comments

Comments
 (0)