Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cc75903

Browse files
committedNov 11, 2018
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.
1 parent d393932 commit cc75903

File tree

31 files changed

+450
-508
lines changed

31 files changed

+450
-508
lines changed
 

‎src/Cargo.lock

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,6 @@ dependencies = [
1515
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
1616
]
1717

18-
[[package]]
19-
name = "alloc_system"
20-
version = "0.0.0"
21-
dependencies = [
22-
"compiler_builtins 0.0.0",
23-
"core 0.0.0",
24-
"dlmalloc 0.0.0",
25-
"libc 0.0.0",
26-
]
27-
2818
[[package]]
2919
name = "ammonia"
3020
version = "1.1.0"
@@ -2104,7 +2094,6 @@ name = "rustc_asan"
21042094
version = "0.0.0"
21052095
dependencies = [
21062096
"alloc 0.0.0",
2107-
"alloc_system 0.0.0",
21082097
"build_helper 0.1.0",
21092098
"cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
21102099
"compiler_builtins 0.0.0",
@@ -2276,7 +2265,6 @@ name = "rustc_lsan"
22762265
version = "0.0.0"
22772266
dependencies = [
22782267
"alloc 0.0.0",
2279-
"alloc_system 0.0.0",
22802268
"build_helper 0.1.0",
22812269
"cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
22822270
"compiler_builtins 0.0.0",
@@ -2328,7 +2316,6 @@ name = "rustc_msan"
23282316
version = "0.0.0"
23292317
dependencies = [
23302318
"alloc 0.0.0",
2331-
"alloc_system 0.0.0",
23322319
"build_helper 0.1.0",
23332320
"cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
23342321
"compiler_builtins 0.0.0",
@@ -2440,7 +2427,6 @@ name = "rustc_tsan"
24402427
version = "0.0.0"
24412428
dependencies = [
24422429
"alloc 0.0.0",
2443-
"alloc_system 0.0.0",
24442430
"build_helper 0.1.0",
24452431
"cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
24462432
"compiler_builtins 0.0.0",
@@ -2679,11 +2665,11 @@ name = "std"
26792665
version = "0.0.0"
26802666
dependencies = [
26812667
"alloc 0.0.0",
2682-
"alloc_system 0.0.0",
26832668
"build_helper 0.1.0",
26842669
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
26852670
"compiler_builtins 0.0.0",
26862671
"core 0.0.0",
2672+
"dlmalloc 0.0.0",
26872673
"libc 0.0.0",
26882674
"panic_abort 0.0.0",
26892675
"panic_unwind 0.0.0",

‎src/bootstrap/dist.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,6 @@ impl Step for Src {
859859
"src/build_helper",
860860
"src/dlmalloc",
861861
"src/liballoc",
862-
"src/liballoc_system",
863862
"src/libbacktrace",
864863
"src/libcompiler_builtins",
865864
"src/libcore",

‎src/ci/docker/wasm32-unknown/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM ubuntu:16.04
1+
FROM ubuntu:18.04
22

33
RUN apt-get update && apt-get install -y --no-install-recommends \
44
g++ \

‎src/liballoc/tests/heap.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use alloc_system::System;
12-
use std::alloc::{Global, Alloc, Layout};
11+
use std::alloc::{Global, Alloc, Layout, System};
1312

1413
/// https://github.com/rust-lang/rust/issues/45955
1514
#[test]

‎src/liballoc/tests/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
// except according to those terms.
1010

1111
#![feature(allocator_api)]
12-
#![feature(alloc_system)]
1312
#![feature(box_syntax)]
1413
#![feature(drain_filter)]
1514
#![feature(exact_size_is_empty)]
@@ -20,7 +19,6 @@
2019
#![feature(unboxed_closures)]
2120
#![feature(repeat_generic_slice)]
2221

23-
extern crate alloc_system;
2422
extern crate core;
2523
extern crate rand;
2624

‎src/liballoc_system/Cargo.toml

Lines changed: 0 additions & 19 deletions
This file was deleted.

‎src/liballoc_system/lib.rs

Lines changed: 0 additions & 410 deletions
This file was deleted.

‎src/librustc_asan/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,5 @@ cmake = "0.1.18"
1515

1616
[dependencies]
1717
alloc = { path = "../liballoc" }
18-
alloc_system = { path = "../liballoc_system" }
1918
core = { path = "../libcore" }
2019
compiler_builtins = { path = "../rustc/compiler_builtins_shim" }

‎src/librustc_asan/lib.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,10 @@
99
// except according to those terms.
1010

1111
#![sanitizer_runtime]
12-
#![feature(alloc_system)]
1312
#![feature(nll)]
1413
#![feature(sanitizer_runtime)]
1514
#![feature(staged_api)]
1615
#![no_std]
1716
#![unstable(feature = "sanitizer_runtime_lib",
1817
reason = "internal implementation detail of sanitizers",
1918
issue = "0")]
20-
21-
extern crate alloc_system;
22-
23-
use alloc_system::System;
24-
25-
#[global_allocator]
26-
static ALLOC: System = System;

‎src/librustc_lsan/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,5 @@ cmake = "0.1.18"
1515

1616
[dependencies]
1717
alloc = { path = "../liballoc" }
18-
alloc_system = { path = "../liballoc_system" }
1918
core = { path = "../libcore" }
2019
compiler_builtins = { path = "../rustc/compiler_builtins_shim" }

‎src/librustc_lsan/lib.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,10 @@
99
// except according to those terms.
1010

1111
#![sanitizer_runtime]
12-
#![feature(alloc_system)]
1312
#![feature(nll)]
1413
#![feature(sanitizer_runtime)]
1514
#![feature(staged_api)]
1615
#![no_std]
1716
#![unstable(feature = "sanitizer_runtime_lib",
1817
reason = "internal implementation detail of sanitizers",
1918
issue = "0")]
20-
21-
extern crate alloc_system;
22-
23-
use alloc_system::System;
24-
25-
#[global_allocator]
26-
static ALLOC: System = System;

‎src/librustc_metadata/creader.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use decoder::proc_macro_def_path_table;
1616
use schema::CrateRoot;
1717
use rustc_data_structures::sync::{Lrc, RwLock, Lock};
1818

19-
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX};
19+
use rustc::hir::def_id::CrateNum;
2020
use rustc_data_structures::svh::Svh;
2121
use rustc::middle::allocator::AllocatorKind;
2222
use rustc::middle::cstore::DepKind;
@@ -871,17 +871,14 @@ impl<'a> CrateLoader<'a> {
871871
// At this point we've determined that we need an allocator. Let's see
872872
// if our compilation session actually needs an allocator based on what
873873
// we're emitting.
874-
let mut all_rlib = true;
875-
for ct in self.sess.crate_types.borrow().iter() {
876-
match *ct {
877-
config::CrateType::Executable |
878-
config::CrateType::Dylib |
879-
config::CrateType::ProcMacro |
880-
config::CrateType::Cdylib |
881-
config::CrateType::Staticlib => all_rlib = false,
882-
config::CrateType::Rlib => {}
883-
}
884-
}
874+
let all_rlib = self.sess.crate_types.borrow()
875+
.iter()
876+
.all(|ct| {
877+
match *ct {
878+
config::CrateType::Rlib => true,
879+
_ => false,
880+
}
881+
});
885882
if all_rlib {
886883
self.sess.allocator_kind.set(None);
887884
return
@@ -1004,8 +1001,6 @@ impl<'a> CrateLoader<'a> {
10041001

10051002
impl<'a> CrateLoader<'a> {
10061003
pub fn postprocess(&mut self, krate: &ast::Crate) {
1007-
// inject the sanitizer runtime before the allocator runtime because all
1008-
// sanitizers force the use of the `alloc_system` allocator
10091004
self.inject_sanitizer_runtime();
10101005
self.inject_profiler_runtime();
10111006
self.inject_allocator_crate(krate);

‎src/librustc_msan/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,5 @@ cmake = "0.1.18"
1515

1616
[dependencies]
1717
alloc = { path = "../liballoc" }
18-
alloc_system = { path = "../liballoc_system" }
1918
core = { path = "../libcore" }
2019
compiler_builtins = { path = "../rustc/compiler_builtins_shim" }

‎src/librustc_msan/lib.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,10 @@
99
// except according to those terms.
1010

1111
#![sanitizer_runtime]
12-
#![feature(alloc_system)]
1312
#![feature(nll)]
1413
#![feature(sanitizer_runtime)]
1514
#![feature(staged_api)]
1615
#![no_std]
1716
#![unstable(feature = "sanitizer_runtime_lib",
1817
reason = "internal implementation detail of sanitizers",
1918
issue = "0")]
20-
21-
extern crate alloc_system;
22-
23-
use alloc_system::System;
24-
25-
#[global_allocator]
26-
static ALLOC: System = System;

‎src/librustc_tsan/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,5 @@ cmake = "0.1.18"
1515

1616
[dependencies]
1717
alloc = { path = "../liballoc" }
18-
alloc_system = { path = "../liballoc_system" }
1918
core = { path = "../libcore" }
2019
compiler_builtins = { path = "../rustc/compiler_builtins_shim" }

‎src/librustc_tsan/lib.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,10 @@
99
// except according to those terms.
1010

1111
#![sanitizer_runtime]
12-
#![feature(alloc_system)]
1312
#![feature(nll)]
1413
#![feature(sanitizer_runtime)]
1514
#![feature(staged_api)]
1615
#![no_std]
1716
#![unstable(feature = "sanitizer_runtime_lib",
1817
reason = "internal implementation detail of sanitizers",
1918
issue = "0")]
20-
21-
extern crate alloc_system;
22-
23-
use alloc_system::System;
24-
25-
#[global_allocator]
26-
static ALLOC: System = System;

‎src/libstd/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ crate-type = ["dylib", "rlib"]
1414

1515
[dependencies]
1616
alloc = { path = "../liballoc" }
17-
alloc_system = { path = "../liballoc_system" }
1817
panic_unwind = { path = "../libpanic_unwind", optional = true }
1918
panic_abort = { path = "../libpanic_abort" }
2019
core = { path = "../libcore" }
@@ -36,6 +35,9 @@ rustc_lsan = { path = "../librustc_lsan" }
3635
rustc_msan = { path = "../librustc_msan" }
3736
rustc_tsan = { path = "../librustc_tsan" }
3837

38+
[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies]
39+
dlmalloc = { path = '../rustc/dlmalloc_shim' }
40+
3941
[build-dependencies]
4042
cc = "1.0"
4143
build_helper = { path = "../build_helper" }

‎src/libstd/alloc.rs

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,100 @@
7373

7474
use core::sync::atomic::{AtomicPtr, Ordering};
7575
use core::{mem, ptr};
76+
use core::ptr::NonNull;
7677
use sys_common::util::dumb_print;
7778

7879
#[stable(feature = "alloc_module", since = "1.28.0")]
7980
#[doc(inline)]
8081
pub use alloc_crate::alloc::*;
8182

83+
/// The default memory allocator provided by the operating system.
84+
///
85+
/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
86+
/// plus related functions.
87+
///
88+
/// This type implements the `GlobalAlloc` trait and Rust programs by deafult
89+
/// work as if they had this definition:
90+
///
91+
/// ```rust
92+
/// use std::alloc::System;
93+
///
94+
/// #[global_allocator]
95+
/// static A: System = System;
96+
///
97+
/// fn main() {
98+
/// let a = Box::new(4); // Allocates from the system allocator.
99+
/// println!("{}", a);
100+
/// }
101+
/// ```
102+
///
103+
/// You can also define your own wrapper around `System` if you'd like, such as
104+
/// keeping track of the number of all bytes allocated:
105+
///
106+
/// ```rust
107+
/// use std::alloc::{System, GlobalAlloc, Layout};
108+
/// use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering::SeqCst};
109+
///
110+
/// struct Counter;
111+
///
112+
/// static ALLOCATED: AtomicUsize = ATOMIC_USIZE_INIT;
113+
///
114+
/// unsafe impl GlobalAlloc for Counter {
115+
/// unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
116+
/// let ret = System.alloc(layout);
117+
/// if !ret.is_null() {
118+
/// ALLOCATED.fetch_add(layout.size(), SeqCst);
119+
/// }
120+
/// return ret
121+
/// }
122+
///
123+
/// unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
124+
/// System.dealloc(ptr, layout);
125+
/// ALLOCATED.fetch_sub(layout.size(), SeqCst);
126+
/// }
127+
/// }
128+
///
129+
/// #[global_allocator]
130+
/// static A: Counter = Counter;
131+
///
132+
/// fn main() {
133+
/// println!("allocated bytes before main: {}", ALLOCATED.load(SeqCst));
134+
/// }
135+
/// ```
136+
///
137+
/// It can also be used directly to allocate memory independently of whatever
138+
/// global allocator has been selected for a Rust program. For example if a Rust
139+
/// program opts in to using jemalloc as the global allocator, `System` will
140+
/// still allocate memory using `malloc` and `HeapAlloc`.
82141
#[stable(feature = "alloc_system_type", since = "1.28.0")]
83-
#[doc(inline)]
84-
pub use alloc_system::System;
142+
#[derive(Debug, Copy, Clone)]
143+
pub struct System;
144+
145+
#[unstable(feature = "allocator_api", issue = "32838")]
146+
unsafe impl Alloc for System {
147+
#[inline]
148+
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
149+
NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
150+
}
151+
152+
#[inline]
153+
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
154+
NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
155+
}
156+
157+
#[inline]
158+
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
159+
GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
160+
}
161+
162+
#[inline]
163+
unsafe fn realloc(&mut self,
164+
ptr: NonNull<u8>,
165+
layout: Layout,
166+
new_size: usize) -> Result<NonNull<u8>, AllocErr> {
167+
NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
168+
}
169+
}
85170

86171
static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
87172

‎src/libstd/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@
235235
#![cfg_attr(test, feature(test, update_panic_count))]
236236
#![feature(alloc)]
237237
#![feature(alloc_error_handler)]
238-
#![feature(alloc_system)]
239238
#![feature(allocator_api)]
240239
#![feature(allocator_internals)]
241240
#![feature(allow_internal_unsafe)]
@@ -316,7 +315,7 @@
316315

317316
#[cfg(stage0)]
318317
#[global_allocator]
319-
static ALLOC: alloc_system::System = alloc_system::System;
318+
static ALLOC: alloc::System = alloc::System;
320319

321320
// Explicitly import the prelude. The compiler uses this same unstable attribute
322321
// to import the prelude implicitly when building crates that depend on std.
@@ -337,7 +336,6 @@ pub use core::{unreachable, unimplemented, write, writeln, try};
337336
#[allow(unused_imports)] // macros from `alloc` are not used on all platforms
338337
#[macro_use]
339338
extern crate alloc as alloc_crate;
340-
extern crate alloc_system;
341339
#[doc(masked)]
342340
extern crate libc;
343341

‎src/libstd/sys/cloudabi/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use io;
1212
use libc;
1313
use mem;
1414

15+
#[path = "../unix/alloc.rs"]
16+
pub mod alloc;
1517
pub mod args;
1618
#[cfg(feature = "backtrace")]
1719
pub mod backtrace;

‎src/libstd/sys/redox/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use io::{self, ErrorKind};
1515
pub use libc::strlen;
1616
pub use self::rand::hashmap_random_keys;
1717

18+
#[path = "../unix/alloc.rs"]
19+
pub mod alloc;
1820
pub mod args;
1921
#[cfg(feature = "backtrace")]
2022
pub mod backtrace;

‎src/libstd/sys/unix/alloc.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use ptr;
12+
use libc;
13+
use sys_common::alloc::{MIN_ALIGN, realloc_fallback};
14+
use alloc::{GlobalAlloc, Layout, System};
15+
16+
#[stable(feature = "alloc_system_type", since = "1.28.0")]
17+
unsafe impl GlobalAlloc for System {
18+
#[inline]
19+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
20+
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
21+
libc::malloc(layout.size()) as *mut u8
22+
} else {
23+
#[cfg(target_os = "macos")]
24+
{
25+
if layout.align() > (1 << 31) {
26+
return ptr::null_mut()
27+
}
28+
}
29+
aligned_malloc(&layout)
30+
}
31+
}
32+
33+
#[inline]
34+
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
35+
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
36+
libc::calloc(layout.size(), 1) as *mut u8
37+
} else {
38+
let ptr = self.alloc(layout.clone());
39+
if !ptr.is_null() {
40+
ptr::write_bytes(ptr, 0, layout.size());
41+
}
42+
ptr
43+
}
44+
}
45+
46+
#[inline]
47+
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
48+
libc::free(ptr as *mut libc::c_void)
49+
}
50+
51+
#[inline]
52+
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
53+
if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
54+
libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
55+
} else {
56+
realloc_fallback(self, ptr, layout, new_size)
57+
}
58+
}
59+
}
60+
61+
#[cfg(any(target_os = "android",
62+
target_os = "hermit",
63+
target_os = "redox",
64+
target_os = "solaris"))]
65+
#[inline]
66+
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
67+
// On android we currently target API level 9 which unfortunately
68+
// doesn't have the `posix_memalign` API used below. Instead we use
69+
// `memalign`, but this unfortunately has the property on some systems
70+
// where the memory returned cannot be deallocated by `free`!
71+
//
72+
// Upon closer inspection, however, this appears to work just fine with
73+
// Android, so for this platform we should be fine to call `memalign`
74+
// (which is present in API level 9). Some helpful references could
75+
// possibly be chromium using memalign [1], attempts at documenting that
76+
// memalign + free is ok [2] [3], or the current source of chromium
77+
// which still uses memalign on android [4].
78+
//
79+
// [1]: https://codereview.chromium.org/10796020/
80+
// [2]: https://code.google.com/p/android/issues/detail?id=35391
81+
// [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
82+
// [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
83+
// /memory/aligned_memory.cc
84+
libc::memalign(layout.align(), layout.size()) as *mut u8
85+
}
86+
87+
#[cfg(not(any(target_os = "android",
88+
target_os = "hermit",
89+
target_os = "redox",
90+
target_os = "solaris")))]
91+
#[inline]
92+
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
93+
let mut out = ptr::null_mut();
94+
let ret = libc::posix_memalign(&mut out, layout.align(), layout.size());
95+
if ret != 0 {
96+
ptr::null_mut()
97+
} else {
98+
out as *mut u8
99+
}
100+
}

‎src/libstd/sys/unix/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub use libc::strlen;
3636
#[macro_use]
3737
pub mod weak;
3838

39+
pub mod alloc;
3940
pub mod args;
4041
pub mod android;
4142
#[cfg(feature = "backtrace")]

‎src/libstd/sys/wasm/alloc.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! This is an implementation of a global allocator on the wasm32 platform when
12+
//! emscripten is not in use. In that situation there's no actual runtime for us
13+
//! to lean on for allocation, so instead we provide our own!
14+
//!
15+
//! The wasm32 instruction set has two instructions for getting the current
16+
//! amount of memory and growing the amount of memory. These instructions are the
17+
//! foundation on which we're able to build an allocator, so we do so! Note that
18+
//! the instructions are also pretty "global" and this is the "global" allocator
19+
//! after all!
20+
//!
21+
//! The current allocator here is the `dlmalloc` crate which we've got included
22+
//! in the rust-lang/rust repository as a submodule. The crate is a port of
23+
//! dlmalloc.c from C to Rust and is basically just so we can have "pure Rust"
24+
//! for now which is currently technically required (can't link with C yet).
25+
//!
26+
//! The crate itself provides a global allocator which on wasm has no
27+
//! synchronization as there are no threads!
28+
29+
extern crate dlmalloc;
30+
31+
use alloc::{GlobalAlloc, Layout, System};
32+
33+
static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
34+
35+
#[stable(feature = "alloc_system_type", since = "1.28.0")]
36+
unsafe impl GlobalAlloc for System {
37+
#[inline]
38+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
39+
let _lock = lock::lock();
40+
DLMALLOC.malloc(layout.size(), layout.align())
41+
}
42+
43+
#[inline]
44+
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
45+
let _lock = lock::lock();
46+
DLMALLOC.calloc(layout.size(), layout.align())
47+
}
48+
49+
#[inline]
50+
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
51+
let _lock = lock::lock();
52+
DLMALLOC.free(ptr, layout.size(), layout.align())
53+
}
54+
55+
#[inline]
56+
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
57+
let _lock = lock::lock();
58+
DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size)
59+
}
60+
}
61+
62+
#[cfg(target_feature = "atomics")]
63+
mod lock {
64+
use arch::wasm32;
65+
use sync::atomic::{AtomicI32, Ordering::SeqCst};
66+
67+
static LOCKED: AtomicI32 = AtomicI32::new(0);
68+
69+
pub struct DropLock;
70+
71+
pub fn lock() -> DropLock {
72+
loop {
73+
if LOCKED.swap(1, SeqCst) == 0 {
74+
return DropLock
75+
}
76+
unsafe {
77+
let r = wasm32::atomic::wait_i32(
78+
&LOCKED as *const AtomicI32 as *mut i32,
79+
1, // expected value
80+
-1, // timeout
81+
);
82+
debug_assert!(r == 0 || r == 1);
83+
}
84+
}
85+
}
86+
87+
impl Drop for DropLock {
88+
fn drop(&mut self) {
89+
let r = LOCKED.swap(0, SeqCst);
90+
debug_assert_eq!(r, 1);
91+
unsafe {
92+
wasm32::atomic::wake(
93+
&LOCKED as *const AtomicI32 as *mut i32,
94+
1, // only one thread
95+
);
96+
}
97+
}
98+
}
99+
}
100+
101+
#[cfg(not(target_feature = "atomics"))]
102+
mod lock {
103+
#[inline]
104+
pub fn lock() {} // no atomics, no threads, that's easy!
105+
}

‎src/libstd/sys/wasm/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use sys_common::{AsInner, FromInner};
3232
use ffi::{OsString, OsStr};
3333
use time::Duration;
3434

35+
pub mod alloc;
3536
pub mod args;
3637
#[cfg(feature = "backtrace")]
3738
pub mod backtrace;

‎src/libstd/sys/windows/alloc.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use alloc::{GlobalAlloc, Layout, System};
12+
use sys::c;
13+
use sys_common::alloc::{MIN_ALIGN, realloc_fallback};
14+
15+
#[repr(C)]
16+
struct Header(*mut u8);
17+
18+
unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
19+
&mut *(ptr as *mut Header).offset(-1)
20+
}
21+
22+
unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
23+
let aligned = ptr.add(align - (ptr as usize & (align - 1)));
24+
*get_header(aligned) = Header(ptr);
25+
aligned
26+
}
27+
28+
#[inline]
29+
unsafe fn allocate_with_flags(layout: Layout, flags: c::DWORD) -> *mut u8 {
30+
if layout.align() <= MIN_ALIGN {
31+
return c::HeapAlloc(c::GetProcessHeap(), flags, layout.size()) as *mut u8
32+
}
33+
34+
let size = layout.size() + layout.align();
35+
let ptr = c::HeapAlloc(c::GetProcessHeap(), flags, size);
36+
if ptr.is_null() {
37+
ptr as *mut u8
38+
} else {
39+
align_ptr(ptr as *mut u8, layout.align())
40+
}
41+
}
42+
43+
#[stable(feature = "alloc_system_type", since = "1.28.0")]
44+
unsafe impl GlobalAlloc for System {
45+
#[inline]
46+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
47+
allocate_with_flags(layout, 0)
48+
}
49+
50+
#[inline]
51+
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
52+
allocate_with_flags(layout, c::HEAP_ZERO_MEMORY)
53+
}
54+
55+
#[inline]
56+
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
57+
if layout.align() <= MIN_ALIGN {
58+
let err = c::HeapFree(c::GetProcessHeap(), 0, ptr as c::LPVOID);
59+
debug_assert!(err != 0, "Failed to free heap memory: {}",
60+
c::GetLastError());
61+
} else {
62+
let header = get_header(ptr);
63+
let err = c::HeapFree(c::GetProcessHeap(), 0, header.0 as c::LPVOID);
64+
debug_assert!(err != 0, "Failed to free heap memory: {}",
65+
c::GetLastError());
66+
}
67+
}
68+
69+
#[inline]
70+
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
71+
if layout.align() <= MIN_ALIGN {
72+
c::HeapReAlloc(c::GetProcessHeap(), 0, ptr as c::LPVOID, new_size) as *mut u8
73+
} else {
74+
realloc_fallback(self, ptr, layout, new_size)
75+
}
76+
}
77+
}

‎src/libstd/sys/windows/c.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ pub const FD_SETSIZE: usize = 64;
309309

310310
pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;
311311

312+
pub const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
313+
312314
#[repr(C)]
313315
#[cfg(not(target_pointer_width = "64"))]
314316
pub struct WSADATA {
@@ -1277,6 +1279,11 @@ extern "system" {
12771279

12781280
#[link_name = "SystemFunction036"]
12791281
pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
1282+
1283+
pub fn GetProcessHeap() -> HANDLE;
1284+
pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
1285+
pub fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
1286+
pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
12801287
}
12811288

12821289
// Functions that aren't available on every version of Windows that we support,

‎src/libstd/sys/windows/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub use self::rand::hashmap_random_keys;
2222

2323
#[macro_use] pub mod compat;
2424

25+
pub mod alloc;
2526
pub mod args;
2627
#[cfg(feature = "backtrace")]
2728
pub mod backtrace;

‎src/libstd/sys_common/alloc.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(dead_code)]
12+
13+
use alloc::{GlobalAlloc, Layout, System};
14+
use cmp;
15+
use ptr;
16+
17+
// The minimum alignment guaranteed by the architecture. This value is used to
18+
// add fast paths for low alignment values.
19+
#[cfg(all(any(target_arch = "x86",
20+
target_arch = "arm",
21+
target_arch = "mips",
22+
target_arch = "powerpc",
23+
target_arch = "powerpc64",
24+
target_arch = "asmjs",
25+
target_arch = "wasm32")))]
26+
pub const MIN_ALIGN: usize = 8;
27+
#[cfg(all(any(target_arch = "x86_64",
28+
target_arch = "aarch64",
29+
target_arch = "mips64",
30+
target_arch = "s390x",
31+
target_arch = "sparc64")))]
32+
pub const MIN_ALIGN: usize = 16;
33+
34+
pub unsafe fn realloc_fallback(
35+
alloc: &System,
36+
ptr: *mut u8,
37+
old_layout: Layout,
38+
new_size: usize,
39+
) -> *mut u8 {
40+
// Docs for GlobalAlloc::realloc require this to be valid:
41+
let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
42+
43+
let new_ptr = GlobalAlloc::alloc(alloc, new_layout);
44+
if !new_ptr.is_null() {
45+
let size = cmp::min(old_layout.size(), new_size);
46+
ptr::copy_nonoverlapping(ptr, new_ptr, size);
47+
GlobalAlloc::dealloc(alloc, ptr, old_layout);
48+
}
49+
new_ptr
50+
}

‎src/libstd/sys_common/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ macro_rules! rtassert {
3838
})
3939
}
4040

41+
pub mod alloc;
4142
pub mod at_exit_imp;
4243
#[cfg(feature = "backtrace")]
4344
pub mod backtrace;

‎src/tools/tidy/src/pal.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
//!
2828
//! - core may not have platform-specific code
2929
//! - libcompiler_builtins may have platform-specific code
30-
//! - liballoc_system may have platform-specific code
3130
//! - libpanic_abort may have platform-specific code
3231
//! - libpanic_unwind may have platform-specific code
3332
//! - libunwind may have platform-specific code
@@ -51,7 +50,6 @@ use std::iter::Iterator;
5150
// Paths that may contain platform-specific code
5251
const EXCEPTION_PATHS: &[&str] = &[
5352
// std crates
54-
"src/liballoc_system",
5553
"src/libcompiler_builtins",
5654
"src/liblibc",
5755
"src/libpanic_abort",

0 commit comments

Comments
 (0)
Please sign in to comment.