forked from s-arash/ascent
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rs
159 lines (129 loc) · 4.21 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#[path ="../tracking_alloc.rs"]
mod tracking_alloc;
use std::alloc::System;
use std::borrow::Borrow;
use ascent::ascent;
use ascent::internal::Instant;
use itertools::Itertools;
use ascent_byods_rels::eqrel;
use tracking_alloc::TrackingAllocator;
#[global_allocator]
static GLOBAL: TrackingAllocator<System> = TrackingAllocator(System);
type Symbol = &'static str;
// examples adapted from Souffle's eqrel paper (https://souffle-lang.github.io/pdf/pact19.pdf)
ascent! {
#![measure_rule_times]
/// Steensgaard analysis using `eqrel`
struct Steensgaard;
relation alloc(Symbol, Symbol);
// x := y;
relation assign(Symbol, Symbol);
// x := y.f;
relation load(Symbol, Symbol, Symbol);
// x.f := y;
relation store(Symbol, Symbol, Symbol);
#[ds(eqrel)]
relation vpt(Symbol, Symbol);
// assignments
vpt(x,y) <--
assign(x,y);
// allocation sites
vpt(x,y) <--
alloc(x,y);
// load/store pairs
vpt(y,p) <--
store(x,f, y),
load(p,q,f),
vpt(x,q);
}
ascent! {
#![measure_rule_times]
/// Explicit Steensgaard analysis
struct SteensgaardExplicit;
relation alloc(Symbol, Symbol);
// x := y;
relation assign(Symbol, Symbol);
// x := y.f;
relation load(Symbol, Symbol, Symbol);
// x.f := y;
relation store(Symbol, Symbol, Symbol);
relation vpt(Symbol, Symbol);
vpt(y, x), vpt(x, x) <-- vpt(x, y);
vpt(x, z) <-- vpt(x, y), vpt(y, z);
// assignments
vpt(x,y) <--
assign(x,y);
// allocation sites
vpt(x,y) <--
alloc(x,y);
// load/store pairs
vpt(y,p) <--
store(x,f, y),
load(p,q,f),
vpt(x,q);
}
fn read_csv<T>(path: &str) -> impl Iterator<Item = T>
where
for<'de> T: serde::de::Deserialize<'de>,
{
csv::ReaderBuilder::new()
.delimiter(b'\t')
.has_headers(false)
.double_quote(false)
.quoting(false)
.from_path(path)
.unwrap()
.into_deserialize()
.map(|x| x.unwrap())
}
fn main() {
let path = "./steensgaard/openjdk_javalang_steensgaard/";
let get_path = |x: &str| format!("{path}{x}");
println!("Running eqrel version.");
let mem_use_before = tracking_alloc::current_alloc();
let start_time = Instant::now();
let mut prog = Steensgaard::default();
prog.alloc = read_csv::<(String, String)>(&get_path("alloc.facts"))
.map(|(x, y)| (leak(x), leak(y)))
.collect_vec();
prog.assign = read_csv::<(String, String)>(&get_path("assign.facts"))
.map(|(x, y)| (leak(x), leak(y)))
.collect_vec();
prog.load = read_csv::<(String, String, String)>(&get_path("load.facts"))
.map(|(x, y, z)| (leak(x), leak(y), leak(z)))
.collect_vec();
prog.store = read_csv::<(String, String, String)>(&get_path("store.facts"))
.map(|(x, y, z)| (leak(x), leak(y), leak(z)))
.collect_vec();
prog.run();
println!("mem use: {:.2} Mib", (tracking_alloc::max_alloc() - mem_use_before) as f64 / 2f64.powi(20));
println!("everything took: {:?}", start_time.elapsed());
println!("vpt size: {}", prog.__vpt_ind_common.count_exact());
tracking_alloc::reset_max_alloc();
// Explicit version:
println!("");
println!("Running Explicit version. This will take FOREVER!");
let mem_use_before = tracking_alloc::current_alloc();
let start_time = Instant::now();
let mut prog = SteensgaardExplicit::default();
prog.alloc = read_csv::<(String, String)>(&get_path("alloc.facts"))
.map(|(x, y)| (leak(x), leak(y)))
.collect_vec();
prog.assign = read_csv::<(String, String)>(&get_path("assign.facts"))
.map(|(x, y)| (leak(x), leak(y)))
.collect_vec();
prog.load = read_csv::<(String, String, String)>(&get_path("load.facts"))
.map(|(x, y, z)| (leak(x), leak(y), leak(z)))
.collect_vec();
prog.store = read_csv::<(String, String, String)>(&get_path("store.facts"))
.map(|(x, y, z)| (leak(x), leak(y), leak(z)))
.collect_vec();
prog.run();
println!("mem use: {:.2} Mib", (tracking_alloc::max_alloc() - mem_use_before) as f64 / 2f64.powi(20));
println!("everything took: {:?}", start_time.elapsed());
println!("vpt size: {}", prog.vpt.len());
}
fn leak<T: Borrow<TB> + 'static, TB: ?Sized>(x: T) -> &'static TB {
let leaked: &'static T = Box::leak(Box::new(x));
leaked.borrow()
}