feat(perf): add Phase 21.8 foundation for IntArrayCore/MatI64 numeric boxes

Prepare infrastructure for specialized numeric array benchmarking:
- Add IntArrayCore plugin stub (crates/nyash_kernel/src/plugin/intarray.rs)
- Add IntArrayCore/MatI64 box definitions (lang/src/runtime/numeric/)
- Add Phase 21.8 documentation and task tracking
- Update nyash.toml/hako.toml with numeric library configuration
- Extend microbench.sh for matmul_core benchmark case

Next: Resolve Stage-B MirBuilder to recognize MatI64/IntArrayCore as boxes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-14 15:18:14 +09:00
parent f1fa182a4b
commit 8214176814
11 changed files with 549 additions and 3 deletions

View File

@ -0,0 +1,159 @@
// IntArrayCore helpers for AOT/VM bridge (handle-based, ring1 numeric core)
// API (Hako-facing via externcall):
// - nyash.intarray.new_h(len) -> handle (IntArrayCore)
// - nyash.intarray.len_h(h) -> i64
// - nyash.intarray.get_hi(h,i) -> i64
// - nyash.intarray.set_hii(h,i,v) -> i64 (0=ok, non-zero=error)
use nyash_rust::{
box_trait::{BoxCore, NyashBox, StringBox},
boxes::basic::BoolBox,
runtime::host_handles as handles,
};
use std::any::Any;
use std::sync::RwLock;
/// Minimal numeric core: contiguous i64 buffer + length.
/// This box is intended for internal numeric kernels (matmul_core 等) 専用で、
/// 一般APIは .hako 側のラッパーMatI64 等)から利用する。
#[derive(Debug)]
pub struct IntArrayCore {
base: nyash_rust::box_trait::BoxBase,
data: RwLock<Vec<i64>>,
}
impl IntArrayCore {
pub fn new(len: i64) -> Self {
let n = if len <= 0 { 0 } else { len as usize };
IntArrayCore {
base: nyash_rust::box_trait::BoxBase::new(),
data: RwLock::new(vec![0; n]),
}
}
pub fn len_i64(&self) -> i64 {
self.data.read().unwrap().len() as i64
}
pub fn get_i64(&self, idx: i64) -> Option<i64> {
if idx < 0 {
return None;
}
let i = idx as usize;
let guard = self.data.read().unwrap();
guard.get(i).copied()
}
pub fn set_i64(&self, idx: i64, v: i64) -> bool {
if idx < 0 {
return false;
}
let i = idx as usize;
let mut guard = self.data.write().unwrap();
if i >= guard.len() {
return false;
}
guard[i] = v;
true
}
}
impl BoxCore for IntArrayCore {
fn box_id(&self) -> u64 {
self.base.id
}
fn parent_type_id(&self) -> Option<std::any::TypeId> {
self.base.parent_type_id
}
fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "IntArrayCore(len={})", self.data.len())
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
impl NyashBox for IntArrayCore {
fn to_string_box(&self) -> StringBox {
StringBox::new(&format!("IntArrayCore(len={})", self.data.len()))
}
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
if let Some(o) = other.as_any().downcast_ref::<IntArrayCore>() {
BoolBox::new(self.data == o.data)
} else {
BoolBox::new(false)
}
}
fn clone_box(&self) -> Box<dyn NyashBox> {
Box::new(IntArrayCore {
base: self.base.clone(),
data: RwLock::new(self.data.read().unwrap().clone()),
})
}
fn share_box(&self) -> Box<dyn NyashBox> {
// Identity semantics are not required here; clone is fine.
self.clone_box()
}
}
// --- Extern API (handle-based) ---
fn get_core(handle: i64) -> Option<std::sync::Arc<dyn NyashBox>> {
if handle <= 0 {
return None;
}
handles::get(handle as u64)
}
#[export_name = \"nyash.intarray.new_h\"]
pub extern \"C\" fn nyash_intarray_new_h(len: i64) -> i64 {
let core = IntArrayCore::new(len);
let arc: std::sync::Arc<dyn NyashBox> = std::sync::Arc::new(core);
let h = handles::to_handle_arc(arc) as i64;
if std::env::var(\"NYASH_CLI_VERBOSE\").ok().as_deref() == Some(\"1\") {
eprintln!(\"[INTARRAY] new_h(len={}) -> handle={}\", len, h);
}
h
}
#[export_name = \"nyash.intarray.len_h\"]
pub extern \"C\" fn nyash_intarray_len_h(handle: i64) -> i64 {
if let Some(obj) = get_core(handle) {
if let Some(core) = obj.as_any().downcast_ref::<IntArrayCore>() {
return core.len_i64();
}
}
0
}
#[export_name = \"nyash.intarray.get_hi\"]
pub extern \"C\" fn nyash_intarray_get_hi(handle: i64, idx: i64) -> i64 {
if let Some(obj) = get_core(handle) {
if let Some(core) = obj.as_any().downcast_ref::<IntArrayCore>() {
if let Some(v) = core.get_i64(idx) {
return v;
}
}
}
0
}
#[export_name = \"nyash.intarray.set_hii\"]
pub extern \"C\" fn nyash_intarray_set_hii(handle: i64, idx: i64, val: i64) -> i64 {
if let Some(obj) = get_core(handle) {
if let Some(core) = obj.as_any().downcast_ref::<IntArrayCore>() {
return if core.set_i64(idx, val) { 0 } else { 1 };
}
}
1
}

View File

@ -6,6 +6,7 @@ pub mod instance;
pub mod invoke;
pub mod invoke_core;
pub mod map;
pub mod intarray;
pub mod semantics;
pub mod string;
@ -17,5 +18,6 @@ pub use instance::*;
pub use invoke::*;
pub use invoke_core::*;
pub use map::*;
pub use intarray::*;
pub use semantics::*;
pub use string::*;