Skip to content

Commit 1d7f292

Browse files
Utilize interning to allow Copy/Clone steps
1 parent d583d31 commit 1d7f292

File tree

17 files changed

+1012
-706
lines changed

17 files changed

+1012
-706
lines changed

src/Cargo.lock

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/bootstrap/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@ serde = "1.0.8"
4040
serde_derive = "1.0.8"
4141
serde_json = "1.0.2"
4242
toml = "0.4"
43+
lazy_static = "0.2"

src/bootstrap/builder.rs

Lines changed: 48 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,21 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use serde::{Serialize, Deserialize};
12-
11+
use std::fmt::Debug;
12+
use std::hash::Hash;
1313
use std::cell::RefCell;
1414
use std::path::{Path, PathBuf};
1515
use std::process::Command;
1616
use std::fs;
1717
use std::ops::Deref;
18+
use std::any::{TypeId, Any};
1819

1920
use compile;
2021
use install;
2122
use dist;
2223
use util::{exe, libdir, add_lib_path};
2324
use {Build, Mode};
24-
use cache::{Cache, Key};
25+
use cache::{INTERNER, Interned, Cache};
2526
use check;
2627
use flags::Subcommand;
2728
use doc;
@@ -34,7 +35,7 @@ pub struct Builder<'a> {
3435
pub top_stage: u32,
3536
pub kind: Kind,
3637
cache: Cache,
37-
stack: RefCell<Vec<Key>>,
38+
stack: RefCell<Vec<(TypeId, Box<Any>)>>,
3839
}
3940

4041
impl<'a> Deref for Builder<'a> {
@@ -45,19 +46,10 @@ impl<'a> Deref for Builder<'a> {
4546
}
4647
}
4748

48-
pub trait Step<'a>: Serialize + Sized {
49-
/// The output type of this step. This is used in a few places to return a
49+
pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
5050
/// `PathBuf` when directories are created or to return a `Compiler` once
5151
/// it's been assembled.
52-
///
53-
/// When possible, this should be used instead of implicitly creating files
54-
/// in a prearranged directory that will later be used by the build system.
55-
/// It's not always practical, however, since it makes avoiding rebuilds
56-
/// somewhat harder.
57-
type Output: Serialize + Deserialize<'a> + 'a;
58-
59-
/// This type, but with a 'static bound. Used for caching the step.
60-
type Id: 'static;
52+
type Output: Clone;
6153

6254
const DEFAULT: bool = false;
6355

@@ -72,13 +64,13 @@ pub trait Step<'a>: Serialize + Sized {
7264

7365
/// Primary function to execute this rule. Can call `builder.ensure(...)`
7466
/// with other steps to run those.
75-
fn run(self, builder: &'a Builder) -> Self::Output;
67+
fn run(self, builder: &Builder) -> Self::Output;
7668

7769
/// When bootstrap is passed a set of paths, this controls whether this rule
7870
/// will execute. However, it does not get called in a "default" context
7971
/// when we are not passed any paths; in that case, make_run is called
8072
/// directly.
81-
fn should_run(_builder: &'a Builder, _path: &Path) -> bool { false }
73+
fn should_run(_builder: &Builder, _path: &Path) -> bool { false }
8274

8375
/// Build up a "root" rule, either as a default rule or from a path passed
8476
/// to us.
@@ -87,10 +79,10 @@ pub trait Step<'a>: Serialize + Sized {
8779
/// passed. When `./x.py build` is run, for example, this rule could get
8880
/// called if it is in the correct list below with a path of `None`.
8981
fn make_run(
90-
_builder: &'a Builder,
82+
_builder: &Builder,
9183
_path: Option<&Path>,
92-
_host: &'a str,
93-
_target: &'a str,
84+
_host: Interned<String>,
85+
_target: Interned<String>,
9486
) { unimplemented!() }
9587
}
9688

@@ -176,26 +168,27 @@ impl<'a> Builder<'a> {
176168
/// not take `Compiler` since all `Compiler` instances are meant to be
177169
/// obtained through this function, since it ensures that they are valid
178170
/// (i.e., built and assembled).
179-
pub fn compiler(&'a self, stage: u32, host: &'a str) -> Compiler<'a> {
171+
pub fn compiler(&self, stage: u32, host: Interned<String>) -> Compiler {
180172
self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } })
181173
}
182174

183-
pub fn sysroot(&self, compiler: Compiler<'a>) -> PathBuf {
175+
pub fn sysroot(&self, compiler: Compiler) -> Interned<PathBuf> {
184176
self.ensure(compile::Sysroot { compiler })
185177
}
186178

187179
/// Returns the libdir where the standard library and other artifacts are
188180
/// found for a compiler's sysroot.
189-
pub fn sysroot_libdir(&self, compiler: Compiler<'a>, target: &'a str) -> PathBuf {
190-
#[derive(Serialize)]
191-
struct Libdir<'a> {
192-
compiler: Compiler<'a>,
193-
target: &'a str,
181+
pub fn sysroot_libdir(
182+
&self, compiler: Compiler, target: Interned<String>
183+
) -> Interned<PathBuf> {
184+
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
185+
struct Libdir {
186+
compiler: Compiler,
187+
target: Interned<String>,
194188
}
195-
impl<'a> Step<'a> for Libdir<'a> {
196-
type Id = Libdir<'static>;
197-
type Output = PathBuf;
198-
fn run(self, builder: &Builder) -> PathBuf {
189+
impl Step for Libdir {
190+
type Output = Interned<PathBuf>;
191+
fn run(self, builder: &Builder) -> Interned<PathBuf> {
199192
let compiler = self.compiler;
200193
let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() {
201194
builder.build.config.libdir_relative.clone().unwrap()
@@ -206,7 +199,7 @@ impl<'a> Builder<'a> {
206199
.join("rustlib").join(self.target).join("lib");
207200
let _ = fs::remove_dir_all(&sysroot);
208201
t!(fs::create_dir_all(&sysroot));
209-
sysroot
202+
INTERNER.intern_path(sysroot)
210203
}
211204
}
212205
self.ensure(Libdir { compiler, target })
@@ -221,7 +214,7 @@ impl<'a> Builder<'a> {
221214
if compiler.is_snapshot(self) {
222215
self.build.rustc_snapshot_libdir()
223216
} else {
224-
self.sysroot(compiler).join(libdir(compiler.host))
217+
self.sysroot(compiler).join(libdir(&compiler.host))
225218
}
226219
}
227220

@@ -243,15 +236,15 @@ impl<'a> Builder<'a> {
243236
if compiler.is_snapshot(self) {
244237
self.initial_rustc.clone()
245238
} else {
246-
self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host))
239+
self.sysroot(compiler).join("bin").join(exe("rustc", &compiler.host))
247240
}
248241
}
249242

250243
/// Get the `rustdoc` executable next to the specified compiler
251244
pub fn rustdoc(&self, compiler: Compiler) -> PathBuf {
252245
let mut rustdoc = self.rustc(compiler);
253246
rustdoc.pop();
254-
rustdoc.push(exe("rustdoc", compiler.host));
247+
rustdoc.push(exe("rustdoc", &compiler.host));
255248
rustdoc
256249
}
257250

@@ -265,7 +258,7 @@ impl<'a> Builder<'a> {
265258
pub fn cargo(&self,
266259
compiler: Compiler,
267260
mode: Mode,
268-
target: &str,
261+
target: Interned<String>,
269262
cmd: &str) -> Command {
270263
let mut cargo = Command::new(&self.initial_cargo);
271264
let out_dir = self.stage_out(compiler, mode);
@@ -427,7 +420,7 @@ impl<'a> Builder<'a> {
427420
cargo
428421
}
429422

430-
fn maybe_run<S: Step<'a>>(&'a self, path: Option<&Path>) {
423+
fn maybe_run<S: Step>(&self, path: Option<&Path>) {
431424
let build = self.build;
432425
let hosts = if S::ONLY_BUILD_TARGETS || S::ONLY_BUILD {
433426
&build.config.host[..1]
@@ -459,41 +452,45 @@ impl<'a> Builder<'a> {
459452

460453
for host in hosts {
461454
for target in targets {
462-
S::make_run(self, path, host, target);
455+
S::make_run(self, path, *host, *target);
463456
}
464457
}
465458
}
466459

467460
/// Ensure that a given step is built, returning it's output. This will
468461
/// cache the step, so it is safe (and good!) to call this as often as
469462
/// needed to ensure that all dependencies are built.
470-
pub fn ensure<S: Step<'a>>(&'a self, step: S) -> S::Output {
471-
let key = Cache::to_key(&step);
463+
pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
464+
let type_id = TypeId::of::<S>();
472465
{
473466
let mut stack = self.stack.borrow_mut();
474-
if stack.contains(&key) {
467+
for &(stack_type_id, ref stack_step) in stack.iter() {
468+
if !(type_id == stack_type_id && step == *stack_step.downcast_ref().unwrap()) {
469+
continue
470+
}
475471
let mut out = String::new();
476-
out += &format!("\n\nCycle in build detected when adding {:?}\n", key);
472+
out += &format!("\n\nCycle in build detected when adding {:?}\n", step);
477473
for el in stack.iter().rev() {
478474
out += &format!("\t{:?}\n", el);
479475
}
480476
panic!(out);
481477
}
482-
if let Some(out) = self.cache.get::<S::Output>(&key) {
483-
self.build.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), key));
478+
if let Some(out) = self.cache.get(&step) {
479+
self.build.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), step));
484480

485481
return out;
486482
}
487-
self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), key));
488-
stack.push(key.clone());
483+
self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), step));
484+
stack.push((type_id, Box::new(step.clone())));
489485
}
490-
let out = step.run(self);
486+
let out = step.clone().run(self);
491487
{
492488
let mut stack = self.stack.borrow_mut();
493-
assert_eq!(stack.pop().as_ref(), Some(&key));
489+
let (cur_type_id, cur_step) = stack.pop().expect("step stack empty");
490+
assert_eq!((cur_type_id, cur_step.downcast_ref()), (type_id, Some(&step)));
494491
}
495-
self.build.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), key));
496-
self.cache.put(key.clone(), &out);
497-
self.cache.get::<S::Output>(&key).unwrap()
492+
self.build.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
493+
self.cache.put(step, out.clone());
494+
out
498495
}
499496
}

0 commit comments

Comments
 (0)