Skip to content

Commit

Permalink
Use LIR for VM byte code
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasWanke committed Sep 30, 2023
1 parent 425daf2 commit af4625f
Show file tree
Hide file tree
Showing 18 changed files with 452 additions and 447 deletions.
2 changes: 1 addition & 1 deletion compiler/cli/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use candy_frontend::{
utils::DoHash,
TracingConfig, TracingMode,
};
use candy_vm::{byte_code::RichIrForByteCode, heap::HeapData, mir_to_byte_code::compile_byte_code};
use candy_vm::{byte_code::RichIrForByteCode, heap::HeapData, lir_to_byte_code::compile_byte_code};
use clap::{Parser, ValueHint};
use colored::{Color, Colorize};
use diffy::{create_patch, PatchFormatter};
Expand Down
2 changes: 1 addition & 1 deletion compiler/cli/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use candy_frontend::{hir, TracingConfig, TracingMode};
use candy_vm::{
environment::DefaultEnvironment,
heap::{Heap, HirId},
mir_to_byte_code::compile_byte_code,
lir_to_byte_code::compile_byte_code,
tracer::stack_trace::StackTracer,
Vm, VmFinished,
};
Expand Down
3 changes: 2 additions & 1 deletion compiler/frontend/src/lir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ impl Body {
}
}

pub fn push(&mut self, expression: Expression) {
pub fn push(&mut self, expression: Expression) -> Id {
self.expressions.push(expression);
self.last_expression_id().unwrap()
}
}
impl ToRichIr for Body {
Expand Down
8 changes: 5 additions & 3 deletions compiler/frontend/src/lir_optimize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ impl Body {

let mut new_expression = old_expression.clone();
new_expression.replace_ids(|id| id_mapping.get(&id).copied().unwrap_or(id));
new_body.push(new_expression);
id_mapping.force_insert(old_id, new_body.last_expression_id().unwrap());
let id = new_body.push(new_expression);
id_mapping.force_insert(old_id, id);
new_body.maybe_dup(&mut reference_count_adjustments, old_id, &id_mapping);
}

Expand All @@ -63,7 +63,9 @@ impl Body {
.sorted_by_key(|(id, _)| *id)
{
match amount {
-1 => new_body.push(Expression::Drop(id)),
-1 => {
new_body.push(Expression::Drop(id));
}
0 => {}
_ => panic!("Unexpected reference count adjustment for {id}: {amount}"),
}
Expand Down
4 changes: 1 addition & 3 deletions compiler/frontend/src/mir_to_lir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,7 @@ impl CurrentBody {
fn push(&mut self, mir_id: mir::Id, expression: impl Into<lir::Expression>) -> lir::Id {
let expression = expression.into();
let is_constant = matches!(expression, lir::Expression::Constant(_));
self.body.push(expression);

let id = self.body.last_expression_id().unwrap();
let id = self.body.push(expression);
assert!(self.id_mapping.insert(mir_id, id).is_none());
if !is_constant {
assert!(self.ids_to_drop.insert(id));
Expand Down
6 changes: 3 additions & 3 deletions compiler/fuzzer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,21 @@ pub use self::{
use candy_frontend::{
ast_to_hir::AstToHir,
cst::CstDb,
mir_optimize::OptimizeMir,
lir_optimize::OptimizeLir,
module::Module,
position::PositionConversionDb,
{hir::Id, TracingConfig, TracingMode},
};
use candy_vm::{
heap::Heap, mir_to_byte_code::compile_byte_code, tracer::stack_trace::StackTracer, Panic, Vm,
heap::Heap, lir_to_byte_code::compile_byte_code, tracer::stack_trace::StackTracer, Panic, Vm,
VmFinished,
};
use std::rc::Rc;
use tracing::{debug, error, info};

pub fn fuzz<DB>(db: &DB, module: Module) -> Vec<FailingFuzzCase>
where
DB: AstToHir + CstDb + OptimizeMir + PositionConversionDb,
DB: AstToHir + CstDb + OptimizeLir + PositionConversionDb,
{
let tracing = TracingConfig {
register_fuzzables: TracingMode::All,
Expand Down
2 changes: 1 addition & 1 deletion compiler/language_server/src/debug_adapter/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use candy_vm::{
byte_code::Instruction,
environment::StateAfterRunWithoutHandles,
heap::{Heap, HirId, Struct},
mir_to_byte_code::compile_byte_code,
lir_to_byte_code::compile_byte_code,
tracer::DummyTracer,
Vm, VmFinished,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use candy_vm::{
byte_code::ByteCode,
environment::StateAfterRunWithoutHandles,
heap::{Heap, ToDebugText},
mir_to_byte_code::compile_byte_code,
lir_to_byte_code::compile_byte_code,
tracer::{evaluated_values::EvaluatedValuesTracer, stack_trace::StackTracer},
Panic, Vm, VmFinished,
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/language_server/src/features_ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl IrFeatures {
),
Ir::VmByteCode(tracing_config) => Self::rich_ir_for_vm_byte_code(
&config.module,
&candy_vm::mir_to_byte_code::compile_byte_code(
&candy_vm::lir_to_byte_code::compile_byte_code(
db,
config.module.clone(),
tracing_config.clone(),
Expand Down
6 changes: 5 additions & 1 deletion compiler/vm/benches/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use candy_frontend::{
cst_to_ast::CstToAstStorage,
hir::{self, HirDbStorage},
hir_to_mir::HirToMirStorage,
lir_optimize::OptimizeLirStorage,
mir_optimize::OptimizeMirStorage,
mir_to_lir::MirToLirStorage,
module::{
GetModuleContentQuery, InMemoryModuleProvider, Module, ModuleDbStorage, ModuleKind,
ModuleProvider, ModuleProviderOwner, MutableModuleProviderOwner, Package,
Expand All @@ -18,7 +20,7 @@ use candy_frontend::{
use candy_vm::{
byte_code::ByteCode,
heap::{Heap, HirId, InlineObject, Struct},
mir_to_byte_code::compile_byte_code,
lir_to_byte_code::compile_byte_code,
tracer::DummyTracer,
PopulateInMemoryProviderFromFileSystem, Vm, VmFinished,
};
Expand All @@ -44,7 +46,9 @@ lazy_static! {
CstToAstStorage,
HirDbStorage,
HirToMirStorage,
MirToLirStorage,
ModuleDbStorage,
OptimizeLirStorage,
OptimizeMirStorage,
PositionConversionStorage,
RcstToCstStorage,
Expand Down
6 changes: 5 additions & 1 deletion compiler/vm/fuzz/fuzz_targets/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use candy_frontend::{
cst_to_ast::CstToAstStorage,
hir::{self, HirDbStorage},
hir_to_mir::HirToMirStorage,
lir_optimize::OptimizeLirStorage,
mir_optimize::OptimizeMirStorage,
mir_to_lir::MirToLirStorage,
module::{
InMemoryModuleProvider, Module, ModuleDbStorage, ModuleKind, ModuleProvider,
ModuleProviderOwner, Package,
Expand All @@ -19,7 +21,7 @@ use candy_frontend::{
};
use candy_vm::{
heap::{Heap, HirId, Struct},
mir_to_byte_code::compile_byte_code,
lir_to_byte_code::compile_byte_code,
tracer::DummyTracer,
PopulateInMemoryProviderFromFileSystem, Vm, VmFinished,
};
Expand All @@ -43,7 +45,9 @@ lazy_static! {
CstToAstStorage,
HirDbStorage,
HirToMirStorage,
MirToLirStorage,
ModuleDbStorage,
OptimizeLirStorage,
OptimizeMirStorage,
PositionConversionStorage,
RcstToCstStorage,
Expand Down
2 changes: 1 addition & 1 deletion compiler/vm/src/builtin_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl MachineState {
Ok(DivergeControlFlow {
function,
responsible,
}) => self.call_function(heap, function, &[], responsible),
}) => self.call_function(function, &[], responsible),
Ok(CallHandle(call)) => InstructionResult::CallHandle(call),
Err(reason) => InstructionResult::Panic(Panic {
reason,
Expand Down
26 changes: 25 additions & 1 deletion compiler/vm/src/byte_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::instruction_pointer::InstructionPointer;
use candy_frontend::hir;
use candy_frontend::rich_ir::ReferenceKey;
use candy_frontend::{
mir::Id,
lir::Id,
module::Module,
rich_ir::{RichIr, RichIrBuilder, ToRichIr, TokenType},
TracingConfig,
Expand Down Expand Up @@ -71,6 +71,19 @@ pub enum Instruction {
/// Leaves the top stack item untouched, but removes n below.
PopMultipleBelowTop(usize),

/// Increases the reference count by `amount`.
///
/// a, value -> a
Dup {
amount: usize,
},

/// Decreases the reference count by one and, if the reference count reaches
/// zero, deallocates it.
///
/// a, value -> a
Drop,

/// Sets up the data stack for a function execution and then changes the
/// instruction pointer to the first instruction.
///
Expand Down Expand Up @@ -151,6 +164,12 @@ impl Instruction {
stack.pop_multiple(*n);
stack.push(top);
}
Self::Dup { amount: _ } => {
stack.pop();
}
Self::Drop => {
stack.pop();
}
Self::Call { num_args } => {
stack.pop(); // responsible
stack.pop_multiple(*num_args);
Expand Down Expand Up @@ -350,6 +369,11 @@ impl Instruction {
builder.push(" ", None, EnumSet::empty());
builder.push(count.to_string(), None, EnumSet::empty());
}
Self::Dup { amount } => {
builder.push(" by ", None, EnumSet::empty());
builder.push(amount.to_string(), None, EnumSet::empty());
}
Self::Drop => {}
Self::Call { num_args } => {
builder.push(
format!(" with {num_args} {}", arguments_plural(*num_args)),
Expand Down
42 changes: 19 additions & 23 deletions compiler/vm/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,7 @@ impl MachineState {
} => {
let captured = captured
.iter()
.map(|offset| {
let object = self.get_from_data_stack(*offset);
object.dup(heap);
object
})
.map(|offset| self.get_from_data_stack(*offset))
.collect_vec();
let function = Function::create(heap, true, &captured, *num_args, *body);
self.push_to_data_stack(function);
Expand All @@ -102,18 +98,23 @@ impl MachineState {
}
Instruction::PushFromStack(offset) => {
let address = self.get_from_data_stack(*offset);
address.dup(heap);
self.push_to_data_stack(address);
InstructionResult::Done
}
Instruction::PopMultipleBelowTop(n) => {
let top = self.pop_from_data_stack();
for _ in 0..*n {
self.pop_from_data_stack().drop(heap);
}
self.pop_multiple_from_data_stack(*n);
self.push_to_data_stack(top);
InstructionResult::Done
}
Instruction::Dup { amount } => {
self.pop_from_data_stack().dup_by(heap, *amount);
InstructionResult::Done
}
Instruction::Drop => {
self.pop_from_data_stack().drop(heap);
InstructionResult::Done
}
Instruction::Call { num_args } => {
let responsible = self.pop_from_data_stack().try_into().unwrap();
let mut arguments = (0..*num_args)
Expand All @@ -136,9 +137,7 @@ impl MachineState {
// PERF: Built the reverse list in place
arguments.reverse();
let callee = self.pop_from_data_stack();
for _ in 0..*num_locals_to_pop {
self.pop_from_data_stack().drop(heap);
}
self.pop_multiple_from_data_stack(*num_locals_to_pop);

// Tail calling a function is basically just a normal call, but
// pretending we are our caller.
Expand Down Expand Up @@ -195,8 +194,8 @@ impl MachineState {
}
Instruction::TraceFoundFuzzableFunction => {
let function = self.pop_from_data_stack().try_into().expect(
"Instruction TraceFoundFuzzableFunction executed, but stack top is not a function.",
);
"Instruction TraceFoundFuzzableFunction executed, but stack top is not a function.",
);
let definition = self.pop_from_data_stack().try_into().unwrap();

tracer.found_fuzzable_function(heap, definition, function);
Expand All @@ -213,9 +212,8 @@ impl MachineState {
responsible: HirId,
) -> InstructionResult {
match callee.into() {
Data::Function(function) => self.call_function(heap, function, arguments, responsible),
Data::Function(function) => self.call_function( function, arguments, responsible),
Data::Builtin(builtin) => {
callee.drop(heap);
self.run_builtin_function(heap, builtin.get(), arguments, responsible)
}
Data::Handle(handle) => {
Expand Down Expand Up @@ -250,7 +248,6 @@ impl MachineState {
if let [value] = arguments {
let tag = Tag::create_with_value(heap, true, tag.symbol(), *value);
self.push_to_data_stack(tag);
value.dup(heap);
InstructionResult::Done
} else {
InstructionResult::Panic(Panic {
Expand All @@ -272,7 +269,6 @@ impl MachineState {
}
pub fn call_function(
&mut self,
heap: &mut Heap,
function: Function,
arguments: &[InlineObject],
responsible: HirId,
Expand All @@ -291,11 +287,7 @@ impl MachineState {
if let Some(next_instruction) = self.next_instruction {
self.call_stack.push(next_instruction);
}
let captured = function.captured();
for captured in captured {
captured.dup(heap);
}
self.data_stack.extend_from_slice(captured);
self.data_stack.extend_from_slice(function.captured());
self.data_stack.extend_from_slice(arguments);
self.push_to_data_stack(responsible);
self.next_instruction = Some(function.body());
Expand All @@ -311,6 +303,10 @@ impl MachineState {
fn pop_from_data_stack(&mut self) -> InlineObject {
self.data_stack.pop().expect("Data stack is empty.")
}
fn pop_multiple_from_data_stack(&mut self, amount: usize) {
assert!(amount <= self.data_stack.len());
self.data_stack.truncate(self.data_stack.len() - amount);
}
}

#[extension_trait]
Expand Down
2 changes: 1 addition & 1 deletion compiler/vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ mod handle_id;
pub mod heap;
mod instruction_pointer;
mod instructions;
pub mod mir_to_byte_code;
pub mod lir_to_byte_code;
pub mod tracer;
mod utils;
mod vm;
Expand Down
Loading

1 comment on commit af4625f

@jwbot
Copy link
Collaborator

@jwbot jwbot commented on af4625f Sep 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compiler

Benchmark suite Current: af4625f Previous: 425daf2 Ratio
Time: Compiler/hello_world 22367865 ns/iter (± 958040) 17653887 ns/iter (± 482024) 1.27
Time: Compiler/fibonacci 171250347 ns/iter (± 1631950) 167509297 ns/iter (± 642630) 1.02

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.