Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 66c407d

Browse files
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

Lines changed: 31 additions & 55 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /