Track subcall read regions within read-only calls
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
| [changes.rs](changes.rs) | 合并变更批次、变更键与有界通知额度 |
|
||||
| [number.rs](number.rs) | Integer/Decimal/Rational/BinaryFloat/Complex 的无损表示和装箱载荷 |
|
||||
| [builtins.rs](builtins.rs) | String、Dict、Cell、Function、BaseException 载荷与 trace 边 |
|
||||
| [heap.rs](heap.rs) | 私有 Heap、不可伪造 ObjectRef、稳定 Box、引用事务、迭代释放、循环回收、只读变更屏障/读取跟踪及私有边界测试 |
|
||||
| [heap.rs](heap.rs) | 私有 Heap、不可伪造 ObjectRef、稳定 Box、引用事务、迭代释放、循环回收、只读变更屏障/全调用及嵌套子调用读取跟踪及私有边界测试 |
|
||||
| [store.rs](store.rs) | ObjectStore、空堆创建、对象操作、retain/release 和回收入口 |
|
||||
| [store_builtins.rs](store_builtins.rs) | 载荷校验、代码/函数工厂、Dict/Cell 操作及键语义 |
|
||||
| [instruction.rs](instruction.rs) | Opcode、Instruction、wordcode 编解码、MakeFunction/比较参数与跳转读取接口 |
|
||||
|
||||
@@ -39,6 +39,7 @@ struct Slot {
|
||||
struct ReadOnly {
|
||||
protected: BTreeSet<ObjectRef>,
|
||||
reads: Mutex<BTreeSet<ObjectRef>>,
|
||||
regions: Mutex<Vec<BTreeSet<ObjectRef>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -84,6 +85,7 @@ impl Heap {
|
||||
self.read_only.push(ReadOnly {
|
||||
protected,
|
||||
reads: Mutex::new(BTreeSet::new()),
|
||||
regions: Mutex::new(Vec::new()),
|
||||
});
|
||||
self.read_only.len()
|
||||
}
|
||||
@@ -103,6 +105,26 @@ impl Heap {
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub(crate) fn begin_read_tracking(&self) -> Result<usize, VmError> {
|
||||
let scope = self.read_only.last().ok_or(VmError::InvalidArgument(
|
||||
"read tracking requires a read-only scope",
|
||||
))?;
|
||||
let mut regions = scope.regions.lock().expect("read tracker poisoned");
|
||||
regions.push(BTreeSet::new());
|
||||
Ok(regions.len())
|
||||
}
|
||||
|
||||
pub(crate) fn end_read_tracking(&self, token: usize) -> Result<Vec<ObjectRef>, VmError> {
|
||||
let scope = self.read_only.last().ok_or(VmError::InvalidArgument(
|
||||
"read tracking requires a read-only scope",
|
||||
))?;
|
||||
let mut regions = scope.regions.lock().expect("read tracker poisoned");
|
||||
if token == 0 || token != regions.len() {
|
||||
return Err(VmError::InvalidArgument("read tracking nesting mismatch"));
|
||||
}
|
||||
Ok(regions.pop().unwrap().into_iter().collect())
|
||||
}
|
||||
|
||||
pub(crate) fn is_read_only(&self) -> bool {
|
||||
!self.read_only.is_empty()
|
||||
}
|
||||
@@ -115,6 +137,14 @@ impl Heap {
|
||||
.lock()
|
||||
.expect("read tracker poisoned")
|
||||
.insert(reference);
|
||||
for region in scope
|
||||
.regions
|
||||
.lock()
|
||||
.expect("read tracker poisoned")
|
||||
.iter_mut()
|
||||
{
|
||||
region.insert(reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,16 @@ impl ObjectStore {
|
||||
pub fn end_read_only(&mut self, scope: usize) -> Result<Vec<ObjectRef>, VmError> {
|
||||
self.heap.end_read_only(scope)
|
||||
}
|
||||
/// Track one subcall inside the active read-only scope. Regions nest in
|
||||
/// LIFO order and do not clear the enclosing call's read dependencies.
|
||||
/// Handles returned by end_read_tracking are borrowed, never owning roots.
|
||||
pub fn begin_read_tracking(&self) -> Result<usize, VmError> {
|
||||
self.heap.begin_read_tracking()
|
||||
}
|
||||
pub fn end_read_tracking(&self, token: usize) -> Result<Vec<ObjectRef>, VmError> {
|
||||
self.heap.end_read_tracking(token)
|
||||
}
|
||||
|
||||
pub fn is_read_only(&self) -> bool {
|
||||
self.heap.is_read_only()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user