Skip to content

Commit 9b25ecf

Browse files
authored
Simplify/Refactor exception handling and last statement value (#3053)
1 parent 530fe97 commit 9b25ecf

File tree

30 files changed

+314
-633
lines changed

30 files changed

+314
-633
lines changed

boa_engine/src/bytecompiler/class.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ impl ByteCompiler<'_, '_> {
7474
compiler.pop_compile_environment();
7575
}
7676

77+
compiler.emit_opcode(Opcode::SetReturnValue);
7778
compiler.emit_opcode(Opcode::Return);
7879

7980
let code = Gc::new(compiler.finish());
@@ -269,6 +270,8 @@ impl ByteCompiler<'_, '_> {
269270
}
270271
field_compiler.pop_compile_environment();
271272
field_compiler.pop_compile_environment();
273+
274+
field_compiler.emit_opcode(Opcode::SetReturnValue);
272275
field_compiler.emit_opcode(Opcode::Return);
273276

274277
field_compiler.code_block_flags |= CodeBlockFlags::IN_CLASS_FIELD_INITIALIZER;
@@ -301,6 +304,8 @@ impl ByteCompiler<'_, '_> {
301304
}
302305
field_compiler.pop_compile_environment();
303306
field_compiler.pop_compile_environment();
307+
308+
field_compiler.emit_opcode(Opcode::SetReturnValue);
304309
field_compiler.emit_opcode(Opcode::Return);
305310

306311
field_compiler.code_block_flags |= CodeBlockFlags::IN_CLASS_FIELD_INITIALIZER;
@@ -343,6 +348,8 @@ impl ByteCompiler<'_, '_> {
343348
}
344349
field_compiler.pop_compile_environment();
345350
field_compiler.pop_compile_environment();
351+
352+
field_compiler.emit_opcode(Opcode::SetReturnValue);
346353
field_compiler.emit_opcode(Opcode::Return);
347354

348355
field_compiler.code_block_flags |= CodeBlockFlags::IN_CLASS_FIELD_INITIALIZER;

boa_engine/src/bytecompiler/expression/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ impl ByteCompiler<'_, '_> {
9898
Expression::Conditional(op) => self.compile_conditional(op, use_expr),
9999
Expression::ArrayLiteral(array) => {
100100
self.emit_opcode(Opcode::PushNewArray);
101-
self.emit_opcode(Opcode::PopOnReturnAdd);
102101

103102
for element in array.as_ref() {
104103
if let Some(element) = element {
@@ -114,7 +113,6 @@ impl ByteCompiler<'_, '_> {
114113
}
115114
}
116115

117-
self.emit_opcode(Opcode::PopOnReturnSub);
118116
if !use_expr {
119117
self.emit(Opcode::Pop, &[]);
120118
}
@@ -194,6 +192,8 @@ impl ByteCompiler<'_, '_> {
194192
self.emit_opcode(Opcode::Await);
195193
}
196194
self.close_active_iterators();
195+
196+
self.emit_opcode(Opcode::SetReturnValue);
197197
self.emit_opcode(Opcode::GeneratorResumeReturn);
198198

199199
self.patch_jump(throw_method_undefined);

boa_engine/src/bytecompiler/function.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ impl FunctionCompiler {
157157
.filter(|last| **last == Opcode::Return as u8)
158158
.is_none()
159159
{
160-
compiler.emit_opcode(Opcode::PushUndefined);
161160
compiler.emit_opcode(Opcode::Return);
162161
}
163162

boa_engine/src/bytecompiler/jump_control.rs

Lines changed: 71 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,15 @@ bitflags! {
3232
const SWITCH = 0b0000_0010;
3333
const TRY_BLOCK = 0b0000_0100;
3434
const LABELLED = 0b0000_1000;
35-
const IN_CATCH = 0b0001_0000;
36-
const IN_FINALLY = 0b0010_0000;
37-
const HAS_FINALLY = 0b0100_0000;
38-
const ITERATOR_LOOP = 0b1000_0000;
39-
const FOR_AWAIT_OF_LOOP = 0b1_0000_0000;
35+
const IN_FINALLY = 0b0001_0000;
36+
const HAS_FINALLY = 0b0010_0000;
37+
const ITERATOR_LOOP = 0b0100_0000;
38+
const FOR_AWAIT_OF_LOOP = 0b1000_0000;
39+
40+
/// Is the statement compiled with use_expr set to true.
41+
///
42+
/// This bitflag is inherited if the previous [`JumpControlInfo`].
43+
const USE_EXPR = 0b0001_0000_0000;
4044
}
4145
}
4246

@@ -134,10 +138,6 @@ impl JumpControlInfo {
134138
self.flags.contains(JumpControlInfoFlags::LABELLED)
135139
}
136140

137-
pub(crate) const fn in_catch(&self) -> bool {
138-
self.flags.contains(JumpControlInfoFlags::IN_CATCH)
139-
}
140-
141141
pub(crate) const fn in_finally(&self) -> bool {
142142
self.flags.contains(JumpControlInfoFlags::IN_FINALLY)
143143
}
@@ -146,6 +146,10 @@ impl JumpControlInfo {
146146
self.flags.contains(JumpControlInfoFlags::HAS_FINALLY)
147147
}
148148

149+
pub(crate) const fn use_expr(&self) -> bool {
150+
self.flags.contains(JumpControlInfoFlags::USE_EXPR)
151+
}
152+
149153
pub(crate) const fn iterator_loop(&self) -> bool {
150154
self.flags.contains(JumpControlInfoFlags::ITERATOR_LOOP)
151155
}
@@ -168,11 +172,6 @@ impl JumpControlInfo {
168172
self.start_address = start_address;
169173
}
170174

171-
/// Sets the `in_catch` field of `JumpControlInfo`.
172-
pub(crate) fn set_in_catch(&mut self, value: bool) {
173-
self.flags.set(JumpControlInfoFlags::IN_CATCH, value);
174-
}
175-
176175
/// Set the `in_finally` field of `JumpControlInfo`.
177176
pub(crate) fn set_in_finally(&mut self, value: bool) {
178177
self.flags.set(JumpControlInfoFlags::IN_FINALLY, value);
@@ -198,9 +197,9 @@ impl ByteCompiler<'_, '_> {
198197
/// Pushes a generic `JumpControlInfo` onto `ByteCompiler`
199198
///
200199
/// Default `JumpControlInfoKind` is `JumpControlInfoKind::Loop`
201-
pub(crate) fn push_empty_loop_jump_control(&mut self) {
202-
self.jump_info
203-
.push(JumpControlInfo::default().with_loop_flag(true));
200+
pub(crate) fn push_empty_loop_jump_control(&mut self, use_expr: bool) {
201+
let new_info = JumpControlInfo::default().with_loop_flag(true);
202+
self.push_contol_info(new_info, use_expr);
204203
}
205204

206205
pub(crate) fn current_jump_control_mut(&mut self) -> Option<&mut JumpControlInfo> {
@@ -212,37 +211,43 @@ impl ByteCompiler<'_, '_> {
212211
info.set_start_address(start_address);
213212
}
214213

215-
pub(crate) fn set_jump_control_in_finally(&mut self, value: bool) {
216-
if !self.jump_info.is_empty() {
217-
let info = self
218-
.jump_info
219-
.last_mut()
220-
.expect("must have try control label");
221-
assert!(info.is_try_block());
222-
info.set_in_finally(value);
214+
pub(crate) fn push_contol_info(&mut self, mut info: JumpControlInfo, use_expr: bool) {
215+
info.flags.set(JumpControlInfoFlags::USE_EXPR, use_expr);
216+
217+
if let Some(last) = self.jump_info.last() {
218+
// Inherits the `JumpControlInfoFlags::USE_EXPR` flag.
219+
info.flags |= last.flags & JumpControlInfoFlags::USE_EXPR;
223220
}
221+
222+
self.jump_info.push(info);
224223
}
225224

226-
pub(crate) fn set_jump_control_in_catch(&mut self, value: bool) {
227-
if !self.jump_info.is_empty() {
228-
let info = self
229-
.jump_info
230-
.last_mut()
231-
.expect("must have try control label");
232-
assert!(info.is_try_block());
233-
info.set_in_catch(value);
225+
/// Does the jump control info have the `use_expr` flag set to true.
226+
///
227+
/// See [`JumpControlInfoFlags`].
228+
pub(crate) fn jump_control_info_has_use_expr(&self) -> bool {
229+
if let Some(last) = self.jump_info.last() {
230+
return last.use_expr();
234231
}
232+
233+
false
235234
}
236235

237236
// ---- Labelled Statement JumpControlInfo methods ---- //
238237

239238
/// Pushes a `LabelledStatement`'s `JumpControlInfo` onto the `jump_info` stack.
240-
pub(crate) fn push_labelled_control_info(&mut self, label: Sym, start_address: u32) {
239+
pub(crate) fn push_labelled_control_info(
240+
&mut self,
241+
label: Sym,
242+
start_address: u32,
243+
use_expr: bool,
244+
) {
241245
let new_info = JumpControlInfo::default()
242246
.with_labelled_block_flag(true)
243247
.with_label(Some(label))
244248
.with_start_address(start_address);
245-
self.jump_info.push(new_info);
249+
250+
self.push_contol_info(new_info, use_expr);
246251
}
247252

248253
/// Pops and handles the info for a label's `JumpControlInfo`
@@ -267,40 +272,50 @@ impl ByteCompiler<'_, '_> {
267272
// ---- `IterationStatement`'s `JumpControlInfo` methods ---- //
268273

269274
/// Pushes an `WhileStatement`, `ForStatement` or `DoWhileStatement`'s `JumpControlInfo` on to the `jump_info` stack.
270-
pub(crate) fn push_loop_control_info(&mut self, label: Option<Sym>, start_address: u32) {
275+
pub(crate) fn push_loop_control_info(
276+
&mut self,
277+
label: Option<Sym>,
278+
start_address: u32,
279+
use_expr: bool,
280+
) {
271281
let new_info = JumpControlInfo::default()
272282
.with_loop_flag(true)
273283
.with_label(label)
274284
.with_start_address(start_address);
275-
self.jump_info.push(new_info);
285+
286+
self.push_contol_info(new_info, use_expr);
276287
}
277288

278289
/// Pushes a `ForInOfStatement`'s `JumpControlInfo` on to the `jump_info` stack.
279290
pub(crate) fn push_loop_control_info_for_of_in_loop(
280291
&mut self,
281292
label: Option<Sym>,
282293
start_address: u32,
294+
use_expr: bool,
283295
) {
284296
let new_info = JumpControlInfo::default()
285297
.with_loop_flag(true)
286298
.with_label(label)
287299
.with_start_address(start_address)
288300
.with_iterator_loop(true);
289-
self.jump_info.push(new_info);
301+
302+
self.push_contol_info(new_info, use_expr);
290303
}
291304

292305
pub(crate) fn push_loop_control_info_for_await_of_loop(
293306
&mut self,
294307
label: Option<Sym>,
295308
start_address: u32,
309+
use_expr: bool,
296310
) {
297311
let new_info = JumpControlInfo::default()
298312
.with_loop_flag(true)
299313
.with_label(label)
300314
.with_start_address(start_address)
301315
.with_iterator_loop(true)
302316
.with_for_await_of_loop(true);
303-
self.jump_info.push(new_info);
317+
318+
self.push_contol_info(new_info, use_expr);
304319
}
305320

306321
/// Pops and handles the info for a loop control block's `JumpControlInfo`
@@ -327,12 +342,18 @@ impl ByteCompiler<'_, '_> {
327342
// ---- `SwitchStatement` `JumpControlInfo` methods ---- //
328343

329344
/// Pushes a `SwitchStatement`'s `JumpControlInfo` on to the `jump_info` stack.
330-
pub(crate) fn push_switch_control_info(&mut self, label: Option<Sym>, start_address: u32) {
345+
pub(crate) fn push_switch_control_info(
346+
&mut self,
347+
label: Option<Sym>,
348+
start_address: u32,
349+
use_expr: bool,
350+
) {
331351
let new_info = JumpControlInfo::default()
332352
.with_switch_flag(true)
333353
.with_label(label)
334354
.with_start_address(start_address);
335-
self.jump_info.push(new_info);
355+
356+
self.push_contol_info(new_info, use_expr);
336357
}
337358

338359
/// Pops and handles the info for a switch block's `JumpControlInfo`
@@ -354,13 +375,18 @@ impl ByteCompiler<'_, '_> {
354375
// ---- `TryStatement`'s `JumpControlInfo` methods ---- //
355376

356377
/// Pushes a `TryStatement`'s `JumpControlInfo` onto the `jump_info` stack.
357-
pub(crate) fn push_try_control_info(&mut self, has_finally: bool, start_address: u32) {
378+
pub(crate) fn push_try_control_info(
379+
&mut self,
380+
has_finally: bool,
381+
start_address: u32,
382+
use_expr: bool,
383+
) {
358384
let new_info = JumpControlInfo::default()
359385
.with_try_block_flag(true)
360386
.with_start_address(start_address)
361387
.with_has_finally(has_finally);
362388

363-
self.jump_info.push(new_info);
389+
self.push_contol_info(new_info, use_expr);
364390
}
365391

366392
/// Pops and handles the info for a try block's `JumpControlInfo`
@@ -406,12 +432,12 @@ impl ByteCompiler<'_, '_> {
406432
}
407433

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

412438
new_info.set_in_finally(true);
413439

414-
self.jump_info.push(new_info);
440+
self.push_contol_info(new_info, use_expr);
415441
}
416442

417443
pub(crate) fn pop_finally_control_info(&mut self) {

boa_engine/src/bytecompiler/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
756756

757757
/// Compile a [`StatementList`].
758758
pub fn compile_statement_list(&mut self, list: &StatementList, use_expr: bool, block: bool) {
759-
if use_expr {
759+
if use_expr || self.jump_control_info_has_use_expr() {
760760
let mut has_returns_value = false;
761761
let mut use_expr_index = 0;
762762
let mut first_return_is_abrupt = false;
@@ -781,6 +781,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
781781

782782
if first_return_is_abrupt {
783783
self.emit_opcode(Opcode::PushUndefined);
784+
self.emit_opcode(Opcode::SetReturnValue);
784785
}
785786

786787
for (i, item) in list.statements().iter().enumerate() {
@@ -1055,7 +1056,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
10551056
fn compile_stmt_list_item(&mut self, item: &StatementListItem, use_expr: bool, block: bool) {
10561057
match item {
10571058
StatementListItem::Statement(stmt) => {
1058-
self.compile_stmt(stmt, use_expr);
1059+
self.compile_stmt(stmt, use_expr, false);
10591060
}
10601061
StatementListItem::Declaration(decl) => self.compile_decl(decl, block),
10611062
}

boa_engine/src/bytecompiler/statement/break.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,12 @@ use boa_interner::Sym;
77

88
impl ByteCompiler<'_, '_> {
99
/// Compile a [`Break`] `boa_ast` node
10-
pub(crate) fn compile_break(&mut self, node: Break) {
11-
let opcode = if node.label().is_some() {
12-
Opcode::BreakLabel
13-
} else {
14-
Opcode::Break
15-
};
16-
10+
pub(crate) fn compile_break(&mut self, node: Break, _use_expr: bool) {
1711
if let Some(info) = self.jump_info.last().filter(|info| info.is_try_block()) {
18-
let in_finally = info.in_finally();
19-
let in_catch_no_finally = info.in_catch() && !info.has_finally();
2012
let has_finally_or_is_finally = info.has_finally() || info.in_finally();
2113

22-
if in_finally {
23-
self.emit_opcode(Opcode::PopIfThrown);
24-
}
25-
if in_finally || in_catch_no_finally {
26-
self.emit_opcode(Opcode::CatchEnd2);
27-
}
28-
29-
let (break_label, target_jump_label) = self.emit_opcode_with_two_operands(opcode);
14+
let (break_label, target_jump_label) =
15+
self.emit_opcode_with_two_operands(Opcode::Break);
3016

3117
if let Some(node_label) = node.label() {
3218
let info = self.jump_info_label(node_label);
@@ -54,7 +40,7 @@ impl ByteCompiler<'_, '_> {
5440
}
5541

5642
// Emit the break opcode -> (Label, Label)
57-
let (break_label, target_label) = self.emit_opcode_with_two_operands(opcode);
43+
let (break_label, target_label) = self.emit_opcode_with_two_operands(Opcode::Break);
5844
if let Some(label) = node.label() {
5945
let info = self.jump_info_label(label);
6046
info.push_break_label(break_label);

boa_engine/src/bytecompiler/statement/continue.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,11 @@ use boa_ast::statement::Continue;
33

44
impl ByteCompiler<'_, '_> {
55
#[allow(clippy::unnecessary_wraps)]
6-
pub(crate) fn compile_continue(&mut self, node: Continue) {
6+
pub(crate) fn compile_continue(&mut self, node: Continue, _use_expr: bool) {
77
if let Some(info) = self.jump_info.last().filter(|info| info.is_try_block()) {
88
let in_finally = info.in_finally();
99
let in_finally_or_has_finally = in_finally || info.has_finally();
10-
let in_catch_no_finally = !info.has_finally() && info.in_catch();
1110

12-
if in_finally {
13-
self.emit_opcode(Opcode::PopIfThrown);
14-
}
15-
if in_finally || in_catch_no_finally {
16-
self.emit_opcode(Opcode::CatchEnd2);
17-
}
1811
// 1. Handle if node has a label.
1912
if let Some(node_label) = node.label() {
2013
let items = self.jump_info.iter().rev().filter(|info| info.is_loop());

0 commit comments

Comments
 (0)