From aa47f342512beffd3d0072be74d025362a070413 Mon Sep 17 00:00:00 2001 From: Haled Odat <8566042+HalidOdat@users.noreply.github.com> Date: Tue, 27 Jun 2023 06:40:58 +0200 Subject: [PATCH] Fix infinity loop in tests --- boa_engine/src/bytecompiler/jump_control.rs | 214 ++++++---------- .../src/bytecompiler/statement/break.rs | 81 ++++--- .../src/bytecompiler/statement/continue.rs | 229 +++++------------- boa_engine/src/bytecompiler/statement/try.rs | 12 +- boa_engine/src/vm/call_frame/try_stack.rs | 14 +- boa_engine/src/vm/mod.rs | 2 +- .../src/vm/opcode/control_flow/throw.rs | 159 ------------ boa_engine/src/vm/opcode/control_flow/try.rs | 4 +- 8 files changed, 192 insertions(+), 523 deletions(-) diff --git a/boa_engine/src/bytecompiler/jump_control.rs b/boa_engine/src/bytecompiler/jump_control.rs index a58e29853b1..e8bdb0309b2 100644 --- a/boa_engine/src/bytecompiler/jump_control.rs +++ b/boa_engine/src/bytecompiler/jump_control.rs @@ -16,41 +16,74 @@ use crate::{ use bitflags::bitflags; use boa_interner::Sym; +#[derive(Debug, Clone, Copy)] +pub(crate) enum JumpRecordAction { + CreateJump, + Transfter { index: u32 }, + PopEnvironments { count: u32 }, + HandleFinally { value: i32 }, + CloseIterator { r#async: bool }, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum JumpRecordKind { Break, Continue, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub(crate) struct JumpRecord { kind: JumpRecordKind, - label: Option, - address: Label, - target_index: Option, + label: Label, + actions: Vec, } impl JumpRecord { pub(crate) const fn new( kind: JumpRecordKind, - label: Option, - address: Label, - target_index: Option, + label: Label, + actions: Vec, ) -> Self { Self { kind, label, - address, - target_index, + actions, } } - pub(crate) const fn label(&self) -> Option { - self.label - } + pub(crate) fn perform_actions( + mut self, + start_address: u32, + compiler: &mut ByteCompiler<'_, '_>, + ) { + while let Some(action) = self.actions.pop() { + match action { + JumpRecordAction::Transfter { index } => { + compiler.jump_info[index as usize].jumps.push(self); + return; + } + JumpRecordAction::PopEnvironments { count } => { + for _ in 0..count { + compiler.emit_opcode(Opcode::PopEnvironment); + } + } + JumpRecordAction::HandleFinally { value } => { + compiler.emit_push_integer(value); + compiler.emit_opcode(Opcode::PushFalse); + } + JumpRecordAction::CreateJump => { + self.label = compiler.jump(); + } + JumpRecordAction::CloseIterator { r#async } => { + compiler.iterator_close(r#async); + } + } + } - pub(crate) const fn target_index(&self) -> Option { - self.target_index + match self.kind { + JumpRecordKind::Break => compiler.patch_jump(self.label), + JumpRecordKind::Continue => compiler.patch_jump_with_target(self.label, start_address), + } } } @@ -59,7 +92,7 @@ impl JumpRecord { pub(crate) struct JumpControlInfo { label: Option, start_address: u32, - flags: JumpControlInfoFlags, + pub(crate) flags: JumpControlInfoFlags, pub(crate) jumps: Vec, current_open_environments_count: u32, } @@ -81,12 +114,7 @@ bitflags! { /// This bitflag is inherited if the previous [`JumpControlInfo`]. const USE_EXPR = 0b0001_0000_0000; - /// Does the control flow jump (`break` or `continue`) require to special finally code generation. - /// - /// This is needed for `break` and `continue`s that are in a try statement - /// (try or catch blocks, for finally not needed because it is already executing it). - /// - const REQUIRE_FINALLY_HANDLING = 0b0010_0000_0000; + const IN_FINALLY = 0b0010_0000_0000; } } @@ -185,6 +213,10 @@ impl JumpControlInfo { self.flags.contains(JumpControlInfoFlags::HAS_FINALLY) } + pub(crate) const fn in_finally(&self) -> bool { + self.flags.contains(JumpControlInfoFlags::IN_FINALLY) + } + pub(crate) const fn use_expr(&self) -> bool { self.flags.contains(JumpControlInfoFlags::USE_EXPR) } @@ -212,34 +244,6 @@ impl JumpControlInfo { pub(crate) fn set_start_address(&mut self, start_address: u32) { self.start_address = start_address; } - - pub(crate) fn push_break_label( - &mut self, - label: Option, - address: Label, - final_target: Option, - ) { - self.jumps.push(JumpRecord::new( - JumpRecordKind::Break, - label, - address, - final_target, - )); - } - - pub(crate) fn push_continue_label( - &mut self, - label: Option, - address: Label, - final_target: Option, - ) { - self.jumps.push(JumpRecord::new( - JumpRecordKind::Continue, - label, - address, - final_target, - )); - } } // `JumpControlInfo` related methods that are implemented on `ByteCompiler`. @@ -257,11 +261,6 @@ impl ByteCompiler<'_, '_> { self.jump_info.last_mut() } - pub(crate) fn set_jump_control_start_address(&mut self, start_address: u32) { - let info = self.jump_info.last_mut().expect("jump_info must exist"); - info.set_start_address(start_address); - } - pub(crate) fn push_contol_info(&mut self, mut info: JumpControlInfo, use_expr: bool) { info.flags.set(JumpControlInfoFlags::USE_EXPR, use_expr); @@ -313,28 +312,9 @@ impl ByteCompiler<'_, '_> { assert!(info.is_labelled()); assert!(info.label().is_some()); - for jump @ JumpRecord { - label, - kind, - address, - .. - } in &info.jumps - { - if info.label() == *label { - match kind { - JumpRecordKind::Break => self.patch_jump(*address), - JumpRecordKind::Continue => { - self.patch_jump_with_target(*address, info.start_address) - } - } - continue; - } - - self.jump_info - .last_mut() - .expect("There should be a previous JumpInfo") - .jumps - .push(*jump); + let start_address = info.start_address(); + for jump_record in info.jumps { + jump_record.perform_actions(start_address, self); } } // ---- `IterationStatement`'s `JumpControlInfo` methods ---- // @@ -398,11 +378,8 @@ impl ByteCompiler<'_, '_> { assert!(info.is_loop()); let start_address = info.start_address(); - for JumpRecord { kind, address, .. } in info.jumps { - match kind { - JumpRecordKind::Break => self.patch_jump(address), - JumpRecordKind::Continue => self.patch_jump_with_target(address, start_address), - } + for jump_record in info.jumps { + jump_record.perform_actions(start_address, self); } } @@ -434,17 +411,9 @@ impl ByteCompiler<'_, '_> { assert!(info.is_switch()); - for jump in info.jumps { - match jump.kind { - JumpRecordKind::Break => self.patch_jump(jump.address), - JumpRecordKind::Continue => { - self.jump_info - .last_mut() - .expect("There should be a previous JumpInfo") - .jumps - .push(jump); - } - } + let start_address = info.start_address(); + for jump_record in info.jumps { + jump_record.perform_actions(start_address, self); } } @@ -472,69 +441,32 @@ impl ByteCompiler<'_, '_> { /// - Will panic if popped `JumpControlInfo` is not for a try block. pub(crate) fn pop_try_control_info(&mut self, try_end: u32) { assert!(!self.jump_info.is_empty()); - let mut info = self.jump_info.pop().expect("no jump information found"); + let info = self.jump_info.pop().expect("no jump information found"); assert!(info.is_try_block()); // Handle breaks. If there is a finally, breaks should go to the finally if info.has_finally() { - for JumpRecord { address, .. } in &info.jumps { - self.patch_jump_with_target(*address, try_end); + for JumpRecord { label, .. } in &info.jumps { + self.patch_jump_with_target(*label, try_end); } let (jumps, default) = self.jump_table(info.jumps.len() as u32); // Handle breaks in a finally block for (i, label) in jumps.iter().enumerate() { - if let Some(jump_info) = self.jump_info.last_mut() { - let jump_record = &info.jumps[i]; - let environments_to_pop = info.current_open_environments_count - - jump_info.current_open_environments_count; - let next = if environments_to_pop == 0 { - *label - } else { - let next_index = jump_info.jumps.len(); - let is_try_block_and_has_finally = - jump_info.is_try_block() && jump_info.has_finally(); - - self.patch_jump(*label); - for _ in 0..environments_to_pop { - self.emit_opcode(Opcode::PopEnvironment); - } - - if is_try_block_and_has_finally { - self.emit_push_integer(next_index as i32 + 1); - self.emit_opcode(Opcode::PushFalse); - } - - self.jump() - }; - - // A target cannot be a try so we append to previous `JumpInfo`. - let jump_info = self.jump_info.last_mut().expect("jump info disapeared"); - match jump_record.kind { - JumpRecordKind::Break => jump_info.push_break_label( - jump_record.label(), - next, - jump_record.target_index(), - ), - JumpRecordKind::Continue => jump_info.push_continue_label( - jump_record.label(), - next, - jump_record.target_index(), - ), - } - } + self.patch_jump(*label); + + let jump_record = info.jumps[i].clone(); + jump_record.perform_actions(u32::MAX, self); } self.patch_jump(default); - } else if !info.jumps.is_empty() { - // When there is no finally, append to previous `JumpInfo`. - self.jump_info - .last_mut() - .expect("There should be a previous JumpInfo") - .jumps - .append(&mut info.jumps); + } else { + assert!( + info.jumps.is_empty(), + "there shouldn't be any breaks or continues attched on a try block without finally" + ) } } diff --git a/boa_engine/src/bytecompiler/statement/break.rs b/boa_engine/src/bytecompiler/statement/break.rs index f1d97be4718..7a349e66682 100644 --- a/boa_engine/src/bytecompiler/statement/break.rs +++ b/boa_engine/src/bytecompiler/statement/break.rs @@ -1,54 +1,73 @@ -use crate::{bytecompiler::ByteCompiler, vm::Opcode}; +use crate::bytecompiler::{ + jump_control::{JumpRecord, JumpRecordAction, JumpRecordKind}, + ByteCompiler, +}; use boa_ast::statement::Break; impl ByteCompiler<'_, '_> { /// Compile a [`Break`] `boa_ast` node pub(crate) fn compile_break(&mut self, node: Break, _use_expr: bool) { - let target_jump_info_index = self.break_jump_info_target_index(node); + let actions = self.break_jump_record_actions(node); - for i in (target_jump_info_index..self.jump_info.len()).rev() { - let count = self.jump_info_open_environment_count(i); - for _ in 0..count { - self.emit_opcode(Opcode::PopEnvironment); - } + JumpRecord::new(JumpRecordKind::Break, Self::DUMMY_LABEL, actions) + .perform_actions(u32::MAX, self); + } - let info = &mut self.jump_info[i]; - if info.is_try_block() && info.has_finally() { - let next_index = info.jumps.len(); + fn break_jump_record_actions(&self, node: Break) -> Vec { + let mut actions = Vec::default(); - self.emit_push_integer(next_index as i32 + 1); - self.emit_opcode(Opcode::PushFalse); - let break_label = self.emit_opcode_with_operand(Opcode::Break); + if let Some(label) = node.label() { + for (i, info) in self.jump_info.iter().enumerate().rev() { + let count = self.jump_info_open_environment_count(i); + actions.push(JumpRecordAction::PopEnvironments { count }); - let info = &mut self.jump_info[i]; - info.push_break_label(node.label(), break_label, Some(target_jump_info_index)); - break; - } + if info.is_try_block() && info.has_finally() && !info.in_finally() { + let next_index = info.jumps.len(); - if i == target_jump_info_index { - let break_label = self.emit_opcode_with_operand(Opcode::Break); - let info = &mut self.jump_info[i]; - info.push_break_label(node.label(), break_label, None); - break; - } - } - } + actions.push(JumpRecordAction::HandleFinally { + value: next_index as i32 + 1, + }); + actions.push(JumpRecordAction::CreateJump); + actions.push(JumpRecordAction::Transfter { index: i as u32 }); + } - fn break_jump_info_target_index(&self, node: Break) -> usize { - if let Some(label) = node.label() { - for (i, info) in self.jump_info.iter().enumerate().rev() { if info.label() == Some(label) { - return i; + actions.push(JumpRecordAction::CreateJump); + actions.push(JumpRecordAction::Transfter { index: i as u32 }); + break; + } + + if info.iterator_loop() { + actions.push(JumpRecordAction::CloseIterator { + r#async: info.for_await_of_loop(), + }); } } } else { for (i, info) in self.jump_info.iter().enumerate().rev() { + let count = self.jump_info_open_environment_count(i); + actions.push(JumpRecordAction::PopEnvironments { count }); + + if info.is_try_block() && info.has_finally() && !info.in_finally() { + let next_index = info.jumps.len(); + + actions.push(JumpRecordAction::HandleFinally { + value: next_index as i32 + 1, + }); + actions.push(JumpRecordAction::CreateJump); + actions.push(JumpRecordAction::Transfter { index: i as u32 }); + } + if info.is_loop() || info.is_switch() { - return i; + actions.push(JumpRecordAction::CreateJump); + actions.push(JumpRecordAction::Transfter { index: i as u32 }); + break; } } } - unreachable!("There should be a valid break jump target") + actions.reverse(); + + actions } } diff --git a/boa_engine/src/bytecompiler/statement/continue.rs b/boa_engine/src/bytecompiler/statement/continue.rs index 8081de45c7d..d32d45d0d51 100644 --- a/boa_engine/src/bytecompiler/statement/continue.rs +++ b/boa_engine/src/bytecompiler/statement/continue.rs @@ -1,196 +1,79 @@ -use crate::{bytecompiler::ByteCompiler, vm::Opcode}; +use crate::bytecompiler::{ + jump_control::{JumpRecord, JumpRecordAction, JumpRecordKind}, + ByteCompiler, +}; use boa_ast::statement::Continue; impl ByteCompiler<'_, '_> { #[allow(clippy::unnecessary_wraps)] pub(crate) fn compile_continue(&mut self, node: Continue, _use_expr: bool) { - // if let Some(info) = self.jump_info.last().filter(|info| info.is_try_block()) { - // // let in_finally = info.in_finally(); - // let in_finally_or_has_finally = in_finally || info.has_finally(); + let actions = self.continue_jump_record_actions(node); - // // 1. Handle if node has a label. - // if let Some(node_label) = node.label() { - // let items = self.jump_info.iter().rev().filter(|info| info.is_loop()); - // let mut iterator_closes = Vec::new(); - - // for info in items { - // if info.label() == Some(node_label) { - // break; - // } - - // if info.iterator_loop() { - // iterator_closes.push(info.for_await_of_loop()); - // } - // } - - // for r#async in iterator_closes { - // self.iterator_close(r#async); - // } - - // let cont_label = self.emit_opcode_with_operand(Opcode::Continue); - - // let loops = self - // .jump_info - // .iter_mut() - // .rev() - // .filter(|info| info.is_loop()); - // // let mut set_continue_as_break = false; - // for info in loops { - // let found_label = info.label() == Some(node_label); - // if found_label && in_finally_or_has_finally { - // // set_continue_as_break = true; - // break; - // } else if found_label && !in_finally_or_has_finally { - // info.push_try_continue_label(Some(node_label), cont_label); - // break; - // } - // } - // // if set_continue_as_break { - // // self.jump_info - // // .last_mut() - // // .expect("no jump information found") - // // .push_break_label(Some(node_label), cont_label); - // // } - // } else { - // // TODO: Add has finally or in finally here - // let cont_label= self.emit_opcode_with_operand(Opcode::Continue); - // // if in_finally_or_has_finally { - // // self.jump_info - // // .last_mut() - // // .expect("Must exist and be a try block") - // // .push_break_label(None, cont_label); - // // }; - // let mut items = self - // .jump_info - // .iter_mut() - // .rev() - // .filter(|info| info.is_loop()); - // let jump_info = items.next().expect("continue must be inside loop"); - // if !in_finally_or_has_finally { - // jump_info.push_try_continue_label(None, cont_label); - // }; - // }; - // } else if let Some(node_label) = node.label() { - // let items = self.jump_info.iter().rev().filter(|info| info.is_loop()); - // let mut iterator_closes = Vec::new(); - // for info in items { - // if info.label() == Some(node_label) { - // break; - // } - - // if info.iterator_loop() { - // iterator_closes.push(info.for_await_of_loop()); - // } - // } - - // for r#async in iterator_closes { - // self.iterator_close(r#async); - // } - - // let cont_label = self.emit_opcode_with_operand(Opcode::Continue); - // let loops = self - // .jump_info - // .iter_mut() - // .rev() - // .filter(|info| info.is_loop()); - - // for info in loops { - // if info.label() == Some(node_label) { - // info.push_try_continue_label(Some(node_label), cont_label); - // } - // } - // } else { - // let cont_label = self.emit_opcode_with_operand(Opcode::Continue); - // let mut items = self - // .jump_info - // .iter_mut() - // .rev() - // .filter(|info| info.is_loop()); - // let jump_info = items.next().expect("continue must be inside loop"); - // jump_info.push_try_continue_label(None, cont_label); - // } - - // for i in (target_jump_info_index..self.jump_info.len()).rev() { - // let count = self.jump_info_open_environment_count(i); - // for _ in 0..count { - // self.emit_opcode(Opcode::PopEnvironment); - // } - - // let info = &mut self.jump_info[i]; - // if info.is_try_block() && info.has_finally() { - // let next_index = info.breaks.len(); - - // self.emit_push_integer(next_index as i32 + 1); - // self.emit_opcode(Opcode::PushFalse); - // let continue_label = self.emit_opcode_with_operand(Opcode::Continue); - - // let info = &mut self.jump_info[i]; - // info.push_(node.label(), continue_label, Some(target_jump_info_index)); - // break; - // } - - // if i == target_jump_info_index { - // let break_label = self.emit_opcode_with_operand(Opcode::Break); - // let info = &mut self.jump_info[i]; - // info.push_break_label(node.label(), break_label, None); - // break; - // } - // } - let target_jump_info_index = self.continue_jump_info_target_index(node); - - for i in (target_jump_info_index..self.jump_info.len()).rev() { - let count = self.jump_info_open_environment_count(i); - for _ in 0..count { - self.emit_opcode(Opcode::PopEnvironment); - } - - if i == target_jump_info_index { - let continue_label = self.emit_opcode_with_operand(Opcode::Continue); - let info = &mut self.jump_info[i]; - info.push_continue_label(node.label(), continue_label, None); - break; - } + JumpRecord::new(JumpRecordKind::Continue, Self::DUMMY_LABEL, actions) + .perform_actions(u32::MAX, self); + } - let info = &mut self.jump_info[i]; - if info.is_try_block() && info.has_finally() { - let next_index = info.jumps.len(); + fn continue_jump_record_actions(&self, node: Continue) -> Vec { + let mut actions = Vec::default(); - self.emit_push_integer(next_index as i32 + 1); - self.emit_opcode(Opcode::PushFalse); - let continue_label = self.emit_opcode_with_operand(Opcode::Continue); + if let Some(label) = node.label() { + for (i, info) in self.jump_info.iter().enumerate().rev() { + let count = self.jump_info_open_environment_count(i); + actions.push(JumpRecordAction::PopEnvironments { count }); - let info = &mut self.jump_info[i]; - info.push_continue_label( - node.label(), - continue_label, - Some(target_jump_info_index), - ); - break; - } + if info.is_try_block() && info.has_finally() && !info.in_finally() { + let next_index = info.jumps.len(); - let info = &self.jump_info[i]; - if info.iterator_loop() { - let r#async = info.for_await_of_loop(); - self.iterator_close(r#async); - } - } - } + actions.push(JumpRecordAction::HandleFinally { + value: next_index as i32 + 1, + }); + actions.push(JumpRecordAction::CreateJump); + actions.push(JumpRecordAction::Transfter { index: i as u32 }); + } - fn continue_jump_info_target_index(&self, node: Continue) -> usize { - if let Some(label) = node.label() { - for (i, info) in self.jump_info.iter().enumerate().rev() { if info.label() == Some(label) { - return i; + actions.push(JumpRecordAction::CreateJump); + actions.push(JumpRecordAction::Transfter { index: i as u32 }); + break; + } + + if info.iterator_loop() { + actions.push(JumpRecordAction::CloseIterator { + r#async: info.for_await_of_loop(), + }); } } } else { for (i, info) in self.jump_info.iter().enumerate().rev() { + let count = self.jump_info_open_environment_count(i); + actions.push(JumpRecordAction::PopEnvironments { count }); + + if info.is_try_block() && info.has_finally() && !info.in_finally() { + let next_index = info.jumps.len(); + + actions.push(JumpRecordAction::HandleFinally { + value: next_index as i32 + 1, + }); + actions.push(JumpRecordAction::CreateJump); + actions.push(JumpRecordAction::Transfter { index: i as u32 }); + } + if info.is_loop() { - return i; + actions.push(JumpRecordAction::CreateJump); + actions.push(JumpRecordAction::Transfter { index: i as u32 }); + break; + } + + if info.iterator_loop() { + actions.push(JumpRecordAction::CloseIterator { + r#async: info.for_await_of_loop(), + }); } } } - unreachable!("There should be a valid break jump target") + actions.reverse(); + + actions } } diff --git a/boa_engine/src/bytecompiler/statement/try.rs b/boa_engine/src/bytecompiler/statement/try.rs index 2e427ec8a0d..c5d1fb11f2f 100644 --- a/boa_engine/src/bytecompiler/statement/try.rs +++ b/boa_engine/src/bytecompiler/statement/try.rs @@ -1,5 +1,5 @@ use crate::{ - bytecompiler::{ByteCompiler, Label}, + bytecompiler::{jump_control::JumpControlInfoFlags, ByteCompiler, Label}, vm::{BindingOpcode, Opcode}, }; use boa_ast::{ @@ -40,7 +40,7 @@ impl ByteCompiler<'_, '_> { if let Some(catch) = t.catch() { self.compile_catch_stmt(catch, has_finally, use_expr); } else { - self.emit_opcode(Opcode::PushZero); + self.emit_opcode(Opcode::Exception); self.emit_opcode(Opcode::PushTrue); } @@ -52,10 +52,14 @@ impl ByteCompiler<'_, '_> { let finally_start = self.next_opcode_location(); let finally_end = self.emit_opcode_with_operand(Opcode::FinallyStart); - self.set_jump_control_start_address(finally_start); + self.jump_info + .last_mut() + .expect("there should be a try block") + .flags |= JumpControlInfoFlags::IN_FINALLY; self.patch_jump_with_target(finally_loc, finally_start); // Compile finally statement body self.compile_finally_stmt(finally, finally_end, has_catch); + self.pop_try_control_info(finally_start); } else { let try_end = self.next_opcode_location(); @@ -112,7 +116,7 @@ impl ByteCompiler<'_, '_> { let has_throw_exit = self.jump_if_false(); if !has_catch { - self.emit_opcode(Opcode::Pop); + self.emit_opcode(Opcode::Throw); } // Rethrow error if error happend! diff --git a/boa_engine/src/vm/call_frame/try_stack.rs b/boa_engine/src/vm/call_frame/try_stack.rs index 9bf537ae993..f399a72566f 100644 --- a/boa_engine/src/vm/call_frame/try_stack.rs +++ b/boa_engine/src/vm/call_frame/try_stack.rs @@ -5,7 +5,6 @@ #[derive(Clone, Debug)] pub(crate) struct TryStackEntry { catch: u32, - finally: u32, /// The length of the value stack when the try block was entered. /// @@ -18,23 +17,14 @@ pub(crate) struct TryStackEntry { impl TryStackEntry { /// Creates a new [`EnvStackEntry`] with the supplied start addresses. - pub(crate) const fn new(catch: u32, finally: u32, fp: u32, env_fp: u32) -> Self { - Self { - catch, - finally, - fp, - env_fp, - } + pub(crate) const fn new(catch: u32, fp: u32, env_fp: u32) -> Self { + Self { catch, fp, env_fp } } pub(crate) const fn catch(&self) -> u32 { self.catch } - pub(crate) const fn finally(&self) -> u32 { - self.finally - } - pub(crate) const fn fp(&self) -> u32 { self.fp } diff --git a/boa_engine/src/vm/mod.rs b/boa_engine/src/vm/mod.rs index 7f99502dc13..2d7ded7f87d 100644 --- a/boa_engine/src/vm/mod.rs +++ b/boa_engine/src/vm/mod.rs @@ -312,7 +312,7 @@ impl Context<'_> { } } - self.vm.err = Some(err.clone()); + self.vm.err = Some(err); let evaluation = Opcode::ReThrow .execute(self) diff --git a/boa_engine/src/vm/opcode/control_flow/throw.rs b/boa_engine/src/vm/opcode/control_flow/throw.rs index e43560cd538..2f29c7cd655 100644 --- a/boa_engine/src/vm/opcode/control_flow/throw.rs +++ b/boa_engine/src/vm/opcode/control_flow/throw.rs @@ -30,165 +30,6 @@ impl Operation for Throw { } Ok(CompletionType::Throw) - // }; - - // // 1. Find the viable catch and finally blocks - // let current_address = context.vm.frame().pc; - // let mut envs = context.vm.frame().env_stack.iter(); - - // // Handle catch block - // if let Some(idx) = - // envs.rposition(|env| env.is_try_env() && env.start_address() != env.exit_address()) - // { - // // TODO: handle this - // // - // // let active_iterator = context.vm.frame().env_stack[..idx] - // // .iter() - // // .filter_map(EnvStackEntry::iterator) - // // .last(); - - // // // Close all iterators that are outside the catch context. - // // if let Some(active_iterator) = active_iterator { - // // let inactive = context - // // .vm - // // .frame_mut() - // // .iterators - // // .split_off(active_iterator as usize + 1); - // // for iterator in inactive { - // // if !iterator.done() { - // // drop(iterator.close(Ok(JsValue::undefined()), context)); - // // } - // // } - // // context.vm.err.take(); - // // } - - // let try_env = &context.vm.frame().env_stack[idx]; - // let try_env_frame_pointer = try_env.try_env_frame_pointer(); - // context.vm.stack.truncate(try_env_frame_pointer as usize); - - // let catch_target = context.vm.frame().env_stack[idx].start_address(); - - // let mut env_to_pop = 0; - // let mut target_address = u32::MAX; - // while context.vm.frame().env_stack.len() > 1 { - // let env_entry = context - // .vm - // .frame_mut() - // .env_stack - // .last() - // .expect("EnvStackEntries must exist"); - - // if env_entry.is_try_env() && env_entry.start_address() < env_entry.exit_address() { - // target_address = env_entry.start_address(); - // env_to_pop += env_entry.env_num(); - // context.vm.frame_mut().env_stack.pop(); - // break; - // } else if env_entry.is_finally_env() { - // if current_address > env_entry.start_address() { - // target_address = env_entry.exit_address(); - // } else { - // target_address = env_entry.start_address(); - // } - // break; - // } - // env_to_pop += env_entry.env_num(); - // context.vm.frame_mut().env_stack.pop(); - // } - - // let env_truncation_len = context.vm.environments.len().saturating_sub(env_to_pop); - // context.vm.environments.truncate(env_truncation_len); - - // if target_address == catch_target { - // context.vm.frame_mut().pc = catch_target; - // } else { - // context.vm.frame_mut().pc = target_address; - // }; - - // let record = AbruptCompletionRecord::new_throw().with_initial_target(catch_target); - // context.vm.frame_mut().abrupt_completion = Some(record); - // let err = error.to_opaque(context); - // context.vm.push(err); - // return Ok(CompletionType::Normal); - // } - - // let mut env_to_pop = 0; - // let mut target_address = None; - // let mut env_stack_to_pop = 0; - // for env_entry in context.vm.frame_mut().env_stack.iter_mut().rev() { - // if env_entry.is_finally_env() { - // if env_entry.start_address() < current_address { - // target_address = Some(env_entry.exit_address()); - // } else { - // target_address = Some(env_entry.start_address()); - // } - // break; - // }; - - // env_to_pop += env_entry.env_num(); - // if env_entry.is_global_env() { - // env_entry.clear_env_num(); - // break; - // }; - - // env_stack_to_pop += 1; - // } - - // let record = AbruptCompletionRecord::new_throw(); - // context.vm.frame_mut().abrupt_completion = Some(record); - - // if let Some(address) = target_address { - // for _ in 0..env_stack_to_pop { - // context.vm.frame_mut().env_stack.pop(); - // } - - // // TODo: handle this. - // // - // // let active_iterator = context - // // .vm - // // .frame() - // // .env_stack - // // .iter() - // // .filter_map(EnvStackEntry::iterator) - // // .last(); - - // // // Close all iterators that are outside the finally context. - // // if let Some(active_iterator) = active_iterator { - // // let inactive = context - // // .vm - // // .frame_mut() - // // .iterators - // // .split_off(active_iterator as usize + 1); - - // // for iterator in inactive { - // // if !iterator.done() { - // // drop(iterator.close(Ok(JsValue::undefined()), context)); - // // } - // // } - // // context.vm.err.take(); - // // } - - // let env_truncation_len = context.vm.environments.len().saturating_sub(env_to_pop); - // context.vm.environments.truncate(env_truncation_len); - - // // NOTE: There is could be leftover stack values, but this is fine, - // // since we truncate to the call frams's frame pointer on return. - - // context.vm.frame_mut().pc = address; - // let err = error.to_opaque(context); - // context.vm.push(err); - // return Ok(CompletionType::Normal); - // } - - // // Close all iterators that are still open. - // for iterator in std::mem::take(&mut context.vm.frame_mut().iterators) { - // if !iterator.done() { - // drop(iterator.close(Ok(JsValue::undefined()), context)); - // } - // } - // context.vm.err.take(); - - // context.vm.err = Some(error); - // Ok(CompletionType::Throw) } } diff --git a/boa_engine/src/vm/opcode/control_flow/try.rs b/boa_engine/src/vm/opcode/control_flow/try.rs index a1cac85d933..e90cd8ac6d9 100644 --- a/boa_engine/src/vm/opcode/control_flow/try.rs +++ b/boa_engine/src/vm/opcode/control_flow/try.rs @@ -16,7 +16,7 @@ impl Operation for TryStart { fn execute(context: &mut Context<'_>) -> JsResult { let catch = context.vm.read::(); - let finally = context.vm.read::(); + let _finally = context.vm.read::(); let fp = context.vm.stack.len() as u32; let env_fp = context.vm.environments.len() as u32; @@ -24,7 +24,7 @@ impl Operation for TryStart { .vm .frame_mut() .try_stack - .push(TryStackEntry::new(catch, finally, fp, env_fp)); + .push(TryStackEntry::new(catch, fp, env_fp)); Ok(CompletionType::Normal) }