mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-27 14:15:23 +00:00
Allocate ExprScopes ScopeEntries in a single arena instead of per ScopeData
This commit is contained in:
parent
2c251a7e2b
commit
ce0896b78c
2 changed files with 49 additions and 13 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use la_arena::{Arena, Idx};
|
use la_arena::{Arena, Idx, IdxRange, RawIdx};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -17,6 +17,7 @@ pub type ScopeId = Idx<ScopeData>;
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct ExprScopes {
|
pub struct ExprScopes {
|
||||||
scopes: Arena<ScopeData>,
|
scopes: Arena<ScopeData>,
|
||||||
|
scope_entries: Arena<ScopeEntry>,
|
||||||
scope_by_expr: FxHashMap<ExprId, ScopeId>,
|
scope_by_expr: FxHashMap<ExprId, ScopeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,7 +42,7 @@ pub struct ScopeData {
|
||||||
parent: Option<ScopeId>,
|
parent: Option<ScopeId>,
|
||||||
block: Option<BlockId>,
|
block: Option<BlockId>,
|
||||||
label: Option<(LabelId, Name)>,
|
label: Option<(LabelId, Name)>,
|
||||||
entries: Vec<ScopeEntry>,
|
entries: IdxRange<ScopeEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExprScopes {
|
impl ExprScopes {
|
||||||
|
|
@ -53,7 +54,7 @@ impl ExprScopes {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
|
pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
|
||||||
&self.scopes[scope].entries
|
&self.scope_entries[self.scopes[scope].entries.clone()]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `scope` refers to a block expression scope, returns the corresponding `BlockId`.
|
/// If `scope` refers to a block expression scope, returns the corresponding `BlockId`.
|
||||||
|
|
@ -85,10 +86,17 @@ impl ExprScopes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn empty_entries(idx: usize) -> IdxRange<ScopeEntry> {
|
||||||
|
IdxRange::new(Idx::from_raw(RawIdx::from(idx as u32))..Idx::from_raw(RawIdx::from(idx as u32)))
|
||||||
|
}
|
||||||
|
|
||||||
impl ExprScopes {
|
impl ExprScopes {
|
||||||
fn new(body: &Body) -> ExprScopes {
|
fn new(body: &Body) -> ExprScopes {
|
||||||
let mut scopes =
|
let mut scopes = ExprScopes {
|
||||||
ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() };
|
scopes: Arena::default(),
|
||||||
|
scope_entries: Arena::default(),
|
||||||
|
scope_by_expr: FxHashMap::default(),
|
||||||
|
};
|
||||||
let mut root = scopes.root_scope();
|
let mut root = scopes.root_scope();
|
||||||
scopes.add_params_bindings(body, root, &body.params);
|
scopes.add_params_bindings(body, root, &body.params);
|
||||||
compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root);
|
compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root);
|
||||||
|
|
@ -96,7 +104,12 @@ impl ExprScopes {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn root_scope(&mut self) -> ScopeId {
|
fn root_scope(&mut self) -> ScopeId {
|
||||||
self.scopes.alloc(ScopeData { parent: None, block: None, label: None, entries: vec![] })
|
self.scopes.alloc(ScopeData {
|
||||||
|
parent: None,
|
||||||
|
block: None,
|
||||||
|
label: None,
|
||||||
|
entries: empty_entries(self.scope_entries.len()),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_scope(&mut self, parent: ScopeId) -> ScopeId {
|
fn new_scope(&mut self, parent: ScopeId) -> ScopeId {
|
||||||
|
|
@ -104,12 +117,17 @@ impl ExprScopes {
|
||||||
parent: Some(parent),
|
parent: Some(parent),
|
||||||
block: None,
|
block: None,
|
||||||
label: None,
|
label: None,
|
||||||
entries: vec![],
|
entries: empty_entries(self.scope_entries.len()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_labeled_scope(&mut self, parent: ScopeId, label: Option<(LabelId, Name)>) -> ScopeId {
|
fn new_labeled_scope(&mut self, parent: ScopeId, label: Option<(LabelId, Name)>) -> ScopeId {
|
||||||
self.scopes.alloc(ScopeData { parent: Some(parent), block: None, label, entries: vec![] })
|
self.scopes.alloc(ScopeData {
|
||||||
|
parent: Some(parent),
|
||||||
|
block: None,
|
||||||
|
label,
|
||||||
|
entries: empty_entries(self.scope_entries.len()),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_block_scope(
|
fn new_block_scope(
|
||||||
|
|
@ -118,13 +136,19 @@ impl ExprScopes {
|
||||||
block: Option<BlockId>,
|
block: Option<BlockId>,
|
||||||
label: Option<(LabelId, Name)>,
|
label: Option<(LabelId, Name)>,
|
||||||
) -> ScopeId {
|
) -> ScopeId {
|
||||||
self.scopes.alloc(ScopeData { parent: Some(parent), block, label, entries: vec![] })
|
self.scopes.alloc(ScopeData {
|
||||||
|
parent: Some(parent),
|
||||||
|
block,
|
||||||
|
label,
|
||||||
|
entries: empty_entries(self.scope_entries.len()),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_bindings(&mut self, body: &Body, scope: ScopeId, binding: BindingId) {
|
fn add_bindings(&mut self, body: &Body, scope: ScopeId, binding: BindingId) {
|
||||||
let Binding { name, .. } = &body.bindings[binding];
|
let Binding { name, .. } = &body.bindings[binding];
|
||||||
let entry = ScopeEntry { name: name.clone(), binding };
|
let entry = self.scope_entries.alloc(ScopeEntry { name: name.clone(), binding });
|
||||||
self.scopes[scope].entries.push(entry);
|
self.scopes[scope].entries =
|
||||||
|
IdxRange::new_inclusive(self.scopes[scope].entries.start()..=entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_pat_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
|
fn add_pat_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
|
||||||
|
|
@ -145,9 +169,9 @@ impl ExprScopes {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shrink_to_fit(&mut self) {
|
fn shrink_to_fit(&mut self) {
|
||||||
let ExprScopes { scopes, scope_by_expr } = self;
|
let ExprScopes { scopes, scope_entries, scope_by_expr } = self;
|
||||||
scopes.shrink_to_fit();
|
scopes.shrink_to_fit();
|
||||||
scopes.values_mut().for_each(|it| it.entries.shrink_to_fit());
|
scope_entries.shrink_to_fit();
|
||||||
scope_by_expr.shrink_to_fit();
|
scope_by_expr.shrink_to_fit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,14 @@ pub use map::{ArenaMap, Entry, OccupiedEntry, VacantEntry};
|
||||||
pub struct RawIdx(u32);
|
pub struct RawIdx(u32);
|
||||||
|
|
||||||
impl From<RawIdx> for u32 {
|
impl From<RawIdx> for u32 {
|
||||||
|
#[inline]
|
||||||
fn from(raw: RawIdx) -> u32 {
|
fn from(raw: RawIdx) -> u32 {
|
||||||
raw.0
|
raw.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u32> for RawIdx {
|
impl From<u32> for RawIdx {
|
||||||
|
#[inline]
|
||||||
fn from(idx: u32) -> RawIdx {
|
fn from(idx: u32) -> RawIdx {
|
||||||
RawIdx(idx)
|
RawIdx(idx)
|
||||||
}
|
}
|
||||||
|
|
@ -160,6 +162,16 @@ impl<T> IdxRange<T> {
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.range.is_empty()
|
self.range.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the start of the index range.
|
||||||
|
pub fn start(&self) -> Idx<T> {
|
||||||
|
Idx::from_raw(RawIdx::from(self.range.start))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the start of the index range.
|
||||||
|
pub fn end(&self) -> Idx<T> {
|
||||||
|
Idx::from_raw(RawIdx::from(self.range.end))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Iterator for IdxRange<T> {
|
impl<T> Iterator for IdxRange<T> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue