Docs: Add phase_9_79b_3_vm_vtable_thunks_and_pic.md\n- Plan to formalize TypeMeta+Thunk and upgrade PIC to poly\n- Diagnostics, risks, milestones, exit criteria, and Phase 10 readiness

This commit is contained in:
Moe Charm
2025-08-27 00:03:48 +09:00
parent c0b70c0e4e
commit edf5ccfcb4
10 changed files with 313 additions and 21 deletions

View File

@ -214,6 +214,8 @@ pub struct VM {
pub(super) boxcall_pic_funcname: std::collections::HashMap<String, String>,
/// VTable-like cache: (type, method_id, arity) → direct target (InstanceBox method)
pub(super) boxcall_vtable_funcname: std::collections::HashMap<String, String>,
/// Version map for cache invalidation: label -> version
pub(super) type_versions: std::collections::HashMap<String, u32>,
// Phase 9.78a: Add unified Box handling components
// TODO: Re-enable when interpreter refactoring is complete
// /// Box registry for creating all Box types
@ -277,6 +279,7 @@ impl VM {
boxcall_pic_hits: std::collections::HashMap::new(),
boxcall_pic_funcname: std::collections::HashMap::new(),
boxcall_vtable_funcname: std::collections::HashMap::new(),
type_versions: std::collections::HashMap::new(),
// TODO: Re-enable when interpreter refactoring is complete
// box_registry: Arc::new(UnifiedBoxRegistry::new()),
// #[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
@ -305,6 +308,7 @@ impl VM {
boxcall_pic_hits: std::collections::HashMap::new(),
boxcall_pic_funcname: std::collections::HashMap::new(),
boxcall_vtable_funcname: std::collections::HashMap::new(),
type_versions: std::collections::HashMap::new(),
}
}
@ -1027,6 +1031,75 @@ console.log("ok")
assert_eq!(result.to_string_box().value, "void");
}
#[test]
fn test_vm_user_box_vtable_caching_two_calls() {
// Defines a simple user box and calls the same method twice; ensures correctness.
// Builder reserves slots for user methods (from 4), so method_id should be present,
// enabling vtable cache population on first call and (conceptually) direct call on second.
let code = r#"
box Greeter {
init { name }
birth(n) { me.name = n }
greet() { return "Hi, " + me.name }
}
local g
g = new Greeter("Bob")
g.greet()
g.greet()
"#;
// Parse to AST
let ast = crate::parser::NyashParser::parse_from_string(code).expect("parse failed");
// Prepare runtime with user-defined declarations and factory
let runtime = {
let rt = crate::runtime::NyashRuntime::new();
// Collect box declarations into runtime so that user-defined factory works
fn collect_box_decls(ast: &crate::ast::ASTNode, runtime: &crate::runtime::NyashRuntime) {
use crate::core::model::BoxDeclaration as CoreBoxDecl;
fn walk(node: &crate::ast::ASTNode, runtime: &crate::runtime::NyashRuntime) {
match node {
crate::ast::ASTNode::Program { statements, .. } => for st in statements { walk(st, runtime); },
crate::ast::ASTNode::BoxDeclaration { name, fields, public_fields, private_fields, methods, constructors, init_fields, weak_fields, is_interface, extends, implements, type_parameters, .. } => {
let decl = CoreBoxDecl {
name: name.clone(),
fields: fields.clone(),
public_fields: public_fields.clone(),
private_fields: private_fields.clone(),
methods: methods.clone(),
constructors: constructors.clone(),
init_fields: init_fields.clone(),
weak_fields: weak_fields.clone(),
is_interface: *is_interface,
extends: extends.clone(),
implements: implements.clone(),
type_parameters: type_parameters.clone(),
};
if let Ok(mut map) = runtime.box_declarations.write() { map.insert(name.clone(), decl); }
}
_ => {}
}
}
walk(ast, runtime);
}
collect_box_decls(&ast, &rt);
// Register user-defined factory
let mut shared = crate::interpreter::SharedState::new();
shared.box_declarations = rt.box_declarations.clone();
let udf = std::sync::Arc::new(crate::box_factory::user_defined::UserDefinedBoxFactory::new(shared));
if let Ok(mut reg) = rt.box_registry.lock() { reg.register(udf); }
rt
};
// Compile and execute
let mut compiler = crate::mir::MirCompiler::new();
let compile_result = compiler.compile(ast).expect("mir compile failed");
let mut vm = VM::with_runtime(runtime);
let result = vm.execute_module(&compile_result.module).expect("vm exec failed");
assert_eq!(result.to_string_box().value, "Hi, Bob");
}
#[test]
fn test_vm_fastpath_universal_type_and_equals() {
// toString/type/equals/cloneのうち、typeとequalsのfast-pathを検証