Skip to content

Commit

Permalink
Clarity changes for the VM (#2531)
Browse files Browse the repository at this point in the history
<!---
Thank you for contributing to Boa! Please fill out the template below, and remove or add any
information as you feel necessary.
--->

Some small changes to the VM with the hopes of making it a bit more clear and concise.

It changes the following:

- Changes `code` to `code_block` and `code` to `bytecode` in `CallFrame` and `CodeBlock`, respectively.
- Adds some creation methods to `CallFrame`.
- Implements `Default` for `Vm`.
  • Loading branch information
nekevss committed Jan 16, 2023
1 parent f52d1d3 commit ff06690
Show file tree
Hide file tree
Showing 26 changed files with 163 additions and 192 deletions.
2 changes: 1 addition & 1 deletion boa_engine/src/builtins/console/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ impl Console {
stack_trace.push(
context
.interner()
.resolve_expect(frame.code.name)
.resolve_expect(frame.code_block.name)
.to_string(),
);
}
Expand Down
20 changes: 10 additions & 10 deletions boa_engine/src/bytecompiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,8 @@ impl<'b, 'icu> ByteCompiler<'b, 'icu> {
}

fn next_opcode_location(&mut self) -> u32 {
assert!(self.code_block.code.len() < u32::MAX as usize);
self.code_block.code.len() as u32
assert!(self.code_block.bytecode.len() < u32::MAX as usize);
self.code_block.bytecode.len() as u32
}

fn emit(&mut self, opcode: Opcode, operands: &[u32]) {
Expand All @@ -361,23 +361,23 @@ impl<'b, 'icu> ByteCompiler<'b, 'icu> {
}

fn emit_u64(&mut self, value: u64) {
self.code_block.code.extend(value.to_ne_bytes());
self.code_block.bytecode.extend(value.to_ne_bytes());
}

fn emit_u32(&mut self, value: u32) {
self.code_block.code.extend(value.to_ne_bytes());
self.code_block.bytecode.extend(value.to_ne_bytes());
}

fn emit_u16(&mut self, value: u16) {
self.code_block.code.extend(value.to_ne_bytes());
self.code_block.bytecode.extend(value.to_ne_bytes());
}

fn emit_opcode(&mut self, opcode: Opcode) {
self.emit_u8(opcode as u8);
}

fn emit_u8(&mut self, value: u8) {
self.code_block.code.push(value);
self.code_block.bytecode.push(value);
}

fn emit_push_integer(&mut self, value: i32) {
Expand Down Expand Up @@ -465,10 +465,10 @@ impl<'b, 'icu> ByteCompiler<'b, 'icu> {
let index = index as usize;

let bytes = target.to_ne_bytes();
self.code_block.code[index + 1] = bytes[0];
self.code_block.code[index + 2] = bytes[1];
self.code_block.code[index + 3] = bytes[2];
self.code_block.code[index + 4] = bytes[3];
self.code_block.bytecode[index + 1] = bytes[0];
self.code_block.bytecode[index + 2] = bytes[1];
self.code_block.bytecode[index + 3] = bytes[2];
self.code_block.bytecode[index + 4] = bytes[3];
}

fn patch_jump(&mut self, label: Label) {
Expand Down
28 changes: 3 additions & 25 deletions boa_engine/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{
object::{FunctionObjectBuilder, GlobalPropertyMap, JsObject},
property::{Attribute, PropertyDescriptor, PropertyKey},
realm::Realm,
vm::{CallFrame, CodeBlock, FinallyReturn, GeneratorResumeKind, Vm},
vm::{CallFrame, CodeBlock, Vm},
JsResult, JsValue,
};

Expand Down Expand Up @@ -205,24 +205,7 @@ impl Context<'_> {
pub fn execute(&mut self, code_block: Gc<CodeBlock>) -> JsResult<JsValue> {
let _timer = Profiler::global().start_event("Execution", "Main");

self.vm.push_frame(CallFrame {
code: code_block,
pc: 0,
catch: Vec::new(),
finally_return: FinallyReturn::None,
finally_jump: Vec::new(),
pop_on_return: 0,
loop_env_stack: Vec::from([0]),
try_env_stack: Vec::from([crate::vm::TryStackEntry {
num_env: 0,
num_loop_stack_entries: 0,
}]),
param_count: 0,
arg_count: 0,
generator_resume_kind: GeneratorResumeKind::Normal,
thrown: false,
async_generator: None,
});
self.vm.push_frame(CallFrame::new(code_block));

self.realm.set_global_binding_number();
let result = self.run();
Expand Down Expand Up @@ -572,12 +555,7 @@ impl<'a> ContextBuilder<'a> {
#[cfg(feature = "console")]
console: Console::default(),
intrinsics,
vm: Vm {
frames: Vec::with_capacity(16),
stack: Vec::with_capacity(1024),
trace: false,
stack_size_limit: 1024,
},
vm: Vm::default(),
#[cfg(feature = "intl")]
icu: self.icu.unwrap_or_else(|| {
let provider = BoaProvider::Buffer(boa_icu_provider::buffer());
Expand Down
40 changes: 39 additions & 1 deletion boa_engine/src/vm/call_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use boa_gc::{Finalize, Gc, Trace};
/// A `CallFrame` holds the state of a function call.
#[derive(Clone, Debug, Finalize, Trace)]
pub struct CallFrame {
pub(crate) code: Gc<CodeBlock>,
pub(crate) code_block: Gc<CodeBlock>,
pub(crate) pc: usize,
#[unsafe_ignore_trace]
pub(crate) catch: Vec<CatchAddresses>,
Expand Down Expand Up @@ -39,6 +39,44 @@ pub struct CallFrame {
pub(crate) async_generator: Option<JsObject>,
}

/// ---- `CallFrame` creation methods ----
impl CallFrame {
/// Creates a new `CallFrame` with the provided `CodeBlock`.
pub(crate) fn new(code_block: Gc<CodeBlock>) -> Self {
Self {
code_block,
pc: 0,
catch: Vec::new(),
finally_return: FinallyReturn::None,
finally_jump: Vec::new(),
pop_on_return: 0,
loop_env_stack: Vec::from([0]),
try_env_stack: Vec::from([TryStackEntry {
num_env: 0,
num_loop_stack_entries: 0,
}]),
param_count: 0,
arg_count: 0,
generator_resume_kind: GeneratorResumeKind::Normal,
thrown: false,
async_generator: None,
}
}

/// Updates a `CallFrame`'s `param_count` field with the value provided.
pub(crate) fn with_param_count(mut self, count: usize) -> Self {
self.param_count = count;
self
}

/// Updates a `CallFrame`'s `arg_count` field with the value provided.
pub(crate) fn with_arg_count(mut self, count: usize) -> Self {
self.arg_count = count;
self
}
}

/// ---- `CallFrame` stack methods ----
impl CallFrame {
/// Tracks that one environment has been pushed in the current loop block.
pub(crate) fn loop_env_stack_inc(&mut self) {
Expand Down
134 changes: 35 additions & 99 deletions boa_engine/src/vm/code_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ use crate::{
js_string,
object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
property::PropertyDescriptor,
vm::call_frame::GeneratorResumeKind,
vm::{call_frame::FinallyReturn, CallFrame, Opcode},
vm::{CallFrame, Opcode},
Context, JsResult, JsString, JsValue,
};
use boa_ast::{
Expand Down Expand Up @@ -78,7 +77,7 @@ pub struct CodeBlock {
pub(crate) params: FormalParameterList,

/// Bytecode
pub(crate) code: Vec<u8>,
pub(crate) bytecode: Vec<u8>,

/// Literals
pub(crate) literals: Vec<JsValue>,
Expand Down Expand Up @@ -127,7 +126,7 @@ impl CodeBlock {
#[must_use]
pub fn new(name: Sym, length: u32, strict: bool) -> Self {
Self {
code: Vec::new(),
bytecode: Vec::new(),
literals: Vec::new(),
names: Vec::new(),
private_names: Vec::new(),
Expand Down Expand Up @@ -162,7 +161,13 @@ impl CodeBlock {
//
// This has to be an unaligned read because we can't guarantee that
// the types are aligned.
unsafe { self.code.as_ptr().add(offset).cast::<T>().read_unaligned() }
unsafe {
self.bytecode
.as_ptr()
.add(offset)
.cast::<T>()
.read_unaligned()
}
}

/// Read type T from code.
Expand All @@ -171,7 +176,7 @@ impl CodeBlock {
where
T: Readable,
{
assert!(offset + size_of::<T>() - 1 < self.code.len());
assert!(offset + size_of::<T>() - 1 < self.bytecode.len());

// Safety: We checked that it is not an out-of-bounds read,
// so this is safe.
Expand All @@ -183,7 +188,7 @@ impl CodeBlock {
///
/// Returns an empty `String` if no operands are present.
pub(crate) fn instruction_operands(&self, pc: &mut usize, interner: &Interner) -> String {
let opcode: Opcode = self.code[*pc].try_into().expect("invalid opcode");
let opcode: Opcode = self.bytecode[*pc].try_into().expect("invalid opcode");
*pc += size_of::<Opcode>();
match opcode {
Opcode::SetFunctionName => {
Expand Down Expand Up @@ -453,8 +458,8 @@ impl ToInternedString for CodeBlock {

let mut pc = 0;
let mut count = 0;
while pc < self.code.len() {
let opcode: Opcode = self.code[pc].try_into().expect("invalid opcode");
while pc < self.bytecode.len() {
let opcode: Opcode = self.bytecode[pc].try_into().expect("invalid opcode");
let opcode = opcode.as_str();
let previous_pc = pc;
let operands = self.instruction_operands(&mut pc, interner);
Expand Down Expand Up @@ -854,24 +859,11 @@ impl JsObject {

let param_count = code.params.as_ref().len();

context.vm.push_frame(CallFrame {
code,
pc: 0,
catch: Vec::new(),
finally_return: FinallyReturn::None,
finally_jump: Vec::new(),
pop_on_return: 0,
loop_env_stack: Vec::from([0]),
try_env_stack: Vec::from([crate::vm::TryStackEntry {
num_env: 0,
num_loop_stack_entries: 0,
}]),
param_count,
arg_count,
generator_resume_kind: GeneratorResumeKind::Normal,
thrown: false,
async_generator: None,
});
context.vm.push_frame(
CallFrame::new(code)
.with_param_count(param_count)
.with_arg_count(arg_count),
);

let result = context.run();
context.vm.pop_frame().expect("must have frame");
Expand Down Expand Up @@ -990,24 +982,11 @@ impl JsObject {

let param_count = code.params.as_ref().len();

context.vm.push_frame(CallFrame {
code,
pc: 0,
catch: Vec::new(),
finally_return: FinallyReturn::None,
finally_jump: Vec::new(),
pop_on_return: 0,
loop_env_stack: Vec::from([0]),
try_env_stack: Vec::from([crate::vm::TryStackEntry {
num_env: 0,
num_loop_stack_entries: 0,
}]),
param_count,
arg_count,
generator_resume_kind: GeneratorResumeKind::Normal,
thrown: false,
async_generator: None,
});
context.vm.push_frame(
CallFrame::new(code)
.with_param_count(param_count)
.with_arg_count(arg_count),
);

let _result = context.run();
context.vm.pop_frame().expect("must have frame");
Expand Down Expand Up @@ -1119,24 +1098,9 @@ impl JsObject {

let param_count = code.params.as_ref().len();

let call_frame = CallFrame {
code,
pc: 0,
catch: Vec::new(),
finally_return: FinallyReturn::None,
finally_jump: Vec::new(),
pop_on_return: 0,
loop_env_stack: Vec::from([0]),
try_env_stack: Vec::from([crate::vm::TryStackEntry {
num_env: 0,
num_loop_stack_entries: 0,
}]),
param_count,
arg_count,
generator_resume_kind: GeneratorResumeKind::Normal,
thrown: false,
async_generator: None,
};
let call_frame = CallFrame::new(code)
.with_param_count(param_count)
.with_arg_count(arg_count);
let mut stack = args;

std::mem::swap(&mut context.vm.stack, &mut stack);
Expand Down Expand Up @@ -1275,24 +1239,9 @@ impl JsObject {

let param_count = code.params.as_ref().len();

let call_frame = CallFrame {
code,
pc: 0,
catch: Vec::new(),
finally_return: FinallyReturn::None,
finally_jump: Vec::new(),
pop_on_return: 0,
loop_env_stack: Vec::from([0]),
try_env_stack: Vec::from([crate::vm::TryStackEntry {
num_env: 0,
num_loop_stack_entries: 0,
}]),
param_count,
arg_count,
generator_resume_kind: GeneratorResumeKind::Normal,
thrown: false,
async_generator: None,
};
let call_frame = CallFrame::new(code)
.with_param_count(param_count)
.with_arg_count(arg_count);
let mut stack = args;

std::mem::swap(&mut context.vm.stack, &mut stack);
Expand Down Expand Up @@ -1494,24 +1443,11 @@ impl JsObject {
let param_count = code.params.as_ref().len();
let has_binding_identifier = code.has_binding_identifier;

context.vm.push_frame(CallFrame {
code,
pc: 0,
catch: Vec::new(),
finally_return: FinallyReturn::None,
finally_jump: Vec::new(),
pop_on_return: 0,
loop_env_stack: Vec::from([0]),
try_env_stack: Vec::from([crate::vm::TryStackEntry {
num_env: 0,
num_loop_stack_entries: 0,
}]),
param_count,
arg_count,
generator_resume_kind: GeneratorResumeKind::Normal,
thrown: false,
async_generator: None,
});
context.vm.push_frame(
CallFrame::new(code)
.with_param_count(param_count)
.with_arg_count(arg_count),
);

let result = context.run();

Expand Down
4 changes: 2 additions & 2 deletions boa_engine/src/vm/flowgraph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ impl CodeBlock {
let mut returns = Vec::new();

let mut pc = 0;
while pc < self.code.len() {
let opcode: Opcode = self.code[pc].try_into().expect("invalid opcode");
while pc < self.bytecode.len() {
let opcode: Opcode = self.bytecode[pc].try_into().expect("invalid opcode");
let opcode_str = opcode.as_str();
let previous_pc = pc;

Expand Down
Loading

0 comments on commit ff06690

Please sign in to comment.