diff --git a/crates/oxide_bytecode/src/opcode.rs b/crates/oxide_bytecode/src/opcode.rs index 8fb1fb25..8fa97ada 100644 --- a/crates/oxide_bytecode/src/opcode.rs +++ b/crates/oxide_bytecode/src/opcode.rs @@ -153,18 +153,6 @@ pub enum OpCode { } impl OpCode { - pub fn is_implemented(&self) -> bool { - !matches!( - self, - OpCode::PROFILE_TYPE - | OpCode::PROFILE_SHAPE - | OpCode::PROFILE_BRANCH - | OpCode::PROFILE_CALL - | OpCode::FORK - | OpCode::JOIN - ) - } - pub fn has_ic_ext_words(&self) -> bool { matches!( self, diff --git a/crates/oxide_compiler/src/compiler.rs b/crates/oxide_compiler/src/compiler.rs index 936e2e17..0ba1167a 100644 --- a/crates/oxide_compiler/src/compiler.rs +++ b/crates/oxide_compiler/src/compiler.rs @@ -646,7 +646,7 @@ impl Compiler { ) } - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] pub(crate) fn compile_function_body_with_field_hooks<'a, C, E>( &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, is_expression_body: bool, extra_bindings: &[(&str, u8)], body_context: FunctionBodyContext, diff --git a/crates/oxide_kernel/src/builtin.rs b/crates/oxide_kernel/src/builtin.rs index f1761a2f..6233c014 100644 --- a/crates/oxide_kernel/src/builtin.rs +++ b/crates/oxide_kernel/src/builtin.rs @@ -144,20 +144,6 @@ pub struct RegExpMethods { pub to_string: *const (), } -pub struct NumberMethods { - pub is_nan: *const (), - pub is_finite: *const (), - pub parse_int: *const (), - pub parse_float: *const (), - pub to_string: *const (), - pub to_fixed: *const (), - pub is_integer: *const (), - pub is_safe_integer: *const (), - pub to_exponential: *const (), - pub to_precision: *const (), - pub value_of: *const (), -} - pub struct FunctionMethods { pub call: *const (), pub apply: *const (), @@ -979,36 +965,6 @@ impl BuiltinWorld { ); } - pub fn bind_number_methods(&self, methods: &NumberMethods, string_forge: &StringForge, shape_forge: &ShapeForge) { - let ctor_ptr = P::as_ptr(&self.number_constructor) as *mut JsObject; - let ctor = unsafe { &mut *ctor_ptr }; - let proto_ptr = P::as_ptr(&self.number_proto) as *mut JsObject; - let proto = unsafe { &mut *proto_ptr }; - bind_methods!( - self, - ctor, - string_forge, - shape_forge, - ("isNaN", methods.is_nan, 1), - ("isFinite", methods.is_finite, 1), - ("parseInt", methods.parse_int, 1), - ("parseFloat", methods.parse_float, 1), - ("isInteger", methods.is_integer, 1), - ("isSafeInteger", methods.is_safe_integer, 1), - ); - bind_methods!( - self, - proto, - string_forge, - shape_forge, - ("toString", methods.to_string, 0), - ("toFixed", methods.to_fixed, 0), - ("toExponential", methods.to_exponential, 0), - ("toPrecision", methods.to_precision, 0), - ("valueOf", methods.value_of, 0), - ); - } - pub fn bind_function_methods( &self, methods: &FunctionMethods, string_forge: &StringForge, shape_forge: &ShapeForge, ) { diff --git a/crates/oxide_kernel/src/kernel.rs b/crates/oxide_kernel/src/kernel.rs index e87d1ea5..60ed7784 100644 --- a/crates/oxide_kernel/src/kernel.rs +++ b/crates/oxide_kernel/src/kernel.rs @@ -80,11 +80,6 @@ impl KernelConfig { pub fn set_session_gc_threshold(&mut self, bytes: usize) { self.session_gc_threshold = bytes; } - - pub fn with_session_gc_threshold(mut self, bytes: usize) -> Self { - self.session_gc_threshold = bytes; - self - } } impl Default for KernelConfig { diff --git a/crates/oxide_kernel/src/string_forge.rs b/crates/oxide_kernel/src/string_forge.rs index 6c64c0d8..8ab5bef9 100644 --- a/crates/oxide_kernel/src/string_forge.rs +++ b/crates/oxide_kernel/src/string_forge.rs @@ -14,8 +14,8 @@ pub fn hash16(s: &str) -> u16 { } pub struct StringEntry { - pub data: String, - pub ref_count: AtomicU32, + pub(crate) data: String, + pub(crate) ref_count: AtomicU32, pub hash: u16, } diff --git a/crates/oxide_test262/src/main.rs b/crates/oxide_test262/src/main.rs index e9f636d0..075759f8 100644 --- a/crates/oxide_test262/src/main.rs +++ b/crates/oxide_test262/src/main.rs @@ -670,7 +670,7 @@ fn read_heartbeat(path: &Path) -> Option { /// and a fresh child resumes from `culprit + 1`. A child that crashes mid-test /// is recovered through the same path. Timeouts/crashes count as skip by default /// and fail under `--no-skip`. -#[allow(clippy::too_many_arguments)] +#[expect(clippy::too_many_arguments)] fn supervise_window( exe: &Path, args: &[String], no_skip: bool, wstart: usize, wend: usize, timeout: Duration, startup_grace: Duration, paths: &[PathBuf], window_id: usize, diff --git a/crates/oxide_types/src/mem.rs b/crates/oxide_types/src/mem.rs index 468cbc63..2ad779d1 100644 --- a/crates/oxide_types/src/mem.rs +++ b/crates/oxide_types/src/mem.rs @@ -15,16 +15,14 @@ impl P { Self(Arc::new(value)) } - pub fn from_arena(value: &T) -> Self - where - T: Clone, - { - Self(Arc::new(value.clone())) - } - pub fn as_ptr(&self) -> *const T { Arc::as_ptr(&self.0) } + + #[inline(always)] + pub fn as_mut_ptr(&self) -> *mut T { + self.as_ptr() as *mut T + } } impl Clone for P { diff --git a/crates/oxide_types/src/object.rs b/crates/oxide_types/src/object.rs index 9596ca41..15572316 100644 --- a/crates/oxide_types/src/object.rs +++ b/crates/oxide_types/src/object.rs @@ -648,17 +648,6 @@ impl JsObject { pos as u32 } - /// Get a pointer to the JsValue at position. - /// Returns None if hash_props not allocated or position out of bounds. - pub fn prop_ptr_at(&self, position: impl PropIndex) -> Option<*const JsValue> { - if self.hash_props.is_null() { - return None; - } - // SAFETY: hash_props was set from Box> in ensure_hash_props/new_array. - let vec = unsafe { &*(self.hash_props as *const Vec) }; - vec.get(position.to_u32() as usize).map(|v| v as *const JsValue) - } - /// Get the length of hash_props vec (returns 0 if not allocated). pub fn prop_vec_len(&self) -> usize { if self.hash_props.is_null() { diff --git a/crates/oxide_types/src/shape.rs b/crates/oxide_types/src/shape.rs index 99a8cd60..4f0697f7 100644 --- a/crates/oxide_types/src/shape.rs +++ b/crates/oxide_types/src/shape.rs @@ -163,10 +163,6 @@ pub fn shape_prop_count(shape_id: ShapeId) -> u32 { store().lock().unwrap().shape_prop_count(shape_id) } -pub fn init_shape_store() { - let _ = store(); -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/oxide_vm/src/bindings/bind_array.rs b/crates/oxide_vm/src/bindings/bind_array.rs index 72f6343f..76b15465 100644 --- a/crates/oxide_vm/src/bindings/bind_array.rs +++ b/crates/oxide_vm/src/bindings/bind_array.rs @@ -4,7 +4,7 @@ use oxide_kernel::builtin::ArrayMethods; use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::JsObject; -use crate::bind_constructor_hash; +use crate::bind_constructor; pub fn bind_array(core: &Arc, session: &KernelSession, global: &mut JsObject) { let _array_methods = ArrayMethods { @@ -47,5 +47,5 @@ pub fn bind_array(core: &Arc, session: &KernelSession, global: &mut ); let ctor_ptr = session.builtin_world().array_constructor.as_ptr() as *mut JsObject; - bind_constructor_hash!(core, global, "Array", ctor_ptr, crate::builtins::array::array_constructor, 1); + bind_constructor!(core, global, "Array", ctor_ptr, crate::builtins::array::array_constructor, 1, hash: true); } diff --git a/crates/oxide_vm/src/bindings/bind_array_buffer.rs b/crates/oxide_vm/src/bindings/bind_array_buffer.rs index 57c6e6f9..b3cd284e 100644 --- a/crates/oxide_vm/src/bindings/bind_array_buffer.rs +++ b/crates/oxide_vm/src/bindings/bind_array_buffer.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::bind_constructor_hash; +use crate::bind_constructor; use crate::bindings::{apply_binding_table, configure_native_constructor}; use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::JsObject; @@ -31,12 +31,13 @@ pub fn bind_array_buffer(core: &Arc, session: &KernelSession, global ], ); - bind_constructor_hash!( + bind_constructor!( core, global, "ArrayBuffer", ctor_ptr, crate::builtins::array_buffer::array_buffer_constructor, - 1 + 1, + hash: true ); } diff --git a/crates/oxide_vm/src/bindings/bind_boolean.rs b/crates/oxide_vm/src/bindings/bind_boolean.rs index 71e21fb8..5106feb1 100644 --- a/crates/oxide_vm/src/bindings/bind_boolean.rs +++ b/crates/oxide_vm/src/bindings/bind_boolean.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::bind_constructor_hash; +use crate::bind_constructor; use crate::bindings::{apply_binding_table, configure_native_constructor}; use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::JsObject; @@ -23,5 +23,5 @@ pub fn bind_boolean(core: &Arc, session: &KernelSession, global: &mu ], ); - bind_constructor_hash!(core, global, "Boolean", ctor_ptr, crate::builtins::boolean::boolean_constructor, 1); + bind_constructor!(core, global, "Boolean", ctor_ptr, crate::builtins::boolean::boolean_constructor, 1, hash: true); } diff --git a/crates/oxide_vm/src/bindings/bind_data_view.rs b/crates/oxide_vm/src/bindings/bind_data_view.rs index 4c590ebb..76613947 100644 --- a/crates/oxide_vm/src/bindings/bind_data_view.rs +++ b/crates/oxide_vm/src/bindings/bind_data_view.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::bind_constructor_hash; +use crate::bind_constructor; use crate::bindings::{apply_binding_table, configure_native_constructor}; use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::JsObject; @@ -42,5 +42,5 @@ pub fn bind_data_view(core: &Arc, session: &KernelSession, global: & ], ); - bind_constructor_hash!(core, global, "DataView", ctor_ptr, crate::builtins::data_view::data_view_constructor, 3); + bind_constructor!(core, global, "DataView", ctor_ptr, crate::builtins::data_view::data_view_constructor, 3, hash: true); } diff --git a/crates/oxide_vm/src/bindings/bind_map.rs b/crates/oxide_vm/src/bindings/bind_map.rs index e8ea2c21..a567fe2e 100644 --- a/crates/oxide_vm/src/bindings/bind_map.rs +++ b/crates/oxide_vm/src/bindings/bind_map.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::bind_constructor_hash; +use crate::bind_constructor; use crate::bindings::{apply_binding_table, configure_native_constructor}; use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::JsObject; @@ -27,5 +27,5 @@ pub fn bind_map(core: &Arc, session: &KernelSession, global: &mut Js ], ); - bind_constructor_hash!(core, global, "Map", ctor_ptr, crate::builtins::map::map_constructor, 1); + bind_constructor!(core, global, "Map", ctor_ptr, crate::builtins::map::map_constructor, 1, hash: true); } diff --git a/crates/oxide_vm/src/bindings/bind_number.rs b/crates/oxide_vm/src/bindings/bind_number.rs index c0238fdd..988a4c83 100644 --- a/crates/oxide_vm/src/bindings/bind_number.rs +++ b/crates/oxide_vm/src/bindings/bind_number.rs @@ -1,72 +1,69 @@ use std::sync::Arc; -use oxide_kernel::bind_methods; -use oxide_kernel::builtin::NumberMethods; +use crate::bind_constructor; +use crate::bindings::{apply_binding_table, configure_native_constructor}; use oxide_kernel::kernel::{KernelCore, KernelSession}; -use oxide_types::object::{JsObject, NativeFnPtr}; +use oxide_types::object::JsObject; use oxide_types::value::JsValue; pub fn bind_number(core: &Arc, session: &KernelSession, global: &mut JsObject) { - let number_methods = NumberMethods { - is_nan: crate::builtins::number::number_is_nan as *const (), - is_finite: crate::builtins::number::number_is_finite as *const (), - parse_int: crate::builtins::number::number_parse_int as *const (), - parse_float: crate::builtins::number::number_parse_float as *const (), - to_string: crate::builtins::number::number_to_string as *const (), - to_fixed: crate::builtins::number::number_to_fixed as *const (), - is_integer: crate::builtins::number::number_is_integer as *const (), - is_safe_integer: crate::builtins::number::number_is_safe_integer as *const (), - to_exponential: crate::builtins::number::number_to_exponential as *const (), - to_precision: crate::builtins::number::number_to_precision as *const (), - value_of: crate::builtins::number::number_value_of as *const (), - }; - session.builtin_world().bind_number_methods( - &number_methods, - core.string_forge().as_ref(), - core.shape_forge().as_ref(), + let ctor_ptr = session.builtin_world().number_constructor.as_ptr() as *mut JsObject; + let ctor = unsafe { &mut *ctor_ptr }; + let proto_ptr = session.builtin_world().number_proto.as_ptr() as *mut JsObject; + let proto = unsafe { &mut *proto_ptr }; + + configure_native_constructor(ctor, crate::builtins::number::number_constructor as *const (), 1); + + apply_binding_table( + session.builtin_world(), + ctor, + core, + &[ + ("isNaN", crate::builtins::number::number_is_nan as *const (), 1), + ("isFinite", crate::builtins::number::number_is_finite as *const (), 1), + ("isInteger", crate::builtins::number::number_is_integer as *const (), 1), + ("isSafeInteger", crate::builtins::number::number_is_safe_integer as *const (), 1), + ], ); - let si_num = core.string_forge().intern("Number").0; - let num_shape = core.shape_forge().make_shape(global.shape_id(), si_num); - let num_val = JsValue::from_js_object(session.builtin_world().number_constructor.as_ptr() as *mut JsObject); - global.set_shape_id(num_shape); - global.ensure_hash_props().push(num_val); - global.bump_generation(); + apply_binding_table( + session.builtin_world(), + proto, + core, + &[ + ("toString", crate::builtins::number::number_to_string as *const (), 0), + ("toFixed", crate::builtins::number::number_to_fixed as *const (), 0), + ("toExponential", crate::builtins::number::number_to_exponential as *const (), 0), + ("toPrecision", crate::builtins::number::number_to_precision as *const (), 0), + ("valueOf", crate::builtins::number::number_value_of as *const (), 0), + ], + ); - { - let num_ctor_ptr = session.builtin_world().number_constructor.as_ptr() as *mut JsObject; - let num_ctor = unsafe { &mut *num_ctor_ptr }; - // SAFETY: number_constructor is a NativeFn fn-item. - num_ctor.set_native_fn(Some(unsafe { - NativeFnPtr::from_raw(crate::builtins::number::number_constructor as *const ()) - })); - num_ctor.set_native_arg_count(1); - - for (name, value) in [ - ("EPSILON", JsValue::float(2.220446049250313e-16)), - ("MAX_SAFE_INTEGER", JsValue::float(9007199254740991f64)), - ("MIN_SAFE_INTEGER", JsValue::float(-9007199254740991f64)), - ("MAX_VALUE", JsValue::float(1.7976931348623157e308)), - ("MIN_VALUE", JsValue::float(5e-324)), - ("NaN", JsValue::float(f64::NAN)), - ("NEGATIVE_INFINITY", JsValue::float(f64::NEG_INFINITY)), - ("POSITIVE_INFINITY", JsValue::float(f64::INFINITY)), - ] { - num_ctor.ensure_hash_props().push(value); - let prop_si = core.string_forge().intern(name).0; - let next_shape = core.shape_forge().make_shape(num_ctor.shape_id(), prop_si); - num_ctor.set_shape_id(next_shape); - } + for (name, value) in [ + ("EPSILON", JsValue::float(2.220446049250313e-16)), + ("MAX_SAFE_INTEGER", JsValue::float(9007199254740991f64)), + ("MIN_SAFE_INTEGER", JsValue::float(-9007199254740991f64)), + ("MAX_VALUE", JsValue::float(1.7976931348623157e308)), + ("MIN_VALUE", JsValue::float(5e-324)), + ("NaN", JsValue::float(f64::NAN)), + ("NEGATIVE_INFINITY", JsValue::float(f64::NEG_INFINITY)), + ("POSITIVE_INFINITY", JsValue::float(f64::INFINITY)), + ] { + ctor.ensure_hash_props().push(value); + let prop_si = core.string_forge().intern(name).0; + let next_shape = core.shape_forge().make_shape(ctor.shape_id(), prop_si); + ctor.set_shape_id(next_shape); } - let pi_fn = crate::builtins::number::number_parse_int as *const (); - let pf_fn = crate::builtins::number::number_parse_float as *const (); - bind_methods!( + bind_constructor!(core, global, "Number", ctor_ptr, crate::builtins::number::number_constructor, 1, hash: true); + + apply_binding_table( session.builtin_world(), global, - core.string_forge().as_ref(), - core.shape_forge().as_ref(), - ("parseInt", pi_fn, 1), - ("parseFloat", pf_fn, 1), + core, + &[ + ("parseInt", crate::builtins::number::number_parse_int as *const (), 1), + ("parseFloat", crate::builtins::number::number_parse_float as *const (), 1), + ], ); } diff --git a/crates/oxide_vm/src/bindings/bind_regexp.rs b/crates/oxide_vm/src/bindings/bind_regexp.rs index 26cca18c..a3c80a88 100644 --- a/crates/oxide_vm/src/bindings/bind_regexp.rs +++ b/crates/oxide_vm/src/bindings/bind_regexp.rs @@ -4,7 +4,7 @@ use crate::bindings::{apply_binding_table, configure_native_constructor}; use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::JsObject; -use crate::bind_constructor_hash; +use crate::bind_constructor; pub fn bind_regexp(core: &Arc, session: &KernelSession, global: &mut JsObject) { let ctor_ptr = session.builtin_world().regexp_constructor.as_ptr() as *mut JsObject; @@ -25,5 +25,5 @@ pub fn bind_regexp(core: &Arc, session: &KernelSession, global: &mut ], ); - bind_constructor_hash!(core, global, "RegExp", ctor_ptr, crate::builtins::regexp::regexp_constructor, 2); + bind_constructor!(core, global, "RegExp", ctor_ptr, crate::builtins::regexp::regexp_constructor, 2, hash: true); } diff --git a/crates/oxide_vm/src/bindings/bind_set.rs b/crates/oxide_vm/src/bindings/bind_set.rs index 9629dd3c..0e51ffc1 100644 --- a/crates/oxide_vm/src/bindings/bind_set.rs +++ b/crates/oxide_vm/src/bindings/bind_set.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::bind_constructor_hash; +use crate::bind_constructor; use crate::bindings::{apply_binding_table, configure_native_constructor}; use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::JsObject; @@ -26,5 +26,5 @@ pub fn bind_set(core: &Arc, session: &KernelSession, global: &mut Js ], ); - bind_constructor_hash!(core, global, "Set", ctor_ptr, crate::builtins::set::set_constructor, 1); + bind_constructor!(core, global, "Set", ctor_ptr, crate::builtins::set::set_constructor, 1, hash: true); } diff --git a/crates/oxide_vm/src/bindings/bind_symbol.rs b/crates/oxide_vm/src/bindings/bind_symbol.rs index abad8524..3625666a 100644 --- a/crates/oxide_vm/src/bindings/bind_symbol.rs +++ b/crates/oxide_vm/src/bindings/bind_symbol.rs @@ -5,7 +5,7 @@ use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::JsObject; use oxide_types::value::JsValue; -use crate::bind_constructor_hash; +use crate::bind_constructor; pub fn bind_symbol(core: &Arc, session: &KernelSession, global: &mut JsObject) { let ctor_ptr = session.builtin_world().symbol_constructor.as_ptr() as *mut JsObject; @@ -57,7 +57,7 @@ pub fn bind_symbol(core: &Arc, session: &KernelSession, global: &mut bind_well_known_symbol(core, ctor, name, val); } - bind_constructor_hash!(core, global, "Symbol", ctor_ptr, crate::builtins::symbol::symbol_constructor, 1); + bind_constructor!(core, global, "Symbol", ctor_ptr, crate::builtins::symbol::symbol_constructor, 1, hash: true); } fn bind_well_known_symbol(core: &Arc, ctor: &mut JsObject, name: &str, val: JsValue) { diff --git a/crates/oxide_vm/src/bindings/bind_typed_array.rs b/crates/oxide_vm/src/bindings/bind_typed_array.rs index f5c09cd2..dcd8a883 100644 --- a/crates/oxide_vm/src/bindings/bind_typed_array.rs +++ b/crates/oxide_vm/src/bindings/bind_typed_array.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::bind_constructor_hash; +use crate::bind_constructor; use crate::bindings::{apply_binding_table, configure_native_constructor}; use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::JsObject; @@ -9,7 +9,7 @@ macro_rules! bind_typed_array_constructor { ($core:expr, $global:expr, $name:literal, $ctor_ptr:expr, $ctor_fn:path) => {{ let ctor = unsafe { &mut *$ctor_ptr }; configure_native_constructor(ctor, $ctor_fn as *const (), 1); - bind_constructor_hash!($core, $global, $name, $ctor_ptr, $ctor_fn, 1); + bind_constructor!($core, $global, $name, $ctor_ptr, $ctor_fn, 1, hash: true); }}; } diff --git a/crates/oxide_vm/src/bindings/mod.rs b/crates/oxide_vm/src/bindings/mod.rs index 3117967d..596f37d0 100644 --- a/crates/oxide_vm/src/bindings/mod.rs +++ b/crates/oxide_vm/src/bindings/mod.rs @@ -32,29 +32,20 @@ use oxide_types::value::JsValue; #[macro_export] macro_rules! bind_constructor { ($core:expr, $global:expr, $name:literal, $ctor_ptr:expr, $ctor_fn:path, $nargs:literal) => {{ - let si = $core.string_forge().intern($name).0; - let shape = $core.shape_forge().make_shape($global.shape_id(), si); - let val = $crate::JsValue::from_js_object($ctor_ptr); - $global.set_shape_id(shape); - $global.push_prop(val); - let ctor = unsafe { &mut *$ctor_ptr }; - // SAFETY: $ctor_fn is a fn-item expression; casting to *const () preserves validity. - ctor.set_native_fn(Some(unsafe { oxide_types::object::NativeFnPtr::from_raw($ctor_fn as *const ()) })); - ctor.set_native_arg_count($nargs); + bind_constructor!($core, $global, $name, $ctor_ptr, $ctor_fn, $nargs, hash: false) }}; -} - -#[macro_export] -macro_rules! bind_constructor_hash { - ($core:expr, $global:expr, $name:literal, $ctor_ptr:expr, $ctor_fn:path, $nargs:literal) => {{ + ($core:expr, $global:expr, $name:literal, $ctor_ptr:expr, $ctor_fn:path, $nargs:literal, hash: $hash:literal) => {{ let si = $core.string_forge().intern($name).0; let shape = $core.shape_forge().make_shape($global.shape_id(), si); let val = $crate::JsValue::from_js_object($ctor_ptr); $global.set_shape_id(shape); - $global.ensure_hash_props().push(val); - $global.bump_generation(); + if $hash { + $global.ensure_hash_props().push(val); + $global.bump_generation(); + } else { + $global.push_prop(val); + } let ctor = unsafe { &mut *$ctor_ptr }; - // SAFETY: $ctor_fn is a fn-item expression; casting to *const () preserves validity. ctor.set_native_fn(Some(unsafe { oxide_types::object::NativeFnPtr::from_raw($ctor_fn as *const ()) })); ctor.set_native_arg_count($nargs); }}; @@ -383,92 +374,73 @@ pub fn bind_global_builtin_slots(core: &Arc, session: &KernelSession /// Maintenance: when adding a `BuiltinDirtySet` group, update this rebind map, /// `BuiltinSnapshot`, and `BuiltinWorld::rebuild_with_dirty()` together. -pub fn rebind_dirty_builtins(core: &Arc, session: &mut KernelSession, dirty: &BuiltinDirtySet) { +pub fn rebind_dirty_builtins(core: &Arc, session: &mut KernelSession, dirty: Option<&BuiltinDirtySet>) { let global_ptr = session.global_object().as_ptr() as *mut JsObject; let global = unsafe { &mut *global_ptr }; - if dirty.object { + if dirty.map_or(true, |d| d.object) { bind_object::bind_object(core, session, global); } - if dirty.array { + if dirty.map_or(true, |d| d.array) { bind_array::bind_array(core, session, global); } - if dirty.array_buffer { + if dirty.map_or(true, |d| d.array_buffer) { bind_array_buffer::bind_array_buffer(core, session, global); } - if dirty.data_view { + if dirty.map_or(true, |d| d.data_view) { bind_data_view::bind_data_view(core, session, global); } - if dirty.typed_array_family { + if dirty.map_or(true, |d| d.typed_array_family) { bind_typed_array::bind_typed_array(core, session, global); } - if dirty.error_family { + if dirty.map_or(true, |d| d.error_family) { bind_error::bind_error(core, session, global); } - if dirty.string { + if dirty.map_or(true, |d| d.string) { bind_string::bind_string(core, session, global); } - if dirty.number { + if dirty.map_or(true, |d| d.number) { bind_number::bind_number(core, session, global); } - if dirty.math { + if dirty.map_or(true, |d| d.math) { bind_math::bind_math(core, session, global); } - if dirty.json { + if dirty.map_or(true, |d| d.json) { bind_json::bind_json(core, session, global); } - if dirty.date { + if dirty.map_or(true, |d| d.date) { bind_date::bind_date(core, session, global); } - if dirty.set { + if dirty.map_or(true, |d| d.set) { bind_set::bind_set(core, session, global); } - if dirty.map { + if dirty.map_or(true, |d| d.map) { bind_map::bind_map(core, session, global); } - if dirty.boolean { + if dirty.map_or(true, |d| d.boolean) { bind_boolean::bind_boolean(core, session, global); } - if dirty.function { + if dirty.map_or(true, |d| d.function) { bind_function::bind_function(core, session, global); } - if dirty.regexp { + if dirty.map_or(true, |d| d.regexp) { bind_regexp::bind_regexp(core, session, global); } - if dirty.symbol_family { + if dirty.map_or(true, |d| d.symbol_family) { bind_symbol::bind_symbol(core, session, global); } - if dirty.stubs { + if dirty.map_or(true, |d| d.stubs) { bind_stubs::bind_stubs(core, session, global); } } pub fn init_kernel_builtins(core: &Arc, session: &mut KernelSession) { + rebind_dirty_builtins(core, session, None); let global_ptr = session.global_object().as_ptr() as *mut oxide_types::object::JsObject; let global = unsafe { &mut *global_ptr }; - - bind_object::bind_object(core, session, global); - bind_array::bind_array(core, session, global); - bind_array_buffer::bind_array_buffer(core, session, global); - bind_data_view::bind_data_view(core, session, global); - bind_typed_array::bind_typed_array(core, session, global); - bind_error::bind_error(core, session, global); - bind_string::bind_string(core, session, global); - bind_number::bind_number(core, session, global); - bind_math::bind_math(core, session, global); - bind_json::bind_json(core, session, global); - bind_date::bind_date(core, session, global); - bind_set::bind_set(core, session, global); - bind_map::bind_map(core, session, global); - bind_boolean::bind_boolean(core, session, global); - bind_function::bind_function(core, session, global); - bind_regexp::bind_regexp(core, session, global); - bind_symbol::bind_symbol(core, session, global); bind_iterator::bind_iterator(core, session, global); bind_reflect::bind_reflect(core, session, global); bind_global::bind_global(core, session, global); - bind_stubs::bind_stubs(core, session, global); - bind_global_value(core, global, "globalThis", JsValue::from_js_object(global_ptr)); session.record_snapshot(); } diff --git a/crates/oxide_vm/src/coercion.rs b/crates/oxide_vm/src/coercion.rs index 2cc428a0..d4c27c85 100644 --- a/crates/oxide_vm/src/coercion.rs +++ b/crates/oxide_vm/src/coercion.rs @@ -4,10 +4,6 @@ use oxide_types::object::JsObject; use oxide_types::shape::EMPTY_SHAPE_ID; use oxide_types::value::JsValue; -pub fn to_primitive(val: JsValue) -> JsValue { - val -} - pub fn to_number(val: JsValue, string_forge: &StringForge) -> f64 { if val.is_int() { return val.as_int() as f64; diff --git a/crates/oxide_vm/src/native.rs b/crates/oxide_vm/src/native.rs index beb1752e..c693b389 100644 --- a/crates/oxide_vm/src/native.rs +++ b/crates/oxide_vm/src/native.rs @@ -15,14 +15,6 @@ impl NativeResult { Self::Err(val) } - pub fn into_result(self) -> Result { - match self { - Self::Ok(val) => Ok(val), - Self::Err(err) => Err(err), - Self::TailCall { .. } => panic!("TailCall cannot be converted to Result"), - } - } - pub fn unwrap(self) -> JsValue { match self { Self::Ok(val) => val, diff --git a/crates/oxide_vm/src/session_gc.rs b/crates/oxide_vm/src/session_gc.rs index d76a79bf..41d468d9 100644 --- a/crates/oxide_vm/src/session_gc.rs +++ b/crates/oxide_vm/src/session_gc.rs @@ -25,22 +25,11 @@ pub struct SessionGc { impl SessionGc { pub fn new() -> Self { - Self { - total_collections: 0, - total_bytes_freed: 0, - total_objects_scanned: 0, - total_objects_live: 0, - total_objects_dead: 0, - last_collection_objects_scanned: 0, - last_collection_objects_live: 0, - last_collection_objects_dead: 0, - last_collection_bytes_freed: 0, - last_collection_duration_us: 0, - max_collection_duration_us: 0, - min_collection_duration_us: u64::MAX, - } + Self::default() } +} +impl SessionGc { #[inline] pub(crate) fn is_session_ptr(&self, vm: &Vm, obj_ptr: *mut JsObject) -> bool { vm.is_session_ptr(obj_ptr) @@ -329,7 +318,20 @@ impl SessionGc { impl Default for SessionGc { fn default() -> Self { - Self::new() + Self { + total_collections: 0, + total_bytes_freed: 0, + total_objects_scanned: 0, + total_objects_live: 0, + total_objects_dead: 0, + last_collection_objects_scanned: 0, + last_collection_objects_live: 0, + last_collection_objects_dead: 0, + last_collection_bytes_freed: 0, + last_collection_duration_us: 0, + max_collection_duration_us: 0, + min_collection_duration_us: u64::MAX, + } } } @@ -487,7 +489,7 @@ mod tests { vm.regs[0] = JsValue::from_js_object(root_session); let roots = vm.gc_roots(); - let mut gc = std::mem::replace(&mut vm.session_gc, SessionGc::new()); + let mut gc = std::mem::take(&mut vm.session_gc); gc.mark(&vm, &roots); vm.session_gc = gc; @@ -512,7 +514,7 @@ mod tests { vm.regs[0] = JsValue::from_js_object(root_session); let dead_session = vm.promote_object(dead); let roots = vm.gc_roots(); - let mut gc = std::mem::replace(&mut vm.session_gc, SessionGc::new()); + let mut gc = std::mem::take(&mut vm.session_gc); gc.mark(&vm, &roots); let _ = gc.sweep(&mut vm); vm.session_gc = gc; @@ -624,7 +626,7 @@ mod tests { let map_session = vm.promote_object(map_value.as_js_object_ptr()); vm.regs.fill(JsValue::undefined()); vm.regs[0] = JsValue::from_js_object(map_session); - let mut gc = std::mem::replace(&mut vm.session_gc, SessionGc::new()); + let mut gc = std::mem::take(&mut vm.session_gc); gc.collect(&mut vm); vm.session_gc = gc; @@ -647,7 +649,7 @@ mod tests { let set_session = vm.promote_object(set_value.as_js_object_ptr()); vm.regs.fill(JsValue::undefined()); vm.regs[0] = JsValue::from_js_object(set_session); - let mut gc = std::mem::replace(&mut vm.session_gc, SessionGc::new()); + let mut gc = std::mem::take(&mut vm.session_gc); gc.collect(&mut vm); vm.session_gc = gc; @@ -686,7 +688,7 @@ mod tests { let root_session = vm.promote_object(root); vm.regs.fill(JsValue::undefined()); vm.regs[0] = JsValue::from_js_object(root_session); - let mut gc = std::mem::replace(&mut vm.session_gc, SessionGc::new()); + let mut gc = std::mem::take(&mut vm.session_gc); gc.collect(&mut vm); vm.session_gc = gc; @@ -735,7 +737,7 @@ mod tests { let view_session = vm.promote_object(view.as_js_object_ptr()); vm.regs.fill(JsValue::undefined()); vm.regs[0] = JsValue::from_js_object(view_session); - let mut gc = std::mem::replace(&mut vm.session_gc, SessionGc::new()); + let mut gc = std::mem::take(&mut vm.session_gc); gc.collect(&mut vm); vm.session_gc = gc; diff --git a/crates/oxide_vm/src/vm.rs b/crates/oxide_vm/src/vm.rs index 3f73b71b..f74a2cf5 100644 --- a/crates/oxide_vm/src/vm.rs +++ b/crates/oxide_vm/src/vm.rs @@ -315,12 +315,6 @@ impl Vm { roots } - pub fn gc_clear_marks(&mut self) { - let mut session_gc = std::mem::take(&mut self.session_gc); - session_gc.clear_all_marks(self); - self.session_gc = session_gc; - } - pub(crate) fn maybe_collect_session_gc(&mut self) { let mut session_gc = std::mem::take(&mut self.session_gc); session_gc.maybe_collect(self); @@ -442,14 +436,6 @@ impl Vm { self.regs[idx as usize] = val; } - pub fn regs_mut(&mut self) -> &mut [JsValue; 256] { - &mut self.regs - } - - pub fn epoch_mut(&mut self) -> &mut Epoch { - &mut self.epoch - } - pub fn epoch(&self) -> &Epoch { &self.epoch } @@ -603,7 +589,7 @@ impl Vm { self.call_bytecode_function_inline(callee, callee_obj, receiver, args) } - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] pub(crate) fn push_bytecode_frame( &mut self, callee: JsValue, this_value: JsValue, args: &[JsValue], construct_result_reg: Option, constructed_this: Option, new_target: JsValue, continuation: FrameContinuation, diff --git a/crates/oxide_vm/src/vm_pool.rs b/crates/oxide_vm/src/vm_pool.rs index 7e5b48bb..daf04366 100644 --- a/crates/oxide_vm/src/vm_pool.rs +++ b/crates/oxide_vm/src/vm_pool.rs @@ -15,8 +15,6 @@ pub struct VmPool { kernel_core: Arc, inner: Mutex, condvar: Condvar, - #[allow(dead_code)] - min_size: usize, max_size: Option, } @@ -28,30 +26,16 @@ pub struct VmGuard { } impl VmPool { - pub fn new( - kernel_core: Arc, #[allow(dead_code)] min_size: usize, max_size: Option, - ) -> Arc { - let pool = Arc::new(Self { + pub fn new(kernel_core: Arc, _min_size: usize, max_size: Option) -> Arc { + Arc::new(Self { kernel_core, inner: Mutex::new(VmPoolInner { - available: Vec::with_capacity(min_size), + available: Vec::new(), total_count: 0, }), condvar: Condvar::new(), - min_size, max_size, - }); - - { - let mut inner = pool.inner.lock().unwrap(); - for _ in 0..min_size { - let vm = Self::new_vm(&pool.kernel_core); - inner.available.push(vm); - inner.total_count += 1; - } - } - - pool + }) } fn new_vm(core: &Arc) -> Vm { @@ -117,10 +101,6 @@ impl VmGuard { pub fn vm_mut(&mut self) -> &mut Vm { self.vm.as_mut().expect("VmGuard has no VM") } - - pub fn mark_dirty(&mut self) { - self.dirty = true; - } } impl Drop for VmGuard { diff --git a/crates/oxide_vm/src/vm_runtime.rs b/crates/oxide_vm/src/vm_runtime.rs index 8272fb23..e0d8a592 100644 --- a/crates/oxide_vm/src/vm_runtime.rs +++ b/crates/oxide_vm/src/vm_runtime.rs @@ -157,11 +157,6 @@ impl Vm { self.dispatch() } - #[allow(dead_code)] - pub fn call_bytecode_func(&mut self, _callback_obj: &JsObject, _args_regs: &[u8]) -> Result { - Err("bytecode function calls not yet supported".into()) - } - pub(crate) fn unwind(&mut self) -> Result<(), String> { while let Some(handler) = self.try_stack.pop() { while self.frames.len() > handler.frame_depth { diff --git a/crates/oxide_vm/src/vm_support.rs b/crates/oxide_vm/src/vm_support.rs index 7eb5ed88..2084b395 100644 --- a/crates/oxide_vm/src/vm_support.rs +++ b/crates/oxide_vm/src/vm_support.rs @@ -108,7 +108,7 @@ impl Vm { pub fn full_reset(&mut self) { let dirty = self.session.selective_reset(&self.kernel_core); if dirty.any_builtin_dirty() { - bindings::rebind_dirty_builtins(&self.kernel_core, &mut self.session, &dirty); + bindings::rebind_dirty_builtins(&self.kernel_core, &mut self.session, Some(&dirty)); } if dirty.global { let global_ptr = self.session.global_object().as_ptr() as *mut JsObject;