mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 12:18:33 +00:00
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.
This commit is contained in:
commit
ca79ecd694
@ -15,16 +15,6 @@ dependencies = [
|
||||
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloc_system"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"compiler_builtins 0.0.0",
|
||||
"core 0.0.0",
|
||||
"dlmalloc 0.0.0",
|
||||
"libc 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ammonia"
|
||||
version = "1.1.0"
|
||||
@ -2104,7 +2094,6 @@ name = "rustc_asan"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc 0.0.0",
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"compiler_builtins 0.0.0",
|
||||
@ -2276,7 +2265,6 @@ name = "rustc_lsan"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc 0.0.0",
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"compiler_builtins 0.0.0",
|
||||
@ -2328,7 +2316,6 @@ name = "rustc_msan"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc 0.0.0",
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"compiler_builtins 0.0.0",
|
||||
@ -2440,7 +2427,6 @@ name = "rustc_tsan"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc 0.0.0",
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"compiler_builtins 0.0.0",
|
||||
@ -2679,11 +2665,11 @@ name = "std"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc 0.0.0",
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"compiler_builtins 0.0.0",
|
||||
"core 0.0.0",
|
||||
"dlmalloc 0.0.0",
|
||||
"libc 0.0.0",
|
||||
"panic_abort 0.0.0",
|
||||
"panic_unwind 0.0.0",
|
||||
|
@ -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",
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM ubuntu:16.04
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
g++ \
|
||||
|
@ -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]
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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" }
|
@ -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!
|
||||
}
|
||||
}
|
@ -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]) {
|
||||
|
@ -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())),
|
||||
|
@ -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" }
|
||||
|
@ -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;
|
||||
|
@ -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" }
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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" }
|
||||
|
@ -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;
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -21,7 +21,6 @@ pub fn opts() -> TargetOptions {
|
||||
]);
|
||||
|
||||
TargetOptions {
|
||||
exe_allocation_crate: None,
|
||||
executables: true,
|
||||
has_elf_tls: true,
|
||||
linker_is_gnu: true,
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
},
|
||||
})
|
||||
|
@ -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()
|
||||
},
|
||||
})
|
||||
|
@ -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()
|
||||
},
|
||||
})
|
||||
|
@ -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(),
|
||||
|
@ -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()
|
||||
},
|
||||
})
|
||||
|
@ -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()
|
||||
},
|
||||
})
|
||||
|
@ -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(),
|
||||
|
@ -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()
|
||||
},
|
||||
})
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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 {
|
||||
|
@ -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" }
|
||||
|
@ -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;
|
||||
|
@ -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" }
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
100
src/libstd/sys/unix/alloc.rs
Normal file
100
src/libstd/sys/unix/alloc.rs
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -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")]
|
||||
|
105
src/libstd/sys/wasm/alloc.rs
Normal file
105
src/libstd/sys/wasm/alloc.rs
Normal file
@ -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!
|
||||
}
|
@ -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;
|
||||
|
77
src/libstd/sys/windows/alloc.rs
Normal file
77
src/libstd/sys/windows/alloc.rs
Normal file
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -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;
|
||||
|
50
src/libstd/sys_common/alloc.rs
Normal file
50
src/libstd/sys_common/alloc.rs
Normal file
@ -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
|
||||
}
|
@ -38,6 +38,7 @@ macro_rules! rtassert {
|
||||
})
|
||||
}
|
||||
|
||||
pub mod alloc;
|
||||
pub mod at_exit_imp;
|
||||
#[cfg(feature = "backtrace")]
|
||||
pub mod backtrace;
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user