about summary refs log tree commit diff
path: root/src/librustc_data_structures
diff options
context:
space:
mode:
authorSimonas Kazlauskas <git@kazlauskas.me>2020-03-14 20:13:55 +0200
committerMateusz MikuĊ‚a <mati865@gmail.com>2020-05-02 16:47:52 +0200
commita5c5365031ce8ec3926e06e207e16e58c4bf3e8b (patch)
tree9229db3a9b196e2e12a38bcb97eb31fdc995d179 /src/librustc_data_structures
parent968f442c7ce591e9cb03b57bb0dac30df4909b50 (diff)
downloadrust-a5c5365031ce8ec3926e06e207e16e58c4bf3e8b.tar.gz
rust-a5c5365031ce8ec3926e06e207e16e58c4bf3e8b.zip
Move ensure_sufficient_stack to data_structures
We anticipate this to have uses in all sorts of crates and keeping it in
`rustc_data_structures` enables access to it from more locations without
necessarily pulling in the large `librustc` crate.
Diffstat (limited to 'src/librustc_data_structures')
-rw-r--r--src/librustc_data_structures/Cargo.toml1
-rw-r--r--src/librustc_data_structures/lib.rs1
-rw-r--r--src/librustc_data_structures/stack.rs17
3 files changed, 19 insertions, 0 deletions
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 6d7022acc78..fbabd1ab541 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -28,6 +28,7 @@ rustc_index = { path = "../librustc_index", package = "rustc_index" }
 bitflags = "1.2.1"
 measureme = "0.7.1"
 libc = "0.2"
+stacker = "0.1.6"
 
 [dependencies.parking_lot]
 version = "0.10"
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index bc2da535fd3..a23181befc1 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -80,6 +80,7 @@ pub mod stable_set;
 #[macro_use]
 pub mod stable_hasher;
 pub mod sharded;
+pub mod stack;
 pub mod sync;
 pub mod thin_vec;
 pub mod tiny_list;
diff --git a/src/librustc_data_structures/stack.rs b/src/librustc_data_structures/stack.rs
new file mode 100644
index 00000000000..a4964b7aa0c
--- /dev/null
+++ b/src/librustc_data_structures/stack.rs
@@ -0,0 +1,17 @@
+// This is the amount of bytes that need to be left on the stack before increasing the size.
+// It must be at least as large as the stack required by any code that does not call
+// `ensure_sufficient_stack`.
+const RED_ZONE: usize = 100 * 1024; // 100k
+
+// Only the first stack that is pushed, grows exponentially (2^n * STACK_PER_RECURSION) from then
+// on. This flag has performance relevant characteristics. Don't set it too high.
+const STACK_PER_RECURSION: usize = 1 * 1024 * 1024; // 1MB
+
+/// Grows the stack on demand to prevent stack overflow. Call this in strategic locations
+/// to "break up" recursive calls. E.g. almost any call to `visit_expr` or equivalent can benefit
+/// from this.
+///
+/// Should not be sprinkled around carelessly, as it causes a little bit of overhead.
+pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
+    stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f)
+}