Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor environment, exception handling and jumping in VM #3059

Merged
merged 16 commits into from
Jul 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion boa_engine/src/builtins/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,10 @@ impl Eval {
context.vm.environments.extend_outer_function_environment();
}

context.vm.push_frame(CallFrame::new(code_block));
let env_fp = context.vm.environments.len() as u32;
context
.vm
.push_frame(CallFrame::new(code_block).with_env_fp(env_fp));
context.realm().resize_global_env();
let record = context.run();
context.vm.pop_frame();
Expand Down
3 changes: 2 additions & 1 deletion boa_engine/src/builtins/generator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,11 @@ impl GeneratorContext {
context
.vm
.push_frame(self.call_frame.take().expect("should have a call frame"));
context.vm.frame_mut().generator_resume_kind = resume_kind;

if let Some(value) = value {
context.vm.push(value);
}
context.vm.push(resume_kind);

let result = context.run();

Expand Down
5 changes: 4 additions & 1 deletion boa_engine/src/builtins/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,10 @@ impl Json {
Gc::new(compiler.finish())
};

context.vm.push_frame(CallFrame::new(code_block));
let env_fp = context.vm.environments.len() as u32;
context
.vm
.push_frame(CallFrame::new(code_block).with_env_fp(env_fp));
context.realm().resize_global_env();
let record = context.run();
context.vm.pop_frame();
Expand Down
15 changes: 5 additions & 10 deletions boa_engine/src/bytecompiler/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,12 @@ impl ByteCompiler<'_, '_> {
compiler.pop_compile_environment();
compiler.code_block_flags |= CodeBlockFlags::IS_CLASS_CONSTRUCTOR;
}
compiler.emit_opcode(Opcode::SetReturnValue);

if class.name().is_some() && class.has_binding_identifier() {
compiler.pop_compile_environment();
}

compiler.emit_opcode(Opcode::SetReturnValue);
compiler.emit_opcode(Opcode::Return);

let code = Gc::new(compiler.finish());
let index = self.functions.len() as u32;
self.functions.push(code);
Expand Down Expand Up @@ -268,12 +266,11 @@ impl ByteCompiler<'_, '_> {
} else {
field_compiler.emit_opcode(Opcode::PushUndefined);
}
field_compiler.emit_opcode(Opcode::SetReturnValue);

field_compiler.pop_compile_environment();
field_compiler.pop_compile_environment();

field_compiler.emit_opcode(Opcode::SetReturnValue);
field_compiler.emit_opcode(Opcode::Return);

field_compiler.code_block_flags |= CodeBlockFlags::IN_CLASS_FIELD_INITIALIZER;

let code = field_compiler.finish();
Expand Down Expand Up @@ -306,7 +303,6 @@ impl ByteCompiler<'_, '_> {
field_compiler.pop_compile_environment();

field_compiler.emit_opcode(Opcode::SetReturnValue);
field_compiler.emit_opcode(Opcode::Return);

field_compiler.code_block_flags |= CodeBlockFlags::IN_CLASS_FIELD_INITIALIZER;

Expand Down Expand Up @@ -346,12 +342,11 @@ impl ByteCompiler<'_, '_> {
} else {
field_compiler.emit_opcode(Opcode::PushUndefined);
}
field_compiler.emit_opcode(Opcode::SetReturnValue);

field_compiler.pop_compile_environment();
field_compiler.pop_compile_environment();

field_compiler.emit_opcode(Opcode::SetReturnValue);
field_compiler.emit_opcode(Opcode::Return);

field_compiler.code_block_flags |= CodeBlockFlags::IN_CLASS_FIELD_INITIALIZER;

let code = field_compiler.finish();
Expand Down
42 changes: 35 additions & 7 deletions boa_engine/src/bytecompiler/declaration/declaration_pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,39 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::ValueNotNullOrUndefined);
self.emit_opcode(Opcode::GetIterator);

// TODO: maybe, refactor this to be more condensed.
let handler_index = self.push_handler();
for element in pattern.bindings() {
self.compile_array_pattern_element(element, def);
}

self.emit_opcode(Opcode::PushFalse);

let exit = self.jump();
self.patch_handler(handler_index);
self.emit_opcode(Opcode::Exception);
self.emit_opcode(Opcode::PushTrue);
self.patch_jump(exit);

self.current_stack_value_count += 2;

let iterator_close_handler = self.push_handler();
self.iterator_close(false);

let exit = self.jump();
self.patch_handler(iterator_close_handler);
self.current_stack_value_count -= 2;
{
let jump = self.jump_if_false();
self.emit_opcode(Opcode::Throw);
self.patch_jump(jump);
}
self.emit_opcode(Opcode::ReThrow);
self.patch_jump(exit);

let jump = self.jump_if_false();
self.emit_opcode(Opcode::Throw);
self.patch_jump(jump);
}
}
}
Expand All @@ -198,15 +226,15 @@ impl ByteCompiler<'_, '_> {
match element {
// ArrayBindingPattern : [ Elision ]
Elision => {
self.emit_opcode(Opcode::IteratorNext);
self.emit_opcode(Opcode::IteratorNextWithoutPop);
}
// SingleNameBinding : BindingIdentifier Initializer[opt]
SingleName {
ident,
default_init,
} => {
self.emit_opcode(Opcode::IteratorNext);
self.emit_opcode(Opcode::IteratorValue);
self.emit_opcode(Opcode::IteratorNextWithoutPop);
self.emit_opcode(Opcode::IteratorValueWithoutPop);
if let Some(init) = default_init {
let skip = self.emit_opcode_with_operand(Opcode::JumpIfNotUndefined);
self.compile_expr(init, true);
Expand All @@ -216,17 +244,17 @@ impl ByteCompiler<'_, '_> {
}
PropertyAccess { access } => {
self.access_set(Access::Property { access }, false, |compiler, _level| {
compiler.emit_opcode(Opcode::IteratorNext);
compiler.emit_opcode(Opcode::IteratorValue);
compiler.emit_opcode(Opcode::IteratorNextWithoutPop);
compiler.emit_opcode(Opcode::IteratorValueWithoutPop);
});
}
// BindingElement : BindingPattern Initializer[opt]
Pattern {
pattern,
default_init,
} => {
self.emit_opcode(Opcode::IteratorNext);
self.emit_opcode(Opcode::IteratorValue);
self.emit_opcode(Opcode::IteratorNextWithoutPop);
self.emit_opcode(Opcode::IteratorValueWithoutPop);

if let Some(init) = default_init {
let skip = self.emit_opcode_with_operand(Opcode::JumpIfNotUndefined);
Expand Down
1 change: 1 addition & 0 deletions boa_engine/src/bytecompiler/declarations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,7 @@ impl ByteCompiler<'_, '_> {
// Don't need to use `AsyncGeneratorYield` since
// we just want to stop the execution of the generator.
self.emit_opcode(Opcode::GeneratorYield);
self.emit_opcode(Opcode::Pop);
}

// 27. If hasParameterExpressions is false, then
Expand Down
2 changes: 2 additions & 0 deletions boa_engine/src/bytecompiler/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use boa_ast::expression::Identifier;
impl ByteCompiler<'_, '_> {
/// Push either a new declarative or function environment on the compile time environment stack.
pub(crate) fn push_compile_environment(&mut self, function_scope: bool) {
self.current_open_environments_count += 1;
self.current_environment = Rc::new(CompileTimeEnvironment::new(
self.current_environment.clone(),
function_scope,
Expand All @@ -16,6 +17,7 @@ impl ByteCompiler<'_, '_> {
/// Pops the top compile time environment and returns its index in the compile time environments array.
#[track_caller]
pub(crate) fn pop_compile_environment(&mut self) -> u32 {
self.current_open_environments_count -= 1;
let index = self.compile_environments.len() as u32;
self.compile_environments
.push(self.current_environment.clone());
Expand Down
25 changes: 18 additions & 7 deletions boa_engine/src/bytecompiler/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod update;
use super::{Access, Callable, NodeKind};
use crate::{
bytecompiler::{ByteCompiler, Literal},
vm::Opcode,
vm::{GeneratorResumeKind, Opcode},
};
use boa_ast::{
expression::{
Expand Down Expand Up @@ -153,31 +153,41 @@ impl ByteCompiler<'_, '_> {
}
}
Expression::Yield(r#yield) => {
// stack:
HalidOdat marked this conversation as resolved.
Show resolved Hide resolved
if let Some(expr) = r#yield.target() {
self.compile_expr(expr, true);
} else {
self.emit_opcode(Opcode::PushUndefined);
}

// stack: value

if r#yield.delegate() {
if self.in_async_generator {
if self.in_async() {
self.emit_opcode(Opcode::GetAsyncIterator);
} else {
self.emit_opcode(Opcode::GetIterator);
}

// stack:
self.emit_opcode(Opcode::PushUndefined);

// stack: undefined
self.emit_push_integer(GeneratorResumeKind::Normal as i32);

// stack: resume_kind, undefined
let start_address = self.next_opcode_location();
let (throw_method_undefined, return_method_undefined) =
self.emit_opcode_with_two_operands(Opcode::GeneratorDelegateNext);

if self.in_async_generator {
if self.in_async() {
self.emit_opcode(Opcode::Pop);
self.emit_opcode(Opcode::Await);
}

let (return_gen, exit) =
self.emit_opcode_with_two_operands(Opcode::GeneratorDelegateResume);
if self.in_async_generator {
if self.in_async() {
self.emit_opcode(Opcode::IteratorValue);
self.async_generator_yield();
} else {
Expand All @@ -188,16 +198,17 @@ impl ByteCompiler<'_, '_> {

self.patch_jump(return_gen);
self.patch_jump(return_method_undefined);
if self.in_async_generator {
if self.in_async() {
self.emit_opcode(Opcode::Await);
self.emit_opcode(Opcode::Pop);
}
self.close_active_iterators();

self.emit_opcode(Opcode::SetReturnValue);
self.emit_opcode(Opcode::GeneratorResumeReturn);
self.r#return();

self.patch_jump(throw_method_undefined);
self.iterator_close(self.in_async_generator);
self.iterator_close(self.in_async());
self.emit_opcode(Opcode::Throw);

self.patch_jump(exit);
Expand Down
14 changes: 3 additions & 11 deletions boa_engine/src/bytecompiler/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
builtins::function::ThisMode,
bytecompiler::ByteCompiler,
environments::CompileTimeEnvironment,
vm::{CodeBlock, CodeBlockFlags, Opcode},
vm::{CodeBlock, CodeBlockFlags},
Context,
};
use boa_ast::function::{FormalParameterList, FunctionBody};
Expand Down Expand Up @@ -99,7 +99,8 @@ impl FunctionCompiler {

let mut compiler = ByteCompiler::new(self.name, self.strict, false, outer_env, context);
compiler.length = length;
compiler.in_async_generator = self.generator && self.r#async;
compiler.in_async = self.r#async;
compiler.in_generator = self.generator;

if self.arrow {
compiler.this_mode = ThisMode::Lexical;
Expand Down Expand Up @@ -151,15 +152,6 @@ impl FunctionCompiler {

compiler.params = parameters.clone();

if compiler
.bytecode
.last()
.filter(|last| **last == Opcode::Return as u8)
.is_none()
{
compiler.emit_opcode(Opcode::Return);
}

Gc::new(compiler.finish())
}
}
Loading