Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(541)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/validate.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of ssa;
6
7 class HValidator extends HInstructionVisitor {
8 bool isValid = true;
9 HGraph graph;
10
11 void visitGraph(HGraph visitee) {
12 graph = visitee;
13 visitDominatorTree(visitee);
14 }
15
16 void markInvalid(String reason) {
17 print(reason);
18 isValid = false;
19 }
20
21 // Note that during construction of the Ssa graph the basic blocks are
22 // not required to be valid yet.
23 void visitBasicBlock(HBasicBlock block) {
24 currentBlock = block;
25 if (!isValid) return; // Don't need to continue if we are already invalid.
26
27 // Test that the last instruction is a branching instruction and that the
28 // basic block contains the branch-target.
29 if (block.first == null || block.last == null) {
30 markInvalid("empty block");
31 }
32 if (block.last is !HControlFlow) {
33 markInvalid("block ends with non-tail node.");
34 }
35 if (block.last is HIf && block.successors.length != 2) {
36 markInvalid("If node without two successors");
37 }
38 if (block.last is HConditionalBranch && block.successors.length != 2) {
39 markInvalid("Conditional node without two successors");
40 }
41 if (block.last is HLoopBranch) {
42 // Assert that the block we inserted to avoid critical edges satisfies
43 // our assumptions. That is, it must not contain any instructions
44 // (although it may contain phi-updates).
45 HBasicBlock avoidCriticalEdgeBlock = block.successors.last;
46 if (avoidCriticalEdgeBlock.first is! HGoto) {
47 markInvalid("Critical edge block contains instructions");
48 }
49 }
50 if (block.last is HGoto && block.successors.length != 1) {
51 markInvalid("Goto node with not exactly one successor");
52 }
53 if (block.last is HJump && block.successors.length != 1) {
54 markInvalid("Break or continue node without one successor");
55 }
56 if ((block.last is HReturn || block.last is HThrow) &&
57 (block.successors.length != 1 || !block.successors[0].isExitBlock())) {
58 markInvalid("Return or throw node with > 1 successor "
59 "or not going to exit-block");
60 }
61 if (block.last is HExit && !block.successors.isEmpty) {
62 markInvalid("Exit block with successor");
63 }
64
65 if (block.successors.isEmpty && !block.isExitBlock()) {
66 markInvalid("Non-exit block without successor");
67 }
68
69 // Check that successors ids are always higher than the current one.
70 // TODO(floitsch): this is, of course, not true for back-branches.
71 if (block.id == null) markInvalid("block without id");
72 for (HBasicBlock successor in block.successors) {
73 if (!isValid) break;
74 if (successor.id == null) markInvalid("successor without id");
75 if (successor.id <= block.id && !successor.isLoopHeader()) {
76 markInvalid("successor with lower id, but not a loop-header");
77 }
78 }
79 // Make sure we don't have a critical edge.
80 if (isValid && block.successors.length > 1 &&
81 block.last is! HTry && block.last is! HExitTry &&
82 block.last is! HSwitch) {
83 for (HBasicBlock successor in block.successors) {
84 if (!isValid) break;
85 if (successor.predecessors.length >= 2) {
86 markInvalid("SSA graph contains critical edge.");
87 }
88 }
89 }
90
91 // Check that the entries in the dominated-list are sorted.
92 int lastId = 0;
93 for (HBasicBlock dominated in block.dominatedBlocks) {
94 if (!isValid) break;
95 if (!identical(dominated.dominator, block)) {
96 markInvalid("dominated block not pointing back");
97 }
98 if (dominated.id == null || dominated.id <= lastId) {
99 markInvalid("dominated.id == null or dominated has <= id");
100 }
101 lastId = dominated.id;
102 }
103
104 if (!isValid) return;
105 block.forEachPhi(visitInstruction);
106
107 // Check that the blocks of the parameters of a phi are dominating the
108 // corresponding predecessor block. Note that a block dominates
109 // itself.
110 block.forEachPhi((HPhi phi) {
111 assert(phi.inputs.length <= block.predecessors.length);
112 for (int i = 0; i < phi.inputs.length; i++) {
113 HInstruction input = phi.inputs[i];
114 if (!input.block.dominates(block.predecessors[i])) {
115 markInvalid("Definition does not dominate use");
116 }
117 }
118 });
119
120 // Check that the blocks of the inputs of an instruction dominate the
121 // instruction's block.
122 block.forEachInstruction((HInstruction instruction) {
123 for (HInstruction input in instruction.inputs) {
124 if (!input.block.dominates(block)) {
125 markInvalid("Definition does not dominate use");
126 }
127 }
128 });
129
130 super.visitBasicBlock(block);
131 }
132
133 /** Returns how often [instruction] is contained in [instructions]. */
134 static int countInstruction(List<HInstruction> instructions,
135 HInstruction instruction) {
136 int result = 0;
137 for (int i = 0; i < instructions.length; i++) {
138 if (identical(instructions[i], instruction)) result++;
139 }
140 return result;
141 }
142
143 /**
144 * Returns true if the predicate returns true for every instruction in the
145 * list. The argument to [f] is an instruction with the count of how often
146 * it appeared in the list [instructions].
147 */
148 static bool everyInstruction(List<HInstruction> instructions, Function f) {
149 var copy = new List<HInstruction>.from(instructions);
150 // TODO(floitsch): there is currently no way to sort HInstructions before
151 // we have assigned an ID. The loop is therefore O(n^2) for now.
152 for (int i = 0; i < copy.length; i++) {
153 var current = copy[i];
154 if (current == null) continue;
155 int count = 1;
156 for (int j = i + 1; j < copy.length; j++) {
157 if (identical(copy[j], current)) {
158 copy[j] = null;
159 count++;
160 }
161 }
162 if (!f(current, count)) return false;
163 }
164 return true;
165 }
166
167 void visitInstruction(HInstruction instruction) {
168 // Verifies that we are in the use list of our inputs.
169 bool hasCorrectInputs() {
170 bool inBasicBlock = instruction.isInBasicBlock();
171 return everyInstruction(instruction.inputs, (input, count) {
172 if (inBasicBlock) {
173 return input.isInBasicBlock()
174 && countInstruction(input.usedBy, instruction) == count;
175 } else {
176 return countInstruction(input.usedBy, instruction) == 0;
177 }
178 });
179 }
180
181 // Verifies that all our uses have us in their inputs.
182 bool hasCorrectUses() {
183 if (!instruction.isInBasicBlock()) return true;
184 return everyInstruction(instruction.usedBy, (use, count) {
185 return use.isInBasicBlock()
186 && countInstruction(use.inputs, instruction) == count;
187 });
188 }
189
190 if (!identical(instruction.block, currentBlock)) {
191 markInvalid("Instruction in wrong block");
192 }
193 if (!hasCorrectInputs()) {
194 markInvalid("Incorrect inputs");
195 }
196 if (!hasCorrectUses()) {
197 markInvalid("Incorrect uses");
198 }
199 }
200 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698