feat: 为内核构造、BuiltinWorld 初始化、ShapeForge/StringForge/CodeForge 添加结构化日志

This commit is contained in:
2026-06-26 21:09:36 +08:00
parent 3e7c082293
commit fc59505116
8 changed files with 45 additions and 5 deletions
Generated
+1
View File
@@ -1098,6 +1098,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"lru", "lru",
"oxide_bytecode", "oxide_bytecode",
"oxide_log",
] ]
[[package]] [[package]]
+1
View File
@@ -8,4 +8,5 @@ description = "OxideJS - Compiler-independent compiled module cache"
[dependencies] [dependencies]
oxide_bytecode = { path = "../oxide_bytecode" } oxide_bytecode = { path = "../oxide_bytecode" }
oxide_log = { path = "../oxide_log" }
lru.workspace = true lru.workspace = true
@@ -0,0 +1,6 @@
#[macro_export]
macro_rules! code_cache_debug {
($($arg:tt)*) => {
oxide_log::__log_event!("oxide::kernel", oxide_log::tracing::Level::DEBUG, $($arg)*)
};
}
+21 -2
View File
@@ -6,6 +6,8 @@ use std::sync::{Arc, Mutex};
use lru::LruCache; use lru::LruCache;
use oxide_bytecode::CompiledModule; use oxide_bytecode::CompiledModule;
mod code_cache_log;
/// Shared compiled-module cache keyed by a caller-provided safe module hash. /// Shared compiled-module cache keyed by a caller-provided safe module hash.
/// ///
/// The cache intentionally does not know how to parse or compile JavaScript. /// The cache intentionally does not know how to parse or compile JavaScript.
@@ -26,12 +28,27 @@ impl CodeForge {
} }
pub fn get(&self, hash: u64) -> Option<Arc<CompiledModule>> { pub fn get(&self, hash: u64) -> Option<Arc<CompiledModule>> {
self.map.lock().unwrap().get(&hash).map(Arc::clone) let result = self.map.lock().unwrap().get(&hash).map(Arc::clone);
if result.is_some() {
code_cache_debug!("CodeForge hit: hash={:#x}", hash);
}
result
} }
pub fn insert(&self, hash: u64, module: CompiledModule) -> Arc<CompiledModule> { pub fn insert(&self, hash: u64, module: CompiledModule) -> Arc<CompiledModule> {
let module = Arc::new(module); let module = Arc::new(module);
self.map.lock().unwrap().put(hash, Arc::clone(&module)); let mut cache = self.map.lock().unwrap();
let evicted_hash = if cache.len() == cache.cap().get() && !cache.contains(&hash) {
cache.peek_lru().map(|(k, _)| *k)
} else {
None
};
cache.put(hash, Arc::clone(&module));
drop(cache);
match evicted_hash {
Some(evicted_hash) => code_cache_debug!("CodeForge evict: hash={:#x}", evicted_hash),
None => code_cache_debug!("CodeForge insert: hash={:#x}", hash),
}
module module
} }
@@ -44,6 +61,7 @@ impl CodeForge {
if let Some(module) = cache.get(&hash) { if let Some(module) = cache.get(&hash) {
let module = Arc::clone(module); let module = Arc::clone(module);
drop(cache); drop(cache);
code_cache_debug!("CodeForge hit: hash={:#x}", hash);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
let fresh = compile()?; let fresh = compile()?;
@@ -57,6 +75,7 @@ impl CodeForge {
} }
let module = Arc::new(compile()?); let module = Arc::new(compile()?);
self.map.lock().unwrap().put(hash, Arc::clone(&module)); self.map.lock().unwrap().put(hash, Arc::clone(&module));
code_cache_debug!("CodeForge miss: hash={:#x}", hash);
Ok(module) Ok(module)
} }
+2
View File
@@ -3,6 +3,7 @@ use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
use oxide_types::value::JsValue; use oxide_types::value::JsValue;
use crate::kernel::{BuiltinDirtySet, BuiltinId}; use crate::kernel::{BuiltinDirtySet, BuiltinId};
use crate::kernel_info;
use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID}; use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID};
use crate::string_forge::PermInterner; use crate::string_forge::PermInterner;
@@ -643,6 +644,7 @@ impl BuiltinWorld {
stub_objects, stub_objects,
}; };
wire_builtin_world_links(&world); wire_builtin_world_links(&world);
kernel_info!("BuiltinWorld initialized");
world world
} }
+7 -2
View File
@@ -9,6 +9,7 @@ use oxide_types::value::JsValue;
use crate::builtin::BuiltinWorld; use crate::builtin::BuiltinWorld;
use crate::code_forge::CodeForge; use crate::code_forge::CodeForge;
use crate::kernel_info;
use crate::prop_forge::PropForge; use crate::prop_forge::PropForge;
use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID}; use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID};
use crate::string_forge::PermInterner; use crate::string_forge::PermInterner;
@@ -124,13 +125,17 @@ impl KernelCore {
NonZeroUsize::new(config.max_cached_modules).expect("max_cached_modules must be greater than zero"), NonZeroUsize::new(config.max_cached_modules).expect("max_cached_modules must be greater than zero"),
)); ));
let prop_forge = Arc::new(PropForge::new()); let prop_forge = Arc::new(PropForge::new());
Arc::new(Self { let max_cached = config.max_cached_modules;
let min_pool = config.min_pool_size;
let core = Arc::new(Self {
config, config,
perm_interner, perm_interner,
shape_forge, shape_forge,
code_forge, code_forge,
prop_forge, prop_forge,
}) });
kernel_info!("KernelCore initialized: max_cached_modules={}, min_pool={}", max_cached, min_pool);
core
} }
pub fn perm_interner(&self) -> &Arc<PermInterner> { pub fn perm_interner(&self) -> &Arc<PermInterner> {
+3 -1
View File
@@ -4,7 +4,7 @@ use std::sync::{Arc, RwLock};
use dashmap::DashMap; use dashmap::DashMap;
use crate::kernel_debug; use crate::{kernel_debug, kernel_trace};
pub type ShapeId = u32; pub type ShapeId = u32;
pub type StringIndex = u32; pub type StringIndex = u32;
@@ -83,6 +83,8 @@ impl ShapeForge {
pub fn make_shape(&self, parent_id: ShapeId, prop_name: StringIndex) -> ShapeId { pub fn make_shape(&self, parent_id: ShapeId, prop_name: StringIndex) -> ShapeId {
let key = Self::pack_key(parent_id, prop_name); let key = Self::pack_key(parent_id, prop_name);
kernel_trace!("ShapeForge lookup: parent={} prop={}", parent_id, prop_name);
if let Some(entry) = self.transitions.get(&key) { if let Some(entry) = self.transitions.get(&key) {
kernel_debug!("ShapeForge transition cached parent={} prop={} -> id={}", parent_id, prop_name, *entry); kernel_debug!("ShapeForge transition cached parent={} prop={} -> id={}", parent_id, prop_name, *entry);
return *entry; return *entry;
+4
View File
@@ -82,9 +82,13 @@ impl PermInterner {
let id = entries.len() as u32; let id = entries.len() as u32;
let leaked: &'static str = Box::leak(s.to_string().into_boxed_str()); let leaked: &'static str = Box::leak(s.to_string().into_boxed_str());
entries.push(PermEntry { data: leaked, hash }); entries.push(PermEntry { data: leaked, hash });
let entry_count = entries.len();
drop(entries); drop(entries);
self.hash_map.entry(hash).or_default().push(id); self.hash_map.entry(hash).or_default().push(id);
kernel_debug!("PermInterner intern new id={} len={}", id, s.len()); kernel_debug!("PermInterner intern new id={} len={}", id, s.len());
if entry_count % 1000 == 0 {
kernel_debug!("PermInterner stats: {} strings", entry_count);
}
(id, hash) (id, hash)
} }