Skip to content

Commit 80b6056

Browse files
committed
auto merge of #9612 : alexcrichton/rust/rc-crate2, r=huonw
This patch exposes actual ownership of an `ast::Crate` structure so it's not implicitly copied and reference counted via `@`. The main purpose for this patch was to get rid of the massive spike in memory during the start of the compiler (this can be seen on isrustfastyet). The reason that this spike exists is that during `phase_2` we're creating many copies of the crate by folding. Because these are reference counted, all instances of the old crates aren't dropped until the end of the function, which is why so much memory is accumulated. This patch exposes true ownership of the crate, meaning that it will be destroyed ASAP when requested. There are no code changes except for dealing with actual ownership of the crate. The large spike is then avoided: http://i.imgur.com/IO3NENy.png This shouldn't help our overall memory usage (that still is the highest at the end), but if we ever manage to bring that down it should help us not have a 1GB spike at the beginning of compilation. (This was to un-stuck bors (hopefully).)
2 parents 0fd8cb0 + 7b18976 commit 80b6056

File tree

21 files changed

+179
-228
lines changed

21 files changed

+179
-228
lines changed

src/librustc/driver/driver.rs

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ pub enum input {
130130
}
131131

132132
pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &input)
133-
-> @ast::Crate {
134-
time(sess.time_passes(), ~"parsing", || {
133+
-> ast::Crate {
134+
time(sess.time_passes(), ~"parsing", (), |_| {
135135
match *input {
136136
file_input(ref file) => {
137137
parse::parse_crate_from_file(&(*file), cfg.clone(), sess.parse_sess)
@@ -153,11 +153,11 @@ pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &input)
153153
/// standard library and prelude.
154154
pub fn phase_2_configure_and_expand(sess: Session,
155155
cfg: ast::CrateConfig,
156-
mut crate: @ast::Crate) -> @ast::Crate {
156+
mut crate: ast::Crate) -> ast::Crate {
157157
let time_passes = sess.time_passes();
158158

159159
*sess.building_library = session::building_library(sess.opts.crate_type,
160-
crate, sess.opts.test);
160+
&crate, sess.opts.test);
161161

162162

163163
// strip before expansion to allow macros to depend on
@@ -167,29 +167,29 @@ pub fn phase_2_configure_and_expand(sess: Session,
167167
// mod bar { macro_rules! baz!(() => {{}}) }
168168
//
169169
// baz! should not use this definition unless foo is enabled.
170-
crate = time(time_passes, ~"std macros injection", ||
170+
crate = time(time_passes, ~"std macros injection", crate, |crate|
171171
syntax::ext::expand::inject_std_macros(sess.parse_sess,
172172
cfg.clone(),
173173
crate));
174174

175-
crate = time(time_passes, ~"configuration 1", ||
175+
crate = time(time_passes, ~"configuration 1", crate, |crate|
176176
front::config::strip_unconfigured_items(crate));
177177

178-
crate = time(time_passes, ~"expansion", ||
178+
crate = time(time_passes, ~"expansion", crate, |crate|
179179
syntax::ext::expand::expand_crate(sess.parse_sess, cfg.clone(),
180180
crate));
181181

182182
// strip again, in case expansion added anything with a #[cfg].
183-
crate = time(time_passes, ~"configuration 2", ||
183+
crate = time(time_passes, ~"configuration 2", crate, |crate|
184184
front::config::strip_unconfigured_items(crate));
185185

186-
crate = time(time_passes, ~"maybe building test harness", ||
186+
crate = time(time_passes, ~"maybe building test harness", crate, |crate|
187187
front::test::modify_for_testing(sess, crate));
188188

189-
crate = time(time_passes, ~"std injection", ||
189+
crate = time(time_passes, ~"std injection", crate, |crate|
190190
front::std_inject::maybe_inject_libstd_ref(sess, crate));
191191

192-
crate = time(time_passes, ~"assigning node ids", ||
192+
crate = time(time_passes, ~"assigning node ids", crate, |crate|
193193
front::assign_node_ids::assign_node_ids(sess, crate));
194194

195195
return crate;
@@ -207,41 +207,41 @@ pub struct CrateAnalysis {
207207
/// miscellaneous analysis passes on the crate. Return various
208208
/// structures carrying the results of the analysis.
209209
pub fn phase_3_run_analysis_passes(sess: Session,
210-
crate: @ast::Crate) -> CrateAnalysis {
210+
crate: &ast::Crate) -> CrateAnalysis {
211211

212212
let time_passes = sess.time_passes();
213213

214-
let ast_map = time(time_passes, ~"ast indexing", ||
214+
let ast_map = time(time_passes, ~"ast indexing", (), |_|
215215
syntax::ast_map::map_crate(sess.diagnostic(), crate));
216216

217-
time(time_passes, ~"external crate/lib resolution", ||
217+
time(time_passes, ~"external crate/lib resolution", (), |_|
218218
creader::read_crates(sess.diagnostic(), crate, sess.cstore,
219219
sess.filesearch,
220220
session::sess_os_to_meta_os(sess.targ_cfg.os),
221221
sess.opts.is_static,
222222
token::get_ident_interner()));
223223

224-
let lang_items = time(time_passes, ~"language item collection", ||
224+
let lang_items = time(time_passes, ~"language item collection", (), |_|
225225
middle::lang_items::collect_language_items(crate, sess));
226226

227227
let middle::resolve::CrateMap {
228228
def_map: def_map,
229229
exp_map2: exp_map2,
230230
trait_map: trait_map
231231
} =
232-
time(time_passes, ~"resolution", ||
232+
time(time_passes, ~"resolution", (), |_|
233233
middle::resolve::resolve_crate(sess, lang_items, crate));
234234

235-
time(time_passes, ~"looking for entry point",
236-
|| middle::entry::find_entry_point(sess, crate, ast_map));
235+
time(time_passes, ~"looking for entry point", (),
236+
|_| middle::entry::find_entry_point(sess, crate, ast_map));
237237

238-
let freevars = time(time_passes, ~"freevar finding", ||
238+
let freevars = time(time_passes, ~"freevar finding", (), |_|
239239
freevars::annotate_freevars(def_map, crate));
240240

241-
let region_map = time(time_passes, ~"region resolution", ||
241+
let region_map = time(time_passes, ~"region resolution", (), |_|
242242
middle::region::resolve_crate(sess, def_map, crate));
243243

244-
let rp_set = time(time_passes, ~"region parameterization inference", ||
244+
let rp_set = time(time_passes, ~"region parameterization inference", (), |_|
245245
middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate));
246246

247247
let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
@@ -252,53 +252,53 @@ pub fn phase_3_run_analysis_passes(sess: Session,
252252
ty_cx, trait_map, crate);
253253

254254
// These next two const passes can probably be merged
255-
time(time_passes, ~"const marking", ||
255+
time(time_passes, ~"const marking", (), |_|
256256
middle::const_eval::process_crate(crate, ty_cx));
257257

258-
time(time_passes, ~"const checking", ||
258+
time(time_passes, ~"const checking", (), |_|
259259
middle::check_const::check_crate(sess, crate, ast_map, def_map,
260260
method_map, ty_cx));
261261

262262
let exported_items =
263-
time(time_passes, ~"privacy checking", ||
263+
time(time_passes, ~"privacy checking", (), |_|
264264
middle::privacy::check_crate(ty_cx, &method_map, &exp_map2, crate));
265265

266-
time(time_passes, ~"effect checking", ||
266+
time(time_passes, ~"effect checking", (), |_|
267267
middle::effect::check_crate(ty_cx, method_map, crate));
268268

269-
time(time_passes, ~"loop checking", ||
269+
time(time_passes, ~"loop checking", (), |_|
270270
middle::check_loop::check_crate(ty_cx, crate));
271271

272-
time(time_passes, ~"stack checking", ||
272+
time(time_passes, ~"stack checking", (), |_|
273273
middle::stack_check::stack_check_crate(ty_cx, crate));
274274

275275
let middle::moves::MoveMaps {moves_map, moved_variables_set,
276276
capture_map} =
277-
time(time_passes, ~"compute moves", ||
277+
time(time_passes, ~"compute moves", (), |_|
278278
middle::moves::compute_moves(ty_cx, method_map, crate));
279279

280-
time(time_passes, ~"match checking", ||
280+
time(time_passes, ~"match checking", (), |_|
281281
middle::check_match::check_crate(ty_cx, method_map,
282282
moves_map, crate));
283283

284-
time(time_passes, ~"liveness checking", ||
284+
time(time_passes, ~"liveness checking", (), |_|
285285
middle::liveness::check_crate(ty_cx, method_map,
286286
capture_map, crate));
287287

288288
let (root_map, write_guard_map) =
289-
time(time_passes, ~"borrow checking", ||
289+
time(time_passes, ~"borrow checking", (), |_|
290290
middle::borrowck::check_crate(ty_cx, method_map,
291291
moves_map, moved_variables_set,
292292
capture_map, crate));
293293

294-
time(time_passes, ~"kind checking", ||
294+
time(time_passes, ~"kind checking", (), |_|
295295
kind::check_crate(ty_cx, method_map, crate));
296296

297297
let reachable_map =
298-
time(time_passes, ~"reachability checking", ||
298+
time(time_passes, ~"reachability checking", (), |_|
299299
reachable::find_reachable(ty_cx, method_map, crate));
300300

301-
time(time_passes, ~"lint checking", ||
301+
time(time_passes, ~"lint checking", (), |_|
302302
lint::check_crate(ty_cx, crate));
303303

304304
CrateAnalysis {
@@ -325,10 +325,10 @@ pub struct CrateTranslation {
325325
/// Run the translation phase to LLVM, after which the AST and analysis can
326326
/// be discarded.
327327
pub fn phase_4_translate_to_llvm(sess: Session,
328-
crate: @ast::Crate,
328+
crate: ast::Crate,
329329
analysis: &CrateAnalysis,
330330
outputs: &OutputFilenames) -> CrateTranslation {
331-
time(sess.time_passes(), ~"translation", ||
331+
time(sess.time_passes(), ~"translation", crate, |crate|
332332
trans::base::trans_crate(sess, crate, analysis,
333333
&outputs.obj_filename))
334334
}
@@ -349,7 +349,7 @@ pub fn phase_5_run_llvm_passes(sess: Session,
349349
let output_type = link::output_type_assembly;
350350
let asm_filename = outputs.obj_filename.with_filetype("s");
351351

352-
time(sess.time_passes(), ~"LLVM passes", ||
352+
time(sess.time_passes(), ~"LLVM passes", (), |_|
353353
link::write::run_passes(sess,
354354
trans.context,
355355
trans.module,
@@ -363,7 +363,7 @@ pub fn phase_5_run_llvm_passes(sess: Session,
363363
os::remove_file(&asm_filename);
364364
}
365365
} else {
366-
time(sess.time_passes(), ~"LLVM passes", ||
366+
time(sess.time_passes(), ~"LLVM passes", (), |_|
367367
link::write::run_passes(sess,
368368
trans.context,
369369
trans.module,
@@ -377,7 +377,7 @@ pub fn phase_5_run_llvm_passes(sess: Session,
377377
pub fn phase_6_link_output(sess: Session,
378378
trans: &CrateTranslation,
379379
outputs: &OutputFilenames) {
380-
time(sess.time_passes(), ~"linking", ||
380+
time(sess.time_passes(), ~"linking", (), |_|
381381
link::link_binary(sess,
382382
&outputs.obj_filename,
383383
&outputs.out_filename,
@@ -430,7 +430,7 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input,
430430
if stop_after_phase_1(sess) { return; }
431431
phase_2_configure_and_expand(sess, cfg, crate)
432432
};
433-
let analysis = phase_3_run_analysis_passes(sess, expanded_crate);
433+
let analysis = phase_3_run_analysis_passes(sess, &expanded_crate);
434434
if stop_after_phase_3(sess) { return; }
435435
let outputs = build_output_filenames(input, outdir, output, [], sess);
436436
let trans = phase_4_translate_to_llvm(sess, expanded_crate,
@@ -535,7 +535,7 @@ pub fn pretty_print_input(sess: Session,
535535
} as @pprust::pp_ann
536536
}
537537
PpmTyped => {
538-
let analysis = phase_3_run_analysis_passes(sess, crate);
538+
let analysis = phase_3_run_analysis_passes(sess, &crate);
539539
@TypedAnnotation {
540540
analysis: analysis
541541
} as @pprust::pp_ann
@@ -548,7 +548,7 @@ pub fn pretty_print_input(sess: Session,
548548
pprust::print_crate(sess.codemap,
549549
token::get_ident_interner(),
550550
sess.span_diagnostic,
551-
crate,
551+
&crate,
552552
source_name(input),
553553
rdr,
554554
io::stdout(),

src/librustc/front/assign_node_ids.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ impl ast_fold for NodeIdAssigner {
2424
}
2525
}
2626

27-
pub fn assign_node_ids(sess: Session, crate: @ast::Crate) -> @ast::Crate {
27+
pub fn assign_node_ids(sess: Session, crate: ast::Crate) -> ast::Crate {
2828
let fold = NodeIdAssigner {
2929
sess: sess,
3030
};
31-
@fold.fold_crate(crate)
31+
fold.fold_crate(crate)
3232
}

src/librustc/front/config.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ struct Context<'self> {
1818

1919
// Support conditional compilation by transforming the AST, stripping out
2020
// any items that do not belong in the current configuration
21-
pub fn strip_unconfigured_items(crate: @ast::Crate) -> @ast::Crate {
21+
pub fn strip_unconfigured_items(crate: ast::Crate) -> ast::Crate {
22+
let config = crate.config.clone();
2223
do strip_items(crate) |attrs| {
23-
in_cfg(crate.config, attrs)
24+
in_cfg(config, attrs)
2425
}
2526
}
2627

@@ -40,13 +41,13 @@ impl<'self> fold::ast_fold for Context<'self> {
4041
}
4142
}
4243

43-
pub fn strip_items(crate: &ast::Crate,
44+
pub fn strip_items(crate: ast::Crate,
4445
in_cfg: &fn(attrs: &[ast::Attribute]) -> bool)
45-
-> @ast::Crate {
46+
-> ast::Crate {
4647
let ctxt = Context {
4748
in_cfg: in_cfg,
4849
};
49-
@ctxt.fold_crate(crate)
50+
ctxt.fold_crate(crate)
5051
}
5152

5253
fn filter_item(cx: &Context, item: @ast::item) -> Option<@ast::item> {

src/librustc/front/std_inject.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ use syntax::opt_vec;
2222

2323
static STD_VERSION: &'static str = "0.9-pre";
2424

25-
pub fn maybe_inject_libstd_ref(sess: Session, crate: @ast::Crate)
26-
-> @ast::Crate {
27-
if use_std(crate) {
25+
pub fn maybe_inject_libstd_ref(sess: Session, crate: ast::Crate)
26+
-> ast::Crate {
27+
if use_std(&crate) {
2828
inject_libstd_ref(sess, crate)
2929
} else {
3030
crate
@@ -51,7 +51,7 @@ struct StandardLibraryInjector {
5151
}
5252

5353
impl fold::ast_fold for StandardLibraryInjector {
54-
fn fold_crate(&self, crate: &ast::Crate) -> ast::Crate {
54+
fn fold_crate(&self, crate: ast::Crate) -> ast::Crate {
5555
let version = STD_VERSION.to_managed();
5656
let vi1 = ast::view_item {
5757
node: ast::view_item_extern_mod(self.sess.ident_of("std"),
@@ -77,10 +77,9 @@ impl fold::ast_fold for StandardLibraryInjector {
7777
new_module = self.fold_mod(&new_module);
7878
}
7979

80-
// FIXME #2543: Bad copy.
8180
ast::Crate {
8281
module: new_module,
83-
..(*crate).clone()
82+
..crate
8483
}
8584
}
8685

@@ -133,9 +132,9 @@ impl fold::ast_fold for StandardLibraryInjector {
133132
}
134133
}
135134

136-
fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate {
135+
fn inject_libstd_ref(sess: Session, crate: ast::Crate) -> ast::Crate {
137136
let fold = StandardLibraryInjector {
138137
sess: sess,
139138
};
140-
@fold.fold_crate(crate)
139+
fold.fold_crate(crate)
141140
}

0 commit comments

Comments
 (0)