|
1 /* -*- Mode: Javascript; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 |
|
3 "use strict"; |
|
4 |
|
5 var functionBodies; |
|
6 |
|
7 function findAllPoints(blockId) |
|
8 { |
|
9 var points = []; |
|
10 var body; |
|
11 |
|
12 for (var xbody of functionBodies) { |
|
13 if (sameBlockId(xbody.BlockId, blockId)) { |
|
14 assert(!body); |
|
15 body = xbody; |
|
16 } |
|
17 } |
|
18 assert(body); |
|
19 |
|
20 if (!("PEdge" in body)) |
|
21 return; |
|
22 for (var edge of body.PEdge) { |
|
23 points.push([body, edge.Index[0]]); |
|
24 if (edge.Kind == "Loop") |
|
25 Array.prototype.push.apply(points, findAllPoints(edge.BlockId)); |
|
26 } |
|
27 |
|
28 return points; |
|
29 } |
|
30 |
|
31 function isMatchingDestructor(constructor, edge) |
|
32 { |
|
33 if (edge.Kind != "Call") |
|
34 return false; |
|
35 var callee = edge.Exp[0]; |
|
36 if (callee.Kind != "Var") |
|
37 return false; |
|
38 var variable = callee.Variable; |
|
39 assert(variable.Kind == "Func"); |
|
40 if (!/::~/.test(variable.Name[0])) |
|
41 return false; |
|
42 |
|
43 var constructExp = constructor.PEdgeCallInstance.Exp; |
|
44 assert(constructExp.Kind == "Var"); |
|
45 |
|
46 var destructExp = edge.PEdgeCallInstance.Exp; |
|
47 if (destructExp.Kind != "Var") |
|
48 return false; |
|
49 |
|
50 return sameVariable(constructExp.Variable, destructExp.Variable); |
|
51 } |
|
52 |
|
53 // Return all calls within the RAII scope of the constructor matched by |
|
54 // isConstructor() |
|
55 function allRAIIGuardedCallPoints(body, isConstructor) |
|
56 { |
|
57 if (!("PEdge" in body)) |
|
58 return []; |
|
59 |
|
60 var points = []; |
|
61 |
|
62 for (var edge of body.PEdge) { |
|
63 if (edge.Kind != "Call") |
|
64 continue; |
|
65 var callee = edge.Exp[0]; |
|
66 if (callee.Kind != "Var") |
|
67 continue; |
|
68 var variable = callee.Variable; |
|
69 assert(variable.Kind == "Func"); |
|
70 if (!isConstructor(variable.Name[0])) |
|
71 continue; |
|
72 if (edge.PEdgeCallInstance.Exp.Kind != "Var") |
|
73 continue; |
|
74 |
|
75 Array.prototype.push.apply(points, pointsInRAIIScope(body, edge)); |
|
76 } |
|
77 |
|
78 return points; |
|
79 } |
|
80 |
|
81 // Test whether the given edge is the constructor corresponding to the given |
|
82 // destructor edge |
|
83 function isMatchingConstructor(destructor, edge) |
|
84 { |
|
85 if (edge.Kind != "Call") |
|
86 return false; |
|
87 var callee = edge.Exp[0]; |
|
88 if (callee.Kind != "Var") |
|
89 return false; |
|
90 var variable = callee.Variable; |
|
91 if (variable.Kind != "Func") |
|
92 return false; |
|
93 var name = readable(variable.Name[0]); |
|
94 var destructorName = readable(destructor.Exp[0].Variable.Name[0]); |
|
95 var match = destructorName.match(/^(.*?::)~(\w+)\(/); |
|
96 if (!match) { |
|
97 printErr("Unhandled destructor syntax: " + destructorName); |
|
98 return false; |
|
99 } |
|
100 var constructorSubstring = match[1] + match[2]; |
|
101 if (name.indexOf(constructorSubstring) == -1) |
|
102 return false; |
|
103 |
|
104 var destructExp = destructor.PEdgeCallInstance.Exp; |
|
105 assert(destructExp.Kind == "Var"); |
|
106 |
|
107 var constructExp = edge.PEdgeCallInstance.Exp; |
|
108 if (constructExp.Kind != "Var") |
|
109 return false; |
|
110 |
|
111 return sameVariable(constructExp.Variable, destructExp.Variable); |
|
112 } |
|
113 |
|
114 function findMatchingConstructor(destructorEdge, body) |
|
115 { |
|
116 var worklist = [destructorEdge]; |
|
117 var predecessors = getPredecessors(body); |
|
118 while(worklist.length > 0) { |
|
119 var edge = worklist.pop(); |
|
120 if (isMatchingConstructor(destructorEdge, edge)) |
|
121 return edge; |
|
122 if (edge.Index[0] in predecessors) { |
|
123 for (var e of predecessors[edge.Index[0]]) |
|
124 worklist.push(e); |
|
125 } |
|
126 } |
|
127 printErr("Could not find matching constructor!"); |
|
128 debugger; |
|
129 } |
|
130 |
|
131 function pointsInRAIIScope(body, constructorEdge) { |
|
132 var seen = {}; |
|
133 var worklist = [constructorEdge.Index[1]]; |
|
134 var points = []; |
|
135 while (worklist.length) { |
|
136 var point = worklist.pop(); |
|
137 if (point in seen) |
|
138 continue; |
|
139 seen[point] = true; |
|
140 points.push([body, point]); |
|
141 var successors = getSuccessors(body); |
|
142 if (!(point in successors)) |
|
143 continue; |
|
144 for (var nedge of successors[point]) { |
|
145 if (isMatchingDestructor(constructorEdge, nedge)) |
|
146 continue; |
|
147 if (nedge.Kind == "Loop") |
|
148 Array.prototype.push.apply(points, findAllPoints(nedge.BlockId)); |
|
149 worklist.push(nedge.Index[1]); |
|
150 } |
|
151 } |
|
152 |
|
153 return points; |
|
154 } |