pub struct CopyingMemory {
pub base: u32,
pub flat_mem: Vec<u8>,
pub perms: Vec<u8>,
pub mat_state: Vec<u8>,
pub code_base: u32,
pub code_top: u32,
pub heap_base: u32,
pub heap_top: u32,
pub max_heap_pages: u32,
}Expand description
Address-space mapping for one execution context.
Flat-buffer layout matching v2 javm. The buffer’s length defines
the upper bound of valid addresses; per-page permissions live in
perms. Implements Memory via inherent-method delegation so
concrete callers don’t need to import the trait.
Fields§
§base: u32Base guest address flat_mem[0] corresponds to. Guest address
addr indexes flat_mem[addr - base]; accesses below base (or
past the buffer) fault. Lets the buffer cover only the high data
region [DATA_BASE, …) without allocating the [0, DATA_BASE)
null-guard hole — matching the recompiler’s page table, which
leaves that range unmapped. 0 for the addr-0-based memories used
in unit tests.
flat_mem: Vec<u8>Contiguous byte buffer covering [base, base + flat_mem.len()).
perms: Vec<u8>One permission byte per PAGE_SIZE-page in flat_mem.
perms.len() == flat_mem.len() / PAGE_SIZE (rounded up). Indexed
by page relative to base.
mat_state: Vec<u8>Category-#3 per-page materialization state (crate::mat::PageState
as a u8), one byte per page, kept the same length as perms.
Software first-touch accounting: a never-touched page is
NotPresent; the first read pages it in, the first write CoWs it.
The interpreter’s #3 charge is kind-independent (the only
kind-sensitive case — a write to a pinned page — is already gated
by the perm::RW write check), so no per-page PageKind is kept;
the recompiler tracks kinds itself for page sourcing.
code_base: u32Guest VA base of the read-only CODE region (PinnedCapRo). Guest
data loads (PIC auipc+load) of the program’s own bytecode page it
in on first read (read-only page-in is charged eagerly at the CALL,
not at this fault, but a PIC read still records residency), identical
to the recompiler. code_top == code_base (the default) means no code
region is declared — code reads then skip #3 (unit tests).
code_top: u32Exclusive top of the code region, page-rounded:
code_base + round_up(code_len). The last code page’s zero-padded
tail is readable (matching the recompiler, which maps whole pages).
heap_base: u32Heap base address (for sbrk).
heap_top: u32Current heap top.
max_heap_pages: u32Maximum heap pages (sbrk refuses beyond this).
Implementations§
Source§impl CopyingMemory
impl CopyingMemory
Sourcepub fn with_pages(n_pages: u32, default_perm: u8) -> Self
pub fn with_pages(n_pages: u32, default_perm: u8) -> Self
Construct with a pre-sized flat buffer (zero-initialized).
n_pages is the number of PAGE_SIZE-pages. base = 0.
Sourcepub fn set_code_region(&mut self, code_base: u32, code_len: u32)
pub fn set_code_region(&mut self, code_base: u32, code_len: u32)
Declare the read-only CODE region for category-#3 accounting:
[code_base, code_base + round_up(code_len)). Guest data loads of
the program’s own bytecode (PIC) then read each touched code page
with no per-fault charge (read-only page-in is accounted eagerly at
the CALL) and hard-fault on any write — matching the recompiler,
which lazily materializes code pages too. code_len is the exact
byte length; the region is page-rounded.
Sourcepub fn perm_of(&self, addr: u32) -> u8
pub fn perm_of(&self, addr: u32) -> u8
Per-page permission for the page containing addr. Returns
perm::NONE if the address is out of range (incl. below base).
Sourcepub fn touch_read(
&mut self,
addr: u32,
width: u32,
gas: &mut GasCounter,
) -> Result<(), TouchFault>
pub fn touch_read( &mut self, addr: u32, width: u32, gas: &mut GasCounter, ) -> Result<(), TouchFault>
Category-#3 first-touch for a width-byte read. See touch.
Sourcepub fn touch_write(
&mut self,
addr: u32,
width: u32,
gas: &mut GasCounter,
) -> Result<(), TouchFault>
pub fn touch_write( &mut self, addr: u32, width: u32, gas: &mut GasCounter, ) -> Result<(), TouchFault>
Category-#3 first-touch for a width-byte write. See touch.
pub fn read_u8(&self, addr: u32) -> Option<u8>
pub fn read_u16_le(&self, addr: u32) -> Option<u16>
pub fn read_u32_le(&self, addr: u32) -> Option<u32>
pub fn read_u64_le(&self, addr: u32) -> Option<u64>
pub fn write_u8(&mut self, addr: u32, val: u8) -> bool
pub fn write_u16_le(&mut self, addr: u32, val: u16) -> bool
pub fn write_u32_le(&mut self, addr: u32, val: u32) -> bool
pub fn write_u64_le(&mut self, addr: u32, val: u64) -> bool
Sourcepub fn map_region(
&mut self,
start: u64,
size: u64,
access: Access,
init: Option<&[u8]>,
) -> Result<(), MapError>
pub fn map_region( &mut self, start: u64, size: u64, access: Access, init: Option<&[u8]>, ) -> Result<(), MapError>
Declare a mapped region at [start, start + size) with
per-page permissions access and optional initial bytes.
startandsizemust each be multiples ofPAGE_SIZE.- Grows
flat_memto coverstart + sizeif necessary (newly-grown bytes are zero-initialized; their pages default toperm::NONEbefore this call sets them). - Sets pages in
[start / PAGE_SIZE, (start + size) / PAGE_SIZE)to the permission byte foraccess. - If
initisSome(bytes), copiesbytes[..bytes.len() .min(size)]intoflat_mem[start..]; the rest of the region remains zero-filled (matches the DataCap canonical form: trailing zeros are stripped fromcontent, but the logicalsizemay be larger).
Trait Implementations§
Source§impl Clone for CopyingMemory
impl Clone for CopyingMemory
Source§fn clone(&self) -> CopyingMemory
fn clone(&self) -> CopyingMemory
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for CopyingMemory
impl Debug for CopyingMemory
Source§impl Default for CopyingMemory
impl Default for CopyingMemory
Source§impl Memory for CopyingMemory
impl Memory for CopyingMemory
fn read_u8(&self, addr: u32) -> Option<u8>
fn read_u16_le(&self, addr: u32) -> Option<u16>
fn read_u32_le(&self, addr: u32) -> Option<u32>
fn read_u64_le(&self, addr: u32) -> Option<u64>
fn write_u8(&mut self, addr: u32, val: u8) -> bool
fn write_u16_le(&mut self, addr: u32, val: u16) -> bool
fn write_u32_le(&mut self, addr: u32, val: u32) -> bool
fn write_u64_le(&mut self, addr: u32, val: u64) -> bool
Source§fn map_region(
&mut self,
start: u64,
size: u64,
access: Access,
init: Option<&[u8]>,
) -> Result<(), MapError>
fn map_region( &mut self, start: u64, size: u64, access: Access, init: Option<&[u8]>, ) -> Result<(), MapError>
CopyingMemory::map_region for
the canonical semantics.Source§fn read(&self, addr: u32, len: usize) -> Result<Vec<u8>, MemAccess>
fn read(&self, addr: u32, len: usize) -> Result<Vec<u8>, MemAccess>
dst.len() bytes starting at addr into dst.Source§fn write(&mut self, addr: u32, data: &[u8]) -> Result<(), MemAccess>
fn write(&mut self, addr: u32, data: &[u8]) -> Result<(), MemAccess>
data.len() bytes starting at addr. Per-page perm
checks apply; out-of-range or RO-page writes return Err.Source§fn touch_read(
&mut self,
addr: u32,
width: u32,
gas: &mut GasCounter,
) -> Result<(), TouchFault>
fn touch_read( &mut self, addr: u32, width: u32, gas: &mut GasCounter, ) -> Result<(), TouchFault>
width-byte read at
addr (page-in on the first read of a page), advancing the
per-page materialization state. See CopyingMemory::touch_read
for the canonical semantics. The default is a no-op (Ok) for
backends that don’t model lazy materialization.Source§fn touch_write(
&mut self,
addr: u32,
width: u32,
gas: &mut GasCounter,
) -> Result<(), TouchFault>
fn touch_write( &mut self, addr: u32, width: u32, gas: &mut GasCounter, ) -> Result<(), TouchFault>
width-byte write at
addr (page-in + copy-on-write on the first write of a page),
advancing the per-page materialization state. See
CopyingMemory::touch_write for the canonical semantics. The
default is a no-op (Ok).