Skip to content

Commit fadc45a

Browse files
authored
[api-dep] feat: improve api-dep performance (#108)
* feat: complete api dependency graph generation * remove redundant comment, keep lifetime.rs empty * fix cargo fmt --check * refactor graph structure, add generic node in api dep graph * feat: refactor DepNode structure and use a better method to collect generic parameters * fix cargo fmt check * feat: extract lifetime constraint by subtyping * update api-dep
1 parent 91f4fd8 commit fadc45a

File tree

5 files changed

+61
-60
lines changed

5 files changed

+61
-60
lines changed

rapx/src/analysis/api_dep/extract.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId;
44
use rustc_infer::infer::region_constraints::Constraint;
55
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
66
use rustc_infer::traits::ObligationCause;
7-
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
7+
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
88
use rustc_span::Span;
99
struct FreeVarFolder<'tcx, 'a> {
1010
cx: TyCtxt<'tcx>,
@@ -32,7 +32,7 @@ impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for FreeVarFolder<'tcx, '_> {
3232
fn cx(&self) -> TyCtxt<'tcx> {
3333
self.cx
3434
}
35-
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
35+
fn fold_region(&mut self, _: ty::Region<'tcx>) -> ty::Region<'tcx> {
3636
self.free_var_cnt += 1;
3737
self.infcx
3838
.next_region_var(infer::RegionVariableOrigin::BorrowRegion(self.span))

rapx/src/analysis/api_dep/graph.rs

+33
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ pub struct ApiDepGraph<'tcx> {
2020
node_indices: HashMap<DepNode<'tcx>, NodeIndex>,
2121
}
2222

23+
pub struct Statistics {
24+
pub api_count: usize,
25+
pub type_count: usize,
26+
pub generic_param_count: usize,
27+
pub edge_cnt: usize,
28+
}
29+
2330
impl<'tcx> ApiDepGraph<'tcx> {
2431
pub fn new() -> ApiDepGraph<'tcx> {
2532
ApiDepGraph {
@@ -32,6 +39,32 @@ impl<'tcx> ApiDepGraph<'tcx> {
3239
&self.graph
3340
}
3441

42+
pub fn statistics(&self) -> Statistics {
43+
let mut api_cnt = 0;
44+
let mut ty_cnt = 0;
45+
let mut generic_param_cnt = 0;
46+
let mut edge_cnt = 0;
47+
48+
for node in self.graph.node_indices() {
49+
match self.graph[node] {
50+
DepNode::Api(_) => api_cnt += 1,
51+
DepNode::Ty(_) => ty_cnt += 1,
52+
DepNode::GenericParamDef(..) => generic_param_cnt += 1,
53+
}
54+
}
55+
56+
for edge in self.graph.edge_indices() {
57+
edge_cnt += 1;
58+
}
59+
60+
Statistics {
61+
api_count: api_cnt,
62+
type_count: ty_cnt,
63+
generic_param_count: generic_param_cnt,
64+
edge_cnt,
65+
}
66+
}
67+
3568
pub fn get_node(&mut self, node: DepNode<'tcx>) -> NodeIndex {
3669
if let Some(node_index) = self.node_indices.get(&node) {
3770
*node_index

rapx/src/analysis/api_dep/graph/ty_wrapper.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ pub fn desc_ty_str<'tcx>(ty: Ty<'tcx>, no: &mut usize, tcx: TyCtxt<'tcx>) -> Str
190190
match ty.kind() {
191191
ty::TyKind::Adt(adt_def, generic_arg) => {
192192
let mut ty_str = tcx.def_path_str(adt_def.did());
193-
if (!generic_arg.is_empty()) {
193+
if !generic_arg.is_empty() {
194194
ty_str += "<";
195195
ty_str += &generic_arg
196196
.iter()

rapx/src/analysis/api_dep/mod.rs

+25-25
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
mod extract;
22
mod graph;
33
mod lifetime;
4-
mod ty;
54
mod visitor;
6-
use crate::{rap_info, utils::fs::rap_create_file};
5+
use crate::{rap_debug, rap_info};
76
use graph::ApiDepGraph;
87
use rustc_hir::{
9-
def_id::{DefId, LocalDefId},
8+
def_id::{DefId, LocalDefId, LOCAL_CRATE},
109
intravisit::{self, FnKind, Visitor},
1110
BodyId, FnDecl,
1211
};
13-
use rustc_middle::{dep_graph, ty::TyCtxt};
14-
use rustc_span::Span;
12+
use rustc_middle::ty::TyCtxt;
1513

16-
use std::io::Write;
1714
use visitor::FnVisitor;
1815

1916
pub struct ApiDep<'tcx> {
@@ -24,31 +21,34 @@ impl<'tcx> ApiDep<'tcx> {
2421
pub fn new(tcx: TyCtxt<'tcx>) -> ApiDep<'tcx> {
2522
ApiDep { tcx }
2623
}
27-
pub fn start(&self) {
28-
rap_info!("Build API dependency graph");
24+
pub fn start(&self) -> ApiDepGraph<'tcx> {
25+
let local_crate_name = self.tcx.crate_name(LOCAL_CRATE);
26+
let local_crate_type = self.tcx.crate_types()[0];
27+
rap_debug!(
28+
"Build API dependency graph on {} ({})",
29+
local_crate_name.as_str(),
30+
local_crate_type
31+
);
32+
2933
let mut api_graph = ApiDepGraph::new();
3034
let mut fn_visitor = FnVisitor::new(self.tcx, &mut api_graph);
3135
self.tcx
3236
.hir()
3337
.visit_all_item_likes_in_crate(&mut fn_visitor);
34-
rap_info!("visitor find {} APIs.", fn_visitor.fn_cnt());
35-
let mut file = rap_create_file("visitor.txt", "fail when create file");
36-
fn_visitor.write_funcs(&mut file);
38+
rap_debug!("api-dep find {} APIs.", fn_visitor.fn_cnt());
3739

38-
api_graph.dump_to_dot("api_graph.dot", self.tcx);
40+
let statistics = api_graph.statistics();
41+
// print all statistics
42+
rap_debug!(
43+
"API Graph contains {} API nodes, {} type nodes, {} generic parameter def nodes",
44+
statistics.api_count,
45+
statistics.type_count,
46+
statistics.generic_param_count
47+
);
3948

40-
let mut file = rap_create_file("traverse.txt", "fail when create file");
41-
let mut fn_cnt = 0;
42-
// TODO: try self.tcx.mir_keys(())
43-
for local_def_id in self.tcx.iter_local_def_id() {
44-
let hir_map = self.tcx.hir();
45-
if hir_map.maybe_body_owned_by(local_def_id).is_some() {
46-
write!(&mut file, "{}\n", self.tcx.def_path_str(local_def_id))
47-
.expect("fail when write file");
48-
// rap_info!("find API: {}", self.tcx.def_path_str(local_def_id));
49-
fn_cnt += 1;
50-
}
51-
}
52-
rap_info!("find {} APIs.", fn_cnt);
49+
let dot_filename = format!("api_graph_{}_{}.dot", local_crate_name, local_crate_type);
50+
rap_info!("Dump API dependency graph to {}", dot_filename);
51+
api_graph.dump_to_dot(dot_filename, self.tcx);
52+
api_graph
5353
}
5454
}

rapx/src/analysis/api_dep/ty.rs

-32
This file was deleted.

0 commit comments

Comments
 (0)