Skip to content

Commit

Permalink
feat: implement GAS, add some more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Mar 25, 2024
1 parent a3e86b2 commit 1f98137
Show file tree
Hide file tree
Showing 13 changed files with 492 additions and 169 deletions.
37 changes: 33 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ revm-interpreter = "3.4.0"

color-eyre = "0.6"
tracing = "0.1"
tracing-error = "0.2"
tracing-subscriber = "0.3"
61 changes: 51 additions & 10 deletions crates/revm-jit-core/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,25 +81,25 @@ impl EvmStack {
Vec::with_capacity(1024)
}

/// Creates a stack from a mutable vector.
/// Creates a stack from a vector's buffer.
///
/// # Panics
///
/// Panics if the vector's capacity is less than the stack size.
/// Panics if the vector's capacity is less than the required stack capacity.
#[inline]
pub fn from_vec(vec: &Vec<EvmWord>) -> &Self {
assert!(vec.capacity() >= Self::CAPACITY);
unsafe { &*vec.as_ptr().cast() }
unsafe { Self::from_ptr(vec.as_ptr()) }
}

/// Creates a stack from a mutable vector.
/// Creates a stack from a mutable vector's buffer.
///
/// The JIT'd function will overwrite the internal contents of the vector, and will not
/// set the length. This is simply to have the stack allocated on the heap.
///
/// # Panics
///
/// Panics if the vector's capacity is less than the stack size.
/// Panics if the vector's capacity is less than the required stack capacity.
///
/// # Examples
///
Expand All @@ -112,7 +112,51 @@ impl EvmStack {
#[inline]
pub fn from_mut_vec(vec: &mut Vec<EvmWord>) -> &mut Self {
assert!(vec.capacity() >= Self::CAPACITY);
unsafe { &mut *vec.as_mut_ptr().cast() }
unsafe { Self::from_mut_ptr(vec.as_mut_ptr()) }
}

/// Creates a stack from a slice.
///
/// # Panics
///
/// Panics if the slice's length is less than the required stack capacity.
#[inline]
pub const fn from_slice(slice: &[EvmWord]) -> &Self {
assert!(slice.len() >= Self::CAPACITY);
unsafe { Self::from_ptr(slice.as_ptr()) }
}

/// Creates a stack from a mutable slice.
///
/// # Panics
///
/// Panics if the slice's length is less than the required stack capacity.
#[inline]
pub fn from_mut_slice(slice: &mut [EvmWord]) -> &mut Self {
assert!(slice.len() >= Self::CAPACITY);
unsafe { Self::from_mut_ptr(slice.as_mut_ptr()) }
}

/// Creates a stack from a pointer.
///
/// # Safety
///
/// The caller must ensure that the pointer is valid and points to at least [`EvmStack::SIZE`]
/// bytes.
#[inline]
pub const unsafe fn from_ptr<'a>(ptr: *const EvmWord) -> &'a Self {
&*ptr.cast()
}

/// Creates a stack from a mutable pointer.
///
/// # Safety
///
/// The caller must ensure that the pointer is valid and points to at least [`EvmStack::SIZE`]
/// bytes.
#[inline]
pub unsafe fn from_mut_ptr<'a>(ptr: *mut EvmWord) -> &'a mut Self {
&mut *ptr.cast()
}

/// Returns the stack as a byte array.
Expand Down Expand Up @@ -168,10 +212,7 @@ fmt_impl!(Binary);
impl From<U256> for EvmWord {
#[inline]
fn from(value: U256) -> Self {
#[cfg(target_endian = "little")]
return unsafe { std::mem::transmute(value) };
#[cfg(target_endian = "big")]
return Self(value.to_be_bytes());
Self::from_u256(value)
}
}

Expand Down
14 changes: 6 additions & 8 deletions crates/revm-jit-core/src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
/// Log the time it takes to execute the given expression.
#[macro_export]
macro_rules! time {
($level:expr, $what:literal, || $e:expr) => {{
let res;
let mut e = || $e;
($level:expr, $what:literal, || $e:expr) => {
if $crate::private::tracing::enabled!($level) {
let timer = std::time::Instant::now();
res = e();
let res = $e;
// $crate::private::tracing::event!($level, elapsed=?timer.elapsed(), $what);
$crate::private::tracing::event!($level, "{:<16} {:?}", $what, timer.elapsed());
$crate::private::tracing::event!($level, "{:<30} {:?}", $what, timer.elapsed());
res
} else {
res = e();
$e
}
res
}};
};
}

/// Log the time it takes to execute the given expression at `debug` level.
Expand Down
2 changes: 2 additions & 0 deletions crates/revm-jit-core/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pub trait Builder: BackendTypes + TypeMethods {
fn create_block_after(&mut self, after: Self::BasicBlock, name: &str) -> Self::BasicBlock;
fn switch_to_block(&mut self, block: Self::BasicBlock);
fn seal_block(&mut self, block: Self::BasicBlock);
fn seal_all_blocks(&mut self);
fn set_cold_block(&mut self, block: Self::BasicBlock);
fn current_block(&mut self) -> Option<Self::BasicBlock>;

Expand Down Expand Up @@ -165,6 +166,7 @@ pub trait Builder: BackendTypes + TypeMethods {
fn sext(&mut self, ty: Self::Type, value: Self::Value) -> Self::Value;

fn gep(&mut self, ty: Self::Type, ptr: Self::Value, offset: Self::Value) -> Self::Value;
fn extract_value(&mut self, value: Self::Value, index: u32) -> Self::Value;

fn call(&mut self, function: Self::Function, args: &[Self::Value]) -> Option<Self::Value>;

Expand Down
12 changes: 12 additions & 0 deletions crates/revm-jit-cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,10 @@ impl<'a> Builder for JitEvmCraneliftBuilder<'a> {
self.bcx.seal_block(block);
}

fn seal_all_blocks(&mut self) {
self.bcx.seal_all_blocks();
}

fn set_cold_block(&mut self, block: Self::BasicBlock) {
self.bcx.set_cold_block(block);
}
Expand Down Expand Up @@ -528,6 +532,14 @@ impl<'a> Builder for JitEvmCraneliftBuilder<'a> {
self.bcx.ins().iadd(ptr, offset)
}

fn extract_value(&mut self, value: Self::Value, index: u32) -> Self::Value {
// let offset = self.bcx.func.dfg.value_type(value).bytes() as i64 * index as i64;
// self.bcx.ins().iadd_imm(value, offset)
let _ = value;
let _ = index;
todo!()
}

fn call(&mut self, function: Self::Function, args: &[Self::Value]) -> Option<Self::Value> {
let ins = self.bcx.ins().call(function, args);
self.bcx.inst_results(ins).first().copied()
Expand Down
8 changes: 8 additions & 0 deletions crates/revm-jit-llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,10 @@ impl<'a, 'ctx> Builder for JitEvmLlvmBuilder<'a, 'ctx> {
// Nothing to do.
}

fn seal_all_blocks(&mut self) {
// Nothing to do.
}

fn set_cold_block(&mut self, block: Self::BasicBlock) {
let prev = self.current_block();
self.switch_to_block(block);
Expand Down Expand Up @@ -659,6 +663,10 @@ impl<'a, 'ctx> Builder for JitEvmLlvmBuilder<'a, 'ctx> {
.into()
}

fn extract_value(&mut self, value: Self::Value, index: u32) -> Self::Value {
self.bcx.build_extract_value(value.into_struct_value(), index, "").unwrap()
}

fn call(&mut self, function: Self::Function, args: &[Self::Value]) -> Option<Self::Value> {
let args = args.iter().copied().map(Into::into).collect::<Vec<_>>();
let callsite = self.bcx.build_call(function, &args, "").unwrap();
Expand Down
3 changes: 2 additions & 1 deletion crates/revm-jit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ bitflags = "2.5"
bitvec = "1"
color-eyre.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
tracing-error.workspace = true
tracing-subscriber = { workspace = true, features = ["fmt", "env-filter"]}

[dev-dependencies]
criterion = "0.5"
Expand Down
6 changes: 3 additions & 3 deletions crates/revm-jit/src/bytecode/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl OpcodeInfo {
}
}

/// Returns the static gas map for the given spec ID.
/// Returns the static gas map for the given spec_id ID.
///
/// The map will contain the gas costs for each opcode if it is known statically, or `0` if the
/// opcode is not known or its gas cost is dynamic.
Expand All @@ -97,11 +97,11 @@ const fn make_map(spec_id: SpecId) -> [OpcodeInfo; 256] {

let mut map = [OpcodeInfo(OpcodeInfo::UNKNOWN); 256];
macro_rules! set {
($($op:ident = $gas:expr $(, if $spec:ident)? ;)*) => {
($($op:ident = $gas:expr $(, if $spec_id:ident)? ;)*) => {
$(
let mut g = $gas;
$(
if (spec_id as u8) < SpecId::$spec as u8 {
if (spec_id as u8) < SpecId::$spec_id as u8 {
g |= OpcodeInfo::DISABLED;
}
)?
Expand Down
Loading

0 comments on commit 1f98137

Please sign in to comment.