Skip to content

Commit

Permalink
WIP: use explicit pool for stack/heap
Browse files Browse the repository at this point in the history
  • Loading branch information
alessandrod committed May 29, 2024
1 parent 517e358 commit e766ff8
Show file tree
Hide file tree
Showing 11 changed files with 439 additions and 32 deletions.
3 changes: 1 addition & 2 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,8 @@ solana-zk-keygen = { path = "zk-keygen", version = "=2.0.0" }
solana-zk-sdk = { path = "zk-sdk", version = "=2.0.0" }
solana-zk-token-proof-program = { path = "programs/zk-token-proof", version = "=2.0.0" }
solana-zk-token-sdk = { path = "zk-token-sdk", version = "=2.0.0" }
solana_rbpf = "=0.8.0"
#solana_rbpf = "=0.8.0"
solana_rbpf = { git = "https://github.com/alessandrod/rbpf", branch = "builtin-mock-call-depth-0.8" }
spl-associated-token-account = "=3.0.2"
spl-instruction-padding = "0.1"
spl-memo = "=4.0.1"
Expand Down
2 changes: 1 addition & 1 deletion ledger-tool/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ pub fn program(ledger_path: &Path, matches: &ArgMatches<'_>) {
account_lengths,
&mut invoke_context,
);
let mut vm = vm.unwrap();
let (mut vm, _, _) = vm.unwrap();
let start_time = Instant::now();
if matches.value_of("mode").unwrap() == "debugger" {
vm.debug_port = Some(matches.value_of("port").unwrap().parse::<u16>().unwrap());
Expand Down
7 changes: 5 additions & 2 deletions program-runtime/src/compute_budget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ impl ::solana_frozen_abi::abi_example::AbiExample for ComputeBudget {
/// default heap page cost = 0.5 * 15 ~= 8CU/page
pub const DEFAULT_HEAP_COST: u64 = 8;

pub const MAX_CALL_DEPTH: usize = 64;
pub const STACK_FRAME_SIZE: usize = 4096;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ComputeBudget {
/// Number of compute units that a transaction or individual instruction is
Expand Down Expand Up @@ -140,8 +143,8 @@ impl ComputeBudget {
sha256_base_cost: 85,
sha256_byte_cost: 1,
sha256_max_slices: 20_000,
max_call_depth: 64,
stack_frame_size: 4_096,
max_call_depth: MAX_CALL_DEPTH,
stack_frame_size: STACK_FRAME_SIZE,
log_pubkey_units: 100,
max_cpi_instruction_size: 1280, // IPv6 Min MTU size
cpi_bytes_per_unit: 250, // ~50MB at 200,000 units
Expand Down
2 changes: 1 addition & 1 deletion program-runtime/src/compute_budget_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use {
},
};

const MAX_HEAP_FRAME_BYTES: u32 = 256 * 1024;
pub const MAX_HEAP_FRAME_BYTES: u32 = 256 * 1024;
pub const DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT: u32 = 200_000;
pub const MAX_COMPUTE_UNIT_LIMIT: u32 = 1_400_000;

Expand Down
50 changes: 30 additions & 20 deletions programs/bpf_loader/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#![deny(clippy::arithmetic_side_effects)]
#![deny(clippy::indexing_slicing)]

pub mod mem_pool;
pub mod serialization;
pub mod syscalls;

use {
mem_pool::VmMemoryPool,
solana_measure::measure::Measure,
solana_program_runtime::{
ic_logger_msg, ic_msg,
Expand All @@ -18,9 +20,8 @@ use {
sysvar_cache::get_sysvar_with_account_check,
},
solana_rbpf::{
aligned_memory::AlignedMemory,
declare_builtin_function,
ebpf::{self, HOST_ALIGN, MM_HEAP_START},
ebpf::{self, MM_HEAP_START},
elf::Executable,
error::{EbpfError, ProgramResult},
memory_region::{AccessType, MemoryCowCallback, MemoryMapping, MemoryRegion},
Expand Down Expand Up @@ -59,6 +60,10 @@ pub const DEFAULT_LOADER_COMPUTE_UNITS: u64 = 570;
pub const DEPRECATED_LOADER_COMPUTE_UNITS: u64 = 1_140;
pub const UPGRADEABLE_LOADER_COMPUTE_UNITS: u64 = 2_370;

thread_local! {
pub static MEMORY_POOL: RefCell<VmMemoryPool> = RefCell::new(VmMemoryPool::new());
}

#[allow(clippy::too_many_arguments)]
pub fn load_program_from_bytes(
log_collector: Option<Rc<RefCell<LogCollector>>>,
Expand Down Expand Up @@ -244,8 +249,8 @@ pub fn create_vm<'a, 'b>(
regions: Vec<MemoryRegion>,
accounts_metadata: Vec<SerializedAccountMetadata>,
invoke_context: &'a mut InvokeContext<'b>,
stack: &mut AlignedMemory<HOST_ALIGN>,
heap: &mut AlignedMemory<HOST_ALIGN>,
stack: &mut [u8],
heap: &mut [u8],
) -> Result<EbpfVm<'a, InvokeContext<'b>>, Box<dyn std::error::Error>> {
let stack_size = stack.len();
let heap_size = heap.len();
Expand Down Expand Up @@ -299,24 +304,23 @@ macro_rules! create_vm {
heap_size,
invoke_context.get_compute_budget().heap_cost,
));
let mut allocations = None;
let $vm = heap_cost_result.and_then(|_| {
let mut stack = solana_rbpf::aligned_memory::AlignedMemory::<
{ solana_rbpf::ebpf::HOST_ALIGN },
>::zero_filled(stack_size);
let mut heap = solana_rbpf::aligned_memory::AlignedMemory::<
{ solana_rbpf::ebpf::HOST_ALIGN },
>::zero_filled(usize::try_from(heap_size).unwrap());
let (mut stack, mut heap) = $crate::MEMORY_POOL
.with_borrow_mut(|pool| (pool.get_stack(stack_size), pool.get_heap(heap_size)));
let vm = $crate::create_vm(
$program,
$regions,
$accounts_metadata,
$invoke_context,
&mut stack,
&mut heap,
stack
.as_slice_mut()
.get_mut(..stack_size)
.expect("invalid stack size"),
heap.as_slice_mut()
.get_mut(..heap_size as usize)
.expect("invalid heap size"),
);
allocations = Some((stack, heap));
vm
vm.map(|vm| (vm, stack, heap))
});
};
}
Expand All @@ -343,13 +347,14 @@ macro_rules! mock_create_vm {
$accounts_metadata,
$invoke_context,
);
let $vm = $vm.map(|(vm, _, _)| vm);
};
}

fn create_memory_mapping<'a, 'b, C: ContextObject>(
executable: &'a Executable<C>,
stack: &'b mut AlignedMemory<{ HOST_ALIGN }>,
heap: &'b mut AlignedMemory<{ HOST_ALIGN }>,
stack: &'b mut [u8],
heap: &'b mut [u8],
additional_regions: Vec<MemoryRegion>,
cow_cb: Option<MemoryCowCallback>,
) -> Result<MemoryMapping<'a>, Box<dyn std::error::Error>> {
Expand All @@ -358,15 +363,15 @@ fn create_memory_mapping<'a, 'b, C: ContextObject>(
let regions: Vec<MemoryRegion> = vec![
executable.get_ro_region(),
MemoryRegion::new_writable_gapped(
stack.as_slice_mut(),
stack,
ebpf::MM_STACK_START,
if !sbpf_version.dynamic_stack_frames() && config.enable_stack_frame_gaps {
config.stack_frame_size as u64
} else {
0
},
),
MemoryRegion::new_writable(heap.as_slice_mut(), MM_HEAP_START),
MemoryRegion::new_writable(heap, MM_HEAP_START),
]
.into_iter()
.chain(additional_regions)
Expand Down Expand Up @@ -1385,7 +1390,7 @@ fn execute<'a, 'b: 'a>(
let execution_result = {
let compute_meter_prev = invoke_context.get_remaining();
create_vm!(vm, executable, regions, accounts_metadata, invoke_context,);
let mut vm = match vm {
let (mut vm, stack, heap) = match vm {
Ok(info) => info,
Err(e) => {
ic_logger_msg!(log_collector, "Failed to create SBF VM: {}", e);
Expand All @@ -1396,6 +1401,11 @@ fn execute<'a, 'b: 'a>(

execute_time = Measure::start("execute");
let (compute_units_consumed, result) = vm.execute_program(executable, !use_jit);
MEMORY_POOL.with_borrow_mut(|memory_pool| {
memory_pool.put_stack(stack);
memory_pool.put_heap(heap);
memory_pool.shrink_if_needed();
});
drop(vm);
ic_logger_msg!(
log_collector,
Expand Down
Loading

0 comments on commit e766ff8

Please sign in to comment.