Browse Source

Implement asynchronous evaluation of scripts (#3044)

* Implement asynchronous evaluation of scripts

* cargo fmt

* FIx fuzz build

* Reduce execution table size

---------

Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com>
pull/3403/head
José Julián Espina 1 year ago committed by GitHub
parent
commit
9ef368f170
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 52
      boa_engine/src/script.rs
  2. 285
      boa_engine/src/vm/mod.rs
  3. 3
      boa_engine/src/vm/opcode/await/mod.rs
  4. 3
      boa_engine/src/vm/opcode/binary_ops/logical.rs
  5. 1
      boa_engine/src/vm/opcode/binary_ops/macro_defined.rs
  6. 6
      boa_engine/src/vm/opcode/binary_ops/mod.rs
  7. 9
      boa_engine/src/vm/opcode/call/mod.rs
  8. 1
      boa_engine/src/vm/opcode/concat/mod.rs
  9. 6
      boa_engine/src/vm/opcode/control_flow/jump.rs
  10. 4
      boa_engine/src/vm/opcode/control_flow/return.rs
  11. 5
      boa_engine/src/vm/opcode/control_flow/throw.rs
  12. 1
      boa_engine/src/vm/opcode/copy/mod.rs
  13. 4
      boa_engine/src/vm/opcode/define/class/getter.rs
  14. 4
      boa_engine/src/vm/opcode/define/class/method.rs
  15. 4
      boa_engine/src/vm/opcode/define/class/setter.rs
  16. 3
      boa_engine/src/vm/opcode/define/mod.rs
  17. 2
      boa_engine/src/vm/opcode/define/own_property.rs
  18. 4
      boa_engine/src/vm/opcode/delete/mod.rs
  19. 1
      boa_engine/src/vm/opcode/dup/mod.rs
  20. 7
      boa_engine/src/vm/opcode/environment/mod.rs
  21. 6
      boa_engine/src/vm/opcode/generator/mod.rs
  22. 2
      boa_engine/src/vm/opcode/generator/yield_stm.rs
  23. 1
      boa_engine/src/vm/opcode/get/argument.rs
  24. 4
      boa_engine/src/vm/opcode/get/function.rs
  25. 2
      boa_engine/src/vm/opcode/get/generator.rs
  26. 4
      boa_engine/src/vm/opcode/get/name.rs
  27. 1
      boa_engine/src/vm/opcode/get/private.rs
  28. 3
      boa_engine/src/vm/opcode/get/property.rs
  29. 1
      boa_engine/src/vm/opcode/iteration/for_in.rs
  30. 2
      boa_engine/src/vm/opcode/iteration/get.rs
  31. 12
      boa_engine/src/vm/opcode/iteration/iterator.rs
  32. 1
      boa_engine/src/vm/opcode/iteration/loop_ops.rs
  33. 2
      boa_engine/src/vm/opcode/meta/mod.rs
  34. 42
      boa_engine/src/vm/opcode/mod.rs
  35. 26
      boa_engine/src/vm/opcode/modifier.rs
  36. 2
      boa_engine/src/vm/opcode/new/mod.rs
  37. 2
      boa_engine/src/vm/opcode/nop/mod.rs
  38. 2
      boa_engine/src/vm/opcode/pop/mod.rs
  39. 4
      boa_engine/src/vm/opcode/push/array.rs
  40. 2
      boa_engine/src/vm/opcode/push/class/field.rs
  41. 1
      boa_engine/src/vm/opcode/push/class/mod.rs
  42. 3
      boa_engine/src/vm/opcode/push/class/private.rs
  43. 4
      boa_engine/src/vm/opcode/push/environment.rs
  44. 2
      boa_engine/src/vm/opcode/push/literal.rs
  45. 1
      boa_engine/src/vm/opcode/push/mod.rs
  46. 2
      boa_engine/src/vm/opcode/push/numbers.rs
  47. 1
      boa_engine/src/vm/opcode/push/object.rs
  48. 1
      boa_engine/src/vm/opcode/require/mod.rs
  49. 1
      boa_engine/src/vm/opcode/rest_parameter/mod.rs
  50. 1
      boa_engine/src/vm/opcode/set/class_prototype.rs
  51. 1
      boa_engine/src/vm/opcode/set/home_object.rs
  52. 3
      boa_engine/src/vm/opcode/set/name.rs
  53. 5
      boa_engine/src/vm/opcode/set/private.rs
  54. 7
      boa_engine/src/vm/opcode/set/property.rs
  55. 1
      boa_engine/src/vm/opcode/set/prototype.rs
  56. 3
      boa_engine/src/vm/opcode/swap/mod.rs
  57. 2
      boa_engine/src/vm/opcode/switch/mod.rs
  58. 2
      boa_engine/src/vm/opcode/templates/mod.rs
  59. 2
      boa_engine/src/vm/opcode/to/mod.rs
  60. 2
      boa_engine/src/vm/opcode/unary_ops/decrement.rs
  61. 2
      boa_engine/src/vm/opcode/unary_ops/increment.rs
  62. 1
      boa_engine/src/vm/opcode/unary_ops/logical.rs
  63. 4
      boa_engine/src/vm/opcode/unary_ops/mod.rs
  64. 1
      boa_engine/src/vm/opcode/unary_ops/void.rs
  65. 2
      boa_engine/src/vm/opcode/value/mod.rs

52
boa_engine/src/script.rs

@ -146,6 +146,52 @@ impl Script {
pub fn evaluate(&self, context: &mut Context<'_>) -> JsResult<JsValue> { pub fn evaluate(&self, context: &mut Context<'_>) -> JsResult<JsValue> {
let _timer = Profiler::global().start_event("Execution", "Main"); let _timer = Profiler::global().start_event("Execution", "Main");
self.prepare_run(context)?;
let record = context.run();
context.vm.pop_frame();
context.clear_kept_objects();
record.consume()
}
/// Evaluates this script and returns its result, periodically yielding to the executor
/// in order to avoid blocking the current thread.
///
/// This uses an implementation defined amount of "clock cycles" that need to pass before
/// execution is suspended. See [`Script::evaluate_async_with_budget`] if you want to also
/// customize this parameter.
#[allow(clippy::future_not_send)]
pub async fn evaluate_async(&self, context: &mut Context<'_>) -> JsResult<JsValue> {
self.evaluate_async_with_budget(context, 256).await
}
/// Evaluates this script and returns its result, yielding to the executor each time `budget`
/// number of "clock cycles" pass.
///
/// Note that "clock cycle" is in quotation marks because we can't determine exactly how many
/// CPU clock cycles a VM instruction will take, but all instructions have a "cost" associated
/// with them that depends on their individual complexity. We'd recommend benchmarking with
/// different budget sizes in order to find the ideal yielding time for your application.
#[allow(clippy::future_not_send)]
pub async fn evaluate_async_with_budget(
&self,
context: &mut Context<'_>,
budget: u32,
) -> JsResult<JsValue> {
let _timer = Profiler::global().start_event("Async Execution", "Main");
self.prepare_run(context)?;
let record = context.run_async_with_budget(budget).await;
context.vm.pop_frame();
context.clear_kept_objects();
record.consume()
}
fn prepare_run(&self, context: &mut Context<'_>) -> JsResult<()> {
let codeblock = self.codeblock(context)?; let codeblock = self.codeblock(context)?;
let env_fp = context.vm.environments.len() as u32; let env_fp = context.vm.environments.len() as u32;
@ -165,11 +211,7 @@ impl Script {
// TODO: Here should be https://tc39.es/ecma262/#sec-globaldeclarationinstantiation // TODO: Here should be https://tc39.es/ecma262/#sec-globaldeclarationinstantiation
self.realm().resize_global_env(); self.realm().resize_global_env();
let record = context.run();
context.vm.pop_frame();
context.clear_kept_objects(); Ok(())
record.consume()
} }
} }

285
boa_engine/src/vm/mod.rs

@ -11,7 +11,7 @@ use crate::{
use boa_gc::{custom_trace, Finalize, Trace}; use boa_gc::{custom_trace, Finalize, Trace};
use boa_profiler::Profiler; use boa_profiler::Profiler;
use std::mem::size_of; use std::{future::Future, mem::size_of, ops::ControlFlow, pin::Pin, task};
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
use boa_interner::ToInternedString; use boa_interner::ToInternedString;
@ -292,7 +292,10 @@ impl Context<'_> {
); );
} }
fn trace_execute_instruction(&mut self) -> JsResult<CompletionType> { fn trace_execute_instruction<F>(&mut self, f: F) -> JsResult<CompletionType>
where
F: FnOnce(Opcode, &mut Context<'_>) -> JsResult<CompletionType>,
{
let bytecodes = &self.vm.frame().code_block.bytecode; let bytecodes = &self.vm.frame().code_block.bytecode;
let pc = self.vm.frame().pc as usize; let pc = self.vm.frame().pc as usize;
let (_, varying_operand_kind, instruction) = InstructionIterator::with_pc(bytecodes, pc) let (_, varying_operand_kind, instruction) = InstructionIterator::with_pc(bytecodes, pc)
@ -322,7 +325,7 @@ impl Context<'_> {
} }
let instant = Instant::now(); let instant = Instant::now();
let result = self.execute_instruction(); let result = self.execute_instruction(f);
let duration = instant.elapsed(); let duration = instant.elapsed();
let fp = self.vm.frames.last().map(|frame| frame.fp as usize); let fp = self.vm.frames.last().map(|frame| frame.fp as usize);
@ -370,7 +373,10 @@ impl Context<'_> {
} }
impl Context<'_> { impl Context<'_> {
fn execute_instruction(&mut self) -> JsResult<CompletionType> { fn execute_instruction<F>(&mut self, f: F) -> JsResult<CompletionType>
where
F: FnOnce(Opcode, &mut Context<'_>) -> 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");
@ -384,138 +390,178 @@ impl Context<'_> {
let _timer = Profiler::global().start_event(opcode.as_instruction_str(), "vm"); let _timer = Profiler::global().start_event(opcode.as_instruction_str(), "vm");
opcode.execute(self) f(opcode, self)
} }
pub(crate) fn run(&mut self) -> CompletionRecord { fn execute_one<F>(&mut self, f: F) -> ControlFlow<CompletionRecord>
let _timer = Profiler::global().start_event("run", "vm"); where
F: FnOnce(Opcode, &mut Context<'_>) -> JsResult<CompletionType>,
#[cfg(feature = "trace")] {
if self.vm.trace { #[cfg(feature = "fuzz")]
self.trace_call_frame(); {
if self.instructions_remaining == 0 {
return ControlFlow::Break(CompletionRecord::Throw(JsError::from_native(
JsNativeError::no_instructions_remain(),
)));
}
self.instructions_remaining -= 1;
} }
'instruction: loop { #[cfg(feature = "trace")]
#[cfg(feature = "fuzz")] let result = if self.vm.trace || self.vm.frame().code_block.traceable() {
{ self.trace_execute_instruction(f)
if self.instructions_remaining == 0 { } else {
return CompletionRecord::Throw(JsError::from_native( self.execute_instruction(f)
JsNativeError::no_instructions_remain(), };
));
}
self.instructions_remaining -= 1;
}
#[cfg(feature = "trace")] #[cfg(not(feature = "trace"))]
let result = if self.vm.trace || self.vm.frame().code_block.traceable() { let result = self.execute_instruction(f);
self.trace_execute_instruction()
} else { let result = match result {
self.execute_instruction() Ok(result) => result,
}; Err(err) => {
// If we hit the execution step limit, bubble up the error to the
#[cfg(not(feature = "trace"))] // (Rust) caller instead of trying to handle as an exception.
let result = self.execute_instruction(); if !err.is_catchable() {
let mut fp = self.vm.stack.len();
let result = match result { let mut env_fp = self.vm.environments.len();
Ok(result) => result, while let Some(frame) = self.vm.frames.last() {
Err(err) => { if frame.exit_early() {
// If we hit the execution step limit, bubble up the error to the break;
// (Rust) caller instead of trying to handle as an exception.
if !err.is_catchable() {
let mut fp = self.vm.stack.len();
let mut env_fp = self.vm.environments.len();
while let Some(frame) = self.vm.frames.last() {
if frame.exit_early() {
break;
}
fp = frame.fp as usize;
env_fp = frame.env_fp as usize;
self.vm.pop_frame();
} }
self.vm.environments.truncate(env_fp);
self.vm.stack.truncate(fp);
return CompletionRecord::Throw(err);
}
// Note: -1 because we increment after fetching the opcode. fp = frame.fp as usize;
let pc = self.vm.frame().pc.saturating_sub(1); env_fp = frame.env_fp as usize;
if self.vm.handle_exception_at(pc) { self.vm.pop_frame();
self.vm.pending_exception = Some(err);
continue;
} }
self.vm.environments.truncate(env_fp);
self.vm.stack.truncate(fp);
return ControlFlow::Break(CompletionRecord::Throw(err));
}
// Inject realm before crossing the function boundry // Note: -1 because we increment after fetching the opcode.
let err = err.inject_realm(self.realm().clone()); let pc = self.vm.frame().pc.saturating_sub(1);
if self.vm.handle_exception_at(pc) {
self.vm.pending_exception = Some(err); self.vm.pending_exception = Some(err);
CompletionType::Throw return ControlFlow::Continue(());
} }
};
match result { // Inject realm before crossing the function boundry
CompletionType::Normal => {} let err = err.inject_realm(self.realm().clone());
CompletionType::Return => {
self.vm.stack.truncate(self.vm.frame().fp as usize);
let result = self.vm.take_return_value(); self.vm.pending_exception = Some(err);
if self.vm.frame().exit_early() { CompletionType::Throw
return CompletionRecord::Normal(result); }
} };
self.vm.push(result); match result {
self.vm.pop_frame(); CompletionType::Normal => {}
CompletionType::Return => {
self.vm.stack.truncate(self.vm.frame().fp as usize);
let result = self.vm.take_return_value();
if self.vm.frame().exit_early() {
return ControlFlow::Break(CompletionRecord::Normal(result));
}
self.vm.push(result);
self.vm.pop_frame();
}
CompletionType::Throw => {
let mut fp = self.vm.frame().fp;
let mut env_fp = self.vm.frame().env_fp;
if self.vm.frame().exit_early() {
self.vm.environments.truncate(env_fp as usize);
self.vm.stack.truncate(fp as usize);
return ControlFlow::Break(CompletionRecord::Throw(
self.vm
.pending_exception
.take()
.expect("Err must exist for a CompletionType::Throw"),
));
} }
CompletionType::Throw => {
let mut fp = self.vm.frame().fp; self.vm.pop_frame();
let mut env_fp = self.vm.frame().env_fp;
if self.vm.frame().exit_early() { while let Some(frame) = self.vm.frames.last_mut() {
self.vm.environments.truncate(env_fp as usize); fp = frame.fp;
self.vm.stack.truncate(fp as usize); env_fp = frame.fp;
return CompletionRecord::Throw( let pc = frame.pc;
let exit_early = frame.exit_early();
if self.vm.handle_exception_at(pc) {
return ControlFlow::Continue(());
}
if exit_early {
return ControlFlow::Break(CompletionRecord::Throw(
self.vm self.vm
.pending_exception .pending_exception
.take() .take()
.expect("Err must exist for a CompletionType::Throw"), .expect("Err must exist for a CompletionType::Throw"),
); ));
} }
self.vm.pop_frame(); self.vm.pop_frame();
}
self.vm.environments.truncate(env_fp as usize);
self.vm.stack.truncate(fp as usize);
}
// Early return immediately.
CompletionType::Yield => {
let result = self.vm.take_return_value();
if self.vm.frame().exit_early() {
return ControlFlow::Break(CompletionRecord::Return(result));
}
while let Some(frame) = self.vm.frames.last_mut() { self.vm.push(result);
fp = frame.fp; self.vm.pop_frame();
env_fp = frame.fp; }
let pc = frame.pc; }
let exit_early = frame.exit_early();
if self.vm.handle_exception_at(pc) { ControlFlow::Continue(())
continue 'instruction; }
}
if exit_early { /// Runs the current frame to completion, yielding to the caller each time `budget`
return CompletionRecord::Throw( /// "clock cycles" have passed.
self.vm #[allow(clippy::future_not_send)]
.pending_exception pub(crate) async fn run_async_with_budget(&mut self, budget: u32) -> CompletionRecord {
.take() let _timer = Profiler::global().start_event("run_async_with_budget", "vm");
.expect("Err must exist for a CompletionType::Throw"),
);
}
self.vm.pop_frame(); #[cfg(feature = "trace")]
} if self.vm.trace {
self.vm.environments.truncate(env_fp as usize); self.trace_call_frame();
self.vm.stack.truncate(fp as usize); }
}
// Early return immediately.
CompletionType::Yield => {
let result = self.vm.take_return_value();
if self.vm.frame().exit_early() {
return CompletionRecord::Return(result);
}
self.vm.push(result); let mut runtime_budget: u32 = budget;
self.vm.pop_frame();
} loop {
match self.execute_one(|opcode, context| {
opcode.spend_budget_and_execute(context, &mut runtime_budget)
}) {
ControlFlow::Continue(()) => {}
ControlFlow::Break(record) => return record,
}
if runtime_budget == 0 {
runtime_budget = budget;
yield_now().await;
}
}
}
pub(crate) fn run(&mut self) -> CompletionRecord {
let _timer = Profiler::global().start_event("run", "vm");
#[cfg(feature = "trace")]
if self.vm.trace {
self.trace_call_frame();
}
loop {
match self.execute_one(Opcode::execute) {
ControlFlow::Continue(()) => {}
ControlFlow::Break(value) => return value,
} }
} }
} }
@ -538,3 +584,24 @@ impl Context<'_> {
Ok(()) Ok(())
} }
} }
/// Yields once to the executor.
fn yield_now() -> impl Future<Output = ()> {
struct YieldNow(bool);
impl Future for YieldNow {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
if self.0 {
task::Poll::Ready(())
} else {
self.0 = true;
cx.waker().wake_by_ref();
task::Poll::Pending
}
}
}
YieldNow(false)
}

3
boa_engine/src/vm/opcode/await/mod.rs

@ -18,6 +18,7 @@ pub(crate) struct Await;
impl Operation for Await { impl Operation for Await {
const NAME: &'static str = "Await"; const NAME: &'static str = "Await";
const INSTRUCTION: &'static str = "INST - Await"; const INSTRUCTION: &'static str = "INST - Await";
const COST: u8 = 5;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -150,6 +151,7 @@ pub(crate) struct CreatePromiseCapability;
impl Operation for CreatePromiseCapability { impl Operation for CreatePromiseCapability {
const NAME: &'static str = "CreatePromiseCapability"; const NAME: &'static str = "CreatePromiseCapability";
const INSTRUCTION: &'static str = "INST - CreatePromiseCapability"; const INSTRUCTION: &'static str = "INST - CreatePromiseCapability";
const COST: u8 = 8;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
if context.vm.frame().promise_capability.is_some() { if context.vm.frame().promise_capability.is_some() {
@ -177,6 +179,7 @@ pub(crate) struct CompletePromiseCapability;
impl Operation for CompletePromiseCapability { impl Operation for CompletePromiseCapability {
const NAME: &'static str = "CompletePromiseCapability"; const NAME: &'static str = "CompletePromiseCapability";
const INSTRUCTION: &'static str = "INST - CompletePromiseCapability"; const INSTRUCTION: &'static str = "INST - CompletePromiseCapability";
const COST: u8 = 8;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
// 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.

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

@ -13,6 +13,7 @@ pub(crate) struct LogicalAnd;
impl Operation for LogicalAnd { impl Operation for LogicalAnd {
const NAME: &'static str = "LogicalAnd"; const NAME: &'static str = "LogicalAnd";
const INSTRUCTION: &'static str = "INST - LogicalAnd"; const INSTRUCTION: &'static str = "INST - LogicalAnd";
const COST: u8 = 1;
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>();
@ -35,6 +36,7 @@ pub(crate) struct LogicalOr;
impl Operation for LogicalOr { impl Operation for LogicalOr {
const NAME: &'static str = "LogicalOr"; const NAME: &'static str = "LogicalOr";
const INSTRUCTION: &'static str = "INST - LogicalOr"; const INSTRUCTION: &'static str = "INST - LogicalOr";
const COST: u8 = 1;
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>();
@ -57,6 +59,7 @@ pub(crate) struct Coalesce;
impl Operation for Coalesce { impl Operation for Coalesce {
const NAME: &'static str = "Coalesce"; const NAME: &'static str = "Coalesce";
const INSTRUCTION: &'static str = "INST - Coalesce"; const INSTRUCTION: &'static str = "INST - Coalesce";
const COST: u8 = 1;
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>();

1
boa_engine/src/vm/opcode/binary_ops/macro_defined.rs

@ -15,6 +15,7 @@ macro_rules! implement_bin_ops {
impl Operation for $name { impl Operation for $name {
const NAME: &'static str = stringify!($name); const NAME: &'static str = stringify!($name);
const INSTRUCTION: &'static str = stringify!("INST - " + $name); const INSTRUCTION: &'static str = stringify!("INST - " + $name);
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let rhs = context.vm.pop(); let rhs = context.vm.pop();

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

@ -20,6 +20,7 @@ pub(crate) struct NotEq;
impl Operation for NotEq { impl Operation for NotEq {
const NAME: &'static str = "NotEq"; const NAME: &'static str = "NotEq";
const INSTRUCTION: &'static str = "INST - NotEq"; const INSTRUCTION: &'static str = "INST - NotEq";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let rhs = context.vm.pop(); let rhs = context.vm.pop();
@ -40,6 +41,7 @@ pub(crate) struct StrictEq;
impl Operation for StrictEq { impl Operation for StrictEq {
const NAME: &'static str = "StrictEq"; const NAME: &'static str = "StrictEq";
const INSTRUCTION: &'static str = "INST - StrictEq"; const INSTRUCTION: &'static str = "INST - StrictEq";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let rhs = context.vm.pop(); let rhs = context.vm.pop();
@ -59,6 +61,7 @@ pub(crate) struct StrictNotEq;
impl Operation for StrictNotEq { impl Operation for StrictNotEq {
const NAME: &'static str = "StrictNotEq"; const NAME: &'static str = "StrictNotEq";
const INSTRUCTION: &'static str = "INST - StrictNotEq"; const INSTRUCTION: &'static str = "INST - StrictNotEq";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let rhs = context.vm.pop(); let rhs = context.vm.pop();
@ -78,6 +81,7 @@ pub(crate) struct In;
impl Operation for In { impl Operation for In {
const NAME: &'static str = "In"; const NAME: &'static str = "In";
const INSTRUCTION: &'static str = "INST - In"; const INSTRUCTION: &'static str = "INST - In";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let rhs = context.vm.pop(); let rhs = context.vm.pop();
@ -137,6 +141,7 @@ impl InPrivate {
impl Operation for InPrivate { impl Operation for InPrivate {
const NAME: &'static str = "InPrivate"; const NAME: &'static str = "InPrivate";
const INSTRUCTION: &'static str = "INST - InPrivate"; const INSTRUCTION: &'static str = "INST - InPrivate";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -164,6 +169,7 @@ pub(crate) struct InstanceOf;
impl Operation for InstanceOf { impl Operation for InstanceOf {
const NAME: &'static str = "InstanceOf"; const NAME: &'static str = "InstanceOf";
const INSTRUCTION: &'static str = "INST - InstanceOf"; const INSTRUCTION: &'static str = "INST - InstanceOf";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let target = context.vm.pop(); let target = context.vm.pop();

9
boa_engine/src/vm/opcode/call/mod.rs

@ -63,6 +63,9 @@ impl CallEval {
impl Operation for CallEval { impl Operation for CallEval {
const NAME: &'static str = "CallEval"; const NAME: &'static str = "CallEval";
const INSTRUCTION: &'static str = "INST - CallEval"; const INSTRUCTION: &'static str = "INST - CallEval";
// TODO: Calls will require a big refactor in order to track
// the cost of the call.
const COST: u8 = 5;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let argument_count = context.vm.read::<u8>(); let argument_count = context.vm.read::<u8>();
@ -90,6 +93,9 @@ pub(crate) struct CallEvalSpread;
impl Operation for CallEvalSpread { impl Operation for CallEvalSpread {
const NAME: &'static str = "CallEvalSpread"; const NAME: &'static str = "CallEvalSpread";
const INSTRUCTION: &'static str = "INST - CallEvalSpread"; const INSTRUCTION: &'static str = "INST - CallEvalSpread";
// TODO: Calls will require a big refactor in order to track
// the cost of the call.
const COST: u8 = 5;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
// Get the arguments that are stored as an array object on the stack. // Get the arguments that are stored as an array object on the stack.
@ -176,6 +182,7 @@ impl Call {
impl Operation for Call { impl Operation for Call {
const NAME: &'static str = "Call"; const NAME: &'static str = "Call";
const INSTRUCTION: &'static str = "INST - Call"; const INSTRUCTION: &'static str = "INST - Call";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let argument_count = context.vm.read::<u8>(); let argument_count = context.vm.read::<u8>();
@ -199,6 +206,7 @@ pub(crate) struct CallSpread;
impl Operation for CallSpread { impl Operation for CallSpread {
const NAME: &'static str = "CallSpread"; const NAME: &'static str = "CallSpread";
const INSTRUCTION: &'static str = "INST - CallSpread"; const INSTRUCTION: &'static str = "INST - CallSpread";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
// Get the arguments that are stored as an array object on the stack. // Get the arguments that are stored as an array object on the stack.
@ -240,6 +248,7 @@ pub(crate) struct ImportCall;
impl Operation for ImportCall { impl Operation for ImportCall {
const NAME: &'static str = "ImportCall"; const NAME: &'static str = "ImportCall";
const INSTRUCTION: &'static str = "INST - ImportCall"; const INSTRUCTION: &'static str = "INST - ImportCall";
const COST: u8 = 15;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
// Import Calls // Import Calls

1
boa_engine/src/vm/opcode/concat/mod.rs

@ -31,6 +31,7 @@ impl ConcatToString {
impl Operation for ConcatToString { impl Operation for ConcatToString {
const NAME: &'static str = "ConcatToString"; const NAME: &'static str = "ConcatToString";
const INSTRUCTION: &'static str = "INST - ConcatToString"; const INSTRUCTION: &'static str = "INST - ConcatToString";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value_count = context.vm.read::<u8>() as usize; let value_count = context.vm.read::<u8>() as usize;

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

@ -13,6 +13,7 @@ pub(crate) struct Jump;
impl Operation for Jump { impl Operation for Jump {
const NAME: &'static str = "Jump"; const NAME: &'static str = "Jump";
const INSTRUCTION: &'static str = "INST - Jump"; const INSTRUCTION: &'static str = "INST - Jump";
const COST: u8 = 1;
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>();
@ -31,6 +32,7 @@ pub(crate) struct JumpIfTrue;
impl Operation for JumpIfTrue { impl Operation for JumpIfTrue {
const NAME: &'static str = "JumpIfTrue"; const NAME: &'static str = "JumpIfTrue";
const INSTRUCTION: &'static str = "INST - JumpIfTrue"; const INSTRUCTION: &'static str = "INST - JumpIfTrue";
const COST: u8 = 1;
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>();
@ -51,6 +53,7 @@ pub(crate) struct JumpIfFalse;
impl Operation for JumpIfFalse { impl Operation for JumpIfFalse {
const NAME: &'static str = "JumpIfFalse"; const NAME: &'static str = "JumpIfFalse";
const INSTRUCTION: &'static str = "INST - JumpIfFalse"; const INSTRUCTION: &'static str = "INST - JumpIfFalse";
const COST: u8 = 1;
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>();
@ -71,6 +74,7 @@ pub(crate) struct JumpIfNotUndefined;
impl Operation for JumpIfNotUndefined { impl Operation for JumpIfNotUndefined {
const NAME: &'static str = "JumpIfNotUndefined"; const NAME: &'static str = "JumpIfNotUndefined";
const INSTRUCTION: &'static str = "INST - JumpIfNotUndefined"; const INSTRUCTION: &'static str = "INST - JumpIfNotUndefined";
const COST: u8 = 1;
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>();
@ -93,6 +97,7 @@ pub(crate) struct JumpIfNullOrUndefined;
impl Operation for JumpIfNullOrUndefined { impl Operation for JumpIfNullOrUndefined {
const NAME: &'static str = "JumpIfNullOrUndefined"; const NAME: &'static str = "JumpIfNullOrUndefined";
const INSTRUCTION: &'static str = "INST - JumpIfNullOrUndefined"; const INSTRUCTION: &'static str = "INST - JumpIfNullOrUndefined";
const COST: u8 = 1;
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>();
@ -116,6 +121,7 @@ pub(crate) struct JumpTable;
impl Operation for JumpTable { impl Operation for JumpTable {
const NAME: &'static str = "JumpTable"; const NAME: &'static str = "JumpTable";
const INSTRUCTION: &'static str = "INST - JumpTable"; const INSTRUCTION: &'static str = "INST - JumpTable";
const COST: u8 = 5;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let default = context.vm.read::<u32>(); let default = context.vm.read::<u32>();

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

@ -13,6 +13,7 @@ pub(crate) struct Return;
impl Operation for Return { impl Operation for Return {
const NAME: &'static str = "Return"; const NAME: &'static str = "Return";
const INSTRUCTION: &'static str = "INST - Return"; const INSTRUCTION: &'static str = "INST - Return";
const COST: u8 = 4;
fn execute(_context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(_context: &mut Context<'_>) -> JsResult<CompletionType> {
Ok(CompletionType::Return) Ok(CompletionType::Return)
@ -29,6 +30,7 @@ pub(crate) struct CheckReturn;
impl Operation for CheckReturn { impl Operation for CheckReturn {
const NAME: &'static str = "CheckReturn"; const NAME: &'static str = "CheckReturn";
const INSTRUCTION: &'static str = "INST - CheckReturn"; const INSTRUCTION: &'static str = "INST - CheckReturn";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
if !context.vm.frame().construct() { if !context.vm.frame().construct() {
@ -80,6 +82,7 @@ pub(crate) struct GetReturnValue;
impl Operation for GetReturnValue { impl Operation for GetReturnValue {
const NAME: &'static str = "GetReturnValue"; const NAME: &'static str = "GetReturnValue";
const INSTRUCTION: &'static str = "INST - GetReturnValue"; const INSTRUCTION: &'static str = "INST - GetReturnValue";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.get_return_value(); let value = context.vm.get_return_value();
@ -98,6 +101,7 @@ pub(crate) struct SetReturnValue;
impl Operation for SetReturnValue { impl Operation for SetReturnValue {
const NAME: &'static str = "SetReturnValue"; const NAME: &'static str = "SetReturnValue";
const INSTRUCTION: &'static str = "INST - SetReturnValue"; const INSTRUCTION: &'static str = "INST - SetReturnValue";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

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

@ -13,6 +13,7 @@ pub(crate) struct Throw;
impl Operation for Throw { impl Operation for Throw {
const NAME: &'static str = "Throw"; const NAME: &'static str = "Throw";
const INSTRUCTION: &'static str = "INST - Throw"; const INSTRUCTION: &'static str = "INST - Throw";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let error = JsError::from_opaque(context.vm.pop()); let error = JsError::from_opaque(context.vm.pop());
@ -38,6 +39,7 @@ pub(crate) struct ReThrow;
impl Operation for ReThrow { impl Operation for ReThrow {
const NAME: &'static str = "ReThrow"; const NAME: &'static str = "ReThrow";
const INSTRUCTION: &'static str = "INST - ReThrow"; const INSTRUCTION: &'static str = "INST - ReThrow";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
// Note: -1 because we increment after fetching the opcode. // Note: -1 because we increment after fetching the opcode.
@ -69,6 +71,7 @@ pub(crate) struct Exception;
impl Operation for Exception { impl Operation for Exception {
const NAME: &'static str = "Exception"; const NAME: &'static str = "Exception";
const INSTRUCTION: &'static str = "INST - Exception"; const INSTRUCTION: &'static str = "INST - Exception";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
if let Some(error) = context.vm.pending_exception.take() { if let Some(error) = context.vm.pending_exception.take() {
@ -96,6 +99,7 @@ pub(crate) struct MaybeException;
impl Operation for MaybeException { impl Operation for MaybeException {
const NAME: &'static str = "MaybeException"; const NAME: &'static str = "MaybeException";
const INSTRUCTION: &'static str = "INST - MaybeException"; const INSTRUCTION: &'static str = "INST - MaybeException";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
if let Some(error) = context.vm.pending_exception.take() { if let Some(error) = context.vm.pending_exception.take() {
@ -133,6 +137,7 @@ impl ThrowNewTypeError {
impl Operation for ThrowNewTypeError { impl Operation for ThrowNewTypeError {
const NAME: &'static str = "ThrowNewTypeError"; const NAME: &'static str = "ThrowNewTypeError";
const INSTRUCTION: &'static str = "INST - ThrowNewTypeError"; const INSTRUCTION: &'static str = "INST - ThrowNewTypeError";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;

1
boa_engine/src/vm/opcode/copy/mod.rs

@ -43,6 +43,7 @@ impl CopyDataProperties {
impl Operation for CopyDataProperties { impl Operation for CopyDataProperties {
const NAME: &'static str = "CopyDataProperties"; const NAME: &'static str = "CopyDataProperties";
const INSTRUCTION: &'static str = "INST - CopyDataProperties"; const INSTRUCTION: &'static str = "INST - CopyDataProperties";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let excluded_key_count = context.vm.read::<u8>() as usize; let excluded_key_count = context.vm.read::<u8>() as usize;

4
boa_engine/src/vm/opcode/define/class/getter.rs

@ -51,6 +51,7 @@ impl DefineClassStaticGetterByName {
impl Operation for DefineClassStaticGetterByName { impl Operation for DefineClassStaticGetterByName {
const NAME: &'static str = "DefineClassStaticGetterByName"; const NAME: &'static str = "DefineClassStaticGetterByName";
const INSTRUCTION: &'static str = "INST - DefineClassStaticGetterByName"; const INSTRUCTION: &'static str = "INST - DefineClassStaticGetterByName";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -114,6 +115,7 @@ impl DefineClassGetterByName {
impl Operation for DefineClassGetterByName { impl Operation for DefineClassGetterByName {
const NAME: &'static str = "DefineClassGetterByName"; const NAME: &'static str = "DefineClassGetterByName";
const INSTRUCTION: &'static str = "INST - DefineClassGetterByName"; const INSTRUCTION: &'static str = "INST - DefineClassGetterByName";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -141,6 +143,7 @@ pub(crate) struct DefineClassStaticGetterByValue;
impl Operation for DefineClassStaticGetterByValue { impl Operation for DefineClassStaticGetterByValue {
const NAME: &'static str = "DefineClassStaticGetterByValue"; const NAME: &'static str = "DefineClassStaticGetterByValue";
const INSTRUCTION: &'static str = "INST - DefineClassStaticGetterByValue"; const INSTRUCTION: &'static str = "INST - DefineClassStaticGetterByValue";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let function = context.vm.pop(); let function = context.vm.pop();
@ -190,6 +193,7 @@ pub(crate) struct DefineClassGetterByValue;
impl Operation for DefineClassGetterByValue { impl Operation for DefineClassGetterByValue {
const NAME: &'static str = "DefineClassGetterByValue"; const NAME: &'static str = "DefineClassGetterByValue";
const INSTRUCTION: &'static str = "INST - DefineClassGetterByValue"; const INSTRUCTION: &'static str = "INST - DefineClassGetterByValue";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let function = context.vm.pop(); let function = context.vm.pop();

4
boa_engine/src/vm/opcode/define/class/method.rs

@ -47,6 +47,7 @@ impl DefineClassStaticMethodByName {
impl Operation for DefineClassStaticMethodByName { impl Operation for DefineClassStaticMethodByName {
const NAME: &'static str = "DefineClassStaticMethodByName"; const NAME: &'static str = "DefineClassStaticMethodByName";
const INSTRUCTION: &'static str = "INST - DefineClassStaticMethodByName"; const INSTRUCTION: &'static str = "INST - DefineClassStaticMethodByName";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -106,6 +107,7 @@ impl DefineClassMethodByName {
impl Operation for DefineClassMethodByName { impl Operation for DefineClassMethodByName {
const NAME: &'static str = "DefineClassMethodByName"; const NAME: &'static str = "DefineClassMethodByName";
const INSTRUCTION: &'static str = "INST - DefineClassMethodByName"; const INSTRUCTION: &'static str = "INST - DefineClassMethodByName";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -133,6 +135,7 @@ pub(crate) struct DefineClassStaticMethodByValue;
impl Operation for DefineClassStaticMethodByValue { impl Operation for DefineClassStaticMethodByValue {
const NAME: &'static str = "DefineClassStaticMethodByValue"; const NAME: &'static str = "DefineClassStaticMethodByValue";
const INSTRUCTION: &'static str = "INST - DefineClassStaticMethodByValue"; const INSTRUCTION: &'static str = "INST - DefineClassStaticMethodByValue";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let function = context.vm.pop(); let function = context.vm.pop();
@ -178,6 +181,7 @@ pub(crate) struct DefineClassMethodByValue;
impl Operation for DefineClassMethodByValue { impl Operation for DefineClassMethodByValue {
const NAME: &'static str = "DefineClassMethodByValue"; const NAME: &'static str = "DefineClassMethodByValue";
const INSTRUCTION: &'static str = "INST - DefineClassMethodByValue"; const INSTRUCTION: &'static str = "INST - DefineClassMethodByValue";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let function = context.vm.pop(); let function = context.vm.pop();

4
boa_engine/src/vm/opcode/define/class/setter.rs

@ -52,6 +52,7 @@ impl DefineClassStaticSetterByName {
impl Operation for DefineClassStaticSetterByName { impl Operation for DefineClassStaticSetterByName {
const NAME: &'static str = "DefineClassStaticSetterByName"; const NAME: &'static str = "DefineClassStaticSetterByName";
const INSTRUCTION: &'static str = "INST - DefineClassStaticSetterByName"; const INSTRUCTION: &'static str = "INST - DefineClassStaticSetterByName";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -117,6 +118,7 @@ impl DefineClassSetterByName {
impl Operation for DefineClassSetterByName { impl Operation for DefineClassSetterByName {
const NAME: &'static str = "DefineClassSetterByName"; const NAME: &'static str = "DefineClassSetterByName";
const INSTRUCTION: &'static str = "INST - DefineClassSetterByName"; const INSTRUCTION: &'static str = "INST - DefineClassSetterByName";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -144,6 +146,7 @@ pub(crate) struct DefineClassStaticSetterByValue;
impl Operation for DefineClassStaticSetterByValue { impl Operation for DefineClassStaticSetterByValue {
const NAME: &'static str = "DefineClassStaticSetterByValue"; const NAME: &'static str = "DefineClassStaticSetterByValue";
const INSTRUCTION: &'static str = "INST - DefineClassStaticSetterByValue"; const INSTRUCTION: &'static str = "INST - DefineClassStaticSetterByValue";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let function = context.vm.pop(); let function = context.vm.pop();
@ -195,6 +198,7 @@ pub(crate) struct DefineClassSetterByValue;
impl Operation for DefineClassSetterByValue { impl Operation for DefineClassSetterByValue {
const NAME: &'static str = "DefineClassSetterByValue"; const NAME: &'static str = "DefineClassSetterByValue";
const INSTRUCTION: &'static str = "INST - DefineClassSetterByValue"; const INSTRUCTION: &'static str = "INST - DefineClassSetterByValue";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let function = context.vm.pop(); let function = context.vm.pop();

3
boa_engine/src/vm/opcode/define/mod.rs

@ -38,6 +38,7 @@ impl DefVar {
impl Operation for DefVar { impl Operation for DefVar {
const NAME: &'static str = "DefVar"; const NAME: &'static str = "DefVar";
const INSTRUCTION: &'static str = "INST - DefVar"; const INSTRUCTION: &'static str = "INST - DefVar";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();
@ -80,6 +81,7 @@ impl DefInitVar {
impl Operation for DefInitVar { impl Operation for DefInitVar {
const NAME: &'static str = "DefInitVar"; const NAME: &'static str = "DefInitVar";
const INSTRUCTION: &'static str = "INST - DefInitVar"; const INSTRUCTION: &'static str = "INST - DefInitVar";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();
@ -122,6 +124,7 @@ impl PutLexicalValue {
impl Operation for PutLexicalValue { impl Operation for PutLexicalValue {
const NAME: &'static str = "PutLexicalValue"; const NAME: &'static str = "PutLexicalValue";
const INSTRUCTION: &'static str = "INST - PutLexicalValue"; const INSTRUCTION: &'static str = "INST - PutLexicalValue";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();

2
boa_engine/src/vm/opcode/define/own_property.rs

@ -38,6 +38,7 @@ impl DefineOwnPropertyByName {
impl Operation for DefineOwnPropertyByName { impl Operation for DefineOwnPropertyByName {
const NAME: &'static str = "DefineOwnPropertyByName"; const NAME: &'static str = "DefineOwnPropertyByName";
const INSTRUCTION: &'static str = "INST - DefineOwnPropertyByName"; const INSTRUCTION: &'static str = "INST - DefineOwnPropertyByName";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -65,6 +66,7 @@ pub(crate) struct DefineOwnPropertyByValue;
impl Operation for DefineOwnPropertyByValue { impl Operation for DefineOwnPropertyByValue {
const NAME: &'static str = "DefineOwnPropertyByValue"; const NAME: &'static str = "DefineOwnPropertyByValue";
const INSTRUCTION: &'static str = "INST - DefineOwnPropertyByValue"; const INSTRUCTION: &'static str = "INST - DefineOwnPropertyByValue";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

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

@ -30,6 +30,7 @@ impl DeletePropertyByName {
impl Operation for DeletePropertyByName { impl Operation for DeletePropertyByName {
const NAME: &'static str = "DeletePropertyByName"; const NAME: &'static str = "DeletePropertyByName";
const INSTRUCTION: &'static str = "INST - DeletePropertyByName"; const INSTRUCTION: &'static str = "INST - DeletePropertyByName";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -57,6 +58,7 @@ pub(crate) struct DeletePropertyByValue;
impl Operation for DeletePropertyByValue { impl Operation for DeletePropertyByValue {
const NAME: &'static str = "DeletePropertyByValue"; const NAME: &'static str = "DeletePropertyByValue";
const INSTRUCTION: &'static str = "INST - DeletePropertyByValue"; const INSTRUCTION: &'static str = "INST - DeletePropertyByValue";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let key_value = context.vm.pop(); let key_value = context.vm.pop();
@ -97,6 +99,7 @@ impl DeleteName {
impl Operation for DeleteName { impl Operation for DeleteName {
const NAME: &'static str = "DeleteName"; const NAME: &'static str = "DeleteName";
const INSTRUCTION: &'static str = "INST - DeleteName"; const INSTRUCTION: &'static str = "INST - DeleteName";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();
@ -124,6 +127,7 @@ pub(crate) struct DeleteSuperThrow;
impl Operation for DeleteSuperThrow { impl Operation for DeleteSuperThrow {
const NAME: &'static str = "DeleteSuperThrow"; const NAME: &'static str = "DeleteSuperThrow";
const INSTRUCTION: &'static str = "INST - DeleteSuperThrow"; const INSTRUCTION: &'static str = "INST - DeleteSuperThrow";
const COST: u8 = 2;
fn execute(_: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(_: &mut Context<'_>) -> JsResult<CompletionType> {
Err(JsNativeError::reference() Err(JsNativeError::reference()

1
boa_engine/src/vm/opcode/dup/mod.rs

@ -13,6 +13,7 @@ pub(crate) struct Dup;
impl Operation for Dup { impl Operation for Dup {
const NAME: &'static str = "Dup"; const NAME: &'static str = "Dup";
const INSTRUCTION: &'static str = "INST - Dup"; const INSTRUCTION: &'static str = "INST - Dup";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

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

@ -14,6 +14,7 @@ pub(crate) struct This;
impl Operation for This { impl Operation for This {
const NAME: &'static str = "This"; const NAME: &'static str = "This";
const INSTRUCTION: &'static str = "INST - This"; const INSTRUCTION: &'static str = "INST - This";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let this = context.vm.environments.get_this_binding()?; let this = context.vm.environments.get_this_binding()?;
@ -32,6 +33,7 @@ pub(crate) struct Super;
impl Operation for Super { impl Operation for Super {
const NAME: &'static str = "Super"; const NAME: &'static str = "Super";
const INSTRUCTION: &'static str = "INST - Super"; const INSTRUCTION: &'static str = "INST - Super";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let home_object = { let home_object = {
@ -72,6 +74,7 @@ pub(crate) struct SuperCallPrepare;
impl Operation for SuperCallPrepare { impl Operation for SuperCallPrepare {
const NAME: &'static str = "SuperCallPrepare"; const NAME: &'static str = "SuperCallPrepare";
const INSTRUCTION: &'static str = "INST - SuperCallPrepare"; const INSTRUCTION: &'static str = "INST - SuperCallPrepare";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let this_env = context let this_env = context
@ -134,6 +137,7 @@ impl SuperCall {
impl Operation for SuperCall { impl Operation for SuperCall {
const NAME: &'static str = "SuperCall"; const NAME: &'static str = "SuperCall";
const INSTRUCTION: &'static str = "INST - SuperCall"; const INSTRUCTION: &'static str = "INST - SuperCall";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value_count = context.vm.read::<u8>() as usize; let value_count = context.vm.read::<u8>() as usize;
@ -161,6 +165,7 @@ pub(crate) struct SuperCallSpread;
impl Operation for SuperCallSpread { impl Operation for SuperCallSpread {
const NAME: &'static str = "SuperCallSpread"; const NAME: &'static str = "SuperCallSpread";
const INSTRUCTION: &'static str = "INST - SuperCallSpread"; const INSTRUCTION: &'static str = "INST - SuperCallSpread";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
// Get the arguments that are stored as an array object on the stack. // Get the arguments that are stored as an array object on the stack.
@ -219,6 +224,7 @@ pub(crate) struct SuperCallDerived;
impl Operation for SuperCallDerived { impl Operation for SuperCallDerived {
const NAME: &'static str = "SuperCallDerived"; const NAME: &'static str = "SuperCallDerived";
const INSTRUCTION: &'static str = "INST - SuperCallDerived"; const INSTRUCTION: &'static str = "INST - SuperCallDerived";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let argument_count = context.vm.frame().argument_count as usize; let argument_count = context.vm.frame().argument_count as usize;
@ -271,6 +277,7 @@ pub(crate) struct BindThisValue;
impl Operation for BindThisValue { impl Operation for BindThisValue {
const NAME: &'static str = "BindThisValue"; const NAME: &'static str = "BindThisValue";
const INSTRUCTION: &'static str = "INST - BindThisValue"; const INSTRUCTION: &'static str = "INST - BindThisValue";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
// Taken from `SuperCall : super Arguments` steps 7-12. // Taken from `SuperCall : super Arguments` steps 7-12.

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

@ -32,6 +32,7 @@ pub(crate) struct Generator;
impl Operation for Generator { impl Operation for Generator {
const NAME: &'static str = "Generator"; const NAME: &'static str = "Generator";
const INSTRUCTION: &'static str = "INST - Generator"; const INSTRUCTION: &'static str = "INST - Generator";
const COST: u8 = 8;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let r#async = context.vm.read::<u8>() != 0; let r#async = context.vm.read::<u8>() != 0;
@ -128,6 +129,7 @@ pub(crate) struct AsyncGeneratorClose;
impl Operation for AsyncGeneratorClose { impl Operation for AsyncGeneratorClose {
const NAME: &'static str = "AsyncGeneratorClose"; const NAME: &'static str = "AsyncGeneratorClose";
const INSTRUCTION: &'static str = "INST - AsyncGeneratorClose"; const INSTRUCTION: &'static str = "INST - AsyncGeneratorClose";
const COST: u8 = 8;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
// Step 3.e-g in [AsyncGeneratorStart](https://tc39.es/ecma262/#sec-asyncgeneratorstart) // Step 3.e-g in [AsyncGeneratorStart](https://tc39.es/ecma262/#sec-asyncgeneratorstart)
@ -176,6 +178,7 @@ pub(crate) struct GeneratorNext;
impl Operation for GeneratorNext { impl Operation for GeneratorNext {
const NAME: &'static str = "GeneratorNext"; const NAME: &'static str = "GeneratorNext";
const INSTRUCTION: &'static str = "INST - GeneratorNext"; const INSTRUCTION: &'static str = "INST - GeneratorNext";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let generator_resume_kind = context.vm.pop().to_generator_resume_kind(); let generator_resume_kind = context.vm.pop().to_generator_resume_kind();
@ -202,6 +205,7 @@ pub(crate) struct JumpIfNotResumeKind;
impl Operation for JumpIfNotResumeKind { impl Operation for JumpIfNotResumeKind {
const NAME: &'static str = "JumpIfNotResumeKind"; const NAME: &'static str = "JumpIfNotResumeKind";
const INSTRUCTION: &'static str = "INST - JumpIfNotResumeKind"; const INSTRUCTION: &'static str = "INST - JumpIfNotResumeKind";
const COST: u8 = 1;
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>();
@ -228,6 +232,7 @@ pub(crate) struct GeneratorDelegateNext;
impl Operation for GeneratorDelegateNext { impl Operation for GeneratorDelegateNext {
const NAME: &'static str = "GeneratorDelegateNext"; const NAME: &'static str = "GeneratorDelegateNext";
const INSTRUCTION: &'static str = "INST - GeneratorDelegateNext"; const INSTRUCTION: &'static str = "INST - GeneratorDelegateNext";
const COST: u8 = 18;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let throw_method_undefined = context.vm.read::<u32>(); let throw_method_undefined = context.vm.read::<u32>();
@ -317,6 +322,7 @@ pub(crate) struct GeneratorDelegateResume;
impl Operation for GeneratorDelegateResume { impl Operation for GeneratorDelegateResume {
const NAME: &'static str = "GeneratorDelegateResume"; const NAME: &'static str = "GeneratorDelegateResume";
const INSTRUCTION: &'static str = "INST - GeneratorDelegateResume"; const INSTRUCTION: &'static str = "INST - GeneratorDelegateResume";
const COST: u8 = 7;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let return_gen = context.vm.read::<u32>(); let return_gen = context.vm.read::<u32>();

2
boa_engine/src/vm/opcode/generator/yield_stm.rs

@ -14,6 +14,7 @@ pub(crate) struct GeneratorYield;
impl Operation for GeneratorYield { impl Operation for GeneratorYield {
const NAME: &'static str = "GeneratorYield"; const NAME: &'static str = "GeneratorYield";
const INSTRUCTION: &'static str = "INST - GeneratorYield"; const INSTRUCTION: &'static str = "INST - GeneratorYield";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -32,6 +33,7 @@ pub(crate) struct AsyncGeneratorYield;
impl Operation for AsyncGeneratorYield { impl Operation for AsyncGeneratorYield {
const NAME: &'static str = "AsyncGeneratorYield"; const NAME: &'static str = "AsyncGeneratorYield";
const INSTRUCTION: &'static str = "INST - AsyncGeneratorYield"; const INSTRUCTION: &'static str = "INST - AsyncGeneratorYield";
const COST: u8 = 8;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

1
boa_engine/src/vm/opcode/get/argument.rs

@ -29,6 +29,7 @@ impl GetArgument {
impl Operation for GetArgument { impl Operation for GetArgument {
const NAME: &'static str = "GetArgument"; const NAME: &'static str = "GetArgument";
const INSTRUCTION: &'static str = "INST - GetArgument"; const INSTRUCTION: &'static str = "INST - GetArgument";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;

4
boa_engine/src/vm/opcode/get/function.rs

@ -23,6 +23,7 @@ impl GetArrowFunction {
impl Operation for GetArrowFunction { impl Operation for GetArrowFunction {
const NAME: &'static str = "GetArrowFunction"; const NAME: &'static str = "GetArrowFunction";
const INSTRUCTION: &'static str = "INST - GetArrowFunction"; const INSTRUCTION: &'static str = "INST - GetArrowFunction";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -60,6 +61,7 @@ impl GetAsyncArrowFunction {
impl Operation for GetAsyncArrowFunction { impl Operation for GetAsyncArrowFunction {
const NAME: &'static str = "GetAsyncArrowFunction"; const NAME: &'static str = "GetAsyncArrowFunction";
const INSTRUCTION: &'static str = "INST - GetAsyncArrowFunction"; const INSTRUCTION: &'static str = "INST - GetAsyncArrowFunction";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -101,6 +103,7 @@ impl GetFunction {
impl Operation for GetFunction { impl Operation for GetFunction {
const NAME: &'static str = "GetFunction"; const NAME: &'static str = "GetFunction";
const INSTRUCTION: &'static str = "INST - GetFunction"; const INSTRUCTION: &'static str = "INST - GetFunction";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -145,6 +148,7 @@ impl GetFunctionAsync {
impl Operation for GetFunctionAsync { impl Operation for GetFunctionAsync {
const NAME: &'static str = "GetFunctionAsync"; const NAME: &'static str = "GetFunctionAsync";
const INSTRUCTION: &'static str = "INST - GetFunctionAsync"; const INSTRUCTION: &'static str = "INST - GetFunctionAsync";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;

2
boa_engine/src/vm/opcode/get/generator.rs

@ -23,6 +23,7 @@ impl GetGenerator {
impl Operation for GetGenerator { impl Operation for GetGenerator {
const NAME: &'static str = "GetGenerator"; const NAME: &'static str = "GetGenerator";
const INSTRUCTION: &'static str = "INST - GetGenerator"; const INSTRUCTION: &'static str = "INST - GetGenerator";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -60,6 +61,7 @@ impl GetGeneratorAsync {
impl Operation for GetGeneratorAsync { impl Operation for GetGeneratorAsync {
const NAME: &'static str = "GetGeneratorAsync"; const NAME: &'static str = "GetGeneratorAsync";
const INSTRUCTION: &'static str = "INST - GetGeneratorAsync"; const INSTRUCTION: &'static str = "INST - GetGeneratorAsync";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;

4
boa_engine/src/vm/opcode/get/name.rs

@ -31,6 +31,7 @@ impl GetName {
impl Operation for GetName { impl Operation for GetName {
const NAME: &'static str = "GetName"; const NAME: &'static str = "GetName";
const INSTRUCTION: &'static str = "INST - GetName"; const INSTRUCTION: &'static str = "INST - GetName";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();
@ -69,6 +70,7 @@ impl GetLocator {
impl Operation for GetLocator { impl Operation for GetLocator {
const NAME: &'static str = "GetLocator"; const NAME: &'static str = "GetLocator";
const INSTRUCTION: &'static str = "INST - GetLocator"; const INSTRUCTION: &'static str = "INST - GetLocator";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();
@ -115,6 +117,7 @@ impl GetNameAndLocator {
impl Operation for GetNameAndLocator { impl Operation for GetNameAndLocator {
const NAME: &'static str = "GetNameAndLocator"; const NAME: &'static str = "GetNameAndLocator";
const INSTRUCTION: &'static str = "INST - GetNameAndLocator"; const INSTRUCTION: &'static str = "INST - GetNameAndLocator";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();
@ -169,6 +172,7 @@ impl GetNameOrUndefined {
impl Operation for GetNameOrUndefined { impl Operation for GetNameOrUndefined {
const NAME: &'static str = "GetNameOrUndefined"; const NAME: &'static str = "GetNameOrUndefined";
const INSTRUCTION: &'static str = "INST - GetNameOrUndefined"; const INSTRUCTION: &'static str = "INST - GetNameOrUndefined";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();

1
boa_engine/src/vm/opcode/get/private.rs

@ -31,6 +31,7 @@ impl GetPrivateField {
impl Operation for GetPrivateField { impl Operation for GetPrivateField {
const NAME: &'static str = "GetPrivateField"; const NAME: &'static str = "GetPrivateField";
const INSTRUCTION: &'static str = "INST - GetPrivateField"; const INSTRUCTION: &'static str = "INST - GetPrivateField";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;

3
boa_engine/src/vm/opcode/get/property.rs

@ -32,6 +32,7 @@ impl GetPropertyByName {
impl Operation for GetPropertyByName { impl Operation for GetPropertyByName {
const NAME: &'static str = "GetPropertyByName"; const NAME: &'static str = "GetPropertyByName";
const INSTRUCTION: &'static str = "INST - GetPropertyByName"; const INSTRUCTION: &'static str = "INST - GetPropertyByName";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();
@ -59,6 +60,7 @@ pub(crate) struct GetPropertyByValue;
impl Operation for GetPropertyByValue { impl Operation for GetPropertyByValue {
const NAME: &'static str = "GetPropertyByValue"; const NAME: &'static str = "GetPropertyByValue";
const INSTRUCTION: &'static str = "INST - GetPropertyByValue"; const INSTRUCTION: &'static str = "INST - GetPropertyByValue";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let key = context.vm.pop(); let key = context.vm.pop();
@ -105,6 +107,7 @@ pub(crate) struct GetPropertyByValuePush;
impl Operation for GetPropertyByValuePush { impl Operation for GetPropertyByValuePush {
const NAME: &'static str = "GetPropertyByValuePush"; const NAME: &'static str = "GetPropertyByValuePush";
const INSTRUCTION: &'static str = "INST - GetPropertyByValuePush"; const INSTRUCTION: &'static str = "INST - GetPropertyByValuePush";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let key = context.vm.pop(); let key = context.vm.pop();

1
boa_engine/src/vm/opcode/iteration/for_in.rs

@ -15,6 +15,7 @@ pub(crate) struct CreateForInIterator;
impl Operation for CreateForInIterator { impl Operation for CreateForInIterator {
const NAME: &'static str = "CreateForInIterator"; const NAME: &'static str = "CreateForInIterator";
const INSTRUCTION: &'static str = "INST - CreateForInIterator"; const INSTRUCTION: &'static str = "INST - CreateForInIterator";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let object = context.vm.pop(); let object = context.vm.pop();

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

@ -14,6 +14,7 @@ pub(crate) struct GetIterator;
impl Operation for GetIterator { impl Operation for GetIterator {
const NAME: &'static str = "GetIterator"; const NAME: &'static str = "GetIterator";
const INSTRUCTION: &'static str = "INST - GetIterator"; const INSTRUCTION: &'static str = "INST - GetIterator";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let object = context.vm.pop(); let object = context.vm.pop();
@ -33,6 +34,7 @@ pub(crate) struct GetAsyncIterator;
impl Operation for GetAsyncIterator { impl Operation for GetAsyncIterator {
const NAME: &'static str = "GetAsyncIterator"; const NAME: &'static str = "GetAsyncIterator";
const INSTRUCTION: &'static str = "INST - GetAsyncIterator"; const INSTRUCTION: &'static str = "INST - GetAsyncIterator";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let object = context.vm.pop(); let object = context.vm.pop();

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

@ -17,6 +17,7 @@ pub(crate) struct IteratorNext;
impl Operation for IteratorNext { impl Operation for IteratorNext {
const NAME: &'static str = "IteratorNext"; const NAME: &'static str = "IteratorNext";
const INSTRUCTION: &'static str = "INST - IteratorNext"; const INSTRUCTION: &'static str = "INST - IteratorNext";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let mut iterator = context let mut iterator = context
@ -44,6 +45,7 @@ pub(crate) struct IteratorNextWithoutPop;
impl Operation for IteratorNextWithoutPop { impl Operation for IteratorNextWithoutPop {
const NAME: &'static str = "IteratorNextWithoutPop"; const NAME: &'static str = "IteratorNextWithoutPop";
const INSTRUCTION: &'static str = "INST - IteratorNextWithoutPop"; const INSTRUCTION: &'static str = "INST - IteratorNextWithoutPop";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let mut iterator = context let mut iterator = context
@ -74,6 +76,7 @@ pub(crate) struct IteratorFinishAsyncNext;
impl Operation for IteratorFinishAsyncNext { impl Operation for IteratorFinishAsyncNext {
const NAME: &'static str = "IteratorFinishAsyncNext"; const NAME: &'static str = "IteratorFinishAsyncNext";
const INSTRUCTION: &'static str = "INST - IteratorFinishAsyncNext"; const INSTRUCTION: &'static str = "INST - IteratorFinishAsyncNext";
const COST: u8 = 5;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let mut iterator = context let mut iterator = context
@ -115,6 +118,7 @@ pub(crate) struct IteratorResult;
impl Operation for IteratorResult { impl Operation for IteratorResult {
const NAME: &'static str = "IteratorResult"; const NAME: &'static str = "IteratorResult";
const INSTRUCTION: &'static str = "INST - IteratorResult"; const INSTRUCTION: &'static str = "INST - IteratorResult";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let last_result = context let last_result = context
@ -143,6 +147,7 @@ pub(crate) struct IteratorValue;
impl Operation for IteratorValue { impl Operation for IteratorValue {
const NAME: &'static str = "IteratorValue"; const NAME: &'static str = "IteratorValue";
const INSTRUCTION: &'static str = "INST - IteratorValue"; const INSTRUCTION: &'static str = "INST - IteratorValue";
const COST: u8 = 5;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let mut iterator = context let mut iterator = context
@ -171,6 +176,7 @@ pub(crate) struct IteratorValueWithoutPop;
impl Operation for IteratorValueWithoutPop { impl Operation for IteratorValueWithoutPop {
const NAME: &'static str = "IteratorValueWithoutPop"; const NAME: &'static str = "IteratorValueWithoutPop";
const INSTRUCTION: &'static str = "INST - IteratorValueWithoutPop"; const INSTRUCTION: &'static str = "INST - IteratorValueWithoutPop";
const COST: u8 = 5;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let mut iterator = context let mut iterator = context
@ -199,6 +205,7 @@ pub(crate) struct IteratorDone;
impl Operation for IteratorDone { impl Operation for IteratorDone {
const NAME: &'static str = "IteratorDone"; const NAME: &'static str = "IteratorDone";
const INSTRUCTION: &'static str = "INST - IteratorDone"; const INSTRUCTION: &'static str = "INST - IteratorDone";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let done = context let done = context
@ -225,6 +232,7 @@ pub(crate) struct IteratorReturn;
impl Operation for IteratorReturn { impl Operation for IteratorReturn {
const NAME: &'static str = "IteratorReturn"; const NAME: &'static str = "IteratorReturn";
const INSTRUCTION: &'static str = "INST - IteratorReturn"; const INSTRUCTION: &'static str = "INST - IteratorReturn";
const COST: u8 = 8;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let record = context let record = context
@ -261,6 +269,7 @@ pub(crate) struct IteratorToArray;
impl Operation for IteratorToArray { impl Operation for IteratorToArray {
const NAME: &'static str = "IteratorToArray"; const NAME: &'static str = "IteratorToArray";
const INSTRUCTION: &'static str = "INST - IteratorToArray"; const INSTRUCTION: &'static str = "INST - IteratorToArray";
const COST: u8 = 8;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let mut iterator = context let mut iterator = context
@ -314,6 +323,7 @@ pub(crate) struct IteratorPop;
impl Operation for IteratorPop { impl Operation for IteratorPop {
const NAME: &'static str = "IteratorPop"; const NAME: &'static str = "IteratorPop";
const INSTRUCTION: &'static str = "INST - IteratorPop"; const INSTRUCTION: &'static str = "INST - IteratorPop";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
context.vm.frame_mut().iterators.pop(); context.vm.frame_mut().iterators.pop();
@ -331,6 +341,7 @@ pub(crate) struct IteratorStackEmpty;
impl Operation for IteratorStackEmpty { impl Operation for IteratorStackEmpty {
const NAME: &'static str = "IteratorStackEmpty"; const NAME: &'static str = "IteratorStackEmpty";
const INSTRUCTION: &'static str = "INST - IteratorStackEmpty"; const INSTRUCTION: &'static str = "INST - IteratorStackEmpty";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let is_empty = context.vm.frame().iterators.is_empty(); let is_empty = context.vm.frame().iterators.is_empty();
@ -349,6 +360,7 @@ pub(crate) struct CreateIteratorResult;
impl Operation for CreateIteratorResult { impl Operation for CreateIteratorResult {
const NAME: &'static str = "CreateIteratorResult"; const NAME: &'static str = "CreateIteratorResult";
const INSTRUCTION: &'static str = "INST - CreateIteratorResult"; const INSTRUCTION: &'static str = "INST - CreateIteratorResult";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

1
boa_engine/src/vm/opcode/iteration/loop_ops.rs

@ -14,6 +14,7 @@ pub(crate) struct IncrementLoopIteration;
impl Operation for IncrementLoopIteration { impl Operation for IncrementLoopIteration {
const NAME: &'static str = "IncrementLoopIteration"; const NAME: &'static str = "IncrementLoopIteration";
const INSTRUCTION: &'static str = "INST - IncrementLoopIteration"; const INSTRUCTION: &'static str = "INST - IncrementLoopIteration";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let previous_iteration_count = context.vm.frame_mut().loop_iteration_count; let previous_iteration_count = context.vm.frame_mut().loop_iteration_count;

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

@ -16,6 +16,7 @@ pub(crate) struct NewTarget;
impl Operation for NewTarget { impl Operation for NewTarget {
const NAME: &'static str = "NewTarget"; const NAME: &'static str = "NewTarget";
const INSTRUCTION: &'static str = "INST - NewTarget"; const INSTRUCTION: &'static str = "INST - NewTarget";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let new_target = if let Some(new_target) = context let new_target = if let Some(new_target) = context
@ -44,6 +45,7 @@ pub(crate) struct ImportMeta;
impl Operation for ImportMeta { impl Operation for ImportMeta {
const NAME: &'static str = "ImportMeta"; const NAME: &'static str = "ImportMeta";
const INSTRUCTION: &'static str = "INST - ImportMeta"; const INSTRUCTION: &'static str = "INST - ImportMeta";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
// Meta Properties // Meta Properties

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

@ -396,11 +396,11 @@ macro_rules! generate_opcodes {
} }
impl Opcode { impl Opcode {
const MAX: usize = 2usize.pow(8) * 3; const MAX: usize = 2usize.pow(8);
// TODO: see if this can be exposed on all features. // TODO: see if this can be exposed on all features.
#[allow(unused)] #[allow(unused)]
const NAMES: [&'static str; Self::MAX] = [ const NAMES: [&'static str; Self::MAX * 3] = [
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::NAME),*, $(<generate_opcodes!(name $Variant $(=> $mapping)?)>::NAME),*,
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::NAME),*, $(<generate_opcodes!(name $Variant $(=> $mapping)?)>::NAME),*,
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::NAME),* $(<generate_opcodes!(name $Variant $(=> $mapping)?)>::NAME),*
@ -414,7 +414,7 @@ macro_rules! generate_opcodes {
Self::NAMES[self as usize] Self::NAMES[self as usize]
} }
const INSTRUCTIONS: [&'static str; Self::MAX] = [ const INSTRUCTIONS: [&'static str; Self::MAX * 3] = [
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::INSTRUCTION),*, $(<generate_opcodes!(name $Variant $(=> $mapping)?)>::INSTRUCTION),*,
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::INSTRUCTION),*, $(<generate_opcodes!(name $Variant $(=> $mapping)?)>::INSTRUCTION),*,
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::INSTRUCTION),* $(<generate_opcodes!(name $Variant $(=> $mapping)?)>::INSTRUCTION),*
@ -426,7 +426,29 @@ macro_rules! generate_opcodes {
Self::INSTRUCTIONS[self as usize] Self::INSTRUCTIONS[self as usize]
} }
const EXECUTE_FNS: [fn(&mut Context<'_>) -> JsResult<CompletionType>; Self::MAX] = [ const SPEND_FNS: [fn(&mut Context<'_>, &mut u32) -> JsResult<CompletionType>; Self::MAX] = [
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::spend_budget_and_execute),*,
];
/// Spends the cost of this opcode into the provided budget and executes it.
pub(super) fn spend_budget_and_execute(
self,
context: &mut Context<'_>,
budget: &mut u32
) -> JsResult<CompletionType> {
Self::SPEND_FNS[self as usize](context, budget)
}
const COSTS: [u8; Self::MAX] = [
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::COST),*,
];
/// Return the cost of this opcode.
pub(super) const fn cost(self) -> u8 {
Self::COSTS[self as usize]
}
const EXECUTE_FNS: [fn(&mut Context<'_>) -> JsResult<CompletionType>; Self::MAX * 3] = [
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::execute),*, $(<generate_opcodes!(name $Variant $(=> $mapping)?)>::execute),*,
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::execute_with_u16_operands),*, $(<generate_opcodes!(name $Variant $(=> $mapping)?)>::execute_with_u16_operands),*,
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::execute_with_u32_operands),* $(<generate_opcodes!(name $Variant $(=> $mapping)?)>::execute_with_u32_operands),*
@ -440,7 +462,7 @@ macro_rules! generate_opcodes {
/// This represents a VM instruction, it contains both opcode and operands. /// This represents a VM instruction, it contains both opcode and operands.
/// ///
// TODO: An instruction should be a representation of a valid executable instruction (opcode + operands), // TODO: An instruction should be a representation of a valid executable instruction (opcode + operands),
// so variants like `ResevedN`, or operand width prefix modifiers, idealy shouldn't // so variants like `ReservedN`, or operand width prefix modifiers, idealy shouldn't
// be a part of `Instruction`. // be a part of `Instruction`.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
#[repr(u8)] #[repr(u8)]
@ -530,6 +552,7 @@ macro_rules! generate_opcodes {
pub(crate) trait Operation { pub(crate) trait Operation {
const NAME: &'static str; const NAME: &'static str;
const INSTRUCTION: &'static str; const INSTRUCTION: &'static str;
const COST: u8;
/// Execute opcode with [`VaryingOperandKind::U8`] sized [`VaryingOperand`]s. /// Execute opcode with [`VaryingOperandKind::U8`] sized [`VaryingOperand`]s.
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType>; fn execute(context: &mut Context<'_>) -> JsResult<CompletionType>;
@ -547,6 +570,15 @@ pub(crate) trait Operation {
fn execute_with_u32_operands(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute_with_u32_operands(context: &mut Context<'_>) -> JsResult<CompletionType> {
Reserved::execute_with_u32_operands(context) Reserved::execute_with_u32_operands(context)
} }
/// Spends the cost of this operation into `budget` and runs `execute`.
fn spend_budget_and_execute(
context: &mut Context<'_>,
budget: &mut u32,
) -> JsResult<CompletionType> {
*budget = budget.saturating_sub(u32::from(Self::COST));
Self::execute(context)
}
} }
generate_opcodes! { generate_opcodes! {

26
boa_engine/src/vm/opcode/modifier.rs

@ -12,11 +12,22 @@ pub(crate) struct U16Operands;
impl Operation for U16Operands { impl Operation for U16Operands {
const NAME: &'static str = "U16Operands"; const NAME: &'static str = "U16Operands";
const INSTRUCTION: &'static str = "INST - U16Operands"; const INSTRUCTION: &'static str = "INST - U16Operands";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let opcode = context.vm.read::<u8>() as usize; let opcode = context.vm.read::<u8>() as usize;
Opcode::EXECUTE_FNS[256 + opcode](context) Opcode::EXECUTE_FNS[Opcode::MAX + opcode](context)
}
fn spend_budget_and_execute(
context: &mut Context<'_>,
budget: &mut u32,
) -> JsResult<CompletionType> {
let opcode: Opcode = context.vm.read::<u8>().into();
*budget = budget.saturating_sub(u32::from(opcode.cost()) + u32::from(Self::COST));
Opcode::EXECUTE_FNS[Opcode::MAX + opcode as usize](context)
} }
} }
@ -30,10 +41,21 @@ pub(crate) struct U32Operands;
impl Operation for U32Operands { impl Operation for U32Operands {
const NAME: &'static str = "U32Operands"; const NAME: &'static str = "U32Operands";
const INSTRUCTION: &'static str = "INST - U32Operands"; const INSTRUCTION: &'static str = "INST - U32Operands";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let opcode = context.vm.read::<u8>() as usize; let opcode = context.vm.read::<u8>() as usize;
Opcode::EXECUTE_FNS[256 * 2 + opcode](context) Opcode::EXECUTE_FNS[Opcode::MAX * 2 + opcode](context)
}
fn spend_budget_and_execute(
context: &mut Context<'_>,
budget: &mut u32,
) -> JsResult<CompletionType> {
let opcode: Opcode = context.vm.read::<u8>().into();
*budget = budget.saturating_sub(u32::from(opcode.cost()) + u32::from(Self::COST));
Opcode::EXECUTE_FNS[Opcode::MAX * 2 + opcode as usize](context)
} }
} }

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

@ -31,6 +31,7 @@ impl New {
impl Operation for New { impl Operation for New {
const NAME: &'static str = "New"; const NAME: &'static str = "New";
const INSTRUCTION: &'static str = "INST - New"; const INSTRUCTION: &'static str = "INST - New";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let argument_count = context.vm.read::<u8>() as usize; let argument_count = context.vm.read::<u8>() as usize;
@ -58,6 +59,7 @@ pub(crate) struct NewSpread;
impl Operation for NewSpread { impl Operation for NewSpread {
const NAME: &'static str = "NewSpread"; const NAME: &'static str = "NewSpread";
const INSTRUCTION: &'static str = "INST - NewSpread"; const INSTRUCTION: &'static str = "INST - NewSpread";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
// Get the arguments that are stored as an array object on the stack. // Get the arguments that are stored as an array object on the stack.

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

@ -13,6 +13,7 @@ pub(crate) struct Nop;
impl Operation for Nop { impl Operation for Nop {
const NAME: &'static str = "Nop"; const NAME: &'static str = "Nop";
const INSTRUCTION: &'static str = "INST - Nop"; const INSTRUCTION: &'static str = "INST - Nop";
const COST: u8 = 1;
fn execute(_: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(_: &mut Context<'_>) -> JsResult<CompletionType> {
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
@ -29,6 +30,7 @@ pub(crate) struct Reserved;
impl Operation for Reserved { impl Operation for Reserved {
const NAME: &'static str = "Reserved"; const NAME: &'static str = "Reserved";
const INSTRUCTION: &'static str = "INST - Reserved"; const INSTRUCTION: &'static str = "INST - Reserved";
const COST: u8 = 0;
fn execute(_: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(_: &mut Context<'_>) -> JsResult<CompletionType> {
unreachable!("Reserved opcodes are unreachable!") unreachable!("Reserved opcodes are unreachable!")

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

@ -13,6 +13,7 @@ pub(crate) struct Pop;
impl Operation for Pop { impl Operation for Pop {
const NAME: &'static str = "Pop"; const NAME: &'static str = "Pop";
const INSTRUCTION: &'static str = "INST - Pop"; const INSTRUCTION: &'static str = "INST - Pop";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let _val = context.vm.pop(); let _val = context.vm.pop();
@ -30,6 +31,7 @@ pub(crate) struct PopEnvironment;
impl Operation for PopEnvironment { impl Operation for PopEnvironment {
const NAME: &'static str = "PopEnvironment"; const NAME: &'static str = "PopEnvironment";
const INSTRUCTION: &'static str = "INST - PopEnvironment"; const INSTRUCTION: &'static str = "INST - PopEnvironment";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
context.vm.environments.pop(); context.vm.environments.pop();

4
boa_engine/src/vm/opcode/push/array.rs

@ -16,6 +16,7 @@ pub(crate) struct PushNewArray;
impl Operation for PushNewArray { impl Operation for PushNewArray {
const NAME: &'static str = "PushNewArray"; const NAME: &'static str = "PushNewArray";
const INSTRUCTION: &'static str = "INST - PushNewArray"; const INSTRUCTION: &'static str = "INST - PushNewArray";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let array = context let array = context
@ -38,6 +39,7 @@ pub(crate) struct PushValueToArray;
impl Operation for PushValueToArray { impl Operation for PushValueToArray {
const NAME: &'static str = "PushValueToArray"; const NAME: &'static str = "PushValueToArray";
const INSTRUCTION: &'static str = "INST - PushValueToArray"; const INSTRUCTION: &'static str = "INST - PushValueToArray";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -63,6 +65,7 @@ pub(crate) struct PushElisionToArray;
impl Operation for PushElisionToArray { impl Operation for PushElisionToArray {
const NAME: &'static str = "PushElisionToArray"; const NAME: &'static str = "PushElisionToArray";
const INSTRUCTION: &'static str = "INST - PushElisionToArray"; const INSTRUCTION: &'static str = "INST - PushElisionToArray";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let array = context.vm.pop(); let array = context.vm.pop();
@ -88,6 +91,7 @@ pub(crate) struct PushIteratorToArray;
impl Operation for PushIteratorToArray { impl Operation for PushIteratorToArray {
const NAME: &'static str = "PushIteratorToArray"; const NAME: &'static str = "PushIteratorToArray";
const INSTRUCTION: &'static str = "INST - PushIteratorToArray"; const INSTRUCTION: &'static str = "INST - PushIteratorToArray";
const COST: u8 = 8;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let mut iterator = context let mut iterator = context

2
boa_engine/src/vm/opcode/push/class/field.rs

@ -14,6 +14,7 @@ pub(crate) struct PushClassField;
impl Operation for PushClassField { impl Operation for PushClassField {
const NAME: &'static str = "PushClassField"; const NAME: &'static str = "PushClassField";
const INSTRUCTION: &'static str = "INST - PushClassField"; const INSTRUCTION: &'static str = "INST - PushClassField";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let field_function_value = context.vm.pop(); let field_function_value = context.vm.pop();
@ -85,6 +86,7 @@ impl PushClassFieldPrivate {
impl Operation for PushClassFieldPrivate { impl Operation for PushClassFieldPrivate {
const NAME: &'static str = "PushClassFieldPrivate"; const NAME: &'static str = "PushClassFieldPrivate";
const INSTRUCTION: &'static str = "INST - PushClassFieldPrivate"; const INSTRUCTION: &'static str = "INST - PushClassFieldPrivate";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;

1
boa_engine/src/vm/opcode/push/class/mod.rs

@ -22,6 +22,7 @@ pub(crate) struct PushClassPrototype;
impl Operation for PushClassPrototype { impl Operation for PushClassPrototype {
const NAME: &'static str = "PushClassPrototype"; const NAME: &'static str = "PushClassPrototype";
const INSTRUCTION: &'static str = "INST - PushClassPrototype"; const INSTRUCTION: &'static str = "INST - PushClassPrototype";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let superclass = context.vm.pop(); let superclass = context.vm.pop();

3
boa_engine/src/vm/opcode/push/class/private.rs

@ -51,6 +51,7 @@ impl PushClassPrivateMethod {
impl Operation for PushClassPrivateMethod { impl Operation for PushClassPrivateMethod {
const NAME: &'static str = "PushClassPrivateMethod"; const NAME: &'static str = "PushClassPrivateMethod";
const INSTRUCTION: &'static str = "INST - PushClassPrivateMethod"; const INSTRUCTION: &'static str = "INST - PushClassPrivateMethod";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -103,6 +104,7 @@ impl PushClassPrivateGetter {
impl Operation for PushClassPrivateGetter { impl Operation for PushClassPrivateGetter {
const NAME: &'static str = "PushClassPrivateGetter"; const NAME: &'static str = "PushClassPrivateGetter";
const INSTRUCTION: &'static str = "INST - PushClassPrivateGetter"; const INSTRUCTION: &'static str = "INST - PushClassPrivateGetter";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -155,6 +157,7 @@ impl PushClassPrivateSetter {
impl Operation for PushClassPrivateSetter { impl Operation for PushClassPrivateSetter {
const NAME: &'static str = "PushClassPrivateSetter"; const NAME: &'static str = "PushClassPrivateSetter";
const INSTRUCTION: &'static str = "INST - PushClassPrivateSetter"; const INSTRUCTION: &'static str = "INST - PushClassPrivateSetter";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;

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

@ -28,6 +28,7 @@ impl PushDeclarativeEnvironment {
impl Operation for PushDeclarativeEnvironment { impl Operation for PushDeclarativeEnvironment {
const NAME: &'static str = "PushDeclarativeEnvironment"; const NAME: &'static str = "PushDeclarativeEnvironment";
const INSTRUCTION: &'static str = "INST - PushDeclarativeEnvironment"; const INSTRUCTION: &'static str = "INST - PushDeclarativeEnvironment";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let compile_environments_index = context.vm.read::<u8>() as usize; let compile_environments_index = context.vm.read::<u8>() as usize;
@ -55,6 +56,7 @@ pub(crate) struct PushObjectEnvironment;
impl Operation for PushObjectEnvironment { impl Operation for PushObjectEnvironment {
const NAME: &'static str = "PushObjectEnvironment"; const NAME: &'static str = "PushObjectEnvironment";
const INSTRUCTION: &'static str = "INST - PushObjectEnvironment"; const INSTRUCTION: &'static str = "INST - PushObjectEnvironment";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let object = context.vm.pop(); let object = context.vm.pop();
@ -75,6 +77,7 @@ pub(crate) struct PushPrivateEnvironment;
impl Operation for PushPrivateEnvironment { impl Operation for PushPrivateEnvironment {
const NAME: &'static str = "PushPrivateEnvironment"; const NAME: &'static str = "PushPrivateEnvironment";
const INSTRUCTION: &'static str = "INST - PushPrivateEnvironment"; const INSTRUCTION: &'static str = "INST - PushPrivateEnvironment";
const COST: u8 = 5;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let class_value = context.vm.pop(); let class_value = context.vm.pop();
@ -114,6 +117,7 @@ pub(crate) struct PopPrivateEnvironment;
impl Operation for PopPrivateEnvironment { impl Operation for PopPrivateEnvironment {
const NAME: &'static str = "PopPrivateEnvironment"; const NAME: &'static str = "PopPrivateEnvironment";
const INSTRUCTION: &'static str = "INST - PopPrivateEnvironment"; const INSTRUCTION: &'static str = "INST - PopPrivateEnvironment";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
context.vm.environments.pop_private(); context.vm.environments.pop_private();

2
boa_engine/src/vm/opcode/push/literal.rs

@ -23,6 +23,7 @@ impl PushLiteral {
impl Operation for PushLiteral { impl Operation for PushLiteral {
const NAME: &'static str = "PushLiteral"; const NAME: &'static str = "PushLiteral";
const INSTRUCTION: &'static str = "INST - PushLiteral"; const INSTRUCTION: &'static str = "INST - PushLiteral";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -65,6 +66,7 @@ impl PushRegExp {
impl Operation for PushRegExp { impl Operation for PushRegExp {
const NAME: &'static str = "PushRegExp"; const NAME: &'static str = "PushRegExp";
const INSTRUCTION: &'static str = "INST - PushRegExp"; const INSTRUCTION: &'static str = "INST - PushRegExp";
const COST: u8 = 5;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let pattern_index = context.vm.read::<u8>() as usize; let pattern_index = context.vm.read::<u8>() as usize;

1
boa_engine/src/vm/opcode/push/mod.rs

@ -29,6 +29,7 @@ macro_rules! implement_push_generics {
impl Operation for $name { impl Operation for $name {
const NAME: &'static str = stringify!($name); const NAME: &'static str = stringify!($name);
const INSTRUCTION: &'static str = stringify!("INST - " + $name); const INSTRUCTION: &'static str = stringify!("INST - " + $name);
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
context.vm.push($push_value); context.vm.push($push_value);

2
boa_engine/src/vm/opcode/push/numbers.rs

@ -15,6 +15,7 @@ macro_rules! implement_push_numbers_with_conversion {
impl Operation for $name { impl Operation for $name {
const NAME: &'static str = stringify!($name); const NAME: &'static str = stringify!($name);
const INSTRUCTION: &'static str = stringify!("INST - " + $name); const INSTRUCTION: &'static str = stringify!("INST - " + $name);
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.read::<$num_type>(); let value = context.vm.read::<$num_type>();
@ -37,6 +38,7 @@ macro_rules! implement_push_numbers_no_conversion {
impl Operation for $name { impl Operation for $name {
const NAME: &'static str = stringify!($name); const NAME: &'static str = stringify!($name);
const INSTRUCTION: &'static str = stringify!("INST - " + $name); const INSTRUCTION: &'static str = stringify!("INST - " + $name);
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.read::<$num_type>(); let value = context.vm.read::<$num_type>();

1
boa_engine/src/vm/opcode/push/object.rs

@ -14,6 +14,7 @@ pub(crate) struct PushEmptyObject;
impl Operation for PushEmptyObject { impl Operation for PushEmptyObject {
const NAME: &'static str = "PushEmptyObject"; const NAME: &'static str = "PushEmptyObject";
const INSTRUCTION: &'static str = "INST - PushEmptyObject"; const INSTRUCTION: &'static str = "INST - PushEmptyObject";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let o = context let o = context

1
boa_engine/src/vm/opcode/require/mod.rs

@ -13,6 +13,7 @@ pub(crate) struct RequireObjectCoercible;
impl Operation for RequireObjectCoercible { impl Operation for RequireObjectCoercible {
const NAME: &'static str = "RequireObjectCoercible"; const NAME: &'static str = "RequireObjectCoercible";
const INSTRUCTION: &'static str = "INST - RequireObjectCoercible"; const INSTRUCTION: &'static str = "INST - RequireObjectCoercible";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

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

@ -14,6 +14,7 @@ pub(crate) struct RestParameterInit;
impl Operation for RestParameterInit { impl Operation for RestParameterInit {
const NAME: &'static str = "RestParameterInit"; const NAME: &'static str = "RestParameterInit";
const INSTRUCTION: &'static str = "INST - RestParameterInit"; const INSTRUCTION: &'static str = "INST - RestParameterInit";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let arg_count = context.vm.frame().argument_count as usize; let arg_count = context.vm.frame().argument_count as usize;

1
boa_engine/src/vm/opcode/set/class_prototype.rs

@ -15,6 +15,7 @@ pub(crate) struct SetClassPrototype;
impl Operation for SetClassPrototype { impl Operation for SetClassPrototype {
const NAME: &'static str = "SetClassPrototype"; const NAME: &'static str = "SetClassPrototype";
const INSTRUCTION: &'static str = "INST - SetClassPrototype"; const INSTRUCTION: &'static str = "INST - SetClassPrototype";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let prototype_value = context.vm.pop(); let prototype_value = context.vm.pop();

1
boa_engine/src/vm/opcode/set/home_object.rs

@ -13,6 +13,7 @@ pub(crate) struct SetHomeObject;
impl Operation for SetHomeObject { impl Operation for SetHomeObject {
const NAME: &'static str = "SetHomeObject"; const NAME: &'static str = "SetHomeObject";
const INSTRUCTION: &'static str = "INST - SetHomeObject"; const INSTRUCTION: &'static str = "INST - SetHomeObject";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let function = context.vm.pop(); let function = context.vm.pop();

3
boa_engine/src/vm/opcode/set/name.rs

@ -27,6 +27,7 @@ impl ThrowMutateImmutable {
impl Operation for ThrowMutateImmutable { impl Operation for ThrowMutateImmutable {
const NAME: &'static str = "ThrowMutateImmutable"; const NAME: &'static str = "ThrowMutateImmutable";
const INSTRUCTION: &'static str = "INST - ThrowMutateImmutable"; const INSTRUCTION: &'static str = "INST - ThrowMutateImmutable";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();
@ -73,6 +74,7 @@ impl SetName {
impl Operation for SetName { impl Operation for SetName {
const NAME: &'static str = "SetName"; const NAME: &'static str = "SetName";
const INSTRUCTION: &'static str = "INST - SetName"; const INSTRUCTION: &'static str = "INST - SetName";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();
@ -100,6 +102,7 @@ pub(crate) struct SetNameByLocator;
impl Operation for SetNameByLocator { impl Operation for SetNameByLocator {
const NAME: &'static str = "SetNameByLocator"; const NAME: &'static str = "SetNameByLocator";
const INSTRUCTION: &'static str = "INST - SetNameByLocator"; const INSTRUCTION: &'static str = "INST - SetNameByLocator";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let binding_locator = context let binding_locator = context

5
boa_engine/src/vm/opcode/set/private.rs

@ -36,6 +36,7 @@ impl SetPrivateField {
impl Operation for SetPrivateField { impl Operation for SetPrivateField {
const NAME: &'static str = "SetPrivateField"; const NAME: &'static str = "SetPrivateField";
const INSTRUCTION: &'static str = "INST - SetPrivateField"; const INSTRUCTION: &'static str = "INST - SetPrivateField";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -81,6 +82,7 @@ impl DefinePrivateField {
impl Operation for DefinePrivateField { impl Operation for DefinePrivateField {
const NAME: &'static str = "DefinePrivateField"; const NAME: &'static str = "DefinePrivateField";
const INSTRUCTION: &'static str = "INST - DefinePrivateField"; const INSTRUCTION: &'static str = "INST - DefinePrivateField";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -140,6 +142,7 @@ impl SetPrivateMethod {
impl Operation for SetPrivateMethod { impl Operation for SetPrivateMethod {
const NAME: &'static str = "SetPrivateMethod"; const NAME: &'static str = "SetPrivateMethod";
const INSTRUCTION: &'static str = "INST - SetPrivateMethod"; const INSTRUCTION: &'static str = "INST - SetPrivateMethod";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -190,6 +193,7 @@ impl SetPrivateSetter {
impl Operation for SetPrivateSetter { impl Operation for SetPrivateSetter {
const NAME: &'static str = "SetPrivateSetter"; const NAME: &'static str = "SetPrivateSetter";
const INSTRUCTION: &'static str = "INST - SetPrivateSetter"; const INSTRUCTION: &'static str = "INST - SetPrivateSetter";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -240,6 +244,7 @@ impl SetPrivateGetter {
impl Operation for SetPrivateGetter { impl Operation for SetPrivateGetter {
const NAME: &'static str = "SetPrivateGetter"; const NAME: &'static str = "SetPrivateGetter";
const INSTRUCTION: &'static str = "INST - SetPrivateGetter"; const INSTRUCTION: &'static str = "INST - SetPrivateGetter";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;

7
boa_engine/src/vm/opcode/set/property.rs

@ -41,6 +41,7 @@ impl SetPropertyByName {
impl Operation for SetPropertyByName { impl Operation for SetPropertyByName {
const NAME: &'static str = "SetPropertyByName"; const NAME: &'static str = "SetPropertyByName";
const INSTRUCTION: &'static str = "INST - SetPropertyByName"; const INSTRUCTION: &'static str = "INST - SetPropertyByName";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>(); let index = context.vm.read::<u8>();
@ -68,6 +69,7 @@ pub(crate) struct SetPropertyByValue;
impl Operation for SetPropertyByValue { impl Operation for SetPropertyByValue {
const NAME: &'static str = "SetPropertyByValue"; const NAME: &'static str = "SetPropertyByValue";
const INSTRUCTION: &'static str = "INST - SetPropertyByValue"; const INSTRUCTION: &'static str = "INST - SetPropertyByValue";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -197,6 +199,7 @@ impl SetPropertyGetterByName {
impl Operation for SetPropertyGetterByName { impl Operation for SetPropertyGetterByName {
const NAME: &'static str = "SetPropertyGetterByName"; const NAME: &'static str = "SetPropertyGetterByName";
const INSTRUCTION: &'static str = "INST - SetPropertyGetterByName"; const INSTRUCTION: &'static str = "INST - SetPropertyGetterByName";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -224,6 +227,7 @@ pub(crate) struct SetPropertyGetterByValue;
impl Operation for SetPropertyGetterByValue { impl Operation for SetPropertyGetterByValue {
const NAME: &'static str = "SetPropertyGetterByValue"; const NAME: &'static str = "SetPropertyGetterByValue";
const INSTRUCTION: &'static str = "INST - SetPropertyGetterByValue"; const INSTRUCTION: &'static str = "INST - SetPropertyGetterByValue";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -285,6 +289,7 @@ impl SetPropertySetterByName {
impl Operation for SetPropertySetterByName { impl Operation for SetPropertySetterByName {
const NAME: &'static str = "SetPropertySetterByName"; const NAME: &'static str = "SetPropertySetterByName";
const INSTRUCTION: &'static str = "INST - SetPropertySetterByName"; const INSTRUCTION: &'static str = "INST - SetPropertySetterByName";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize; let index = context.vm.read::<u8>() as usize;
@ -312,6 +317,7 @@ pub(crate) struct SetPropertySetterByValue;
impl Operation for SetPropertySetterByValue { impl Operation for SetPropertySetterByValue {
const NAME: &'static str = "SetPropertySetterByValue"; const NAME: &'static str = "SetPropertySetterByValue";
const INSTRUCTION: &'static str = "INST - SetPropertySetterByValue"; const INSTRUCTION: &'static str = "INST - SetPropertySetterByValue";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -348,6 +354,7 @@ pub(crate) struct SetFunctionName;
impl Operation for SetFunctionName { impl Operation for SetFunctionName {
const NAME: &'static str = "SetFunctionName"; const NAME: &'static str = "SetFunctionName";
const INSTRUCTION: &'static str = "INST - SetFunctionName"; const INSTRUCTION: &'static str = "INST - SetFunctionName";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let prefix = context.vm.read::<u8>(); let prefix = context.vm.read::<u8>();

1
boa_engine/src/vm/opcode/set/prototype.rs

@ -13,6 +13,7 @@ pub(crate) struct SetPrototype;
impl Operation for SetPrototype { impl Operation for SetPrototype {
const NAME: &'static str = "SetPrototype"; const NAME: &'static str = "SetPrototype";
const INSTRUCTION: &'static str = "INST - SetPrototype"; const INSTRUCTION: &'static str = "INST - SetPrototype";
const COST: u8 = 4;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

3
boa_engine/src/vm/opcode/swap/mod.rs

@ -13,6 +13,7 @@ pub(crate) struct Swap;
impl Operation for Swap { impl Operation for Swap {
const NAME: &'static str = "Swap"; const NAME: &'static str = "Swap";
const INSTRUCTION: &'static str = "INST - Swap"; const INSTRUCTION: &'static str = "INST - Swap";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let len = context.vm.stack.len(); let len = context.vm.stack.len();
@ -32,6 +33,7 @@ pub(crate) struct RotateLeft;
impl Operation for RotateLeft { impl Operation for RotateLeft {
const NAME: &'static str = "RotateLeft"; const NAME: &'static str = "RotateLeft";
const INSTRUCTION: &'static str = "INST - RotateLeft"; const INSTRUCTION: &'static str = "INST - RotateLeft";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let n = context.vm.read::<u8>() as usize; let n = context.vm.read::<u8>() as usize;
@ -51,6 +53,7 @@ pub(crate) struct RotateRight;
impl Operation for RotateRight { impl Operation for RotateRight {
const NAME: &'static str = "RotateRight"; const NAME: &'static str = "RotateRight";
const INSTRUCTION: &'static str = "INST - RotateRight"; const INSTRUCTION: &'static str = "INST - RotateRight";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let n = context.vm.read::<u8>() as usize; let n = context.vm.read::<u8>() as usize;

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

@ -14,6 +14,7 @@ pub(crate) struct Case;
impl Operation for Case { impl Operation for Case {
const NAME: &'static str = "Case"; const NAME: &'static str = "Case";
const INSTRUCTION: &'static str = "INST - Case"; const INSTRUCTION: &'static str = "INST - Case";
const COST: u8 = 2;
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>();
@ -39,6 +40,7 @@ pub(crate) struct Default;
impl Operation for Default { impl Operation for Default {
const NAME: &'static str = "Default"; const NAME: &'static str = "Default";
const INSTRUCTION: &'static str = "INST - Default"; const INSTRUCTION: &'static str = "INST - Default";
const COST: u8 = 2;
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>();

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

@ -17,6 +17,7 @@ pub(crate) struct TemplateLookup;
impl Operation for TemplateLookup { impl Operation for TemplateLookup {
const NAME: &'static str = "TemplateLookup"; const NAME: &'static str = "TemplateLookup";
const INSTRUCTION: &'static str = "INST - TemplateLookup"; const INSTRUCTION: &'static str = "INST - TemplateLookup";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let jump = context.vm.read::<u32>(); let jump = context.vm.read::<u32>();
@ -101,6 +102,7 @@ impl TemplateCreate {
impl Operation for TemplateCreate { impl Operation for TemplateCreate {
const NAME: &'static str = "TemplateCreate"; const NAME: &'static str = "TemplateCreate";
const INSTRUCTION: &'static str = "INST - TemplateCreate"; const INSTRUCTION: &'static str = "INST - TemplateCreate";
const COST: u8 = 6;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let count = u32::from(context.vm.read::<u8>()); let count = u32::from(context.vm.read::<u8>());

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

@ -13,6 +13,7 @@ pub(crate) struct ToBoolean;
impl Operation for ToBoolean { impl Operation for ToBoolean {
const NAME: &'static str = "ToBoolean"; const NAME: &'static str = "ToBoolean";
const INSTRUCTION: &'static str = "INST - ToBoolean"; const INSTRUCTION: &'static str = "INST - ToBoolean";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -31,6 +32,7 @@ pub(crate) struct ToPropertyKey;
impl Operation for ToPropertyKey { impl Operation for ToPropertyKey {
const NAME: &'static str = "ToPropertyKey"; const NAME: &'static str = "ToPropertyKey";
const INSTRUCTION: &'static str = "INST - ToPropertyKey"; const INSTRUCTION: &'static str = "INST - ToPropertyKey";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

2
boa_engine/src/vm/opcode/unary_ops/decrement.rs

@ -14,6 +14,7 @@ pub(crate) struct Dec;
impl Operation for Dec { impl Operation for Dec {
const NAME: &'static str = "Dec"; const NAME: &'static str = "Dec";
const INSTRUCTION: &'static str = "INST - Dec"; const INSTRUCTION: &'static str = "INST - Dec";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -42,6 +43,7 @@ pub(crate) struct DecPost;
impl Operation for DecPost { impl Operation for DecPost {
const NAME: &'static str = "DecPost"; const NAME: &'static str = "DecPost";
const INSTRUCTION: &'static str = "INST - DecPost"; const INSTRUCTION: &'static str = "INST - DecPost";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

2
boa_engine/src/vm/opcode/unary_ops/increment.rs

@ -14,6 +14,7 @@ pub(crate) struct Inc;
impl Operation for Inc { impl Operation for Inc {
const NAME: &'static str = "Inc"; const NAME: &'static str = "Inc";
const INSTRUCTION: &'static str = "INST - Inc"; const INSTRUCTION: &'static str = "INST - Inc";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -42,6 +43,7 @@ pub(crate) struct IncPost;
impl Operation for IncPost { impl Operation for IncPost {
const NAME: &'static str = "IncPost"; const NAME: &'static str = "IncPost";
const INSTRUCTION: &'static str = "INST - IncPost"; const INSTRUCTION: &'static str = "INST - IncPost";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

1
boa_engine/src/vm/opcode/unary_ops/logical.rs

@ -13,6 +13,7 @@ pub(crate) struct LogicalNot;
impl Operation for LogicalNot { impl Operation for LogicalNot {
const NAME: &'static str = "LogicalNot"; const NAME: &'static str = "LogicalNot";
const INSTRUCTION: &'static str = "INST - LogicalNot"; const INSTRUCTION: &'static str = "INST - LogicalNot";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

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

@ -26,6 +26,7 @@ pub(crate) struct TypeOf;
impl Operation for TypeOf { impl Operation for TypeOf {
const NAME: &'static str = "TypeOf"; const NAME: &'static str = "TypeOf";
const INSTRUCTION: &'static str = "INST - TypeOf"; const INSTRUCTION: &'static str = "INST - TypeOf";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -44,6 +45,7 @@ pub(crate) struct Pos;
impl Operation for Pos { impl Operation for Pos {
const NAME: &'static str = "Pos"; const NAME: &'static str = "Pos";
const INSTRUCTION: &'static str = "INST - Pos"; const INSTRUCTION: &'static str = "INST - Pos";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -63,6 +65,7 @@ pub(crate) struct Neg;
impl Operation for Neg { impl Operation for Neg {
const NAME: &'static str = "Neg"; const NAME: &'static str = "Neg";
const INSTRUCTION: &'static str = "INST - Neg"; const INSTRUCTION: &'static str = "INST - Neg";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -84,6 +87,7 @@ pub(crate) struct BitNot;
impl Operation for BitNot { impl Operation for BitNot {
const NAME: &'static str = "BitNot"; const NAME: &'static str = "BitNot";
const INSTRUCTION: &'static str = "INST - BitNot"; const INSTRUCTION: &'static str = "INST - BitNot";
const COST: u8 = 3;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

1
boa_engine/src/vm/opcode/unary_ops/void.rs

@ -13,6 +13,7 @@ pub(crate) struct Void;
impl Operation for Void { impl Operation for Void {
const NAME: &'static str = "Void"; const NAME: &'static str = "Void";
const INSTRUCTION: &'static str = "INST - Void"; const INSTRUCTION: &'static str = "INST - Void";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let _old = context.vm.pop(); let _old = context.vm.pop();

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

@ -14,6 +14,7 @@ pub(crate) struct ValueNotNullOrUndefined;
impl Operation for ValueNotNullOrUndefined { impl Operation for ValueNotNullOrUndefined {
const NAME: &'static str = "ValueNotNullOrUndefined"; const NAME: &'static str = "ValueNotNullOrUndefined";
const INSTRUCTION: &'static str = "INST - ValueNotNullOrUndefined"; const INSTRUCTION: &'static str = "INST - ValueNotNullOrUndefined";
const COST: u8 = 2;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();
@ -42,6 +43,7 @@ pub(crate) struct IsObject;
impl Operation for IsObject { impl Operation for IsObject {
const NAME: &'static str = "IsObject"; const NAME: &'static str = "IsObject";
const INSTRUCTION: &'static str = "INST - IsObject"; const INSTRUCTION: &'static str = "INST - IsObject";
const COST: u8 = 1;
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop(); let value = context.vm.pop();

Loading…
Cancel
Save