mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
Fix symbol lifetime
This commit is contained in:
parent
13781a6f8f
commit
65d6d64102
2 changed files with 39 additions and 9 deletions
|
@ -11,7 +11,7 @@
|
||||||
// re-enable this when working on performance optimizations than have it block PRs.
|
// re-enable this when working on performance optimizations than have it block PRs.
|
||||||
#![allow(clippy::large_enum_variant)]
|
#![allow(clippy::large_enum_variant)]
|
||||||
|
|
||||||
use bumpalo::Bump;
|
use bumpalo::{collections::Vec, Bump};
|
||||||
use object::write::Object;
|
use object::write::Object;
|
||||||
use roc_collections::all::{MutMap, MutSet};
|
use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_module::ident::TagName;
|
use roc_module::ident::TagName;
|
||||||
|
@ -69,6 +69,12 @@ where
|
||||||
/// last_seen_map gets the map from symbol to when it is last seen in the function.
|
/// last_seen_map gets the map from symbol to when it is last seen in the function.
|
||||||
fn last_seen_map(&mut self) -> &mut MutMap<Symbol, *const Stmt<'a>>;
|
fn last_seen_map(&mut self) -> &mut MutMap<Symbol, *const Stmt<'a>>;
|
||||||
|
|
||||||
|
/// free_map gets the map statement to the symbols that are free after they run.
|
||||||
|
fn free_map(&mut self) -> &mut MutMap<*const Stmt<'a>, Vec<'a, Symbol>>;
|
||||||
|
|
||||||
|
/// set_free_map sets the free map to the given map.
|
||||||
|
fn set_free_map(&mut self, map: MutMap<*const Stmt<'a>, Vec<'a, Symbol>>);
|
||||||
|
|
||||||
/// load_literal sets a symbol to be equal to a literal.
|
/// load_literal sets a symbol to be equal to a literal.
|
||||||
fn load_literal(
|
fn load_literal(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -95,6 +101,7 @@ where
|
||||||
// TODO: let the backend know of all the arguments.
|
// TODO: let the backend know of all the arguments.
|
||||||
// let start = std::time::Instant::now();
|
// let start = std::time::Instant::now();
|
||||||
self.calculate_last_seen(&proc.body);
|
self.calculate_last_seen(&proc.body);
|
||||||
|
self.create_free_map();
|
||||||
// let duration = start.elapsed();
|
// let duration = start.elapsed();
|
||||||
// println!("Time to calculate lifetimes: {:?}", duration);
|
// println!("Time to calculate lifetimes: {:?}", duration);
|
||||||
// println!("{:?}", self.last_seen_map());
|
// println!("{:?}", self.last_seen_map());
|
||||||
|
@ -107,13 +114,13 @@ where
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Let(sym, expr, layout, following) => {
|
Stmt::Let(sym, expr, layout, following) => {
|
||||||
self.build_expr(sym, expr, layout)?;
|
self.build_expr(sym, expr, layout)?;
|
||||||
self.maybe_free_symbol(sym, stmt);
|
self.free_symbols(stmt);
|
||||||
self.build_stmt(following)?;
|
self.build_stmt(following)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Stmt::Ret(sym) => {
|
Stmt::Ret(sym) => {
|
||||||
self.return_symbol(sym)?;
|
self.return_symbol(sym)?;
|
||||||
self.maybe_free_symbol(sym, stmt);
|
self.free_symbols(stmt);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
x => Err(format!("the statement, {:?}, is not yet implemented", x)),
|
x => Err(format!("the statement, {:?}, is not yet implemented", x)),
|
||||||
|
@ -186,12 +193,14 @@ where
|
||||||
/// It only deals with inputs and outputs of i64 type.
|
/// It only deals with inputs and outputs of i64 type.
|
||||||
fn build_num_abs_i64(&mut self, dst: &Symbol, src: &Symbol) -> Result<(), String>;
|
fn build_num_abs_i64(&mut self, dst: &Symbol, src: &Symbol) -> Result<(), String>;
|
||||||
|
|
||||||
/// maybe_free will check if the symbol is last seen in the current state. If so, it will free the symbol resources, like registers.
|
/// free_symbols will free all symbols for the given statement.
|
||||||
fn maybe_free_symbol(&mut self, sym: &Symbol, stmt: &Stmt<'a>) {
|
fn free_symbols(&mut self, stmt: &Stmt<'a>) {
|
||||||
match self.last_seen_map().get(sym) {
|
match self.free_map().remove(&(stmt as *const Stmt<'a>)) {
|
||||||
Some(laststmt) if *laststmt == stmt as *const Stmt<'a> => {
|
Some(syms) => {
|
||||||
|
for sym in syms {
|
||||||
//println!("Freeing symbol: {:?}", sym);
|
//println!("Freeing symbol: {:?}", sym);
|
||||||
self.free_symbol(sym);
|
self.free_symbol(&sym);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -202,6 +211,16 @@ where
|
||||||
self.last_seen_map().insert(sym, stmt);
|
self.last_seen_map().insert(sym, stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_free_map(&mut self) {
|
||||||
|
let mut free_map = MutMap::default();
|
||||||
|
let arena = self.env().arena;
|
||||||
|
for (sym, stmt) in self.last_seen_map() {
|
||||||
|
let vals = free_map.entry(*stmt).or_insert(bumpalo::vec!(in arena));
|
||||||
|
vals.push(*sym);
|
||||||
|
}
|
||||||
|
self.set_free_map(free_map);
|
||||||
|
}
|
||||||
|
|
||||||
/// calculate_last_seen runs through the ast and fill the last seen map.
|
/// calculate_last_seen runs through the ast and fill the last seen map.
|
||||||
/// This must iterate through the ast in the same way that build_stmt does. i.e. then before else.
|
/// This must iterate through the ast in the same way that build_stmt does. i.e. then before else.
|
||||||
fn calculate_last_seen(&mut self, stmt: &Stmt<'a>) {
|
fn calculate_last_seen(&mut self, stmt: &Stmt<'a>) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ pub struct X86_64Backend<'a> {
|
||||||
leaf_proc: bool,
|
leaf_proc: bool,
|
||||||
|
|
||||||
last_seen_map: MutMap<Symbol, *const Stmt<'a>>,
|
last_seen_map: MutMap<Symbol, *const Stmt<'a>>,
|
||||||
|
free_map: MutMap<*const Stmt<'a>, Vec<'a, Symbol>>,
|
||||||
symbols_map: MutMap<Symbol, SymbolStorage<'a>>,
|
symbols_map: MutMap<Symbol, SymbolStorage<'a>>,
|
||||||
|
|
||||||
gp_param_regs: &'static [GPReg],
|
gp_param_regs: &'static [GPReg],
|
||||||
|
@ -58,6 +59,7 @@ impl<'a> Backend<'a> for X86_64Backend<'a> {
|
||||||
leaf_proc: true,
|
leaf_proc: true,
|
||||||
buf: bumpalo::vec!(in env.arena),
|
buf: bumpalo::vec!(in env.arena),
|
||||||
last_seen_map: MutMap::default(),
|
last_seen_map: MutMap::default(),
|
||||||
|
free_map: MutMap::default(),
|
||||||
symbols_map: MutMap::default(),
|
symbols_map: MutMap::default(),
|
||||||
gp_param_regs: &[
|
gp_param_regs: &[
|
||||||
GPReg::RDI,
|
GPReg::RDI,
|
||||||
|
@ -121,6 +123,7 @@ impl<'a> Backend<'a> for X86_64Backend<'a> {
|
||||||
leaf_proc: true,
|
leaf_proc: true,
|
||||||
buf: bumpalo::vec!(in env.arena),
|
buf: bumpalo::vec!(in env.arena),
|
||||||
last_seen_map: MutMap::default(),
|
last_seen_map: MutMap::default(),
|
||||||
|
free_map: MutMap::default(),
|
||||||
symbols_map: MutMap::default(),
|
symbols_map: MutMap::default(),
|
||||||
gp_param_regs: &[GPReg::RCX, GPReg::RDX, GPReg::R8, GPReg::R9],
|
gp_param_regs: &[GPReg::RCX, GPReg::RDX, GPReg::R8, GPReg::R9],
|
||||||
gp_return_regs: &[GPReg::RAX],
|
gp_return_regs: &[GPReg::RAX],
|
||||||
|
@ -188,6 +191,14 @@ impl<'a> Backend<'a> for X86_64Backend<'a> {
|
||||||
&mut self.last_seen_map
|
&mut self.last_seen_map
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_free_map(&mut self, map: MutMap<*const Stmt<'a>, Vec<'a, Symbol>>) {
|
||||||
|
self.free_map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free_map(&mut self) -> &mut MutMap<*const Stmt<'a>, Vec<'a, Symbol>> {
|
||||||
|
&mut self.free_map
|
||||||
|
}
|
||||||
|
|
||||||
fn load_literal(
|
fn load_literal(
|
||||||
&mut self,
|
&mut self,
|
||||||
sym: &Symbol,
|
sym: &Symbol,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue