1 // 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.
5 #include "src/compiler/verifier.h"
12 #include "src/bit-vector.h"
13 #include "src/compiler/generic-algorithm.h"
14 #include "src/compiler/generic-node-inl.h"
15 #include "src/compiler/generic-node.h"
16 #include "src/compiler/graph-inl.h"
17 #include "src/compiler/graph.h"
18 #include "src/compiler/node.h"
19 #include "src/compiler/node-properties-inl.h"
20 #include "src/compiler/node-properties.h"
21 #include "src/compiler/opcodes.h"
22 #include "src/compiler/operator.h"
23 #include "src/compiler/schedule.h"
24 #include "src/compiler/simplified-operator.h"
25 #include "src/ostreams.h"
32 static bool IsDefUseChainLinkPresent(Node* def, Node* use) {
33 Node::Uses uses = def->uses();
34 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
35 if (*it == use) return true;
41 static bool IsUseDefChainLinkPresent(Node* def, Node* use) {
42 Node::Inputs inputs = use->inputs();
43 for (Node::Inputs::iterator it = inputs.begin(); it != inputs.end(); ++it) {
44 if (*it == def) return true;
50 class Verifier::Visitor : public NullNodeVisitor {
52 Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {}
54 // Fulfills the PreNodeCallback interface.
61 // TODO(rossberg): Get rid of these once we got rid of NodeProperties.
62 Bounds bounds(Node* node) { return NodeProperties::GetBounds(node); }
63 Node* ValueInput(Node* node, int i = 0) {
64 return NodeProperties::GetValueInput(node, i);
66 FieldAccess Field(Node* node) {
67 DCHECK(node->opcode() == IrOpcode::kLoadField ||
68 node->opcode() == IrOpcode::kStoreField);
69 return OpParameter<FieldAccess>(node);
71 ElementAccess Element(Node* node) {
72 DCHECK(node->opcode() == IrOpcode::kLoadElement ||
73 node->opcode() == IrOpcode::kStoreElement);
74 return OpParameter<ElementAccess>(node);
76 void CheckNotTyped(Node* node) {
77 if (NodeProperties::IsTyped(node)) {
78 std::ostringstream str;
79 str << "TypeError: node #" << node->opcode() << ":"
80 << node->op()->mnemonic() << " should never have a type";
81 V8_Fatal(__FILE__, __LINE__, str.str().c_str());
84 void CheckUpperIs(Node* node, Type* type) {
85 if (typing == TYPED && !bounds(node).upper->Is(type)) {
86 std::ostringstream str;
87 str << "TypeError: node #" << node->opcode() << ":"
88 << node->op()->mnemonic() << " upper bound ";
89 bounds(node).upper->PrintTo(str);
92 V8_Fatal(__FILE__, __LINE__, str.str().c_str());
95 void CheckUpperMaybe(Node* node, Type* type) {
96 if (typing == TYPED && !bounds(node).upper->Maybe(type)) {
97 std::ostringstream str;
98 str << "TypeError: node #" << node->opcode() << ":"
99 << node->op()->mnemonic() << " upper bound ";
100 bounds(node).upper->PrintTo(str);
101 str << " must intersect ";
103 V8_Fatal(__FILE__, __LINE__, str.str().c_str());
106 void CheckValueInputIs(Node* node, int i, Type* type) {
107 Node* input = ValueInput(node, i);
108 if (typing == TYPED && !bounds(input).upper->Is(type)) {
109 std::ostringstream str;
110 str << "TypeError: node #" << node->opcode() << ":"
111 << node->op()->mnemonic() << "(input @" << i << " = "
112 << input->opcode() << ":" << input->op()->mnemonic()
114 bounds(input).upper->PrintTo(str);
117 V8_Fatal(__FILE__, __LINE__, str.str().c_str());
123 void Verifier::Visitor::Pre(Node* node) {
124 int value_count = node->op()->ValueInputCount();
125 int context_count = OperatorProperties::GetContextInputCount(node->op());
126 int frame_state_count =
127 OperatorProperties::GetFrameStateInputCount(node->op());
128 int effect_count = node->op()->EffectInputCount();
129 int control_count = node->op()->ControlInputCount();
131 // Verify number of inputs matches up.
132 int input_count = value_count + context_count + frame_state_count +
133 effect_count + control_count;
134 CHECK_EQ(input_count, node->InputCount());
136 // Verify that frame state has been inserted for the nodes that need it.
137 if (OperatorProperties::HasFrameStateInput(node->op())) {
138 Node* frame_state = NodeProperties::GetFrameStateInput(node);
139 CHECK(frame_state->opcode() == IrOpcode::kFrameState ||
140 // kFrameState uses undefined as a sentinel.
141 (node->opcode() == IrOpcode::kFrameState &&
142 frame_state->opcode() == IrOpcode::kHeapConstant));
143 CHECK(IsDefUseChainLinkPresent(frame_state, node));
144 CHECK(IsUseDefChainLinkPresent(frame_state, node));
147 // Verify all value inputs actually produce a value.
148 for (int i = 0; i < value_count; ++i) {
149 Node* value = NodeProperties::GetValueInput(node, i);
150 CHECK(value->op()->ValueOutputCount() > 0);
151 CHECK(IsDefUseChainLinkPresent(value, node));
152 CHECK(IsUseDefChainLinkPresent(value, node));
155 // Verify all context inputs are value nodes.
156 for (int i = 0; i < context_count; ++i) {
157 Node* context = NodeProperties::GetContextInput(node);
158 CHECK(context->op()->ValueOutputCount() > 0);
159 CHECK(IsDefUseChainLinkPresent(context, node));
160 CHECK(IsUseDefChainLinkPresent(context, node));
163 // Verify all effect inputs actually have an effect.
164 for (int i = 0; i < effect_count; ++i) {
165 Node* effect = NodeProperties::GetEffectInput(node);
166 CHECK(effect->op()->EffectOutputCount() > 0);
167 CHECK(IsDefUseChainLinkPresent(effect, node));
168 CHECK(IsUseDefChainLinkPresent(effect, node));
171 // Verify all control inputs are control nodes.
172 for (int i = 0; i < control_count; ++i) {
173 Node* control = NodeProperties::GetControlInput(node, i);
174 CHECK(control->op()->ControlOutputCount() > 0);
175 CHECK(IsDefUseChainLinkPresent(control, node));
176 CHECK(IsUseDefChainLinkPresent(control, node));
179 // Verify all successors are projections if multiple value outputs exist.
180 if (node->op()->ValueOutputCount() > 1) {
181 Node::Uses uses = node->uses();
182 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
183 CHECK(!NodeProperties::IsValueEdge(it.edge()) ||
184 (*it)->opcode() == IrOpcode::kProjection ||
185 (*it)->opcode() == IrOpcode::kParameter);
189 switch (node->opcode()) {
190 case IrOpcode::kStart:
191 // Start has no inputs.
192 CHECK_EQ(0, input_count);
194 // TODO(rossberg): Multiple outputs are currently typed as Internal.
195 CheckUpperIs(node, Type::Internal());
198 // End has no outputs.
199 CHECK(node->op()->ValueOutputCount() == 0);
200 CHECK(node->op()->EffectOutputCount() == 0);
201 CHECK(node->op()->ControlOutputCount() == 0);
205 case IrOpcode::kDead:
206 // Dead is never connected to the graph.
208 case IrOpcode::kBranch: {
209 // Branch uses are IfTrue and IfFalse.
210 Node::Uses uses = node->uses();
211 int count_true = 0, count_false = 0;
212 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
213 CHECK((*it)->opcode() == IrOpcode::kIfTrue ||
214 (*it)->opcode() == IrOpcode::kIfFalse);
215 if ((*it)->opcode() == IrOpcode::kIfTrue) ++count_true;
216 if ((*it)->opcode() == IrOpcode::kIfFalse) ++count_false;
218 CHECK(count_true == 1 && count_false == 1);
223 case IrOpcode::kIfTrue:
224 case IrOpcode::kIfFalse:
225 CHECK_EQ(IrOpcode::kBranch,
226 NodeProperties::GetControlInput(node, 0)->opcode());
230 case IrOpcode::kLoop:
231 case IrOpcode::kMerge:
232 CHECK_EQ(control_count, input_count);
236 case IrOpcode::kReturn:
237 // TODO(rossberg): check successor is End
241 case IrOpcode::kThrow:
242 // TODO(rossberg): what are the constraints on these?
246 case IrOpcode::kTerminate:
249 CHECK_EQ(1, control_count);
250 CHECK_EQ(input_count, 1 + effect_count);
255 case IrOpcode::kParameter: {
256 // Parameters have the start node as inputs.
257 CHECK_EQ(1, input_count);
258 CHECK_EQ(IrOpcode::kStart,
259 NodeProperties::GetValueInput(node, 0)->opcode());
260 // Parameter has an input that produces enough values.
261 int index = OpParameter<int>(node);
262 Node* input = NodeProperties::GetValueInput(node, 0);
263 // Currently, parameter indices start at -1 instead of 0.
264 CHECK_GT(input->op()->ValueOutputCount(), index + 1);
265 // Type can be anything.
266 CheckUpperIs(node, Type::Any());
269 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant?
270 // Constants have no inputs.
271 CHECK_EQ(0, input_count);
272 // Type is a 32 bit integer, signed or unsigned.
273 CheckUpperIs(node, Type::Integral32());
275 case IrOpcode::kInt64Constant:
276 // Constants have no inputs.
277 CHECK_EQ(0, input_count);
279 // TODO(rossberg): Introduce proper Int64 type.
280 CheckUpperIs(node, Type::Internal());
282 case IrOpcode::kFloat32Constant:
283 case IrOpcode::kFloat64Constant:
284 case IrOpcode::kNumberConstant:
285 // Constants have no inputs.
286 CHECK_EQ(0, input_count);
288 CheckUpperIs(node, Type::Number());
290 case IrOpcode::kHeapConstant:
291 // Constants have no inputs.
292 CHECK_EQ(0, input_count);
293 // Type can be anything represented as a heap pointer.
294 CheckUpperIs(node, Type::TaggedPtr());
296 case IrOpcode::kExternalConstant:
297 // Constants have no inputs.
298 CHECK_EQ(0, input_count);
299 // Type is considered internal.
300 CheckUpperIs(node, Type::Internal());
302 case IrOpcode::kProjection: {
303 // Projection has an input that produces enough values.
304 int index = static_cast<int>(OpParameter<size_t>(node->op()));
305 Node* input = NodeProperties::GetValueInput(node, 0);
306 CHECK_GT(input->op()->ValueOutputCount(), index);
307 // Type can be anything.
308 // TODO(rossberg): Introduce tuple types for this.
309 // TODO(titzer): Convince rossberg not to.
310 CheckUpperIs(node, Type::Any());
313 case IrOpcode::kSelect: {
314 CHECK_EQ(0, effect_count);
315 CHECK_EQ(0, control_count);
316 CHECK_EQ(3, value_count);
319 case IrOpcode::kPhi: {
320 // Phi input count matches parent control node.
321 CHECK_EQ(0, effect_count);
322 CHECK_EQ(1, control_count);
323 Node* control = NodeProperties::GetControlInput(node, 0);
324 CHECK_EQ(value_count, control->op()->ControlInputCount());
325 CHECK_EQ(input_count, 1 + value_count);
326 // Type must be subsumed by all input types.
327 // TODO(rossberg): for now at least, narrowing does not really hold.
329 for (int i = 0; i < value_count; ++i) {
330 // TODO(rossberg, jarin): Figure out what to do about lower bounds.
331 // CHECK(bounds(node).lower->Is(bounds(ValueInput(node, i)).lower));
332 CHECK(bounds(ValueInput(node, i)).upper->Is(bounds(node).upper));
337 case IrOpcode::kEffectPhi: {
338 // EffectPhi input count matches parent control node.
339 CHECK_EQ(0, value_count);
340 CHECK_EQ(1, control_count);
341 Node* control = NodeProperties::GetControlInput(node, 0);
342 CHECK_EQ(effect_count, control->op()->ControlInputCount());
343 CHECK_EQ(input_count, 1 + effect_count);
346 case IrOpcode::kValueEffect:
347 // TODO(rossberg): what are the constraints on these?
349 case IrOpcode::kFinish: {
350 // TODO(rossberg): what are the constraints on these?
351 // Type must be subsumed by input type.
352 if (typing == TYPED) {
353 CHECK(bounds(ValueInput(node)).lower->Is(bounds(node).lower));
354 CHECK(bounds(ValueInput(node)).upper->Is(bounds(node).upper));
358 case IrOpcode::kFrameState:
359 // TODO(jarin): what are the constraints on these?
361 case IrOpcode::kStateValues:
362 // TODO(jarin): what are the constraints on these?
364 case IrOpcode::kCall:
365 // TODO(rossberg): what are the constraints on these?
368 // JavaScript operators
369 // --------------------
370 case IrOpcode::kJSEqual:
371 case IrOpcode::kJSNotEqual:
372 case IrOpcode::kJSStrictEqual:
373 case IrOpcode::kJSStrictNotEqual:
374 case IrOpcode::kJSLessThan:
375 case IrOpcode::kJSGreaterThan:
376 case IrOpcode::kJSLessThanOrEqual:
377 case IrOpcode::kJSGreaterThanOrEqual:
378 case IrOpcode::kJSUnaryNot:
380 CheckUpperIs(node, Type::Boolean());
383 case IrOpcode::kJSBitwiseOr:
384 case IrOpcode::kJSBitwiseXor:
385 case IrOpcode::kJSBitwiseAnd:
386 case IrOpcode::kJSShiftLeft:
387 case IrOpcode::kJSShiftRight:
388 case IrOpcode::kJSShiftRightLogical:
389 // Type is 32 bit integral.
390 CheckUpperIs(node, Type::Integral32());
392 case IrOpcode::kJSAdd:
393 // Type is Number or String.
394 CheckUpperIs(node, Type::NumberOrString());
396 case IrOpcode::kJSSubtract:
397 case IrOpcode::kJSMultiply:
398 case IrOpcode::kJSDivide:
399 case IrOpcode::kJSModulus:
401 CheckUpperIs(node, Type::Number());
404 case IrOpcode::kJSToBoolean:
406 CheckUpperIs(node, Type::Boolean());
408 case IrOpcode::kJSToNumber:
410 CheckUpperIs(node, Type::Number());
412 case IrOpcode::kJSToString:
414 CheckUpperIs(node, Type::String());
416 case IrOpcode::kJSToName:
418 CheckUpperIs(node, Type::Name());
420 case IrOpcode::kJSToObject:
422 CheckUpperIs(node, Type::Receiver());
425 case IrOpcode::kJSCreate:
427 CheckUpperIs(node, Type::Object());
429 case IrOpcode::kJSLoadProperty:
430 case IrOpcode::kJSLoadNamed:
431 // Type can be anything.
432 CheckUpperIs(node, Type::Any());
434 case IrOpcode::kJSStoreProperty:
435 case IrOpcode::kJSStoreNamed:
439 case IrOpcode::kJSDeleteProperty:
440 case IrOpcode::kJSHasProperty:
441 case IrOpcode::kJSInstanceOf:
443 CheckUpperIs(node, Type::Boolean());
445 case IrOpcode::kJSTypeOf:
447 CheckUpperIs(node, Type::String());
450 case IrOpcode::kJSLoadContext:
451 // Type can be anything.
452 CheckUpperIs(node, Type::Any());
454 case IrOpcode::kJSStoreContext:
458 case IrOpcode::kJSCreateFunctionContext:
459 case IrOpcode::kJSCreateCatchContext:
460 case IrOpcode::kJSCreateWithContext:
461 case IrOpcode::kJSCreateBlockContext:
462 case IrOpcode::kJSCreateModuleContext:
463 case IrOpcode::kJSCreateGlobalContext: {
464 // Type is Context, and operand is Internal.
465 Node* context = NodeProperties::GetContextInput(node);
466 // TODO(rossberg): This should really be Is(Internal), but the typer
467 // currently can't do backwards propagation.
468 CheckUpperMaybe(context, Type::Internal());
469 if (typing == TYPED) CHECK(bounds(node).upper->IsContext());
473 case IrOpcode::kJSCallConstruct:
475 CheckUpperIs(node, Type::Receiver());
477 case IrOpcode::kJSCallFunction:
478 case IrOpcode::kJSCallRuntime:
479 case IrOpcode::kJSYield:
480 case IrOpcode::kJSDebugger:
481 // Type can be anything.
482 CheckUpperIs(node, Type::Any());
485 // Simplified operators
486 // -------------------------------
487 case IrOpcode::kBooleanNot:
488 // Boolean -> Boolean
489 CheckValueInputIs(node, 0, Type::Boolean());
490 CheckUpperIs(node, Type::Boolean());
492 case IrOpcode::kBooleanToNumber:
494 CheckValueInputIs(node, 0, Type::Boolean());
495 CheckUpperIs(node, Type::Number());
497 case IrOpcode::kNumberEqual:
498 case IrOpcode::kNumberLessThan:
499 case IrOpcode::kNumberLessThanOrEqual:
500 // (Number, Number) -> Boolean
501 CheckValueInputIs(node, 0, Type::Number());
502 CheckValueInputIs(node, 1, Type::Number());
503 CheckUpperIs(node, Type::Boolean());
505 case IrOpcode::kNumberAdd:
506 case IrOpcode::kNumberSubtract:
507 case IrOpcode::kNumberMultiply:
508 case IrOpcode::kNumberDivide:
509 case IrOpcode::kNumberModulus:
510 // (Number, Number) -> Number
511 CheckValueInputIs(node, 0, Type::Number());
512 CheckValueInputIs(node, 1, Type::Number());
513 // TODO(rossberg): activate once we retype after opcode changes.
514 // CheckUpperIs(node, Type::Number());
516 case IrOpcode::kNumberToInt32:
517 // Number -> Signed32
518 CheckValueInputIs(node, 0, Type::Number());
519 CheckUpperIs(node, Type::Signed32());
521 case IrOpcode::kNumberToUint32:
522 // Number -> Unsigned32
523 CheckValueInputIs(node, 0, Type::Number());
524 CheckUpperIs(node, Type::Unsigned32());
526 case IrOpcode::kStringEqual:
527 case IrOpcode::kStringLessThan:
528 case IrOpcode::kStringLessThanOrEqual:
529 // (String, String) -> Boolean
530 CheckValueInputIs(node, 0, Type::String());
531 CheckValueInputIs(node, 1, Type::String());
532 CheckUpperIs(node, Type::Boolean());
534 case IrOpcode::kStringAdd:
535 // (String, String) -> String
536 CheckValueInputIs(node, 0, Type::String());
537 CheckValueInputIs(node, 1, Type::String());
538 CheckUpperIs(node, Type::String());
540 case IrOpcode::kReferenceEqual: {
541 // (Unique, Any) -> Boolean and
542 // (Any, Unique) -> Boolean
543 if (typing == TYPED) {
544 CHECK(bounds(ValueInput(node, 0)).upper->Is(Type::Unique()) ||
545 bounds(ValueInput(node, 1)).upper->Is(Type::Unique()));
547 CheckUpperIs(node, Type::Boolean());
550 case IrOpcode::kObjectIsSmi:
551 CheckValueInputIs(node, 0, Type::Any());
552 CheckUpperIs(node, Type::Boolean());
554 case IrOpcode::kObjectIsNonNegativeSmi:
555 CheckValueInputIs(node, 0, Type::Any());
556 CheckUpperIs(node, Type::Boolean());
559 case IrOpcode::kChangeTaggedToInt32: {
560 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
561 // TODO(neis): Activate once ChangeRepresentation works in typer.
562 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
563 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
564 // CheckValueInputIs(node, 0, from));
565 // CheckUpperIs(node, to));
568 case IrOpcode::kChangeTaggedToUint32: {
569 // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32
570 // TODO(neis): Activate once ChangeRepresentation works in typer.
571 // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged());
572 // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32());
573 // CheckValueInputIs(node, 0, from));
574 // CheckUpperIs(node, to));
577 case IrOpcode::kChangeTaggedToFloat64: {
578 // Number /\ Tagged -> Number /\ UntaggedFloat64
579 // TODO(neis): Activate once ChangeRepresentation works in typer.
580 // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
581 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
582 // CheckValueInputIs(node, 0, from));
583 // CheckUpperIs(node, to));
586 case IrOpcode::kChangeInt32ToTagged: {
587 // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged
588 // TODO(neis): Activate once ChangeRepresentation works in typer.
589 // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
590 // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged());
591 // CheckValueInputIs(node, 0, from));
592 // CheckUpperIs(node, to));
595 case IrOpcode::kChangeUint32ToTagged: {
596 // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged
597 // TODO(neis): Activate once ChangeRepresentation works in typer.
598 // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32());
599 // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged());
600 // CheckValueInputIs(node, 0, from));
601 // CheckUpperIs(node, to));
604 case IrOpcode::kChangeFloat64ToTagged: {
605 // Number /\ UntaggedFloat64 -> Number /\ Tagged
606 // TODO(neis): Activate once ChangeRepresentation works in typer.
607 // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64());
608 // Type* to = Type::Intersect(Type::Number(), Type::Tagged());
609 // CheckValueInputIs(node, 0, from));
610 // CheckUpperIs(node, to));
613 case IrOpcode::kChangeBoolToBit: {
614 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
615 // TODO(neis): Activate once ChangeRepresentation works in typer.
616 // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
617 // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
618 // CheckValueInputIs(node, 0, from));
619 // CheckUpperIs(node, to));
622 case IrOpcode::kChangeBitToBool: {
623 // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
624 // TODO(neis): Activate once ChangeRepresentation works in typer.
625 // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
626 // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
627 // CheckValueInputIs(node, 0, from));
628 // CheckUpperIs(node, to));
632 case IrOpcode::kLoadField:
633 // Object -> fieldtype
634 // TODO(rossberg): activate once machine ops are typed.
635 // CheckValueInputIs(node, 0, Type::Object());
636 // CheckUpperIs(node, Field(node).type));
638 case IrOpcode::kLoadElement:
639 // Object -> elementtype
640 // TODO(rossberg): activate once machine ops are typed.
641 // CheckValueInputIs(node, 0, Type::Object());
642 // CheckUpperIs(node, Element(node).type));
644 case IrOpcode::kStoreField:
645 // (Object, fieldtype) -> _|_
646 // TODO(rossberg): activate once machine ops are typed.
647 // CheckValueInputIs(node, 0, Type::Object());
648 // CheckValueInputIs(node, 1, Field(node).type));
651 case IrOpcode::kStoreElement:
652 // (Object, elementtype) -> _|_
653 // TODO(rossberg): activate once machine ops are typed.
654 // CheckValueInputIs(node, 0, Type::Object());
655 // CheckValueInputIs(node, 1, Element(node).type));
660 // -----------------------
661 case IrOpcode::kLoad:
662 case IrOpcode::kStore:
663 case IrOpcode::kWord32And:
664 case IrOpcode::kWord32Or:
665 case IrOpcode::kWord32Xor:
666 case IrOpcode::kWord32Shl:
667 case IrOpcode::kWord32Shr:
668 case IrOpcode::kWord32Sar:
669 case IrOpcode::kWord32Ror:
670 case IrOpcode::kWord32Equal:
671 case IrOpcode::kWord64And:
672 case IrOpcode::kWord64Or:
673 case IrOpcode::kWord64Xor:
674 case IrOpcode::kWord64Shl:
675 case IrOpcode::kWord64Shr:
676 case IrOpcode::kWord64Sar:
677 case IrOpcode::kWord64Ror:
678 case IrOpcode::kWord64Equal:
679 case IrOpcode::kInt32Add:
680 case IrOpcode::kInt32AddWithOverflow:
681 case IrOpcode::kInt32Sub:
682 case IrOpcode::kInt32SubWithOverflow:
683 case IrOpcode::kInt32Mul:
684 case IrOpcode::kInt32MulHigh:
685 case IrOpcode::kInt32Div:
686 case IrOpcode::kInt32Mod:
687 case IrOpcode::kInt32LessThan:
688 case IrOpcode::kInt32LessThanOrEqual:
689 case IrOpcode::kUint32Div:
690 case IrOpcode::kUint32Mod:
691 case IrOpcode::kUint32MulHigh:
692 case IrOpcode::kUint32LessThan:
693 case IrOpcode::kUint32LessThanOrEqual:
694 case IrOpcode::kInt64Add:
695 case IrOpcode::kInt64Sub:
696 case IrOpcode::kInt64Mul:
697 case IrOpcode::kInt64Div:
698 case IrOpcode::kInt64Mod:
699 case IrOpcode::kInt64LessThan:
700 case IrOpcode::kInt64LessThanOrEqual:
701 case IrOpcode::kUint64Div:
702 case IrOpcode::kUint64Mod:
703 case IrOpcode::kUint64LessThan:
704 case IrOpcode::kFloat64Add:
705 case IrOpcode::kFloat64Sub:
706 case IrOpcode::kFloat64Mul:
707 case IrOpcode::kFloat64Div:
708 case IrOpcode::kFloat64Mod:
709 case IrOpcode::kFloat64Sqrt:
710 case IrOpcode::kFloat64Floor:
711 case IrOpcode::kFloat64Ceil:
712 case IrOpcode::kFloat64RoundTruncate:
713 case IrOpcode::kFloat64RoundTiesAway:
714 case IrOpcode::kFloat64Equal:
715 case IrOpcode::kFloat64LessThan:
716 case IrOpcode::kFloat64LessThanOrEqual:
717 case IrOpcode::kTruncateInt64ToInt32:
718 case IrOpcode::kTruncateFloat64ToFloat32:
719 case IrOpcode::kTruncateFloat64ToInt32:
720 case IrOpcode::kChangeInt32ToInt64:
721 case IrOpcode::kChangeUint32ToUint64:
722 case IrOpcode::kChangeInt32ToFloat64:
723 case IrOpcode::kChangeUint32ToFloat64:
724 case IrOpcode::kChangeFloat32ToFloat64:
725 case IrOpcode::kChangeFloat64ToInt32:
726 case IrOpcode::kChangeFloat64ToUint32:
727 case IrOpcode::kLoadStackPointer:
728 // TODO(rossberg): Check.
734 void Verifier::Run(Graph* graph, Typing typing) {
735 Visitor visitor(graph->zone(), typing);
736 CHECK_NE(NULL, graph->start());
737 CHECK_NE(NULL, graph->end());
738 graph->VisitNodeInputsFromEnd(&visitor);
742 // -----------------------------------------------------------------------------
744 static bool HasDominatingDef(Schedule* schedule, Node* node,
745 BasicBlock* container, BasicBlock* use_block,
747 BasicBlock* block = use_block;
749 while (use_pos >= 0) {
750 if (block->NodeAt(use_pos) == node) return true;
753 block = block->dominator();
754 if (block == NULL) break;
755 use_pos = static_cast<int>(block->NodeCount()) - 1;
756 if (node == block->control_input()) return true;
762 static bool Dominates(Schedule* schedule, Node* dominator, Node* dominatee) {
763 BasicBlock* dom = schedule->block(dominator);
764 BasicBlock* sub = schedule->block(dominatee);
765 while (sub != NULL) {
769 sub = sub->dominator();
775 static void CheckInputsDominate(Schedule* schedule, BasicBlock* block,
776 Node* node, int use_pos) {
777 for (int j = node->op()->ValueInputCount() - 1; j >= 0; j--) {
778 BasicBlock* use_block = block;
779 if (node->opcode() == IrOpcode::kPhi) {
780 use_block = use_block->PredecessorAt(j);
781 use_pos = static_cast<int>(use_block->NodeCount()) - 1;
783 Node* input = node->InputAt(j);
784 if (!HasDominatingDef(schedule, node->InputAt(j), block, use_block,
786 V8_Fatal(__FILE__, __LINE__,
787 "Node #%d:%s in B%d is not dominated by input@%d #%d:%s",
788 node->id(), node->op()->mnemonic(), block->id().ToInt(), j,
789 input->id(), input->op()->mnemonic());
792 // Ensure that nodes are dominated by their control inputs;
793 // kEnd is an exception, as unreachable blocks resulting from kMerge
794 // are not in the RPO.
795 if (node->op()->ControlInputCount() == 1 &&
796 node->opcode() != IrOpcode::kEnd) {
797 Node* ctl = NodeProperties::GetControlInput(node);
798 if (!Dominates(schedule, ctl, node)) {
799 V8_Fatal(__FILE__, __LINE__,
800 "Node #%d:%s in B%d is not dominated by control input #%d:%s",
801 node->id(), node->op()->mnemonic(), block->id(), ctl->id(),
802 ctl->op()->mnemonic());
808 void ScheduleVerifier::Run(Schedule* schedule) {
809 const size_t count = schedule->BasicBlockCount();
810 Zone tmp_zone(schedule->zone()->isolate());
811 Zone* zone = &tmp_zone;
812 BasicBlock* start = schedule->start();
813 BasicBlockVector* rpo_order = schedule->rpo_order();
815 // Verify the RPO order contains only blocks from this schedule.
816 CHECK_GE(count, rpo_order->size());
817 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
819 CHECK_EQ((*b), schedule->GetBlockById((*b)->id()));
820 // All predecessors and successors should be in rpo and in this schedule.
821 for (BasicBlock::Predecessors::iterator j = (*b)->predecessors_begin();
822 j != (*b)->predecessors_end(); ++j) {
823 CHECK_GE((*j)->rpo_number(), 0);
824 CHECK_EQ((*j), schedule->GetBlockById((*j)->id()));
826 for (BasicBlock::Successors::iterator j = (*b)->successors_begin();
827 j != (*b)->successors_end(); ++j) {
828 CHECK_GE((*j)->rpo_number(), 0);
829 CHECK_EQ((*j), schedule->GetBlockById((*j)->id()));
833 // Verify RPO numbers of blocks.
834 CHECK_EQ(start, rpo_order->at(0)); // Start should be first.
835 for (size_t b = 0; b < rpo_order->size(); b++) {
836 BasicBlock* block = rpo_order->at(b);
837 CHECK_EQ(static_cast<int>(b), block->rpo_number());
838 BasicBlock* dom = block->dominator();
840 // All blocks except start should have a dominator.
843 // Check that the immediate dominator appears somewhere before the block.
845 CHECK_LT(dom->rpo_number(), block->rpo_number());
849 // Verify that all blocks reachable from start are in the RPO.
850 BoolVector marked(static_cast<int>(count), false, zone);
852 ZoneQueue<BasicBlock*> queue(zone);
854 marked[start->id().ToSize()] = true;
855 while (!queue.empty()) {
856 BasicBlock* block = queue.front();
858 for (size_t s = 0; s < block->SuccessorCount(); s++) {
859 BasicBlock* succ = block->SuccessorAt(s);
860 if (!marked[succ->id().ToSize()]) {
861 marked[succ->id().ToSize()] = true;
867 // Verify marked blocks are in the RPO.
868 for (size_t i = 0; i < count; i++) {
869 BasicBlock* block = schedule->GetBlockById(BasicBlock::Id::FromSize(i));
871 CHECK_GE(block->rpo_number(), 0);
872 CHECK_EQ(block, rpo_order->at(block->rpo_number()));
875 // Verify RPO blocks are marked.
876 for (size_t b = 0; b < rpo_order->size(); b++) {
877 CHECK(marked[rpo_order->at(b)->id().ToSize()]);
881 // Verify the dominance relation.
882 ZoneVector<BitVector*> dominators(zone);
883 dominators.resize(count, NULL);
885 // Compute a set of all the nodes that dominate a given node by using
886 // a forward fixpoint. O(n^2).
887 ZoneQueue<BasicBlock*> queue(zone);
889 dominators[start->id().ToSize()] =
890 new (zone) BitVector(static_cast<int>(count), zone);
891 while (!queue.empty()) {
892 BasicBlock* block = queue.front();
894 BitVector* block_doms = dominators[block->id().ToSize()];
895 BasicBlock* idom = block->dominator();
896 if (idom != NULL && !block_doms->Contains(idom->id().ToInt())) {
897 V8_Fatal(__FILE__, __LINE__, "Block B%d is not dominated by B%d",
898 block->id().ToInt(), idom->id().ToInt());
900 for (size_t s = 0; s < block->SuccessorCount(); s++) {
901 BasicBlock* succ = block->SuccessorAt(s);
902 BitVector* succ_doms = dominators[succ->id().ToSize()];
904 if (succ_doms == NULL) {
905 // First time visiting the node. S.doms = B U B.doms
906 succ_doms = new (zone) BitVector(static_cast<int>(count), zone);
907 succ_doms->CopyFrom(*block_doms);
908 succ_doms->Add(block->id().ToInt());
909 dominators[succ->id().ToSize()] = succ_doms;
912 // Nth time visiting the successor. S.doms = S.doms ^ (B U B.doms)
913 bool had = succ_doms->Contains(block->id().ToInt());
914 if (had) succ_doms->Remove(block->id().ToInt());
915 if (succ_doms->IntersectIsChanged(*block_doms)) queue.push(succ);
916 if (had) succ_doms->Add(block->id().ToInt());
921 // Verify the immediateness of dominators.
922 for (BasicBlockVector::iterator b = rpo_order->begin();
923 b != rpo_order->end(); ++b) {
924 BasicBlock* block = *b;
925 BasicBlock* idom = block->dominator();
926 if (idom == NULL) continue;
927 BitVector* block_doms = dominators[block->id().ToSize()];
929 for (BitVector::Iterator it(block_doms); !it.Done(); it.Advance()) {
931 schedule->GetBlockById(BasicBlock::Id::FromInt(it.Current()));
933 !dominators[idom->id().ToSize()]->Contains(dom->id().ToInt())) {
934 V8_Fatal(__FILE__, __LINE__,
935 "Block B%d is not immediately dominated by B%d",
936 block->id().ToInt(), idom->id().ToInt());
942 // Verify phis are placed in the block of their control input.
943 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
945 for (BasicBlock::const_iterator i = (*b)->begin(); i != (*b)->end(); ++i) {
947 if (phi->opcode() != IrOpcode::kPhi) continue;
948 // TODO(titzer): Nasty special case. Phis from RawMachineAssembler
949 // schedules don't have control inputs.
950 if (phi->InputCount() > phi->op()->ValueInputCount()) {
951 Node* control = NodeProperties::GetControlInput(phi);
952 CHECK(control->opcode() == IrOpcode::kMerge ||
953 control->opcode() == IrOpcode::kLoop);
954 CHECK_EQ((*b), schedule->block(control));
959 // Verify that all uses are dominated by their definitions.
960 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
962 BasicBlock* block = *b;
964 // Check inputs to control for this block.
965 Node* control = block->control_input();
966 if (control != NULL) {
967 CHECK_EQ(block, schedule->block(control));
968 CheckInputsDominate(schedule, block, control,
969 static_cast<int>(block->NodeCount()) - 1);
971 // Check inputs for all nodes in the block.
972 for (size_t i = 0; i < block->NodeCount(); i++) {
973 Node* node = block->NodeAt(i);
974 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1);
980 } // namespace v8::internal::compiler