Skip to content

Commit 5ac0c14

Browse files
committed
Remove some vec clones in const-eval
1 parent 5125063 commit 5ac0c14

File tree

8 files changed

+161
-128
lines changed

8 files changed

+161
-128
lines changed

crates/hir-ty/src/display.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ fn render_const_scalar(
515515
TyKind::Dyn(_) => {
516516
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
517517
let ty_id = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
518-
let Ok(t) = memory_map.vtable.ty(ty_id) else {
518+
let Ok(t) = memory_map.vtable_ty(ty_id) else {
519519
return f.write_str("<ty-missing-in-vtable-map>");
520520
};
521521
let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else {

crates/hir-ty/src/infer/closure.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Inference of closure parameter types based on the closure's expected type.
22
3-
use std::{cmp, collections::HashMap, convert::Infallible, mem};
3+
use std::{cmp, convert::Infallible, mem};
44

55
use chalk_ir::{
66
cast::Cast,
@@ -778,7 +778,7 @@ impl InferenceContext<'_> {
778778

779779
fn minimize_captures(&mut self) {
780780
self.current_captures.sort_by_key(|it| it.place.projections.len());
781-
let mut hash_map = HashMap::<HirPlace, usize>::new();
781+
let mut hash_map = FxHashMap::<HirPlace, usize>::default();
782782
let result = mem::take(&mut self.current_captures);
783783
for item in result {
784784
let mut lookup_place = HirPlace { local: item.place.local, projections: vec![] };

crates/hir-ty/src/interner.rs

-32
Original file line numberDiff line numberDiff line change
@@ -36,35 +36,6 @@ impl<T> std::ops::Deref for InternedWrapper<T> {
3636
}
3737
}
3838

39-
#[derive(Eq)]
40-
pub struct PreHashedWrapper<T>(T, u64);
41-
42-
impl<T: fmt::Debug> fmt::Debug for PreHashedWrapper<T> {
43-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44-
fmt::Debug::fmt(&self.0, f)
45-
}
46-
}
47-
48-
impl<T: PartialEq> PartialEq for PreHashedWrapper<T> {
49-
fn eq(&self, other: &Self) -> bool {
50-
self.1 == other.1 && self.0 == other.0
51-
}
52-
}
53-
54-
impl<T> std::ops::Deref for PreHashedWrapper<T> {
55-
type Target = T;
56-
57-
fn deref(&self) -> &Self::Target {
58-
&self.0
59-
}
60-
}
61-
62-
impl<T: std::hash::Hash> std::hash::Hash for PreHashedWrapper<T> {
63-
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
64-
state.write_u64(self.1);
65-
}
66-
}
67-
6839
impl_internable!(
6940
InternedWrapper<Vec<VariableKind>>,
7041
InternedWrapper<SmallVec<[GenericArg; 2]>>,
@@ -76,7 +47,6 @@ impl_internable!(
7647
InternedWrapper<Vec<ProgramClause>>,
7748
InternedWrapper<Vec<QuantifiedWhereClause>>,
7849
InternedWrapper<SmallVec<[Variance; 16]>>,
79-
// InternedWrapper<PreHashedWrapper<Goals>>,
8050
);
8151

8252
impl chalk_ir::interner::Interner for Interner {
@@ -88,7 +58,6 @@ impl chalk_ir::interner::Interner for Interner {
8858
// We could do the following, but that saves "only" 20mb on self while increasing inferecene
8959
// time by ~2.5%
9060
// type InternedGoal = Interned<InternedWrapper<GoalData>>;
91-
// type InternedGoal = Interned<InternedWrapper<PreHashedWrapper<GoalData>>>;
9261
type InternedGoal = Arc<GoalData>;
9362
type InternedGoals = Vec<Goal>;
9463
type InternedSubstitution = Interned<InternedWrapper<SmallVec<[GenericArg; 2]>>>;
@@ -97,7 +66,6 @@ impl chalk_ir::interner::Interner for Interner {
9766
type InternedQuantifiedWhereClauses = Interned<InternedWrapper<Vec<QuantifiedWhereClause>>>;
9867
type InternedVariableKinds = Interned<InternedWrapper<Vec<VariableKind>>>;
9968
type InternedCanonicalVarKinds = Interned<InternedWrapper<Vec<CanonicalVarKind>>>;
100-
// type InternedConstraints = SmallVec<[InEnvironment<Constraint>; 1]>;
10169
type InternedConstraints = Vec<InEnvironment<Constraint>>;
10270
type InternedVariances = SmallVec<[Variance; 16]>;
10371
type DefId = InternId;

crates/hir-ty/src/lib.rs

+54-22
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ mod tests;
3737
mod test_db;
3838

3939
use std::{
40-
collections::{hash_map::Entry, HashMap},
41-
hash::Hash,
40+
collections::hash_map::Entry,
41+
hash::{BuildHasherDefault, Hash},
4242
};
4343

4444
use chalk_ir::{
@@ -52,7 +52,7 @@ use hir_def::{hir::ExprId, type_ref::Rawness, GeneralConstId, TypeOrConstParamId
5252
use hir_expand::name;
5353
use la_arena::{Arena, Idx};
5454
use mir::{MirEvalError, VTableMap};
55-
use rustc_hash::FxHashSet;
55+
use rustc_hash::{FxHashMap, FxHashSet};
5656
use syntax::ast::{make, ConstArg};
5757
use traits::FnTrait;
5858
use triomphe::Arc;
@@ -171,47 +171,79 @@ pub type Variances = chalk_ir::Variances<Interner>;
171171
/// the necessary bits of memory of the const eval session to keep the constant
172172
/// meaningful.
173173
#[derive(Debug, Default, Clone, PartialEq, Eq)]
174-
pub struct MemoryMap {
175-
pub memory: HashMap<usize, Vec<u8>>,
176-
pub vtable: VTableMap,
174+
pub enum MemoryMap {
175+
#[default]
176+
Empty,
177+
Simple(Box<[u8]>),
178+
Complex(Box<ComplexMemoryMap>),
177179
}
178180

179-
impl MemoryMap {
180-
fn insert(&mut self, addr: usize, x: Vec<u8>) {
181+
#[derive(Debug, Default, Clone, PartialEq, Eq)]
182+
pub struct ComplexMemoryMap {
183+
memory: FxHashMap<usize, Box<[u8]>>,
184+
vtable: VTableMap,
185+
}
186+
187+
impl ComplexMemoryMap {
188+
fn insert(&mut self, addr: usize, val: Box<[u8]>) {
181189
match self.memory.entry(addr) {
182190
Entry::Occupied(mut e) => {
183-
if e.get().len() < x.len() {
184-
e.insert(x);
191+
if e.get().len() < val.len() {
192+
e.insert(val);
185193
}
186194
}
187195
Entry::Vacant(e) => {
188-
e.insert(x);
196+
e.insert(val);
189197
}
190198
}
191199
}
200+
}
201+
202+
impl MemoryMap {
203+
pub fn vtable_ty(&self, id: usize) -> Result<&Ty, MirEvalError> {
204+
match self {
205+
MemoryMap::Empty | MemoryMap::Simple(_) => Err(MirEvalError::InvalidVTableId(id)),
206+
MemoryMap::Complex(cm) => cm.vtable.ty(id),
207+
}
208+
}
209+
210+
fn simple(v: Box<[u8]>) -> Self {
211+
MemoryMap::Simple(v)
212+
}
192213

193214
/// This functions convert each address by a function `f` which gets the byte intervals and assign an address
194215
/// to them. It is useful when you want to load a constant with a memory map in a new memory. You can pass an
195216
/// allocator function as `f` and it will return a mapping of old addresses to new addresses.
196217
fn transform_addresses(
197218
&self,
198219
mut f: impl FnMut(&[u8], usize) -> Result<usize, MirEvalError>,
199-
) -> Result<HashMap<usize, usize>, MirEvalError> {
200-
self.memory
201-
.iter()
202-
.map(|x| {
203-
let addr = *x.0;
204-
let align = if addr == 0 { 64 } else { (addr - (addr & (addr - 1))).min(64) };
205-
Ok((addr, f(x.1, align)?))
206-
})
207-
.collect()
220+
) -> Result<FxHashMap<usize, usize>, MirEvalError> {
221+
let mut transform = |(addr, val): (&usize, &Box<[u8]>)| {
222+
let addr = *addr;
223+
let align = if addr == 0 { 64 } else { (addr - (addr & (addr - 1))).min(64) };
224+
f(val, align).and_then(|it| Ok((addr, it)))
225+
};
226+
match self {
227+
MemoryMap::Empty => Ok(Default::default()),
228+
MemoryMap::Simple(m) => transform((&0, m)).map(|(addr, val)| {
229+
let mut map = FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());
230+
map.insert(addr, val);
231+
map
232+
}),
233+
MemoryMap::Complex(cm) => cm.memory.iter().map(transform).collect(),
234+
}
208235
}
209236

210-
fn get<'a>(&'a self, addr: usize, size: usize) -> Option<&'a [u8]> {
237+
fn get(&self, addr: usize, size: usize) -> Option<&[u8]> {
211238
if size == 0 {
212239
Some(&[])
213240
} else {
214-
self.memory.get(&addr)?.get(0..size)
241+
match self {
242+
MemoryMap::Empty => Some(&[]),
243+
MemoryMap::Simple(m) if addr == 0 => m.get(0..size),
244+
MemoryMap::Simple(_) => None,
245+
MemoryMap::Complex(cm) => cm.memory.get(&addr)?.get(0..size),
246+
}
215247
}
216248
}
217249
}

0 commit comments

Comments
 (0)