@@ -9,7 +9,7 @@ use std::io::{self, Write};
9
9
use std:: mem:: replace;
10
10
use std:: process:: { Child , Output } ;
11
11
12
- pub fn read2_abbreviated ( mut child : Child , exclude_from_len : & [ String ] ) -> io:: Result < Output > {
12
+ pub fn read2_abbreviated ( mut child : Child , filter_paths_from_len : & [ String ] ) -> io:: Result < Output > {
13
13
let mut stdout = ProcOutput :: new ( ) ;
14
14
let mut stderr = ProcOutput :: new ( ) ;
15
15
@@ -18,7 +18,7 @@ pub fn read2_abbreviated(mut child: Child, exclude_from_len: &[String]) -> io::R
18
18
child. stdout . take ( ) . unwrap ( ) ,
19
19
child. stderr . take ( ) . unwrap ( ) ,
20
20
& mut |is_stdout, data, _| {
21
- if is_stdout { & mut stdout } else { & mut stderr } . extend ( data, exclude_from_len ) ;
21
+ if is_stdout { & mut stdout } else { & mut stderr } . extend ( data, filter_paths_from_len ) ;
22
22
data. clear ( ) ;
23
23
} ,
24
24
) ?;
@@ -29,23 +29,30 @@ pub fn read2_abbreviated(mut child: Child, exclude_from_len: &[String]) -> io::R
29
29
30
30
const HEAD_LEN : usize = 160 * 1024 ;
31
31
const TAIL_LEN : usize = 256 * 1024 ;
32
- const EXCLUDED_PLACEHOLDER_LEN : isize = 32 ;
32
+
33
+ // Whenever a path is filtered when counting the length of the output, we need to add some
34
+ // placeholder length to ensure a compiler emitting only filtered paths doesn't cause a OOM.
35
+ //
36
+ // 32 was chosen semi-arbitrarily: it was the highest power of two that still allowed the test
37
+ // suite to pass at the moment of implementing path filtering.
38
+ const FILTERED_PATHS_PLACEHOLDER_LEN : usize = 32 ;
33
39
34
40
enum ProcOutput {
35
- Full { bytes : Vec < u8 > , excluded_len : isize } ,
41
+ Full { bytes : Vec < u8 > , filtered_len : usize } ,
36
42
Abbreviated { head : Vec < u8 > , skipped : usize , tail : Box < [ u8 ] > } ,
37
43
}
38
44
39
45
impl ProcOutput {
40
46
fn new ( ) -> Self {
41
- ProcOutput :: Full { bytes : Vec :: new ( ) , excluded_len : 0 }
47
+ ProcOutput :: Full { bytes : Vec :: new ( ) , filtered_len : 0 }
42
48
}
43
49
44
- fn extend ( & mut self , data : & [ u8 ] , exclude_from_len : & [ String ] ) {
50
+ fn extend ( & mut self , data : & [ u8 ] , filter_paths_from_len : & [ String ] ) {
45
51
let new_self = match * self {
46
- ProcOutput :: Full { ref mut bytes, ref mut excluded_len } => {
52
+ ProcOutput :: Full { ref mut bytes, ref mut filtered_len } => {
47
53
let old_len = bytes. len ( ) ;
48
54
bytes. extend_from_slice ( data) ;
55
+ * filtered_len += data. len ( ) ;
49
56
50
57
// We had problems in the past with tests failing only in some environments,
51
58
// due to the length of the base path pushing the output size over the limit.
@@ -58,21 +65,25 @@ impl ProcOutput {
58
65
// The compiler emitting only excluded strings is addressed by adding a
59
66
// placeholder size for each excluded segment, which will eventually reach
60
67
// the configured threshold.
61
- for pattern in exclude_from_len {
62
- let pattern_bytes = pattern . as_bytes ( ) ;
63
- // We start matching `pattern_bytes - 1` into the previously loaded data,
64
- // to account for the fact a pattern might be included across multiple
65
- // `extend` calls. Starting from `- 1` avoids double-counting patterns .
66
- let matches = ( & bytes[ ( old_len. saturating_sub ( pattern_bytes . len ( ) - 1 ) ) ..] )
67
- . windows ( pattern_bytes . len ( ) )
68
- . filter ( |window| window == & pattern_bytes )
68
+ for path in filter_paths_from_len {
69
+ let path_bytes = path . as_bytes ( ) ;
70
+ // We start matching `path_bytes - 1` into the previously loaded data,
71
+ // to account for the fact a path_bytes might be included across multiple
72
+ // `extend` calls. Starting from `- 1` avoids double-counting paths .
73
+ let matches = ( & bytes[ ( old_len. saturating_sub ( path_bytes . len ( ) - 1 ) ) ..] )
74
+ . windows ( path_bytes . len ( ) )
75
+ . filter ( |window| window == & path_bytes )
69
76
. count ( ) ;
70
- * excluded_len += matches as isize
71
- * ( EXCLUDED_PLACEHOLDER_LEN - pattern_bytes. len ( ) as isize ) ;
77
+ * filtered_len -= matches * path_bytes. len ( ) ;
78
+
79
+ // We can't just remove the length of the filtered path from the output lenght,
80
+ // otherwise a compiler emitting only filtered paths would OOM compiletest. Add
81
+ // a fixed placeholder length for each path to prevent that.
82
+ * filtered_len += matches * FILTERED_PATHS_PLACEHOLDER_LEN ;
72
83
}
73
84
74
85
let new_len = bytes. len ( ) ;
75
- if ( new_len as isize + * excluded_len ) as usize <= HEAD_LEN + TAIL_LEN {
86
+ if * filtered_len <= HEAD_LEN + TAIL_LEN {
76
87
return ;
77
88
}
78
89
0 commit comments