Browse Source

Add `Instruction` and `InstructionIterator` (#3201)

pull/3264/head
Haled Odat 1 year ago committed by GitHub
parent
commit
3ea0a77606
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      boa_engine/src/bytecompiler/mod.rs
  2. 5
      boa_engine/src/vm/call_frame/mod.rs
  3. 640
      boa_engine/src/vm/code_block.rs
  4. 651
      boa_engine/src/vm/flowgraph/mod.rs
  5. 7
      boa_engine/src/vm/mod.rs
  6. 2
      boa_engine/src/vm/opcode/control_flow/jump.rs
  7. 3592
      boa_engine/src/vm/opcode/mod.rs

4
boa_engine/src/bytecompiler/mod.rs

@ -596,9 +596,9 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
let index = self.next_opcode_location(); let index = self.next_opcode_location();
self.emit( self.emit(
Opcode::JumpTable, Opcode::JumpTable,
&[Operand::U32(count), Operand::U32(Self::DUMMY_ADDRESS)], &[Operand::U32(Self::DUMMY_ADDRESS), Operand::U32(count)],
); );
let default = Label { index: index + 4 }; let default = Label { index };
let mut labels = Vec::with_capacity(count as usize); let mut labels = Vec::with_capacity(count as usize);
for i in 0..count { for i in 0..count {
labels.push(Label { labels.push(Label {

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

@ -87,9 +87,10 @@ impl CallFrame {
} }
/// Indicates how a generator function that has been called/resumed should return. /// Indicates how a generator function that has been called/resumed should return.
#[derive(Copy, Clone, Debug, PartialEq, Default)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
#[repr(u8)] #[repr(u8)]
pub(crate) enum GeneratorResumeKind { #[allow(missing_docs)]
pub enum GeneratorResumeKind {
#[default] #[default]
Normal = 0, Normal = 0,
Throw, Throw,

640
boa_engine/src/vm/code_block.rs

@ -301,387 +301,335 @@ impl CodeBlock {
/// Returns an empty `String` if no operands are present. /// Returns an empty `String` if no operands are present.
#[cfg(any(feature = "trace", feature = "flowgraph"))] #[cfg(any(feature = "trace", feature = "flowgraph"))]
pub(crate) fn instruction_operands(&self, pc: &mut usize, interner: &Interner) -> String { pub(crate) fn instruction_operands(&self, pc: &mut usize, interner: &Interner) -> String {
let opcode: Opcode = self.bytecode[*pc].into(); use super::Instruction;
*pc += size_of::<Opcode>();
match opcode { let instruction = Instruction::from_bytecode(&self.bytecode, pc);
Opcode::SetFunctionName => { match instruction {
let operand = self.read::<u8>(*pc); Instruction::SetFunctionName { prefix } => match prefix {
*pc += size_of::<u8>(); 0 => "prefix: none",
match operand { 1 => "prefix: get",
0 => "prefix: none", 2 => "prefix: set",
1 => "prefix: get", _ => unreachable!(),
2 => "prefix: set",
_ => unreachable!(),
}
.to_owned()
}
Opcode::RotateLeft | Opcode::RotateRight => {
let result = self.read::<u8>(*pc).to_string();
*pc += size_of::<u8>();
result
} }
Opcode::Generator => { .to_owned(),
let result = self.read::<u8>(*pc); Instruction::RotateLeft { n } | Instruction::RotateRight { n } => n.to_string(),
*pc += size_of::<u8>(); Instruction::Generator { r#async } => {
format!("async: {}", result != 0) format!("async: {async}")
} }
Opcode::PushInt8 => { Instruction::PushInt8 { value } => value.to_string(),
let result = self.read::<i8>(*pc).to_string(); Instruction::PushInt16 { value } => value.to_string(),
*pc += size_of::<i8>(); Instruction::PushInt32 { value } => value.to_string(),
result Instruction::PushFloat { value } => ryu_js::Buffer::new().format(value).to_string(),
Instruction::PushDouble { value } => ryu_js::Buffer::new().format(value).to_string(),
Instruction::PushLiteral { index: value }
| Instruction::ThrowNewTypeError { message: value }
| Instruction::Jump { address: value }
| Instruction::JumpIfTrue { address: value }
| Instruction::JumpIfFalse { address: value }
| Instruction::JumpIfNotUndefined { address: value }
| Instruction::JumpIfNullOrUndefined { address: value }
| Instruction::Case { address: value }
| Instruction::Default { address: value }
| Instruction::LogicalAnd { exit: value }
| Instruction::LogicalOr { exit: value }
| Instruction::Coalesce { exit: value }
| Instruction::CallEval {
argument_count: value,
} }
Opcode::PushInt16 => { | Instruction::Call {
let result = self.read::<i16>(*pc).to_string(); argument_count: value,
*pc += size_of::<i16>();
result
} }
Opcode::PushInt32 => { | Instruction::New {
let result = self.read::<i32>(*pc).to_string(); argument_count: value,
*pc += size_of::<i32>();
result
} }
Opcode::PushFloat => { | Instruction::SuperCall {
let operand = self.read::<f32>(*pc); argument_count: value,
*pc += size_of::<f32>();
ryu_js::Buffer::new().format(operand).to_string()
} }
Opcode::PushDouble => { | Instruction::ConcatToString { value_count: value } => value.to_string(),
let operand = self.read::<f64>(*pc); Instruction::PushDeclarativeEnvironment {
*pc += size_of::<f64>(); compile_environments_index,
ryu_js::Buffer::new().format(operand).to_string()
} }
Opcode::PushLiteral | Instruction::PushFunctionEnvironment {
| Opcode::ThrowNewTypeError compile_environments_index,
| Opcode::Jump } => compile_environments_index.to_string(),
| Opcode::JumpIfTrue Instruction::CopyDataProperties {
| Opcode::JumpIfFalse excluded_key_count: value1,
| Opcode::JumpIfNotUndefined excluded_key_count_computed: value2,
| Opcode::JumpIfNullOrUndefined
| Opcode::Case
| Opcode::Default
| Opcode::LogicalAnd
| Opcode::LogicalOr
| Opcode::Coalesce
| Opcode::CallEval
| Opcode::Call
| Opcode::New
| Opcode::SuperCall
| Opcode::ConcatToString => {
let result = self.read::<u32>(*pc).to_string();
*pc += size_of::<u32>();
result
} }
Opcode::PushDeclarativeEnvironment | Opcode::PushFunctionEnvironment => { | Instruction::GeneratorDelegateNext {
let operand = self.read::<u32>(*pc); return_method_undefined: value1,
*pc += size_of::<u32>(); throw_method_undefined: value2,
format!("{operand}")
} }
Opcode::CopyDataProperties | Instruction::GeneratorDelegateResume {
| Opcode::GeneratorDelegateNext exit: value1,
| Opcode::GeneratorDelegateResume => { r#return: value2,
let operand1 = self.read::<u32>(*pc); } => {
*pc += size_of::<u32>(); format!("{value1}, {value2}")
let operand2 = self.read::<u32>(*pc);
*pc += size_of::<u32>();
format!("{operand1}, {operand2}")
} }
Opcode::TemplateLookup | Opcode::TemplateCreate => { Instruction::TemplateLookup { exit: value, site }
let operand1 = self.read::<u32>(*pc); | Instruction::TemplateCreate { count: value, site } => {
*pc += size_of::<u32>(); format!("{value}, {site}")
let operand2 = self.read::<u64>(*pc);
*pc += size_of::<u64>();
format!("{operand1}, {operand2}")
} }
Opcode::GetArrowFunction Instruction::GetArrowFunction { index, method }
| Opcode::GetAsyncArrowFunction | Instruction::GetAsyncArrowFunction { index, method }
| Opcode::GetFunction | Instruction::GetFunction { index, method }
| Opcode::GetFunctionAsync => { | Instruction::GetFunctionAsync { index, method } => {
let operand = self.read::<u32>(*pc);
*pc += size_of::<u32>() + size_of::<u8>();
format!( format!(
"{operand:04}: '{}' (length: {})", "{index:04}: '{}' (length: {}), method: {method}",
self.functions[operand as usize] self.functions[index as usize]
.name() .name()
.to_std_string_escaped(), .to_std_string_escaped(),
self.functions[operand as usize].length self.functions[index as usize].length
) )
} }
Opcode::GetGenerator | Opcode::GetGeneratorAsync => { Instruction::GetGenerator { index } | Instruction::GetGeneratorAsync { index } => {
let operand = self.read::<u32>(*pc);
*pc += size_of::<u32>();
format!( format!(
"{operand:04}: '{}' (length: {})", "{index:04}: '{}' (length: {})",
self.functions[operand as usize] self.functions[index as usize]
.name() .name()
.to_std_string_escaped(), .to_std_string_escaped(),
self.functions[operand as usize].length self.functions[index as usize].length
) )
} }
Opcode::DefVar Instruction::DefVar { index }
| Opcode::DefInitVar | Instruction::DefInitVar { index }
| Opcode::PutLexicalValue | Instruction::PutLexicalValue { index }
| Opcode::GetName | Instruction::GetName { index }
| Opcode::GetLocator | Instruction::GetLocator { index }
| Opcode::GetNameAndLocator | Instruction::GetNameAndLocator { index }
| Opcode::GetNameOrUndefined | Instruction::GetNameOrUndefined { index }
| Opcode::SetName | Instruction::SetName { index }
| Opcode::DeleteName => { | Instruction::DeleteName { index } => {
let operand = self.read::<u32>(*pc);
*pc += size_of::<u32>();
format!( format!(
"{:04}: '{}'", "{index:04}: '{}'",
operand, interner.resolve_expect(self.bindings[index as usize].name().sym()),
interner.resolve_expect(self.bindings[operand as usize].name().sym()),
) )
} }
Opcode::GetPropertyByName Instruction::GetPropertyByName { index }
| Opcode::GetMethod | Instruction::GetMethod { index }
| Opcode::SetPropertyByName | Instruction::SetPropertyByName { index }
| Opcode::DefineOwnPropertyByName | Instruction::DefineOwnPropertyByName { index }
| Opcode::DefineClassStaticMethodByName | Instruction::DefineClassStaticMethodByName { index }
| Opcode::DefineClassMethodByName | Instruction::DefineClassMethodByName { index }
| Opcode::SetPropertyGetterByName | Instruction::SetPropertyGetterByName { index }
| Opcode::DefineClassStaticGetterByName | Instruction::DefineClassStaticGetterByName { index }
| Opcode::DefineClassGetterByName | Instruction::DefineClassGetterByName { index }
| Opcode::SetPropertySetterByName | Instruction::SetPropertySetterByName { index }
| Opcode::DefineClassStaticSetterByName | Instruction::DefineClassStaticSetterByName { index }
| Opcode::DefineClassSetterByName | Instruction::DefineClassSetterByName { index }
| Opcode::DeletePropertyByName | Instruction::DeletePropertyByName { index }
| Opcode::SetPrivateField | Instruction::SetPrivateField { index }
| Opcode::DefinePrivateField | Instruction::DefinePrivateField { index }
| Opcode::SetPrivateMethod | Instruction::SetPrivateMethod { index }
| Opcode::SetPrivateSetter | Instruction::SetPrivateSetter { index }
| Opcode::SetPrivateGetter | Instruction::SetPrivateGetter { index }
| Opcode::GetPrivateField | Instruction::GetPrivateField { index }
| Opcode::PushClassFieldPrivate | Instruction::PushClassFieldPrivate { index }
| Opcode::PushClassPrivateGetter | Instruction::PushClassPrivateGetter { index }
| Opcode::PushClassPrivateSetter | Instruction::PushClassPrivateSetter { index }
| Opcode::PushClassPrivateMethod | Instruction::PushClassPrivateMethod { index }
| Opcode::InPrivate | Instruction::InPrivate { index }
| Opcode::ThrowMutateImmutable => { | Instruction::ThrowMutateImmutable { index } => {
let operand = self.read::<u32>(*pc);
*pc += size_of::<u32>();
format!( format!(
"{operand:04}: '{}'", "{index:04}: '{}'",
self.names[operand as usize].to_std_string_escaped(), self.names[index as usize].to_std_string_escaped(),
) )
} }
Opcode::PushPrivateEnvironment => { Instruction::PushPrivateEnvironment { name_indices } => {
let count = self.read::<u32>(*pc); format!("{name_indices:?}")
*pc += size_of::<u32>() * (count as usize + 1);
String::new()
} }
Opcode::JumpTable => { Instruction::JumpTable { default, addresses } => {
let count = self.read::<u32>(*pc); let mut operands = format!("#{}: Default: {default:4}", addresses.len());
*pc += size_of::<u32>(); for (i, address) in addresses.iter().enumerate() {
let default = self.read::<u32>(*pc);
*pc += size_of::<u32>();
let mut operands = format!("#{count}: Default: {default:4}");
for i in 1..=count {
let address = self.read::<u32>(*pc);
*pc += size_of::<u32>();
operands += &format!(", {i}: {address}"); operands += &format!(", {i}: {address}");
} }
operands operands
} }
Opcode::JumpIfNotResumeKind => { Instruction::JumpIfNotResumeKind { exit, resume_kind } => {
let exit = self.read::<u32>(*pc); format!("ResumeKind: {resume_kind:?}, exit: {exit}")
*pc += size_of::<u32>();
let resume_kind = self.read::<u8>(*pc);
*pc += size_of::<u8>();
format!(
"ResumeKind: {:?}, exit: {exit}",
JsValue::new(resume_kind).to_generator_resume_kind()
)
} }
Opcode::CreateIteratorResult => { Instruction::CreateIteratorResult { done } => {
let done = self.read::<u8>(*pc) != 0;
*pc += size_of::<u8>();
format!("done: {done}") format!("done: {done}")
} }
Opcode::Pop Instruction::Pop
| Opcode::Dup | Instruction::Dup
| Opcode::Swap | Instruction::Swap
| Opcode::PushZero | Instruction::PushZero
| Opcode::PushOne | Instruction::PushOne
| Opcode::PushNaN | Instruction::PushNaN
| Opcode::PushPositiveInfinity | Instruction::PushPositiveInfinity
| Opcode::PushNegativeInfinity | Instruction::PushNegativeInfinity
| Opcode::PushNull | Instruction::PushNull
| Opcode::PushTrue | Instruction::PushTrue
| Opcode::PushFalse | Instruction::PushFalse
| Opcode::PushUndefined | Instruction::PushUndefined
| Opcode::PushEmptyObject | Instruction::PushEmptyObject
| Opcode::PushClassPrototype | Instruction::PushClassPrototype
| Opcode::SetClassPrototype | Instruction::SetClassPrototype
| Opcode::SetHomeObject | Instruction::SetHomeObject
| Opcode::SetHomeObjectClass | Instruction::SetHomeObjectClass
| Opcode::Add | Instruction::Add
| Opcode::Sub | Instruction::Sub
| Opcode::Div | Instruction::Div
| Opcode::Mul | Instruction::Mul
| Opcode::Mod | Instruction::Mod
| Opcode::Pow | Instruction::Pow
| Opcode::ShiftRight | Instruction::ShiftRight
| Opcode::ShiftLeft | Instruction::ShiftLeft
| Opcode::UnsignedShiftRight | Instruction::UnsignedShiftRight
| Opcode::BitOr | Instruction::BitOr
| Opcode::BitAnd | Instruction::BitAnd
| Opcode::BitXor | Instruction::BitXor
| Opcode::BitNot | Instruction::BitNot
| Opcode::In | Instruction::In
| Opcode::Eq | Instruction::Eq
| Opcode::StrictEq | Instruction::StrictEq
| Opcode::NotEq | Instruction::NotEq
| Opcode::StrictNotEq | Instruction::StrictNotEq
| Opcode::GreaterThan | Instruction::GreaterThan
| Opcode::GreaterThanOrEq | Instruction::GreaterThanOrEq
| Opcode::LessThan | Instruction::LessThan
| Opcode::LessThanOrEq | Instruction::LessThanOrEq
| Opcode::InstanceOf | Instruction::InstanceOf
| Opcode::TypeOf | Instruction::TypeOf
| Opcode::Void | Instruction::Void
| Opcode::LogicalNot | Instruction::LogicalNot
| Opcode::Pos | Instruction::Pos
| Opcode::Neg | Instruction::Neg
| Opcode::Inc | Instruction::Inc
| Opcode::IncPost | Instruction::IncPost
| Opcode::Dec | Instruction::Dec
| Opcode::DecPost | Instruction::DecPost
| Opcode::GetPropertyByValue | Instruction::GetPropertyByValue
| Opcode::GetPropertyByValuePush | Instruction::GetPropertyByValuePush
| Opcode::SetPropertyByValue | Instruction::SetPropertyByValue
| Opcode::DefineOwnPropertyByValue | Instruction::DefineOwnPropertyByValue
| Opcode::DefineClassStaticMethodByValue | Instruction::DefineClassStaticMethodByValue
| Opcode::DefineClassMethodByValue | Instruction::DefineClassMethodByValue
| Opcode::SetPropertyGetterByValue | Instruction::SetPropertyGetterByValue
| Opcode::DefineClassStaticGetterByValue | Instruction::DefineClassStaticGetterByValue
| Opcode::DefineClassGetterByValue | Instruction::DefineClassGetterByValue
| Opcode::SetPropertySetterByValue | Instruction::SetPropertySetterByValue
| Opcode::DefineClassStaticSetterByValue | Instruction::DefineClassStaticSetterByValue
| Opcode::DefineClassSetterByValue | Instruction::DefineClassSetterByValue
| Opcode::DeletePropertyByValue | Instruction::DeletePropertyByValue
| Opcode::DeleteSuperThrow | Instruction::DeleteSuperThrow
| Opcode::ToPropertyKey | Instruction::ToPropertyKey
| Opcode::ToBoolean | Instruction::ToBoolean
| Opcode::Throw | Instruction::Throw
| Opcode::ReThrow | Instruction::ReThrow
| Opcode::Exception | Instruction::Exception
| Opcode::MaybeException | Instruction::MaybeException
| Opcode::This | Instruction::This
| Opcode::Super | Instruction::Super
| Opcode::Return | Instruction::Return
| Opcode::AsyncGeneratorClose | Instruction::AsyncGeneratorClose
| Opcode::CreatePromiseCapability | Instruction::CreatePromiseCapability
| Opcode::CompletePromiseCapability | Instruction::CompletePromiseCapability
| Opcode::PopEnvironment | Instruction::PopEnvironment
| Opcode::IncrementLoopIteration | Instruction::IncrementLoopIteration
| Opcode::CreateForInIterator | Instruction::CreateForInIterator
| Opcode::GetIterator | Instruction::GetIterator
| Opcode::GetAsyncIterator | Instruction::GetAsyncIterator
| Opcode::IteratorNext | Instruction::IteratorNext
| Opcode::IteratorNextWithoutPop | Instruction::IteratorNextWithoutPop
| Opcode::IteratorFinishAsyncNext | Instruction::IteratorFinishAsyncNext
| Opcode::IteratorValue | Instruction::IteratorValue
| Opcode::IteratorValueWithoutPop | Instruction::IteratorValueWithoutPop
| Opcode::IteratorResult | Instruction::IteratorResult
| Opcode::IteratorDone | Instruction::IteratorDone
| Opcode::IteratorToArray | Instruction::IteratorToArray
| Opcode::IteratorPop | Instruction::IteratorPop
| Opcode::IteratorReturn | Instruction::IteratorReturn
| Opcode::IteratorStackEmpty | Instruction::IteratorStackEmpty
| Opcode::RequireObjectCoercible | Instruction::RequireObjectCoercible
| Opcode::ValueNotNullOrUndefined | Instruction::ValueNotNullOrUndefined
| Opcode::RestParameterInit | Instruction::RestParameterInit
| Opcode::RestParameterPop | Instruction::RestParameterPop
| Opcode::PushValueToArray | Instruction::PushValueToArray
| Opcode::PushElisionToArray | Instruction::PushElisionToArray
| Opcode::PushIteratorToArray | Instruction::PushIteratorToArray
| Opcode::PushNewArray | Instruction::PushNewArray
| Opcode::GeneratorYield | Instruction::GeneratorYield
| Opcode::AsyncGeneratorYield | Instruction::AsyncGeneratorYield
| Opcode::GeneratorNext | Instruction::GeneratorNext
| Opcode::PushClassField | Instruction::PushClassField
| Opcode::SuperCallDerived | Instruction::SuperCallDerived
| Opcode::Await | Instruction::Await
| Opcode::NewTarget | Instruction::NewTarget
| Opcode::ImportMeta | Instruction::ImportMeta
| Opcode::SuperCallPrepare | Instruction::SuperCallPrepare
| Opcode::CallEvalSpread | Instruction::CallEvalSpread
| Opcode::CallSpread | Instruction::CallSpread
| Opcode::NewSpread | Instruction::NewSpread
| Opcode::SuperCallSpread | Instruction::SuperCallSpread
| Opcode::SetPrototype | Instruction::SetPrototype
| Opcode::PushObjectEnvironment | Instruction::PushObjectEnvironment
| Opcode::IsObject | Instruction::IsObject
| Opcode::SetNameByLocator | Instruction::SetNameByLocator
| Opcode::PopPrivateEnvironment | Instruction::PopPrivateEnvironment
| Opcode::ImportCall | Instruction::ImportCall
| Opcode::GetReturnValue | Instruction::GetReturnValue
| Opcode::SetReturnValue | Instruction::SetReturnValue
| Opcode::Nop => String::new(), | Instruction::Nop => String::new(),
Opcode::Reserved1 Instruction::Reserved1
| Opcode::Reserved2 | Instruction::Reserved2
| Opcode::Reserved3 | Instruction::Reserved3
| Opcode::Reserved4 | Instruction::Reserved4
| Opcode::Reserved5 | Instruction::Reserved5
| Opcode::Reserved6 | Instruction::Reserved6
| Opcode::Reserved7 | Instruction::Reserved7
| Opcode::Reserved8 | Instruction::Reserved8
| Opcode::Reserved9 | Instruction::Reserved9
| Opcode::Reserved10 | Instruction::Reserved10
| Opcode::Reserved11 | Instruction::Reserved11
| Opcode::Reserved12 | Instruction::Reserved12
| Opcode::Reserved13 | Instruction::Reserved13
| Opcode::Reserved14 | Instruction::Reserved14
| Opcode::Reserved15 | Instruction::Reserved15
| Opcode::Reserved16 | Instruction::Reserved16
| Opcode::Reserved17 | Instruction::Reserved17
| Opcode::Reserved18 | Instruction::Reserved18
| Opcode::Reserved19 | Instruction::Reserved19
| Opcode::Reserved20 | Instruction::Reserved20
| Opcode::Reserved21 | Instruction::Reserved21
| Opcode::Reserved22 | Instruction::Reserved22
| Opcode::Reserved23 | Instruction::Reserved23
| Opcode::Reserved24 | Instruction::Reserved24
| Opcode::Reserved25 | Instruction::Reserved25
| Opcode::Reserved26 | Instruction::Reserved26
| Opcode::Reserved27 | Instruction::Reserved27
| Opcode::Reserved28 | Instruction::Reserved28
| Opcode::Reserved29 | Instruction::Reserved29
| Opcode::Reserved30 | Instruction::Reserved30
| Opcode::Reserved31 | Instruction::Reserved31
| Opcode::Reserved32 | Instruction::Reserved32
| Opcode::Reserved33 | Instruction::Reserved33
| Opcode::Reserved34 | Instruction::Reserved34
| Opcode::Reserved35 | Instruction::Reserved35
| Opcode::Reserved36 | Instruction::Reserved36
| Opcode::Reserved37 | Instruction::Reserved37
| Opcode::Reserved38 | Instruction::Reserved38
| Opcode::Reserved39 | Instruction::Reserved39
| Opcode::Reserved40 | Instruction::Reserved40
| Opcode::Reserved41 | Instruction::Reserved41
| Opcode::Reserved42 | Instruction::Reserved42
| Opcode::Reserved43 | Instruction::Reserved43
| Opcode::Reserved44 | Instruction::Reserved44
| Opcode::Reserved45 | Instruction::Reserved45
| Opcode::Reserved46 | Instruction::Reserved46
| Opcode::Reserved47 | Instruction::Reserved47
| Opcode::Reserved48 | Instruction::Reserved48
| Opcode::Reserved49 | Instruction::Reserved49
| Opcode::Reserved50 | Instruction::Reserved50
| Opcode::Reserved51 | Instruction::Reserved51
| Opcode::Reserved52 | Instruction::Reserved52
| Opcode::Reserved53 | Instruction::Reserved53
| Opcode::Reserved54 | Instruction::Reserved54
| Opcode::Reserved55 | Instruction::Reserved55
| Opcode::Reserved56 | Instruction::Reserved56
| Opcode::Reserved57 | Instruction::Reserved57
| Opcode::Reserved58 => unreachable!("Reserved opcodes are unrechable"), | Instruction::Reserved58 => unreachable!("Reserved opcodes are unrechable"),
} }
} }
} }

651
boa_engine/src/vm/flowgraph/mod.rs

@ -1,9 +1,8 @@
//! This module is responsible for generating the vm instruction flowgraph. //! This module is responsible for generating the vm instruction flowgraph.
use crate::vm::{CodeBlock, Opcode}; use crate::vm::CodeBlock;
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16; use boa_macros::utf16;
use std::mem::size_of;
mod color; mod color;
mod edge; mod edge;
@ -15,6 +14,8 @@ pub use edge::*;
pub use graph::*; pub use graph::*;
pub use node::*; pub use node::*;
use super::Instruction;
impl CodeBlock { impl CodeBlock {
/// Output the [`CodeBlock`] VM instructions into a [`Graph`]. /// Output the [`CodeBlock`] VM instructions into a [`Graph`].
#[allow(clippy::match_same_arms)] #[allow(clippy::match_same_arms)]
@ -30,104 +31,78 @@ impl CodeBlock {
let mut pc = 0; let mut pc = 0;
while pc < self.bytecode.len() { while pc < self.bytecode.len() {
let opcode: Opcode = self.bytecode[pc].into();
let opcode_str = opcode.as_str();
let previous_pc = pc; let previous_pc = pc;
let instruction = Instruction::from_bytecode(&self.bytecode, &mut pc);
let opcode = instruction.opcode();
let opcode_str = opcode.as_str();
let mut tmp = pc; let mut tmp = previous_pc;
let label = format!( let label = format!(
"{opcode_str} {}", "{opcode_str} {}",
self.instruction_operands(&mut tmp, interner) self.instruction_operands(&mut tmp, interner)
); );
pc += size_of::<Opcode>(); match instruction {
match opcode { Instruction::SetFunctionName { .. } => {
Opcode::SetFunctionName => {
let operand = self.read::<u8>(pc);
pc += size_of::<u8>();
let label = format!(
"{opcode_str} {}",
match operand {
0 => "prefix: none",
1 => "prefix: get",
2 => "prefix: set",
_ => unreachable!(),
}
);
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::RotateLeft | Opcode::RotateRight | Opcode::CreateIteratorResult => { Instruction::RotateLeft { .. }
pc += size_of::<u8>(); | Instruction::RotateRight { .. }
| Instruction::CreateIteratorResult { .. } => {
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::Generator => { Instruction::Generator { .. } => {
pc += size_of::<u8>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::PushInt8 => { Instruction::PushInt8 { .. } => {
pc += size_of::<i8>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::PushInt16 => { Instruction::PushInt16 { .. } => {
pc += size_of::<i16>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::PushInt32 => { Instruction::PushInt32 { .. } => {
pc += size_of::<i32>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::PushFloat => { Instruction::PushFloat { .. } => {
pc += size_of::<f32>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::PushDouble => { Instruction::PushDouble { .. } => {
pc += size_of::<f64>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::PushLiteral => { Instruction::PushLiteral { index } => {
let operand = self.read::<u32>(pc); let operand_str = self.literals[index as usize].display().to_string();
pc += size_of::<u32>();
let operand_str = self.literals[operand as usize].display().to_string();
let operand_str = operand_str.escape_debug(); let operand_str = operand_str.escape_debug();
let label = format!("{opcode_str} {operand_str}"); let label = format!("{opcode_str} {operand_str}");
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::Jump => { Instruction::Jump { address } => {
let operand = self.read::<u32>(pc);
pc += size_of::<u32>();
graph.add_node(previous_pc, NodeShape::Diamond, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::Diamond, label.into(), Color::None);
graph.add_edge( graph.add_edge(
previous_pc, previous_pc,
operand as usize, address as usize,
None, None,
Color::None, Color::None,
EdgeStyle::Line, EdgeStyle::Line,
); );
} }
Opcode::JumpIfFalse Instruction::JumpIfFalse { address }
| Opcode::JumpIfTrue | Instruction::JumpIfTrue { address }
| Opcode::JumpIfNotUndefined | Instruction::JumpIfNotUndefined { address }
| Opcode::JumpIfNullOrUndefined => { | Instruction::JumpIfNullOrUndefined { address } => {
let operand = self.read::<u32>(pc);
pc += size_of::<u32>();
graph.add_node(previous_pc, NodeShape::Diamond, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::Diamond, label.into(), Color::None);
graph.add_edge( graph.add_edge(
previous_pc, previous_pc,
operand as usize, address as usize,
Some("YES".into()), Some("YES".into()),
Color::Green, Color::Green,
EdgeStyle::Line, EdgeStyle::Line,
@ -140,19 +115,13 @@ impl CodeBlock {
EdgeStyle::Line, EdgeStyle::Line,
); );
} }
Opcode::TemplateLookup | Opcode::TemplateCreate => { Instruction::TemplateLookup { .. } | Instruction::TemplateCreate { .. } => {
let start_address = self.read::<u32>(pc);
pc += size_of::<u32>();
let end_address = self.read::<u64>(pc);
pc += size_of::<u64>();
let label = format!("{opcode_str} {start_address}, {end_address}");
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::Red); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::Red);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::LogicalAnd | Opcode::LogicalOr | Opcode::Coalesce => { Instruction::LogicalAnd { exit }
let exit = self.read::<u32>(pc); | Instruction::LogicalOr { exit }
pc += size_of::<u32>(); | Instruction::Coalesce { exit } => {
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
graph.add_edge( graph.add_edge(
@ -163,9 +132,7 @@ impl CodeBlock {
EdgeStyle::Line, EdgeStyle::Line,
); );
} }
Opcode::Case => { Instruction::Case { address } => {
let address = self.read::<u32>(pc) as usize;
pc += size_of::<u32>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge( graph.add_edge(
previous_pc, previous_pc,
@ -176,23 +143,26 @@ impl CodeBlock {
); );
graph.add_edge( graph.add_edge(
previous_pc, previous_pc,
address, address as usize,
Some("YES".into()), Some("YES".into()),
Color::Green, Color::Green,
EdgeStyle::Line, EdgeStyle::Line,
); );
} }
Opcode::Default => { Instruction::Default { address } => {
let address = self.read::<u32>(pc) as usize;
pc += size_of::<u32>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, address, None, Color::None, EdgeStyle::Line); graph.add_edge(
previous_pc,
address as usize,
None,
Color::None,
EdgeStyle::Line,
);
} }
Opcode::GeneratorDelegateNext => { Instruction::GeneratorDelegateNext {
let throw_method_undefined = self.read::<u32>(pc) as usize; return_method_undefined,
pc += size_of::<u32>(); throw_method_undefined,
let return_method_undefined = self.read::<u32>(pc) as usize; } => {
pc += size_of::<u32>();
graph.add_node( graph.add_node(
previous_pc, previous_pc,
NodeShape::Diamond, NodeShape::Diamond,
@ -202,24 +172,20 @@ impl CodeBlock {
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
graph.add_edge( graph.add_edge(
previous_pc, previous_pc,
throw_method_undefined, throw_method_undefined as usize,
Some("`throw` undefined".into()), Some("`throw` undefined".into()),
Color::Red, Color::Red,
EdgeStyle::Line, EdgeStyle::Line,
); );
graph.add_edge( graph.add_edge(
previous_pc, previous_pc,
return_method_undefined, return_method_undefined as usize,
Some("`return` undefined".into()), Some("`return` undefined".into()),
Color::Blue, Color::Blue,
EdgeStyle::Line, EdgeStyle::Line,
); );
} }
Opcode::GeneratorDelegateResume => { Instruction::GeneratorDelegateResume { r#return, exit } => {
let return_gen = self.read::<u32>(pc) as usize;
pc += size_of::<u32>();
let exit = self.read::<u32>(pc) as usize;
pc += size_of::<u32>();
graph.add_node( graph.add_node(
previous_pc, previous_pc,
NodeShape::Diamond, NodeShape::Diamond,
@ -229,35 +195,28 @@ impl CodeBlock {
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
graph.add_edge( graph.add_edge(
previous_pc, previous_pc,
return_gen, r#return as usize,
Some("return".into()), Some("return".into()),
Color::Yellow, Color::Yellow,
EdgeStyle::Line, EdgeStyle::Line,
); );
graph.add_edge( graph.add_edge(
previous_pc, previous_pc,
exit, exit as usize,
Some("done".into()), Some("done".into()),
Color::Blue, Color::Blue,
EdgeStyle::Line, EdgeStyle::Line,
); );
} }
Opcode::CallEval Instruction::CallEval { .. }
| Opcode::Call | Instruction::Call { .. }
| Opcode::New | Instruction::New { .. }
| Opcode::SuperCall | Instruction::SuperCall { .. }
| Opcode::ConcatToString => { | Instruction::ConcatToString { .. } => {
pc += size_of::<u32>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::JumpIfNotResumeKind => { Instruction::JumpIfNotResumeKind { exit, .. } => {
let exit = self.read::<u32>(pc);
pc += size_of::<u32>();
let _resume_kind = self.read::<u8>(pc);
pc += size_of::<u8>();
graph.add_node(previous_pc, NodeShape::Diamond, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::Diamond, label.into(), Color::None);
graph.add_edge( graph.add_edge(
previous_pc, previous_pc,
@ -268,21 +227,14 @@ impl CodeBlock {
); );
graph.add_edge(previous_pc, pc, None, Color::Green, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::Green, EdgeStyle::Line);
} }
Opcode::CopyDataProperties => { Instruction::CopyDataProperties { .. } => {
let operand1 = self.read::<u32>(pc);
pc += size_of::<u32>();
let operand2 = self.read::<u32>(pc);
pc += size_of::<u32>();
let label = format!("{opcode_str} {operand1}, {operand2}");
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::PushDeclarativeEnvironment | Opcode::PushFunctionEnvironment => { Instruction::PushDeclarativeEnvironment { .. }
| Instruction::PushFunctionEnvironment { .. } => {
let random = rand::random(); let random = rand::random();
pc += size_of::<u32>();
graph.add_node( graph.add_node(
previous_pc, previous_pc,
NodeShape::None, NodeShape::None,
@ -291,93 +243,62 @@ impl CodeBlock {
); );
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::PopEnvironment => { Instruction::PopEnvironment => {
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::GetArrowFunction Instruction::GetArrowFunction { .. }
| Opcode::GetAsyncArrowFunction | Instruction::GetAsyncArrowFunction { .. }
| Opcode::GetFunction | Instruction::GetFunction { .. }
| Opcode::GetFunctionAsync => { | Instruction::GetFunctionAsync { .. } => {
let operand = self.read::<u32>(pc);
let fn_name = self.functions[operand as usize]
.name()
.to_std_string_escaped();
pc += size_of::<u32>() + size_of::<u8>();
let label = format!(
"{opcode_str} '{fn_name}' (length: {})",
self.functions[operand as usize].length
);
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::GetGenerator | Opcode::GetGeneratorAsync => { Instruction::GetGenerator { .. } | Instruction::GetGeneratorAsync { .. } => {
let operand = self.read::<u32>(pc);
let fn_name = self.functions[operand as usize]
.name()
.to_std_string_escaped();
let label = format!(
"{opcode_str} '{fn_name}' (length: {})",
self.functions[operand as usize].length
);
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::DefVar Instruction::DefVar { .. }
| Opcode::DefInitVar | Instruction::DefInitVar { .. }
| Opcode::PutLexicalValue | Instruction::PutLexicalValue { .. }
| Opcode::GetName | Instruction::GetName { .. }
| Opcode::GetLocator | Instruction::GetLocator { .. }
| Opcode::GetNameAndLocator | Instruction::GetNameAndLocator { .. }
| Opcode::GetNameOrUndefined | Instruction::GetNameOrUndefined { .. }
| Opcode::SetName | Instruction::SetName { .. }
| Opcode::DeleteName => { | Instruction::DeleteName { .. } => {
let operand = self.read::<u32>(pc);
pc += size_of::<u32>();
let label = format!(
"{opcode_str} '{}'",
interner.resolve_expect(self.bindings[operand as usize].name().sym()),
);
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::GetPropertyByName Instruction::GetPropertyByName { .. }
| Opcode::GetMethod | Instruction::GetMethod { .. }
| Opcode::SetPropertyByName | Instruction::SetPropertyByName { .. }
| Opcode::DefineOwnPropertyByName | Instruction::DefineOwnPropertyByName { .. }
| Opcode::DefineClassStaticMethodByName | Instruction::DefineClassStaticMethodByName { .. }
| Opcode::DefineClassMethodByName | Instruction::DefineClassMethodByName { .. }
| Opcode::SetPropertyGetterByName | Instruction::SetPropertyGetterByName { .. }
| Opcode::DefineClassStaticGetterByName | Instruction::DefineClassStaticGetterByName { .. }
| Opcode::DefineClassGetterByName | Instruction::DefineClassGetterByName { .. }
| Opcode::SetPropertySetterByName | Instruction::SetPropertySetterByName { .. }
| Opcode::DefineClassStaticSetterByName | Instruction::DefineClassStaticSetterByName { .. }
| Opcode::DefineClassSetterByName | Instruction::DefineClassSetterByName { .. }
| Opcode::SetPrivateField | Instruction::SetPrivateField { .. }
| Opcode::DefinePrivateField | Instruction::DefinePrivateField { .. }
| Opcode::SetPrivateMethod | Instruction::SetPrivateMethod { .. }
| Opcode::SetPrivateSetter | Instruction::SetPrivateSetter { .. }
| Opcode::SetPrivateGetter | Instruction::SetPrivateGetter { .. }
| Opcode::GetPrivateField | Instruction::GetPrivateField { .. }
| Opcode::DeletePropertyByName | Instruction::DeletePropertyByName { .. }
| Opcode::PushClassFieldPrivate | Instruction::PushClassFieldPrivate { .. }
| Opcode::PushClassPrivateGetter | Instruction::PushClassPrivateGetter { .. }
| Opcode::PushClassPrivateSetter | Instruction::PushClassPrivateSetter { .. }
| Opcode::PushClassPrivateMethod | Instruction::PushClassPrivateMethod { .. }
| Opcode::InPrivate | Instruction::InPrivate { .. }
| Opcode::ThrowMutateImmutable => { | Instruction::ThrowMutateImmutable { .. } => {
let operand = self.read::<u32>(pc);
pc += size_of::<u32>();
let label = format!(
"{opcode_str} '{}'",
self.names[operand as usize].to_std_string_escaped(),
);
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::ThrowNewTypeError => { Instruction::ThrowNewTypeError { .. } => {
pc += size_of::<u32>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
if let Some((i, handler)) = self.find_handler(previous_pc as u32) { if let Some((i, handler)) = self.find_handler(previous_pc as u32) {
graph.add_edge( graph.add_edge(
@ -389,7 +310,7 @@ impl CodeBlock {
); );
} }
} }
Opcode::Throw | Opcode::ReThrow => { Instruction::Throw | Instruction::ReThrow => {
if let Some((i, handler)) = self.find_handler(previous_pc as u32) { if let Some((i, handler)) = self.find_handler(previous_pc as u32) {
graph.add_node(previous_pc, NodeShape::Record, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::Record, label.into(), Color::None);
graph.add_edge( graph.add_edge(
@ -403,18 +324,11 @@ impl CodeBlock {
graph.add_node(previous_pc, NodeShape::Diamond, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::Diamond, label.into(), Color::None);
} }
} }
Opcode::PushPrivateEnvironment => { Instruction::PushPrivateEnvironment { .. } => {
let count = self.read::<u32>(pc);
pc += size_of::<u32>() * (count as usize + 1);
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::JumpTable => { Instruction::JumpTable { default, addresses } => {
let count = self.read::<u32>(pc);
pc += size_of::<u32>();
let default = self.read::<u32>(pc);
pc += size_of::<u32>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge( graph.add_edge(
previous_pc, previous_pc,
@ -424,200 +338,197 @@ impl CodeBlock {
EdgeStyle::Line, EdgeStyle::Line,
); );
for i in 0..count { for (i, address) in addresses.iter().enumerate() {
let address = self.read::<u32>(pc);
pc += size_of::<u32>();
graph.add_edge( graph.add_edge(
previous_pc, previous_pc,
address as usize, *address as usize,
Some(format!("Index: {i}").into()), Some(format!("Index: {i}").into()),
Color::None, Color::None,
EdgeStyle::Line, EdgeStyle::Line,
); );
} }
} }
Opcode::Pop Instruction::Pop
| Opcode::Dup | Instruction::Dup
| Opcode::Swap | Instruction::Swap
| Opcode::PushZero | Instruction::PushZero
| Opcode::PushOne | Instruction::PushOne
| Opcode::PushNaN | Instruction::PushNaN
| Opcode::PushPositiveInfinity | Instruction::PushPositiveInfinity
| Opcode::PushNegativeInfinity | Instruction::PushNegativeInfinity
| Opcode::PushNull | Instruction::PushNull
| Opcode::PushTrue | Instruction::PushTrue
| Opcode::PushFalse | Instruction::PushFalse
| Opcode::PushUndefined | Instruction::PushUndefined
| Opcode::PushEmptyObject | Instruction::PushEmptyObject
| Opcode::PushClassPrototype | Instruction::PushClassPrototype
| Opcode::SetClassPrototype | Instruction::SetClassPrototype
| Opcode::SetHomeObject | Instruction::SetHomeObject
| Opcode::SetHomeObjectClass | Instruction::SetHomeObjectClass
| Opcode::Add | Instruction::Add
| Opcode::Sub | Instruction::Sub
| Opcode::Div | Instruction::Div
| Opcode::Mul | Instruction::Mul
| Opcode::Mod | Instruction::Mod
| Opcode::Pow | Instruction::Pow
| Opcode::ShiftRight | Instruction::ShiftRight
| Opcode::ShiftLeft | Instruction::ShiftLeft
| Opcode::UnsignedShiftRight | Instruction::UnsignedShiftRight
| Opcode::BitOr | Instruction::BitOr
| Opcode::BitAnd | Instruction::BitAnd
| Opcode::BitXor | Instruction::BitXor
| Opcode::BitNot | Instruction::BitNot
| Opcode::In | Instruction::In
| Opcode::Eq | Instruction::Eq
| Opcode::StrictEq | Instruction::StrictEq
| Opcode::NotEq | Instruction::NotEq
| Opcode::StrictNotEq | Instruction::StrictNotEq
| Opcode::GreaterThan | Instruction::GreaterThan
| Opcode::GreaterThanOrEq | Instruction::GreaterThanOrEq
| Opcode::LessThan | Instruction::LessThan
| Opcode::LessThanOrEq | Instruction::LessThanOrEq
| Opcode::InstanceOf | Instruction::InstanceOf
| Opcode::TypeOf | Instruction::TypeOf
| Opcode::Void | Instruction::Void
| Opcode::LogicalNot | Instruction::LogicalNot
| Opcode::Pos | Instruction::Pos
| Opcode::Neg | Instruction::Neg
| Opcode::Inc | Instruction::Inc
| Opcode::IncPost | Instruction::IncPost
| Opcode::Dec | Instruction::Dec
| Opcode::DecPost | Instruction::DecPost
| Opcode::GetPropertyByValue | Instruction::GetPropertyByValue
| Opcode::GetPropertyByValuePush | Instruction::GetPropertyByValuePush
| Opcode::SetPropertyByValue | Instruction::SetPropertyByValue
| Opcode::DefineOwnPropertyByValue | Instruction::DefineOwnPropertyByValue
| Opcode::DefineClassStaticMethodByValue | Instruction::DefineClassStaticMethodByValue
| Opcode::DefineClassMethodByValue | Instruction::DefineClassMethodByValue
| Opcode::SetPropertyGetterByValue | Instruction::SetPropertyGetterByValue
| Opcode::DefineClassStaticGetterByValue | Instruction::DefineClassStaticGetterByValue
| Opcode::DefineClassGetterByValue | Instruction::DefineClassGetterByValue
| Opcode::SetPropertySetterByValue | Instruction::SetPropertySetterByValue
| Opcode::DefineClassStaticSetterByValue | Instruction::DefineClassStaticSetterByValue
| Opcode::DefineClassSetterByValue | Instruction::DefineClassSetterByValue
| Opcode::DeletePropertyByValue | Instruction::DeletePropertyByValue
| Opcode::DeleteSuperThrow | Instruction::DeleteSuperThrow
| Opcode::ToPropertyKey | Instruction::ToPropertyKey
| Opcode::ToBoolean | Instruction::ToBoolean
| Opcode::This | Instruction::This
| Opcode::Super | Instruction::Super
| Opcode::IncrementLoopIteration | Instruction::IncrementLoopIteration
| Opcode::CreateForInIterator | Instruction::CreateForInIterator
| Opcode::GetIterator | Instruction::GetIterator
| Opcode::GetAsyncIterator | Instruction::GetAsyncIterator
| Opcode::IteratorNext | Instruction::IteratorNext
| Opcode::IteratorNextWithoutPop | Instruction::IteratorNextWithoutPop
| Opcode::IteratorFinishAsyncNext | Instruction::IteratorFinishAsyncNext
| Opcode::IteratorValue | Instruction::IteratorValue
| Opcode::IteratorValueWithoutPop | Instruction::IteratorValueWithoutPop
| Opcode::IteratorResult | Instruction::IteratorResult
| Opcode::IteratorDone | Instruction::IteratorDone
| Opcode::IteratorToArray | Instruction::IteratorToArray
| Opcode::IteratorPop | Instruction::IteratorPop
| Opcode::IteratorReturn | Instruction::IteratorReturn
| Opcode::IteratorStackEmpty | Instruction::IteratorStackEmpty
| Opcode::RequireObjectCoercible | Instruction::RequireObjectCoercible
| Opcode::ValueNotNullOrUndefined | Instruction::ValueNotNullOrUndefined
| Opcode::RestParameterInit | Instruction::RestParameterInit
| Opcode::RestParameterPop | Instruction::RestParameterPop
| Opcode::PushValueToArray | Instruction::PushValueToArray
| Opcode::PushElisionToArray | Instruction::PushElisionToArray
| Opcode::PushIteratorToArray | Instruction::PushIteratorToArray
| Opcode::PushNewArray | Instruction::PushNewArray
| Opcode::GeneratorYield | Instruction::GeneratorYield
| Opcode::AsyncGeneratorYield | Instruction::AsyncGeneratorYield
| Opcode::AsyncGeneratorClose | Instruction::AsyncGeneratorClose
| Opcode::CreatePromiseCapability | Instruction::CreatePromiseCapability
| Opcode::CompletePromiseCapability | Instruction::CompletePromiseCapability
| Opcode::GeneratorNext | Instruction::GeneratorNext
| Opcode::PushClassField | Instruction::PushClassField
| Opcode::SuperCallDerived | Instruction::SuperCallDerived
| Opcode::Await | Instruction::Await
| Opcode::NewTarget | Instruction::NewTarget
| Opcode::ImportMeta | Instruction::ImportMeta
| Opcode::CallEvalSpread | Instruction::CallEvalSpread
| Opcode::CallSpread | Instruction::CallSpread
| Opcode::NewSpread | Instruction::NewSpread
| Opcode::SuperCallSpread | Instruction::SuperCallSpread
| Opcode::SuperCallPrepare | Instruction::SuperCallPrepare
| Opcode::SetPrototype | Instruction::SetPrototype
| Opcode::IsObject | Instruction::IsObject
| Opcode::SetNameByLocator | Instruction::SetNameByLocator
| Opcode::PushObjectEnvironment | Instruction::PushObjectEnvironment
| Opcode::PopPrivateEnvironment | Instruction::PopPrivateEnvironment
| Opcode::ImportCall | Instruction::ImportCall
| Opcode::GetReturnValue | Instruction::GetReturnValue
| Opcode::SetReturnValue | Instruction::SetReturnValue
| Opcode::Exception | Instruction::Exception
| Opcode::MaybeException | Instruction::MaybeException
| Opcode::Nop => { | Instruction::Nop => {
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::Return => { Instruction::Return => {
graph.add_node(previous_pc, NodeShape::Diamond, label.into(), Color::Red); graph.add_node(previous_pc, NodeShape::Diamond, label.into(), Color::Red);
} }
Opcode::Reserved1 Instruction::Reserved1
| Opcode::Reserved2 | Instruction::Reserved2
| Opcode::Reserved3 | Instruction::Reserved3
| Opcode::Reserved4 | Instruction::Reserved4
| Opcode::Reserved5 | Instruction::Reserved5
| Opcode::Reserved6 | Instruction::Reserved6
| Opcode::Reserved7 | Instruction::Reserved7
| Opcode::Reserved8 | Instruction::Reserved8
| Opcode::Reserved9 | Instruction::Reserved9
| Opcode::Reserved10 | Instruction::Reserved10
| Opcode::Reserved11 | Instruction::Reserved11
| Opcode::Reserved12 | Instruction::Reserved12
| Opcode::Reserved13 | Instruction::Reserved13
| Opcode::Reserved14 | Instruction::Reserved14
| Opcode::Reserved15 | Instruction::Reserved15
| Opcode::Reserved16 | Instruction::Reserved16
| Opcode::Reserved17 | Instruction::Reserved17
| Opcode::Reserved18 | Instruction::Reserved18
| Opcode::Reserved19 | Instruction::Reserved19
| Opcode::Reserved20 | Instruction::Reserved20
| Opcode::Reserved21 | Instruction::Reserved21
| Opcode::Reserved22 | Instruction::Reserved22
| Opcode::Reserved23 | Instruction::Reserved23
| Opcode::Reserved24 | Instruction::Reserved24
| Opcode::Reserved25 | Instruction::Reserved25
| Opcode::Reserved26 | Instruction::Reserved26
| Opcode::Reserved27 | Instruction::Reserved27
| Opcode::Reserved28 | Instruction::Reserved28
| Opcode::Reserved29 | Instruction::Reserved29
| Opcode::Reserved30 | Instruction::Reserved30
| Opcode::Reserved31 | Instruction::Reserved31
| Opcode::Reserved32 | Instruction::Reserved32
| Opcode::Reserved33 | Instruction::Reserved33
| Opcode::Reserved34 | Instruction::Reserved34
| Opcode::Reserved35 | Instruction::Reserved35
| Opcode::Reserved36 | Instruction::Reserved36
| Opcode::Reserved37 | Instruction::Reserved37
| Opcode::Reserved38 | Instruction::Reserved38
| Opcode::Reserved39 | Instruction::Reserved39
| Opcode::Reserved40 | Instruction::Reserved40
| Opcode::Reserved41 | Instruction::Reserved41
| Opcode::Reserved42 | Instruction::Reserved42
| Opcode::Reserved43 | Instruction::Reserved43
| Opcode::Reserved44 | Instruction::Reserved44
| Opcode::Reserved45 | Instruction::Reserved45
| Opcode::Reserved46 | Instruction::Reserved46
| Opcode::Reserved47 | Instruction::Reserved47
| Opcode::Reserved48 | Instruction::Reserved48
| Opcode::Reserved49 | Instruction::Reserved49
| Opcode::Reserved50 | Instruction::Reserved50
| Opcode::Reserved51 | Instruction::Reserved51
| Opcode::Reserved52 | Instruction::Reserved52
| Opcode::Reserved53 | Instruction::Reserved53
| Opcode::Reserved54 | Instruction::Reserved54
| Opcode::Reserved55 | Instruction::Reserved55
| Opcode::Reserved56 | Instruction::Reserved56
| Opcode::Reserved57 | Instruction::Reserved57
| Opcode::Reserved58 => unreachable!("Reserved opcodes are unrechable"), | Instruction::Reserved58 => unreachable!("Reserved opcodes are unrechable"),
} }
} }

7
boa_engine/src/vm/mod.rs

@ -33,10 +33,13 @@ mod runtime_limits;
pub mod flowgraph; pub mod flowgraph;
pub use runtime_limits::RuntimeLimits; pub use runtime_limits::RuntimeLimits;
pub use {call_frame::CallFrame, code_block::CodeBlock, opcode::Opcode}; pub use {
call_frame::{CallFrame, GeneratorResumeKind},
code_block::CodeBlock,
opcode::{Instruction, InstructionIterator, Opcode},
};
pub(crate) use { pub(crate) use {
call_frame::GeneratorResumeKind,
code_block::{ code_block::{
create_function_object, create_function_object_fast, create_generator_function_object, create_function_object, create_function_object_fast, create_generator_function_object,
CodeBlockFlags, Handler, CodeBlockFlags, Handler,

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

@ -118,8 +118,8 @@ impl Operation for JumpTable {
const INSTRUCTION: &'static str = "INST - JumpTable"; const INSTRUCTION: &'static str = "INST - JumpTable";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let count = context.vm.read::<u32>();
let default = context.vm.read::<u32>(); let default = context.vm.read::<u32>();
let count = context.vm.read::<u32>();
let value = context.vm.pop(); let value = context.vm.pop();
if let JsValue::Integer(value) = &value { if let JsValue::Integer(value) = &value {

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

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save