vm: stabilize plugin-first VM output + TLV decode\n\n- runtime(plugin_loader_v2): decode plugin TLV generically (tag 1/2/3/5/6/7/8/9)\n- vm(print): coerce plugin-backed results via semantics (i64/string) for consistent output\n- vm(plugin_invoke): add decode debug; align return handling\n- bin/lib: expose runner_plugin_init in bin; fix call sites to init plugin host\n- tools(build_aot.sh): disable legacy-forbid diag and toml env for object emit\n- add VM/JIT smoke scripts (counter, filebox, jit-compare)\n\nResult: VM plugin smokes PASS; jit-direct compare PASS. AOT emit still needs CLIF block init tweak.

This commit is contained in:
nyash-dev
2025-09-08 01:08:59 +09:00
parent 1bb2d2db5b
commit 5ab3cc6688
18 changed files with 565 additions and 119 deletions

View File

@ -266,26 +266,49 @@ impl PluginLoaderV2 {
// Encode TLV args via shared helper (numeric→string→toString)
let tlv = crate::runtime::plugin_ffi_common::encode_args(args);
let (_code, out_len, out) = super::host_bridge::invoke_alloc(plugin.invoke_fn, type_id, method.method_id, instance_id, &tlv);
// Minimal decoding by method name
match method_name {
// Expect UTF-8 string result in bytes → StringBox
"toUtf8" | "toString" => {
let s = String::from_utf8_lossy(&out[0..out_len]).to_string();
return Ok(Some(Box::new(crate::box_trait::StringBox::new(s))));
}
// Expect IntegerBox via little-endian i64 in first 8 bytes
"get" => {
if out_len >= 8 { let mut buf=[0u8;8]; buf.copy_from_slice(&out[0..8]); let n=i64::from_le_bytes(buf); return Ok(Some(Box::new(crate::box_trait::IntegerBox::new(n)))) }
return Ok(Some(Box::new(crate::box_trait::IntegerBox::new(0))));
}
// Float path (approx): read 8 bytes as f64 and Box as FloatBox
"toDouble" => {
if out_len >= 8 { let mut buf=[0u8;8]; buf.copy_from_slice(&out[0..8]); let x=f64::from_le_bytes(buf); return Ok(Some(Box::new(crate::boxes::FloatBox::new(x)))) }
return Ok(Some(Box::new(crate::boxes::FloatBox::new(0.0))));
}
_ => {}
// Decode TLV (first entry) generically
if let Some((tag, _sz, payload)) = crate::runtime::plugin_ffi_common::decode::tlv_first(&out[..out_len]) {
let bx: Box<dyn NyashBox> = match tag {
1 => Box::new(crate::box_trait::BoolBox::new(crate::runtime::plugin_ffi_common::decode::bool(payload).unwrap_or(false))),
2 => Box::new(crate::box_trait::IntegerBox::new(crate::runtime::plugin_ffi_common::decode::i32(payload).unwrap_or(0) as i64)),
3 => {
// i64 payload
if payload.len() == 8 { let mut b=[0u8;8]; b.copy_from_slice(payload); Box::new(crate::box_trait::IntegerBox::new(i64::from_le_bytes(b))) }
else { Box::new(crate::box_trait::IntegerBox::new(0)) }
}
5 => {
let x = crate::runtime::plugin_ffi_common::decode::f64(payload).unwrap_or(0.0);
Box::new(crate::boxes::FloatBox::new(x))
}
6 | 7 => {
let s = crate::runtime::plugin_ffi_common::decode::string(payload);
Box::new(crate::box_trait::StringBox::new(s))
}
8 => {
// Plugin handle (type_id, instance_id) → wrap into PluginBoxV2
if let Some((ret_type, inst)) = crate::runtime::plugin_ffi_common::decode::plugin_handle(payload) {
let handle = Arc::new(super::types::PluginHandleInner {
type_id: ret_type,
invoke_fn: plugin.invoke_fn,
instance_id: inst,
fini_method_id: None,
finalized: std::sync::atomic::AtomicBool::new(false),
});
Box::new(super::types::PluginBoxV2 { box_type: box_type.to_string(), inner: handle })
} else { Box::new(crate::box_trait::VoidBox::new()) }
}
9 => {
// Host handle (u64) → try to map back to BoxRef, else void
if let Some(u) = crate::runtime::plugin_ffi_common::decode::u64(payload) {
if let Some(arc) = crate::runtime::host_handles::get(u) { return Ok(Some(arc.share_box())); }
}
Box::new(crate::box_trait::VoidBox::new())
}
_ => Box::new(crate::box_trait::VoidBox::new()),
};
return Ok(Some(bx));
}
Ok(None)
Ok(Some(Box::new(crate::box_trait::VoidBox::new())))
}
pub fn create_box(&self, box_type: &str, _args: &[Box<dyn NyashBox>]) -> BidResult<Box<dyn NyashBox>> {