Phase 12: extern registry + diagnostics, JIT host-bridge PoC by-slot, vtable Map.set + VT/PIC tracing, and tests
This commit is contained in:
@ -206,6 +206,7 @@ impl JitEngine {
|
||||
/// Register built-in externs (collections)
|
||||
fn register_default_externs(&mut self) {
|
||||
use crate::jit::r#extern::collections as c;
|
||||
use crate::jit::r#extern::host_bridge as hb;
|
||||
self.register_extern(c::SYM_ARRAY_LEN, Arc::new(|args| c::array_len(args)));
|
||||
self.register_extern(c::SYM_ARRAY_GET, Arc::new(|args| c::array_get(args)));
|
||||
self.register_extern(c::SYM_ARRAY_SET, Arc::new(|args| c::array_set(args)));
|
||||
@ -213,6 +214,16 @@ impl JitEngine {
|
||||
self.register_extern(c::SYM_MAP_GET, Arc::new(|args| c::map_get(args)));
|
||||
self.register_extern(c::SYM_MAP_SET, Arc::new(|args| c::map_set(args)));
|
||||
self.register_extern(c::SYM_MAP_SIZE, Arc::new(|args| c::map_size(args)));
|
||||
// Host-bridge variants (by-slot via C symbol). Guarded by env opt-in for now.
|
||||
if std::env::var("NYASH_JIT_HOST_BRIDGE").ok().as_deref() == Some("1") {
|
||||
self.register_extern(hb::SYM_HOST_ARRAY_LEN, Arc::new(|args| hb::array_len(args)));
|
||||
self.register_extern(hb::SYM_HOST_ARRAY_GET, Arc::new(|args| hb::array_get(args)));
|
||||
self.register_extern(hb::SYM_HOST_ARRAY_SET, Arc::new(|args| hb::array_set(args)));
|
||||
self.register_extern(hb::SYM_HOST_MAP_SIZE, Arc::new(|args| hb::map_size(args)));
|
||||
self.register_extern(hb::SYM_HOST_MAP_GET, Arc::new(|args| hb::map_get(args)));
|
||||
self.register_extern(hb::SYM_HOST_MAP_SET, Arc::new(|args| hb::map_set(args)));
|
||||
self.register_extern(hb::SYM_HOST_MAP_HAS, Arc::new(|args| hb::map_has(args)));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_extern(&mut self, name: &str, f: Arc<dyn Fn(&[crate::backend::vm::VMValue]) -> crate::backend::vm::VMValue + Send + Sync>) {
|
||||
|
||||
83
src/jit/extern/host_bridge.rs
vendored
Normal file
83
src/jit/extern/host_bridge.rs
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
//! JIT externs bridging to NyRT host API (C symbols) via by-slot encoding.
|
||||
//!
|
||||
//! 目的: VM/JIT一致のため、JITからも host_api::nyrt_host_call_slot を使うPoC。
|
||||
|
||||
use crate::backend::vm::VMValue;
|
||||
|
||||
fn tlv_encode_values(args: &[VMValue]) -> Vec<u8> {
|
||||
use crate::runtime::plugin_ffi_common::encode as enc;
|
||||
let mut buf = crate::runtime::plugin_ffi_common::encode_tlv_header(args.len() as u16);
|
||||
for a in args {
|
||||
match a {
|
||||
VMValue::Integer(i) => enc::i64(&mut buf, *i),
|
||||
VMValue::Float(f) => enc::f64(&mut buf, *f),
|
||||
VMValue::Bool(b) => enc::bool(&mut buf, *b),
|
||||
VMValue::String(s) => enc::string(&mut buf, s),
|
||||
VMValue::BoxRef(_) | VMValue::Future(_) | VMValue::Void => enc::string(&mut buf, ""),
|
||||
}
|
||||
}
|
||||
buf
|
||||
}
|
||||
|
||||
fn call_slot(handle: u64, slot: u64, argv: &[VMValue]) -> VMValue {
|
||||
let tlv = tlv_encode_values(argv);
|
||||
let mut out = vec![0u8; 256];
|
||||
let mut out_len: usize = out.len();
|
||||
let code = unsafe { crate::runtime::host_api::nyrt_host_call_slot(handle, slot, tlv.as_ptr(), tlv.len(), out.as_mut_ptr(), &mut out_len) };
|
||||
if code != 0 { return VMValue::Void; }
|
||||
if let Some((tag, _sz, payload)) = crate::runtime::plugin_ffi_common::decode::tlv_first(&out[..out_len]) {
|
||||
match tag {
|
||||
6|7 => VMValue::String(crate::runtime::plugin_ffi_common::decode::string(payload)),
|
||||
1 => crate::runtime::plugin_ffi_common::decode::bool(payload).map(VMValue::Bool).unwrap_or(VMValue::Void),
|
||||
2 => crate::runtime::plugin_ffi_common::decode::i32(payload).map(|v| VMValue::Integer(v as i64)).unwrap_or(VMValue::Void),
|
||||
3 => crate::runtime::plugin_ffi_common::decode::u64(payload).map(|v| VMValue::Integer(v as i64)).unwrap_or(VMValue::Void),
|
||||
5 => crate::runtime::plugin_ffi_common::decode::f64(payload).map(VMValue::Float).unwrap_or(VMValue::Void),
|
||||
9 => {
|
||||
if let Some(h) = crate::runtime::plugin_ffi_common::decode::u64(payload) {
|
||||
if let Some(arc) = crate::runtime::host_handles::get(h) { return VMValue::BoxRef(arc); }
|
||||
}
|
||||
VMValue::Void
|
||||
}
|
||||
_ => VMValue::Void,
|
||||
}
|
||||
} else { VMValue::Void }
|
||||
}
|
||||
|
||||
fn to_handle(recv: &VMValue) -> Option<u64> {
|
||||
match recv {
|
||||
VMValue::BoxRef(arc) => Some(crate::runtime::host_handles::to_handle_arc(arc.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// Public bridge helpers (symbol strings align with collections for PoC)
|
||||
pub const SYM_HOST_ARRAY_GET: &str = "nyash.host.array.get"; // (ArrayBox, i64)
|
||||
pub const SYM_HOST_ARRAY_SET: &str = "nyash.host.array.set"; // (ArrayBox, i64, val)
|
||||
pub const SYM_HOST_ARRAY_LEN: &str = "nyash.host.array.len"; // (ArrayBox)
|
||||
pub const SYM_HOST_MAP_GET: &str = "nyash.host.map.get"; // (MapBox, key)
|
||||
pub const SYM_HOST_MAP_SET: &str = "nyash.host.map.set"; // (MapBox, key, val)
|
||||
pub const SYM_HOST_MAP_SIZE: &str = "nyash.host.map.size"; // (MapBox)
|
||||
pub const SYM_HOST_MAP_HAS: &str = "nyash.host.map.has"; // (MapBox, key)
|
||||
|
||||
pub fn array_get(args: &[VMValue]) -> VMValue {
|
||||
if let Some(h) = to_handle(args.get(0).unwrap_or(&VMValue::Void)) { call_slot(h, 100, &args[1..]) } else { VMValue::Void }
|
||||
}
|
||||
pub fn array_set(args: &[VMValue]) -> VMValue {
|
||||
if let Some(h) = to_handle(args.get(0).unwrap_or(&VMValue::Void)) { call_slot(h, 101, &args[1..]) } else { VMValue::Void }
|
||||
}
|
||||
pub fn array_len(args: &[VMValue]) -> VMValue {
|
||||
if let Some(h) = to_handle(args.get(0).unwrap_or(&VMValue::Void)) { call_slot(h, 102, &[]) } else { VMValue::Integer(0) }
|
||||
}
|
||||
pub fn map_get(args: &[VMValue]) -> VMValue {
|
||||
if let Some(h) = to_handle(args.get(0).unwrap_or(&VMValue::Void)) { call_slot(h, 203, &args[1..]) } else { VMValue::Void }
|
||||
}
|
||||
pub fn map_set(args: &[VMValue]) -> VMValue {
|
||||
if let Some(h) = to_handle(args.get(0).unwrap_or(&VMValue::Void)) { call_slot(h, 204, &args[1..]) } else { VMValue::Void }
|
||||
}
|
||||
pub fn map_size(args: &[VMValue]) -> VMValue {
|
||||
if let Some(h) = to_handle(args.get(0).unwrap_or(&VMValue::Void)) { call_slot(h, 200, &[]) } else { VMValue::Integer(0) }
|
||||
}
|
||||
pub fn map_has(args: &[VMValue]) -> VMValue {
|
||||
if let Some(h) = to_handle(args.get(0).unwrap_or(&VMValue::Void)) { call_slot(h, 202, &args[1..]) } else { VMValue::Bool(false) }
|
||||
}
|
||||
|
||||
1
src/jit/extern/mod.rs
vendored
1
src/jit/extern/mod.rs
vendored
@ -5,6 +5,7 @@
|
||||
//! these externs once call emission is added.
|
||||
|
||||
pub mod collections;
|
||||
pub mod host_bridge;
|
||||
pub mod handles;
|
||||
pub mod birth;
|
||||
pub mod runtime;
|
||||
|
||||
Reference in New Issue
Block a user