mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-26 19:51:11 +08:00
perf: 寄存器保存改用共享 save_stack,消除 Box<[JsValue]> 堆分配
This commit is contained in:
@@ -177,7 +177,7 @@ mod tests {
|
|||||||
return_addr: 0,
|
return_addr: 0,
|
||||||
function_name: name_si,
|
function_name: name_si,
|
||||||
caller_reg_limit: 1,
|
caller_reg_limit: 1,
|
||||||
saved_regs: vec![JsValue::undefined()].into_boxed_slice(),
|
saved_reg_offset: 0,
|
||||||
saved_this: JsValue::undefined(),
|
saved_this: JsValue::undefined(),
|
||||||
saved_new_target: JsValue::undefined(),
|
saved_new_target: JsValue::undefined(),
|
||||||
callee: JsValue::undefined(),
|
callee: JsValue::undefined(),
|
||||||
|
|||||||
@@ -460,10 +460,10 @@ fn rewrite_vm_roots(vm: &mut Vm, forwarding: &HashMap<*mut JsObject, *mut JsObje
|
|||||||
for value in &mut vm.regs {
|
for value in &mut vm.regs {
|
||||||
*value = rewrite_forwarded_value(*value, forwarding);
|
*value = rewrite_forwarded_value(*value, forwarding);
|
||||||
}
|
}
|
||||||
for frame in &mut vm.frames {
|
for value in &mut vm.save_stack {
|
||||||
for value in frame.saved_regs.iter_mut() {
|
|
||||||
*value = rewrite_forwarded_value(*value, forwarding);
|
*value = rewrite_forwarded_value(*value, forwarding);
|
||||||
}
|
}
|
||||||
|
for frame in &mut vm.frames {
|
||||||
frame.saved_this = rewrite_forwarded_value(frame.saved_this, forwarding);
|
frame.saved_this = rewrite_forwarded_value(frame.saved_this, forwarding);
|
||||||
frame.saved_new_target = rewrite_forwarded_value(frame.saved_new_target, forwarding);
|
frame.saved_new_target = rewrite_forwarded_value(frame.saved_new_target, forwarding);
|
||||||
frame.callee = rewrite_forwarded_value(frame.callee, forwarding);
|
frame.callee = rewrite_forwarded_value(frame.callee, forwarding);
|
||||||
@@ -553,8 +553,8 @@ mod tests {
|
|||||||
vm.frames.push(CallFrame {
|
vm.frames.push(CallFrame {
|
||||||
return_addr: 0,
|
return_addr: 0,
|
||||||
function_name: 0,
|
function_name: 0,
|
||||||
caller_reg_limit: 0,
|
caller_reg_limit: 1,
|
||||||
saved_regs: vec![JsValue::from_js_object(frame_session)].into_boxed_slice(),
|
saved_reg_offset: 0,
|
||||||
saved_this: JsValue::from_js_object(this_session),
|
saved_this: JsValue::from_js_object(this_session),
|
||||||
saved_new_target: JsValue::from_js_object(child_session),
|
saved_new_target: JsValue::from_js_object(child_session),
|
||||||
callee: JsValue::from_js_object(child_session),
|
callee: JsValue::from_js_object(child_session),
|
||||||
@@ -563,6 +563,7 @@ mod tests {
|
|||||||
is_derived_constructor: false,
|
is_derived_constructor: false,
|
||||||
continuation: FrameContinuation::None,
|
continuation: FrameContinuation::None,
|
||||||
});
|
});
|
||||||
|
vm.save_stack.push(JsValue::from_js_object(frame_session));
|
||||||
|
|
||||||
vm.regs[1] = JsValue::from_js_object(child_session);
|
vm.regs[1] = JsValue::from_js_object(child_session);
|
||||||
vm.exception_value = Some(JsValue::from_js_object(root_session));
|
vm.exception_value = Some(JsValue::from_js_object(root_session));
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ pub struct CallFrame {
|
|||||||
pub return_addr: usize,
|
pub return_addr: usize,
|
||||||
pub function_name: u32,
|
pub function_name: u32,
|
||||||
pub caller_reg_limit: u8,
|
pub caller_reg_limit: u8,
|
||||||
pub saved_regs: Box<[JsValue]>,
|
pub saved_reg_offset: u32,
|
||||||
pub saved_this: JsValue,
|
pub saved_this: JsValue,
|
||||||
pub saved_new_target: JsValue,
|
pub saved_new_target: JsValue,
|
||||||
pub callee: JsValue,
|
pub callee: JsValue,
|
||||||
@@ -140,6 +140,7 @@ pub(crate) struct InlineSyncState {
|
|||||||
pub(crate) last_for_of_result: JsValue,
|
pub(crate) last_for_of_result: JsValue,
|
||||||
pub(crate) saved_bytecode_stack: Vec<Vec<opcode::Instr>>,
|
pub(crate) saved_bytecode_stack: Vec<Vec<opcode::Instr>>,
|
||||||
pub(crate) saved_constants_stack: Vec<Vec<JsValue>>,
|
pub(crate) saved_constants_stack: Vec<Vec<JsValue>>,
|
||||||
|
pub(crate) save_stack: Vec<JsValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Vm {
|
pub struct Vm {
|
||||||
@@ -169,6 +170,10 @@ pub struct Vm {
|
|||||||
pub(crate) sub_module_constants: Vec<Vec<JsValue>>,
|
pub(crate) sub_module_constants: Vec<Vec<JsValue>>,
|
||||||
pub(crate) saved_bytecode_stack: Vec<Vec<opcode::Instr>>,
|
pub(crate) saved_bytecode_stack: Vec<Vec<opcode::Instr>>,
|
||||||
pub(crate) saved_constants_stack: Vec<Vec<JsValue>>,
|
pub(crate) saved_constants_stack: Vec<Vec<JsValue>>,
|
||||||
|
/// Shared register save-stack. Each active `CallFrame` saved its caller's live
|
||||||
|
/// registers (`regs[..caller_reg_limit]`) here at `saved_reg_offset`; restore copies
|
||||||
|
/// them back and truncates. Capacity is retained across calls — zero per-call heap alloc.
|
||||||
|
pub(crate) save_stack: Vec<JsValue>,
|
||||||
pub(crate) try_stack: Vec<TryHandler>,
|
pub(crate) try_stack: Vec<TryHandler>,
|
||||||
pub(crate) exception_value: Option<JsValue>,
|
pub(crate) exception_value: Option<JsValue>,
|
||||||
pub(crate) pending_exception: Option<JsValue>,
|
pub(crate) pending_exception: Option<JsValue>,
|
||||||
@@ -302,14 +307,14 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for frame in &self.frames {
|
for frame in &self.frames {
|
||||||
for &v in &frame.saved_regs {
|
|
||||||
f(v);
|
|
||||||
}
|
|
||||||
f(frame.saved_this);
|
f(frame.saved_this);
|
||||||
f(frame.saved_new_target);
|
f(frame.saved_new_target);
|
||||||
f(frame.callee);
|
f(frame.callee);
|
||||||
f(frame.constructed_this.unwrap_or(JsValue::undefined()));
|
f(frame.constructed_this.unwrap_or(JsValue::undefined()));
|
||||||
}
|
}
|
||||||
|
for &v in &self.save_stack {
|
||||||
|
f(v);
|
||||||
|
}
|
||||||
f(JsValue::from_js_object(self.session.global_object().as_ptr() as *mut JsObject));
|
f(JsValue::from_js_object(self.session.global_object().as_ptr() as *mut JsObject));
|
||||||
f(self.exception_value.unwrap_or(JsValue::undefined()));
|
f(self.exception_value.unwrap_or(JsValue::undefined()));
|
||||||
f(self.pending_exception.unwrap_or(JsValue::undefined()));
|
f(self.pending_exception.unwrap_or(JsValue::undefined()));
|
||||||
@@ -650,7 +655,8 @@ impl Vm {
|
|||||||
let sub_param_base = self.sub_modules[sub_idx].param_base as usize;
|
let sub_param_base = self.sub_modules[sub_idx].param_base as usize;
|
||||||
let sub_is_arrow = self.sub_modules[sub_idx].is_arrow;
|
let sub_is_arrow = self.sub_modules[sub_idx].is_arrow;
|
||||||
let caller_reg_limit = self.active_reg_limit.max(1);
|
let caller_reg_limit = self.active_reg_limit.max(1);
|
||||||
let saved_regs = self.regs[..caller_reg_limit as usize].to_vec().into_boxed_slice();
|
let saved_reg_offset = self.save_stack.len() as u32;
|
||||||
|
self.save_stack.extend_from_slice(&self.regs[..caller_reg_limit as usize]);
|
||||||
let saved_this = self.regs[254];
|
let saved_this = self.regs[254];
|
||||||
let saved_new_target = self.regs[255];
|
let saved_new_target = self.regs[255];
|
||||||
|
|
||||||
@@ -674,7 +680,7 @@ impl Vm {
|
|||||||
return_addr: self.pc,
|
return_addr: self.pc,
|
||||||
function_name,
|
function_name,
|
||||||
caller_reg_limit,
|
caller_reg_limit,
|
||||||
saved_regs,
|
saved_reg_offset,
|
||||||
saved_this,
|
saved_this,
|
||||||
saved_new_target,
|
saved_new_target,
|
||||||
callee,
|
callee,
|
||||||
@@ -971,7 +977,8 @@ impl Vm {
|
|||||||
let sub_constants = self.sub_modules[sub_idx].constants.clone();
|
let sub_constants = self.sub_modules[sub_idx].constants.clone();
|
||||||
let sub_param_base = self.sub_modules[sub_idx].param_base as usize;
|
let sub_param_base = self.sub_modules[sub_idx].param_base as usize;
|
||||||
let caller_reg_limit = self.active_reg_limit.max(1);
|
let caller_reg_limit = self.active_reg_limit.max(1);
|
||||||
let saved_regs = self.regs[..caller_reg_limit as usize].to_vec().into_boxed_slice();
|
let saved_reg_offset = self.save_stack.len() as u32;
|
||||||
|
self.save_stack.extend_from_slice(&self.regs[..caller_reg_limit as usize]);
|
||||||
let saved_this = self.regs[254];
|
let saved_this = self.regs[254];
|
||||||
let saved_new_target = self.regs[255];
|
let saved_new_target = self.regs[255];
|
||||||
|
|
||||||
@@ -993,7 +1000,7 @@ impl Vm {
|
|||||||
.map(|name| self.kernel_core.perm_interner().intern(name).0)
|
.map(|name| self.kernel_core.perm_interner().intern(name).0)
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
caller_reg_limit,
|
caller_reg_limit,
|
||||||
saved_regs,
|
saved_reg_offset,
|
||||||
saved_this,
|
saved_this,
|
||||||
saved_new_target,
|
saved_new_target,
|
||||||
callee: super_ctor,
|
callee: super_ctor,
|
||||||
@@ -1426,7 +1433,7 @@ mod tests {
|
|||||||
return_addr: 1,
|
return_addr: 1,
|
||||||
function_name: 0,
|
function_name: 0,
|
||||||
caller_reg_limit: 2,
|
caller_reg_limit: 2,
|
||||||
saved_regs: vec![JsValue::undefined()].into_boxed_slice(),
|
saved_reg_offset: 0,
|
||||||
saved_this: JsValue::undefined(),
|
saved_this: JsValue::undefined(),
|
||||||
saved_new_target: JsValue::undefined(),
|
saved_new_target: JsValue::undefined(),
|
||||||
callee: JsValue::undefined(),
|
callee: JsValue::undefined(),
|
||||||
@@ -1435,6 +1442,7 @@ mod tests {
|
|||||||
is_derived_constructor: false,
|
is_derived_constructor: false,
|
||||||
continuation: super::FrameContinuation::None,
|
continuation: super::FrameContinuation::None,
|
||||||
});
|
});
|
||||||
|
vm.save_stack.push(JsValue::undefined());
|
||||||
vm.for_in_iters.push(std::ptr::dangling_mut::<super::ForInIter<'static>>());
|
vm.for_in_iters.push(std::ptr::dangling_mut::<super::ForInIter<'static>>());
|
||||||
vm.for_of_iters.push(JsValue::undefined());
|
vm.for_of_iters.push(JsValue::undefined());
|
||||||
vm.saved_bytecode_stack
|
vm.saved_bytecode_stack
|
||||||
@@ -1453,6 +1461,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(vm.pc, 0);
|
assert_eq!(vm.pc, 0);
|
||||||
assert!(vm.frames.is_empty());
|
assert!(vm.frames.is_empty());
|
||||||
|
assert!(vm.save_stack.is_empty());
|
||||||
assert!(vm.for_in_iters.is_empty());
|
assert!(vm.for_in_iters.is_empty());
|
||||||
assert!(vm.for_of_iters.is_empty());
|
assert!(vm.for_of_iters.is_empty());
|
||||||
assert!(vm.saved_bytecode_stack.is_empty());
|
assert!(vm.saved_bytecode_stack.is_empty());
|
||||||
|
|||||||
@@ -99,7 +99,8 @@ impl Vm {
|
|||||||
let sub_constants = self.sub_modules[sub_idx].constants.clone();
|
let sub_constants = self.sub_modules[sub_idx].constants.clone();
|
||||||
let sub_param_base = self.sub_modules[sub_idx].param_base as usize;
|
let sub_param_base = self.sub_modules[sub_idx].param_base as usize;
|
||||||
let caller_reg_limit = self.active_reg_limit.max(1);
|
let caller_reg_limit = self.active_reg_limit.max(1);
|
||||||
let saved_regs = self.regs[..caller_reg_limit as usize].to_vec().into_boxed_slice();
|
let saved_reg_offset = self.save_stack.len() as u32;
|
||||||
|
self.save_stack.extend_from_slice(&self.regs[..caller_reg_limit as usize]);
|
||||||
let saved_this = self.regs[254];
|
let saved_this = self.regs[254];
|
||||||
let saved_new_target = self.regs[255];
|
let saved_new_target = self.regs[255];
|
||||||
|
|
||||||
@@ -126,7 +127,7 @@ impl Vm {
|
|||||||
.map(|name| self.kernel_core.perm_interner().intern(name).0)
|
.map(|name| self.kernel_core.perm_interner().intern(name).0)
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
caller_reg_limit,
|
caller_reg_limit,
|
||||||
saved_regs,
|
saved_reg_offset,
|
||||||
saved_this,
|
saved_this,
|
||||||
saved_new_target,
|
saved_new_target,
|
||||||
callee: constructor,
|
callee: constructor,
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ impl Vm {
|
|||||||
last_for_of_result: self.last_for_of_result,
|
last_for_of_result: self.last_for_of_result,
|
||||||
saved_bytecode_stack: std::mem::take(&mut self.saved_bytecode_stack),
|
saved_bytecode_stack: std::mem::take(&mut self.saved_bytecode_stack),
|
||||||
saved_constants_stack: std::mem::take(&mut self.saved_constants_stack),
|
saved_constants_stack: std::mem::take(&mut self.saved_constants_stack),
|
||||||
|
save_stack: std::mem::take(&mut self.save_stack),
|
||||||
});
|
});
|
||||||
|
|
||||||
self.regs = [JsValue::undefined(); 256];
|
self.regs = [JsValue::undefined(); 256];
|
||||||
@@ -91,6 +92,7 @@ impl Vm {
|
|||||||
self.last_for_of_result = saved.last_for_of_result;
|
self.last_for_of_result = saved.last_for_of_result;
|
||||||
self.saved_bytecode_stack = saved.saved_bytecode_stack;
|
self.saved_bytecode_stack = saved.saved_bytecode_stack;
|
||||||
self.saved_constants_stack = saved.saved_constants_stack;
|
self.saved_constants_stack = saved.saved_constants_stack;
|
||||||
|
self.save_stack = saved.save_stack;
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@@ -102,8 +104,10 @@ impl Vm {
|
|||||||
if let Some(saved_consts) = self.saved_constants_stack.pop() {
|
if let Some(saved_consts) = self.saved_constants_stack.pop() {
|
||||||
self.constants = saved_consts;
|
self.constants = saved_consts;
|
||||||
}
|
}
|
||||||
let restore_len = frame.saved_regs.len();
|
let offset = frame.saved_reg_offset as usize;
|
||||||
self.regs[..restore_len].copy_from_slice(&frame.saved_regs);
|
let len = frame.caller_reg_limit as usize;
|
||||||
|
self.regs[..len].copy_from_slice(&self.save_stack[offset..offset + len]);
|
||||||
|
self.save_stack.truncate(offset);
|
||||||
self.regs[254] = frame.saved_this;
|
self.regs[254] = frame.saved_this;
|
||||||
self.regs[255] = frame.saved_new_target;
|
self.regs[255] = frame.saved_new_target;
|
||||||
self.active_reg_limit = frame.caller_reg_limit;
|
self.active_reg_limit = frame.caller_reg_limit;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ impl Vm {
|
|||||||
sub_module_constants: Vec::new(),
|
sub_module_constants: Vec::new(),
|
||||||
saved_bytecode_stack: Vec::new(),
|
saved_bytecode_stack: Vec::new(),
|
||||||
saved_constants_stack: Vec::new(),
|
saved_constants_stack: Vec::new(),
|
||||||
|
save_stack: Vec::new(),
|
||||||
try_stack: Vec::new(),
|
try_stack: Vec::new(),
|
||||||
exception_value: None,
|
exception_value: None,
|
||||||
pending_exception: None,
|
pending_exception: None,
|
||||||
@@ -88,6 +89,7 @@ impl Vm {
|
|||||||
sub_module_constants: Vec::new(),
|
sub_module_constants: Vec::new(),
|
||||||
saved_bytecode_stack: Vec::new(),
|
saved_bytecode_stack: Vec::new(),
|
||||||
saved_constants_stack: Vec::new(),
|
saved_constants_stack: Vec::new(),
|
||||||
|
save_stack: Vec::new(),
|
||||||
try_stack: Vec::new(),
|
try_stack: Vec::new(),
|
||||||
exception_value: None,
|
exception_value: None,
|
||||||
pending_exception: None,
|
pending_exception: None,
|
||||||
@@ -174,6 +176,7 @@ impl Vm {
|
|||||||
self.last_for_of_result = JsValue::undefined();
|
self.last_for_of_result = JsValue::undefined();
|
||||||
self.saved_bytecode_stack.clear();
|
self.saved_bytecode_stack.clear();
|
||||||
self.saved_constants_stack.clear();
|
self.saved_constants_stack.clear();
|
||||||
|
self.save_stack.clear();
|
||||||
self.try_stack.clear();
|
self.try_stack.clear();
|
||||||
self.exception_value = None;
|
self.exception_value = None;
|
||||||
self.pending_exception = None;
|
self.pending_exception = None;
|
||||||
|
|||||||
Reference in New Issue
Block a user