From d3939322e3273059bdfedec52cb8d6f78476af7c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 3 Nov 2018 10:51:31 -0700 Subject: [PATCH 1/2] rustc: Clean up allocator injection logic This commit cleans up allocator injection logic found in the compiler around selecting the global allocator. It turns out that now that jemalloc is gone the compiler never actually injects anything! This means that basically everything around loading crates here and there can be easily pruned. This also removes the `exe_allocation_crate` option from custom target specs as it's no longer used by the compiler anywhere. --- src/liballoc_system/lib.rs | 1 - src/librustc/middle/dependency_format.rs | 15 --- src/librustc/session/mod.rs | 2 - src/librustc_metadata/creader.rs | 113 +++--------------- .../spec/aarch64_unknown_freebsd.rs | 3 - .../spec/aarch64_unknown_linux_gnu.rs | 3 - .../spec/aarch64_unknown_linux_musl.rs | 3 - src/librustc_target/spec/hermit_base.rs | 1 - src/librustc_target/spec/l4re_base.rs | 1 - .../spec/mips64_unknown_linux_gnuabi64.rs | 3 - .../spec/mips64el_unknown_linux_gnuabi64.rs | 3 - .../spec/mips_unknown_linux_gnu.rs | 3 - .../spec/mips_unknown_linux_musl.rs | 2 - .../spec/mips_unknown_linux_uclibc.rs | 3 - .../spec/mipsel_unknown_linux_gnu.rs | 3 - .../spec/mipsel_unknown_linux_musl.rs | 2 - .../spec/mipsel_unknown_linux_uclibc.rs | 3 - src/librustc_target/spec/mod.rs | 6 - .../spec/powerpc64_unknown_linux_gnu.rs | 3 - .../spec/powerpc64le_unknown_linux_gnu.rs | 3 - .../spec/powerpc64le_unknown_linux_musl.rs | 3 - .../spec/powerpc_unknown_linux_gnu.rs | 3 - .../spec/powerpc_unknown_linux_gnuspe.rs | 3 - .../spec/powerpc_unknown_netbsd.rs | 3 - .../spec/s390x_unknown_linux_gnu.rs | 2 - .../spec/sparc64_unknown_linux_gnu.rs | 1 - .../spec/sparc_unknown_linux_gnu.rs | 1 - .../spec/sparcv9_sun_solaris.rs | 1 - .../spec/x86_64_rumprun_netbsd.rs | 1 - 29 files changed, 17 insertions(+), 177 deletions(-) diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 0e6887a508223..533eb23c193e1 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -25,7 +25,6 @@ feature(integer_atomics, stdsimd) )] #![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))] -#![rustc_alloc_kind = "lib"] // The minimum alignment guaranteed by the architecture. This value is used to // add fast paths for low alignment values. diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index e3f9c51a1235e..671f513d5b933 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -63,7 +63,6 @@ use hir::def_id::CrateNum; -use session; use session::config; use ty::TyCtxt; use middle::cstore::{self, DepKind}; @@ -224,7 +223,6 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // quite yet, so do so here. activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret, &|cnum| tcx.is_panic_runtime(cnum)); - activate_injected_allocator(sess, &mut ret); // When dylib B links to dylib A, then when using B we must also link to A. // It could be the case, however, that the rlib for A is present (hence we @@ -303,7 +301,6 @@ fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option, } } -fn activate_injected_allocator(sess: &session::Session, - list: &mut DependencyList) { - let cnum = match sess.injected_allocator.get() { - Some(cnum) => cnum, - None => return, - }; - let idx = cnum.as_usize() - 1; - if list[idx] == Linkage::NotLinked { - list[idx] = Linkage::Static; - } -} - // After the linkage for a crate has been determined we need to verify that // there's only going to be one allocator in the output. fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) { diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index efd7e8b610efc..8cfbd27fc6163 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -112,7 +112,6 @@ pub struct Session { /// The metadata::creader module may inject an allocator/panic_runtime /// dependency if it didn't already find one, and this tracks what was /// injected. - pub injected_allocator: Once>, pub allocator_kind: Once>, pub injected_panic_runtime: Once>, @@ -1162,7 +1161,6 @@ pub fn build_session_( type_length_limit: Once::new(), const_eval_stack_frame_limit: 100, next_node_id: OneThread::new(Cell::new(NodeId::new(1))), - injected_allocator: Once::new(), allocator_kind: Once::new(), injected_panic_runtime: Once::new(), imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 7733ab2e246d1..734d84b409a9e 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -864,7 +864,6 @@ impl<'a> CrateLoader<'a> { needs_allocator = needs_allocator || data.root.needs_allocator; }); if !needs_allocator { - self.sess.injected_allocator.set(None); self.sess.allocator_kind.set(None); return } @@ -872,20 +871,18 @@ impl<'a> CrateLoader<'a> { // At this point we've determined that we need an allocator. Let's see // if our compilation session actually needs an allocator based on what // we're emitting. - let mut need_lib_alloc = false; - let mut need_exe_alloc = false; + let mut all_rlib = true; for ct in self.sess.crate_types.borrow().iter() { match *ct { - config::CrateType::Executable => need_exe_alloc = true, + config::CrateType::Executable | config::CrateType::Dylib | config::CrateType::ProcMacro | config::CrateType::Cdylib | - config::CrateType::Staticlib => need_lib_alloc = true, + config::CrateType::Staticlib => all_rlib = false, config::CrateType::Rlib => {} } } - if !need_lib_alloc && !need_exe_alloc { - self.sess.injected_allocator.set(None); + if all_rlib { self.sess.allocator_kind.set(None); return } @@ -924,103 +921,27 @@ impl<'a> CrateLoader<'a> { }); if global_allocator.is_some() { self.sess.allocator_kind.set(Some(AllocatorKind::Global)); - self.sess.injected_allocator.set(None); return } // Ok we haven't found a global allocator but we still need an - // allocator. At this point we'll either fall back to the "library - // allocator" or the "exe allocator" depending on a few variables. Let's - // figure out which one. - // - // Note that here we favor linking to the "library allocator" as much as - // possible. If we're not creating rustc's version of libstd - // (need_lib_alloc and prefer_dynamic) then we select `None`, and if the - // exe allocation crate doesn't exist for this target then we also - // select `None`. - let exe_allocation_crate_data = - if need_lib_alloc && !self.sess.opts.cg.prefer_dynamic { - None - } else { - self.sess - .target - .target - .options - .exe_allocation_crate - .as_ref() - .map(|name| { - // We've determined that we're injecting an "exe allocator" which means - // that we're going to load up a whole new crate. An example of this is - // that we're producing a normal binary on Linux which means we need to - // load the `alloc_jemalloc` crate to link as an allocator. - let name = Symbol::intern(name); - let (cnum, data) = self.resolve_crate(&None, - name, - name, - None, - None, - DUMMY_SP, - PathKind::Crate, - DepKind::Implicit) - .unwrap_or_else(|err| err.report()); - self.sess.injected_allocator.set(Some(cnum)); - data - }) - }; - - let allocation_crate_data = exe_allocation_crate_data.or_else(|| { - // No allocator was injected - self.sess.injected_allocator.set(None); - - if attr::contains_name(&krate.attrs, "default_lib_allocator") { - // Prefer self as the allocator if there's a collision - return None; + // allocator. At this point our allocator request is typically fulfilled + // by the standard library, denoted by the `#![default_lib_allocator]` + // attribute. + let mut has_default = attr::contains_name(&krate.attrs, "default_lib_allocator"); + self.cstore.iter_crate_data(|_, data| { + if data.root.has_default_lib_allocator { + has_default = true; } - // We're not actually going to inject an allocator, we're going to - // require that something in our crate graph is the default lib - // allocator. This is typically libstd, so this'll rarely be an - // error. - let mut allocator = None; - self.cstore.iter_crate_data(|_, data| { - if allocator.is_none() && data.root.has_default_lib_allocator { - allocator = Some(data.clone()); - } - }); - allocator }); - match allocation_crate_data { - Some(data) => { - // We have an allocator. We detect separately what kind it is, to allow for some - // flexibility in misconfiguration. - let attrs = data.get_item_attrs(CRATE_DEF_INDEX, self.sess); - let kind_interned = attr::first_attr_value_str_by_name(&attrs, "rustc_alloc_kind") - .map(Symbol::as_str); - let kind_str = kind_interned - .as_ref() - .map(|s| s as &str); - let alloc_kind = match kind_str { - None | - Some("lib") => AllocatorKind::DefaultLib, - Some("exe") => AllocatorKind::DefaultExe, - Some(other) => { - self.sess.err(&format!("Allocator kind {} not known", other)); - return; - } - }; - self.sess.allocator_kind.set(Some(alloc_kind)); - }, - None => { - if !attr::contains_name(&krate.attrs, "default_lib_allocator") { - self.sess.err("no global memory allocator found but one is \ - required; link to std or \ - add #[global_allocator] to a static item \ - that implements the GlobalAlloc trait."); - return; - } - self.sess.allocator_kind.set(Some(AllocatorKind::DefaultLib)); - } + if !has_default { + self.sess.err("no global memory allocator found but one is \ + required; link to std or \ + add #[global_allocator] to a static item \ + that implements the GlobalAlloc trait."); } + self.sess.allocator_kind.set(Some(AllocatorKind::DefaultLib)); fn has_global_allocator(krate: &ast::Crate) -> bool { struct Finder(bool); diff --git a/src/librustc_target/spec/aarch64_unknown_freebsd.rs b/src/librustc_target/spec/aarch64_unknown_freebsd.rs index 541f0564a01e2..b120f57192bfb 100644 --- a/src/librustc_target/spec/aarch64_unknown_freebsd.rs +++ b/src/librustc_target/spec/aarch64_unknown_freebsd.rs @@ -14,9 +14,6 @@ pub fn target() -> TargetResult { let mut base = super::freebsd_base::opts(); base.max_atomic_width = Some(128); - // see #36994 - base.exe_allocation_crate = None; - Ok(Target { llvm_target: "aarch64-unknown-freebsd".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/aarch64_unknown_linux_gnu.rs b/src/librustc_target/spec/aarch64_unknown_linux_gnu.rs index 2351d01469215..af7ec6a1787f0 100644 --- a/src/librustc_target/spec/aarch64_unknown_linux_gnu.rs +++ b/src/librustc_target/spec/aarch64_unknown_linux_gnu.rs @@ -14,9 +14,6 @@ pub fn target() -> TargetResult { let mut base = super::linux_base::opts(); base.max_atomic_width = Some(128); - // see #36994 - base.exe_allocation_crate = None; - Ok(Target { llvm_target: "aarch64-unknown-linux-gnu".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/aarch64_unknown_linux_musl.rs b/src/librustc_target/spec/aarch64_unknown_linux_musl.rs index 5ab55a076f45b..e5ca91aabe56a 100644 --- a/src/librustc_target/spec/aarch64_unknown_linux_musl.rs +++ b/src/librustc_target/spec/aarch64_unknown_linux_musl.rs @@ -14,9 +14,6 @@ pub fn target() -> TargetResult { let mut base = super::linux_musl_base::opts(); base.max_atomic_width = Some(128); - // see #36994 - base.exe_allocation_crate = None; - Ok(Target { llvm_target: "aarch64-unknown-linux-musl".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/hermit_base.rs b/src/librustc_target/spec/hermit_base.rs index 2a24f771e9289..168eac685e4f3 100644 --- a/src/librustc_target/spec/hermit_base.rs +++ b/src/librustc_target/spec/hermit_base.rs @@ -21,7 +21,6 @@ pub fn opts() -> TargetOptions { ]); TargetOptions { - exe_allocation_crate: None, executables: true, has_elf_tls: true, linker_is_gnu: true, diff --git a/src/librustc_target/spec/l4re_base.rs b/src/librustc_target/spec/l4re_base.rs index 4ebc930d48b6f..7932adf3b1054 100644 --- a/src/librustc_target/spec/l4re_base.rs +++ b/src/librustc_target/spec/l4re_base.rs @@ -30,7 +30,6 @@ pub fn opts() -> TargetOptions { TargetOptions { executables: true, has_elf_tls: false, - exe_allocation_crate: None, panic_strategy: PanicStrategy::Abort, linker: Some("ld".to_string()), pre_link_args: args, diff --git a/src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs index 1f60d918908d0..b80b6b561cd42 100644 --- a/src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs +++ b/src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs @@ -28,9 +28,6 @@ pub fn target() -> TargetResult { features: "+mips64r2".to_string(), max_atomic_width: Some(64), - // see #36994 - exe_allocation_crate: None, - ..super::linux_base::opts() }, }) diff --git a/src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs index e42fde8d403fb..1c835af6e412b 100644 --- a/src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs +++ b/src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs @@ -28,9 +28,6 @@ pub fn target() -> TargetResult { features: "+mips64r2".to_string(), max_atomic_width: Some(64), - // see #36994 - exe_allocation_crate: None, - ..super::linux_base::opts() }, }) diff --git a/src/librustc_target/spec/mips_unknown_linux_gnu.rs b/src/librustc_target/spec/mips_unknown_linux_gnu.rs index 59e15137cf40d..6331031c9a284 100644 --- a/src/librustc_target/spec/mips_unknown_linux_gnu.rs +++ b/src/librustc_target/spec/mips_unknown_linux_gnu.rs @@ -27,9 +27,6 @@ pub fn target() -> TargetResult { features: "+mips32r2,+fpxx,+nooddspreg".to_string(), max_atomic_width: Some(32), - // see #36994 - exe_allocation_crate: None, - ..super::linux_base::opts() }, }) diff --git a/src/librustc_target/spec/mips_unknown_linux_musl.rs b/src/librustc_target/spec/mips_unknown_linux_musl.rs index 8ee399ba56c32..0b20765172a02 100644 --- a/src/librustc_target/spec/mips_unknown_linux_musl.rs +++ b/src/librustc_target/spec/mips_unknown_linux_musl.rs @@ -15,8 +15,6 @@ pub fn target() -> TargetResult { base.cpu = "mips32r2".to_string(); base.features = "+mips32r2,+soft-float".to_string(); base.max_atomic_width = Some(32); - // see #36994 - base.exe_allocation_crate = None; base.crt_static_default = false; Ok(Target { llvm_target: "mips-unknown-linux-musl".to_string(), diff --git a/src/librustc_target/spec/mips_unknown_linux_uclibc.rs b/src/librustc_target/spec/mips_unknown_linux_uclibc.rs index 384ab1e413123..d3f614c982ae4 100644 --- a/src/librustc_target/spec/mips_unknown_linux_uclibc.rs +++ b/src/librustc_target/spec/mips_unknown_linux_uclibc.rs @@ -27,9 +27,6 @@ pub fn target() -> TargetResult { features: "+mips32r2,+soft-float".to_string(), max_atomic_width: Some(32), - // see #36994 - exe_allocation_crate: None, - ..super::linux_base::opts() }, }) diff --git a/src/librustc_target/spec/mipsel_unknown_linux_gnu.rs b/src/librustc_target/spec/mipsel_unknown_linux_gnu.rs index edd29164caca8..79ebefa79a320 100644 --- a/src/librustc_target/spec/mipsel_unknown_linux_gnu.rs +++ b/src/librustc_target/spec/mipsel_unknown_linux_gnu.rs @@ -28,9 +28,6 @@ pub fn target() -> TargetResult { features: "+mips32r2,+fpxx,+nooddspreg".to_string(), max_atomic_width: Some(32), - // see #36994 - exe_allocation_crate: None, - ..super::linux_base::opts() }, }) diff --git a/src/librustc_target/spec/mipsel_unknown_linux_musl.rs b/src/librustc_target/spec/mipsel_unknown_linux_musl.rs index 1d9378ca1b814..042e2b71c3256 100644 --- a/src/librustc_target/spec/mipsel_unknown_linux_musl.rs +++ b/src/librustc_target/spec/mipsel_unknown_linux_musl.rs @@ -15,8 +15,6 @@ pub fn target() -> TargetResult { base.cpu = "mips32r2".to_string(); base.features = "+mips32r2,+soft-float".to_string(); base.max_atomic_width = Some(32); - // see #36994 - base.exe_allocation_crate = None; base.crt_static_default = false; Ok(Target { llvm_target: "mipsel-unknown-linux-musl".to_string(), diff --git a/src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs b/src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs index a1db1791bb7ce..8cb5cd3f03a67 100644 --- a/src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs +++ b/src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs @@ -28,9 +28,6 @@ pub fn target() -> TargetResult { features: "+mips32r2,+soft-float".to_string(), max_atomic_width: Some(32), - // see #36994 - exe_allocation_crate: None, - ..super::linux_base::opts() }, }) diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index c8af81c02ea4a..16dc2a91030f1 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -596,9 +596,6 @@ pub struct TargetOptions { /// `eh_unwind_resume` lang item. pub custom_unwind_resume: bool, - /// If necessary, a different crate to link exe allocators by default - pub exe_allocation_crate: Option, - /// Flag indicating whether ELF TLS (e.g. #[thread_local]) is available for /// this target. pub has_elf_tls: bool, @@ -740,7 +737,6 @@ impl Default for TargetOptions { link_env: Vec::new(), archive_format: "gnu".to_string(), custom_unwind_resume: false, - exe_allocation_crate: None, allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, @@ -1025,7 +1021,6 @@ impl Target { key!(archive_format); key!(allow_asm, bool); key!(custom_unwind_resume, bool); - key!(exe_allocation_crate, optional); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); key!(no_integrated_as, bool); @@ -1235,7 +1230,6 @@ impl ToJson for Target { target_option_val!(archive_format); target_option_val!(allow_asm); target_option_val!(custom_unwind_resume); - target_option_val!(exe_allocation_crate); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); target_option_val!(no_integrated_as); diff --git a/src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs b/src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs index 1959871161343..1d0afcd5e0c60 100644 --- a/src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs +++ b/src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs @@ -20,9 +20,6 @@ pub fn target() -> TargetResult { // for now. https://github.com/rust-lang/rust/pull/43170#issuecomment-315411474 base.relro_level = RelroLevel::Partial; - // see #36994 - base.exe_allocation_crate = None; - Ok(Target { llvm_target: "powerpc64-unknown-linux-gnu".to_string(), target_endian: "big".to_string(), diff --git a/src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs b/src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs index 39840692dff18..01811c5a0c322 100644 --- a/src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs +++ b/src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs @@ -16,9 +16,6 @@ pub fn target() -> TargetResult { base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.max_atomic_width = Some(64); - // see #36994 - base.exe_allocation_crate = None; - Ok(Target { llvm_target: "powerpc64le-unknown-linux-gnu".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/powerpc64le_unknown_linux_musl.rs b/src/librustc_target/spec/powerpc64le_unknown_linux_musl.rs index 34ec82412289d..590c5ba8d54b4 100644 --- a/src/librustc_target/spec/powerpc64le_unknown_linux_musl.rs +++ b/src/librustc_target/spec/powerpc64le_unknown_linux_musl.rs @@ -16,9 +16,6 @@ pub fn target() -> TargetResult { base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.max_atomic_width = Some(64); - // see #36994 - base.exe_allocation_crate = None; - Ok(Target { llvm_target: "powerpc64le-unknown-linux-musl".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/powerpc_unknown_linux_gnu.rs b/src/librustc_target/spec/powerpc_unknown_linux_gnu.rs index c05b110a75d39..99d8d99fbb2b6 100644 --- a/src/librustc_target/spec/powerpc_unknown_linux_gnu.rs +++ b/src/librustc_target/spec/powerpc_unknown_linux_gnu.rs @@ -15,9 +15,6 @@ pub fn target() -> TargetResult { base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); base.max_atomic_width = Some(32); - // see #36994 - base.exe_allocation_crate = None; - Ok(Target { llvm_target: "powerpc-unknown-linux-gnu".to_string(), target_endian: "big".to_string(), diff --git a/src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs b/src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs index c76c3119c87c5..9b15b0a5dc4b7 100644 --- a/src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs +++ b/src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs @@ -15,9 +15,6 @@ pub fn target() -> TargetResult { base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mspe".to_string()); base.max_atomic_width = Some(32); - // see #36994 - base.exe_allocation_crate = None; - Ok(Target { llvm_target: "powerpc-unknown-linux-gnuspe".to_string(), target_endian: "big".to_string(), diff --git a/src/librustc_target/spec/powerpc_unknown_netbsd.rs b/src/librustc_target/spec/powerpc_unknown_netbsd.rs index 740222c960805..98625a63f5298 100644 --- a/src/librustc_target/spec/powerpc_unknown_netbsd.rs +++ b/src/librustc_target/spec/powerpc_unknown_netbsd.rs @@ -15,9 +15,6 @@ pub fn target() -> TargetResult { base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); base.max_atomic_width = Some(32); - // see #36994 - base.exe_allocation_crate = None; - Ok(Target { llvm_target: "powerpc-unknown-netbsd".to_string(), target_endian: "big".to_string(), diff --git a/src/librustc_target/spec/s390x_unknown_linux_gnu.rs b/src/librustc_target/spec/s390x_unknown_linux_gnu.rs index c9a9625ebab95..bd8b7e435d340 100644 --- a/src/librustc_target/spec/s390x_unknown_linux_gnu.rs +++ b/src/librustc_target/spec/s390x_unknown_linux_gnu.rs @@ -19,8 +19,6 @@ pub fn target() -> TargetResult { // Pass the -vector feature string to LLVM to respect this assumption. base.features = "-vector".to_string(); base.max_atomic_width = Some(64); - // see #36994 - base.exe_allocation_crate = None; base.min_global_align = Some(16); Ok(Target { diff --git a/src/librustc_target/spec/sparc64_unknown_linux_gnu.rs b/src/librustc_target/spec/sparc64_unknown_linux_gnu.rs index f68b5fd24bf75..f2b99aa46d2d0 100644 --- a/src/librustc_target/spec/sparc64_unknown_linux_gnu.rs +++ b/src/librustc_target/spec/sparc64_unknown_linux_gnu.rs @@ -14,7 +14,6 @@ pub fn target() -> TargetResult { let mut base = super::linux_base::opts(); base.cpu = "v9".to_string(); base.max_atomic_width = Some(64); - base.exe_allocation_crate = None; Ok(Target { llvm_target: "sparc64-unknown-linux-gnu".to_string(), diff --git a/src/librustc_target/spec/sparc_unknown_linux_gnu.rs b/src/librustc_target/spec/sparc_unknown_linux_gnu.rs index 4e352374f90b0..81db39cd23f87 100644 --- a/src/librustc_target/spec/sparc_unknown_linux_gnu.rs +++ b/src/librustc_target/spec/sparc_unknown_linux_gnu.rs @@ -15,7 +15,6 @@ pub fn target() -> TargetResult { base.cpu = "v9".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mv8plus".to_string()); - base.exe_allocation_crate = None; Ok(Target { llvm_target: "sparc-unknown-linux-gnu".to_string(), diff --git a/src/librustc_target/spec/sparcv9_sun_solaris.rs b/src/librustc_target/spec/sparcv9_sun_solaris.rs index 8bc233107b8bb..5029e857eb543 100644 --- a/src/librustc_target/spec/sparcv9_sun_solaris.rs +++ b/src/librustc_target/spec/sparcv9_sun_solaris.rs @@ -16,7 +16,6 @@ pub fn target() -> TargetResult { // llvm calls this "v9" base.cpu = "v9".to_string(); base.max_atomic_width = Some(64); - base.exe_allocation_crate = None; Ok(Target { llvm_target: "sparcv9-sun-solaris".to_string(), diff --git a/src/librustc_target/spec/x86_64_rumprun_netbsd.rs b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs index 684bf5a6c1026..e7570cd2da6ec 100644 --- a/src/librustc_target/spec/x86_64_rumprun_netbsd.rs +++ b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs @@ -21,7 +21,6 @@ pub fn target() -> TargetResult { base.has_rpath = false; base.position_independent_executables = false; base.disable_redzone = true; - base.exe_allocation_crate = None; base.stack_probes = true; Ok(Target { From cc7590341a6ac213909d0ef56a7ebc2834274c8b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 3 Nov 2018 11:15:48 -0700 Subject: [PATCH 2/2] std: Delete the `alloc_system` crate This commit deletes the `alloc_system` crate from the standard distribution. This unstable crate is no longer needed in the modern stable global allocator world, but rather its functionality is folded directly into the standard library. The standard library was already the only stable location to access this crate, and as a result this should not affect any stable code. --- src/Cargo.lock | 16 +- src/bootstrap/dist.rs | 1 - src/ci/docker/wasm32-unknown/Dockerfile | 2 +- src/liballoc/tests/heap.rs | 3 +- src/liballoc/tests/lib.rs | 2 - src/liballoc_system/Cargo.toml | 19 -- src/liballoc_system/lib.rs | 410 ------------------------ src/librustc_asan/Cargo.toml | 1 - src/librustc_asan/lib.rs | 8 - src/librustc_lsan/Cargo.toml | 1 - src/librustc_lsan/lib.rs | 8 - src/librustc_metadata/creader.rs | 23 +- src/librustc_msan/Cargo.toml | 1 - src/librustc_msan/lib.rs | 8 - src/librustc_tsan/Cargo.toml | 1 - src/librustc_tsan/lib.rs | 8 - src/libstd/Cargo.toml | 4 +- src/libstd/alloc.rs | 89 ++++- src/libstd/lib.rs | 4 +- src/libstd/sys/cloudabi/mod.rs | 2 + src/libstd/sys/redox/mod.rs | 2 + src/libstd/sys/unix/alloc.rs | 100 ++++++ src/libstd/sys/unix/mod.rs | 1 + src/libstd/sys/wasm/alloc.rs | 105 ++++++ src/libstd/sys/wasm/mod.rs | 1 + src/libstd/sys/windows/alloc.rs | 77 +++++ src/libstd/sys/windows/c.rs | 7 + src/libstd/sys/windows/mod.rs | 1 + src/libstd/sys_common/alloc.rs | 50 +++ src/libstd/sys_common/mod.rs | 1 + src/tools/tidy/src/pal.rs | 2 - 31 files changed, 450 insertions(+), 508 deletions(-) delete mode 100644 src/liballoc_system/Cargo.toml delete mode 100644 src/liballoc_system/lib.rs create mode 100644 src/libstd/sys/unix/alloc.rs create mode 100644 src/libstd/sys/wasm/alloc.rs create mode 100644 src/libstd/sys/windows/alloc.rs create mode 100644 src/libstd/sys_common/alloc.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 2ac51263cb5ca..32304c81182f1 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -15,16 +15,6 @@ dependencies = [ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "alloc_system" -version = "0.0.0" -dependencies = [ - "compiler_builtins 0.0.0", - "core 0.0.0", - "dlmalloc 0.0.0", - "libc 0.0.0", -] - [[package]] name = "ammonia" version = "1.1.0" @@ -2104,7 +2094,6 @@ name = "rustc_asan" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "alloc_system 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", @@ -2276,7 +2265,6 @@ name = "rustc_lsan" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "alloc_system 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", @@ -2328,7 +2316,6 @@ name = "rustc_msan" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "alloc_system 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", @@ -2440,7 +2427,6 @@ name = "rustc_tsan" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "alloc_system 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", @@ -2679,11 +2665,11 @@ name = "std" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "alloc_system 0.0.0", "build_helper 0.1.0", "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", + "dlmalloc 0.0.0", "libc 0.0.0", "panic_abort 0.0.0", "panic_unwind 0.0.0", diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 567b47a70a12c..0aab64465fd1c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -859,7 +859,6 @@ impl Step for Src { "src/build_helper", "src/dlmalloc", "src/liballoc", - "src/liballoc_system", "src/libbacktrace", "src/libcompiler_builtins", "src/libcore", diff --git a/src/ci/docker/wasm32-unknown/Dockerfile b/src/ci/docker/wasm32-unknown/Dockerfile index f2a29b0315100..161f0c0062fa0 100644 --- a/src/ci/docker/wasm32-unknown/Dockerfile +++ b/src/ci/docker/wasm32-unknown/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:16.04 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ diff --git a/src/liballoc/tests/heap.rs b/src/liballoc/tests/heap.rs index b6be38107da7f..bf256b23f9ac0 100644 --- a/src/liballoc/tests/heap.rs +++ b/src/liballoc/tests/heap.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc_system::System; -use std::alloc::{Global, Alloc, Layout}; +use std::alloc::{Global, Alloc, Layout, System}; /// https://github.com/rust-lang/rust/issues/45955 #[test] diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 3294837cb91c4..e514a8a69c020 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(allocator_api)] -#![feature(alloc_system)] #![feature(box_syntax)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] @@ -20,7 +19,6 @@ #![feature(unboxed_closures)] #![feature(repeat_generic_slice)] -extern crate alloc_system; extern crate core; extern crate rand; diff --git a/src/liballoc_system/Cargo.toml b/src/liballoc_system/Cargo.toml deleted file mode 100644 index c34e2f203a837..0000000000000 --- a/src/liballoc_system/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "alloc_system" -version = "0.0.0" - -[lib] -name = "alloc_system" -path = "lib.rs" -test = false -doc = false - -[dependencies] -core = { path = "../libcore" } -libc = { path = "../rustc/libc_shim" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim" } - -# See comments in the source for what this dependency is -[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] -dlmalloc = { path = "../rustc/dlmalloc_shim" } diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs deleted file mode 100644 index 533eb23c193e1..0000000000000 --- a/src/liballoc_system/lib.rs +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![no_std] -#![allow(unused_attributes)] -#![unstable(feature = "alloc_system", - reason = "this library is unlikely to be stabilized in its current \ - form or name", - issue = "32838")] - -#![feature(allocator_api)] -#![feature(core_intrinsics)] -#![feature(nll)] -#![feature(staged_api)] -#![feature(rustc_attrs)] -#![cfg_attr( - all(target_arch = "wasm32", not(target_os = "emscripten")), - feature(integer_atomics, stdsimd) -)] -#![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))] - -// The minimum alignment guaranteed by the architecture. This value is used to -// add fast paths for low alignment values. -#[cfg(all(any(target_arch = "x86", - target_arch = "arm", - target_arch = "mips", - target_arch = "powerpc", - target_arch = "powerpc64", - target_arch = "asmjs", - target_arch = "wasm32")))] -#[allow(dead_code)] -const MIN_ALIGN: usize = 8; -#[cfg(all(any(target_arch = "x86_64", - target_arch = "aarch64", - target_arch = "mips64", - target_arch = "s390x", - target_arch = "sparc64")))] -#[allow(dead_code)] -const MIN_ALIGN: usize = 16; - -use core::alloc::{Alloc, GlobalAlloc, AllocErr, Layout}; -use core::ptr::NonNull; - -/// The default memory allocator provided by the operating system. -/// -/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows, -/// plus related functions. -/// -/// This type can be used in a `static` item -/// with the `#[global_allocator]` attribute -/// to force the global allocator to be the system’s one. -/// (The default is jemalloc for executables, on some platforms.) -/// -/// ```rust -/// use std::alloc::System; -/// -/// #[global_allocator] -/// static A: System = System; -/// -/// fn main() { -/// let a = Box::new(4); // Allocates from the system allocator. -/// println!("{}", a); -/// } -/// ``` -/// -/// It can also be used directly to allocate memory -/// independently of the standard library’s global allocator. -#[stable(feature = "alloc_system_type", since = "1.28.0")] -pub struct System; - -#[unstable(feature = "allocator_api", issue = "32838")] -unsafe impl Alloc for System { - #[inline] - unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { - NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr) - } - - #[inline] - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result, AllocErr> { - NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr) - } - - #[inline] - unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { - GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) - } - - #[inline] - unsafe fn realloc(&mut self, - ptr: NonNull, - layout: Layout, - new_size: usize) -> Result, AllocErr> { - NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr) - } -} - -#[cfg(any(windows, unix, target_os = "cloudabi", target_os = "redox"))] -mod realloc_fallback { - use core::alloc::{GlobalAlloc, Layout}; - use core::cmp; - use core::ptr; - - impl super::System { - pub(crate) unsafe fn realloc_fallback(&self, ptr: *mut u8, old_layout: Layout, - new_size: usize) -> *mut u8 { - // Docs for GlobalAlloc::realloc require this to be valid: - let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align()); - - let new_ptr = GlobalAlloc::alloc(self, new_layout); - if !new_ptr.is_null() { - let size = cmp::min(old_layout.size(), new_size); - ptr::copy_nonoverlapping(ptr, new_ptr, size); - GlobalAlloc::dealloc(self, ptr, old_layout); - } - new_ptr - } - } -} - -#[cfg(any(unix, target_os = "cloudabi", target_os = "redox"))] -mod platform { - extern crate libc; - - use core::ptr; - - use MIN_ALIGN; - use System; - use core::alloc::{GlobalAlloc, Layout}; - - #[stable(feature = "alloc_system_type", since = "1.28.0")] - unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - libc::malloc(layout.size()) as *mut u8 - } else { - #[cfg(target_os = "macos")] - { - if layout.align() > (1 << 31) { - return ptr::null_mut() - } - } - aligned_malloc(&layout) - } - } - - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - libc::calloc(layout.size(), 1) as *mut u8 - } else { - let ptr = self.alloc(layout.clone()); - if !ptr.is_null() { - ptr::write_bytes(ptr, 0, layout.size()); - } - ptr - } - } - - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - libc::free(ptr as *mut libc::c_void) - } - - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - if layout.align() <= MIN_ALIGN && layout.align() <= new_size { - libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 - } else { - self.realloc_fallback(ptr, layout, new_size) - } - } - } - - #[cfg(any(target_os = "android", - target_os = "hermit", - target_os = "redox", - target_os = "solaris"))] - #[inline] - unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { - // On android we currently target API level 9 which unfortunately - // doesn't have the `posix_memalign` API used below. Instead we use - // `memalign`, but this unfortunately has the property on some systems - // where the memory returned cannot be deallocated by `free`! - // - // Upon closer inspection, however, this appears to work just fine with - // Android, so for this platform we should be fine to call `memalign` - // (which is present in API level 9). Some helpful references could - // possibly be chromium using memalign [1], attempts at documenting that - // memalign + free is ok [2] [3], or the current source of chromium - // which still uses memalign on android [4]. - // - // [1]: https://codereview.chromium.org/10796020/ - // [2]: https://code.google.com/p/android/issues/detail?id=35391 - // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 - // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ - // /memory/aligned_memory.cc - libc::memalign(layout.align(), layout.size()) as *mut u8 - } - - #[cfg(not(any(target_os = "android", - target_os = "hermit", - target_os = "redox", - target_os = "solaris")))] - #[inline] - unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { - let mut out = ptr::null_mut(); - let ret = libc::posix_memalign(&mut out, layout.align(), layout.size()); - if ret != 0 { - ptr::null_mut() - } else { - out as *mut u8 - } - } -} - -#[cfg(windows)] -#[allow(nonstandard_style)] -mod platform { - use MIN_ALIGN; - use System; - use core::alloc::{GlobalAlloc, Layout}; - - type LPVOID = *mut u8; - type HANDLE = LPVOID; - type SIZE_T = usize; - type DWORD = u32; - type BOOL = i32; - - extern "system" { - fn GetProcessHeap() -> HANDLE; - fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; - fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID; - fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; - fn GetLastError() -> DWORD; - } - - #[repr(C)] - struct Header(*mut u8); - - const HEAP_ZERO_MEMORY: DWORD = 0x00000008; - - unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header { - &mut *(ptr as *mut Header).offset(-1) - } - - unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { - let aligned = ptr.add(align - (ptr as usize & (align - 1))); - *get_header(aligned) = Header(ptr); - aligned - } - - #[inline] - unsafe fn allocate_with_flags(layout: Layout, flags: DWORD) -> *mut u8 { - let ptr = if layout.align() <= MIN_ALIGN { - HeapAlloc(GetProcessHeap(), flags, layout.size()) - } else { - let size = layout.size() + layout.align(); - let ptr = HeapAlloc(GetProcessHeap(), flags, size); - if ptr.is_null() { - ptr - } else { - align_ptr(ptr, layout.align()) - } - }; - ptr as *mut u8 - } - - #[stable(feature = "alloc_system_type", since = "1.28.0")] - unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - allocate_with_flags(layout, 0) - } - - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - allocate_with_flags(layout, HEAP_ZERO_MEMORY) - } - - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - if layout.align() <= MIN_ALIGN { - let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID); - debug_assert!(err != 0, "Failed to free heap memory: {}", - GetLastError()); - } else { - let header = get_header(ptr); - let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID); - debug_assert!(err != 0, "Failed to free heap memory: {}", - GetLastError()); - } - } - - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - if layout.align() <= MIN_ALIGN { - HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, new_size) as *mut u8 - } else { - self.realloc_fallback(ptr, layout, new_size) - } - } - } -} - -// This is an implementation of a global allocator on the wasm32 platform when -// emscripten is not in use. In that situation there's no actual runtime for us -// to lean on for allocation, so instead we provide our own! -// -// The wasm32 instruction set has two instructions for getting the current -// amount of memory and growing the amount of memory. These instructions are the -// foundation on which we're able to build an allocator, so we do so! Note that -// the instructions are also pretty "global" and this is the "global" allocator -// after all! -// -// The current allocator here is the `dlmalloc` crate which we've got included -// in the rust-lang/rust repository as a submodule. The crate is a port of -// dlmalloc.c from C to Rust and is basically just so we can have "pure Rust" -// for now which is currently technically required (can't link with C yet). -// -// The crate itself provides a global allocator which on wasm has no -// synchronization as there are no threads! -#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] -mod platform { - extern crate dlmalloc; - - use core::alloc::{GlobalAlloc, Layout}; - use System; - - static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT; - - #[stable(feature = "alloc_system_type", since = "1.28.0")] - unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - let _lock = lock::lock(); - DLMALLOC.malloc(layout.size(), layout.align()) - } - - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - let _lock = lock::lock(); - DLMALLOC.calloc(layout.size(), layout.align()) - } - - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - let _lock = lock::lock(); - DLMALLOC.free(ptr, layout.size(), layout.align()) - } - - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - let _lock = lock::lock(); - DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) - } - } - - #[cfg(target_feature = "atomics")] - mod lock { - use core::arch::wasm32; - use core::sync::atomic::{AtomicI32, Ordering::SeqCst}; - - static LOCKED: AtomicI32 = AtomicI32::new(0); - - pub struct DropLock; - - pub fn lock() -> DropLock { - loop { - if LOCKED.swap(1, SeqCst) == 0 { - return DropLock - } - unsafe { - let r = wasm32::atomic::wait_i32( - &LOCKED as *const AtomicI32 as *mut i32, - 1, // expected value - -1, // timeout - ); - debug_assert!(r == 0 || r == 1); - } - } - } - - impl Drop for DropLock { - fn drop(&mut self) { - let r = LOCKED.swap(0, SeqCst); - debug_assert_eq!(r, 1); - unsafe { - wasm32::atomic::wake( - &LOCKED as *const AtomicI32 as *mut i32, - 1, // only one thread - ); - } - } - } - } - - #[cfg(not(target_feature = "atomics"))] - mod lock { - #[inline] - pub fn lock() {} // no atomics, no threads, that's easy! - } -} diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml index 34d8b75a5bfb3..734564c2d8567 100644 --- a/src/librustc_asan/Cargo.toml +++ b/src/librustc_asan/Cargo.toml @@ -15,6 +15,5 @@ cmake = "0.1.18" [dependencies] alloc = { path = "../liballoc" } -alloc_system = { path = "../liballoc_system" } core = { path = "../libcore" } compiler_builtins = { path = "../rustc/compiler_builtins_shim" } diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs index 7b845e631ffa3..47f917e40c1ff 100644 --- a/src/librustc_asan/lib.rs +++ b/src/librustc_asan/lib.rs @@ -9,7 +9,6 @@ // except according to those terms. #![sanitizer_runtime] -#![feature(alloc_system)] #![feature(nll)] #![feature(sanitizer_runtime)] #![feature(staged_api)] @@ -17,10 +16,3 @@ #![unstable(feature = "sanitizer_runtime_lib", reason = "internal implementation detail of sanitizers", issue = "0")] - -extern crate alloc_system; - -use alloc_system::System; - -#[global_allocator] -static ALLOC: System = System; diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml index 9c19b53742654..2573825a5ff45 100644 --- a/src/librustc_lsan/Cargo.toml +++ b/src/librustc_lsan/Cargo.toml @@ -15,6 +15,5 @@ cmake = "0.1.18" [dependencies] alloc = { path = "../liballoc" } -alloc_system = { path = "../liballoc_system" } core = { path = "../libcore" } compiler_builtins = { path = "../rustc/compiler_builtins_shim" } diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs index 7b845e631ffa3..47f917e40c1ff 100644 --- a/src/librustc_lsan/lib.rs +++ b/src/librustc_lsan/lib.rs @@ -9,7 +9,6 @@ // except according to those terms. #![sanitizer_runtime] -#![feature(alloc_system)] #![feature(nll)] #![feature(sanitizer_runtime)] #![feature(staged_api)] @@ -17,10 +16,3 @@ #![unstable(feature = "sanitizer_runtime_lib", reason = "internal implementation detail of sanitizers", issue = "0")] - -extern crate alloc_system; - -use alloc_system::System; - -#[global_allocator] -static ALLOC: System = System; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 734d84b409a9e..a14dd99eeb3b3 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -16,7 +16,7 @@ use decoder::proc_macro_def_path_table; use schema::CrateRoot; use rustc_data_structures::sync::{Lrc, RwLock, Lock}; -use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX}; +use rustc::hir::def_id::CrateNum; use rustc_data_structures::svh::Svh; use rustc::middle::allocator::AllocatorKind; use rustc::middle::cstore::DepKind; @@ -871,17 +871,14 @@ impl<'a> CrateLoader<'a> { // At this point we've determined that we need an allocator. Let's see // if our compilation session actually needs an allocator based on what // we're emitting. - let mut all_rlib = true; - for ct in self.sess.crate_types.borrow().iter() { - match *ct { - config::CrateType::Executable | - config::CrateType::Dylib | - config::CrateType::ProcMacro | - config::CrateType::Cdylib | - config::CrateType::Staticlib => all_rlib = false, - config::CrateType::Rlib => {} - } - } + let all_rlib = self.sess.crate_types.borrow() + .iter() + .all(|ct| { + match *ct { + config::CrateType::Rlib => true, + _ => false, + } + }); if all_rlib { self.sess.allocator_kind.set(None); return @@ -1004,8 +1001,6 @@ impl<'a> CrateLoader<'a> { impl<'a> CrateLoader<'a> { pub fn postprocess(&mut self, krate: &ast::Crate) { - // inject the sanitizer runtime before the allocator runtime because all - // sanitizers force the use of the `alloc_system` allocator self.inject_sanitizer_runtime(); self.inject_profiler_runtime(); self.inject_allocator_crate(krate); diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml index 17ec2b96438ad..29165675a2ad7 100644 --- a/src/librustc_msan/Cargo.toml +++ b/src/librustc_msan/Cargo.toml @@ -15,6 +15,5 @@ cmake = "0.1.18" [dependencies] alloc = { path = "../liballoc" } -alloc_system = { path = "../liballoc_system" } core = { path = "../libcore" } compiler_builtins = { path = "../rustc/compiler_builtins_shim" } diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs index 7b845e631ffa3..47f917e40c1ff 100644 --- a/src/librustc_msan/lib.rs +++ b/src/librustc_msan/lib.rs @@ -9,7 +9,6 @@ // except according to those terms. #![sanitizer_runtime] -#![feature(alloc_system)] #![feature(nll)] #![feature(sanitizer_runtime)] #![feature(staged_api)] @@ -17,10 +16,3 @@ #![unstable(feature = "sanitizer_runtime_lib", reason = "internal implementation detail of sanitizers", issue = "0")] - -extern crate alloc_system; - -use alloc_system::System; - -#[global_allocator] -static ALLOC: System = System; diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml index 8bb67c0bbac5f..baadb64511ae1 100644 --- a/src/librustc_tsan/Cargo.toml +++ b/src/librustc_tsan/Cargo.toml @@ -15,6 +15,5 @@ cmake = "0.1.18" [dependencies] alloc = { path = "../liballoc" } -alloc_system = { path = "../liballoc_system" } core = { path = "../libcore" } compiler_builtins = { path = "../rustc/compiler_builtins_shim" } diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs index 7b845e631ffa3..47f917e40c1ff 100644 --- a/src/librustc_tsan/lib.rs +++ b/src/librustc_tsan/lib.rs @@ -9,7 +9,6 @@ // except according to those terms. #![sanitizer_runtime] -#![feature(alloc_system)] #![feature(nll)] #![feature(sanitizer_runtime)] #![feature(staged_api)] @@ -17,10 +16,3 @@ #![unstable(feature = "sanitizer_runtime_lib", reason = "internal implementation detail of sanitizers", issue = "0")] - -extern crate alloc_system; - -use alloc_system::System; - -#[global_allocator] -static ALLOC: System = System; diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 0f22459b34349..2b1d515c83b75 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -14,7 +14,6 @@ crate-type = ["dylib", "rlib"] [dependencies] alloc = { path = "../liballoc" } -alloc_system = { path = "../liballoc_system" } panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } core = { path = "../libcore" } @@ -36,6 +35,9 @@ rustc_lsan = { path = "../librustc_lsan" } rustc_msan = { path = "../librustc_msan" } rustc_tsan = { path = "../librustc_tsan" } +[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] +dlmalloc = { path = '../rustc/dlmalloc_shim' } + [build-dependencies] cc = "1.0" build_helper = { path = "../build_helper" } diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 1ff342fa7a7be..485b2ffe1975e 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -73,15 +73,100 @@ use core::sync::atomic::{AtomicPtr, Ordering}; use core::{mem, ptr}; +use core::ptr::NonNull; use sys_common::util::dumb_print; #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] pub use alloc_crate::alloc::*; +/// The default memory allocator provided by the operating system. +/// +/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows, +/// plus related functions. +/// +/// This type implements the `GlobalAlloc` trait and Rust programs by deafult +/// work as if they had this definition: +/// +/// ```rust +/// use std::alloc::System; +/// +/// #[global_allocator] +/// static A: System = System; +/// +/// fn main() { +/// let a = Box::new(4); // Allocates from the system allocator. +/// println!("{}", a); +/// } +/// ``` +/// +/// You can also define your own wrapper around `System` if you'd like, such as +/// keeping track of the number of all bytes allocated: +/// +/// ```rust +/// use std::alloc::{System, GlobalAlloc, Layout}; +/// use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering::SeqCst}; +/// +/// struct Counter; +/// +/// static ALLOCATED: AtomicUsize = ATOMIC_USIZE_INIT; +/// +/// unsafe impl GlobalAlloc for Counter { +/// unsafe fn alloc(&self, layout: Layout) -> *mut u8 { +/// let ret = System.alloc(layout); +/// if !ret.is_null() { +/// ALLOCATED.fetch_add(layout.size(), SeqCst); +/// } +/// return ret +/// } +/// +/// unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { +/// System.dealloc(ptr, layout); +/// ALLOCATED.fetch_sub(layout.size(), SeqCst); +/// } +/// } +/// +/// #[global_allocator] +/// static A: Counter = Counter; +/// +/// fn main() { +/// println!("allocated bytes before main: {}", ALLOCATED.load(SeqCst)); +/// } +/// ``` +/// +/// It can also be used directly to allocate memory independently of whatever +/// global allocator has been selected for a Rust program. For example if a Rust +/// program opts in to using jemalloc as the global allocator, `System` will +/// still allocate memory using `malloc` and `HeapAlloc`. #[stable(feature = "alloc_system_type", since = "1.28.0")] -#[doc(inline)] -pub use alloc_system::System; +#[derive(Debug, Copy, Clone)] +pub struct System; + +#[unstable(feature = "allocator_api", issue = "32838")] +unsafe impl Alloc for System { + #[inline] + unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { + NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr) + } + + #[inline] + unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result, AllocErr> { + NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr) + } + + #[inline] + unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { + GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) + } + + #[inline] + unsafe fn realloc(&mut self, + ptr: NonNull, + layout: Layout, + new_size: usize) -> Result, AllocErr> { + NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr) + } +} static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 0829593505d69..f460d109c894a 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -235,7 +235,6 @@ #![cfg_attr(test, feature(test, update_panic_count))] #![feature(alloc)] #![feature(alloc_error_handler)] -#![feature(alloc_system)] #![feature(allocator_api)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] @@ -316,7 +315,7 @@ #[cfg(stage0)] #[global_allocator] -static ALLOC: alloc_system::System = alloc_system::System; +static ALLOC: alloc::System = alloc::System; // Explicitly import the prelude. The compiler uses this same unstable attribute // to import the prelude implicitly when building crates that depend on std. @@ -337,7 +336,6 @@ pub use core::{unreachable, unimplemented, write, writeln, try}; #[allow(unused_imports)] // macros from `alloc` are not used on all platforms #[macro_use] extern crate alloc as alloc_crate; -extern crate alloc_system; #[doc(masked)] extern crate libc; diff --git a/src/libstd/sys/cloudabi/mod.rs b/src/libstd/sys/cloudabi/mod.rs index 9e943c17fc85f..dfb56472c6c83 100644 --- a/src/libstd/sys/cloudabi/mod.rs +++ b/src/libstd/sys/cloudabi/mod.rs @@ -12,6 +12,8 @@ use io; use libc; use mem; +#[path = "../unix/alloc.rs"] +pub mod alloc; pub mod args; #[cfg(feature = "backtrace")] pub mod backtrace; diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index f943257c68733..edb407ecd23ce 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -15,6 +15,8 @@ use io::{self, ErrorKind}; pub use libc::strlen; pub use self::rand::hashmap_random_keys; +#[path = "../unix/alloc.rs"] +pub mod alloc; pub mod args; #[cfg(feature = "backtrace")] pub mod backtrace; diff --git a/src/libstd/sys/unix/alloc.rs b/src/libstd/sys/unix/alloc.rs new file mode 100644 index 0000000000000..2a7f1934518e1 --- /dev/null +++ b/src/libstd/sys/unix/alloc.rs @@ -0,0 +1,100 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ptr; +use libc; +use sys_common::alloc::{MIN_ALIGN, realloc_fallback}; +use alloc::{GlobalAlloc, Layout, System}; + +#[stable(feature = "alloc_system_type", since = "1.28.0")] +unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + libc::malloc(layout.size()) as *mut u8 + } else { + #[cfg(target_os = "macos")] + { + if layout.align() > (1 << 31) { + return ptr::null_mut() + } + } + aligned_malloc(&layout) + } + } + + #[inline] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + libc::calloc(layout.size(), 1) as *mut u8 + } else { + let ptr = self.alloc(layout.clone()); + if !ptr.is_null() { + ptr::write_bytes(ptr, 0, layout.size()); + } + ptr + } + } + + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { + libc::free(ptr as *mut libc::c_void) + } + + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= new_size { + libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 + } else { + realloc_fallback(self, ptr, layout, new_size) + } + } +} + +#[cfg(any(target_os = "android", + target_os = "hermit", + target_os = "redox", + target_os = "solaris"))] +#[inline] +unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { + // On android we currently target API level 9 which unfortunately + // doesn't have the `posix_memalign` API used below. Instead we use + // `memalign`, but this unfortunately has the property on some systems + // where the memory returned cannot be deallocated by `free`! + // + // Upon closer inspection, however, this appears to work just fine with + // Android, so for this platform we should be fine to call `memalign` + // (which is present in API level 9). Some helpful references could + // possibly be chromium using memalign [1], attempts at documenting that + // memalign + free is ok [2] [3], or the current source of chromium + // which still uses memalign on android [4]. + // + // [1]: https://codereview.chromium.org/10796020/ + // [2]: https://code.google.com/p/android/issues/detail?id=35391 + // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 + // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ + // /memory/aligned_memory.cc + libc::memalign(layout.align(), layout.size()) as *mut u8 +} + +#[cfg(not(any(target_os = "android", + target_os = "hermit", + target_os = "redox", + target_os = "solaris")))] +#[inline] +unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { + let mut out = ptr::null_mut(); + let ret = libc::posix_memalign(&mut out, layout.align(), layout.size()); + if ret != 0 { + ptr::null_mut() + } else { + out as *mut u8 + } +} diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 17214be5b0549..e8101bd0bc964 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -36,6 +36,7 @@ pub use libc::strlen; #[macro_use] pub mod weak; +pub mod alloc; pub mod args; pub mod android; #[cfg(feature = "backtrace")] diff --git a/src/libstd/sys/wasm/alloc.rs b/src/libstd/sys/wasm/alloc.rs new file mode 100644 index 0000000000000..0faa3c9a740f1 --- /dev/null +++ b/src/libstd/sys/wasm/alloc.rs @@ -0,0 +1,105 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This is an implementation of a global allocator on the wasm32 platform when +//! emscripten is not in use. In that situation there's no actual runtime for us +//! to lean on for allocation, so instead we provide our own! +//! +//! The wasm32 instruction set has two instructions for getting the current +//! amount of memory and growing the amount of memory. These instructions are the +//! foundation on which we're able to build an allocator, so we do so! Note that +//! the instructions are also pretty "global" and this is the "global" allocator +//! after all! +//! +//! The current allocator here is the `dlmalloc` crate which we've got included +//! in the rust-lang/rust repository as a submodule. The crate is a port of +//! dlmalloc.c from C to Rust and is basically just so we can have "pure Rust" +//! for now which is currently technically required (can't link with C yet). +//! +//! The crate itself provides a global allocator which on wasm has no +//! synchronization as there are no threads! + +extern crate dlmalloc; + +use alloc::{GlobalAlloc, Layout, System}; + +static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT; + +#[stable(feature = "alloc_system_type", since = "1.28.0")] +unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let _lock = lock::lock(); + DLMALLOC.malloc(layout.size(), layout.align()) + } + + #[inline] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + let _lock = lock::lock(); + DLMALLOC.calloc(layout.size(), layout.align()) + } + + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + let _lock = lock::lock(); + DLMALLOC.free(ptr, layout.size(), layout.align()) + } + + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + let _lock = lock::lock(); + DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) + } +} + +#[cfg(target_feature = "atomics")] +mod lock { + use arch::wasm32; + use sync::atomic::{AtomicI32, Ordering::SeqCst}; + + static LOCKED: AtomicI32 = AtomicI32::new(0); + + pub struct DropLock; + + pub fn lock() -> DropLock { + loop { + if LOCKED.swap(1, SeqCst) == 0 { + return DropLock + } + unsafe { + let r = wasm32::atomic::wait_i32( + &LOCKED as *const AtomicI32 as *mut i32, + 1, // expected value + -1, // timeout + ); + debug_assert!(r == 0 || r == 1); + } + } + } + + impl Drop for DropLock { + fn drop(&mut self) { + let r = LOCKED.swap(0, SeqCst); + debug_assert_eq!(r, 1); + unsafe { + wasm32::atomic::wake( + &LOCKED as *const AtomicI32 as *mut i32, + 1, // only one thread + ); + } + } + } +} + +#[cfg(not(target_feature = "atomics"))] +mod lock { + #[inline] + pub fn lock() {} // no atomics, no threads, that's easy! +} diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs index e11b4d71aaeea..e8f7e32ac9177 100644 --- a/src/libstd/sys/wasm/mod.rs +++ b/src/libstd/sys/wasm/mod.rs @@ -32,6 +32,7 @@ use sys_common::{AsInner, FromInner}; use ffi::{OsString, OsStr}; use time::Duration; +pub mod alloc; pub mod args; #[cfg(feature = "backtrace")] pub mod backtrace; diff --git a/src/libstd/sys/windows/alloc.rs b/src/libstd/sys/windows/alloc.rs new file mode 100644 index 0000000000000..e5de3e016c99b --- /dev/null +++ b/src/libstd/sys/windows/alloc.rs @@ -0,0 +1,77 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use alloc::{GlobalAlloc, Layout, System}; +use sys::c; +use sys_common::alloc::{MIN_ALIGN, realloc_fallback}; + +#[repr(C)] +struct Header(*mut u8); + +unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header { + &mut *(ptr as *mut Header).offset(-1) +} + +unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { + let aligned = ptr.add(align - (ptr as usize & (align - 1))); + *get_header(aligned) = Header(ptr); + aligned +} + +#[inline] +unsafe fn allocate_with_flags(layout: Layout, flags: c::DWORD) -> *mut u8 { + if layout.align() <= MIN_ALIGN { + return c::HeapAlloc(c::GetProcessHeap(), flags, layout.size()) as *mut u8 + } + + let size = layout.size() + layout.align(); + let ptr = c::HeapAlloc(c::GetProcessHeap(), flags, size); + if ptr.is_null() { + ptr as *mut u8 + } else { + align_ptr(ptr as *mut u8, layout.align()) + } +} + +#[stable(feature = "alloc_system_type", since = "1.28.0")] +unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + allocate_with_flags(layout, 0) + } + + #[inline] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + allocate_with_flags(layout, c::HEAP_ZERO_MEMORY) + } + + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + if layout.align() <= MIN_ALIGN { + let err = c::HeapFree(c::GetProcessHeap(), 0, ptr as c::LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", + c::GetLastError()); + } else { + let header = get_header(ptr); + let err = c::HeapFree(c::GetProcessHeap(), 0, header.0 as c::LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", + c::GetLastError()); + } + } + + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + if layout.align() <= MIN_ALIGN { + c::HeapReAlloc(c::GetProcessHeap(), 0, ptr as c::LPVOID, new_size) as *mut u8 + } else { + realloc_fallback(self, ptr, layout, new_size) + } + } +} diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index f4bd9c22bb93f..c84874a3e880f 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -309,6 +309,8 @@ pub const FD_SETSIZE: usize = 64; pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000; +pub const HEAP_ZERO_MEMORY: DWORD = 0x00000008; + #[repr(C)] #[cfg(not(target_pointer_width = "64"))] pub struct WSADATA { @@ -1277,6 +1279,11 @@ extern "system" { #[link_name = "SystemFunction036"] pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; + + pub fn GetProcessHeap() -> HANDLE; + pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; + pub fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID; + pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; } // Functions that aren't available on every version of Windows that we support, diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 31ef9fa2bedfd..f880bc8c050be 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -22,6 +22,7 @@ pub use self::rand::hashmap_random_keys; #[macro_use] pub mod compat; +pub mod alloc; pub mod args; #[cfg(feature = "backtrace")] pub mod backtrace; diff --git a/src/libstd/sys_common/alloc.rs b/src/libstd/sys_common/alloc.rs new file mode 100644 index 0000000000000..439a9dfb3fdb5 --- /dev/null +++ b/src/libstd/sys_common/alloc.rs @@ -0,0 +1,50 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +use alloc::{GlobalAlloc, Layout, System}; +use cmp; +use ptr; + +// The minimum alignment guaranteed by the architecture. This value is used to +// add fast paths for low alignment values. +#[cfg(all(any(target_arch = "x86", + target_arch = "arm", + target_arch = "mips", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "asmjs", + target_arch = "wasm32")))] +pub const MIN_ALIGN: usize = 8; +#[cfg(all(any(target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "mips64", + target_arch = "s390x", + target_arch = "sparc64")))] +pub const MIN_ALIGN: usize = 16; + +pub unsafe fn realloc_fallback( + alloc: &System, + ptr: *mut u8, + old_layout: Layout, + new_size: usize, +) -> *mut u8 { + // Docs for GlobalAlloc::realloc require this to be valid: + let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align()); + + let new_ptr = GlobalAlloc::alloc(alloc, new_layout); + if !new_ptr.is_null() { + let size = cmp::min(old_layout.size(), new_size); + ptr::copy_nonoverlapping(ptr, new_ptr, size); + GlobalAlloc::dealloc(alloc, ptr, old_layout); + } + new_ptr +} diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index d0c4d6a773746..4b8cde3d1f486 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -38,6 +38,7 @@ macro_rules! rtassert { }) } +pub mod alloc; pub mod at_exit_imp; #[cfg(feature = "backtrace")] pub mod backtrace; diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index e8f197ba78afe..12e9a54da5281 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -27,7 +27,6 @@ //! //! - core may not have platform-specific code //! - libcompiler_builtins may have platform-specific code -//! - liballoc_system may have platform-specific code //! - libpanic_abort may have platform-specific code //! - libpanic_unwind may have platform-specific code //! - libunwind may have platform-specific code @@ -51,7 +50,6 @@ use std::iter::Iterator; // Paths that may contain platform-specific code const EXCEPTION_PATHS: &[&str] = &[ // std crates - "src/liballoc_system", "src/libcompiler_builtins", "src/liblibc", "src/libpanic_abort",