mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-17 16:44:19 +01:00
introduce instruction virtual table
This commit is contained in:
@@ -412,7 +412,8 @@ impl CompiledExpression {
|
||||
// Execute the program
|
||||
let mut pc = 0usize;
|
||||
while pc < program.insns.len() {
|
||||
let (insn, insn_fn) = &program.insns[pc];
|
||||
let (insn, _) = &program.insns[pc];
|
||||
let insn_fn = insn.to_function_fast();
|
||||
state.pc = pc as u32;
|
||||
|
||||
// Execute the instruction
|
||||
|
||||
@@ -64,7 +64,7 @@ impl CheckpointResult {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, EnumString)]
|
||||
#[derive(Debug, Copy, Clone, Default, EnumString)]
|
||||
#[strum(ascii_case_insensitive)]
|
||||
pub enum CheckpointMode {
|
||||
/// Checkpoint as many frames as possible without waiting for any database readers or writers to finish, then sync the database file if all frames in the log were checkpointed.
|
||||
@@ -73,6 +73,7 @@ pub enum CheckpointMode {
|
||||
/// Optional upper_bound_inclusive parameter can be set in order to checkpoint frames with number no larger than the parameter
|
||||
Passive { upper_bound_inclusive: Option<u64> },
|
||||
/// This mode blocks until there is no database writer and all readers are reading from the most recent database snapshot. It then checkpoints all frames in the log file and syncs the database file. This mode blocks new database writers while it is pending, but new database readers are allowed to continue unimpeded.
|
||||
#[default]
|
||||
Full,
|
||||
/// This mode works the same way as `Full` with the addition that after checkpointing the log file it blocks (calls the busy-handler callback) until all readers are reading from the database file only. This ensures that the next writer will restart the log file from the beginning. Like `Full`, this mode blocks new database writer attempts while it is pending, but does not impede readers.
|
||||
Restart,
|
||||
|
||||
@@ -34,7 +34,7 @@ impl TableRefIdCounter {
|
||||
}
|
||||
}
|
||||
|
||||
use super::{BranchOffset, CursorID, Insn, InsnFunction, InsnReference, JumpTarget, Program};
|
||||
use super::{BranchOffset, CursorID, Insn, InsnReference, JumpTarget, Program};
|
||||
|
||||
/// A key that uniquely identifies a cursor.
|
||||
/// The key is a pair of table reference id and index.
|
||||
@@ -85,7 +85,7 @@ pub struct ProgramBuilder {
|
||||
next_free_register: usize,
|
||||
next_free_cursor_id: usize,
|
||||
/// Instruction, the function to execute it with, and its original index in the vector.
|
||||
insns: Vec<(Insn, InsnFunction, usize)>,
|
||||
insns: Vec<(Insn, usize)>,
|
||||
/// A span of instructions from (offset_start_inclusive, offset_end_exclusive),
|
||||
/// that are deemed to be compile-time constant and can be hoisted out of loops
|
||||
/// so that they get evaluated only once at the start of the program.
|
||||
@@ -328,10 +328,9 @@ impl ProgramBuilder {
|
||||
|
||||
#[instrument(skip(self), level = Level::DEBUG)]
|
||||
pub fn emit_insn(&mut self, insn: Insn) {
|
||||
let function = insn.to_function();
|
||||
// This seemingly empty trace here is needed so that a function span is emmited with it
|
||||
tracing::trace!("");
|
||||
self.insns.push((insn, function, self.insns.len()));
|
||||
self.insns.push((insn, self.insns.len()));
|
||||
}
|
||||
|
||||
pub fn close_cursors(&mut self, cursors: &[CursorID]) {
|
||||
@@ -419,7 +418,7 @@ impl ProgramBuilder {
|
||||
pub fn pop_current_parent_explain(&mut self) {
|
||||
if let QueryMode::ExplainQueryPlan = self.query_mode {
|
||||
if let Some(current) = self.current_parent_explain_idx {
|
||||
let (Insn::Explain { p2, .. }, _, _) = &self.insns[current] else {
|
||||
let (Insn::Explain { p2, .. }, _) = &self.insns[current] else {
|
||||
unreachable!("current_parent_explain_idx must point to an Explain insn");
|
||||
};
|
||||
self.current_parent_explain_idx = *p2;
|
||||
@@ -447,7 +446,7 @@ impl ProgramBuilder {
|
||||
// 1. if insn not in any constant span, it stays where it is
|
||||
// 2. if insn is in a constant span, it is after other insns, except those that are in a later constant span
|
||||
// 3. within a single constant span the order is preserver
|
||||
self.insns.sort_by(|(_, _, index_a), (_, _, index_b)| {
|
||||
self.insns.sort_by(|(_, index_a), (_, index_b)| {
|
||||
let a_span = self
|
||||
.constant_spans
|
||||
.iter()
|
||||
@@ -471,7 +470,7 @@ impl ProgramBuilder {
|
||||
let new_offset = self
|
||||
.insns
|
||||
.iter()
|
||||
.position(|(_, _, index)| *old_offset == *index as u32)
|
||||
.position(|(_, index)| *old_offset == *index as u32)
|
||||
.unwrap() as u32;
|
||||
*resolved_offset = Some((new_offset, *target));
|
||||
}
|
||||
@@ -482,7 +481,7 @@ impl ProgramBuilder {
|
||||
let new_offset = self
|
||||
.insns
|
||||
.iter()
|
||||
.position(|(_, _, index)| *old_offset == *index as u32)
|
||||
.position(|(_, index)| *old_offset == *index as u32)
|
||||
.expect("comment must exist") as u32;
|
||||
*old_offset = new_offset;
|
||||
}
|
||||
@@ -492,25 +491,23 @@ impl ProgramBuilder {
|
||||
if let Some(old_parent) = self.current_parent_explain_idx {
|
||||
self.insns
|
||||
.iter()
|
||||
.position(|(_, _, index)| old_parent == *index)
|
||||
.position(|(_, index)| old_parent == *index)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
for i in 0..self.insns.len() {
|
||||
let (Insn::Explain { p2, .. }, _, _) = &self.insns[i] else {
|
||||
let (Insn::Explain { p2, .. }, _) = &self.insns[i] else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let new_p2 = if p2.is_some() {
|
||||
self.insns
|
||||
.iter()
|
||||
.position(|(_, _, index)| *p2 == Some(*index))
|
||||
self.insns.iter().position(|(_, index)| *p2 == Some(*index))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let (Insn::Explain { p1, p2, .. }, _, _) = &mut self.insns[i] else {
|
||||
let (Insn::Explain { p1, p2, .. }, _) = &mut self.insns[i] else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
@@ -591,7 +588,7 @@ impl ProgramBuilder {
|
||||
);
|
||||
}
|
||||
};
|
||||
for (insn, _, _) in self.insns.iter_mut() {
|
||||
for (insn, _) in self.insns.iter_mut() {
|
||||
match insn {
|
||||
Insn::Init { target_pc } => {
|
||||
resolve(target_pc, "Init");
|
||||
@@ -997,11 +994,7 @@ impl ProgramBuilder {
|
||||
self.parameters.list.dedup();
|
||||
Program {
|
||||
max_registers: self.next_free_register,
|
||||
insns: self
|
||||
.insns
|
||||
.into_iter()
|
||||
.map(|(insn, function, _)| (insn, function))
|
||||
.collect(),
|
||||
insns: self.insns,
|
||||
cursor_ref: self.cursor_ref,
|
||||
comments: self.comments,
|
||||
connection,
|
||||
|
||||
@@ -10,6 +10,10 @@ use crate::{
|
||||
translate::{collate::CollationSeq, emitter::TransactionMode},
|
||||
Value,
|
||||
};
|
||||
use std::sync::LazyLock;
|
||||
use strum::EnumCount;
|
||||
use strum::VariantArray as _;
|
||||
use strum_macros::{EnumDiscriminants, VariantArray};
|
||||
use turso_macros::Description;
|
||||
use turso_parser::ast::SortOrder;
|
||||
|
||||
@@ -150,7 +154,11 @@ impl<T: Copy + std::fmt::Display> std::fmt::Display for RegisterOrLiteral<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Description, Debug)]
|
||||
#[derive(Description, Debug, EnumDiscriminants)]
|
||||
#[strum_discriminants(vis(pub(crate)))]
|
||||
#[strum_discriminants(derive(VariantArray, EnumCount))]
|
||||
#[strum_discriminants(repr(u8))]
|
||||
#[strum_discriminants(name(InsnVariants))]
|
||||
pub enum Insn {
|
||||
/// Initialize the program state and jump to the given PC.
|
||||
Init {
|
||||
@@ -1095,147 +1103,175 @@ pub enum Insn {
|
||||
},
|
||||
}
|
||||
|
||||
impl Insn {
|
||||
pub fn to_function(&self) -> InsnFunction {
|
||||
static INSN_VIRTUAL_TABLE: LazyLock<[InsnFunction; InsnVariants::COUNT]> = LazyLock::new(|| {
|
||||
let mut result: [InsnFunction; InsnVariants::COUNT] = [execute::op_null; InsnVariants::COUNT];
|
||||
|
||||
for variant in InsnVariants::VARIANTS {
|
||||
result[*variant as u8 as usize] = variant.to_function();
|
||||
}
|
||||
|
||||
result
|
||||
});
|
||||
|
||||
impl InsnVariants {
|
||||
pub(crate) fn to_function_fast(&self) -> InsnFunction {
|
||||
INSN_VIRTUAL_TABLE[*self as u8 as usize]
|
||||
}
|
||||
|
||||
pub(crate) fn to_function(&self) -> InsnFunction {
|
||||
match self {
|
||||
Insn::Init { .. } => execute::op_init,
|
||||
Insn::Null { .. } => execute::op_null,
|
||||
Insn::BeginSubrtn { .. } => execute::op_null,
|
||||
Insn::NullRow { .. } => execute::op_null_row,
|
||||
Insn::Add { .. } => execute::op_add,
|
||||
Insn::Subtract { .. } => execute::op_subtract,
|
||||
Insn::Multiply { .. } => execute::op_multiply,
|
||||
Insn::Divide { .. } => execute::op_divide,
|
||||
Insn::DropIndex { .. } => execute::op_drop_index,
|
||||
Insn::Compare { .. } => execute::op_compare,
|
||||
Insn::BitAnd { .. } => execute::op_bit_and,
|
||||
Insn::BitOr { .. } => execute::op_bit_or,
|
||||
Insn::BitNot { .. } => execute::op_bit_not,
|
||||
Insn::Checkpoint { .. } => execute::op_checkpoint,
|
||||
Insn::Remainder { .. } => execute::op_remainder,
|
||||
Insn::Jump { .. } => execute::op_jump,
|
||||
Insn::Move { .. } => execute::op_move,
|
||||
Insn::IfPos { .. } => execute::op_if_pos,
|
||||
Insn::NotNull { .. } => execute::op_not_null,
|
||||
Insn::Eq { .. }
|
||||
| Insn::Ne { .. }
|
||||
| Insn::Lt { .. }
|
||||
| Insn::Le { .. }
|
||||
| Insn::Gt { .. }
|
||||
| Insn::Ge { .. } => execute::op_comparison,
|
||||
Insn::If { .. } => execute::op_if,
|
||||
Insn::IfNot { .. } => execute::op_if_not,
|
||||
Insn::OpenRead { .. } => execute::op_open_read,
|
||||
Insn::VOpen { .. } => execute::op_vopen,
|
||||
Insn::VCreate { .. } => execute::op_vcreate,
|
||||
Insn::VFilter { .. } => execute::op_vfilter,
|
||||
Insn::VColumn { .. } => execute::op_vcolumn,
|
||||
Insn::VUpdate { .. } => execute::op_vupdate,
|
||||
Insn::VNext { .. } => execute::op_vnext,
|
||||
Insn::VDestroy { .. } => execute::op_vdestroy,
|
||||
InsnVariants::Init { .. } => execute::op_init,
|
||||
InsnVariants::Null { .. } => execute::op_null,
|
||||
InsnVariants::BeginSubrtn { .. } => execute::op_null,
|
||||
InsnVariants::NullRow { .. } => execute::op_null_row,
|
||||
InsnVariants::Add { .. } => execute::op_add,
|
||||
InsnVariants::Subtract { .. } => execute::op_subtract,
|
||||
InsnVariants::Multiply { .. } => execute::op_multiply,
|
||||
InsnVariants::Divide { .. } => execute::op_divide,
|
||||
InsnVariants::DropIndex { .. } => execute::op_drop_index,
|
||||
InsnVariants::Compare { .. } => execute::op_compare,
|
||||
InsnVariants::BitAnd { .. } => execute::op_bit_and,
|
||||
InsnVariants::BitOr { .. } => execute::op_bit_or,
|
||||
InsnVariants::BitNot { .. } => execute::op_bit_not,
|
||||
InsnVariants::Checkpoint { .. } => execute::op_checkpoint,
|
||||
InsnVariants::Remainder { .. } => execute::op_remainder,
|
||||
InsnVariants::Jump { .. } => execute::op_jump,
|
||||
InsnVariants::Move { .. } => execute::op_move,
|
||||
InsnVariants::IfPos { .. } => execute::op_if_pos,
|
||||
InsnVariants::NotNull { .. } => execute::op_not_null,
|
||||
InsnVariants::Eq { .. }
|
||||
| InsnVariants::Ne { .. }
|
||||
| InsnVariants::Lt { .. }
|
||||
| InsnVariants::Le { .. }
|
||||
| InsnVariants::Gt { .. }
|
||||
| InsnVariants::Ge { .. } => execute::op_comparison,
|
||||
InsnVariants::If { .. } => execute::op_if,
|
||||
InsnVariants::IfNot { .. } => execute::op_if_not,
|
||||
InsnVariants::OpenRead { .. } => execute::op_open_read,
|
||||
InsnVariants::VOpen { .. } => execute::op_vopen,
|
||||
InsnVariants::VCreate { .. } => execute::op_vcreate,
|
||||
InsnVariants::VFilter { .. } => execute::op_vfilter,
|
||||
InsnVariants::VColumn { .. } => execute::op_vcolumn,
|
||||
InsnVariants::VUpdate { .. } => execute::op_vupdate,
|
||||
InsnVariants::VNext { .. } => execute::op_vnext,
|
||||
InsnVariants::VDestroy { .. } => execute::op_vdestroy,
|
||||
|
||||
Insn::OpenPseudo { .. } => execute::op_open_pseudo,
|
||||
Insn::Rewind { .. } => execute::op_rewind,
|
||||
Insn::Last { .. } => execute::op_last,
|
||||
Insn::Column { .. } => execute::op_column,
|
||||
Insn::TypeCheck { .. } => execute::op_type_check,
|
||||
Insn::MakeRecord { .. } => execute::op_make_record,
|
||||
Insn::ResultRow { .. } => execute::op_result_row,
|
||||
Insn::Next { .. } => execute::op_next,
|
||||
Insn::Prev { .. } => execute::op_prev,
|
||||
Insn::Halt { .. } => execute::op_halt,
|
||||
Insn::HaltIfNull { .. } => execute::op_halt_if_null,
|
||||
Insn::Transaction { .. } => execute::op_transaction,
|
||||
Insn::AutoCommit { .. } => execute::op_auto_commit,
|
||||
Insn::Goto { .. } => execute::op_goto,
|
||||
Insn::Gosub { .. } => execute::op_gosub,
|
||||
Insn::Return { .. } => execute::op_return,
|
||||
Insn::Integer { .. } => execute::op_integer,
|
||||
Insn::Real { .. } => execute::op_real,
|
||||
Insn::RealAffinity { .. } => execute::op_real_affinity,
|
||||
Insn::String8 { .. } => execute::op_string8,
|
||||
Insn::Blob { .. } => execute::op_blob,
|
||||
Insn::RowData { .. } => execute::op_row_data,
|
||||
Insn::RowId { .. } => execute::op_row_id,
|
||||
Insn::IdxRowId { .. } => execute::op_idx_row_id,
|
||||
Insn::SeekRowid { .. } => execute::op_seek_rowid,
|
||||
Insn::DeferredSeek { .. } => execute::op_deferred_seek,
|
||||
Insn::SeekGE { .. }
|
||||
| Insn::SeekGT { .. }
|
||||
| Insn::SeekLE { .. }
|
||||
| Insn::SeekLT { .. } => execute::op_seek,
|
||||
Insn::SeekEnd { .. } => execute::op_seek_end,
|
||||
Insn::IdxGE { .. } => execute::op_idx_ge,
|
||||
Insn::IdxGT { .. } => execute::op_idx_gt,
|
||||
Insn::IdxLE { .. } => execute::op_idx_le,
|
||||
Insn::IdxLT { .. } => execute::op_idx_lt,
|
||||
Insn::DecrJumpZero { .. } => execute::op_decr_jump_zero,
|
||||
Insn::AggStep { .. } => execute::op_agg_step,
|
||||
Insn::AggFinal { .. } => execute::op_agg_final,
|
||||
Insn::SorterOpen { .. } => execute::op_sorter_open,
|
||||
Insn::SorterInsert { .. } => execute::op_sorter_insert,
|
||||
Insn::SorterSort { .. } => execute::op_sorter_sort,
|
||||
Insn::SorterData { .. } => execute::op_sorter_data,
|
||||
Insn::SorterNext { .. } => execute::op_sorter_next,
|
||||
Insn::Function { .. } => execute::op_function,
|
||||
Insn::Cast { .. } => execute::op_cast,
|
||||
Insn::InitCoroutine { .. } => execute::op_init_coroutine,
|
||||
Insn::EndCoroutine { .. } => execute::op_end_coroutine,
|
||||
Insn::Yield { .. } => execute::op_yield,
|
||||
Insn::Insert { .. } => execute::op_insert,
|
||||
Insn::Int64 { .. } => execute::op_int_64,
|
||||
Insn::IdxInsert { .. } => execute::op_idx_insert,
|
||||
Insn::Delete { .. } => execute::op_delete,
|
||||
Insn::NewRowid { .. } => execute::op_new_rowid,
|
||||
Insn::MustBeInt { .. } => execute::op_must_be_int,
|
||||
Insn::SoftNull { .. } => execute::op_soft_null,
|
||||
Insn::NoConflict { .. } => execute::op_no_conflict,
|
||||
Insn::NotExists { .. } => execute::op_not_exists,
|
||||
Insn::OffsetLimit { .. } => execute::op_offset_limit,
|
||||
Insn::OpenWrite { .. } => execute::op_open_write,
|
||||
Insn::Copy { .. } => execute::op_copy,
|
||||
Insn::CreateBtree { .. } => execute::op_create_btree,
|
||||
Insn::Destroy { .. } => execute::op_destroy,
|
||||
InsnVariants::OpenPseudo { .. } => execute::op_open_pseudo,
|
||||
InsnVariants::Rewind { .. } => execute::op_rewind,
|
||||
InsnVariants::Last { .. } => execute::op_last,
|
||||
InsnVariants::Column { .. } => execute::op_column,
|
||||
InsnVariants::TypeCheck { .. } => execute::op_type_check,
|
||||
InsnVariants::MakeRecord { .. } => execute::op_make_record,
|
||||
InsnVariants::ResultRow { .. } => execute::op_result_row,
|
||||
InsnVariants::Next { .. } => execute::op_next,
|
||||
InsnVariants::Prev { .. } => execute::op_prev,
|
||||
InsnVariants::Halt { .. } => execute::op_halt,
|
||||
InsnVariants::HaltIfNull { .. } => execute::op_halt_if_null,
|
||||
InsnVariants::Transaction { .. } => execute::op_transaction,
|
||||
InsnVariants::AutoCommit { .. } => execute::op_auto_commit,
|
||||
InsnVariants::Goto { .. } => execute::op_goto,
|
||||
InsnVariants::Gosub { .. } => execute::op_gosub,
|
||||
InsnVariants::Return { .. } => execute::op_return,
|
||||
InsnVariants::Integer { .. } => execute::op_integer,
|
||||
InsnVariants::Real { .. } => execute::op_real,
|
||||
InsnVariants::RealAffinity { .. } => execute::op_real_affinity,
|
||||
InsnVariants::String8 { .. } => execute::op_string8,
|
||||
InsnVariants::Blob { .. } => execute::op_blob,
|
||||
InsnVariants::RowData { .. } => execute::op_row_data,
|
||||
InsnVariants::RowId { .. } => execute::op_row_id,
|
||||
InsnVariants::IdxRowId { .. } => execute::op_idx_row_id,
|
||||
InsnVariants::SeekRowid { .. } => execute::op_seek_rowid,
|
||||
InsnVariants::DeferredSeek { .. } => execute::op_deferred_seek,
|
||||
InsnVariants::SeekGE { .. }
|
||||
| InsnVariants::SeekGT { .. }
|
||||
| InsnVariants::SeekLE { .. }
|
||||
| InsnVariants::SeekLT { .. } => execute::op_seek,
|
||||
InsnVariants::SeekEnd { .. } => execute::op_seek_end,
|
||||
InsnVariants::IdxGE { .. } => execute::op_idx_ge,
|
||||
InsnVariants::IdxGT { .. } => execute::op_idx_gt,
|
||||
InsnVariants::IdxLE { .. } => execute::op_idx_le,
|
||||
InsnVariants::IdxLT { .. } => execute::op_idx_lt,
|
||||
InsnVariants::DecrJumpZero { .. } => execute::op_decr_jump_zero,
|
||||
InsnVariants::AggStep { .. } => execute::op_agg_step,
|
||||
InsnVariants::AggFinal { .. } => execute::op_agg_final,
|
||||
InsnVariants::SorterOpen { .. } => execute::op_sorter_open,
|
||||
InsnVariants::SorterInsert { .. } => execute::op_sorter_insert,
|
||||
InsnVariants::SorterSort { .. } => execute::op_sorter_sort,
|
||||
InsnVariants::SorterData { .. } => execute::op_sorter_data,
|
||||
InsnVariants::SorterNext { .. } => execute::op_sorter_next,
|
||||
InsnVariants::Function { .. } => execute::op_function,
|
||||
InsnVariants::Cast { .. } => execute::op_cast,
|
||||
InsnVariants::InitCoroutine { .. } => execute::op_init_coroutine,
|
||||
InsnVariants::EndCoroutine { .. } => execute::op_end_coroutine,
|
||||
InsnVariants::Yield { .. } => execute::op_yield,
|
||||
InsnVariants::Insert { .. } => execute::op_insert,
|
||||
InsnVariants::Int64 { .. } => execute::op_int_64,
|
||||
InsnVariants::IdxInsert { .. } => execute::op_idx_insert,
|
||||
InsnVariants::Delete { .. } => execute::op_delete,
|
||||
InsnVariants::NewRowid { .. } => execute::op_new_rowid,
|
||||
InsnVariants::MustBeInt { .. } => execute::op_must_be_int,
|
||||
InsnVariants::SoftNull { .. } => execute::op_soft_null,
|
||||
InsnVariants::NoConflict { .. } => execute::op_no_conflict,
|
||||
InsnVariants::NotExists { .. } => execute::op_not_exists,
|
||||
InsnVariants::OffsetLimit { .. } => execute::op_offset_limit,
|
||||
InsnVariants::OpenWrite { .. } => execute::op_open_write,
|
||||
InsnVariants::Copy { .. } => execute::op_copy,
|
||||
InsnVariants::CreateBtree { .. } => execute::op_create_btree,
|
||||
InsnVariants::Destroy { .. } => execute::op_destroy,
|
||||
|
||||
Insn::DropTable { .. } => execute::op_drop_table,
|
||||
Insn::DropView { .. } => execute::op_drop_view,
|
||||
Insn::Close { .. } => execute::op_close,
|
||||
Insn::IsNull { .. } => execute::op_is_null,
|
||||
Insn::CollSeq { .. } => execute::op_coll_seq,
|
||||
Insn::ParseSchema { .. } => execute::op_parse_schema,
|
||||
Insn::PopulateMaterializedViews { .. } => execute::op_populate_materialized_views,
|
||||
Insn::ShiftRight { .. } => execute::op_shift_right,
|
||||
Insn::ShiftLeft { .. } => execute::op_shift_left,
|
||||
Insn::AddImm { .. } => execute::op_add_imm,
|
||||
Insn::Variable { .. } => execute::op_variable,
|
||||
Insn::ZeroOrNull { .. } => execute::op_zero_or_null,
|
||||
Insn::Not { .. } => execute::op_not,
|
||||
Insn::Concat { .. } => execute::op_concat,
|
||||
Insn::And { .. } => execute::op_and,
|
||||
Insn::Or { .. } => execute::op_or,
|
||||
Insn::Noop => execute::op_noop,
|
||||
Insn::PageCount { .. } => execute::op_page_count,
|
||||
Insn::ReadCookie { .. } => execute::op_read_cookie,
|
||||
Insn::SetCookie { .. } => execute::op_set_cookie,
|
||||
Insn::OpenEphemeral { .. } | Insn::OpenAutoindex { .. } => execute::op_open_ephemeral,
|
||||
Insn::Once { .. } => execute::op_once,
|
||||
Insn::Found { .. } | Insn::NotFound { .. } => execute::op_found,
|
||||
Insn::Affinity { .. } => execute::op_affinity,
|
||||
Insn::IdxDelete { .. } => execute::op_idx_delete,
|
||||
Insn::Count { .. } => execute::op_count,
|
||||
Insn::IntegrityCk { .. } => execute::op_integrity_check,
|
||||
Insn::RenameTable { .. } => execute::op_rename_table,
|
||||
Insn::DropColumn { .. } => execute::op_drop_column,
|
||||
Insn::AddColumn { .. } => execute::op_add_column,
|
||||
Insn::AlterColumn { .. } => execute::op_alter_column,
|
||||
Insn::MaxPgcnt { .. } => execute::op_max_pgcnt,
|
||||
Insn::JournalMode { .. } => execute::op_journal_mode,
|
||||
Insn::IfNeg { .. } => execute::op_if_neg,
|
||||
Insn::Explain { .. } => execute::op_noop,
|
||||
InsnVariants::DropTable { .. } => execute::op_drop_table,
|
||||
InsnVariants::DropView { .. } => execute::op_drop_view,
|
||||
InsnVariants::Close { .. } => execute::op_close,
|
||||
InsnVariants::IsNull { .. } => execute::op_is_null,
|
||||
InsnVariants::CollSeq { .. } => execute::op_coll_seq,
|
||||
InsnVariants::ParseSchema { .. } => execute::op_parse_schema,
|
||||
InsnVariants::PopulateMaterializedViews { .. } => {
|
||||
execute::op_populate_materialized_views
|
||||
}
|
||||
InsnVariants::ShiftRight { .. } => execute::op_shift_right,
|
||||
InsnVariants::ShiftLeft { .. } => execute::op_shift_left,
|
||||
InsnVariants::AddImm { .. } => execute::op_add_imm,
|
||||
InsnVariants::Variable { .. } => execute::op_variable,
|
||||
InsnVariants::ZeroOrNull { .. } => execute::op_zero_or_null,
|
||||
InsnVariants::Not { .. } => execute::op_not,
|
||||
InsnVariants::Concat { .. } => execute::op_concat,
|
||||
InsnVariants::And { .. } => execute::op_and,
|
||||
InsnVariants::Or { .. } => execute::op_or,
|
||||
InsnVariants::Noop => execute::op_noop,
|
||||
InsnVariants::PageCount { .. } => execute::op_page_count,
|
||||
InsnVariants::ReadCookie { .. } => execute::op_read_cookie,
|
||||
InsnVariants::SetCookie { .. } => execute::op_set_cookie,
|
||||
InsnVariants::OpenEphemeral { .. } | InsnVariants::OpenAutoindex { .. } => {
|
||||
execute::op_open_ephemeral
|
||||
}
|
||||
InsnVariants::Once { .. } => execute::op_once,
|
||||
InsnVariants::Found { .. } | InsnVariants::NotFound { .. } => execute::op_found,
|
||||
InsnVariants::Affinity { .. } => execute::op_affinity,
|
||||
InsnVariants::IdxDelete { .. } => execute::op_idx_delete,
|
||||
InsnVariants::Count { .. } => execute::op_count,
|
||||
InsnVariants::IntegrityCk { .. } => execute::op_integrity_check,
|
||||
InsnVariants::RenameTable { .. } => execute::op_rename_table,
|
||||
InsnVariants::DropColumn { .. } => execute::op_drop_column,
|
||||
InsnVariants::AddColumn { .. } => execute::op_add_column,
|
||||
InsnVariants::AlterColumn { .. } => execute::op_alter_column,
|
||||
InsnVariants::MaxPgcnt { .. } => execute::op_max_pgcnt,
|
||||
InsnVariants::JournalMode { .. } => execute::op_journal_mode,
|
||||
InsnVariants::IfNeg { .. } => execute::op_if_neg,
|
||||
InsnVariants::Explain { .. } => execute::op_noop,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Insn {
|
||||
pub fn to_function_fast(&self) -> InsnFunction {
|
||||
InsnVariants::from(self).to_function_fast()
|
||||
}
|
||||
|
||||
pub fn to_function(&self) -> InsnFunction {
|
||||
InsnVariants::from(self).to_function()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add remaining cookies.
|
||||
#[derive(Description, Debug, Clone, Copy)]
|
||||
pub enum Cookie {
|
||||
@@ -1256,3 +1292,21 @@ pub enum Cookie {
|
||||
/// The application ID as set by the application_id pragma.
|
||||
ApplicationId = 8,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_make_sure_correct_insn_table() {
|
||||
for variant in super::InsnVariants::VARIANTS {
|
||||
let func1 = variant.to_function();
|
||||
let func2 = variant.to_function_fast();
|
||||
assert_eq!(
|
||||
func1 as usize, func2 as usize,
|
||||
"Variant {:?} does not match in fast table",
|
||||
variant
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ pub enum JumpTarget {
|
||||
AfterThisInsn,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||
/// Represents a target for a jump instruction.
|
||||
/// Stores 32-bit ints to keep the enum word-sized.
|
||||
pub enum BranchOffset {
|
||||
@@ -108,6 +108,7 @@ pub enum BranchOffset {
|
||||
Offset(InsnReference),
|
||||
/// A placeholder is a temporary value to satisfy the compiler.
|
||||
/// It must be set later.
|
||||
#[default]
|
||||
Placeholder,
|
||||
}
|
||||
|
||||
@@ -475,7 +476,9 @@ macro_rules! get_cursor {
|
||||
|
||||
pub struct Program {
|
||||
pub max_registers: usize,
|
||||
pub insns: Vec<(Insn, InsnFunction)>,
|
||||
// we store original indices because we don't want to create new vec from
|
||||
// ProgramBuilder
|
||||
pub insns: Vec<(Insn, usize)>,
|
||||
pub cursor_ref: Vec<(Option<CursorKey>, CursorType)>,
|
||||
pub comments: Vec<(InsnReference, &'static str)>,
|
||||
pub parameters: crate::parameters::Parameters,
|
||||
@@ -644,7 +647,8 @@ impl Program {
|
||||
}
|
||||
// invalidate row
|
||||
let _ = state.result_row.take();
|
||||
let (insn, insn_function) = &self.insns[state.pc as usize];
|
||||
let (insn, _) = &self.insns[state.pc as usize];
|
||||
let insn_function = insn.to_function_fast();
|
||||
if enable_tracing {
|
||||
trace_insn(self, state.pc as InsnReference, insn);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user