Phase 10.10: GC Switchable Runtime & Unified Debug System 実装完了

Phase 10.10の主要実装:
- GcConfigBox: GC設定の実行時制御(counting/trace/barrier_strict)
- DebugConfigBox: デバッグ設定の統一管理(JIT events/stats/dump/dot)
- メソッドディスパッチ: system_methods.rsで両Boxのメソッド実装
- CountingGC動作確認: write_barriers正常カウント(VM実行時)

技術的詳細:
- BoxCore/BoxBase統一アーキテクチャを活用
- setFlag/getFlag/apply/summaryメソッドで統一API提供
- 環境変数経由でVM/JITランタイムと連携
- GcConfigBox.apply()は次回実行から有効(ランタイム作成前に環境変数参照)

テスト済み:
- examples/gc_counting_demo.nyash: CountingGCの動作確認
- write_barriers=3でArray.push/set, Map.setを正しくカウント
- NYASH_GC_TRACE=1でGC統計出力確認

Box-First哲学の体現: 設定も制御も観測もすべてBox!

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-28 22:31:51 +09:00
parent 4e1b595796
commit d67f27f4b8
27 changed files with 1341 additions and 63 deletions

View File

@ -21,6 +21,7 @@ pub const SYM_ARRAY_PUSH_H: &str = "nyash.array.push_h";
pub const SYM_ARRAY_LAST_H: &str = "nyash.array.last_h";
pub const SYM_MAP_SIZE_H: &str = "nyash.map.size_h";
pub const SYM_MAP_GET_H: &str = "nyash.map.get_h";
pub const SYM_MAP_GET_HH: &str = "nyash.map.get_hh";
pub const SYM_MAP_SET_H: &str = "nyash.map.set_h";
pub const SYM_MAP_HAS_H: &str = "nyash.map.has_h";
// Generic read-only helper
@ -61,18 +62,45 @@ pub fn array_get(args: &[VMValue]) -> VMValue {
}
pub fn array_set(args: &[VMValue]) -> VMValue {
// Enforce policy for mutating operation
if crate::jit::policy::current().read_only &&
!crate::jit::policy::current().hostcall_whitelist.iter().any(|s| s == SYM_ARRAY_SET)
{
crate::jit::events::emit(
"hostcall", "<jit>", None, None,
serde_json::json!({"id": SYM_ARRAY_SET, "decision":"fallback", "reason":"policy_denied_mutating"})
);
return VMValue::Integer(0);
}
if let (Some(arr), Some(VMValue::Integer(idx)), Some(value)) = (as_array(args), args.get(1), args.get(2)) {
let val_box: Box<dyn NyashBox> = value.to_nyash_box();
let res = arr.set(Box::new(IntegerBox::new(*idx)), val_box);
crate::jit::events::emit(
"hostcall", "<jit>", None, None,
serde_json::json!({"id": SYM_ARRAY_SET, "decision":"allow", "argc":3, "arg_types":["Handle","I64","Handle"]})
);
return VMValue::from_nyash_box(res);
}
VMValue::BoxRef(Arc::new(StringBox::new("Error: array.set expects (ArrayBox, i64, value)")))
}
pub fn array_push(args: &[VMValue]) -> VMValue {
if crate::jit::policy::current().read_only &&
!crate::jit::policy::current().hostcall_whitelist.iter().any(|s| s == SYM_ARRAY_PUSH)
{
crate::jit::events::emit(
"hostcall", "<jit>", None, None,
serde_json::json!({"id": SYM_ARRAY_PUSH, "decision":"fallback", "reason":"policy_denied_mutating"})
);
return VMValue::Integer(0);
}
if let (Some(arr), Some(value)) = (as_array(args), args.get(1)) {
let val_box: Box<dyn NyashBox> = value.to_nyash_box();
let res = arr.push(val_box);
crate::jit::events::emit(
"hostcall", "<jit>", None, None,
serde_json::json!({"id": SYM_ARRAY_PUSH, "decision":"allow", "argc":2, "arg_types":["Handle","Handle"]})
);
return VMValue::from_nyash_box(res);
}
VMValue::BoxRef(Arc::new(StringBox::new("Error: array.push expects (ArrayBox, value)")))
@ -87,10 +115,24 @@ pub fn map_get(args: &[VMValue]) -> VMValue {
}
pub fn map_set(args: &[VMValue]) -> VMValue {
if crate::jit::policy::current().read_only &&
!crate::jit::policy::current().hostcall_whitelist.iter().any(|s| s == SYM_MAP_SET)
{
crate::jit::events::emit(
"hostcall", "<jit>", None, None,
serde_json::json!({"id": SYM_MAP_SET, "decision":"fallback", "reason":"policy_denied_mutating"})
);
return VMValue::Integer(0);
}
if let (Some(map), Some(key), Some(value)) = (as_map(args), args.get(1), args.get(2)) {
let key_box: Box<dyn NyashBox> = key.to_nyash_box();
let val_box: Box<dyn NyashBox> = value.to_nyash_box();
return VMValue::from_nyash_box(map.set(key_box, val_box));
let out = map.set(key_box, val_box);
crate::jit::events::emit(
"hostcall", "<jit>", None, None,
serde_json::json!({"id": SYM_MAP_SET, "decision":"allow", "argc":3, "arg_types":["Handle","Handle","Handle"]})
);
return VMValue::from_nyash_box(out);
}
VMValue::BoxRef(Arc::new(StringBox::new("Error: map.set expects (MapBox, key, value)")))
}