Browse Source

Remove redundant `param_count` field from `CallFrame` (#2962)

pull/2968/head
Haled Odat 1 year ago committed by GitHub
parent
commit
15749ed295
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      boa_engine/src/vm/call_frame/mod.rs
  2. 19
      boa_engine/src/vm/code_block.rs
  3. 22
      boa_engine/src/vm/mod.rs
  4. 6
      boa_engine/src/vm/opcode/binary_ops/logical.rs
  5. 2
      boa_engine/src/vm/opcode/control_flow/break.rs
  6. 2
      boa_engine/src/vm/opcode/control_flow/catch.rs
  7. 2
      boa_engine/src/vm/opcode/control_flow/continue.rs
  8. 28
      boa_engine/src/vm/opcode/control_flow/finally.rs
  9. 2
      boa_engine/src/vm/opcode/control_flow/labelled.rs
  10. 6
      boa_engine/src/vm/opcode/control_flow/return.rs
  11. 14
      boa_engine/src/vm/opcode/control_flow/throw.rs
  12. 4
      boa_engine/src/vm/opcode/environment/mod.rs
  13. 26
      boa_engine/src/vm/opcode/generator/mod.rs
  14. 2
      boa_engine/src/vm/opcode/iteration/iterator.rs
  15. 10
      boa_engine/src/vm/opcode/jump/mod.rs
  16. 2
      boa_engine/src/vm/opcode/mod.rs
  17. 12
      boa_engine/src/vm/opcode/rest_parameter/mod.rs
  18. 4
      boa_engine/src/vm/opcode/switch/mod.rs
  19. 2
      boa_engine/src/vm/opcode/templates/mod.rs

26
boa_engine/src/vm/call_frame/mod.rs

@ -19,18 +19,17 @@ pub(crate) use env_stack::EnvStackEntry;
#[derive(Clone, Debug, Finalize, Trace)] #[derive(Clone, Debug, Finalize, Trace)]
pub struct CallFrame { pub struct CallFrame {
pub(crate) code_block: Gc<CodeBlock>, pub(crate) code_block: Gc<CodeBlock>,
pub(crate) pc: usize, pub(crate) pc: u32,
pub(crate) fp: usize, pub(crate) fp: u32,
#[unsafe_ignore_trace] #[unsafe_ignore_trace]
pub(crate) abrupt_completion: Option<AbruptCompletionRecord>, pub(crate) abrupt_completion: Option<AbruptCompletionRecord>,
#[unsafe_ignore_trace] #[unsafe_ignore_trace]
pub(crate) r#yield: bool, pub(crate) r#yield: bool,
pub(crate) pop_on_return: usize, pub(crate) pop_on_return: u32,
// Tracks the number of environments in environment entry. // Tracks the number of environments in environment entry.
// On abrupt returns this is used to decide how many environments need to be pop'ed. // On abrupt returns this is used to decide how many environments need to be pop'ed.
pub(crate) env_stack: Vec<EnvStackEntry>, pub(crate) env_stack: Vec<EnvStackEntry>,
pub(crate) param_count: usize, pub(crate) argument_count: u32,
pub(crate) arg_count: usize,
#[unsafe_ignore_trace] #[unsafe_ignore_trace]
pub(crate) generator_resume_kind: GeneratorResumeKind, pub(crate) generator_resume_kind: GeneratorResumeKind,
pub(crate) promise_capability: Option<PromiseCapability>, pub(crate) promise_capability: Option<PromiseCapability>,
@ -68,8 +67,7 @@ impl CallFrame {
env_stack: Vec::from([EnvStackEntry::new(0, max_length)]), env_stack: Vec::from([EnvStackEntry::new(0, max_length)]),
abrupt_completion: None, abrupt_completion: None,
r#yield: false, r#yield: false,
param_count: 0, argument_count: 0,
arg_count: 0,
generator_resume_kind: GeneratorResumeKind::Normal, generator_resume_kind: GeneratorResumeKind::Normal,
promise_capability: None, promise_capability: None,
async_generator: None, async_generator: None,
@ -78,22 +76,16 @@ impl CallFrame {
} }
} }
/// Updates a `CallFrame`'s `param_count` field with the value provided. /// Updates a `CallFrame`'s `argument_count` field with the value provided.
pub(crate) fn with_param_count(mut self, count: usize) -> Self { pub(crate) fn with_argument_count(mut self, count: u32) -> Self {
self.param_count = count; self.argument_count = count;
self
}
/// Updates a `CallFrame`'s `arg_count` field with the value provided.
pub(crate) fn with_arg_count(mut self, count: usize) -> Self {
self.arg_count = count;
self self
} }
} }
/// ---- `CallFrame` stack methods ---- /// ---- `CallFrame` stack methods ----
impl CallFrame { impl CallFrame {
pub(crate) fn set_frame_pointer(&mut self, pointer: usize) { pub(crate) fn set_frame_pointer(&mut self, pointer: u32) {
self.fp = pointer; self.fp = pointer;
} }

19
boa_engine/src/vm/code_block.rs

@ -1063,7 +1063,7 @@ impl JsObject {
); );
} }
let arg_count = args.len(); let argument_count = args.len();
// Push function arguments to the stack. // Push function arguments to the stack.
let mut args = if code.params.as_ref().len() > args.len() { let mut args = if code.params.as_ref().len() > args.len() {
@ -1081,11 +1081,7 @@ impl JsObject {
std::mem::swap(&mut context.vm.stack, &mut stack); std::mem::swap(&mut context.vm.stack, &mut stack);
let param_count = code.params.as_ref().len(); let mut frame = CallFrame::new(code).with_argument_count(argument_count as u32);
let mut frame = CallFrame::new(code)
.with_param_count(param_count)
.with_arg_count(arg_count);
frame.promise_capability = promise_capability.clone(); frame.promise_capability = promise_capability.clone();
std::mem::swap(&mut context.vm.active_runnable, &mut script_or_module); std::mem::swap(&mut context.vm.active_runnable, &mut script_or_module);
@ -1326,7 +1322,7 @@ impl JsObject {
); );
} }
let arg_count = args.len(); let argument_count = args.len();
// Push function arguments to the stack. // Push function arguments to the stack.
let args = if code.params.as_ref().len() > args.len() { let args = if code.params.as_ref().len() > args.len() {
@ -1344,16 +1340,13 @@ impl JsObject {
context.vm.push(arg.clone()); context.vm.push(arg.clone());
} }
let param_count = code.params.as_ref().len();
let has_binding_identifier = code.has_binding_identifier; let has_binding_identifier = code.has_binding_identifier;
std::mem::swap(&mut context.vm.active_runnable, &mut script_or_module); std::mem::swap(&mut context.vm.active_runnable, &mut script_or_module);
context.vm.push_frame( context
CallFrame::new(code) .vm
.with_param_count(param_count) .push_frame(CallFrame::new(code).with_argument_count(argument_count as u32));
.with_arg_count(arg_count),
);
let record = context.run(); let record = context.run();

22
boa_engine/src/vm/mod.rs

@ -114,8 +114,8 @@ impl Vm {
#[track_caller] #[track_caller]
pub(crate) fn read<T: Readable>(&mut self) -> T { pub(crate) fn read<T: Readable>(&mut self) -> T {
let value = self.frame().code_block.read::<T>(self.frame().pc); let value = self.frame().code_block.read::<T>(self.frame().pc as usize);
self.frame_mut().pc += size_of::<T>(); self.frame_mut().pc += size_of::<T>() as u32;
value value
} }
@ -159,7 +159,7 @@ impl Context<'_> {
fn execute_instruction(&mut self) -> JsResult<CompletionType> { fn execute_instruction(&mut self) -> JsResult<CompletionType> {
let opcode: Opcode = { let opcode: Opcode = {
let _timer = Profiler::global().start_event("Opcode retrieval", "vm"); let _timer = Profiler::global().start_event("Opcode retrieval", "vm");
let opcode = self.vm.frame().code_block.bytecode[self.vm.frame().pc] let opcode = self.vm.frame().code_block.bytecode[self.vm.frame().pc as usize]
.try_into() .try_into()
.expect("could not convert code at PC to opcode"); .expect("could not convert code at PC to opcode");
self.vm.frame_mut().pc += 1; self.vm.frame_mut().pc += 1;
@ -213,7 +213,9 @@ impl Context<'_> {
} }
let current_stack_length = self.vm.stack.len(); let current_stack_length = self.vm.stack.len();
self.vm.frame_mut().set_frame_pointer(current_stack_length); self.vm
.frame_mut()
.set_frame_pointer(current_stack_length as u32);
// If the current executing function is an async function we have to resolve/reject it's promise at the end. // If the current executing function is an async function we have to resolve/reject it's promise at the end.
// The relevant spec section is 3. in [AsyncBlockStart](https://tc39.es/ecma262/#sec-asyncblockstart). // The relevant spec section is 3. in [AsyncBlockStart](https://tc39.es/ecma262/#sec-asyncblockstart).
@ -221,7 +223,7 @@ impl Context<'_> {
let execution_completion = loop { let execution_completion = loop {
// 1. Exit the execution loop if program counter ever is equal to or exceeds the amount of instructions // 1. Exit the execution loop if program counter ever is equal to or exceeds the amount of instructions
if self.vm.frame().code_block.bytecode.len() <= self.vm.frame().pc { if self.vm.frame().code_block.bytecode.len() <= self.vm.frame().pc as usize {
break CompletionType::Normal; break CompletionType::Normal;
} }
@ -238,7 +240,7 @@ impl Context<'_> {
// 1. Run the next instruction. // 1. Run the next instruction.
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
let result = if self.vm.trace || self.vm.frame().code_block.trace.get() { let result = if self.vm.trace || self.vm.frame().code_block.trace.get() {
let mut pc = self.vm.frame().pc; let mut pc = self.vm.frame().pc as usize;
let opcode: Opcode = self let opcode: Opcode = self
.vm .vm
.frame() .frame()
@ -357,18 +359,18 @@ impl Context<'_> {
// Determine the execution result // Determine the execution result
let execution_result = if execution_completion == CompletionType::Throw { let execution_result = if execution_completion == CompletionType::Throw {
self.vm.frame_mut().abrupt_completion = None; self.vm.frame_mut().abrupt_completion = None;
self.vm.stack.truncate(self.vm.frame().fp); self.vm.stack.truncate(self.vm.frame().fp as usize);
JsValue::undefined() JsValue::undefined()
} else if execution_completion == CompletionType::Return { } else if execution_completion == CompletionType::Return {
self.vm.frame_mut().abrupt_completion = None; self.vm.frame_mut().abrupt_completion = None;
let result = self.vm.pop(); let result = self.vm.pop();
self.vm.stack.truncate(self.vm.frame().fp); self.vm.stack.truncate(self.vm.frame().fp as usize);
result result
} else if self.vm.stack.len() <= self.vm.frame().fp { } else if self.vm.stack.len() <= self.vm.frame().fp as usize {
JsValue::undefined() JsValue::undefined()
} else { } else {
let result = self.vm.pop(); let result = self.vm.pop();
self.vm.stack.truncate(self.vm.frame().fp); self.vm.stack.truncate(self.vm.frame().fp as usize);
result result
}; };

6
boa_engine/src/vm/opcode/binary_ops/logical.rs

@ -18,7 +18,7 @@ impl Operation for LogicalAnd {
let exit = context.vm.read::<u32>(); let exit = context.vm.read::<u32>();
let lhs = context.vm.pop(); let lhs = context.vm.pop();
if !lhs.to_boolean() { if !lhs.to_boolean() {
context.vm.frame_mut().pc = exit as usize; context.vm.frame_mut().pc = exit;
context.vm.push(lhs); context.vm.push(lhs);
} }
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
@ -40,7 +40,7 @@ impl Operation for LogicalOr {
let exit = context.vm.read::<u32>(); let exit = context.vm.read::<u32>();
let lhs = context.vm.pop(); let lhs = context.vm.pop();
if lhs.to_boolean() { if lhs.to_boolean() {
context.vm.frame_mut().pc = exit as usize; context.vm.frame_mut().pc = exit;
context.vm.push(lhs); context.vm.push(lhs);
} }
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
@ -62,7 +62,7 @@ impl Operation for Coalesce {
let exit = context.vm.read::<u32>(); let exit = context.vm.read::<u32>();
let lhs = context.vm.pop(); let lhs = context.vm.pop();
if !lhs.is_null_or_undefined() { if !lhs.is_null_or_undefined() {
context.vm.frame_mut().pc = exit as usize; context.vm.frame_mut().pc = exit;
context.vm.push(lhs); context.vm.push(lhs);
} }
Ok(CompletionType::Normal) Ok(CompletionType::Normal)

2
boa_engine/src/vm/opcode/control_flow/break.rs

@ -63,7 +63,7 @@ impl Operation for Break {
context.vm.frame_mut().abrupt_completion = Some(new_record); context.vm.frame_mut().abrupt_completion = Some(new_record);
// 3. Set program counter and finally return fields. // 3. Set program counter and finally return fields.
context.vm.frame_mut().pc = jump_address as usize; context.vm.frame_mut().pc = jump_address;
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
} }
} }

2
boa_engine/src/vm/opcode/control_flow/catch.rs

@ -15,7 +15,7 @@ impl Operation for CatchStart {
const INSTRUCTION: &'static str = "INST - CatchStart"; const INSTRUCTION: &'static str = "INST - CatchStart";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let start = context.vm.frame().pc as u32 - 1; let start = context.vm.frame().pc - 1;
let finally = context.vm.read::<u32>(); let finally = context.vm.read::<u32>();
context context

2
boa_engine/src/vm/opcode/control_flow/continue.rs

@ -71,7 +71,7 @@ impl Operation for Continue {
context.vm.frame_mut().abrupt_completion = Some(new_record); context.vm.frame_mut().abrupt_completion = Some(new_record);
// 3. Set program counter and finally return fields. // 3. Set program counter and finally return fields.
context.vm.frame_mut().pc = jump_address as usize; context.vm.frame_mut().pc = jump_address;
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
} }
} }

28
boa_engine/src/vm/opcode/control_flow/finally.rs

@ -41,9 +41,12 @@ impl Operation for FinallyEnd {
const INSTRUCTION: &'static str = "INST - FinallyEnd"; const INSTRUCTION: &'static str = "INST - FinallyEnd";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let finally_candidates = context.vm.frame().env_stack.iter().filter(|env| { let finally_candidates = context
env.is_finally_env() && context.vm.frame().pc < (env.start_address() as usize) .vm
}); .frame()
.env_stack
.iter()
.filter(|env| env.is_finally_env() && context.vm.frame().pc < env.start_address());
let next_finally = match finally_candidates.last() { let next_finally = match finally_candidates.last() {
Some(env) => env.start_address(), Some(env) => env.start_address(),
@ -53,7 +56,7 @@ impl Operation for FinallyEnd {
let mut envs_to_pop = 0; let mut envs_to_pop = 0;
match context.vm.frame().abrupt_completion { match context.vm.frame().abrupt_completion {
Some(record) if next_finally < record.target() => { Some(record) if next_finally < record.target() => {
context.vm.frame_mut().pc = next_finally as usize; context.vm.frame_mut().pc = next_finally;
while let Some(env_entry) = context.vm.frame().env_stack.last() { while let Some(env_entry) = context.vm.frame().env_stack.last() {
if next_finally <= env_entry.exit_address() { if next_finally <= env_entry.exit_address() {
@ -67,11 +70,9 @@ impl Operation for FinallyEnd {
let env_truncation_len = context.vm.environments.len().saturating_sub(envs_to_pop); let env_truncation_len = context.vm.environments.len().saturating_sub(envs_to_pop);
context.vm.environments.truncate(env_truncation_len); context.vm.environments.truncate(env_truncation_len);
} }
Some(record) Some(record) if record.is_break() && context.vm.frame().pc < record.target() => {
if record.is_break() && context.vm.frame().pc < record.target() as usize =>
{
// handle the continuation of an abrupt break. // handle the continuation of an abrupt break.
context.vm.frame_mut().pc = record.target() as usize; context.vm.frame_mut().pc = record.target();
while let Some(env_entry) = context.vm.frame().env_stack.last() { while let Some(env_entry) = context.vm.frame().env_stack.last() {
if record.target() == env_entry.exit_address() { if record.target() == env_entry.exit_address() {
break; break;
@ -86,11 +87,9 @@ impl Operation for FinallyEnd {
let env_truncation_len = context.vm.environments.len().saturating_sub(envs_to_pop); let env_truncation_len = context.vm.environments.len().saturating_sub(envs_to_pop);
context.vm.environments.truncate(env_truncation_len); context.vm.environments.truncate(env_truncation_len);
} }
Some(record) Some(record) if record.is_continue() && context.vm.frame().pc > record.target() => {
if record.is_continue() && context.vm.frame().pc > record.target() as usize =>
{
// Handle the continuation of an abrupt continue // Handle the continuation of an abrupt continue
context.vm.frame_mut().pc = record.target() as usize; context.vm.frame_mut().pc = record.target();
while let Some(env_entry) = context.vm.frame().env_stack.last() { while let Some(env_entry) = context.vm.frame().env_stack.last() {
if env_entry.start_address() == record.target() { if env_entry.start_address() == record.target() {
break; break;
@ -107,10 +106,9 @@ impl Operation for FinallyEnd {
return Ok(CompletionType::Return); return Ok(CompletionType::Return);
} }
Some(record) Some(record)
if record.is_throw_with_target() if record.is_throw_with_target() && context.vm.frame().pc < record.target() =>
&& context.vm.frame().pc < record.target() as usize =>
{ {
context.vm.frame_mut().pc = record.target() as usize; context.vm.frame_mut().pc = record.target();
while let Some(env_entry) = context.vm.frame_mut().env_stack.pop() { while let Some(env_entry) = context.vm.frame_mut().env_stack.pop() {
envs_to_pop += env_entry.env_num(); envs_to_pop += env_entry.env_num();
if env_entry.start_address() == record.target() { if env_entry.start_address() == record.target() {

2
boa_engine/src/vm/opcode/control_flow/labelled.rs

@ -15,7 +15,7 @@ impl Operation for LabelledStart {
const INSTRUCTION: &'static str = "INST - LabelledStart"; const INSTRUCTION: &'static str = "INST - LabelledStart";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let start = context.vm.frame().pc as u32 - 1; let start = context.vm.frame().pc - 1;
let end = context.vm.read::<u32>(); let end = context.vm.read::<u32>();
context context
.vm .vm

6
boa_engine/src/vm/opcode/control_flow/return.rs

@ -20,10 +20,10 @@ impl Operation for Return {
let mut finally_address = None; let mut finally_address = None;
while let Some(env_entry) = context.vm.frame().env_stack.last() { while let Some(env_entry) = context.vm.frame().env_stack.last() {
if env_entry.is_finally_env() { if env_entry.is_finally_env() {
if (env_entry.start_address() as usize) < current_address { if env_entry.start_address() < current_address {
finally_address = Some(env_entry.exit_address() as usize); finally_address = Some(env_entry.exit_address());
} else { } else {
finally_address = Some(env_entry.start_address() as usize); finally_address = Some(env_entry.start_address());
} }
break; break;
} }

14
boa_engine/src/vm/opcode/control_flow/throw.rs

@ -64,7 +64,7 @@ impl Operation for Throw {
context.vm.frame_mut().env_stack.pop(); context.vm.frame_mut().env_stack.pop();
break; break;
} else if env_entry.is_finally_env() { } else if env_entry.is_finally_env() {
if current_address > (env_entry.start_address() as usize) { if current_address > env_entry.start_address() {
target_address = env_entry.exit_address(); target_address = env_entry.exit_address();
} else { } else {
target_address = env_entry.start_address(); target_address = env_entry.start_address();
@ -79,9 +79,9 @@ impl Operation for Throw {
context.vm.environments.truncate(env_truncation_len); context.vm.environments.truncate(env_truncation_len);
if target_address == catch_target { if target_address == catch_target {
context.vm.frame_mut().pc = catch_target as usize; context.vm.frame_mut().pc = catch_target;
} else { } else {
context.vm.frame_mut().pc = target_address as usize; context.vm.frame_mut().pc = target_address;
}; };
for _ in 0..context.vm.frame().pop_on_return { for _ in 0..context.vm.frame().pop_on_return {
@ -101,10 +101,10 @@ impl Operation for Throw {
let mut env_stack_to_pop = 0; let mut env_stack_to_pop = 0;
for env_entry in context.vm.frame_mut().env_stack.iter_mut().rev() { for env_entry in context.vm.frame_mut().env_stack.iter_mut().rev() {
if env_entry.is_finally_env() { if env_entry.is_finally_env() {
if (env_entry.start_address() as usize) < current_address { if env_entry.start_address() < current_address {
target_address = Some(env_entry.exit_address() as usize); target_address = Some(env_entry.exit_address());
} else { } else {
target_address = Some(env_entry.start_address() as usize); target_address = Some(env_entry.start_address());
} }
break; break;
}; };
@ -133,7 +133,7 @@ impl Operation for Throw {
.vm .vm
.stack .stack
.len() .len()
.saturating_sub(context.vm.frame().pop_on_return); .saturating_sub(context.vm.frame().pop_on_return as usize);
context.vm.stack.truncate(previous_stack_size); context.vm.stack.truncate(previous_stack_size);
context.vm.frame_mut().pop_on_return = 0; context.vm.frame_mut().pop_on_return = 0;

4
boa_engine/src/vm/opcode/environment/mod.rs

@ -220,8 +220,8 @@ impl Operation for SuperCallDerived {
const INSTRUCTION: &'static str = "INST - SuperCallDerived"; const INSTRUCTION: &'static str = "INST - SuperCallDerived";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let argument_count = context.vm.frame().arg_count; let argument_count = context.vm.frame().argument_count;
let mut arguments = Vec::with_capacity(argument_count); let mut arguments = Vec::with_capacity(argument_count as usize);
for _ in 0..argument_count { for _ in 0..argument_count {
arguments.push(context.vm.pop()); arguments.push(context.vm.pop());
} }

26
boa_engine/src/vm/opcode/generator/mod.rs

@ -40,8 +40,8 @@ impl Operation for GeneratorNext {
.iter() .iter()
.filter(|entry| entry.is_finally_env()); .filter(|entry| entry.is_finally_env());
if let Some(next_finally) = finally_entries.rev().next() { if let Some(next_finally) = finally_entries.rev().next() {
if context.vm.frame().pc < next_finally.start_address() as usize { if context.vm.frame().pc < next_finally.start_address() {
context.vm.frame_mut().pc = next_finally.start_address() as usize; context.vm.frame_mut().pc = next_finally.start_address();
let return_record = AbruptCompletionRecord::new_return(); let return_record = AbruptCompletionRecord::new_return();
context.vm.frame_mut().abrupt_completion = Some(return_record); context.vm.frame_mut().abrupt_completion = Some(return_record);
return Ok(CompletionType::Normal); return Ok(CompletionType::Normal);
@ -107,10 +107,10 @@ impl Operation for AsyncGeneratorNext {
Err(e) => e.clone().to_opaque(context), Err(e) => e.clone().to_opaque(context),
}; };
context.vm.push(value); context.vm.push(value);
context.vm.frame_mut().pc = skip_yield as usize; context.vm.frame_mut().pc = skip_yield;
} else { } else {
context.vm.push(completion.clone()?); context.vm.push(completion.clone()?);
context.vm.frame_mut().pc = skip_yield_await as usize; context.vm.frame_mut().pc = skip_yield_await;
} }
} else { } else {
gen.state = AsyncGeneratorState::SuspendedYield; gen.state = AsyncGeneratorState::SuspendedYield;
@ -135,7 +135,7 @@ impl Operation for GeneratorAsyncResumeYield {
match context.vm.frame().generator_resume_kind { match context.vm.frame().generator_resume_kind {
GeneratorResumeKind::Normal => { GeneratorResumeKind::Normal => {
context.vm.frame_mut().pc = normal_completion as usize; context.vm.frame_mut().pc = normal_completion;
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
} }
GeneratorResumeKind::Throw => Err(JsError::from_opaque(context.vm.pop())), GeneratorResumeKind::Throw => Err(JsError::from_opaque(context.vm.pop())),
@ -190,7 +190,7 @@ impl Operation for GeneratorNextDelegate {
})?; })?;
let done = result.get(utf16!("done"), context)?.to_boolean(); let done = result.get(utf16!("done"), context)?.to_boolean();
if done { if done {
context.vm.frame_mut().pc = done_address as usize; context.vm.frame_mut().pc = done_address;
let value = result.get(utf16!("value"), context)?; let value = result.get(utf16!("value"), context)?;
context.vm.push(value); context.vm.push(value);
return Ok(CompletionType::Normal); return Ok(CompletionType::Normal);
@ -211,7 +211,7 @@ impl Operation for GeneratorNextDelegate {
})?; })?;
let done = result_object.get(utf16!("done"), context)?.to_boolean(); let done = result_object.get(utf16!("done"), context)?.to_boolean();
if done { if done {
context.vm.frame_mut().pc = done_address as usize; context.vm.frame_mut().pc = done_address;
let value = result_object.get(utf16!("value"), context)?; let value = result_object.get(utf16!("value"), context)?;
context.vm.push(value); context.vm.push(value);
return Ok(CompletionType::Normal); return Ok(CompletionType::Normal);
@ -222,7 +222,7 @@ impl Operation for GeneratorNextDelegate {
context.vm.frame_mut().r#yield = true; context.vm.frame_mut().r#yield = true;
return Ok(CompletionType::Return); return Ok(CompletionType::Return);
} }
context.vm.frame_mut().pc = done_address as usize; context.vm.frame_mut().pc = done_address;
let iterator_record = IteratorRecord::new(iterator.clone(), next_method, false); let iterator_record = IteratorRecord::new(iterator.clone(), next_method, false);
iterator_record.close(Ok(JsValue::Undefined), context)?; iterator_record.close(Ok(JsValue::Undefined), context)?;
@ -302,7 +302,7 @@ impl Operation for GeneratorAsyncDelegateNext {
context.vm.push(iterator.clone()); context.vm.push(iterator.clone());
context.vm.push(next_method.clone()); context.vm.push(next_method.clone());
context.vm.push(false); context.vm.push(false);
context.vm.frame_mut().pc = throw_method_undefined as usize; context.vm.frame_mut().pc = throw_method_undefined;
} }
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
@ -320,7 +320,7 @@ impl Operation for GeneratorAsyncDelegateNext {
context.vm.push(iterator.clone()); context.vm.push(iterator.clone());
context.vm.push(next_method.clone()); context.vm.push(next_method.clone());
context.vm.push(received); context.vm.push(received);
context.vm.frame_mut().pc = return_method_undefined as usize; context.vm.frame_mut().pc = return_method_undefined;
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
} }
} }
@ -362,7 +362,7 @@ impl Operation for GeneratorAsyncDelegateResume {
return Return::execute(context); return Return::execute(context);
} }
context.vm.frame_mut().pc = exit as usize; context.vm.frame_mut().pc = exit;
return Ok(CompletionType::Normal); return Ok(CompletionType::Normal);
} }
@ -396,10 +396,10 @@ impl Operation for GeneratorAsyncDelegateResume {
Err(e) => e.clone().to_opaque(context), Err(e) => e.clone().to_opaque(context),
}; };
context.vm.push(value); context.vm.push(value);
context.vm.frame_mut().pc = skip_yield as usize; context.vm.frame_mut().pc = skip_yield;
} else { } else {
context.vm.push(completion.clone()?); context.vm.push(completion.clone()?);
context.vm.frame_mut().pc = normal_completion as usize; context.vm.frame_mut().pc = normal_completion;
} }
} else { } else {
gen.state = AsyncGeneratorState::SuspendedYield; gen.state = AsyncGeneratorState::SuspendedYield;

2
boa_engine/src/vm/opcode/iteration/iterator.rs

@ -155,7 +155,7 @@ impl Operation for IteratorUnwrapNextOrJump {
.ok_or_else(|| JsNativeError::typ().with_message("next value should be an object"))?; .ok_or_else(|| JsNativeError::typ().with_message("next value should be an object"))?;
if next_result.complete(context)? { if next_result.complete(context)? {
context.vm.frame_mut().pc = address as usize; context.vm.frame_mut().pc = address;
context.vm.push(true); context.vm.push(true);
} else { } else {
context.vm.push(false); context.vm.push(false);

10
boa_engine/src/vm/opcode/jump/mod.rs

@ -16,7 +16,7 @@ impl Operation for Jump {
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let address = context.vm.read::<u32>(); let address = context.vm.read::<u32>();
context.vm.frame_mut().pc = address as usize; context.vm.frame_mut().pc = address;
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
} }
} }
@ -35,7 +35,7 @@ impl Operation for JumpIfTrue {
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let address = context.vm.read::<u32>(); let address = context.vm.read::<u32>();
if context.vm.pop().to_boolean() { if context.vm.pop().to_boolean() {
context.vm.frame_mut().pc = address as usize; context.vm.frame_mut().pc = address;
} }
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
} }
@ -55,7 +55,7 @@ impl Operation for JumpIfFalse {
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let address = context.vm.read::<u32>(); let address = context.vm.read::<u32>();
if !context.vm.pop().to_boolean() { if !context.vm.pop().to_boolean() {
context.vm.frame_mut().pc = address as usize; context.vm.frame_mut().pc = address;
} }
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
} }
@ -76,7 +76,7 @@ impl Operation for JumpIfNotUndefined {
let address = context.vm.read::<u32>(); let address = context.vm.read::<u32>();
let value = context.vm.pop(); let value = context.vm.pop();
if !value.is_undefined() { if !value.is_undefined() {
context.vm.frame_mut().pc = address as usize; context.vm.frame_mut().pc = address;
context.vm.push(value); context.vm.push(value);
} }
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
@ -98,7 +98,7 @@ impl Operation for JumpIfNullOrUndefined {
let address = context.vm.read::<u32>(); let address = context.vm.read::<u32>();
let value = context.vm.pop(); let value = context.vm.pop();
if value.is_null_or_undefined() { if value.is_null_or_undefined() {
context.vm.frame_mut().pc = address as usize; context.vm.frame_mut().pc = address;
} else { } else {
context.vm.push(value); context.vm.push(value);
} }

2
boa_engine/src/vm/opcode/mod.rs

@ -679,7 +679,7 @@ generate_impl! {
/// Stack: **=>** /// Stack: **=>**
GetLocator, GetLocator,
/// Find a binding on the environment chain and push its value to the stack and its /// Find a binding on the environment chain and push its value to the stack and its
/// `BindingLocator` to the `bindings_stack`. /// `BindingLocator` to the `bindings_stack`.
/// ///
/// Operands: name_index: `u32` /// Operands: name_index: `u32`

12
boa_engine/src/vm/opcode/rest_parameter/mod.rs

@ -12,12 +12,12 @@ use crate::{
pub(crate) struct RestParameterInit; pub(crate) struct RestParameterInit;
impl Operation for RestParameterInit { impl Operation for RestParameterInit {
const NAME: &'static str = "FunctionRestParameter"; const NAME: &'static str = "RestParameterInit";
const INSTRUCTION: &'static str = "INST - FunctionRestParameter"; const INSTRUCTION: &'static str = "INST - RestParameterInit";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let arg_count = context.vm.frame().arg_count; let arg_count = context.vm.frame().argument_count as usize;
let param_count = context.vm.frame().param_count; let param_count = context.vm.frame().code_block().params.as_ref().len();
if arg_count >= param_count { if arg_count >= param_count {
let rest_count = arg_count - param_count + 1; let rest_count = arg_count - param_count + 1;
let mut args = Vec::with_capacity(rest_count); let mut args = Vec::with_capacity(rest_count);
@ -50,8 +50,8 @@ impl Operation for RestParameterPop {
const INSTRUCTION: &'static str = "INST - RestParameterPop"; const INSTRUCTION: &'static str = "INST - RestParameterPop";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let arg_count = context.vm.frame().arg_count; let arg_count = context.vm.frame().argument_count;
let param_count = context.vm.frame().param_count; let param_count = context.vm.frame().code_block().params.as_ref().len() as u32;
if arg_count > param_count { if arg_count > param_count {
for _ in 0..(arg_count - param_count) { for _ in 0..(arg_count - param_count) {
context.vm.pop(); context.vm.pop();

4
boa_engine/src/vm/opcode/switch/mod.rs

@ -21,7 +21,7 @@ impl Operation for Case {
let value = context.vm.pop(); let value = context.vm.pop();
if value.strict_equals(&cond) { if value.strict_equals(&cond) {
context.vm.frame_mut().pc = address as usize; context.vm.frame_mut().pc = address;
} else { } else {
context.vm.push(value); context.vm.push(value);
} }
@ -43,7 +43,7 @@ impl Operation for Default {
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let exit = context.vm.read::<u32>(); let exit = context.vm.read::<u32>();
let _val = context.vm.pop(); let _val = context.vm.pop();
context.vm.frame_mut().pc = exit as usize; context.vm.frame_mut().pc = exit;
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
} }
} }

2
boa_engine/src/vm/opcode/templates/mod.rs

@ -24,7 +24,7 @@ impl Operation for TemplateLookup {
if let Some(template) = context.realm().lookup_template(site) { if let Some(template) = context.realm().lookup_template(site) {
context.vm.push(template); context.vm.push(template);
context.vm.frame_mut().pc = jump as usize; context.vm.frame_mut().pc = jump;
} }
Ok(CompletionType::Normal) Ok(CompletionType::Normal)

Loading…
Cancel
Save