Skip to content

Commit 3ffe9a1

Browse files
committed
pipeline: .verify()
1 parent c911d7d commit 3ffe9a1

File tree

6 files changed

+124
-8
lines changed

6 files changed

+124
-8
lines changed

lib/pipeline/cfg/block.js

+24
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,27 @@ Block.prototype.link = function link() {
8787
var b = this.predecessors[1];
8888
this.setControl(a.getLastControl(), b.getLastControl());
8989
};
90+
91+
Block.prototype._shortId = function _shortId() {
92+
return 'b' + this.blockIndex + '[' + this.opcode + ']';
93+
};
94+
95+
Block.prototype.verify = function verify() {
96+
pipeline.Pipeline.Node.prototype.verify.call(this);
97+
98+
var id = this._shortId();
99+
for (var i = 0; i < this.successors.length; i++) {
100+
var succ = this.successors[i];
101+
assert(succ.predecessors.indexOf(this) !== -1,
102+
'Not found ' + id + ' in ' + succ._shortId() + ' predecessors');
103+
}
104+
105+
for (var i = 0; i < this.predecessors.length; i++) {
106+
var pred = this.predecessors[i];
107+
assert(pred.successors.indexOf(this) !== -1,
108+
'Not found ' + id + ' in ' + pred._shortId() + ' successors');
109+
}
110+
111+
assert(!(this.successors.length === 2 && this.predecessors.length === 2),
112+
'X intersection at ' + id);
113+
};

lib/pipeline/pipeline/index.js

+5
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,8 @@ Pipeline.prototype.cut = function cut(node) {
8080

8181
this._maybeRemove(node);
8282
};
83+
84+
Pipeline.prototype.verify = function verify() {
85+
for (var i = 0; i < this.nodes.length; i++)
86+
this.nodes[i].verify();
87+
};

lib/pipeline/pipeline/node.js

+62
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,65 @@ Node.prototype.replace = function replace(other) {
194194
}
195195
this.controlUses.length = 0;
196196
};
197+
198+
Node.prototype._shortId = function _shortId() {
199+
return 'i' + this.index + '[' + this.opcode + ']';
200+
};
201+
202+
Node.prototype.verify = function verify() {
203+
var id = this._shortId();
204+
205+
// Verify that every input has use at this node
206+
for (var i = 0; i < this.inputs.length; i++) {
207+
var input = this.inputs[i];
208+
209+
var found = false;
210+
for (var j = 0; !found && j < input.uses.length; j += 2) {
211+
var use = input.uses[j];
212+
var useIndex = input.uses[j + 1];
213+
if (use === this && useIndex === i)
214+
found = true;
215+
}
216+
217+
assert(found,
218+
id + '->' + input._shortId() +
219+
': input without use in other node');
220+
}
221+
222+
// Verify that every control has use at this node
223+
assert(this.control.length <= 2, id + ': too much control inputs');
224+
for (var i = 0; i < this.control.length; i++) {
225+
var control = this.control[i];
226+
227+
var found = false;
228+
for (var j = 0; !found && j < control.controlUses.length; j += 2) {
229+
var use = control.controlUses[j];
230+
var useIndex = control.controlUses[j + 1];
231+
if (use === this && useIndex === i)
232+
found = true;
233+
}
234+
235+
assert(found,
236+
id + '<-' + control._shortId() +
237+
': control without use in other node');
238+
}
239+
240+
// Verify that uses have their inputs
241+
for (var i = 0; i < this.uses.length; i += 2) {
242+
var use = this.uses[i];
243+
var useIndex = this.uses[i + 1];
244+
245+
assert.equal(use.inputs[useIndex],
246+
this,
247+
'Use for ' + id + ' not found at ' + use._shortId());
248+
}
249+
250+
for (var i = 0; i < this.controlUses.length; i += 2) {
251+
var use = this.controlUses[i];
252+
var useIndex = this.controlUses[i + 1];
253+
254+
assert.equal(use.control[useIndex],
255+
this,
256+
'Use for ' + id + ' not found at ' + use._shortId());
257+
}
258+
};

test/cfg-test.js

+22-8
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ describe('JSON CFG Builder', function() {
4040
assert(phi.block === merge);
4141

4242
p.link();
43+
p.verify();
4344

4445
// Normal export
4546
assert.deepEqual(p.render('json'), fixtures.json.p1);
@@ -50,6 +51,7 @@ describe('JSON CFG Builder', function() {
5051

5152
it('should parse CFG', function() {
5253
p.parse(fixtures.json.p1cfg, { cfg: true }, 'json');
54+
p.verify();
5355

5456
// NOTE: we can't use `.render()` + `deepEqual()` here, because the indexes
5557
// are off after parsing
@@ -87,6 +89,7 @@ describe('JSON CFG Builder', function() {
8789

8890
p.reindex();
8991
p.link();
92+
p.verify();
9093

9194
// CFG export
9295
var text = p.render({ cfg: true }, 'printable');
@@ -128,17 +131,23 @@ describe('JSON CFG Builder', function() {
128131

129132
var head = p.jumpFrom(start);
130133
var read = p.add('read');
131-
var branch = p.addControl('if', [ read ]);
132134

133-
var body = p.jumpFrom(head);
135+
var next = p.jumpFrom(head);
136+
137+
var branch = p.addControl('if', [ read ]);
138+
var body = p.jumpFrom(next);
134139
p.add('print');
140+
141+
// Ensure no X intersection
135142
body.jump(head);
136143

137-
var end = p.jumpFrom(head);
144+
var end = p.jumpFrom(next);
138145
p.addControl('return', read);
139146

140147
p.reindex();
141148
p.link();
149+
console.log(p.render({ cfg: true }, 'printable'));
150+
p.verify();
142151

143152
// CFG export
144153
var text = p.render({ cfg: true }, 'printable');
@@ -150,15 +159,18 @@ describe('JSON CFG Builder', function() {
150159
b0 -> b1
151160
b1 {
152161
i1 = read
153-
i2 = if ^b1, i1
154162
}
155-
b1 -> b2, b3
163+
b1 -> b2
156164
b2 {
157-
i3 = print
165+
i2 = if ^b2, i1
158166
}
159-
b2 -> b1
167+
b2 -> b3, b4
160168
b3 {
161-
i4 = return ^b3, i1
169+
i3 = print
170+
}
171+
b3 -> b1
172+
b4 {
173+
i4 = return ^b4, i1
162174
}
163175
}
164176
*/}));
@@ -184,6 +196,7 @@ describe('JSON CFG Builder', function() {
184196
right.jump(merge);
185197

186198
p.link();
199+
p.verify();
187200

188201
var text = p.render('printable');
189202
assertText.equal(text, fixtures.fn2str(function() {/*
@@ -208,6 +221,7 @@ describe('JSON CFG Builder', function() {
208221

209222
p.remove(rem);
210223
p.link();
224+
p.verify();
211225

212226
var text = p.render({ cfg: true }, 'printable');
213227
assertText.equal(text, fixtures.fn2str(function() {/*

test/dominance-test.js

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ describe('JSON Dominance', function() {
3636
p.addControl('return', [ phi ]);
3737

3838
p.link();
39+
p.verify();
3940

4041
// Dominance export
4142
assert.deepEqual(p.render({
@@ -47,6 +48,8 @@ describe('JSON Dominance', function() {
4748
it('should parse CFG with Dominator tree', function() {
4849
p.parse(fixtures.json.p2dom, { cfg: true, dominance: true }, 'json');
4950

51+
p.verify();
52+
5053
// Tree
5154
assert(p.blocks[0].parent === null);
5255
assert(p.blocks[1].parent === p.blocks[0]);
@@ -88,6 +91,7 @@ describe('JSON Dominance', function() {
8891
p.parse(input, { cfg: true, dominance: true }, 'printable');
8992

9093
p.enumerate();
94+
p.verify();
9195

9296
/*
9397
* b0

test/pipeline-test.js

+7
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ describe('JSON Pipeline', function() {
4444

4545
p.remove(extra1);
4646
p.remove(extra2);
47+
p.verify();
4748

4849
assert.equal(one.uses.length, 2);
4950
assert.equal(two.uses.length, 2);
@@ -58,6 +59,7 @@ describe('JSON Pipeline', function() {
5859
var end = p.add('end').setControl(middle);
5960

6061
p.remove(middle);
62+
p.verify();
6163

6264
assertText.equal(p.render('printable'), fixtures.fn2str(function() {/*
6365
pipeline {
@@ -76,6 +78,7 @@ describe('JSON Pipeline', function() {
7678

7779
p.cut(branch);
7880
assert.equal(start.controlUses.length, 0);
81+
p.verify();
7982

8083
assertText.equal(p.render('printable'), fixtures.fn2str(function() {/*
8184
pipeline {
@@ -100,6 +103,7 @@ describe('JSON Pipeline', function() {
100103
assert.equal(three.uses.length, 2);
101104
assert.equal(three.uses[0], add);
102105
assert.equal(three.uses[1], 0);
106+
p.verify();
103107

104108
assertText.equal(p.render('printable'), fixtures.fn2str(function() {/*
105109
pipeline {
@@ -140,6 +144,7 @@ describe('JSON Pipeline', function() {
140144
assert.equal(replaced.controlUses.length, 2);
141145
assert.equal(replaced.control.length, 1);
142146
assert.equal(end.control.length, 1);
147+
p.verify();
143148

144149
assertText.equal(p.render('printable'), fixtures.fn2str(function() {/*
145150
pipeline {
@@ -175,6 +180,7 @@ describe('JSON Pipeline', function() {
175180
var end = p.add('end').setControl(middle);
176181

177182
middle.removeControl();
183+
p.verify();
178184

179185
assertText.equal(p.render('printable'), fixtures.fn2str(function() {/*
180186
pipeline {
@@ -193,6 +199,7 @@ describe('JSON Pipeline', function() {
193199

194200
assert.equal(start.controlUses.length, 2);
195201
assert.equal(middle.controlUses.length, 2);
202+
p.verify();
196203

197204
assertText.equal(p.render('printable'), fixtures.fn2str(function() {/*
198205
pipeline {

0 commit comments

Comments
 (0)