about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-11-11 19:51:56 +0000
committerbors <bors@rust-lang.org>2018-11-11 19:51:56 +0000
commitca79ecd6940e30d4b2466bf378632efcdf5745c7 (patch)
treee8d30ebe5389de5b10097945fb3e5647b205548e /src
parent5a2ca1a6f18aa93d3120761f614ec2d39b4cb1ac (diff)
parentcc7590341a6ac213909d0ef56a7ebc2834274c8b (diff)
downloadrust-ca79ecd6940e30d4b2466bf378632efcdf5745c7.tar.gz
rust-ca79ecd6940e30d4b2466bf378632efcdf5745c7.zip
Auto merge of #55660 - alexcrichton:cleanup-alloc-system, r=dtolnay,SimonSapin
Remove the `alloc_system` crate

In what's hopefully one of the final nails in the coffin of the "old allocator story of yore" this PR deletes the `alloc_system` crate and all traces of it from the compiler. The compiler no longer needs to inject allocator crates anywhere and the `alloc_system` crate has no real reason to exist outside the standard library.

The unstable `alloc_system` crate is folded directly into the standard library where its stable interface, the `System` type, remains the same. All unstable traces of `alloc_system` are removed, however.
Diffstat (limited to 'src')
-rw-r--r--src/Cargo.lock16
-rw-r--r--src/bootstrap/dist.rs1
-rw-r--r--src/ci/docker/wasm32-unknown/Dockerfile2
-rw-r--r--src/liballoc/tests/heap.rs3
-rw-r--r--src/liballoc/tests/lib.rs2
-rw-r--r--src/liballoc_system/Cargo.toml19
-rw-r--r--src/liballoc_system/lib.rs411
-rw-r--r--src/librustc/middle/dependency_format.rs15
-rw-r--r--src/librustc/session/mod.rs2
-rw-r--r--src/librustc_asan/Cargo.toml1
-rw-r--r--src/librustc_asan/lib.rs8
-rw-r--r--src/librustc_lsan/Cargo.toml1
-rw-r--r--src/librustc_lsan/lib.rs8
-rw-r--r--src/librustc_metadata/creader.rs130
-rw-r--r--src/librustc_msan/Cargo.toml1
-rw-r--r--src/librustc_msan/lib.rs8
-rw-r--r--src/librustc_target/spec/aarch64_unknown_freebsd.rs3
-rw-r--r--src/librustc_target/spec/aarch64_unknown_linux_gnu.rs3
-rw-r--r--src/librustc_target/spec/aarch64_unknown_linux_musl.rs3
-rw-r--r--src/librustc_target/spec/hermit_base.rs1
-rw-r--r--src/librustc_target/spec/l4re_base.rs1
-rw-r--r--src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs3
-rw-r--r--src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs3
-rw-r--r--src/librustc_target/spec/mips_unknown_linux_gnu.rs3
-rw-r--r--src/librustc_target/spec/mips_unknown_linux_musl.rs2
-rw-r--r--src/librustc_target/spec/mips_unknown_linux_uclibc.rs3
-rw-r--r--src/librustc_target/spec/mipsel_unknown_linux_gnu.rs3
-rw-r--r--src/librustc_target/spec/mipsel_unknown_linux_musl.rs2
-rw-r--r--src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs3
-rw-r--r--src/librustc_target/spec/mod.rs6
-rw-r--r--src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs3
-rw-r--r--src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs3
-rw-r--r--src/librustc_target/spec/powerpc64le_unknown_linux_musl.rs3
-rw-r--r--src/librustc_target/spec/powerpc_unknown_linux_gnu.rs3
-rw-r--r--src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs3
-rw-r--r--src/librustc_target/spec/powerpc_unknown_netbsd.rs3
-rw-r--r--src/librustc_target/spec/s390x_unknown_linux_gnu.rs2
-rw-r--r--src/librustc_target/spec/sparc64_unknown_linux_gnu.rs1
-rw-r--r--src/librustc_target/spec/sparc_unknown_linux_gnu.rs1
-rw-r--r--src/librustc_target/spec/sparcv9_sun_solaris.rs1
-rw-r--r--src/librustc_target/spec/x86_64_rumprun_netbsd.rs1
-rw-r--r--src/librustc_tsan/Cargo.toml1
-rw-r--r--src/librustc_tsan/lib.rs8
-rw-r--r--src/libstd/Cargo.toml4
-rw-r--r--src/libstd/alloc.rs89
-rw-r--r--src/libstd/lib.rs4
-rw-r--r--src/libstd/sys/cloudabi/mod.rs2
-rw-r--r--src/libstd/sys/redox/mod.rs2
-rw-r--r--src/libstd/sys/unix/alloc.rs100
-rw-r--r--src/libstd/sys/unix/mod.rs1
-rw-r--r--src/libstd/sys/wasm/alloc.rs105
-rw-r--r--src/libstd/sys/wasm/mod.rs1
-rw-r--r--src/libstd/sys/windows/alloc.rs77
-rw-r--r--src/libstd/sys/windows/c.rs7
-rw-r--r--src/libstd/sys/windows/mod.rs1
-rw-r--r--src/libstd/sys_common/alloc.rs50
-rw-r--r--src/libstd/sys_common/mod.rs1
-rw-r--r--src/tools/tidy/src/pal.rs2
58 files changed, 464 insertions, 682 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 2ac51263cb5..32304c81182 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -16,16 +16,6 @@ dependencies = [
 ]
 
 [[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"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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 567b47a70a1..0aab64465fd 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 f2a29b03151..161f0c0062f 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 b6be38107da..bf256b23f9a 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 3294837cb91..e514a8a69c0 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 c34e2f203a8..00000000000
--- 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 0e6887a5082..00000000000
--- a/src/liballoc_system/lib.rs
+++ /dev/null
@@ -1,411 +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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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))]
-#![rustc_alloc_kind = "lib"]
-
-// 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<NonNull<u8>, AllocErr> {
-        NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
-    }
-
-    #[inline]
-    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
-        NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
-    }
-
-    #[inline]
-    unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
-        GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
-    }
-
-    #[inline]
-    unsafe fn realloc(&mut self,
-                      ptr: NonNull<u8>,
-                      layout: Layout,
-                      new_size: usize) -> Result<NonNull<u8>, 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/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index e3f9c51a123..671f513d5b9 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<DependencyLis
     // that here and activate them.
     activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret,
                           &|cnum| tcx.is_panic_runtime(cnum));
-    activate_injected_allocator(sess, &mut ret);
 
     Some(ret)
 }
@@ -336,18 +333,6 @@ fn activate_injected_dep(injected: Option<CrateNum>,
     }
 }
 
-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 efd7e8b610e..8cfbd27fc61 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<Option<CrateNum>>,
     pub allocator_kind: Once<Option<AllocatorKind>>,
     pub injected_panic_runtime: Once<Option<CrateNum>>,
 
@@ -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_asan/Cargo.toml b/src/librustc_asan/Cargo.toml
index 34d8b75a5bf..734564c2d85 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 7b845e631ff..47f917e40c1 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 9c19b537426..2573825a5ff 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 7b845e631ff..47f917e40c1 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 7733ab2e246..a14dd99eeb3 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;
@@ -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,15 @@ 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;
-        for ct in self.sess.crate_types.borrow().iter() {
-            match *ct {
-                config::CrateType::Executable => need_exe_alloc = true,
-                config::CrateType::Dylib |
-                config::CrateType::ProcMacro |
-                config::CrateType::Cdylib |
-                config::CrateType::Staticlib => need_lib_alloc = true,
-                config::CrateType::Rlib => {}
-            }
-        }
-        if !need_lib_alloc && !need_exe_alloc {
-            self.sess.injected_allocator.set(None);
+        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
         }
@@ -924,103 +918,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);
@@ -1083,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 17ec2b96438..29165675a2a 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 7b845e631ff..47f917e40c1 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_target/spec/aarch64_unknown_freebsd.rs b/src/librustc_target/spec/aarch64_unknown_freebsd.rs
index 541f0564a01..b120f57192b 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 2351d014692..af7ec6a1787 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 5ab55a076f4..e5ca91aabe5 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 2a24f771e92..168eac685e4 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 4ebc930d48b..7932adf3b10 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 1f60d918908..b80b6b561cd 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 e42fde8d403..1c835af6e41 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 59e15137cf4..6331031c9a2 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 8ee399ba56c..0b20765172a 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 384ab1e4131..d3f614c982a 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 edd29164cac..79ebefa79a3 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 1d9378ca1b8..042e2b71c32 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 a1db1791bb7..8cb5cd3f03a 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 c8af81c02ea..16dc2a91030 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<String>,
-
     /// 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 19598711613..1d0afcd5e0c 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 39840692dff..01811c5a0c3 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 34ec8241228..590c5ba8d54 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 c05b110a75d..99d8d99fbb2 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 c76c3119c87..9b15b0a5dc4 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 740222c9608..98625a63f52 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 c9a9625ebab..bd8b7e435d3 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 f68b5fd24bf..f2b99aa46d2 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 4e352374f90..81db39cd23f 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 8bc233107b8..5029e857eb5 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 684bf5a6c10..e7570cd2da6 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 {
diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml
index 8bb67c0bbac..baadb64511a 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 7b845e631ff..47f917e40c1 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 0f22459b343..2b1d515c83b 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 1ff342fa7a7..485b2ffe197 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<NonNull<u8>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
+    }
+
+    #[inline]
+    unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
+        GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
+    }
+
+    #[inline]
+    unsafe fn realloc(&mut self,
+                      ptr: NonNull<u8>,
+                      layout: Layout,
+                      new_size: usize) -> Result<NonNull<u8>, 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 0829593505d..f460d109c89 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 9e943c17fc8..dfb56472c6c 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 f943257c687..edb407ecd23 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 00000000000..2a7f1934518
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 17214be5b05..e8101bd0bc9 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 00000000000..0faa3c9a740
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 e11b4d71aae..e8f7e32ac91 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 00000000000..e5de3e016c9
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 f4bd9c22bb9..c84874a3e88 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 31ef9fa2bed..f880bc8c050 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 00000000000..439a9dfb3fd
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 d0c4d6a7737..4b8cde3d1f4 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 e8f197ba78a..12e9a54da52 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",