Browse Source

Direct conversion from `u8` to `Opcode` (#2951)

pull/2981/head
Haled Odat 1 year ago committed by GitHub
parent
commit
f0422bdf3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 60
      boa_engine/src/vm/code_block.rs
  2. 58
      boa_engine/src/vm/flowgraph/mod.rs
  3. 12
      boa_engine/src/vm/mod.rs
  4. 162
      boa_engine/src/vm/opcode/mod.rs
  5. 16
      boa_engine/src/vm/opcode/nop/mod.rs

60
boa_engine/src/vm/code_block.rs

@ -259,7 +259,7 @@ impl CodeBlock {
/// Returns an empty `String` if no operands are present.
#[cfg(any(feature = "trace", feature = "flowgraph"))]
pub(crate) fn instruction_operands(&self, pc: &mut usize, interner: &Interner) -> String {
let opcode: Opcode = self.bytecode[*pc].try_into().expect("invalid opcode");
let opcode: Opcode = self.bytecode[*pc].into();
*pc += size_of::<Opcode>();
match opcode {
Opcode::SetFunctionName => {
@ -557,6 +557,62 @@ impl CodeBlock {
| Opcode::PopPrivateEnvironment
| Opcode::ImportCall
| Opcode::Nop => String::new(),
Opcode::Reserved1
| Opcode::Reserved2
| Opcode::Reserved3
| Opcode::Reserved4
| Opcode::Reserved5
| Opcode::Reserved6
| Opcode::Reserved7
| Opcode::Reserved8
| Opcode::Reserved9
| Opcode::Reserved10
| Opcode::Reserved11
| Opcode::Reserved12
| Opcode::Reserved13
| Opcode::Reserved14
| Opcode::Reserved15
| Opcode::Reserved16
| Opcode::Reserved17
| Opcode::Reserved18
| Opcode::Reserved19
| Opcode::Reserved20
| Opcode::Reserved21
| Opcode::Reserved22
| Opcode::Reserved23
| Opcode::Reserved24
| Opcode::Reserved25
| Opcode::Reserved26
| Opcode::Reserved27
| Opcode::Reserved28
| Opcode::Reserved29
| Opcode::Reserved30
| Opcode::Reserved31
| Opcode::Reserved32
| Opcode::Reserved33
| Opcode::Reserved34
| Opcode::Reserved35
| Opcode::Reserved36
| Opcode::Reserved37
| Opcode::Reserved38
| Opcode::Reserved39
| Opcode::Reserved40
| Opcode::Reserved41
| Opcode::Reserved42
| Opcode::Reserved43
| Opcode::Reserved44
| Opcode::Reserved45
| Opcode::Reserved46
| Opcode::Reserved47
| Opcode::Reserved48
| Opcode::Reserved49
| Opcode::Reserved50
| Opcode::Reserved51
| Opcode::Reserved52
| Opcode::Reserved53
| Opcode::Reserved54
| Opcode::Reserved55
| Opcode::Reserved56 => unreachable!("Reserved opcodes are unrechable"),
}
}
}
@ -579,7 +635,7 @@ impl ToInternedString for CodeBlock {
let mut pc = 0;
let mut count = 0;
while pc < self.bytecode.len() {
let opcode: Opcode = self.bytecode[pc].try_into().expect("invalid opcode");
let opcode: Opcode = self.bytecode[pc].into();
let opcode = opcode.as_str();
let previous_pc = pc;
let operands = self.instruction_operands(&mut pc, interner);

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

@ -32,7 +32,7 @@ impl CodeBlock {
let mut pc = 0;
while pc < self.bytecode.len() {
let opcode: Opcode = self.bytecode[pc].try_into().expect("invalid opcode");
let opcode: Opcode = self.bytecode[pc].into();
let opcode_str = opcode.as_str();
let previous_pc = pc;
@ -622,6 +622,62 @@ impl CodeBlock {
returns.push(previous_pc);
}
}
Opcode::Reserved1
| Opcode::Reserved2
| Opcode::Reserved3
| Opcode::Reserved4
| Opcode::Reserved5
| Opcode::Reserved6
| Opcode::Reserved7
| Opcode::Reserved8
| Opcode::Reserved9
| Opcode::Reserved10
| Opcode::Reserved11
| Opcode::Reserved12
| Opcode::Reserved13
| Opcode::Reserved14
| Opcode::Reserved15
| Opcode::Reserved16
| Opcode::Reserved17
| Opcode::Reserved18
| Opcode::Reserved19
| Opcode::Reserved20
| Opcode::Reserved21
| Opcode::Reserved22
| Opcode::Reserved23
| Opcode::Reserved24
| Opcode::Reserved25
| Opcode::Reserved26
| Opcode::Reserved27
| Opcode::Reserved28
| Opcode::Reserved29
| Opcode::Reserved30
| Opcode::Reserved31
| Opcode::Reserved32
| Opcode::Reserved33
| Opcode::Reserved34
| Opcode::Reserved35
| Opcode::Reserved36
| Opcode::Reserved37
| Opcode::Reserved38
| Opcode::Reserved39
| Opcode::Reserved40
| Opcode::Reserved41
| Opcode::Reserved42
| Opcode::Reserved43
| Opcode::Reserved44
| Opcode::Reserved45
| Opcode::Reserved46
| Opcode::Reserved47
| Opcode::Reserved48
| Opcode::Reserved49
| Opcode::Reserved50
| Opcode::Reserved51
| Opcode::Reserved52
| Opcode::Reserved53
| Opcode::Reserved54
| Opcode::Reserved55
| Opcode::Reserved56 => unreachable!("Reserved opcodes are unrechable"),
}
}

12
boa_engine/src/vm/mod.rs

@ -16,7 +16,7 @@ use crate::{
use boa_gc::{custom_trace, Finalize, Gc, Trace};
use boa_profiler::Profiler;
use std::{convert::TryInto, mem::size_of};
use std::mem::size_of;
#[cfg(feature = "trace")]
use boa_interner::ToInternedString;
@ -160,10 +160,12 @@ impl Context<'_> {
fn execute_instruction(&mut self) -> JsResult<CompletionType> {
let opcode: Opcode = {
let _timer = Profiler::global().start_event("Opcode retrieval", "vm");
let opcode = self.vm.frame().code_block.bytecode[self.vm.frame().pc as usize]
.try_into()
.expect("could not convert code at PC to opcode");
self.vm.frame_mut().pc += 1;
let frame = self.vm.frame_mut();
let pc = frame.pc;
let opcode = Opcode::from(frame.code_block.bytecode[pc as usize]);
frame.pc += 1;
opcode
};

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

@ -1,8 +1,6 @@
/// The opcodes of the vm.
use crate::{vm::CompletionType, Context, JsResult};
use num_enum::TryFromPrimitive;
// Operation modules
mod await_stm;
mod binary_ops;
@ -92,12 +90,15 @@ pub(crate) use unary_ops::*;
pub(crate) use value::*;
macro_rules! generate_impl {
( name $name:ident ) => { $name };
( name $name:ident => $mapping:ident ) => { $mapping };
(
$(#[$outer:meta])*
pub enum $Type:ident {
$(
$(#[$inner:ident $($args:tt)*])*
$Variant:ident $(= $index:expr)*
$Variant:ident $(=> $mapping:ident)? $(= $index:expr)*
),*
$(,)?
}
@ -111,22 +112,24 @@ macro_rules! generate_impl {
),*
}
impl $Type {
/// Create opcode from `u8` byte.
///
/// # Safety
///
/// Does not check if `u8` type is a valid `Opcode`.
#[must_use]
pub unsafe fn from_raw(value: u8) -> Self {
// Safety:
// The caller is responsible for ensuring that the value is a valid opcode.
unsafe { std::mem::transmute(value) }
impl From<u8> for Opcode {
#[inline]
#[allow(non_upper_case_globals)]
fn from(value: u8) -> Self {
$(
const $Variant: u8 = Opcode::$Variant as u8;
)*
match value {
$($Variant => Self::$Variant),*
}
}
}
impl $Type {
const MAX: usize = 2usize.pow(8);
const NAMES: &[&'static str] = &[
$($Variant::NAME),*
const NAMES: [&'static str; Self::MAX] = [
$(<generate_impl!(name $Variant $(=> $mapping)?)>::NAME),*
];
/// Name of this opcode.
@ -135,8 +138,8 @@ macro_rules! generate_impl {
Self::NAMES[self as usize]
}
const INSTRUCTIONS: &[&'static str] = &[
$($Variant::INSTRUCTION),*
const INSTRUCTIONS: [&'static str; Self::MAX] = [
$(<generate_impl!(name $Variant $(=> $mapping)?)>::INSTRUCTION),*
];
/// Name of the profiler event for this opcode.
@ -145,8 +148,8 @@ macro_rules! generate_impl {
Self::INSTRUCTIONS[self as usize]
}
const EXECUTE_FNS: &[fn(&mut Context<'_>) -> JsResult<CompletionType>] = &[
$($Variant::execute),*
const EXECUTE_FNS: [fn(&mut Context<'_>) -> JsResult<CompletionType>; Self::MAX] = [
$(<generate_impl!(name $Variant $(=> $mapping)?)>::execute),*
];
pub(super) fn execute(self, context: &mut Context<'_>) -> JsResult<CompletionType> {
@ -170,7 +173,7 @@ pub(crate) trait Operation {
}
generate_impl! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromPrimitive)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Opcode {
/// Pop the top value from the stack.
@ -1655,9 +1658,120 @@ generate_impl! {
/// Operands:
///
/// Stack: **=>**
// Safety: Must be last in the list since, we use this for range checking
// in `TryFrom<u8>` impl.
Nop,
/// Reserved [`Opcode`].
Reserved1 => Reserved,
/// Reserved [`Opcode`].
Reserved2 => Reserved,
/// Reserved [`Opcode`].
Reserved3 => Reserved,
/// Reserved [`Opcode`].
Reserved4 => Reserved,
/// Reserved [`Opcode`].
Reserved5 => Reserved,
/// Reserved [`Opcode`].
Reserved6 => Reserved,
/// Reserved [`Opcode`].
Reserved7 => Reserved,
/// Reserved [`Opcode`].
Reserved8 => Reserved,
/// Reserved [`Opcode`].
Reserved9 => Reserved,
/// Reserved [`Opcode`].
Reserved10 => Reserved,
/// Reserved [`Opcode`].
Reserved11 => Reserved,
/// Reserved [`Opcode`].
Reserved12 => Reserved,
/// Reserved [`Opcode`].
Reserved13 => Reserved,
/// Reserved [`Opcode`].
Reserved14 => Reserved,
/// Reserved [`Opcode`].
Reserved15 => Reserved,
/// Reserved [`Opcode`].
Reserved16 => Reserved,
/// Reserved [`Opcode`].
Reserved17 => Reserved,
/// Reserved [`Opcode`].
Reserved18 => Reserved,
/// Reserved [`Opcode`].
Reserved19 => Reserved,
/// Reserved [`Opcode`].
Reserved20 => Reserved,
/// Reserved [`Opcode`].
Reserved21 => Reserved,
/// Reserved [`Opcode`].
Reserved22 => Reserved,
/// Reserved [`Opcode`].
Reserved23 => Reserved,
/// Reserved [`Opcode`].
Reserved24 => Reserved,
/// Reserved [`Opcode`].
Reserved25 => Reserved,
/// Reserved [`Opcode`].
Reserved26 => Reserved,
/// Reserved [`Opcode`].
Reserved27 => Reserved,
/// Reserved [`Opcode`].
Reserved28 => Reserved,
/// Reserved [`Opcode`].
Reserved29 => Reserved,
/// Reserved [`Opcode`].
Reserved30 => Reserved,
/// Reserved [`Opcode`].
Reserved31 => Reserved,
/// Reserved [`Opcode`].
Reserved32 => Reserved,
/// Reserved [`Opcode`].
Reserved33 => Reserved,
/// Reserved [`Opcode`].
Reserved34 => Reserved,
/// Reserved [`Opcode`].
Reserved35 => Reserved,
/// Reserved [`Opcode`].
Reserved36 => Reserved,
/// Reserved [`Opcode`].
Reserved37 => Reserved,
/// Reserved [`Opcode`].
Reserved38 => Reserved,
/// Reserved [`Opcode`].
Reserved39 => Reserved,
/// Reserved [`Opcode`].
Reserved40 => Reserved,
/// Reserved [`Opcode`].
Reserved41 => Reserved,
/// Reserved [`Opcode`].
Reserved42 => Reserved,
/// Reserved [`Opcode`].
Reserved43 => Reserved,
/// Reserved [`Opcode`].
Reserved44 => Reserved,
/// Reserved [`Opcode`].
Reserved45 => Reserved,
/// Reserved [`Opcode`].
Reserved46 => Reserved,
/// Reserved [`Opcode`].
Reserved47 => Reserved,
/// Reserved [`Opcode`].
Reserved48 => Reserved,
/// Reserved [`Opcode`].
Reserved49 => Reserved,
/// Reserved [`Opcode`].
Reserved50 => Reserved,
/// Reserved [`Opcode`].
Reserved51 => Reserved,
/// Reserved [`Opcode`].
Reserved52 => Reserved,
/// Reserved [`Opcode`].
Reserved53 => Reserved,
/// Reserved [`Opcode`].
Reserved54 => Reserved,
/// Reserved [`Opcode`].
Reserved55 => Reserved,
/// Reserved [`Opcode`].
Reserved56 => Reserved,
}
}

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

@ -18,3 +18,19 @@ impl Operation for Nop {
Ok(CompletionType::Normal)
}
}
/// `Reserved` implements the Opcode Operation for `Opcode::Reserved`
///
/// Operation:
/// - Panics, this should be unreachable.
#[derive(Debug, Clone, Copy)]
pub(crate) struct Reserved;
impl Operation for Reserved {
const NAME: &'static str = "Reserved";
const INSTRUCTION: &'static str = "INST - Reserved";
fn execute(_: &mut Context<'_>) -> JsResult<CompletionType> {
unreachable!("Reserved opcodes are unreachable!")
}
}

Loading…
Cancel
Save