240 lines
10 KiB
Rust
240 lines
10 KiB
Rust
|
|
// ---- Handle-based birth shims for AOT/JIT object linkage ----
|
||
|
|
// These resolve symbols like "nyash.string.birth_h" referenced by ObjectModule.
|
||
|
|
|
||
|
|
// Generic birth by type_id -> handle (no args). Exported as nyash.box.birth_h
|
||
|
|
#[export_name = "nyash.box.birth_h"]
|
||
|
|
pub extern "C" fn nyash_box_birth_h_export(type_id: i64) -> i64 {
|
||
|
|
if type_id <= 0 {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
let tid = type_id as u32;
|
||
|
|
// Map type_id back to type name
|
||
|
|
let name_opt = nyash_rust::runtime::plugin_loader_unified::get_global_plugin_host()
|
||
|
|
.read()
|
||
|
|
.ok()
|
||
|
|
.and_then(|h| h.config_ref().map(|cfg| cfg.box_types.clone()))
|
||
|
|
.and_then(|m| m.into_iter().find(|(_k, v)| *v == tid).map(|(k, _v)| k));
|
||
|
|
if let Some(box_type) = name_opt {
|
||
|
|
if let Ok(host_g) = nyash_rust::runtime::get_global_plugin_host().read() {
|
||
|
|
if let Ok(b) = host_g.create_box(&box_type, &[]) {
|
||
|
|
let arc: std::sync::Arc<dyn nyash_rust::box_trait::NyashBox> =
|
||
|
|
std::sync::Arc::from(b);
|
||
|
|
let h = nyash_rust::jit::rt::handles::to_handle(arc);
|
||
|
|
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||
|
|
println!(
|
||
|
|
"nyrt: birth_h {} (type_id={}) -> handle={}",
|
||
|
|
box_type, tid, h
|
||
|
|
);
|
||
|
|
}
|
||
|
|
return h as i64;
|
||
|
|
} else if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||
|
|
eprintln!(
|
||
|
|
"nyrt: birth_h {} (type_id={}) FAILED: create_box",
|
||
|
|
box_type, tid
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||
|
|
eprintln!("nyrt: birth_h (type_id={}) FAILED: type map not found", tid);
|
||
|
|
}
|
||
|
|
0
|
||
|
|
}
|
||
|
|
// Generic birth with args: (type_id, argc, a1, a2) -> handle
|
||
|
|
// Export name: nyash.box.birth_i64
|
||
|
|
#[export_name = "nyash.box.birth_i64"]
|
||
|
|
pub extern "C" fn nyash_box_birth_i64_export(type_id: i64, argc: i64, a1: i64, a2: i64) -> i64 {
|
||
|
|
use nyash_rust::runtime::plugin_loader_v2::PluginBoxV2;
|
||
|
|
if type_id <= 0 {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
let mut invoke: Option<
|
||
|
|
unsafe extern "C" fn(u32, u32, u32, *const u8, usize, *mut u8, *mut usize) -> i32,
|
||
|
|
> = None;
|
||
|
|
// Resolve invoke_fn via temporary instance
|
||
|
|
let box_type_name = nyash_rust::runtime::plugin_loader_unified::get_global_plugin_host()
|
||
|
|
.read()
|
||
|
|
.ok()
|
||
|
|
.and_then(|h| h.config_ref().map(|cfg| cfg.box_types.clone()))
|
||
|
|
.and_then(|m| {
|
||
|
|
m.into_iter()
|
||
|
|
.find(|(_k, v)| *v == (type_id as u32))
|
||
|
|
.map(|(k, _v)| k)
|
||
|
|
})
|
||
|
|
.unwrap_or_else(|| "PluginBox".to_string());
|
||
|
|
if let Ok(host_g) = nyash_rust::runtime::get_global_plugin_host().read() {
|
||
|
|
if let Ok(b) = host_g.create_box(&box_type_name, &[]) {
|
||
|
|
if let Some(p) = b.as_any().downcast_ref::<PluginBoxV2>() {
|
||
|
|
invoke = Some(p.inner.invoke_fn);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if invoke.is_none() {
|
||
|
|
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||
|
|
eprintln!("nyrt: birth_i64 (type_id={}) FAILED: no invoke", type_id);
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
let method_id: u32 = 0; // birth
|
||
|
|
let instance_id: u32 = 0; // static
|
||
|
|
// Build TLV args
|
||
|
|
use nyash_rust::jit::rt::handles;
|
||
|
|
let nargs = argc.max(0) as usize;
|
||
|
|
let mut buf = nyash_rust::runtime::plugin_ffi_common::encode_tlv_header(nargs as u16);
|
||
|
|
let mut encode_handle = |h: i64| {
|
||
|
|
if h > 0 {
|
||
|
|
if let Some(obj) = handles::get(h as u64) {
|
||
|
|
if let Some(p) = obj.as_any().downcast_ref::<PluginBoxV2>() {
|
||
|
|
let host = nyash_rust::runtime::get_global_plugin_host();
|
||
|
|
if let Ok(hg) = host.read() {
|
||
|
|
if p.box_type == "StringBox" {
|
||
|
|
if let Ok(Some(sb)) = hg.invoke_instance_method(
|
||
|
|
"StringBox",
|
||
|
|
"toUtf8",
|
||
|
|
p.instance_id(),
|
||
|
|
&[],
|
||
|
|
) {
|
||
|
|
if let Some(s) = sb
|
||
|
|
.as_any()
|
||
|
|
.downcast_ref::<nyash_rust::box_trait::StringBox>()
|
||
|
|
{
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::encode::string(
|
||
|
|
&mut buf, &s.value,
|
||
|
|
);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else if p.box_type == "IntegerBox" {
|
||
|
|
if let Ok(Some(ibx)) =
|
||
|
|
hg.invoke_instance_method("IntegerBox", "get", p.instance_id(), &[])
|
||
|
|
{
|
||
|
|
if let Some(i) = ibx
|
||
|
|
.as_any()
|
||
|
|
.downcast_ref::<nyash_rust::box_trait::IntegerBox>()
|
||
|
|
{
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::encode::i64(
|
||
|
|
&mut buf, i.value,
|
||
|
|
);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::encode::plugin_handle(
|
||
|
|
&mut buf,
|
||
|
|
p.inner.type_id,
|
||
|
|
p.instance_id(),
|
||
|
|
);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::encode::i64(&mut buf, h);
|
||
|
|
};
|
||
|
|
if nargs >= 1 {
|
||
|
|
encode_handle(a1);
|
||
|
|
}
|
||
|
|
if nargs >= 2 {
|
||
|
|
encode_handle(a2);
|
||
|
|
}
|
||
|
|
// Extra birth args from legacy VM when present
|
||
|
|
if nargs > 2 && std::env::var("NYASH_JIT_ARGS_HANDLE_ONLY").ok().as_deref() != Some("1") {
|
||
|
|
for pos in 3..=nargs {
|
||
|
|
nyash_rust::jit::rt::with_legacy_vm_args(|args| {
|
||
|
|
if let Some(v) = args.get(pos) {
|
||
|
|
use nyash_rust::backend::vm::VMValue as V;
|
||
|
|
match v {
|
||
|
|
V::String(s) => {
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::encode::string(&mut buf, s)
|
||
|
|
}
|
||
|
|
V::Integer(i) => {
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::encode::i64(&mut buf, *i)
|
||
|
|
}
|
||
|
|
V::Float(f) => {
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::encode::f64(&mut buf, *f)
|
||
|
|
}
|
||
|
|
V::Bool(b) => {
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::encode::bool(&mut buf, *b)
|
||
|
|
}
|
||
|
|
V::BoxRef(bx) => {
|
||
|
|
if let Some(pb) = bx.as_any().downcast_ref::<PluginBoxV2>() {
|
||
|
|
if let Some(bufbox) =
|
||
|
|
bx.as_any()
|
||
|
|
.downcast_ref::<nyash_rust::boxes::buffer::BufferBox>()
|
||
|
|
{
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::encode::bytes(
|
||
|
|
&mut buf,
|
||
|
|
&bufbox.to_vec(),
|
||
|
|
);
|
||
|
|
} else {
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::encode::plugin_handle(
|
||
|
|
&mut buf,
|
||
|
|
pb.inner.type_id,
|
||
|
|
pb.instance_id(),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
let s = bx.to_string_box().value;
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::encode::string(&mut buf, &s)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_ => {}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
let mut out = vec![0u8; 1024];
|
||
|
|
let mut out_len: usize = out.len();
|
||
|
|
let rc = unsafe {
|
||
|
|
invoke.unwrap()(
|
||
|
|
type_id as u32,
|
||
|
|
method_id,
|
||
|
|
instance_id,
|
||
|
|
buf.as_ptr(),
|
||
|
|
buf.len(),
|
||
|
|
out.as_mut_ptr(),
|
||
|
|
&mut out_len,
|
||
|
|
)
|
||
|
|
};
|
||
|
|
if rc != 0 {
|
||
|
|
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||
|
|
eprintln!(
|
||
|
|
"nyrt: birth_i64 (type_id={}) FAILED: invoke rc={}",
|
||
|
|
type_id, rc
|
||
|
|
);
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if let Some((tag, _sz, payload)) =
|
||
|
|
nyash_rust::runtime::plugin_ffi_common::decode::tlv_first(&out[..out_len])
|
||
|
|
{
|
||
|
|
if tag == 8 && payload.len() == 8 {
|
||
|
|
let mut t = [0u8; 4];
|
||
|
|
t.copy_from_slice(&payload[0..4]);
|
||
|
|
let mut i = [0u8; 4];
|
||
|
|
i.copy_from_slice(&payload[4..8]);
|
||
|
|
let r_type = u32::from_le_bytes(t);
|
||
|
|
let r_inst = u32::from_le_bytes(i);
|
||
|
|
let pb = nyash_rust::runtime::plugin_loader_v2::make_plugin_box_v2(
|
||
|
|
box_type_name.clone(),
|
||
|
|
r_type,
|
||
|
|
r_inst,
|
||
|
|
invoke.unwrap(),
|
||
|
|
);
|
||
|
|
let arc: std::sync::Arc<dyn nyash_rust::box_trait::NyashBox> = std::sync::Arc::new(pb);
|
||
|
|
let h = nyash_rust::jit::rt::handles::to_handle(arc);
|
||
|
|
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||
|
|
println!(
|
||
|
|
"nyrt: birth_i64 {} (type_id={}) argc={} -> handle={}",
|
||
|
|
box_type_name, type_id, nargs, h
|
||
|
|
);
|
||
|
|
}
|
||
|
|
return h as i64;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||
|
|
eprintln!("nyrt: birth_i64 (type_id={}) FAILED: decode", type_id);
|
||
|
|
}
|
||
|
|
0
|
||
|
|
}
|