feat(phase285): Complete weak reference implementation (VM + LLVM harness)
Phase 285LLVM-1.1 to 1.4 + weak reference infrastructure: **LLVM Harness** (Phase 285LLVM-1.x): - 285LLVM-1.1: User Box registration & debug output - 285LLVM-1.2: WeakRef basic operations (identity deferred) - 285LLVM-1.3: InstanceBox field access (getField/setField) - 285LLVM-1.4: print Handle resolution (type tag propagation) **VM Runtime** (nyash_kernel): - FFI functions: nyrt_weak_new, nyrt_weak_to_strong, nyrt_weak_drop (crates/nyash_kernel/src/lib.rs: +209 lines) - WeakRef plugin invoke support (crates/nyash_kernel/src/plugin/invoke.rs: +250 lines) - weak_handles.rs: WeakRef handle registry (NEW) **LLVM Python Backend**: - WeakRef instruction lowering (weak.py: NEW) - Entry point integration (entry.py: +93 lines) - Instruction lowering (instruction_lower.py: +13 lines) - LLVM harness runner script (tools/run_llvm_harness.sh: NEW) **MIR & Runtime**: - WeakRef emission & validation - MIR JSON export for weak instructions - Environment variable support (NYASH_WEAK_*, HAKO_WEAK_*) **Documentation**: - CLAUDE.md: Phase 285 completion notes - LANGUAGE_REFERENCE_2025.md: Weak reference syntax - 10-Now.md & 30-Backlog.md: Phase 285 status updates Total: +864 lines, 24 files changed SSOT: docs/reference/language/lifecycle.md Related: Phase 285W-Syntax-0, Phase 285W-Syntax-0.1
This commit is contained in:
@ -31,6 +31,7 @@ pub mod unified_registry; // Deprecation warnings with warn-once guards
|
||||
pub mod extern_registry; // ExternCall (env.*) 登録・診断用レジストリ
|
||||
pub mod host_api; // C ABI: plugins -> host 逆呼び出しAPI(TLSでVMに橋渡し)
|
||||
pub mod host_handles; // C ABI(TLV) 向け HostHandle レジストリ(ユーザー/内蔵Box受け渡し)
|
||||
pub mod weak_handles; // Phase 285LLVM-1: WeakRef Handle レジストリ(bit 63 = 1)
|
||||
pub mod modules_registry;
|
||||
pub mod type_box_abi; // Phase 12: Nyash ABI (vtable) 雛形
|
||||
pub mod type_meta;
|
||||
|
||||
146
src/runtime/weak_handles.rs
Normal file
146
src/runtime/weak_handles.rs
Normal file
@ -0,0 +1,146 @@
|
||||
/*!
|
||||
* Weak Handle Registry (Phase 285LLVM-1)
|
||||
*
|
||||
* 目的:
|
||||
* - WeakRef のための LLVM handle 管理を提供。
|
||||
* - i64 handle (bit 63 = 1) → Weak<dyn NyashBox> をグローバルに保持。
|
||||
* - LLVM backend から FFI 経由でアクセス可能。
|
||||
*
|
||||
* Runtime 表現:
|
||||
* - Strong handle: 0x0000_0000_0000_0001 ~ 0x7FFF_FFFF_FFFF_FFFF (bit 63 = 0)
|
||||
* - Weak handle: 0x8000_0000_0000_0001 ~ 0xFFFF_FFFF_FFFF_FFFF (bit 63 = 1)
|
||||
*/
|
||||
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{
|
||||
atomic::{AtomicU64, Ordering},
|
||||
Arc, RwLock, Weak,
|
||||
};
|
||||
|
||||
use crate::box_trait::NyashBox;
|
||||
|
||||
/// Weak handle marker (bit 63 = 1)
|
||||
const WEAK_HANDLE_MARKER: u64 = 0x8000_0000_0000_0000;
|
||||
|
||||
/// Extract raw handle ID (clear bit 63)
|
||||
#[inline]
|
||||
fn extract_weak_id(handle: i64) -> u64 {
|
||||
(handle as u64) & !WEAK_HANDLE_MARKER
|
||||
}
|
||||
|
||||
/// Mark handle as weak (set bit 63)
|
||||
#[inline]
|
||||
fn mark_weak_handle(id: u64) -> i64 {
|
||||
(id | WEAK_HANDLE_MARKER) as i64
|
||||
}
|
||||
|
||||
/// Check if handle is weak (bit 63 = 1)
|
||||
#[inline]
|
||||
pub fn is_weak_handle(handle: i64) -> bool {
|
||||
(handle as u64 & WEAK_HANDLE_MARKER) != 0
|
||||
}
|
||||
|
||||
struct WeakRegistry {
|
||||
next: AtomicU64,
|
||||
map: RwLock<HashMap<u64, Weak<dyn NyashBox>>>,
|
||||
}
|
||||
|
||||
impl WeakRegistry {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
next: AtomicU64::new(1),
|
||||
map: RwLock::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn alloc(&self, weak: Weak<dyn NyashBox>) -> i64 {
|
||||
let id = self.next.fetch_add(1, Ordering::Relaxed);
|
||||
if let Ok(mut m) = self.map.write() {
|
||||
m.insert(id, weak);
|
||||
}
|
||||
mark_weak_handle(id)
|
||||
}
|
||||
|
||||
fn get(&self, handle: i64) -> Option<Weak<dyn NyashBox>> {
|
||||
let id = extract_weak_id(handle);
|
||||
self.map.read().ok().and_then(|m| m.get(&id).cloned())
|
||||
}
|
||||
|
||||
fn drop_handle(&self, handle: i64) {
|
||||
let id = extract_weak_id(handle);
|
||||
if let Ok(mut m) = self.map.write() {
|
||||
m.remove(&id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static WEAK_REG: OnceCell<WeakRegistry> = OnceCell::new();
|
||||
fn weak_reg() -> &'static WeakRegistry {
|
||||
WEAK_REG.get_or_init(WeakRegistry::new)
|
||||
}
|
||||
|
||||
/// Weak<dyn NyashBox> → Weak Handle (i64, bit 63 = 1)
|
||||
pub fn to_handle_weak(weak: Weak<dyn NyashBox>) -> i64 {
|
||||
weak_reg().alloc(weak)
|
||||
}
|
||||
|
||||
/// Weak Handle (i64) → Weak<dyn NyashBox>
|
||||
pub fn get_weak(handle: i64) -> Option<Weak<dyn NyashBox>> {
|
||||
weak_reg().get(handle)
|
||||
}
|
||||
|
||||
/// Drop weak handle (release from registry)
|
||||
pub fn drop_weak_handle(handle: i64) {
|
||||
weak_reg().drop_handle(handle)
|
||||
}
|
||||
|
||||
/// Upgrade weak handle to strong handle
|
||||
/// Returns: strong handle (>0) on success, 0 (Void) on failure
|
||||
pub fn upgrade_weak_handle(weak_handle: i64) -> i64 {
|
||||
if let Some(weak) = get_weak(weak_handle) {
|
||||
if let Some(arc) = weak.upgrade() {
|
||||
return crate::runtime::host_handles::to_handle_arc(arc) as i64;
|
||||
}
|
||||
}
|
||||
0 // Void (null)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::box_trait::StringBox;
|
||||
|
||||
#[test]
|
||||
fn test_weak_handle_marker() {
|
||||
let strong_handle = 0x0000_0000_0000_0001i64;
|
||||
let weak_handle = 0x8000_0000_0000_0001i64;
|
||||
|
||||
assert!(!is_weak_handle(strong_handle));
|
||||
assert!(is_weak_handle(weak_handle));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_weak_handle_lifecycle() {
|
||||
let arc: Arc<dyn NyashBox> = Arc::new(StringBox::new("test"));
|
||||
let weak = Arc::downgrade(&arc);
|
||||
|
||||
// Allocate weak handle
|
||||
let weak_handle = to_handle_weak(weak.clone());
|
||||
assert!(is_weak_handle(weak_handle));
|
||||
|
||||
// Upgrade should succeed (arc is alive)
|
||||
let strong_handle = upgrade_weak_handle(weak_handle);
|
||||
assert!(strong_handle > 0);
|
||||
|
||||
// Drop arc
|
||||
drop(arc);
|
||||
|
||||
// Upgrade should fail (arc is dead)
|
||||
let result = upgrade_weak_handle(weak_handle);
|
||||
assert_eq!(result, 0); // Void
|
||||
|
||||
// Cleanup
|
||||
drop_weak_handle(weak_handle);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user