use super::block::Block;
use crate::util::linear_scan::{Region, RegionIterator};
use crate::util::metadata::side_metadata::SideMetadataSpec;
use crate::{
util::{Address, ObjectReference},
vm::*,
};
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Eq)]
pub struct Line(Address);
impl Region for Line {
const LOG_BYTES: usize = 8;
#[allow(clippy::assertions_on_constants)] fn from_aligned_address(address: Address) -> Self {
debug_assert!(!super::BLOCK_ONLY);
debug_assert!(address.is_aligned_to(Self::BYTES));
Self(address)
}
fn start(&self) -> Address {
self.0
}
}
#[allow(clippy::assertions_on_constants)]
impl Line {
pub const RESET_MARK_STATE: u8 = 1;
pub const MAX_MARK_STATE: u8 = 127;
pub const MARK_TABLE: SideMetadataSpec =
crate::util::metadata::side_metadata::spec_defs::IX_LINE_MARK;
pub fn block(&self) -> Block {
debug_assert!(!super::BLOCK_ONLY);
Block::from_unaligned_address(self.0)
}
pub fn get_index_within_block(&self) -> usize {
let addr = self.start();
addr.get_extent(Block::align(addr)) >> Line::LOG_BYTES
}
pub fn mark(&self, state: u8) {
debug_assert!(!super::BLOCK_ONLY);
unsafe {
Self::MARK_TABLE.store::<u8>(self.start(), state);
}
}
pub fn is_marked(&self, state: u8) -> bool {
debug_assert!(!super::BLOCK_ONLY);
unsafe { Self::MARK_TABLE.load::<u8>(self.start()) == state }
}
pub fn mark_lines_for_object<VM: VMBinding>(object: ObjectReference, state: u8) -> usize {
debug_assert!(!super::BLOCK_ONLY);
let start = object.to_object_start::<VM>();
let end = start + VM::VMObjectModel::get_current_size(object);
let start_line = Line::from_unaligned_address(start);
let mut end_line = Line::from_unaligned_address(end);
if !Line::is_aligned(end) {
end_line = end_line.next();
}
let mut marked_lines = 0;
let iter = RegionIterator::<Line>::new(start_line, end_line);
for line in iter {
if !line.is_marked(state) {
marked_lines += 1;
}
line.mark(state)
}
marked_lines
}
}