Skip to content

Commit 8a6878a

Browse files
committed
Auto merge of #135587 - matthiaskrgr:rollup-851qgnh, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #133720 ([cfg_match] Adjust syntax) - #134496 (Update documentation for Arc::from_raw, Arc::increment_strong_count, and Arc::decrement_strong_count to clarify allocator requirement) - #135249 (Fix overflows in the implementation of `overflowing_literals` lint's help) - #135251 (Only treat plain literal patterns as short) - #135556 (Clarify note in `std::sync::LazyLock` example) r? `@ghost` `@rustbot` modify labels: rollup
2 parents d8a6409 + dbbbed0 commit 8a6878a

File tree

12 files changed

+629
-40
lines changed

12 files changed

+629
-40
lines changed

compiler/rustc_data_structures/src/flock.rs

+25
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! green/native threading. This is just a bare-bones enough solution for
55
//! librustdoc, it is not production quality at all.
66
7+
#[cfg(bootstrap)]
78
cfg_match! {
89
cfg(target_os = "linux") => {
910
mod linux;
@@ -27,4 +28,28 @@ cfg_match! {
2728
}
2829
}
2930

31+
#[cfg(not(bootstrap))]
32+
cfg_match! {
33+
target_os = "linux" => {
34+
mod linux;
35+
use linux as imp;
36+
}
37+
target_os = "redox" => {
38+
mod linux;
39+
use linux as imp;
40+
}
41+
unix => {
42+
mod unix;
43+
use unix as imp;
44+
}
45+
windows => {
46+
mod windows;
47+
use self::windows as imp;
48+
}
49+
_ => {
50+
mod unsupported;
51+
use unsupported as imp;
52+
}
53+
}
54+
3055
pub use imp::Lock;

compiler/rustc_data_structures/src/profiling.rs

+63
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ fn get_thread_id() -> u32 {
860860
}
861861

862862
// Memory reporting
863+
#[cfg(bootstrap)]
863864
cfg_match! {
864865
cfg(windows) => {
865866
pub fn get_resident_set_size() -> Option<usize> {
@@ -921,5 +922,67 @@ cfg_match! {
921922
}
922923
}
923924

925+
#[cfg(not(bootstrap))]
926+
cfg_match! {
927+
windows => {
928+
pub fn get_resident_set_size() -> Option<usize> {
929+
use std::mem;
930+
931+
use windows::{
932+
Win32::System::ProcessStatus::{K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS},
933+
Win32::System::Threading::GetCurrentProcess,
934+
};
935+
936+
let mut pmc = PROCESS_MEMORY_COUNTERS::default();
937+
let pmc_size = mem::size_of_val(&pmc);
938+
unsafe {
939+
K32GetProcessMemoryInfo(
940+
GetCurrentProcess(),
941+
&mut pmc,
942+
pmc_size as u32,
943+
)
944+
}
945+
.ok()
946+
.ok()?;
947+
948+
Some(pmc.WorkingSetSize)
949+
}
950+
}
951+
target_os = "macos" => {
952+
pub fn get_resident_set_size() -> Option<usize> {
953+
use libc::{c_int, c_void, getpid, proc_pidinfo, proc_taskinfo, PROC_PIDTASKINFO};
954+
use std::mem;
955+
const PROC_TASKINFO_SIZE: c_int = mem::size_of::<proc_taskinfo>() as c_int;
956+
957+
unsafe {
958+
let mut info: proc_taskinfo = mem::zeroed();
959+
let info_ptr = &mut info as *mut proc_taskinfo as *mut c_void;
960+
let pid = getpid() as c_int;
961+
let ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, info_ptr, PROC_TASKINFO_SIZE);
962+
if ret == PROC_TASKINFO_SIZE {
963+
Some(info.pti_resident_size as usize)
964+
} else {
965+
None
966+
}
967+
}
968+
}
969+
}
970+
unix => {
971+
pub fn get_resident_set_size() -> Option<usize> {
972+
let field = 1;
973+
let contents = fs::read("/proc/self/statm").ok()?;
974+
let contents = String::from_utf8(contents).ok()?;
975+
let s = contents.split_whitespace().nth(field)?;
976+
let npages = s.parse::<usize>().ok()?;
977+
Some(npages * 4096)
978+
}
979+
}
980+
_ => {
981+
pub fn get_resident_set_size() -> Option<usize> {
982+
None
983+
}
984+
}
985+
}
986+
924987
#[cfg(test)]
925988
mod tests;

compiler/rustc_lint/src/types/literal.rs

+23-8
Original file line numberDiff line numberDiff line change
@@ -204,20 +204,35 @@ fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static
204204
match t.kind() {
205205
ty::Uint(ty::UintTy::Usize) | ty::Int(ty::IntTy::Isize) => None,
206206
ty::Uint(_) => Some(Integer::fit_unsigned(val).uint_ty_str()),
207-
ty::Int(_) if negative => Some(Integer::fit_signed(-(val as i128)).int_ty_str()),
208-
ty::Int(int) => {
209-
let signed = Integer::fit_signed(val as i128);
210-
let unsigned = Integer::fit_unsigned(val);
211-
Some(if Some(unsigned.size().bits()) == int.bit_width() {
212-
unsigned.uint_ty_str()
207+
ty::Int(_) => {
208+
let signed = literal_to_i128(val, negative).map(Integer::fit_signed);
209+
if negative {
210+
signed.map(Integer::int_ty_str)
213211
} else {
214-
signed.int_ty_str()
215-
})
212+
let unsigned = Integer::fit_unsigned(val);
213+
Some(if let Some(signed) = signed {
214+
if unsigned.size() < signed.size() {
215+
unsigned.uint_ty_str()
216+
} else {
217+
signed.int_ty_str()
218+
}
219+
} else {
220+
unsigned.uint_ty_str()
221+
})
222+
}
216223
}
217224
_ => None,
218225
}
219226
}
220227

228+
fn literal_to_i128(val: u128, negative: bool) -> Option<i128> {
229+
if negative {
230+
(val <= i128::MAX as u128 + 1).then(|| val.wrapping_neg() as i128)
231+
} else {
232+
val.try_into().ok()
233+
}
234+
}
235+
221236
fn lint_int_literal<'tcx>(
222237
cx: &LateContext<'tcx>,
223238
type_limits: &TypeLimits,

compiler/rustc_span/src/analyze_source_file.rs

+160
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub(crate) fn analyze_source_file(src: &str) -> (Vec<RelativeBytePos>, Vec<Multi
2929
(lines, multi_byte_chars)
3030
}
3131

32+
#[cfg(bootstrap)]
3233
cfg_match! {
3334
cfg(any(target_arch = "x86", target_arch = "x86_64")) => {
3435
fn analyze_source_file_dispatch(
@@ -185,6 +186,165 @@ cfg_match! {
185186
}
186187
}
187188
}
189+
190+
#[cfg(not(bootstrap))]
191+
cfg_match! {
192+
any(target_arch = "x86", target_arch = "x86_64") => {
193+
fn analyze_source_file_dispatch(
194+
src: &str,
195+
lines: &mut Vec<RelativeBytePos>,
196+
multi_byte_chars: &mut Vec<MultiByteChar>,
197+
) {
198+
if is_x86_feature_detected!("sse2") {
199+
unsafe {
200+
analyze_source_file_sse2(src, lines, multi_byte_chars);
201+
}
202+
} else {
203+
analyze_source_file_generic(
204+
src,
205+
src.len(),
206+
RelativeBytePos::from_u32(0),
207+
lines,
208+
multi_byte_chars,
209+
);
210+
}
211+
}
212+
213+
/// Checks 16 byte chunks of text at a time. If the chunk contains
214+
/// something other than printable ASCII characters and newlines, the
215+
/// function falls back to the generic implementation. Otherwise it uses
216+
/// SSE2 intrinsics to quickly find all newlines.
217+
#[target_feature(enable = "sse2")]
218+
unsafe fn analyze_source_file_sse2(
219+
src: &str,
220+
lines: &mut Vec<RelativeBytePos>,
221+
multi_byte_chars: &mut Vec<MultiByteChar>,
222+
) {
223+
#[cfg(target_arch = "x86")]
224+
use std::arch::x86::*;
225+
#[cfg(target_arch = "x86_64")]
226+
use std::arch::x86_64::*;
227+
228+
const CHUNK_SIZE: usize = 16;
229+
230+
let src_bytes = src.as_bytes();
231+
232+
let chunk_count = src.len() / CHUNK_SIZE;
233+
234+
// This variable keeps track of where we should start decoding a
235+
// chunk. If a multi-byte character spans across chunk boundaries,
236+
// we need to skip that part in the next chunk because we already
237+
// handled it.
238+
let mut intra_chunk_offset = 0;
239+
240+
for chunk_index in 0..chunk_count {
241+
let ptr = src_bytes.as_ptr() as *const __m128i;
242+
// We don't know if the pointer is aligned to 16 bytes, so we
243+
// use `loadu`, which supports unaligned loading.
244+
let chunk = unsafe { _mm_loadu_si128(ptr.add(chunk_index)) };
245+
246+
// For character in the chunk, see if its byte value is < 0, which
247+
// indicates that it's part of a UTF-8 char.
248+
let multibyte_test = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(0)) };
249+
// Create a bit mask from the comparison results.
250+
let multibyte_mask = unsafe { _mm_movemask_epi8(multibyte_test) };
251+
252+
// If the bit mask is all zero, we only have ASCII chars here:
253+
if multibyte_mask == 0 {
254+
assert!(intra_chunk_offset == 0);
255+
256+
// Check if there are any control characters in the chunk. All
257+
// control characters that we can encounter at this point have a
258+
// byte value less than 32 or ...
259+
let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) };
260+
let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) };
261+
262+
// ... it's the ASCII 'DEL' character with a value of 127.
263+
let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) };
264+
let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) };
265+
266+
let control_char_mask = control_char_mask0 | control_char_mask1;
267+
268+
if control_char_mask != 0 {
269+
// Check for newlines in the chunk
270+
let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) };
271+
let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };
272+
273+
if control_char_mask == newlines_mask {
274+
// All control characters are newlines, record them
275+
let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32;
276+
let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1);
277+
278+
loop {
279+
let index = newlines_mask.trailing_zeros();
280+
281+
if index >= CHUNK_SIZE as u32 {
282+
// We have arrived at the end of the chunk.
283+
break;
284+
}
285+
286+
lines.push(RelativeBytePos(index) + output_offset);
287+
288+
// Clear the bit, so we can find the next one.
289+
newlines_mask &= (!1) << index;
290+
}
291+
292+
// We are done for this chunk. All control characters were
293+
// newlines and we took care of those.
294+
continue;
295+
} else {
296+
// Some of the control characters are not newlines,
297+
// fall through to the slow path below.
298+
}
299+
} else {
300+
// No control characters, nothing to record for this chunk
301+
continue;
302+
}
303+
}
304+
305+
// The slow path.
306+
// There are control chars in here, fallback to generic decoding.
307+
let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset;
308+
intra_chunk_offset = analyze_source_file_generic(
309+
&src[scan_start..],
310+
CHUNK_SIZE - intra_chunk_offset,
311+
RelativeBytePos::from_usize(scan_start),
312+
lines,
313+
multi_byte_chars,
314+
);
315+
}
316+
317+
// There might still be a tail left to analyze
318+
let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
319+
if tail_start < src.len() {
320+
analyze_source_file_generic(
321+
&src[tail_start..],
322+
src.len() - tail_start,
323+
RelativeBytePos::from_usize(tail_start),
324+
lines,
325+
multi_byte_chars,
326+
);
327+
}
328+
}
329+
}
330+
_ => {
331+
// The target (or compiler version) does not support SSE2 ...
332+
fn analyze_source_file_dispatch(
333+
src: &str,
334+
lines: &mut Vec<RelativeBytePos>,
335+
multi_byte_chars: &mut Vec<MultiByteChar>,
336+
) {
337+
analyze_source_file_generic(
338+
src,
339+
src.len(),
340+
RelativeBytePos::from_u32(0),
341+
lines,
342+
multi_byte_chars,
343+
);
344+
}
345+
}
346+
}
347+
188348
// `scan_len` determines the number of bytes in `src` to scan. Note that the
189349
// function can read past `scan_len` if a multi-byte character start within the
190350
// range but extends past it. The overflow is returned by the function.

library/alloc/src/sync.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1397,6 +1397,8 @@ impl<T: ?Sized> Arc<T> {
13971397
/// different types. See [`mem::transmute`][transmute] for more information
13981398
/// on what restrictions apply in this case.
13991399
///
1400+
/// The raw pointer must point to a block of memory allocated by the global allocator.
1401+
///
14001402
/// The user of `from_raw` has to make sure a specific value of `T` is only
14011403
/// dropped once.
14021404
///
@@ -1452,7 +1454,8 @@ impl<T: ?Sized> Arc<T> {
14521454
///
14531455
/// The pointer must have been obtained through `Arc::into_raw`, and the
14541456
/// associated `Arc` instance must be valid (i.e. the strong count must be at
1455-
/// least 1) for the duration of this method.
1457+
/// least 1) for the duration of this method, and `ptr` must point to a block of memory
1458+
/// allocated by the global allocator.
14561459
///
14571460
/// # Examples
14581461
///
@@ -1486,7 +1489,8 @@ impl<T: ?Sized> Arc<T> {
14861489
///
14871490
/// The pointer must have been obtained through `Arc::into_raw`, and the
14881491
/// associated `Arc` instance must be valid (i.e. the strong count must be at
1489-
/// least 1) when invoking this method. This method can be used to release the final
1492+
/// least 1) when invoking this method, and `ptr` must point to a block of memory
1493+
/// allocated by the global allocator. This method can be used to release the final
14901494
/// `Arc` and backing storage, but **should not** be called after the final `Arc` has been
14911495
/// released.
14921496
///

0 commit comments

Comments
 (0)