blob: 693b414650596a495711ebee885490e164058a2c [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/verifier.h"
6
7#include <deque>
8#include <queue>
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009#include <sstream>
10#include <string>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012#include "src/bit-vector.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/compiler/generic-algorithm.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014#include "src/compiler/graph-inl.h"
15#include "src/compiler/graph.h"
16#include "src/compiler/node.h"
17#include "src/compiler/node-properties-inl.h"
18#include "src/compiler/node-properties.h"
19#include "src/compiler/opcodes.h"
20#include "src/compiler/operator.h"
21#include "src/compiler/schedule.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022#include "src/compiler/simplified-operator.h"
23#include "src/ostreams.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024
25namespace v8 {
26namespace internal {
27namespace compiler {
28
29
30static bool IsDefUseChainLinkPresent(Node* def, Node* use) {
31 Node::Uses uses = def->uses();
32 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
33 if (*it == use) return true;
34 }
35 return false;
36}
37
38
39static bool IsUseDefChainLinkPresent(Node* def, Node* use) {
40 Node::Inputs inputs = use->inputs();
41 for (Node::Inputs::iterator it = inputs.begin(); it != inputs.end(); ++it) {
42 if (*it == def) return true;
43 }
44 return false;
45}
46
47
48class Verifier::Visitor : public NullNodeVisitor {
49 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050 Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051
52 // Fulfills the PreNodeCallback interface.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040053 void Pre(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054
Emily Bernierd0a1eb72015-03-24 16:35:39 -040055 Zone* zone;
56 Typing typing;
57
58 private:
59 // TODO(rossberg): Get rid of these once we got rid of NodeProperties.
60 Bounds bounds(Node* node) { return NodeProperties::GetBounds(node); }
61 Node* ValueInput(Node* node, int i = 0) {
62 return NodeProperties::GetValueInput(node, i);
63 }
64 FieldAccess Field(Node* node) {
65 DCHECK(node->opcode() == IrOpcode::kLoadField ||
66 node->opcode() == IrOpcode::kStoreField);
67 return OpParameter<FieldAccess>(node);
68 }
69 ElementAccess Element(Node* node) {
70 DCHECK(node->opcode() == IrOpcode::kLoadElement ||
71 node->opcode() == IrOpcode::kStoreElement);
72 return OpParameter<ElementAccess>(node);
73 }
74 void CheckNotTyped(Node* node) {
75 if (NodeProperties::IsTyped(node)) {
76 std::ostringstream str;
77 str << "TypeError: node #" << node->opcode() << ":"
78 << node->op()->mnemonic() << " should never have a type";
79 V8_Fatal(__FILE__, __LINE__, str.str().c_str());
80 }
81 }
82 void CheckUpperIs(Node* node, Type* type) {
83 if (typing == TYPED && !bounds(node).upper->Is(type)) {
84 std::ostringstream str;
85 str << "TypeError: node #" << node->opcode() << ":"
86 << node->op()->mnemonic() << " upper bound ";
87 bounds(node).upper->PrintTo(str);
88 str << " is not ";
89 type->PrintTo(str);
90 V8_Fatal(__FILE__, __LINE__, str.str().c_str());
91 }
92 }
93 void CheckUpperMaybe(Node* node, Type* type) {
94 if (typing == TYPED && !bounds(node).upper->Maybe(type)) {
95 std::ostringstream str;
96 str << "TypeError: node #" << node->opcode() << ":"
97 << node->op()->mnemonic() << " upper bound ";
98 bounds(node).upper->PrintTo(str);
99 str << " must intersect ";
100 type->PrintTo(str);
101 V8_Fatal(__FILE__, __LINE__, str.str().c_str());
102 }
103 }
104 void CheckValueInputIs(Node* node, int i, Type* type) {
105 Node* input = ValueInput(node, i);
106 if (typing == TYPED && !bounds(input).upper->Is(type)) {
107 std::ostringstream str;
108 str << "TypeError: node #" << node->opcode() << ":"
109 << node->op()->mnemonic() << "(input @" << i << " = "
110 << input->opcode() << ":" << input->op()->mnemonic()
111 << ") upper bound ";
112 bounds(input).upper->PrintTo(str);
113 str << " is not ";
114 type->PrintTo(str);
115 V8_Fatal(__FILE__, __LINE__, str.str().c_str());
116 }
117 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118};
119
120
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400121void Verifier::Visitor::Pre(Node* node) {
122 int value_count = node->op()->ValueInputCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123 int context_count = OperatorProperties::GetContextInputCount(node->op());
124 int frame_state_count =
125 OperatorProperties::GetFrameStateInputCount(node->op());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400126 int effect_count = node->op()->EffectInputCount();
127 int control_count = node->op()->ControlInputCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128
129 // Verify number of inputs matches up.
130 int input_count = value_count + context_count + frame_state_count +
131 effect_count + control_count;
132 CHECK_EQ(input_count, node->InputCount());
133
134 // Verify that frame state has been inserted for the nodes that need it.
135 if (OperatorProperties::HasFrameStateInput(node->op())) {
136 Node* frame_state = NodeProperties::GetFrameStateInput(node);
137 CHECK(frame_state->opcode() == IrOpcode::kFrameState ||
138 // kFrameState uses undefined as a sentinel.
139 (node->opcode() == IrOpcode::kFrameState &&
140 frame_state->opcode() == IrOpcode::kHeapConstant));
141 CHECK(IsDefUseChainLinkPresent(frame_state, node));
142 CHECK(IsUseDefChainLinkPresent(frame_state, node));
143 }
144
145 // Verify all value inputs actually produce a value.
146 for (int i = 0; i < value_count; ++i) {
147 Node* value = NodeProperties::GetValueInput(node, i);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400148 CHECK(value->op()->ValueOutputCount() > 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149 CHECK(IsDefUseChainLinkPresent(value, node));
150 CHECK(IsUseDefChainLinkPresent(value, node));
151 }
152
153 // Verify all context inputs are value nodes.
154 for (int i = 0; i < context_count; ++i) {
155 Node* context = NodeProperties::GetContextInput(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400156 CHECK(context->op()->ValueOutputCount() > 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157 CHECK(IsDefUseChainLinkPresent(context, node));
158 CHECK(IsUseDefChainLinkPresent(context, node));
159 }
160
161 // Verify all effect inputs actually have an effect.
162 for (int i = 0; i < effect_count; ++i) {
163 Node* effect = NodeProperties::GetEffectInput(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400164 CHECK(effect->op()->EffectOutputCount() > 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000165 CHECK(IsDefUseChainLinkPresent(effect, node));
166 CHECK(IsUseDefChainLinkPresent(effect, node));
167 }
168
169 // Verify all control inputs are control nodes.
170 for (int i = 0; i < control_count; ++i) {
171 Node* control = NodeProperties::GetControlInput(node, i);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400172 CHECK(control->op()->ControlOutputCount() > 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173 CHECK(IsDefUseChainLinkPresent(control, node));
174 CHECK(IsUseDefChainLinkPresent(control, node));
175 }
176
177 // Verify all successors are projections if multiple value outputs exist.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400178 if (node->op()->ValueOutputCount() > 1) {
179 for (Edge edge : node->use_edges()) {
180 Node* use = edge.from();
181 CHECK(!NodeProperties::IsValueEdge(edge) ||
182 use->opcode() == IrOpcode::kProjection ||
183 use->opcode() == IrOpcode::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 }
185 }
186
187 switch (node->opcode()) {
188 case IrOpcode::kStart:
189 // Start has no inputs.
190 CHECK_EQ(0, input_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400191 // Type is a tuple.
192 // TODO(rossberg): Multiple outputs are currently typed as Internal.
193 CheckUpperIs(node, Type::Internal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 break;
195 case IrOpcode::kEnd:
196 // End has no outputs.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400197 CHECK(node->op()->ValueOutputCount() == 0);
198 CHECK(node->op()->EffectOutputCount() == 0);
199 CHECK(node->op()->ControlOutputCount() == 0);
200 // Type is empty.
201 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202 break;
203 case IrOpcode::kDead:
204 // Dead is never connected to the graph.
205 UNREACHABLE();
206 case IrOpcode::kBranch: {
207 // Branch uses are IfTrue and IfFalse.
208 Node::Uses uses = node->uses();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400209 int count_true = 0, count_false = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400211 CHECK((*it)->opcode() == IrOpcode::kIfTrue ||
212 (*it)->opcode() == IrOpcode::kIfFalse);
213 if ((*it)->opcode() == IrOpcode::kIfTrue) ++count_true;
214 if ((*it)->opcode() == IrOpcode::kIfFalse) ++count_false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400216 CHECK(count_true == 1 && count_false == 1);
217 // Type is empty.
218 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 break;
220 }
221 case IrOpcode::kIfTrue:
222 case IrOpcode::kIfFalse:
223 CHECK_EQ(IrOpcode::kBranch,
224 NodeProperties::GetControlInput(node, 0)->opcode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400225 // Type is empty.
226 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227 break;
228 case IrOpcode::kLoop:
229 case IrOpcode::kMerge:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400230 CHECK_EQ(control_count, input_count);
231 // Type is empty.
232 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 break;
234 case IrOpcode::kReturn:
235 // TODO(rossberg): check successor is End
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400236 // Type is empty.
237 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 break;
239 case IrOpcode::kThrow:
240 // TODO(rossberg): what are the constraints on these?
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400241 // Type is empty.
242 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400244 case IrOpcode::kTerminate:
245 // Type is empty.
246 CheckNotTyped(node);
247 CHECK_EQ(1, control_count);
248 CHECK_EQ(input_count, 1 + effect_count);
249 break;
250
251 // Common operators
252 // ----------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000253 case IrOpcode::kParameter: {
254 // Parameters have the start node as inputs.
255 CHECK_EQ(1, input_count);
256 CHECK_EQ(IrOpcode::kStart,
257 NodeProperties::GetValueInput(node, 0)->opcode());
258 // Parameter has an input that produces enough values.
259 int index = OpParameter<int>(node);
260 Node* input = NodeProperties::GetValueInput(node, 0);
261 // Currently, parameter indices start at -1 instead of 0.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400262 CHECK_GT(input->op()->ValueOutputCount(), index + 1);
263 // Type can be anything.
264 CheckUpperIs(node, Type::Any());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265 break;
266 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400267 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant?
268 // Constants have no inputs.
269 CHECK_EQ(0, input_count);
270 // Type is a 32 bit integer, signed or unsigned.
271 CheckUpperIs(node, Type::Integral32());
272 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 case IrOpcode::kInt64Constant:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400274 // Constants have no inputs.
275 CHECK_EQ(0, input_count);
276 // Type is internal.
277 // TODO(rossberg): Introduce proper Int64 type.
278 CheckUpperIs(node, Type::Internal());
279 break;
280 case IrOpcode::kFloat32Constant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 case IrOpcode::kFloat64Constant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282 case IrOpcode::kNumberConstant:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400283 // Constants have no inputs.
284 CHECK_EQ(0, input_count);
285 // Type is a number.
286 CheckUpperIs(node, Type::Number());
287 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000288 case IrOpcode::kHeapConstant:
289 // Constants have no inputs.
290 CHECK_EQ(0, input_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400291 // Type can be anything represented as a heap pointer.
292 CheckUpperIs(node, Type::TaggedPointer());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400294 case IrOpcode::kExternalConstant:
295 // Constants have no inputs.
296 CHECK_EQ(0, input_count);
297 // Type is considered internal.
298 CheckUpperIs(node, Type::Internal());
299 break;
300 case IrOpcode::kProjection: {
301 // Projection has an input that produces enough values.
302 int index = static_cast<int>(OpParameter<size_t>(node->op()));
303 Node* input = NodeProperties::GetValueInput(node, 0);
304 CHECK_GT(input->op()->ValueOutputCount(), index);
305 // Type can be anything.
306 // TODO(rossberg): Introduce tuple types for this.
307 // TODO(titzer): Convince rossberg not to.
308 CheckUpperIs(node, Type::Any());
309 break;
310 }
311 case IrOpcode::kSelect: {
312 CHECK_EQ(0, effect_count);
313 CHECK_EQ(0, control_count);
314 CHECK_EQ(3, value_count);
315 break;
316 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317 case IrOpcode::kPhi: {
318 // Phi input count matches parent control node.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400319 CHECK_EQ(0, effect_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 CHECK_EQ(1, control_count);
321 Node* control = NodeProperties::GetControlInput(node, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400322 CHECK_EQ(value_count, control->op()->ControlInputCount());
323 CHECK_EQ(input_count, 1 + value_count);
324 // Type must be subsumed by all input types.
325 // TODO(rossberg): for now at least, narrowing does not really hold.
326 /*
327 for (int i = 0; i < value_count; ++i) {
328 // TODO(rossberg, jarin): Figure out what to do about lower bounds.
329 // CHECK(bounds(node).lower->Is(bounds(ValueInput(node, i)).lower));
330 CHECK(bounds(ValueInput(node, i)).upper->Is(bounds(node).upper));
331 }
332 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000333 break;
334 }
335 case IrOpcode::kEffectPhi: {
336 // EffectPhi input count matches parent control node.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400337 CHECK_EQ(0, value_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338 CHECK_EQ(1, control_count);
339 Node* control = NodeProperties::GetControlInput(node, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400340 CHECK_EQ(effect_count, control->op()->ControlInputCount());
341 CHECK_EQ(input_count, 1 + effect_count);
342 break;
343 }
344 case IrOpcode::kValueEffect:
345 // TODO(rossberg): what are the constraints on these?
346 break;
347 case IrOpcode::kFinish: {
348 // TODO(rossberg): what are the constraints on these?
349 // Type must be subsumed by input type.
350 if (typing == TYPED) {
351 CHECK(bounds(ValueInput(node)).lower->Is(bounds(node).lower));
352 CHECK(bounds(ValueInput(node)).upper->Is(bounds(node).upper));
353 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000354 break;
355 }
356 case IrOpcode::kFrameState:
357 // TODO(jarin): what are the constraints on these?
358 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400359 case IrOpcode::kStateValues:
360 // TODO(jarin): what are the constraints on these?
361 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 case IrOpcode::kCall:
363 // TODO(rossberg): what are the constraints on these?
364 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400365
366 // JavaScript operators
367 // --------------------
368 case IrOpcode::kJSEqual:
369 case IrOpcode::kJSNotEqual:
370 case IrOpcode::kJSStrictEqual:
371 case IrOpcode::kJSStrictNotEqual:
372 case IrOpcode::kJSLessThan:
373 case IrOpcode::kJSGreaterThan:
374 case IrOpcode::kJSLessThanOrEqual:
375 case IrOpcode::kJSGreaterThanOrEqual:
376 case IrOpcode::kJSUnaryNot:
377 // Type is Boolean.
378 CheckUpperIs(node, Type::Boolean());
379 break;
380
381 case IrOpcode::kJSBitwiseOr:
382 case IrOpcode::kJSBitwiseXor:
383 case IrOpcode::kJSBitwiseAnd:
384 case IrOpcode::kJSShiftLeft:
385 case IrOpcode::kJSShiftRight:
386 case IrOpcode::kJSShiftRightLogical:
387 // Type is 32 bit integral.
388 CheckUpperIs(node, Type::Integral32());
389 break;
390 case IrOpcode::kJSAdd:
391 // Type is Number or String.
392 CheckUpperIs(node, Type::NumberOrString());
393 break;
394 case IrOpcode::kJSSubtract:
395 case IrOpcode::kJSMultiply:
396 case IrOpcode::kJSDivide:
397 case IrOpcode::kJSModulus:
398 // Type is Number.
399 CheckUpperIs(node, Type::Number());
400 break;
401
402 case IrOpcode::kJSToBoolean:
403 // Type is Boolean.
404 CheckUpperIs(node, Type::Boolean());
405 break;
406 case IrOpcode::kJSToNumber:
407 // Type is Number.
408 CheckUpperIs(node, Type::Number());
409 break;
410 case IrOpcode::kJSToString:
411 // Type is String.
412 CheckUpperIs(node, Type::String());
413 break;
414 case IrOpcode::kJSToName:
415 // Type is Name.
416 CheckUpperIs(node, Type::Name());
417 break;
418 case IrOpcode::kJSToObject:
419 // Type is Receiver.
420 CheckUpperIs(node, Type::Receiver());
421 break;
422
423 case IrOpcode::kJSCreate:
424 // Type is Object.
425 CheckUpperIs(node, Type::Object());
426 break;
427 case IrOpcode::kJSLoadProperty:
428 case IrOpcode::kJSLoadNamed:
429 // Type can be anything.
430 CheckUpperIs(node, Type::Any());
431 break;
432 case IrOpcode::kJSStoreProperty:
433 case IrOpcode::kJSStoreNamed:
434 // Type is empty.
435 CheckNotTyped(node);
436 break;
437 case IrOpcode::kJSDeleteProperty:
438 case IrOpcode::kJSHasProperty:
439 case IrOpcode::kJSInstanceOf:
440 // Type is Boolean.
441 CheckUpperIs(node, Type::Boolean());
442 break;
443 case IrOpcode::kJSTypeOf:
444 // Type is String.
445 CheckUpperIs(node, Type::String());
446 break;
447
448 case IrOpcode::kJSLoadContext:
449 // Type can be anything.
450 CheckUpperIs(node, Type::Any());
451 break;
452 case IrOpcode::kJSStoreContext:
453 // Type is empty.
454 CheckNotTyped(node);
455 break;
456 case IrOpcode::kJSCreateFunctionContext:
457 case IrOpcode::kJSCreateCatchContext:
458 case IrOpcode::kJSCreateWithContext:
459 case IrOpcode::kJSCreateBlockContext:
460 case IrOpcode::kJSCreateModuleContext:
461 case IrOpcode::kJSCreateScriptContext: {
462 // Type is Context, and operand is Internal.
463 Node* context = NodeProperties::GetContextInput(node);
464 // TODO(rossberg): This should really be Is(Internal), but the typer
465 // currently can't do backwards propagation.
466 CheckUpperMaybe(context, Type::Internal());
467 if (typing == TYPED) CHECK(bounds(node).upper->IsContext());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000468 break;
469 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400470
471 case IrOpcode::kJSCallConstruct:
472 // Type is Receiver.
473 CheckUpperIs(node, Type::Receiver());
474 break;
475 case IrOpcode::kJSCallFunction:
476 case IrOpcode::kJSCallRuntime:
477 case IrOpcode::kJSYield:
478 case IrOpcode::kJSDebugger:
479 // Type can be anything.
480 CheckUpperIs(node, Type::Any());
481 break;
482
483 // Simplified operators
484 // -------------------------------
485 case IrOpcode::kAnyToBoolean:
486 // Type is Boolean.
487 CheckUpperIs(node, Type::Boolean());
488 break;
489 case IrOpcode::kBooleanNot:
490 // Boolean -> Boolean
491 CheckValueInputIs(node, 0, Type::Boolean());
492 CheckUpperIs(node, Type::Boolean());
493 break;
494 case IrOpcode::kBooleanToNumber:
495 // Boolean -> Number
496 CheckValueInputIs(node, 0, Type::Boolean());
497 CheckUpperIs(node, Type::Number());
498 break;
499 case IrOpcode::kNumberEqual:
500 case IrOpcode::kNumberLessThan:
501 case IrOpcode::kNumberLessThanOrEqual:
502 // (Number, Number) -> Boolean
503 CheckValueInputIs(node, 0, Type::Number());
504 CheckValueInputIs(node, 1, Type::Number());
505 CheckUpperIs(node, Type::Boolean());
506 break;
507 case IrOpcode::kNumberAdd:
508 case IrOpcode::kNumberSubtract:
509 case IrOpcode::kNumberMultiply:
510 case IrOpcode::kNumberDivide:
511 case IrOpcode::kNumberModulus:
512 // (Number, Number) -> Number
513 CheckValueInputIs(node, 0, Type::Number());
514 CheckValueInputIs(node, 1, Type::Number());
515 // TODO(rossberg): activate once we retype after opcode changes.
516 // CheckUpperIs(node, Type::Number());
517 break;
518 case IrOpcode::kNumberToInt32:
519 // Number -> Signed32
520 CheckValueInputIs(node, 0, Type::Number());
521 CheckUpperIs(node, Type::Signed32());
522 break;
523 case IrOpcode::kNumberToUint32:
524 // Number -> Unsigned32
525 CheckValueInputIs(node, 0, Type::Number());
526 CheckUpperIs(node, Type::Unsigned32());
527 break;
528 case IrOpcode::kStringEqual:
529 case IrOpcode::kStringLessThan:
530 case IrOpcode::kStringLessThanOrEqual:
531 // (String, String) -> Boolean
532 CheckValueInputIs(node, 0, Type::String());
533 CheckValueInputIs(node, 1, Type::String());
534 CheckUpperIs(node, Type::Boolean());
535 break;
536 case IrOpcode::kStringAdd:
537 // (String, String) -> String
538 CheckValueInputIs(node, 0, Type::String());
539 CheckValueInputIs(node, 1, Type::String());
540 CheckUpperIs(node, Type::String());
541 break;
542 case IrOpcode::kReferenceEqual: {
543 // (Unique, Any) -> Boolean and
544 // (Any, Unique) -> Boolean
545 if (typing == TYPED) {
546 CHECK(bounds(ValueInput(node, 0)).upper->Is(Type::Unique()) ||
547 bounds(ValueInput(node, 1)).upper->Is(Type::Unique()));
548 }
549 CheckUpperIs(node, Type::Boolean());
550 break;
551 }
552 case IrOpcode::kObjectIsSmi:
553 CheckValueInputIs(node, 0, Type::Any());
554 CheckUpperIs(node, Type::Boolean());
555 break;
556 case IrOpcode::kObjectIsNonNegativeSmi:
557 CheckValueInputIs(node, 0, Type::Any());
558 CheckUpperIs(node, Type::Boolean());
559 break;
560
561 case IrOpcode::kChangeTaggedToInt32: {
562 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
563 // TODO(neis): Activate once ChangeRepresentation works in typer.
564 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
565 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
566 // CheckValueInputIs(node, 0, from));
567 // CheckUpperIs(node, to));
568 break;
569 }
570 case IrOpcode::kChangeTaggedToUint32: {
571 // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32
572 // TODO(neis): Activate once ChangeRepresentation works in typer.
573 // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged());
574 // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32());
575 // CheckValueInputIs(node, 0, from));
576 // CheckUpperIs(node, to));
577 break;
578 }
579 case IrOpcode::kChangeTaggedToFloat64: {
580 // Number /\ Tagged -> Number /\ UntaggedFloat64
581 // TODO(neis): Activate once ChangeRepresentation works in typer.
582 // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
583 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
584 // CheckValueInputIs(node, 0, from));
585 // CheckUpperIs(node, to));
586 break;
587 }
588 case IrOpcode::kChangeInt32ToTagged: {
589 // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged
590 // TODO(neis): Activate once ChangeRepresentation works in typer.
591 // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
592 // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged());
593 // CheckValueInputIs(node, 0, from));
594 // CheckUpperIs(node, to));
595 break;
596 }
597 case IrOpcode::kChangeUint32ToTagged: {
598 // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged
599 // TODO(neis): Activate once ChangeRepresentation works in typer.
600 // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32());
601 // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged());
602 // CheckValueInputIs(node, 0, from));
603 // CheckUpperIs(node, to));
604 break;
605 }
606 case IrOpcode::kChangeFloat64ToTagged: {
607 // Number /\ UntaggedFloat64 -> Number /\ Tagged
608 // TODO(neis): Activate once ChangeRepresentation works in typer.
609 // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64());
610 // Type* to = Type::Intersect(Type::Number(), Type::Tagged());
611 // CheckValueInputIs(node, 0, from));
612 // CheckUpperIs(node, to));
613 break;
614 }
615 case IrOpcode::kChangeBoolToBit: {
616 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
617 // TODO(neis): Activate once ChangeRepresentation works in typer.
618 // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
619 // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
620 // CheckValueInputIs(node, 0, from));
621 // CheckUpperIs(node, to));
622 break;
623 }
624 case IrOpcode::kChangeBitToBool: {
625 // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
626 // TODO(neis): Activate once ChangeRepresentation works in typer.
627 // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
628 // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
629 // CheckValueInputIs(node, 0, from));
630 // CheckUpperIs(node, to));
631 break;
632 }
633
634 case IrOpcode::kLoadField:
635 // Object -> fieldtype
636 // TODO(rossberg): activate once machine ops are typed.
637 // CheckValueInputIs(node, 0, Type::Object());
638 // CheckUpperIs(node, Field(node).type));
639 break;
640 case IrOpcode::kLoadBuffer:
641 break;
642 case IrOpcode::kLoadElement:
643 // Object -> elementtype
644 // TODO(rossberg): activate once machine ops are typed.
645 // CheckValueInputIs(node, 0, Type::Object());
646 // CheckUpperIs(node, Element(node).type));
647 break;
648 case IrOpcode::kStoreField:
649 // (Object, fieldtype) -> _|_
650 // TODO(rossberg): activate once machine ops are typed.
651 // CheckValueInputIs(node, 0, Type::Object());
652 // CheckValueInputIs(node, 1, Field(node).type));
653 CheckNotTyped(node);
654 break;
655 case IrOpcode::kStoreBuffer:
656 break;
657 case IrOpcode::kStoreElement:
658 // (Object, elementtype) -> _|_
659 // TODO(rossberg): activate once machine ops are typed.
660 // CheckValueInputIs(node, 0, Type::Object());
661 // CheckValueInputIs(node, 1, Element(node).type));
662 CheckNotTyped(node);
663 break;
664
665 // Machine operators
666 // -----------------------
667 case IrOpcode::kLoad:
668 case IrOpcode::kStore:
669 case IrOpcode::kWord32And:
670 case IrOpcode::kWord32Or:
671 case IrOpcode::kWord32Xor:
672 case IrOpcode::kWord32Shl:
673 case IrOpcode::kWord32Shr:
674 case IrOpcode::kWord32Sar:
675 case IrOpcode::kWord32Ror:
676 case IrOpcode::kWord32Equal:
677 case IrOpcode::kWord64And:
678 case IrOpcode::kWord64Or:
679 case IrOpcode::kWord64Xor:
680 case IrOpcode::kWord64Shl:
681 case IrOpcode::kWord64Shr:
682 case IrOpcode::kWord64Sar:
683 case IrOpcode::kWord64Ror:
684 case IrOpcode::kWord64Equal:
685 case IrOpcode::kInt32Add:
686 case IrOpcode::kInt32AddWithOverflow:
687 case IrOpcode::kInt32Sub:
688 case IrOpcode::kInt32SubWithOverflow:
689 case IrOpcode::kInt32Mul:
690 case IrOpcode::kInt32MulHigh:
691 case IrOpcode::kInt32Div:
692 case IrOpcode::kInt32Mod:
693 case IrOpcode::kInt32LessThan:
694 case IrOpcode::kInt32LessThanOrEqual:
695 case IrOpcode::kUint32Div:
696 case IrOpcode::kUint32Mod:
697 case IrOpcode::kUint32MulHigh:
698 case IrOpcode::kUint32LessThan:
699 case IrOpcode::kUint32LessThanOrEqual:
700 case IrOpcode::kInt64Add:
701 case IrOpcode::kInt64Sub:
702 case IrOpcode::kInt64Mul:
703 case IrOpcode::kInt64Div:
704 case IrOpcode::kInt64Mod:
705 case IrOpcode::kInt64LessThan:
706 case IrOpcode::kInt64LessThanOrEqual:
707 case IrOpcode::kUint64Div:
708 case IrOpcode::kUint64Mod:
709 case IrOpcode::kUint64LessThan:
710 case IrOpcode::kFloat64Add:
711 case IrOpcode::kFloat64Sub:
712 case IrOpcode::kFloat64Mul:
713 case IrOpcode::kFloat64Div:
714 case IrOpcode::kFloat64Mod:
715 case IrOpcode::kFloat64Sqrt:
716 case IrOpcode::kFloat64Floor:
717 case IrOpcode::kFloat64Ceil:
718 case IrOpcode::kFloat64RoundTruncate:
719 case IrOpcode::kFloat64RoundTiesAway:
720 case IrOpcode::kFloat64Equal:
721 case IrOpcode::kFloat64LessThan:
722 case IrOpcode::kFloat64LessThanOrEqual:
723 case IrOpcode::kTruncateInt64ToInt32:
724 case IrOpcode::kTruncateFloat64ToFloat32:
725 case IrOpcode::kTruncateFloat64ToInt32:
726 case IrOpcode::kChangeInt32ToInt64:
727 case IrOpcode::kChangeUint32ToUint64:
728 case IrOpcode::kChangeInt32ToFloat64:
729 case IrOpcode::kChangeUint32ToFloat64:
730 case IrOpcode::kChangeFloat32ToFloat64:
731 case IrOpcode::kChangeFloat64ToInt32:
732 case IrOpcode::kChangeFloat64ToUint32:
733 case IrOpcode::kLoadStackPointer:
734 case IrOpcode::kCheckedLoad:
735 case IrOpcode::kCheckedStore:
736 // TODO(rossberg): Check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737 break;
738 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000739}
740
741
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400742void Verifier::Run(Graph* graph, Typing typing) {
743 Visitor visitor(graph->zone(), typing);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000744 CHECK_NE(NULL, graph->start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000745 CHECK_NE(NULL, graph->end());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 graph->VisitNodeInputsFromEnd(&visitor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000747}
748
749
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400750// -----------------------------------------------------------------------------
751
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000752static bool HasDominatingDef(Schedule* schedule, Node* node,
753 BasicBlock* container, BasicBlock* use_block,
754 int use_pos) {
755 BasicBlock* block = use_block;
756 while (true) {
757 while (use_pos >= 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400758 if (block->NodeAt(use_pos) == node) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000759 use_pos--;
760 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400761 block = block->dominator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000762 if (block == NULL) break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400763 use_pos = static_cast<int>(block->NodeCount()) - 1;
764 if (node == block->control_input()) return true;
765 }
766 return false;
767}
768
769
770static bool Dominates(Schedule* schedule, Node* dominator, Node* dominatee) {
771 BasicBlock* dom = schedule->block(dominator);
772 BasicBlock* sub = schedule->block(dominatee);
773 while (sub != NULL) {
774 if (sub == dom) {
775 return true;
776 }
777 sub = sub->dominator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000778 }
779 return false;
780}
781
782
783static void CheckInputsDominate(Schedule* schedule, BasicBlock* block,
784 Node* node, int use_pos) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400785 for (int j = node->op()->ValueInputCount() - 1; j >= 0; j--) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000786 BasicBlock* use_block = block;
787 if (node->opcode() == IrOpcode::kPhi) {
788 use_block = use_block->PredecessorAt(j);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400789 use_pos = static_cast<int>(use_block->NodeCount()) - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000790 }
791 Node* input = node->InputAt(j);
792 if (!HasDominatingDef(schedule, node->InputAt(j), block, use_block,
793 use_pos)) {
794 V8_Fatal(__FILE__, __LINE__,
795 "Node #%d:%s in B%d is not dominated by input@%d #%d:%s",
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400796 node->id(), node->op()->mnemonic(), block->id().ToInt(), j,
797 input->id(), input->op()->mnemonic());
798 }
799 }
800 // Ensure that nodes are dominated by their control inputs;
801 // kEnd is an exception, as unreachable blocks resulting from kMerge
802 // are not in the RPO.
803 if (node->op()->ControlInputCount() == 1 &&
804 node->opcode() != IrOpcode::kEnd) {
805 Node* ctl = NodeProperties::GetControlInput(node);
806 if (!Dominates(schedule, ctl, node)) {
807 V8_Fatal(__FILE__, __LINE__,
808 "Node #%d:%s in B%d is not dominated by control input #%d:%s",
809 node->id(), node->op()->mnemonic(), block->id(), ctl->id(),
810 ctl->op()->mnemonic());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000811 }
812 }
813}
814
815
816void ScheduleVerifier::Run(Schedule* schedule) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400817 const size_t count = schedule->BasicBlockCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000818 Zone tmp_zone(schedule->zone()->isolate());
819 Zone* zone = &tmp_zone;
820 BasicBlock* start = schedule->start();
821 BasicBlockVector* rpo_order = schedule->rpo_order();
822
823 // Verify the RPO order contains only blocks from this schedule.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400824 CHECK_GE(count, rpo_order->size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000825 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
826 ++b) {
827 CHECK_EQ((*b), schedule->GetBlockById((*b)->id()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400828 // All predecessors and successors should be in rpo and in this schedule.
829 for (BasicBlock::Predecessors::iterator j = (*b)->predecessors_begin();
830 j != (*b)->predecessors_end(); ++j) {
831 CHECK_GE((*j)->rpo_number(), 0);
832 CHECK_EQ((*j), schedule->GetBlockById((*j)->id()));
833 }
834 for (BasicBlock::Successors::iterator j = (*b)->successors_begin();
835 j != (*b)->successors_end(); ++j) {
836 CHECK_GE((*j)->rpo_number(), 0);
837 CHECK_EQ((*j), schedule->GetBlockById((*j)->id()));
838 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000839 }
840
841 // Verify RPO numbers of blocks.
842 CHECK_EQ(start, rpo_order->at(0)); // Start should be first.
843 for (size_t b = 0; b < rpo_order->size(); b++) {
844 BasicBlock* block = rpo_order->at(b);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400845 CHECK_EQ(static_cast<int>(b), block->rpo_number());
846 BasicBlock* dom = block->dominator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000847 if (b == 0) {
848 // All blocks except start should have a dominator.
849 CHECK_EQ(NULL, dom);
850 } else {
851 // Check that the immediate dominator appears somewhere before the block.
852 CHECK_NE(NULL, dom);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400853 CHECK_LT(dom->rpo_number(), block->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000854 }
855 }
856
857 // Verify that all blocks reachable from start are in the RPO.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400858 BoolVector marked(static_cast<int>(count), false, zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000859 {
860 ZoneQueue<BasicBlock*> queue(zone);
861 queue.push(start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400862 marked[start->id().ToSize()] = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863 while (!queue.empty()) {
864 BasicBlock* block = queue.front();
865 queue.pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400866 for (size_t s = 0; s < block->SuccessorCount(); s++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000867 BasicBlock* succ = block->SuccessorAt(s);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400868 if (!marked[succ->id().ToSize()]) {
869 marked[succ->id().ToSize()] = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000870 queue.push(succ);
871 }
872 }
873 }
874 }
875 // Verify marked blocks are in the RPO.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400876 for (size_t i = 0; i < count; i++) {
877 BasicBlock* block = schedule->GetBlockById(BasicBlock::Id::FromSize(i));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878 if (marked[i]) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400879 CHECK_GE(block->rpo_number(), 0);
880 CHECK_EQ(block, rpo_order->at(block->rpo_number()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000881 }
882 }
883 // Verify RPO blocks are marked.
884 for (size_t b = 0; b < rpo_order->size(); b++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400885 CHECK(marked[rpo_order->at(b)->id().ToSize()]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000886 }
887
888 {
889 // Verify the dominance relation.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400890 ZoneVector<BitVector*> dominators(zone);
891 dominators.resize(count, NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000892
893 // Compute a set of all the nodes that dominate a given node by using
894 // a forward fixpoint. O(n^2).
895 ZoneQueue<BasicBlock*> queue(zone);
896 queue.push(start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400897 dominators[start->id().ToSize()] =
898 new (zone) BitVector(static_cast<int>(count), zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899 while (!queue.empty()) {
900 BasicBlock* block = queue.front();
901 queue.pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400902 BitVector* block_doms = dominators[block->id().ToSize()];
903 BasicBlock* idom = block->dominator();
904 if (idom != NULL && !block_doms->Contains(idom->id().ToInt())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000905 V8_Fatal(__FILE__, __LINE__, "Block B%d is not dominated by B%d",
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400906 block->id().ToInt(), idom->id().ToInt());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000907 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400908 for (size_t s = 0; s < block->SuccessorCount(); s++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000909 BasicBlock* succ = block->SuccessorAt(s);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400910 BitVector* succ_doms = dominators[succ->id().ToSize()];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000911
912 if (succ_doms == NULL) {
913 // First time visiting the node. S.doms = B U B.doms
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400914 succ_doms = new (zone) BitVector(static_cast<int>(count), zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000915 succ_doms->CopyFrom(*block_doms);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400916 succ_doms->Add(block->id().ToInt());
917 dominators[succ->id().ToSize()] = succ_doms;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000918 queue.push(succ);
919 } else {
920 // Nth time visiting the successor. S.doms = S.doms ^ (B U B.doms)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400921 bool had = succ_doms->Contains(block->id().ToInt());
922 if (had) succ_doms->Remove(block->id().ToInt());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923 if (succ_doms->IntersectIsChanged(*block_doms)) queue.push(succ);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400924 if (had) succ_doms->Add(block->id().ToInt());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000925 }
926 }
927 }
928
929 // Verify the immediateness of dominators.
930 for (BasicBlockVector::iterator b = rpo_order->begin();
931 b != rpo_order->end(); ++b) {
932 BasicBlock* block = *b;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400933 BasicBlock* idom = block->dominator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000934 if (idom == NULL) continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400935 BitVector* block_doms = dominators[block->id().ToSize()];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936
937 for (BitVector::Iterator it(block_doms); !it.Done(); it.Advance()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400938 BasicBlock* dom =
939 schedule->GetBlockById(BasicBlock::Id::FromInt(it.Current()));
940 if (dom != idom &&
941 !dominators[idom->id().ToSize()]->Contains(dom->id().ToInt())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000942 V8_Fatal(__FILE__, __LINE__,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400943 "Block B%d is not immediately dominated by B%d",
944 block->id().ToInt(), idom->id().ToInt());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000945 }
946 }
947 }
948 }
949
950 // Verify phis are placed in the block of their control input.
951 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
952 ++b) {
953 for (BasicBlock::const_iterator i = (*b)->begin(); i != (*b)->end(); ++i) {
954 Node* phi = *i;
955 if (phi->opcode() != IrOpcode::kPhi) continue;
956 // TODO(titzer): Nasty special case. Phis from RawMachineAssembler
957 // schedules don't have control inputs.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400958 if (phi->InputCount() > phi->op()->ValueInputCount()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000959 Node* control = NodeProperties::GetControlInput(phi);
960 CHECK(control->opcode() == IrOpcode::kMerge ||
961 control->opcode() == IrOpcode::kLoop);
962 CHECK_EQ((*b), schedule->block(control));
963 }
964 }
965 }
966
967 // Verify that all uses are dominated by their definitions.
968 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
969 ++b) {
970 BasicBlock* block = *b;
971
972 // Check inputs to control for this block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400973 Node* control = block->control_input();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000974 if (control != NULL) {
975 CHECK_EQ(block, schedule->block(control));
976 CheckInputsDominate(schedule, block, control,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400977 static_cast<int>(block->NodeCount()) - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000978 }
979 // Check inputs for all nodes in the block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400980 for (size_t i = 0; i < block->NodeCount(); i++) {
981 Node* node = block->NodeAt(i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000982 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1);
983 }
984 }
985}
986}
987}
988} // namespace v8::internal::compiler