Skip to content

Commit

Permalink
Use Vec<CallFrame> instead of singly-linked list
Browse files Browse the repository at this point in the history
- Remove the unneeded `prev` field in `CallFrame`
- Preallocate some space for future calls (16 slots)
- Rename Vm::frame => Vm::frames
  • Loading branch information
HalidOdat committed Jul 5, 2022
1 parent cdc49e3 commit 5e20795
Show file tree
Hide file tree
Showing 7 changed files with 16 additions and 28 deletions.
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/console/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,16 +294,14 @@ impl Console {

fn get_stack_trace(context: &mut Context) -> Vec<String> {
let mut stack_trace: Vec<String> = vec![];
let mut prev_frame = context.vm.frame.as_ref();

while let Some(frame) = prev_frame {
for frame in context.vm.frames.iter().rev() {
stack_trace.push(
context
.interner()
.resolve_expect(frame.code.name)
.to_owned(),
);
prev_frame = frame.prev.as_ref();
}

stack_trace
Expand Down
4 changes: 2 additions & 2 deletions boa_engine/src/builtins/generator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ impl Generator {

let result = context.run();

generator_context.call_frame = *context
generator_context.call_frame = context
.vm
.pop_frame()
.expect("generator call frame must exist");
Expand Down Expand Up @@ -384,7 +384,7 @@ impl Generator {
context.run()
}
};
generator_context.call_frame = *context
generator_context.call_frame = context
.vm
.pop_frame()
.expect("generator call frame must exist");
Expand Down
3 changes: 1 addition & 2 deletions boa_engine/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,6 @@ impl Context {
let _timer = Profiler::global().start_event("Execution", "Main");

self.vm.push_frame(CallFrame {
prev: None,
code: code_block,
pc: 0,
catch: Vec::new(),
Expand Down Expand Up @@ -833,7 +832,7 @@ impl ContextBuilder {
console: Console::default(),
intrinsics: Intrinsics::default(),
vm: Vm {
frame: None,
frames: Vec::with_capacity(16),
stack: Vec::with_capacity(1024),
trace: false,
stack_size_limit: 1024,
Expand Down
1 change: 0 additions & 1 deletion boa_engine/src/vm/call_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use boa_gc::{Finalize, Gc, Trace};

#[derive(Clone, Debug, Finalize, Trace)]
pub struct CallFrame {
pub(crate) prev: Option<Box<Self>>,
pub(crate) code: Gc<CodeBlock>,
pub(crate) pc: usize,
#[unsafe_ignore_trace]
Expand Down
6 changes: 1 addition & 5 deletions boa_engine/src/vm/code_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,6 @@ impl JsObject {
let has_expressions = code.params.has_expressions();

context.vm.push_frame(CallFrame {
prev: None,
code,
pc: 0,
catch: Vec::new(),
Expand Down Expand Up @@ -844,7 +843,6 @@ impl JsObject {
let has_expressions = code.params.has_expressions();

context.vm.push_frame(CallFrame {
prev: None,
code,
pc: 0,
catch: Vec::new(),
Expand Down Expand Up @@ -955,7 +953,6 @@ impl JsObject {
let param_count = code.params.parameters.len();

let call_frame = CallFrame {
prev: None,
code,
pc: 0,
catch: Vec::new(),
Expand Down Expand Up @@ -999,7 +996,7 @@ impl JsObject {
state: GeneratorState::SuspendedStart,
context: Some(Gc::new(Cell::new(GeneratorContext {
environments,
call_frame: *call_frame,
call_frame,
stack,
}))),
}),
Expand Down Expand Up @@ -1189,7 +1186,6 @@ impl JsObject {
let param_count = code.params.parameters.len();

context.vm.push_frame(CallFrame {
prev: None,
code,
pc: 0,
catch: Vec::new(),
Expand Down
24 changes: 10 additions & 14 deletions boa_engine/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ mod tests;
/// Virtual Machine.
#[derive(Debug)]
pub struct Vm {
pub(crate) frame: Option<Box<CallFrame>>,
pub(crate) frames: Vec<CallFrame>,
pub(crate) stack: Vec<JsValue>,
pub(crate) trace: bool,
pub(crate) stack_size_limit: usize,
Expand Down Expand Up @@ -81,7 +81,7 @@ impl Vm {
/// If there is no frame, then this will panic.
#[inline]
pub(crate) fn frame(&self) -> &CallFrame {
self.frame.as_ref().expect("no frame found")
self.frames.last().expect("no frame found")
}

/// Retrieves the VM frame mutably
Expand All @@ -91,21 +91,17 @@ impl Vm {
/// If there is no frame, then this will panic.
#[inline]
pub(crate) fn frame_mut(&mut self) -> &mut CallFrame {
self.frame.as_mut().expect("no frame found")
self.frames.last_mut().expect("no frame found")
}

#[inline]
pub(crate) fn push_frame(&mut self, mut frame: CallFrame) {
let prev = self.frame.take();
frame.prev = prev;
self.frame = Some(Box::new(frame));
pub(crate) fn push_frame(&mut self, frame: CallFrame) {
self.frames.push(frame);
}

#[inline]
pub(crate) fn pop_frame(&mut self) -> Option<Box<CallFrame>> {
let mut current = self.frame.take()?;
self.frame = current.prev.take();
Some(current)
pub(crate) fn pop_frame(&mut self) -> Option<CallFrame> {
self.frames.pop()
}
}

Expand Down Expand Up @@ -2307,7 +2303,7 @@ impl Context {
context.vm.push(args.get_or_undefined(0));
context.run()?;

*frame = *context
*frame = context
.vm
.pop_frame()
.expect("generator call frame must exist");
Expand Down Expand Up @@ -2346,7 +2342,7 @@ impl Context {
context.vm.push(args.get_or_undefined(0));
context.run()?;

*frame = *context
*frame = context
.vm
.pop_frame()
.expect("generator call frame must exist");
Expand Down Expand Up @@ -2392,7 +2388,7 @@ impl Context {
let _timer = Profiler::global().start_event("run", "vm");

if self.vm.trace {
let msg = if self.vm.frame().prev.is_some() {
let msg = if self.vm.frames.get(self.vm.frames.len() - 2).is_some() {
" Call Frame "
} else {
" VM Start "
Expand Down
2 changes: 1 addition & 1 deletion test262
Submodule test262 updated 1331 files

0 comments on commit 5e20795

Please sign in to comment.