Skip to content

Commit

Permalink
Skip StmtId entries in execution graph when not debugging (#1328)
Browse files Browse the repository at this point in the history
This change is an optimization that configures the lowerer to know when
debugging is the intended scenario for the lowered FIR. When not
debugging, no `StmtId` nodes are included in the execution graph, which
skips the (minimal but non-zero) overhead of checking each statement for
possible breakpoints. Only the debugger creates the interpreter and the
underlying lowerer with these debug entries enabled, preserving behavior
for those scenarios.
  • Loading branch information
swernli authored Apr 2, 2024
1 parent 2ed0ff8 commit 5f7ab13
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 4 deletions.
46 changes: 43 additions & 3 deletions compiler/qsc/src/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,44 @@ impl Interpreter {
package_type: PackageType,
capabilities: RuntimeCapabilityFlags,
language_features: LanguageFeatures,
) -> std::result::Result<Self, Vec<Error>> {
Self::new_internal(
false,
std,
sources,
package_type,
capabilities,
language_features,
)
}

/// Creates a new incremental compiler with debugging stmts enabled, compiling the passed in sources.
/// # Errors
/// If compiling the sources fails, compiler errors are returned.
pub fn new_with_debug(
std: bool,
sources: SourceMap,
package_type: PackageType,
capabilities: RuntimeCapabilityFlags,
language_features: LanguageFeatures,
) -> std::result::Result<Self, Vec<Error>> {
Self::new_internal(
true,
std,
sources,
package_type,
capabilities,
language_features,
)
}

fn new_internal(
dbg: bool,
std: bool,
sources: SourceMap,
package_type: PackageType,
capabilities: RuntimeCapabilityFlags,
language_features: LanguageFeatures,
) -> std::result::Result<Self, Vec<Error>> {
let compiler = Compiler::new(std, sources, package_type, capabilities, language_features)
.map_err(into_errors)?;
Expand All @@ -152,7 +190,9 @@ impl Interpreter {
for (id, unit) in compiler.package_store() {
fir_store.insert(
map_hir_package_to_fir(id),
qsc_eval::lower::Lowerer::new().lower_package(&unit.package),
qsc_eval::lower::Lowerer::new()
.with_debug(dbg)
.lower_package(&unit.package),
);
}

Expand All @@ -163,7 +203,7 @@ impl Interpreter {
lines: 0,
capabilities,
fir_store,
lowerer: qsc_eval::lower::Lowerer::new(),
lowerer: qsc_eval::lower::Lowerer::new().with_debug(dbg),
env: Env::default(),
sim: BackendChain::new(
SparseSim::new(),
Expand Down Expand Up @@ -490,7 +530,7 @@ impl Debugger {
position_encoding: Encoding,
language_features: LanguageFeatures,
) -> std::result::Result<Self, Vec<Error>> {
let interpreter = Interpreter::new(
let interpreter = Interpreter::new_with_debug(
true,
sources,
PackageType::Exe,
Expand Down
12 changes: 11 additions & 1 deletion compiler/qsc_eval/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub struct Lowerer {
blocks: IndexMap<BlockId, Block>,
assigner: Assigner,
exec_graph: Vec<ExecGraphNode>,
enable_debug: bool,
}

impl Default for Lowerer {
Expand All @@ -41,9 +42,16 @@ impl Lowerer {
blocks: IndexMap::new(),
assigner: Assigner::new(),
exec_graph: Vec::new(),
enable_debug: false,
}
}

#[must_use]
pub fn with_debug(mut self, dbg: bool) -> Self {
self.enable_debug = dbg;
self
}

pub fn take_exec_graph(&mut self) -> Vec<ExecGraphNode> {
self.exec_graph
.drain(..)
Expand Down Expand Up @@ -281,7 +289,9 @@ impl Lowerer {
fn lower_stmt(&mut self, stmt: &hir::Stmt) -> fir::StmtId {
let id = self.assigner.next_stmt();
let graph_start_idx = self.exec_graph.len();
self.exec_graph.push(ExecGraphNode::Stmt(id));
if self.enable_debug {
self.exec_graph.push(ExecGraphNode::Stmt(id));
}
let kind = match &stmt.kind {
hir::StmtKind::Expr(expr) => fir::StmtKind::Expr(self.lower_expr(expr)),
hir::StmtKind::Item(item) => fir::StmtKind::Item(lower_local_item_id(*item)),
Expand Down

0 comments on commit 5f7ab13

Please sign in to comment.