]> git.lizzy.rs Git - rust.git/blob - src/liballoc_jemalloc/lib.rs
Auto merge of #54718 - froydnj:aarch64-ci, r=alexcrichton
[rust.git] / src / liballoc_jemalloc / lib.rs
1 // Copyright 2015 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 #![no_std]
12 #![allow(unused_attributes)]
13 #![unstable(feature = "alloc_jemalloc",
14             reason = "implementation detail of std, does not provide any public API",
15             issue = "0")]
16 #![feature(core_intrinsics)]
17 #![feature(libc)]
18 #![feature(linkage)]
19 #![feature(nll)]
20 #![feature(staged_api)]
21 #![feature(rustc_attrs)]
22 #![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
23 #![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
24 #![rustc_alloc_kind = "exe"]
25
26 extern crate libc;
27
28 #[cfg(not(dummy_jemalloc))]
29 pub use contents::*;
30 #[cfg(not(dummy_jemalloc))]
31 mod contents {
32     use libc::{c_int, c_void, size_t};
33
34     // Note that the symbols here are prefixed by default on macOS and Windows (we
35     // don't explicitly request it), and on Android and DragonFly we explicitly
36     // request it as unprefixing cause segfaults (mismatches in allocators).
37     extern "C" {
38         #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
39                        target_os = "dragonfly", target_os = "windows", target_env = "musl"),
40                    link_name = "je_mallocx")]
41         fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
42         #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
43                        target_os = "dragonfly", target_os = "windows", target_env = "musl"),
44                    link_name = "je_calloc")]
45         fn calloc(size: size_t, flags: c_int) -> *mut c_void;
46         #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
47                        target_os = "dragonfly", target_os = "windows", target_env = "musl"),
48                    link_name = "je_rallocx")]
49         fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
50         #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
51                        target_os = "dragonfly", target_os = "windows", target_env = "musl"),
52                    link_name = "je_sdallocx")]
53         fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
54     }
55
56     const MALLOCX_ZERO: c_int = 0x40;
57
58     // The minimum alignment guaranteed by the architecture. This value is used to
59     // add fast paths for low alignment values.
60     #[cfg(all(any(target_arch = "arm",
61                   target_arch = "mips",
62                   target_arch = "powerpc")))]
63     const MIN_ALIGN: usize = 8;
64     #[cfg(all(any(target_arch = "x86",
65                   target_arch = "x86_64",
66                   target_arch = "aarch64",
67                   target_arch = "powerpc64",
68                   target_arch = "mips64",
69                   target_arch = "s390x",
70                   target_arch = "sparc64")))]
71     const MIN_ALIGN: usize = 16;
72
73     // MALLOCX_ALIGN(a) macro
74     fn mallocx_align(a: usize) -> c_int {
75         a.trailing_zeros() as c_int
76     }
77
78     fn align_to_flags(align: usize, size: usize) -> c_int {
79         if align <= MIN_ALIGN && align <= size {
80             0
81         } else {
82             mallocx_align(align)
83         }
84     }
85
86     // for symbol names src/librustc/middle/allocator.rs
87     // for signatures src/librustc_allocator/lib.rs
88
89     // linkage directives are provided as part of the current compiler allocator
90     // ABI
91
92     #[rustc_std_internal_symbol]
93     pub unsafe extern fn __rde_alloc(size: usize, align: usize) -> *mut u8 {
94         let flags = align_to_flags(align, size);
95         let ptr = mallocx(size as size_t, flags) as *mut u8;
96         ptr
97     }
98
99     #[rustc_std_internal_symbol]
100     pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
101                                        size: usize,
102                                        align: usize) {
103         let flags = align_to_flags(align, size);
104         sdallocx(ptr as *mut c_void, size, flags);
105     }
106
107     #[rustc_std_internal_symbol]
108     pub unsafe extern fn __rde_realloc(ptr: *mut u8,
109                                        _old_size: usize,
110                                        align: usize,
111                                        new_size: usize) -> *mut u8 {
112         let flags = align_to_flags(align, new_size);
113         let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
114         ptr
115     }
116
117     #[rustc_std_internal_symbol]
118     pub unsafe extern fn __rde_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
119         let ptr = if align <= MIN_ALIGN && align <= size {
120             calloc(size as size_t, 1) as *mut u8
121         } else {
122             let flags = align_to_flags(align, size) | MALLOCX_ZERO;
123             mallocx(size as size_t, flags) as *mut u8
124         };
125         ptr
126     }
127 }