refactor: 清理未使用符号,合并bind_constructor宏,统一init/rebind绑定列表,bind_number改为表驱动
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -670,7 +670,7 @@ fn read_heartbeat(path: &Path) -> Option<Heartbeat> {
|
||||
/// 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,
|
||||
|
||||
@@ -15,16 +15,14 @@ impl<T> P<T> {
|
||||
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<T> Clone for P<T> {
|
||||
|
||||
@@ -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<Vec<JsValue>> in ensure_hash_props/new_array.
|
||||
let vec = unsafe { &*(self.hash_props as *const Vec<JsValue>) };
|
||||
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() {
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -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<KernelCore>, session: &KernelSession, global: &mut JsObject) {
|
||||
let _array_methods = ArrayMethods {
|
||||
@@ -47,5 +47,5 @@ pub fn bind_array(core: &Arc<KernelCore>, 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);
|
||||
}
|
||||
|
||||
@@ -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<KernelCore>, session: &KernelSession, global
|
||||
],
|
||||
);
|
||||
|
||||
bind_constructor_hash!(
|
||||
bind_constructor!(
|
||||
core,
|
||||
global,
|
||||
"ArrayBuffer",
|
||||
ctor_ptr,
|
||||
crate::builtins::array_buffer::array_buffer_constructor,
|
||||
1
|
||||
1,
|
||||
hash: true
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<KernelCore>, 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);
|
||||
}
|
||||
|
||||
@@ -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<KernelCore>, 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);
|
||||
}
|
||||
|
||||
@@ -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<KernelCore>, 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);
|
||||
}
|
||||
|
||||
@@ -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<KernelCore>, 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),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<KernelCore>, 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<KernelCore>, 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);
|
||||
}
|
||||
|
||||
@@ -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<KernelCore>, 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);
|
||||
}
|
||||
|
||||
@@ -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<KernelCore>, 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<KernelCore>, 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<KernelCore>, ctor: &mut JsObject, name: &str, val: JsValue) {
|
||||
|
||||
@@ -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);
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<KernelCore>, 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<KernelCore>, session: &mut KernelSession, dirty: &BuiltinDirtySet) {
|
||||
pub fn rebind_dirty_builtins(core: &Arc<KernelCore>, 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<KernelCore>, 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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -15,14 +15,6 @@ impl NativeResult {
|
||||
Self::Err(val)
|
||||
}
|
||||
|
||||
pub fn into_result(self) -> Result<JsValue, JsValue> {
|
||||
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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<u8>,
|
||||
constructed_this: Option<JsValue>, new_target: JsValue, continuation: FrameContinuation,
|
||||
|
||||
@@ -15,8 +15,6 @@ pub struct VmPool {
|
||||
kernel_core: Arc<KernelCore>,
|
||||
inner: Mutex<VmPoolInner>,
|
||||
condvar: Condvar,
|
||||
#[allow(dead_code)]
|
||||
min_size: usize,
|
||||
max_size: Option<usize>,
|
||||
}
|
||||
|
||||
@@ -28,30 +26,16 @@ pub struct VmGuard {
|
||||
}
|
||||
|
||||
impl VmPool {
|
||||
pub fn new(
|
||||
kernel_core: Arc<KernelCore>, #[allow(dead_code)] min_size: usize, max_size: Option<usize>,
|
||||
) -> Arc<Self> {
|
||||
let pool = Arc::new(Self {
|
||||
pub fn new(kernel_core: Arc<KernelCore>, _min_size: usize, max_size: Option<usize>) -> Arc<Self> {
|
||||
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<KernelCore>) -> 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 {
|
||||
|
||||
@@ -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<JsValue, String> {
|
||||
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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user