mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-12 13:28:49 +00:00
Merge branch 'wasix-core-changes' into wasix
This commit is contained in:
2
.github/workflows/benchmark.yaml
vendored
2
.github/workflows/benchmark.yaml
vendored
@@ -24,7 +24,7 @@ jobs:
|
|||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
toolchain: 1.63
|
toolchain: 1.64
|
||||||
- name: Configure cargo data directory
|
- name: Configure cargo data directory
|
||||||
# After this point, all cargo registry and crate data is stored in
|
# After this point, all cargo registry and crate data is stored in
|
||||||
# $GITHUB_WORKSPACE/.cargo_home. This allows us to cache only the files
|
# $GITHUB_WORKSPACE/.cargo_home. This allows us to cache only the files
|
||||||
|
|||||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -100,7 +100,7 @@ jobs:
|
|||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
toolchain: 1.63
|
toolchain: 1.64
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
- uses: Swatinem/rust-cache@v1
|
- uses: Swatinem/rust-cache@v1
|
||||||
if: matrix.use_sccache != true
|
if: matrix.use_sccache != true
|
||||||
|
|||||||
2
.github/workflows/cloudcompiler.yaml
vendored
2
.github/workflows/cloudcompiler.yaml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
toolchain: 1.63
|
toolchain: 1.64
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
- name: Install wasm32-wasi target
|
- name: Install wasm32-wasi target
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
2
.github/workflows/documentation.yaml
vendored
2
.github/workflows/documentation.yaml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
toolchain: 1.63
|
toolchain: 1.64
|
||||||
- name: Install LLVM
|
- name: Install LLVM
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
2
.github/workflows/test-js.yaml
vendored
2
.github/workflows/test-js.yaml
vendored
@@ -33,7 +33,7 @@ jobs:
|
|||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
toolchain: 1.63
|
toolchain: 1.64
|
||||||
|
|
||||||
- name: Install NodeJS
|
- name: Install NodeJS
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
|
|||||||
2
.github/workflows/test-sys.yaml
vendored
2
.github/workflows/test-sys.yaml
vendored
@@ -113,7 +113,7 @@ jobs:
|
|||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
toolchain: 1.63
|
toolchain: 1.64
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
- uses: Swatinem/rust-cache@v1
|
- uses: Swatinem/rust-cache@v1
|
||||||
if: matrix.use_sccache != true
|
if: matrix.use_sccache != true
|
||||||
|
|||||||
13
bors.toml
13
bors.toml
@@ -1,13 +0,0 @@
|
|||||||
status = [
|
|
||||||
#"Audit",
|
|
||||||
"Code lint",
|
|
||||||
#"Test on linux-x64",
|
|
||||||
# "Test on linux-musl-x64",
|
|
||||||
# "Test on linux-aarch64",
|
|
||||||
#"Test on macos-arm64",
|
|
||||||
#"Test on macos-x64",
|
|
||||||
#"Test on windows-x64",
|
|
||||||
]
|
|
||||||
required_approvals = 0
|
|
||||||
timeout_sec = 7200
|
|
||||||
delete_merged_branches = true
|
|
||||||
@@ -54,7 +54,7 @@ impl VMMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Copies this memory to a new memory
|
/// Copies this memory to a new memory
|
||||||
pub fn fork(&self) -> Result<VMMemory, wasmer_types::MemoryError> {
|
pub fn duplicate(&self) -> Result<VMMemory, wasmer_types::MemoryError> {
|
||||||
let new_memory = crate::Memory::new_internal(self.ty.clone())?;
|
let new_memory = crate::Memory::new_internal(self.ty.clone())?;
|
||||||
|
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
|
|||||||
4
lib/api/src/js/externals/memory.rs
vendored
4
lib/api/src/js/externals/memory.rs
vendored
@@ -265,9 +265,9 @@ impl Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Copies this memory to a new memory
|
/// Copies this memory to a new memory
|
||||||
pub fn fork(&mut self, store: &impl AsStoreRef) -> Result<VMMemory, MemoryError> {
|
pub fn duplicate(&mut self, store: &impl AsStoreRef) -> Result<VMMemory, MemoryError> {
|
||||||
let mem = self.handle.get(store.as_store_ref().objects());
|
let mem = self.handle.get(store.as_store_ref().objects());
|
||||||
mem.fork()
|
mem.duplicate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,10 +117,12 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_clone(&self) -> Option<Box<dyn LinearMemory + 'static>> {
|
fn try_clone(&self) -> Option<Box<dyn LinearMemory + 'static>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn fork(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError> {
|
|
||||||
|
fn duplicate(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError> {
|
||||||
let mem = self.mem.clone();
|
let mem = self.mem.clone();
|
||||||
Ok(Box::new(Self {
|
Ok(Box::new(Self {
|
||||||
memory_definition: Some(UnsafeCell::new(VMMemoryDefinition {
|
memory_definition: Some(UnsafeCell::new(VMMemoryDefinition {
|
||||||
|
|||||||
@@ -110,8 +110,6 @@ pub fn sbrk(mut ctx: FunctionEnvMut<EmEnv>, increment: i32) -> i32 {
|
|||||||
increment,
|
increment,
|
||||||
total_memory
|
total_memory
|
||||||
);
|
);
|
||||||
let _ = dynamictop_ptr;
|
|
||||||
|
|
||||||
if increment > 0 && new_dynamic_top < old_dynamic_top || new_dynamic_top < 0 {
|
if increment > 0 && new_dynamic_top < old_dynamic_top || new_dynamic_top < 0 {
|
||||||
abort_on_cannot_grow_memory_old(ctx);
|
abort_on_cannot_grow_memory_old(ctx);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -119,11 +119,11 @@ impl WasmMmap {
|
|||||||
|
|
||||||
/// Copies the memory
|
/// Copies the memory
|
||||||
/// (in this case it performs a copy-on-write to save memory)
|
/// (in this case it performs a copy-on-write to save memory)
|
||||||
pub fn fork(&mut self) -> Result<Self, MemoryError> {
|
pub fn duplicate(&mut self) -> Result<Self, MemoryError> {
|
||||||
let mem_length = self.size.bytes().0;
|
let mem_length = self.size.bytes().0;
|
||||||
let mut alloc = self
|
let mut alloc = self
|
||||||
.alloc
|
.alloc
|
||||||
.fork(Some(mem_length))
|
.duplicate(Some(mem_length))
|
||||||
.map_err(MemoryError::Generic)?;
|
.map_err(MemoryError::Generic)?;
|
||||||
let base_ptr = alloc.as_mut_ptr();
|
let base_ptr = alloc.as_mut_ptr();
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -289,9 +289,9 @@ impl VMOwnedMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Copies this memory to a new memory
|
/// Copies this memory to a new memory
|
||||||
pub fn fork(&mut self) -> Result<Self, MemoryError> {
|
pub fn duplicate(&mut self) -> Result<Self, MemoryError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
mmap: self.mmap.fork()?,
|
mmap: self.mmap.duplicate()?,
|
||||||
config: self.config.clone(),
|
config: self.config.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -333,8 +333,8 @@ impl LinearMemory for VMOwnedMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Copies this memory to a new memory
|
/// Copies this memory to a new memory
|
||||||
fn fork(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError> {
|
fn duplicate(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError> {
|
||||||
let forked = Self::fork(self)?;
|
let forked = Self::duplicate(self)?;
|
||||||
Ok(Box::new(forked))
|
Ok(Box::new(forked))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,10 +376,10 @@ impl VMSharedMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Copies this memory to a new memory
|
/// Copies this memory to a new memory
|
||||||
pub fn fork(&mut self) -> Result<Self, MemoryError> {
|
pub fn duplicate(&mut self) -> Result<Self, MemoryError> {
|
||||||
let mut guard = self.mmap.write().unwrap();
|
let mut guard = self.mmap.write().unwrap();
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
mmap: Arc::new(RwLock::new(guard.fork()?)),
|
mmap: Arc::new(RwLock::new(guard.duplicate()?)),
|
||||||
config: self.config.clone(),
|
config: self.config.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -427,8 +427,8 @@ impl LinearMemory for VMSharedMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Copies this memory to a new memory
|
/// Copies this memory to a new memory
|
||||||
fn fork(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError> {
|
fn duplicate(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError> {
|
||||||
let forked = Self::fork(self)?;
|
let forked = Self::duplicate(self)?;
|
||||||
Ok(Box::new(forked))
|
Ok(Box::new(forked))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -495,8 +495,8 @@ impl LinearMemory for VMMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Copies this memory to a new memory
|
/// Copies this memory to a new memory
|
||||||
fn fork(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError> {
|
fn duplicate(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError> {
|
||||||
self.0.fork()
|
self.0.duplicate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,8 +558,8 @@ impl VMMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Copies this memory to a new memory
|
/// Copies this memory to a new memory
|
||||||
pub fn fork(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError> {
|
pub fn duplicate(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError> {
|
||||||
LinearMemory::fork(self)
|
LinearMemory::duplicate(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,5 +615,5 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Copies this memory to a new memory
|
/// Copies this memory to a new memory
|
||||||
fn fork(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError>;
|
fn duplicate(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,8 +317,10 @@ impl Mmap {
|
|||||||
|
|
||||||
/// Copies the memory to a new swap file (using copy-on-write if available)
|
/// Copies the memory to a new swap file (using copy-on-write if available)
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
pub fn fork(&mut self, hint_used: Option<usize>) -> Result<Self, String> {
|
pub fn duplicate(&mut self, hint_used: Option<usize>) -> Result<Self, String> {
|
||||||
// Empty memory is an edge case
|
// Empty memory is an edge case
|
||||||
|
|
||||||
|
use std::os::unix::prelude::FromRawFd;
|
||||||
if self.len == 0 {
|
if self.len == 0 {
|
||||||
return Ok(Self::new());
|
return Ok(Self::new());
|
||||||
}
|
}
|
||||||
@@ -355,28 +357,11 @@ impl Mmap {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// The shallow copy failed so we have to do it the hard way
|
// The shallow copy failed so we have to do it the hard way
|
||||||
let mut off_in: libc::off_t = 0;
|
|
||||||
let mut off_out: libc::off_t = 0;
|
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
let mut source = std::fs::File::from_raw_fd(self.fd.0);
|
||||||
if #[cfg(not(any(target_env = "musl", target_vendor = "apple")))]
|
let mut out = std::fs::File::from_raw_fd(fd.0);
|
||||||
{
|
copy_file_range(&mut source, 0, &mut out, 0, len)
|
||||||
let ret = libc::copy_file_range(self.fd.0, &mut off_in, fd.0, &mut off_out, len, 0);
|
.map_err(|err| format!("Could not copy memory: {err}"))?;
|
||||||
} else {
|
|
||||||
// TODO: don't use as casts...
|
|
||||||
let ret = match copy_file_range_impl(self.fd.0, off_in as u64, fd.0, off_out as u64, len) {
|
|
||||||
Ok(_) => 0,
|
|
||||||
Err(_err) => -1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ret < 0 {
|
|
||||||
return Err(format!(
|
|
||||||
"failed to copy temporary file data - {}",
|
|
||||||
io::Error::last_os_error()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
trace!("memory copy finished (size={})", len);
|
trace!("memory copy finished (size={})", len);
|
||||||
@@ -410,7 +395,7 @@ impl Mmap {
|
|||||||
|
|
||||||
/// Copies the memory to a new swap file (using copy-on-write if available)
|
/// Copies the memory to a new swap file (using copy-on-write if available)
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub fn fork(&mut self, hint_used: Option<usize>) -> Result<Self, String> {
|
pub fn duplicate(&mut self, hint_used: Option<usize>) -> Result<Self, String> {
|
||||||
// Create a new memory which we will copy to
|
// Create a new memory which we will copy to
|
||||||
let new_mmap = Self::with_at_least(self.len)?;
|
let new_mmap = Self::with_at_least(self.len)?;
|
||||||
|
|
||||||
@@ -436,66 +421,6 @@ impl Mmap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rust implementation of libc::copy_file_range.
|
|
||||||
///
|
|
||||||
/// Needed because that function is not available on all platforms.
|
|
||||||
// TODO: better implementation! (this is very quick, low effort)
|
|
||||||
// TODO: this function needs tests!
|
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn copy_file_range_impl(
|
|
||||||
source_fd: i32,
|
|
||||||
source_offset: u64,
|
|
||||||
out_fd: i32,
|
|
||||||
out_offset: u64,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<(), std::io::Error> {
|
|
||||||
use std::{
|
|
||||||
io::{Seek, SeekFrom},
|
|
||||||
os::unix::io::FromRawFd,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut f1 = unsafe { std::fs::File::from_raw_fd(source_fd) };
|
|
||||||
let f1_original_pos = f1.stream_position()?;
|
|
||||||
|
|
||||||
// TODO: don't cast with as
|
|
||||||
f1.seek(SeekFrom::Start(source_offset))?;
|
|
||||||
|
|
||||||
let mut f2 = unsafe { std::fs::File::from_raw_fd(out_fd) };
|
|
||||||
let f2_original_pos = f2.stream_position()?;
|
|
||||||
f2.seek(SeekFrom::Start(out_offset))?;
|
|
||||||
|
|
||||||
let mut reader = std::io::BufReader::new(f1);
|
|
||||||
let mut writer = std::io::BufWriter::new(f2);
|
|
||||||
|
|
||||||
let mut buffer = vec![0u8; 4096];
|
|
||||||
|
|
||||||
let mut offset = 0;
|
|
||||||
let end = len.saturating_sub(buffer.len());
|
|
||||||
while offset < end {
|
|
||||||
let read = reader.read(&mut buffer)?;
|
|
||||||
writer.write_all(&buffer)?;
|
|
||||||
offset += read;
|
|
||||||
}
|
|
||||||
// Need to read the last chunk.
|
|
||||||
let remaining = len - offset;
|
|
||||||
if remaining > 0 {
|
|
||||||
reader.read_exact(&mut buffer[0..remaining])?;
|
|
||||||
writer.write_all(&buffer[0..remaining])?;
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.flush()?;
|
|
||||||
|
|
||||||
// Restore files to original position.
|
|
||||||
let mut f1 = reader.into_inner();
|
|
||||||
f1.seek(SeekFrom::Start(f1_original_pos))?;
|
|
||||||
|
|
||||||
let mut f2 = writer.into_inner()?;
|
|
||||||
f2.seek(SeekFrom::Start(f2_original_pos))?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Mmap {
|
impl Drop for Mmap {
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
@@ -522,6 +447,54 @@ fn _assert() {
|
|||||||
_assert_send_sync::<Mmap>();
|
_assert_send_sync::<Mmap>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Copy a range of a file to another file.
|
||||||
|
// We could also use libc::copy_file_range on some systems, but it's
|
||||||
|
// hard to do this because it is not available on many libc implementations.
|
||||||
|
// (not on Mac OS, musl, ...)
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
fn copy_file_range(
|
||||||
|
source: &mut std::fs::File,
|
||||||
|
source_offset: u64,
|
||||||
|
out: &mut std::fs::File,
|
||||||
|
out_offset: u64,
|
||||||
|
len: usize,
|
||||||
|
) -> Result<(), std::io::Error> {
|
||||||
|
use std::io::{Seek, SeekFrom};
|
||||||
|
|
||||||
|
let source_original_pos = source.stream_position()?;
|
||||||
|
source.seek(SeekFrom::Start(source_offset))?;
|
||||||
|
|
||||||
|
// TODO: don't cast with as
|
||||||
|
|
||||||
|
let out_original_pos = out.stream_position()?;
|
||||||
|
out.seek(SeekFrom::Start(out_offset))?;
|
||||||
|
|
||||||
|
// TODO: don't do this horrible "triple buffering" below".
|
||||||
|
// let mut reader = std::io::BufReader::new(source);
|
||||||
|
|
||||||
|
// TODO: larger buffer?
|
||||||
|
let mut buffer = vec![0u8; 4096];
|
||||||
|
|
||||||
|
let mut to_read = len;
|
||||||
|
while to_read > 0 {
|
||||||
|
let chunk_size = std::cmp::min(to_read, buffer.len());
|
||||||
|
let read = source.read(&mut buffer[0..chunk_size])?;
|
||||||
|
out.write_all(&buffer[0..read])?;
|
||||||
|
to_read -= read;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to read the last chunk.
|
||||||
|
out.flush()?;
|
||||||
|
|
||||||
|
// Restore files to original position.
|
||||||
|
source.seek(SeekFrom::Start(source_original_pos))?;
|
||||||
|
out.flush()?;
|
||||||
|
out.sync_data()?;
|
||||||
|
out.seek(SeekFrom::Start(out_original_pos))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -533,4 +506,59 @@ mod tests {
|
|||||||
assert_eq!(round_up_to_page_size(4096, 4096), 4096);
|
assert_eq!(round_up_to_page_size(4096, 4096), 4096);
|
||||||
assert_eq!(round_up_to_page_size(4097, 4096), 8192);
|
assert_eq!(round_up_to_page_size(4097, 4096), 8192);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
#[test]
|
||||||
|
fn test_copy_file_range() -> Result<(), std::io::Error> {
|
||||||
|
// I know tempfile:: exists, but this doesn't bring in an extra
|
||||||
|
// dependency.
|
||||||
|
|
||||||
|
use std::{fs::OpenOptions, io::Seek};
|
||||||
|
|
||||||
|
let dir = std::env::temp_dir().join("wasmer/copy_file_range");
|
||||||
|
if dir.is_dir() {
|
||||||
|
std::fs::remove_dir_all(&dir).unwrap()
|
||||||
|
}
|
||||||
|
std::fs::create_dir_all(&dir).unwrap();
|
||||||
|
|
||||||
|
let pa = dir.join("a");
|
||||||
|
let pb = dir.join("b");
|
||||||
|
|
||||||
|
let data: Vec<u8> = (0..100).collect();
|
||||||
|
let mut a = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create_new(true)
|
||||||
|
.open(&pa)
|
||||||
|
.unwrap();
|
||||||
|
a.write_all(&data).unwrap();
|
||||||
|
|
||||||
|
let datb: Vec<u8> = (100..200).collect();
|
||||||
|
let mut b = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create_new(true)
|
||||||
|
.open(&pb)
|
||||||
|
.unwrap();
|
||||||
|
b.write_all(&datb).unwrap();
|
||||||
|
|
||||||
|
a.seek(io::SeekFrom::Start(30)).unwrap();
|
||||||
|
b.seek(io::SeekFrom::Start(99)).unwrap();
|
||||||
|
copy_file_range(&mut a, 10, &mut b, 40, 15).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(a.stream_position().unwrap(), 30);
|
||||||
|
assert_eq!(b.stream_position().unwrap(), 99);
|
||||||
|
|
||||||
|
b.seek(io::SeekFrom::Start(0)).unwrap();
|
||||||
|
let mut out = Vec::new();
|
||||||
|
let len = b.read_to_end(&mut out).unwrap();
|
||||||
|
assert_eq!(len, 100);
|
||||||
|
assert_eq!(out[0..40], datb[0..40]);
|
||||||
|
assert_eq!(out[40..55], data[10..25]);
|
||||||
|
assert_eq!(out[55..100], datb[55..100]);
|
||||||
|
|
||||||
|
// TODO: needs more variant tests, but this is enough for now.
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use core::slice::Iter;
|
||||||
use std::{
|
use std::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
fmt,
|
fmt,
|
||||||
@@ -9,9 +10,9 @@ use std::{
|
|||||||
|
|
||||||
use wasmer_types::StoreSnapshot;
|
use wasmer_types::StoreSnapshot;
|
||||||
|
|
||||||
use crate::VMExternObj;
|
use crate::{
|
||||||
|
InstanceHandle, VMExternObj, VMFunction, VMFunctionEnvironment, VMGlobal, VMMemory, VMTable,
|
||||||
use crate::{InstanceHandle, VMFunction, VMFunctionEnvironment, VMGlobal, VMMemory, VMTable};
|
};
|
||||||
|
|
||||||
/// Unique ID to identify a context.
|
/// Unique ID to identify a context.
|
||||||
///
|
///
|
||||||
@@ -104,6 +105,21 @@ impl StoreObjects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return an immutable iterator over all globals
|
||||||
|
pub fn iter_globals(&self) -> Iter<VMGlobal> {
|
||||||
|
self.globals.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a global, at index idx. Will panic if idx is out of range
|
||||||
|
/// Safety: the caller should check taht the raw value is compatible
|
||||||
|
/// with destination VMGlobal type
|
||||||
|
pub fn set_global_unchecked(&self, idx: usize, val: u128) {
|
||||||
|
assert!(idx < self.globals.len());
|
||||||
|
unsafe {
|
||||||
|
self.globals[idx].vmglobal().as_mut().val.u128 = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Serializes the mutable things into a snapshot
|
/// Serializes the mutable things into a snapshot
|
||||||
pub fn save_snapshot(&self) -> StoreSnapshot {
|
pub fn save_snapshot(&self) -> StoreSnapshot {
|
||||||
let mut ret = StoreSnapshot::default();
|
let mut ret = StoreSnapshot::default();
|
||||||
|
|||||||
Reference in New Issue
Block a user