Skip to content

Commit 1cb5ef1

Browse files
committed
Stop using a BTreeSet to store items.
We use sequential id's so a Vec<Option<T>> does the trick. This reduces the time for: time ./target/release/bindgen tests/stylo.hpp --no-rustfmt-bindings From ~6s to less than 5s on my machine.
1 parent 8a579b1 commit 1cb5ef1

File tree

3 files changed

+55
-62
lines changed

3 files changed

+55
-62
lines changed

src/ir/context.rs

Lines changed: 52 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ use parse::ClangItemParser;
2727
use proc_macro2::{Ident, Span};
2828
use std::borrow::Cow;
2929
use std::cell::Cell;
30-
use std::collections::btree_map::{self, BTreeMap};
3130
use std::iter::IntoIterator;
3231
use std::mem;
3332
use std::collections::HashMap as StdHashMap;
@@ -302,14 +301,8 @@ enum TypeKey {
302301
/// A context used during parsing and generation of structs.
303302
#[derive(Debug)]
304303
pub struct BindgenContext {
305-
/// The map of all the items parsed so far.
306-
///
307-
/// It's a BTreeMap because we want the keys to be sorted to have consistent
308-
/// output.
309-
items: BTreeMap<ItemId, Item>,
310-
311-
/// The next item id to use during this bindings regeneration.
312-
next_item_id: ItemId,
304+
/// The map of all the items parsed so far, keyed off ItemId.
305+
items: Vec<Option<Item>>,
313306

314307
/// Clang USR to type map. This is needed to be able to associate types with
315308
/// item ids during parsing.
@@ -597,12 +590,11 @@ If you encounter an error missing from this list, please file an issue or a PR!"
597590
let root_module = Self::build_root_module(ItemId(0));
598591
let root_module_id = root_module.id().as_module_id_unchecked();
599592

600-
let mut me = BindgenContext {
601-
items: Default::default(),
593+
BindgenContext {
594+
items: vec![Some(root_module)],
602595
types: Default::default(),
603596
type_params: Default::default(),
604597
modules: Default::default(),
605-
next_item_id: ItemId(1),
606598
root_module: root_module_id,
607599
current_module: root_module_id,
608600
semantic_parents: Default::default(),
@@ -631,11 +623,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
631623
have_destructor: None,
632624
has_type_param_in_array: None,
633625
has_float: None,
634-
};
635-
636-
me.add_item(root_module, None, None);
637-
638-
me
626+
}
639627
}
640628

641629
/// Creates a timer for the current bindgen phase. If time_phases is `true`,
@@ -718,7 +706,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
718706
self.need_bitfield_allocation.push(id);
719707
}
720708

721-
let old_item = self.items.insert(id, item);
709+
let old_item = mem::replace(&mut self.items[id.0], Some(item));
722710
assert!(
723711
old_item.is_none(),
724712
"should not have already associated an item with the given id"
@@ -746,7 +734,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
746734
debug!(
747735
"Invalid declaration {:?} found for type {:?}",
748736
declaration,
749-
self.items.get(&id).unwrap().kind().expect_type()
737+
self.resolve_item_fallible(id).unwrap().kind().expect_type()
750738
);
751739
return;
752740
}
@@ -775,9 +763,9 @@ If you encounter an error missing from this list, please file an issue or a PR!"
775763
/// details.
776764
fn add_item_to_module(&mut self, item: &Item) {
777765
assert!(item.id() != self.root_module);
778-
assert!(!self.items.contains_key(&item.id()));
766+
assert!(self.resolve_item_fallible(item.id()).is_none());
779767

780-
if let Some(parent) = self.items.get_mut(&item.parent_id()) {
768+
if let Some(ref mut parent) = self.items[item.parent_id().0] {
781769
if let Some(module) = parent.as_module_mut() {
782770
debug!(
783771
"add_item_to_module: adding {:?} as child of parent module {:?}",
@@ -796,8 +784,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
796784
self.current_module
797785
);
798786

799-
self.items
800-
.get_mut(&self.current_module.into())
787+
self.items[(self.current_module.0).0]
788+
.as_mut()
801789
.expect("Should always have an item for self.current_module")
802790
.as_module_mut()
803791
.expect("self.current_module should always be a module")
@@ -825,7 +813,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
825813
self.add_item_to_module(&item);
826814

827815
let id = item.id();
828-
let old_item = self.items.insert(id, item);
816+
let old_item = mem::replace(&mut self.items[id.0], Some(item));
829817
assert!(
830818
old_item.is_none(),
831819
"should not have already associated an item with the given id"
@@ -941,8 +929,14 @@ If you encounter an error missing from this list, please file an issue or a PR!"
941929
}
942930

943931
/// Iterate over all items that have been defined.
944-
pub fn items<'a>(&'a self) -> btree_map::Iter<'a, ItemId, Item> {
945-
self.items.iter()
932+
pub fn items(&self) -> impl Iterator<Item = (ItemId, &Item)> {
933+
self.items
934+
.iter()
935+
.enumerate()
936+
.filter_map(|(index, item)| {
937+
let item = item.as_ref()?;
938+
Some((ItemId(index), item))
939+
})
946940
}
947941

948942
/// Have we collected all unresolved type references yet?
@@ -957,7 +951,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
957951
debug_assert!(!self.collected_typerefs);
958952
self.collected_typerefs = true;
959953
let mut typerefs = vec![];
960-
for (id, ref mut item) in &mut self.items {
954+
955+
for (id, item) in self.items() {
961956
let kind = item.kind();
962957
let ty = match kind.as_type() {
963958
Some(ty) => ty,
@@ -966,7 +961,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
966961

967962
match *ty.kind() {
968963
TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) => {
969-
typerefs.push((*id, ty.clone(), loc, parent_id));
964+
typerefs.push((id, ty.clone(), loc, parent_id));
970965
}
971966
_ => {}
972967
};
@@ -987,7 +982,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
987982
Item::new_opaque_type(self.next_item_id(), &ty, self)
988983
});
989984

990-
let item = self.items.get_mut(&id).unwrap();
985+
let item = self.items[id.0].as_mut().unwrap();
991986
*item.kind_mut().as_type_mut().unwrap().kind_mut() =
992987
TypeKind::ResolvedTypeRef(resolved);
993988
resolved
@@ -1018,11 +1013,11 @@ If you encounter an error missing from this list, please file an issue or a PR!"
10181013
where
10191014
F: (FnOnce(&BindgenContext, &mut Item) -> T)
10201015
{
1021-
let mut item = self.items.remove(&id).unwrap();
1016+
let mut item = self.items[id.0].take().unwrap();
10221017

10231018
let result = f(self, &mut item);
10241019

1025-
let existing = self.items.insert(id, item);
1020+
let existing = mem::replace(&mut self.items[id.0], Some(item));
10261021
assert!(existing.is_none());
10271022

10281023
result
@@ -1051,15 +1046,13 @@ If you encounter an error missing from this list, please file an issue or a PR!"
10511046
fn deanonymize_fields(&mut self) {
10521047
let _t = self.timer("deanonymize_fields");
10531048

1054-
let comp_item_ids: Vec<ItemId> = self.items
1055-
.iter()
1049+
let comp_item_ids: Vec<ItemId> = self.items()
10561050
.filter_map(|(id, item)| {
10571051
if item.kind().as_type()?.is_comp() {
10581052
return Some(id);
10591053
}
10601054
None
10611055
})
1062-
.cloned()
10631056
.collect();
10641057

10651058
for id in comp_item_ids {
@@ -1090,7 +1083,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
10901083

10911084
let mut replacements = vec![];
10921085

1093-
for (id, item) in self.items.iter() {
1086+
for (id, item) in self.items() {
10941087
if item.annotations().use_instead_of().is_some() {
10951088
continue;
10961089
}
@@ -1114,10 +1107,10 @@ If you encounter an error missing from this list, please file an issue or a PR!"
11141107
let replacement = self.replacements.get(&path[1..]);
11151108

11161109
if let Some(replacement) = replacement {
1117-
if replacement != id {
1110+
if *replacement != id {
11181111
// We set this just after parsing the annotation. It's
11191112
// very unlikely, but this can happen.
1120-
if self.items.get(replacement).is_some() {
1113+
if self.resolve_item_fallible(*replacement).is_some() {
11211114
replacements.push((id.expect_type_id(self), replacement.expect_type_id(self)));
11221115
}
11231116
}
@@ -1126,9 +1119,9 @@ If you encounter an error missing from this list, please file an issue or a PR!"
11261119

11271120
for (id, replacement_id) in replacements {
11281121
debug!("Replacing {:?} with {:?}", id, replacement_id);
1129-
11301122
let new_parent = {
1131-
let item = self.items.get_mut(&id.into()).unwrap();
1123+
let item_id: ItemId = id.into();
1124+
let item = self.items[item_id.0].as_mut().unwrap();
11321125
*item.kind_mut().as_type_mut().unwrap().kind_mut() =
11331126
TypeKind::ResolvedTypeRef(replacement_id);
11341127
item.parent_id()
@@ -1146,8 +1139,9 @@ If you encounter an error missing from this list, please file an issue or a PR!"
11461139
continue;
11471140
}
11481141

1149-
self.items
1150-
.get_mut(&replacement_id.into())
1142+
let replacement_item_id: ItemId = replacement_id.into();
1143+
self.items[replacement_item_id.0]
1144+
.as_mut()
11511145
.unwrap()
11521146
.set_parent_for_replacement(new_parent);
11531147

@@ -1183,16 +1177,16 @@ If you encounter an error missing from this list, please file an issue or a PR!"
11831177
continue;
11841178
}
11851179

1186-
self.items
1187-
.get_mut(&old_module)
1180+
self.items[old_module.0]
1181+
.as_mut()
11881182
.unwrap()
11891183
.as_module_mut()
11901184
.unwrap()
11911185
.children_mut()
11921186
.remove(&replacement_id.into());
11931187

1194-
self.items
1195-
.get_mut(&new_module)
1188+
self.items[new_module.0]
1189+
.as_mut()
11961190
.unwrap()
11971191
.as_module_mut()
11981192
.unwrap()
@@ -1260,7 +1254,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
12601254
assert!(self.in_codegen_phase());
12611255
assert!(self.current_module == self.root_module);
12621256

1263-
let roots = self.items().map(|(&id, _)| id);
1257+
let roots = self.items().map(|(id, _)| id);
12641258
traversal::AssertNoDanglingItemsTraversal::new(
12651259
self,
12661260
roots,
@@ -1276,7 +1270,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
12761270
assert!(self.in_codegen_phase());
12771271
assert!(self.current_module == self.root_module);
12781272

1279-
for (&id, _item) in self.items() {
1273+
for (id, _item) in self.items() {
12801274
if id == self.root_module {
12811275
continue;
12821276
}
@@ -1467,7 +1461,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
14671461
debug_assert!(item.kind().is_type());
14681462
self.add_item_to_module(&item);
14691463
let id = item.id();
1470-
let old_item = self.items.insert(id, item);
1464+
let old_item = mem::replace(&mut self.items[id.0], Some(item));
14711465
assert!(old_item.is_none(), "Inserted type twice?");
14721466
}
14731467

@@ -1502,21 +1496,21 @@ If you encounter an error missing from this list, please file an issue or a PR!"
15021496
///
15031497
/// Panics if the id resolves to an item that is not a type.
15041498
pub fn safe_resolve_type(&self, type_id: TypeId) -> Option<&Type> {
1505-
self.items.get(&type_id.into()).map(|t| t.kind().expect_type())
1499+
self.resolve_item_fallible(type_id).map(|t| t.kind().expect_type())
15061500
}
15071501

15081502
/// Resolve the given `ItemId` into an `Item`, or `None` if no such item
15091503
/// exists.
15101504
pub fn resolve_item_fallible<Id: Into<ItemId>>(&self, id: Id) -> Option<&Item> {
1511-
self.items.get(&id.into())
1505+
self.items.get(id.into().0)?.as_ref()
15121506
}
15131507

15141508
/// Resolve the given `ItemId` into an `Item`.
15151509
///
15161510
/// Panics if the given id does not resolve to any item.
15171511
pub fn resolve_item<Id: Into<ItemId>>(&self, item_id: Id) -> &Item {
15181512
let item_id = item_id.into();
1519-
match self.items.get(&item_id) {
1513+
match self.resolve_item_fallible(item_id) {
15201514
Some(item) => item,
15211515
None => panic!("Not an item: {:?}", item_id),
15221516
}
@@ -1782,8 +1776,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
17821776
sub_item
17831777
);
17841778
self.add_item_to_module(&sub_item);
1785-
debug_assert!(sub_id == sub_item.id());
1786-
self.items.insert(sub_id, sub_item);
1779+
debug_assert_eq!(sub_id, sub_item.id());
1780+
self.items[sub_id.0] = Some(sub_item);
17871781
args.push(sub_id.as_type_id_unchecked());
17881782
}
17891783
}
@@ -1842,8 +1836,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
18421836
// Bypass all the validations in add_item explicitly.
18431837
debug!("instantiate_template: inserting item: {:?}", item);
18441838
self.add_item_to_module(&item);
1845-
debug_assert!(with_id == item.id());
1846-
self.items.insert(with_id, item);
1839+
debug_assert_eq!(with_id, item.id());
1840+
self.items[with_id.0] = Some(item);
18471841
Some(with_id.as_type_id_unchecked())
18481842
}
18491843

@@ -1999,8 +1993,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
19991993

20001994
/// Returns the next item id to be used for an item.
20011995
pub fn next_item_id(&mut self) -> ItemId {
2002-
let ret = self.next_item_id;
2003-
self.next_item_id = ItemId(self.next_item_id.0 + 1);
1996+
let ret = ItemId(self.items.len());
1997+
self.items.push(None);
20041998
ret
20051999
}
20062000

@@ -2349,7 +2343,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
23492343
}
23502344
}
23512345
})
2352-
.map(|(&id, _)| id)
2346+
.map(|(id, _)| id)
23532347
.collect::<Vec<_>>();
23542348

23552349
// The reversal preserves the expected ordering of traversal,

src/ir/dot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ where
3232
let mut err: Option<io::Result<_>> = None;
3333

3434
for (id, item) in ctx.items() {
35-
let is_whitelisted = ctx.whitelisted_items().contains(id);
35+
let is_whitelisted = ctx.whitelisted_items().contains(&id);
3636

3737
writeln!(
3838
&mut dot_file,

src/ir/objc.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,9 @@ impl ObjCInterface {
131131
if protocol.is_protocol
132132
{
133133
debug!("Checking protocol {}, ty.name {:?}", protocol.name, ty.name());
134-
if Some(needle.as_ref()) == ty.name()
135-
{
134+
if Some(needle.as_ref()) == ty.name() {
136135
debug!("Found conforming protocol {:?}", item);
137-
interface.conforms_to.push(*id);
136+
interface.conforms_to.push(id);
138137
break;
139138
}
140139
}

0 commit comments

Comments
 (0)