Skip to content
Draft
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
16 changes: 16 additions & 0 deletions third_party/move/mono-move/core/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ pub struct Function {
/// frames may scan the same memory. The forwarding markers in
/// `gc_copy_object` handle double-scans correctly.
pub frame_layout: FrameLayoutInfo,
/// Static gas cost of the entry basic block (block 0).
///
/// Charged at call time, before any instruction in block 0 executes
/// (charge-before-work). Set by [`mono_move_gas::GasInstrumentor::run`].
pub entry_gas: u64,
/// Per-safe-point frame layouts.
///
/// During GC, for each frame on the call stack, the GC scans the
Expand Down Expand Up @@ -222,6 +227,17 @@ impl Function {
unsafe { self.safe_point_layouts.layout_at(pc) }
}

/// Replaces every [`MicroOp::CallFunc`] (index-based dispatch) with
/// [`MicroOp::CallLocalFunc`] (direct pointer dispatch).
///
/// `func_ptrs` is indexed by definition index and may contain `None`
/// for functions that were not lowered (e.g. generic functions).
///
/// # Safety
///
/// The caller must have exclusive access to the functions and their
/// arena-allocated code. The arena must outlive all uses of the patched
/// code.
/// Replaces every [`MicroOp::CallFunc`] (index-based dispatch) with
/// [`MicroOp::CallLocalFunc`] (direct pointer dispatch).
///
Expand Down
132 changes: 57 additions & 75 deletions third_party/move/mono-move/core/src/instruction/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,7 @@
//! framework. Plug in a different ISA by writing an equivalent file.

use super::{CodeOffset, MicroOp};
use mono_move_gas::{GasMeteredInstruction, GasSchedule, HasCfgInfo, InstrCost, RemapTargets};

// ---------------------------------------------------------------------------
// GasMeteredInstruction
// ---------------------------------------------------------------------------

impl GasMeteredInstruction for MicroOp {
fn charge(cost: u64) -> Self {
MicroOp::Charge { cost }
}
}
use mono_move_gas::{ChargeOnJump, GasSchedule, HasCfgInfo};

// ---------------------------------------------------------------------------
// HasCfgInfo
Expand All @@ -27,7 +17,7 @@ impl GasMeteredInstruction for MicroOp {
impl HasCfgInfo for MicroOp {
fn branch_target(&self) -> Option<usize> {
match self {
MicroOp::Jump { target }
MicroOp::Jump { target, .. }
| MicroOp::JumpNotZeroU64 { target, .. }
| MicroOp::JumpGreaterEqualU64Imm { target, .. }
| MicroOp::JumpLessU64Imm { target, .. }
Expand Down Expand Up @@ -64,86 +54,81 @@ impl HasCfgInfo for MicroOp {
| MicroOp::HeapMoveTo8 { .. }
| MicroOp::HeapMoveToImm8 { .. }
| MicroOp::HeapMoveTo { .. }
| MicroOp::Charge { .. }
| MicroOp::StoreRandomU64 { .. }
| MicroOp::ForceGC => None,
}
}
}

// ---------------------------------------------------------------------------
// RemapTargets
// ChargeOnJump
// ---------------------------------------------------------------------------

impl RemapTargets for MicroOp {
fn remap_targets(self, remap: impl Fn(usize) -> usize) -> Self {
let co = |c: CodeOffset| CodeOffset(remap(c.0 as usize) as u32);
impl ChargeOnJump for MicroOp {
fn with_gas(self, taken: u64, fallthrough: u64) -> Self {
// Saturate to u32 for the conditional-jump gas fields.
// Block costs fit comfortably in u32 for any realistic program.
let gt = taken.min(u32::MAX as u64) as u32;
let gf = fallthrough.min(u32::MAX as u64) as u32;
let co = |c: CodeOffset| c; // no-op, just for symmetry
match self {
MicroOp::Jump { target } => MicroOp::Jump { target: co(target) },
MicroOp::JumpNotZeroU64 { target, src } => MicroOp::JumpNotZeroU64 {
MicroOp::Jump { target, .. } => MicroOp::Jump {
target: co(target),
src,
gas: taken,
},
MicroOp::JumpGreaterEqualU64Imm { target, src, imm } => {
MicroOp::JumpGreaterEqualU64Imm {
target: co(target),
src,
imm,
}
MicroOp::JumpNotZeroU64 { target, src, .. } => MicroOp::JumpNotZeroU64 {
target,
src,
gas_taken: gt,
gas_fallthrough: gf,
},
MicroOp::JumpLessU64 { target, lhs, rhs } => MicroOp::JumpLessU64 {
target: co(target),
lhs,
rhs,
MicroOp::JumpGreaterEqualU64Imm {
target, src, imm, ..
} => MicroOp::JumpGreaterEqualU64Imm {
target,
src,
imm,
gas_taken: gt,
gas_fallthrough: gf,
},
MicroOp::JumpLessU64Imm { target, src, imm } => MicroOp::JumpLessU64Imm {
target: co(target),
MicroOp::JumpLessU64Imm {
target, src, imm, ..
} => MicroOp::JumpLessU64Imm {
target,
src,
imm,
gas_taken: gt,
gas_fallthrough: gf,
},
MicroOp::JumpGreaterEqualU64 { target, lhs, rhs } => MicroOp::JumpGreaterEqualU64 {
target: co(target),
MicroOp::JumpLessU64 {
target, lhs, rhs, ..
} => MicroOp::JumpLessU64 {
target,
lhs,
rhs,
gas_taken: gt,
gas_fallthrough: gf,
},
MicroOp::JumpNotEqualU64 { target, lhs, rhs } => MicroOp::JumpNotEqualU64 {
target: co(target),
MicroOp::JumpGreaterEqualU64 {
target, lhs, rhs, ..
} => MicroOp::JumpGreaterEqualU64 {
target,
lhs,
rhs,
gas_taken: gt,
gas_fallthrough: gf,
},
op @ (MicroOp::StoreImm8 { .. }
| MicroOp::Move8 { .. }
| MicroOp::Move { .. }
| MicroOp::AddU64 { .. }
| MicroOp::AddU64Imm { .. }
| MicroOp::SubU64Imm { .. }
| MicroOp::RSubU64Imm { .. }
| MicroOp::XorU64 { .. }
| MicroOp::ShrU64Imm { .. }
| MicroOp::ModU64 { .. }
| MicroOp::Return
| MicroOp::CallFunc { .. }
| MicroOp::CallLocalFunc { .. }
| MicroOp::VecNew { .. }
| MicroOp::VecLen { .. }
| MicroOp::VecPushBack { .. }
| MicroOp::VecPopBack { .. }
| MicroOp::VecLoadElem { .. }
| MicroOp::VecStoreElem { .. }
| MicroOp::SlotBorrow { .. }
| MicroOp::VecBorrow { .. }
| MicroOp::HeapBorrow { .. }
| MicroOp::ReadRef { .. }
| MicroOp::WriteRef { .. }
| MicroOp::HeapNew { .. }
| MicroOp::HeapMoveFrom8 { .. }
| MicroOp::HeapMoveFrom { .. }
| MicroOp::HeapMoveTo8 { .. }
| MicroOp::HeapMoveToImm8 { .. }
| MicroOp::HeapMoveTo { .. }
| MicroOp::Charge { .. }
| MicroOp::StoreRandomU64 { .. }
| MicroOp::ForceGC) => op,
MicroOp::JumpNotEqualU64 {
target, lhs, rhs, ..
} => MicroOp::JumpNotEqualU64 {
target,
lhs,
rhs,
gas_taken: gt,
gas_fallthrough: gf,
},
// Non-jump instructions: no gas parameter to embed.
other => other,
}
}
}
Expand All @@ -158,8 +143,8 @@ impl RemapTargets for MicroOp {
pub struct MicroOpGasSchedule;

impl GasSchedule<MicroOp> for MicroOpGasSchedule {
fn cost(&self, instr: &MicroOp) -> InstrCost<MicroOp> {
InstrCost::constant(match instr {
fn cost(&self, instr: &MicroOp) -> u64 {
match instr {
// --- Data movement ---
MicroOp::StoreImm8 { .. } => 2,
MicroOp::Move8 { .. } => 2,
Expand Down Expand Up @@ -208,12 +193,9 @@ impl GasSchedule<MicroOp> for MicroOpGasSchedule {
2 + 3 * *size as u64
},

// --- Gas metering (inserted by instrumentation; not in input) ---
MicroOp::Charge { .. } => 0,

// --- Debug ---
MicroOp::StoreRandomU64 { .. } => 1,
MicroOp::ForceGC => 100,
})
}
}
}
Loading
Loading