Skip to content

Commit 7a50cc6

Browse files
committed
WIP
1 parent bcb7631 commit 7a50cc6

File tree

26 files changed

+540
-839
lines changed

26 files changed

+540
-839
lines changed

boa_engine/src/bytecompiler/env.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use boa_gc::{Gc, GcRefCell};
66
impl ByteCompiler<'_, '_> {
77
/// Push either a new declarative or function environment on the compile time environment stack.
88
pub(crate) fn push_compile_environment(&mut self, function_scope: bool) {
9+
self.current_open_environments_count += 1;
910
self.current_environment = Gc::new(GcRefCell::new(CompileTimeEnvironment::new(
1011
self.current_environment.clone(),
1112
function_scope,
@@ -15,6 +16,7 @@ impl ByteCompiler<'_, '_> {
1516
/// Pops the top compile time environment and returns its index in the compile time environments array.
1617
#[track_caller]
1718
pub(crate) fn pop_compile_environment(&mut self) -> u32 {
19+
self.current_open_environments_count -= 1;
1820
let index = self.compile_environments.len() as u32;
1921
self.compile_environments
2022
.push(self.current_environment.clone());

boa_engine/src/bytecompiler/jump_control.rs

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
//! [try spec]: https://tc39.es/ecma262/#sec-try-statement
1010
//! [labelled spec]: https://tc39.es/ecma262/#sec-labelled-statements
1111
12-
use crate::bytecompiler::{ByteCompiler, Label};
12+
use crate::{
13+
bytecompiler::{ByteCompiler, Label},
14+
vm::Opcode,
15+
};
1316
use bitflags::bitflags;
1417
use boa_interner::Sym;
1518

@@ -22,6 +25,7 @@ pub(crate) struct JumpControlInfo {
2225
set_jumps: Vec<Label>,
2326
breaks: Vec<Label>,
2427
try_continues: Vec<Label>,
28+
current_open_environments_count: u32,
2529
}
2630

2731
bitflags! {
@@ -50,21 +54,20 @@ impl Default for JumpControlInfoFlags {
5054
}
5155
}
5256

53-
impl Default for JumpControlInfo {
54-
fn default() -> Self {
57+
/// ---- `JumpControlInfo` Creation Methods ----
58+
impl JumpControlInfo {
59+
fn new(current_open_environments_count: u32) -> Self {
5560
Self {
5661
label: None,
5762
start_address: u32::MAX,
5863
flags: JumpControlInfoFlags::default(),
5964
set_jumps: Vec::new(),
6065
breaks: Vec::new(),
6166
try_continues: Vec::new(),
67+
current_open_environments_count,
6268
}
6369
}
64-
}
6570

66-
/// ---- `JumpControlInfo` Creation Methods ----
67-
impl JumpControlInfo {
6871
pub(crate) const fn with_label(mut self, label: Option<Sym>) -> Self {
6972
self.label = label;
7073
self
@@ -157,6 +160,10 @@ impl JumpControlInfo {
157160
pub(crate) const fn for_await_of_loop(&self) -> bool {
158161
self.flags.contains(JumpControlInfoFlags::FOR_AWAIT_OF_LOOP)
159162
}
163+
164+
pub(crate) const fn current_open_environments_count(&self) -> u32 {
165+
self.current_open_environments_count
166+
}
160167
}
161168

162169
/// ---- `JumpControlInfo` interaction methods ----
@@ -198,7 +205,8 @@ impl ByteCompiler<'_, '_> {
198205
///
199206
/// Default `JumpControlInfoKind` is `JumpControlInfoKind::Loop`
200207
pub(crate) fn push_empty_loop_jump_control(&mut self, use_expr: bool) {
201-
let new_info = JumpControlInfo::default().with_loop_flag(true);
208+
let new_info =
209+
JumpControlInfo::new(self.current_open_environments_count).with_loop_flag(true);
202210
self.push_contol_info(new_info, use_expr);
203211
}
204212

@@ -242,7 +250,7 @@ impl ByteCompiler<'_, '_> {
242250
start_address: u32,
243251
use_expr: bool,
244252
) {
245-
let new_info = JumpControlInfo::default()
253+
let new_info = JumpControlInfo::new(self.current_open_environments_count)
246254
.with_labelled_block_flag(true)
247255
.with_label(Some(label))
248256
.with_start_address(start_address);
@@ -278,7 +286,7 @@ impl ByteCompiler<'_, '_> {
278286
start_address: u32,
279287
use_expr: bool,
280288
) {
281-
let new_info = JumpControlInfo::default()
289+
let new_info = JumpControlInfo::new(self.current_open_environments_count)
282290
.with_loop_flag(true)
283291
.with_label(label)
284292
.with_start_address(start_address);
@@ -293,7 +301,7 @@ impl ByteCompiler<'_, '_> {
293301
start_address: u32,
294302
use_expr: bool,
295303
) {
296-
let new_info = JumpControlInfo::default()
304+
let new_info = JumpControlInfo::new(self.current_open_environments_count)
297305
.with_loop_flag(true)
298306
.with_label(label)
299307
.with_start_address(start_address)
@@ -308,7 +316,7 @@ impl ByteCompiler<'_, '_> {
308316
start_address: u32,
309317
use_expr: bool,
310318
) {
311-
let new_info = JumpControlInfo::default()
319+
let new_info = JumpControlInfo::new(self.current_open_environments_count)
312320
.with_loop_flag(true)
313321
.with_label(label)
314322
.with_start_address(start_address)
@@ -348,7 +356,7 @@ impl ByteCompiler<'_, '_> {
348356
start_address: u32,
349357
use_expr: bool,
350358
) {
351-
let new_info = JumpControlInfo::default()
359+
let new_info = JumpControlInfo::new(self.current_open_environments_count)
352360
.with_switch_flag(true)
353361
.with_label(label)
354362
.with_start_address(start_address);
@@ -381,7 +389,7 @@ impl ByteCompiler<'_, '_> {
381389
start_address: u32,
382390
use_expr: bool,
383391
) {
384-
let new_info = JumpControlInfo::default()
392+
let new_info = JumpControlInfo::new(self.current_open_environments_count)
385393
.with_try_block_flag(true)
386394
.with_start_address(start_address)
387395
.with_has_finally(has_finally);
@@ -433,7 +441,8 @@ impl ByteCompiler<'_, '_> {
433441

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

438447
new_info.set_in_finally(true);
439448

@@ -466,4 +475,14 @@ impl ByteCompiler<'_, '_> {
466475
jump_info.try_continues.append(&mut info.try_continues);
467476
}
468477
}
478+
479+
pub(crate) fn emit_pop_environments(&mut self, info_current_open_environments_count: u32) {
480+
let current_open_environments_count = self.current_open_environments_count;
481+
482+
assert!(current_open_environments_count >= info_current_open_environments_count);
483+
484+
for _ in info_current_open_environments_count..current_open_environments_count {
485+
self.emit_opcode(Opcode::PopEnvironment);
486+
}
487+
}
469488
}

boa_engine/src/bytecompiler/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ pub struct ByteCompiler<'ctx, 'host> {
246246
/// The environment that is currently active.
247247
pub(crate) current_environment: Gc<GcRefCell<CompileTimeEnvironment>>,
248248

249+
pub(crate) current_open_environments_count: u32,
250+
249251
pub(crate) code_block_flags: CodeBlockFlags,
250252

251253
literals_map: FxHashMap<Literal, u32>,
@@ -290,6 +292,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
290292
this_mode: ThisMode::Global,
291293
params: FormalParameterList::default(),
292294
compile_environments: Vec::default(),
295+
current_open_environments_count: 0,
293296
code_block_flags,
294297

295298
literals_map: FxHashMap::default(),

boa_engine/src/bytecompiler/statement/break.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ impl ByteCompiler<'_, '_> {
99
/// Compile a [`Break`] `boa_ast` node
1010
pub(crate) fn compile_break(&mut self, node: Break, _use_expr: bool) {
1111
if let Some(info) = self.jump_info.last().filter(|info| info.is_try_block()) {
12+
let current_open_environments_count = info.current_open_environments_count();
13+
self.emit_pop_environments(current_open_environments_count);
14+
15+
let info = self.jump_info.last().expect("This try block must exist");
16+
1217
let has_finally_or_is_finally = info.has_finally() || info.in_finally();
1318

1419
let (break_label, target_jump_label) =
@@ -40,14 +45,23 @@ impl ByteCompiler<'_, '_> {
4045
}
4146

4247
// Emit the break opcode -> (Label, Label)
43-
let (break_label, target_label) = self.emit_opcode_with_two_operands(Opcode::Break);
4448
if let Some(label) = node.label() {
49+
let info = self.jump_info_label(label);
50+
let current_open_environments_count = info.current_open_environments_count();
51+
self.emit_pop_environments(current_open_environments_count);
52+
53+
let (break_label, target_label) = self.emit_opcode_with_two_operands(Opcode::Break);
4554
let info = self.jump_info_label(label);
4655
info.push_break_label(break_label);
4756
info.push_break_label(target_label);
4857
return;
4958
}
5059

60+
let info = self.jump_info_non_labelled();
61+
let current_open_environments_count = info.current_open_environments_count();
62+
self.emit_pop_environments(current_open_environments_count);
63+
64+
let (break_label, target_label) = self.emit_opcode_with_two_operands(Opcode::Break);
5165
let info = self.jump_info_non_labelled();
5266
info.push_break_label(break_label);
5367
info.push_break_label(target_label);

boa_engine/src/bytecompiler/statement/labelled.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,5 @@ impl ByteCompiler<'_, '_> {
4141
let labelled_end = self.next_opcode_location();
4242
self.patch_jump_with_target(end_label, labelled_end);
4343
self.pop_labelled_control_info();
44-
self.emit_opcode(Opcode::LabelledEnd);
4544
}
4645
}

boa_engine/src/bytecompiler/statement/loop.rs

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl ByteCompiler<'_, '_> {
5757
}
5858

5959
self.push_empty_loop_jump_control(use_expr);
60-
let (loop_start, loop_exit) = self.emit_opcode_with_two_operands(Opcode::LoopStart);
60+
self.emit_opcode(Opcode::LoopStart);
6161
let initial_jump = self.jump();
6262
let start_address = self.next_opcode_location();
6363

@@ -81,7 +81,6 @@ impl ByteCompiler<'_, '_> {
8181
}
8282

8383
self.emit_opcode(Opcode::LoopContinue);
84-
self.patch_jump_with_target(loop_start, start_address);
8584

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

103102
self.patch_jump(exit);
104-
self.patch_jump(loop_exit);
103+
if env_labels.is_some() {
104+
self.emit_opcode(Opcode::PopEnvironment);
105+
}
105106
self.pop_loop_control_info();
106107
self.emit_opcode(Opcode::LoopEnd);
107108

@@ -111,7 +112,6 @@ impl ByteCompiler<'_, '_> {
111112
if let Some(iteration_env_labels) = iteration_env_labels {
112113
self.patch_jump_with_target(iteration_env_labels, env_index);
113114
}
114-
self.emit_opcode(Opcode::PopEnvironment);
115115
}
116116
}
117117

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

157-
let (loop_start, exit_label) =
158-
self.emit_opcode_with_two_operands(Opcode::IteratorLoopStart);
157+
self.emit_opcode(Opcode::IteratorLoopStart);
158+
159159
let start_address = self.next_opcode_location();
160160
self.push_loop_control_info_for_of_in_loop(label, start_address, use_expr);
161161
self.emit_opcode(Opcode::LoopContinue);
162-
self.patch_jump_with_target(loop_start, start_address);
163162

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

235234
self.patch_jump(exit);
236-
self.patch_jump(exit_label);
237235
self.pop_loop_control_info();
238236
self.emit_opcode(Opcode::LoopEnd);
239237

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

281-
let (loop_start, loop_exit) = self.emit_opcode_with_two_operands(Opcode::IteratorLoopStart);
279+
self.emit_opcode(Opcode::IteratorLoopStart);
282280
let start_address = self.next_opcode_location();
283281
if for_of_loop.r#await() {
284282
self.push_loop_control_info_for_await_of_loop(label, start_address, use_expr);
285283
} else {
286284
self.push_loop_control_info_for_of_in_loop(label, start_address, use_expr);
287285
}
288286
self.emit_opcode(Opcode::LoopContinue);
289-
self.patch_jump_with_target(loop_start, start_address);
290287

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

383380
self.patch_jump(exit);
384-
self.patch_jump(loop_exit);
385381
self.pop_loop_control_info();
386382
self.emit_opcode(Opcode::LoopEnd);
387383

@@ -394,11 +390,10 @@ impl ByteCompiler<'_, '_> {
394390
label: Option<Sym>,
395391
use_expr: bool,
396392
) {
397-
let (loop_start, loop_exit) = self.emit_opcode_with_two_operands(Opcode::LoopStart);
393+
self.emit_opcode(Opcode::LoopStart);
398394
let start_address = self.next_opcode_location();
399395
self.emit_opcode(Opcode::LoopContinue);
400396
self.push_loop_control_info(label, start_address, use_expr);
401-
self.patch_jump_with_target(loop_start, start_address);
402397

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

410405
self.patch_jump(exit);
411-
self.patch_jump(loop_exit);
412406
self.pop_loop_control_info();
413407
self.emit_opcode(Opcode::LoopEnd);
414408
}
@@ -419,12 +413,11 @@ impl ByteCompiler<'_, '_> {
419413
label: Option<Sym>,
420414
use_expr: bool,
421415
) {
422-
let (loop_start, loop_exit) = self.emit_opcode_with_two_operands(Opcode::LoopStart);
416+
self.emit_opcode(Opcode::LoopStart);
423417
let initial_label = self.jump();
424418

425419
let start_address = self.next_opcode_location();
426420

427-
self.patch_jump_with_target(loop_start, start_address);
428421
self.push_loop_control_info(label, start_address, use_expr);
429422

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

439432
self.emit(Opcode::Jump, &[condition_label_address]);
440433
self.patch_jump(exit);
441-
self.patch_jump(loop_exit);
442434

443435
self.pop_loop_control_info();
444436
self.emit_opcode(Opcode::LoopEnd);

boa_engine/src/bytecompiler/statement/switch.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ impl ByteCompiler<'_, '_> {
1111

1212
self.block_declaration_instantiation(switch);
1313

14-
let (start_label, end_label) = self.emit_opcode_with_two_operands(Opcode::LoopStart);
14+
self.emit_opcode(Opcode::LoopStart);
1515

1616
let start_address = self.next_opcode_location();
1717
self.push_switch_control_info(None, start_address, use_expr);
18-
self.patch_jump_with_target(start_label, start_address);
1918

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

5453
self.pop_switch_control_info();
55-
self.patch_jump(end_label);
5654
self.emit_opcode(Opcode::LoopEnd);
5755

5856
let env_index = self.pop_compile_environment();

0 commit comments

Comments
 (0)