Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed Jun 22, 2023
1 parent bcb7631 commit 7a50cc6
Show file tree
Hide file tree
Showing 26 changed files with 540 additions and 839 deletions.
2 changes: 2 additions & 0 deletions boa_engine/src/bytecompiler/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use boa_gc::{Gc, GcRefCell};
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 = Gc::new(GcRefCell::new(CompileTimeEnvironment::new(
self.current_environment.clone(),
function_scope,
Expand All @@ -15,6 +16,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
47 changes: 33 additions & 14 deletions boa_engine/src/bytecompiler/jump_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
//! [try spec]: https://tc39.es/ecma262/#sec-try-statement
//! [labelled spec]: https://tc39.es/ecma262/#sec-labelled-statements
use crate::bytecompiler::{ByteCompiler, Label};
use crate::{
bytecompiler::{ByteCompiler, Label},
vm::Opcode,
};
use bitflags::bitflags;
use boa_interner::Sym;

Expand All @@ -22,6 +25,7 @@ pub(crate) struct JumpControlInfo {
set_jumps: Vec<Label>,
breaks: Vec<Label>,
try_continues: Vec<Label>,
current_open_environments_count: u32,
}

bitflags! {
Expand Down Expand Up @@ -50,21 +54,20 @@ impl Default for JumpControlInfoFlags {
}
}

impl Default for JumpControlInfo {
fn default() -> Self {
/// ---- `JumpControlInfo` Creation Methods ----
impl JumpControlInfo {
fn new(current_open_environments_count: u32) -> Self {
Self {
label: None,
start_address: u32::MAX,
flags: JumpControlInfoFlags::default(),
set_jumps: Vec::new(),
breaks: Vec::new(),
try_continues: Vec::new(),
current_open_environments_count,
}
}
}

/// ---- `JumpControlInfo` Creation Methods ----
impl JumpControlInfo {
pub(crate) const fn with_label(mut self, label: Option<Sym>) -> Self {
self.label = label;
self
Expand Down Expand Up @@ -157,6 +160,10 @@ impl JumpControlInfo {
pub(crate) const fn for_await_of_loop(&self) -> bool {
self.flags.contains(JumpControlInfoFlags::FOR_AWAIT_OF_LOOP)
}

pub(crate) const fn current_open_environments_count(&self) -> u32 {
self.current_open_environments_count
}
}

/// ---- `JumpControlInfo` interaction methods ----
Expand Down Expand Up @@ -198,7 +205,8 @@ impl ByteCompiler<'_, '_> {
///
/// Default `JumpControlInfoKind` is `JumpControlInfoKind::Loop`
pub(crate) fn push_empty_loop_jump_control(&mut self, use_expr: bool) {
let new_info = JumpControlInfo::default().with_loop_flag(true);
let new_info =
JumpControlInfo::new(self.current_open_environments_count).with_loop_flag(true);
self.push_contol_info(new_info, use_expr);
}

Expand Down Expand Up @@ -242,7 +250,7 @@ impl ByteCompiler<'_, '_> {
start_address: u32,
use_expr: bool,
) {
let new_info = JumpControlInfo::default()
let new_info = JumpControlInfo::new(self.current_open_environments_count)
.with_labelled_block_flag(true)
.with_label(Some(label))
.with_start_address(start_address);
Expand Down Expand Up @@ -278,7 +286,7 @@ impl ByteCompiler<'_, '_> {
start_address: u32,
use_expr: bool,
) {
let new_info = JumpControlInfo::default()
let new_info = JumpControlInfo::new(self.current_open_environments_count)
.with_loop_flag(true)
.with_label(label)
.with_start_address(start_address);
Expand All @@ -293,7 +301,7 @@ impl ByteCompiler<'_, '_> {
start_address: u32,
use_expr: bool,
) {
let new_info = JumpControlInfo::default()
let new_info = JumpControlInfo::new(self.current_open_environments_count)
.with_loop_flag(true)
.with_label(label)
.with_start_address(start_address)
Expand All @@ -308,7 +316,7 @@ impl ByteCompiler<'_, '_> {
start_address: u32,
use_expr: bool,
) {
let new_info = JumpControlInfo::default()
let new_info = JumpControlInfo::new(self.current_open_environments_count)
.with_loop_flag(true)
.with_label(label)
.with_start_address(start_address)
Expand Down Expand Up @@ -348,7 +356,7 @@ impl ByteCompiler<'_, '_> {
start_address: u32,
use_expr: bool,
) {
let new_info = JumpControlInfo::default()
let new_info = JumpControlInfo::new(self.current_open_environments_count)
.with_switch_flag(true)
.with_label(label)
.with_start_address(start_address);
Expand Down Expand Up @@ -381,7 +389,7 @@ impl ByteCompiler<'_, '_> {
start_address: u32,
use_expr: bool,
) {
let new_info = JumpControlInfo::default()
let new_info = JumpControlInfo::new(self.current_open_environments_count)
.with_try_block_flag(true)
.with_start_address(start_address)
.with_has_finally(has_finally);
Expand Down Expand Up @@ -433,7 +441,8 @@ impl ByteCompiler<'_, '_> {

/// Pushes a `TryStatement`'s Finally block `JumpControlInfo` onto the `jump_info` stack.
pub(crate) fn push_init_finally_control_info(&mut self, use_expr: bool) {
let mut new_info = JumpControlInfo::default().with_try_block_flag(true);
let mut new_info =
JumpControlInfo::new(self.current_open_environments_count).with_try_block_flag(true);

new_info.set_in_finally(true);

Expand Down Expand Up @@ -466,4 +475,14 @@ impl ByteCompiler<'_, '_> {
jump_info.try_continues.append(&mut info.try_continues);
}
}

pub(crate) fn emit_pop_environments(&mut self, info_current_open_environments_count: u32) {
let current_open_environments_count = self.current_open_environments_count;

assert!(current_open_environments_count >= info_current_open_environments_count);

for _ in info_current_open_environments_count..current_open_environments_count {
self.emit_opcode(Opcode::PopEnvironment);
}
}
}
3 changes: 3 additions & 0 deletions boa_engine/src/bytecompiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ pub struct ByteCompiler<'ctx, 'host> {
/// The environment that is currently active.
pub(crate) current_environment: Gc<GcRefCell<CompileTimeEnvironment>>,

pub(crate) current_open_environments_count: u32,

pub(crate) code_block_flags: CodeBlockFlags,

literals_map: FxHashMap<Literal, u32>,
Expand Down Expand Up @@ -290,6 +292,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
this_mode: ThisMode::Global,
params: FormalParameterList::default(),
compile_environments: Vec::default(),
current_open_environments_count: 0,
code_block_flags,

literals_map: FxHashMap::default(),
Expand Down
16 changes: 15 additions & 1 deletion boa_engine/src/bytecompiler/statement/break.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ impl ByteCompiler<'_, '_> {
/// Compile a [`Break`] `boa_ast` node
pub(crate) fn compile_break(&mut self, node: Break, _use_expr: bool) {
if let Some(info) = self.jump_info.last().filter(|info| info.is_try_block()) {
let current_open_environments_count = info.current_open_environments_count();
self.emit_pop_environments(current_open_environments_count);

let info = self.jump_info.last().expect("This try block must exist");

let has_finally_or_is_finally = info.has_finally() || info.in_finally();

let (break_label, target_jump_label) =
Expand Down Expand Up @@ -40,14 +45,23 @@ impl ByteCompiler<'_, '_> {
}

// Emit the break opcode -> (Label, Label)
let (break_label, target_label) = self.emit_opcode_with_two_operands(Opcode::Break);
if let Some(label) = node.label() {
let info = self.jump_info_label(label);
let current_open_environments_count = info.current_open_environments_count();
self.emit_pop_environments(current_open_environments_count);

let (break_label, target_label) = self.emit_opcode_with_two_operands(Opcode::Break);
let info = self.jump_info_label(label);
info.push_break_label(break_label);
info.push_break_label(target_label);
return;
}

let info = self.jump_info_non_labelled();
let current_open_environments_count = info.current_open_environments_count();
self.emit_pop_environments(current_open_environments_count);

let (break_label, target_label) = self.emit_opcode_with_two_operands(Opcode::Break);
let info = self.jump_info_non_labelled();
info.push_break_label(break_label);
info.push_break_label(target_label);
Expand Down
1 change: 0 additions & 1 deletion boa_engine/src/bytecompiler/statement/labelled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,5 @@ impl ByteCompiler<'_, '_> {
let labelled_end = self.next_opcode_location();
self.patch_jump_with_target(end_label, labelled_end);
self.pop_labelled_control_info();
self.emit_opcode(Opcode::LabelledEnd);
}
}
26 changes: 9 additions & 17 deletions boa_engine/src/bytecompiler/statement/loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl ByteCompiler<'_, '_> {
}

self.push_empty_loop_jump_control(use_expr);
let (loop_start, loop_exit) = self.emit_opcode_with_two_operands(Opcode::LoopStart);
self.emit_opcode(Opcode::LoopStart);
let initial_jump = self.jump();
let start_address = self.next_opcode_location();

Expand All @@ -81,7 +81,6 @@ impl ByteCompiler<'_, '_> {
}

self.emit_opcode(Opcode::LoopContinue);
self.patch_jump_with_target(loop_start, start_address);

if let Some(final_expr) = for_loop.final_expr() {
self.compile_expr(final_expr, false);
Expand All @@ -101,7 +100,9 @@ impl ByteCompiler<'_, '_> {
self.emit(Opcode::Jump, &[start_address]);

self.patch_jump(exit);
self.patch_jump(loop_exit);
if env_labels.is_some() {
self.emit_opcode(Opcode::PopEnvironment);
}
self.pop_loop_control_info();
self.emit_opcode(Opcode::LoopEnd);

Expand All @@ -111,7 +112,6 @@ impl ByteCompiler<'_, '_> {
if let Some(iteration_env_labels) = iteration_env_labels {
self.patch_jump_with_target(iteration_env_labels, env_index);
}
self.emit_opcode(Opcode::PopEnvironment);
}
}

Expand Down Expand Up @@ -154,12 +154,11 @@ impl ByteCompiler<'_, '_> {
let early_exit = self.jump_if_null_or_undefined();
self.emit_opcode(Opcode::CreateForInIterator);

let (loop_start, exit_label) =
self.emit_opcode_with_two_operands(Opcode::IteratorLoopStart);
self.emit_opcode(Opcode::IteratorLoopStart);

let start_address = self.next_opcode_location();
self.push_loop_control_info_for_of_in_loop(label, start_address, use_expr);
self.emit_opcode(Opcode::LoopContinue);
self.patch_jump_with_target(loop_start, start_address);

self.emit_opcode(Opcode::IteratorNext);
self.emit_opcode(Opcode::IteratorDone);
Expand Down Expand Up @@ -233,7 +232,6 @@ impl ByteCompiler<'_, '_> {
self.emit(Opcode::Jump, &[start_address]);

self.patch_jump(exit);
self.patch_jump(exit_label);
self.pop_loop_control_info();
self.emit_opcode(Opcode::LoopEnd);

Expand Down Expand Up @@ -278,15 +276,14 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::GetIterator);
}

let (loop_start, loop_exit) = self.emit_opcode_with_two_operands(Opcode::IteratorLoopStart);
self.emit_opcode(Opcode::IteratorLoopStart);
let start_address = self.next_opcode_location();
if for_of_loop.r#await() {
self.push_loop_control_info_for_await_of_loop(label, start_address, use_expr);
} else {
self.push_loop_control_info_for_of_in_loop(label, start_address, use_expr);
}
self.emit_opcode(Opcode::LoopContinue);
self.patch_jump_with_target(loop_start, start_address);

self.emit_opcode(Opcode::IteratorNext);
if for_of_loop.r#await() {
Expand Down Expand Up @@ -381,7 +378,6 @@ impl ByteCompiler<'_, '_> {
self.emit(Opcode::Jump, &[start_address]);

self.patch_jump(exit);
self.patch_jump(loop_exit);
self.pop_loop_control_info();
self.emit_opcode(Opcode::LoopEnd);

Expand All @@ -394,11 +390,10 @@ impl ByteCompiler<'_, '_> {
label: Option<Sym>,
use_expr: bool,
) {
let (loop_start, loop_exit) = self.emit_opcode_with_two_operands(Opcode::LoopStart);
self.emit_opcode(Opcode::LoopStart);
let start_address = self.next_opcode_location();
self.emit_opcode(Opcode::LoopContinue);
self.push_loop_control_info(label, start_address, use_expr);
self.patch_jump_with_target(loop_start, start_address);

self.compile_expr(while_loop.condition(), true);
let exit = self.jump_if_false();
Expand All @@ -408,7 +403,6 @@ impl ByteCompiler<'_, '_> {
self.emit(Opcode::Jump, &[start_address]);

self.patch_jump(exit);
self.patch_jump(loop_exit);
self.pop_loop_control_info();
self.emit_opcode(Opcode::LoopEnd);
}
Expand All @@ -419,12 +413,11 @@ impl ByteCompiler<'_, '_> {
label: Option<Sym>,
use_expr: bool,
) {
let (loop_start, loop_exit) = self.emit_opcode_with_two_operands(Opcode::LoopStart);
self.emit_opcode(Opcode::LoopStart);
let initial_label = self.jump();

let start_address = self.next_opcode_location();

self.patch_jump_with_target(loop_start, start_address);
self.push_loop_control_info(label, start_address, use_expr);

let condition_label_address = self.next_opcode_location();
Expand All @@ -438,7 +431,6 @@ impl ByteCompiler<'_, '_> {

self.emit(Opcode::Jump, &[condition_label_address]);
self.patch_jump(exit);
self.patch_jump(loop_exit);

self.pop_loop_control_info();
self.emit_opcode(Opcode::LoopEnd);
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/bytecompiler/statement/switch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ impl ByteCompiler<'_, '_> {

self.block_declaration_instantiation(switch);

let (start_label, end_label) = self.emit_opcode_with_two_operands(Opcode::LoopStart);
self.emit_opcode(Opcode::LoopStart);

let start_address = self.next_opcode_location();
self.push_switch_control_info(None, start_address, use_expr);
self.patch_jump_with_target(start_label, start_address);

let mut labels = Vec::with_capacity(switch.cases().len());
for case in switch.cases() {
Expand Down Expand Up @@ -52,7 +51,6 @@ impl ByteCompiler<'_, '_> {
}

self.pop_switch_control_info();
self.patch_jump(end_label);
self.emit_opcode(Opcode::LoopEnd);

let env_index = self.pop_compile_environment();
Expand Down
Loading

0 comments on commit 7a50cc6

Please sign in to comment.