Skip to content

Commit 66c407d

Browse files
committed
zkVM: Cache args from host
Retrieve argc/argv from the host once, on demand when the first `env::ArgsOs` is constructed, and globally cache it. Copy each argument to an `OsString` while iterating.
1 parent 9ee2cef commit 66c407d

File tree

1 file changed

+31
-55
lines changed

1 file changed

+31
-55
lines changed

library/std/src/sys/args/zkvm.rs

+31-55
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,94 @@
1-
use crate::ffi::OsString;
2-
use crate::fmt;
1+
use crate::ffi::{OsStr, OsString};
32
use crate::num::NonZero;
4-
use crate::sys::os_str;
3+
use crate::sync::OnceLock;
54
use crate::sys::pal::{WORD_SIZE, abi};
6-
use crate::sys_common::FromInner;
7-
8-
#[derive(Clone)]
9-
pub struct Args {
10-
front: usize,
11-
back: usize,
12-
}
5+
use crate::{fmt, ptr, slice};
136

147
pub fn args() -> Args {
15-
let count = unsafe { abi::sys_argc() };
16-
Args { front: 0, back: count }
8+
Args { iter: ARGS.get_or_init(|| get_args()).iter() }
179
}
1810

19-
impl Args {
20-
/// Use sys_argv to get the arg at the requested index. Does not check that i is less than argc
21-
/// and will not return if the index is out of bounds.
22-
fn argv(i: usize) -> OsString {
23-
let arg_len = unsafe { abi::sys_argv(crate::ptr::null_mut(), 0, i) };
11+
fn get_args() -> Vec<&'static OsStr> {
12+
let argc = unsafe { abi::sys_argc() };
13+
let mut args = Vec::with_capacity(argc);
14+
15+
for i in 0..argc {
16+
// Get the size of the argument then the data.
17+
let arg_len = unsafe { abi::sys_argv(ptr::null_mut(), 0, i) };
2418

2519
let arg_len_words = (arg_len + WORD_SIZE - 1) / WORD_SIZE;
2620
let words = unsafe { abi::sys_alloc_words(arg_len_words) };
2721

2822
let arg_len2 = unsafe { abi::sys_argv(words, arg_len_words, i) };
2923
debug_assert_eq!(arg_len, arg_len2);
3024

31-
// Convert to OsString.
32-
//
33-
// FIXME: We can probably get rid of the extra copy here if we
34-
// reimplement "os_str" instead of just using the generic unix
35-
// "os_str".
36-
let arg_bytes: &[u8] =
37-
unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, arg_len) };
38-
OsString::from_inner(os_str::Buf { inner: arg_bytes.to_vec() })
25+
let arg_bytes = unsafe { slice::from_raw_parts(words.cast(), arg_len) };
26+
args.push(unsafe { OsStr::from_encoded_bytes_unchecked(arg_bytes) });
3927
}
28+
args
29+
}
30+
31+
static ARGS: OnceLock<Vec<&'static OsStr>> = OnceLock::new();
32+
33+
pub struct Args {
34+
iter: slice::Iter<'static, &'static OsStr>,
4035
}
4136

4237
impl !Send for Args {}
4338
impl !Sync for Args {}
4439

4540
impl fmt::Debug for Args {
4641
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47-
f.debug_list().entries(self.clone()).finish()
42+
self.iter.as_slice().fmt(f)
4843
}
4944
}
5045

5146
impl Iterator for Args {
5247
type Item = OsString;
5348

54-
#[inline]
5549
fn next(&mut self) -> Option<OsString> {
56-
if self.front == self.back {
57-
None
58-
} else {
59-
let arg = Self::argv(self.front);
60-
self.front += 1;
61-
Some(arg)
62-
}
50+
self.iter.next().map(|arg| arg.to_os_string())
6351
}
6452

6553
#[inline]
6654
fn size_hint(&self) -> (usize, Option<usize>) {
67-
let len = self.len();
68-
(len, Some(len))
55+
self.iter.size_hint()
6956
}
7057

7158
#[inline]
7259
fn count(self) -> usize {
73-
self.len()
60+
self.iter.len()
7461
}
7562

76-
#[inline]
77-
fn last(mut self) -> Option<OsString> {
78-
self.next_back()
63+
fn last(self) -> Option<OsString> {
64+
self.iter.last().map(|arg| arg.to_os_string())
7965
}
8066

8167
#[inline]
8268
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
83-
let step_size = self.len().min(n);
84-
self.front += step_size;
85-
NonZero::new(n - step_size).map_or(Ok(()), Err)
69+
self.iter.advance_by(n)
8670
}
8771
}
8872

8973
impl DoubleEndedIterator for Args {
90-
#[inline]
9174
fn next_back(&mut self) -> Option<OsString> {
92-
if self.back == self.front {
93-
None
94-
} else {
95-
self.back -= 1;
96-
Some(Self::argv(self.back))
97-
}
75+
self.iter.next_back().map(|arg| arg.to_os_string())
9876
}
9977

10078
#[inline]
10179
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
102-
let step_size = self.len().min(n);
103-
self.back -= step_size;
104-
NonZero::new(n - step_size).map_or(Ok(()), Err)
80+
self.iter.advance_back_by(n)
10581
}
10682
}
10783

10884
impl ExactSizeIterator for Args {
10985
#[inline]
11086
fn len(&self) -> usize {
111-
self.back - self.front
87+
self.iter.len()
11288
}
11389

11490
#[inline]
11591
fn is_empty(&self) -> bool {
116-
self.front == self.back
92+
self.iter.is_empty()
11793
}
11894
}

0 commit comments

Comments
 (0)