Singlular syscall context (#24204)
This commit is contained in:
parent
c1687b0604
commit
8a754d45b3
|
@ -30,7 +30,15 @@ use {
|
||||||
InstructionAccount, InstructionContext, TransactionAccount, TransactionContext,
|
InstructionAccount, InstructionContext, TransactionAccount, TransactionContext,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
std::{borrow::Cow, cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc, sync::Arc},
|
std::{
|
||||||
|
alloc::Layout,
|
||||||
|
borrow::Cow,
|
||||||
|
cell::RefCell,
|
||||||
|
collections::HashMap,
|
||||||
|
fmt::{self, Debug},
|
||||||
|
rc::Rc,
|
||||||
|
sync::Arc,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type ProcessInstructionWithContext =
|
pub type ProcessInstructionWithContext =
|
||||||
|
@ -150,10 +158,27 @@ impl ComputeMeter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Based loosely on the unstable std::alloc::Alloc trait
|
||||||
|
pub trait Alloc {
|
||||||
|
fn alloc(&mut self, layout: Layout) -> Result<u64, AllocErr>;
|
||||||
|
fn dealloc(&mut self, addr: u64, layout: Layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct AllocErr;
|
||||||
|
|
||||||
|
impl fmt::Display for AllocErr {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.write_str("Error: Memory allocation failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct StackFrame<'a> {
|
pub struct StackFrame<'a> {
|
||||||
pub number_of_program_accounts: usize,
|
pub number_of_program_accounts: usize,
|
||||||
pub keyed_accounts: Vec<KeyedAccount<'a>>,
|
pub keyed_accounts: Vec<KeyedAccount<'a>>,
|
||||||
pub keyed_accounts_range: std::ops::Range<usize>,
|
pub keyed_accounts_range: std::ops::Range<usize>,
|
||||||
|
pub orig_account_lengths: Option<Vec<usize>>,
|
||||||
|
pub allocator: Option<Rc<RefCell<dyn Alloc>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StackFrame<'a> {
|
impl<'a> StackFrame<'a> {
|
||||||
|
@ -166,6 +191,8 @@ impl<'a> StackFrame<'a> {
|
||||||
number_of_program_accounts,
|
number_of_program_accounts,
|
||||||
keyed_accounts,
|
keyed_accounts,
|
||||||
keyed_accounts_range,
|
keyed_accounts_range,
|
||||||
|
orig_account_lengths: None,
|
||||||
|
allocator: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +220,8 @@ pub struct InvokeContext<'a> {
|
||||||
pub timings: ExecuteDetailsTimings,
|
pub timings: ExecuteDetailsTimings,
|
||||||
pub blockhash: Hash,
|
pub blockhash: Hash,
|
||||||
pub lamports_per_signature: u64,
|
pub lamports_per_signature: u64,
|
||||||
|
pub check_aligned: bool,
|
||||||
|
pub check_size: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> InvokeContext<'a> {
|
impl<'a> InvokeContext<'a> {
|
||||||
|
@ -227,6 +256,8 @@ impl<'a> InvokeContext<'a> {
|
||||||
timings: ExecuteDetailsTimings::default(),
|
timings: ExecuteDetailsTimings::default(),
|
||||||
blockhash,
|
blockhash,
|
||||||
lamports_per_signature,
|
lamports_per_signature,
|
||||||
|
check_aligned: true,
|
||||||
|
check_size: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1048,6 +1079,63 @@ impl<'a> InvokeContext<'a> {
|
||||||
self.transaction_context
|
self.transaction_context
|
||||||
.get_key_of_account_at_index(index_in_transaction)
|
.get_key_of_account_at_index(index_in_transaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the original account lengths
|
||||||
|
pub fn set_orig_account_lengths(
|
||||||
|
&mut self,
|
||||||
|
orig_account_lengths: Vec<usize>,
|
||||||
|
) -> Result<(), InstructionError> {
|
||||||
|
let stack_frame = &mut self
|
||||||
|
.invoke_stack
|
||||||
|
.last_mut()
|
||||||
|
.ok_or(InstructionError::CallDepth)?;
|
||||||
|
stack_frame.orig_account_lengths = Some(orig_account_lengths);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the original account lengths
|
||||||
|
pub fn get_orig_account_lengths(&self) -> Result<&[usize], InstructionError> {
|
||||||
|
self.invoke_stack
|
||||||
|
.last()
|
||||||
|
.and_then(|frame| frame.orig_account_lengths.as_ref())
|
||||||
|
.ok_or(InstructionError::CallDepth)
|
||||||
|
.map(|orig_account_lengths| orig_account_lengths.as_slice())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_check_aligned(&mut self, check_aligned: bool) {
|
||||||
|
self.check_aligned = check_aligned;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_check_aligned(&self) -> bool {
|
||||||
|
self.check_aligned
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_check_size(&mut self, check_size: bool) {
|
||||||
|
self.check_size = check_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_check_size(&self) -> bool {
|
||||||
|
self.check_size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_allocator(
|
||||||
|
&mut self,
|
||||||
|
allocator: Rc<RefCell<dyn Alloc>>,
|
||||||
|
) -> Result<(), InstructionError> {
|
||||||
|
let stack_frame = &mut self
|
||||||
|
.invoke_stack
|
||||||
|
.last_mut()
|
||||||
|
.ok_or(InstructionError::CallDepth)?;
|
||||||
|
stack_frame.allocator = Some(allocator);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_allocator(&self) -> Result<Rc<RefCell<dyn Alloc>>, InstructionError> {
|
||||||
|
self.invoke_stack
|
||||||
|
.last()
|
||||||
|
.and_then(|frame| frame.allocator.clone())
|
||||||
|
.ok_or(InstructionError::CallDepth)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MockInvokeContextPreparation {
|
pub struct MockInvokeContextPreparation {
|
||||||
|
|
|
@ -115,7 +115,8 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
Executable::<BpfError, ThisInstructionMeter>::jit_compile(&mut executable).unwrap();
|
Executable::<BpfError, ThisInstructionMeter>::jit_compile(&mut executable).unwrap();
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
let mut vm = create_vm(&executable, &mut inner_iter, invoke_context, &[]).unwrap();
|
invoke_context.set_orig_account_lengths(vec![]).unwrap();
|
||||||
|
let mut vm = create_vm(&executable, &mut inner_iter, invoke_context).unwrap();
|
||||||
|
|
||||||
println!("Interpreted:");
|
println!("Interpreted:");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -219,6 +220,9 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
invoke_context
|
||||||
|
.set_orig_account_lengths(account_lengths)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
||||||
&elf,
|
&elf,
|
||||||
|
@ -229,13 +233,7 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
bencher.iter(|| {
|
bencher.iter(|| {
|
||||||
let _ = create_vm(
|
let _ = create_vm(&executable, serialized.as_slice_mut(), invoke_context).unwrap();
|
||||||
&executable,
|
|
||||||
serialized.as_slice_mut(),
|
|
||||||
invoke_context,
|
|
||||||
&account_lengths,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -270,13 +268,10 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
let mut vm = create_vm(
|
invoke_context
|
||||||
&executable,
|
.set_orig_account_lengths(account_lengths)
|
||||||
serialized.as_slice_mut(),
|
.unwrap();
|
||||||
invoke_context,
|
let mut vm = create_vm(&executable, serialized.as_slice_mut(), invoke_context).unwrap();
|
||||||
&account_lengths,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut measure = Measure::start("tune");
|
let mut measure = Measure::start("tune");
|
||||||
let _ = vm.execute_program_interpreted(&mut instruction_meter);
|
let _ = vm.execute_program_interpreted(&mut instruction_meter);
|
||||||
|
|
|
@ -245,13 +245,11 @@ fn run_program(name: &str) -> u64 {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut parameter_bytes = parameter_bytes.clone();
|
let mut parameter_bytes = parameter_bytes.clone();
|
||||||
{
|
{
|
||||||
let mut vm = create_vm(
|
invoke_context
|
||||||
&executable,
|
.set_orig_account_lengths(account_lengths.clone())
|
||||||
parameter_bytes.as_slice_mut(),
|
.unwrap();
|
||||||
invoke_context,
|
let mut vm =
|
||||||
&account_lengths,
|
create_vm(&executable, parameter_bytes.as_slice_mut(), invoke_context).unwrap();
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let result = if i == 0 {
|
let result = if i == 0 {
|
||||||
vm.execute_program_interpreted(&mut instruction_meter)
|
vm.execute_program_interpreted(&mut instruction_meter)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1418,7 +1416,7 @@ fn assert_instruction_count() {
|
||||||
#[cfg(feature = "bpf_c")]
|
#[cfg(feature = "bpf_c")]
|
||||||
{
|
{
|
||||||
programs.extend_from_slice(&[
|
programs.extend_from_slice(&[
|
||||||
("alloc", 1237),
|
("alloc", 11502),
|
||||||
("bpf_to_bpf", 313),
|
("bpf_to_bpf", 313),
|
||||||
("multiple_static", 208),
|
("multiple_static", 208),
|
||||||
("noop", 5),
|
("noop", 5),
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
use std::{alloc::Layout, fmt};
|
|
||||||
|
|
||||||
/// Based loosely on the unstable std::alloc::Alloc trait
|
|
||||||
pub trait Alloc {
|
|
||||||
fn alloc(&mut self, layout: Layout) -> Result<u64, AllocErr>;
|
|
||||||
fn dealloc(&mut self, addr: u64, layout: Layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
||||||
pub struct AllocErr;
|
|
||||||
|
|
||||||
impl fmt::Display for AllocErr {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
f.write_str("Error: Memory allocation failed")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,7 @@
|
||||||
#![allow(clippy::integer_arithmetic)]
|
#![allow(clippy::integer_arithmetic)]
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::alloc,
|
solana_program_runtime::invoke_context::{Alloc, AllocErr},
|
||||||
alloc::{Alloc, AllocErr},
|
|
||||||
solana_rbpf::aligned_memory::AlignedMemory,
|
solana_rbpf::aligned_memory::AlignedMemory,
|
||||||
std::alloc::Layout,
|
std::alloc::Layout,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#![deny(clippy::integer_arithmetic)]
|
#![deny(clippy::integer_arithmetic)]
|
||||||
#![deny(clippy::indexing_slicing)]
|
#![deny(clippy::indexing_slicing)]
|
||||||
|
|
||||||
pub mod alloc;
|
|
||||||
pub mod allocator_bump;
|
pub mod allocator_bump;
|
||||||
pub mod deprecated;
|
pub mod deprecated;
|
||||||
pub mod serialization;
|
pub mod serialization;
|
||||||
|
@ -234,7 +233,6 @@ pub fn create_vm<'a, 'b>(
|
||||||
program: &'a Pin<Box<Executable<BpfError, ThisInstructionMeter>>>,
|
program: &'a Pin<Box<Executable<BpfError, ThisInstructionMeter>>>,
|
||||||
parameter_bytes: &mut [u8],
|
parameter_bytes: &mut [u8],
|
||||||
invoke_context: &'a mut InvokeContext<'b>,
|
invoke_context: &'a mut InvokeContext<'b>,
|
||||||
orig_data_lens: &'a [usize],
|
|
||||||
) -> Result<EbpfVm<'a, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
|
) -> Result<EbpfVm<'a, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
|
||||||
let compute_budget = invoke_context.get_compute_budget();
|
let compute_budget = invoke_context.get_compute_budget();
|
||||||
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
|
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
|
||||||
|
@ -251,7 +249,7 @@ pub fn create_vm<'a, 'b>(
|
||||||
let mut heap =
|
let mut heap =
|
||||||
AlignedMemory::new_with_size(compute_budget.heap_size.unwrap_or(HEAP_LENGTH), HOST_ALIGN);
|
AlignedMemory::new_with_size(compute_budget.heap_size.unwrap_or(HEAP_LENGTH), HOST_ALIGN);
|
||||||
let mut vm = EbpfVm::new(program, heap.as_slice_mut(), parameter_bytes)?;
|
let mut vm = EbpfVm::new(program, heap.as_slice_mut(), parameter_bytes)?;
|
||||||
syscalls::bind_syscall_context_objects(&mut vm, invoke_context, heap, orig_data_lens)?;
|
syscalls::bind_syscall_context_objects(&mut vm, invoke_context, heap)?;
|
||||||
Ok(vm)
|
Ok(vm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1145,6 +1143,7 @@ impl Executor for BpfExecutor {
|
||||||
let (mut parameter_bytes, account_lengths) =
|
let (mut parameter_bytes, account_lengths) =
|
||||||
serialize_parameters(invoke_context.transaction_context, instruction_context)?;
|
serialize_parameters(invoke_context.transaction_context, instruction_context)?;
|
||||||
serialize_time.stop();
|
serialize_time.stop();
|
||||||
|
invoke_context.set_orig_account_lengths(account_lengths)?;
|
||||||
let mut create_vm_time = Measure::start("create_vm");
|
let mut create_vm_time = Measure::start("create_vm");
|
||||||
let mut execute_time;
|
let mut execute_time;
|
||||||
let execution_result = {
|
let execution_result = {
|
||||||
|
@ -1152,7 +1151,6 @@ impl Executor for BpfExecutor {
|
||||||
&self.executable,
|
&self.executable,
|
||||||
parameter_bytes.as_slice_mut(),
|
parameter_bytes.as_slice_mut(),
|
||||||
invoke_context,
|
invoke_context,
|
||||||
&account_lengths,
|
|
||||||
) {
|
) {
|
||||||
Ok(info) => info,
|
Ok(info) => info,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -1234,7 +1232,7 @@ impl Executor for BpfExecutor {
|
||||||
.transaction_context
|
.transaction_context
|
||||||
.get_current_instruction_context()?,
|
.get_current_instruction_context()?,
|
||||||
parameter_bytes.as_slice(),
|
parameter_bytes.as_slice(),
|
||||||
&account_lengths,
|
invoke_context.get_orig_account_lengths()?,
|
||||||
invoke_context
|
invoke_context
|
||||||
.feature_set
|
.feature_set
|
||||||
.is_active(&do_support_realloc::id()),
|
.is_active(&do_support_realloc::id()),
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -292,11 +292,13 @@ native machine code before execting it in the virtual machine.",
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
invoke_context
|
||||||
|
.set_orig_account_lengths(account_lengths)
|
||||||
|
.unwrap();
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(
|
||||||
&executable,
|
&executable,
|
||||||
parameter_bytes.as_slice_mut(),
|
parameter_bytes.as_slice_mut(),
|
||||||
&mut invoke_context,
|
&mut invoke_context,
|
||||||
&account_lengths,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
|
|
Loading…
Reference in New Issue