Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Direct conversion from u8 to Opcode #2951

Merged
merged 1 commit into from
May 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 58 additions & 2 deletions boa_engine/src/vm/code_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down Expand Up @@ -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"),
}
}
}
Expand All @@ -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);
Expand Down
58 changes: 57 additions & 1 deletion boa_engine/src/vm/flowgraph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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"),
}
}

Expand Down
12 changes: 7 additions & 5 deletions boa_engine/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
};

Expand Down
162 changes: 138 additions & 24 deletions boa_engine/src/vm/opcode/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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)*
),*
$(,)?
}
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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> {
Expand All @@ -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.
Expand Down Expand Up @@ -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,
}
}

Expand Down
Loading