-
Notifications
You must be signed in to change notification settings - Fork 37
/
ShareStrings.hx
86 lines (79 loc) · 1.89 KB
/
ShareStrings.hx
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
import FlowUtil;
import Flow;
typedef StringShare = {
varName : String,
string : Flow,
count : Int
}
// A pass to change the code to share identical strings by introducing new global variables for them
class ShareStrings {
public static function shareStrings(p : Program) : Void {
var vars = 0;
var bigStrings = new Map<String,StringShare>();
// First, register all strings and find the duplicated ones
for (d in p.declsOrder) {
var e = p.topdecs.get(d);
FlowUtil.traverseExp(e, function(f) {
switch (f) {
case ConstantString(s, p): {
var seen = bigStrings.get(s);
if (seen != null) {
seen.count = seen.count + 1;
bigStrings.set(s, seen);
} else {
if (s.length > 5) {
var share = {
varName: "%" + vars,
string: f,
count: 1
};
bigStrings.set(s, share);
vars++;
}
}
}
default:
}
});
}
// Next, share the ones that can be shared
for (d in p.declsOrder) {
var e = p.topdecs.get(d);
var changed = FlowUtil.mapFlow(e, function(f) {
return switch (f) {
case ConstantString(s, p): {
var seen = bigStrings.get(s);
if (shouldShare(seen)) {
VarRef(seen.varName, p);
} else {
f;
}
}
default: f;
}
});
p.topdecs.set(d, changed);
}
var sharedStrings = new FlowArray();
for (s in bigStrings.iterator()) {
if (shouldShare(s)) {
sharedStrings.push(s.varName);
p.topdecs.set(s.varName, s.string);
}
}
p.declsOrder = sharedStrings.concat(p.declsOrder);
#if false
for (d in p.order) {
var e = p.topdecs.get(d);
Sys.println(d + "=" + Prettyprint.print(e));
}
#end
}
static function shouldShare(s : StringShare) : Bool {
if (s == null || s.count < 2) {
return false;
}
var saving = (s.count - 1) * FlowUtil.getString(s.string).length;
return saving > 0;
}
}