use super::{Cx, NativeSite};
use crate::value::Value;
#[derive(Default)]
pub(crate) struct ViaCalls {
pub(crate) calls: Vec<Value>,
pub(crate) frames: Vec<(u32, Value)>,
}
#[cold]
#[inline(never)]
pub(super) fn begin(cx: &mut Cx<'_>, first: Value) {
let calls = &mut cx.heap.vm.via.calls;
calls.clear();
calls.push(first);
}
#[cold]
#[inline(never)]
pub(super) fn record(cx: &mut Cx<'_>, function: Value) {
cx.heap.vm.via.calls.push(function);
}
#[cold]
#[inline(never)]
pub(super) fn abandon(cx: &mut Cx<'_>) {
cx.heap.vm.via.calls.clear();
}
#[inline(never)]
pub(super) fn enter_bytecode(cx: &mut Cx<'_>) {
let depth = cx.heap.vm.frames.len() as u32;
let via = &mut *cx.heap.vm.via;
let keep = via.frames.partition_point(|&(at, _)| at < depth);
via.frames.truncate(keep);
via.frames
.extend(via.calls.drain(..).map(|function| (depth, function)));
}
#[inline]
pub(super) fn list(cx: &mut Cx<'_>, pc: usize) -> usize {
if cx.heap.vm.via.calls.is_empty() {
return 0;
}
list_recorded(cx, pc)
}
#[cold]
#[inline(never)]
fn list_recorded(cx: &mut Cx<'_>, pc: usize) -> usize {
let depth = cx.heap.vm.frames.len() as u32;
let vm = &mut cx.heap.vm;
let count = vm.via.calls.len();
vm.natives
.extend(vm.via.calls.drain(..).map(|callee| NativeSite {
depth,
pc: pc as u32,
callee,
}));
count
}
#[inline]
pub(super) fn unlist(cx: &mut Cx<'_>, count: usize) {
if count == 0 {
return;
}
let keep = cx.heap.vm.natives.len() - count;
cx.heap.vm.natives.truncate(keep);
}