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. 4 5 #include "src/compiler/verifier.h" 6 7 #include <algorithm> 8 #include <deque> 9 #include <queue> 10 #include <sstream> 11 #include <string> 12 13 #include "src/bit-vector.h" 14 #include "src/compiler/all-nodes.h" 15 #include "src/compiler/common-operator.h" 16 #include "src/compiler/graph.h" 17 #include "src/compiler/node.h" 18 #include "src/compiler/node-properties.h" 19 #include "src/compiler/opcodes.h" 20 #include "src/compiler/operator.h" 21 #include "src/compiler/operator-properties.h" 22 #include "src/compiler/schedule.h" 23 #include "src/compiler/simplified-operator.h" 24 #include "src/ostreams.h" 25 #include "src/types-inl.h" 26 27 namespace v8 { 28 namespace internal { 29 namespace compiler { 30 31 32 static bool IsDefUseChainLinkPresent(Node* def, Node* use) { 33 auto const uses = def->uses(); 34 return std::find(uses.begin(), uses.end(), use) != uses.end(); 35 } 36 37 38 static bool IsUseDefChainLinkPresent(Node* def, Node* use) { 39 auto const inputs = use->inputs(); 40 return std::find(inputs.begin(), inputs.end(), def) != inputs.end(); 41 } 42 43 44 class Verifier::Visitor { 45 public: 46 Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {} 47 48 void Check(Node* node); 49 50 Zone* zone; 51 Typing typing; 52 53 private: 54 void CheckNotTyped(Node* node) { 55 if (NodeProperties::IsTyped(node)) { 56 std::ostringstream str; 57 str << "TypeError: node #" << node->id() << ":" << *node->op() 58 << " should never have a type"; 59 FATAL(str.str().c_str()); 60 } 61 } 62 void CheckUpperIs(Node* node, Type* type) { 63 if (typing == TYPED && !NodeProperties::GetType(node)->Is(type)) { 64 std::ostringstream str; 65 str << "TypeError: node #" << node->id() << ":" << *node->op() 66 << " type "; 67 NodeProperties::GetType(node)->PrintTo(str); 68 str << " is not "; 69 type->PrintTo(str); 70 FATAL(str.str().c_str()); 71 } 72 } 73 void CheckUpperMaybe(Node* node, Type* type) { 74 if (typing == TYPED && !NodeProperties::GetType(node)->Maybe(type)) { 75 std::ostringstream str; 76 str << "TypeError: node #" << node->id() << ":" << *node->op() 77 << " type "; 78 NodeProperties::GetType(node)->PrintTo(str); 79 str << " must intersect "; 80 type->PrintTo(str); 81 FATAL(str.str().c_str()); 82 } 83 } 84 void CheckValueInputIs(Node* node, int i, Type* type) { 85 Node* input = NodeProperties::GetValueInput(node, i); 86 if (typing == TYPED && !NodeProperties::GetType(input)->Is(type)) { 87 std::ostringstream str; 88 str << "TypeError: node #" << node->id() << ":" << *node->op() 89 << "(input @" << i << " = " << input->opcode() << ":" 90 << input->op()->mnemonic() << ") type "; 91 NodeProperties::GetType(input)->PrintTo(str); 92 str << " is not "; 93 type->PrintTo(str); 94 FATAL(str.str().c_str()); 95 } 96 } 97 void CheckOutput(Node* node, Node* use, int count, const char* kind) { 98 if (count <= 0) { 99 std::ostringstream str; 100 str << "GraphError: node #" << node->id() << ":" << *node->op() 101 << " does not produce " << kind << " output used by node #" 102 << use->id() << ":" << *use->op(); 103 FATAL(str.str().c_str()); 104 } 105 } 106 }; 107 108 109 void Verifier::Visitor::Check(Node* node) { 110 int value_count = node->op()->ValueInputCount(); 111 int context_count = OperatorProperties::GetContextInputCount(node->op()); 112 int frame_state_count = 113 OperatorProperties::GetFrameStateInputCount(node->op()); 114 int effect_count = node->op()->EffectInputCount(); 115 int control_count = node->op()->ControlInputCount(); 116 117 // Verify number of inputs matches up. 118 int input_count = value_count + context_count + frame_state_count + 119 effect_count + control_count; 120 CHECK_EQ(input_count, node->InputCount()); 121 122 // Verify that frame state has been inserted for the nodes that need it. 123 for (int i = 0; i < frame_state_count; i++) { 124 Node* frame_state = NodeProperties::GetFrameStateInput(node, i); 125 CHECK(frame_state->opcode() == IrOpcode::kFrameState || 126 // kFrameState uses Start as a sentinel. 127 (node->opcode() == IrOpcode::kFrameState && 128 frame_state->opcode() == IrOpcode::kStart)); 129 CHECK(IsDefUseChainLinkPresent(frame_state, node)); 130 CHECK(IsUseDefChainLinkPresent(frame_state, node)); 131 } 132 133 // Verify all value inputs actually produce a value. 134 for (int i = 0; i < value_count; ++i) { 135 Node* value = NodeProperties::GetValueInput(node, i); 136 CheckOutput(value, node, value->op()->ValueOutputCount(), "value"); 137 CHECK(IsDefUseChainLinkPresent(value, node)); 138 CHECK(IsUseDefChainLinkPresent(value, node)); 139 } 140 141 // Verify all context inputs are value nodes. 142 for (int i = 0; i < context_count; ++i) { 143 Node* context = NodeProperties::GetContextInput(node); 144 CheckOutput(context, node, context->op()->ValueOutputCount(), "context"); 145 CHECK(IsDefUseChainLinkPresent(context, node)); 146 CHECK(IsUseDefChainLinkPresent(context, node)); 147 } 148 149 // Verify all effect inputs actually have an effect. 150 for (int i = 0; i < effect_count; ++i) { 151 Node* effect = NodeProperties::GetEffectInput(node); 152 CheckOutput(effect, node, effect->op()->EffectOutputCount(), "effect"); 153 CHECK(IsDefUseChainLinkPresent(effect, node)); 154 CHECK(IsUseDefChainLinkPresent(effect, node)); 155 } 156 157 // Verify all control inputs are control nodes. 158 for (int i = 0; i < control_count; ++i) { 159 Node* control = NodeProperties::GetControlInput(node, i); 160 CheckOutput(control, node, control->op()->ControlOutputCount(), "control"); 161 CHECK(IsDefUseChainLinkPresent(control, node)); 162 CHECK(IsUseDefChainLinkPresent(control, node)); 163 } 164 165 // Verify all successors are projections if multiple value outputs exist. 166 if (node->op()->ValueOutputCount() > 1) { 167 for (Edge edge : node->use_edges()) { 168 Node* use = edge.from(); 169 CHECK(!NodeProperties::IsValueEdge(edge) || 170 use->opcode() == IrOpcode::kProjection || 171 use->opcode() == IrOpcode::kParameter); 172 } 173 } 174 175 switch (node->opcode()) { 176 case IrOpcode::kStart: 177 // Start has no inputs. 178 CHECK_EQ(0, input_count); 179 // Type is a tuple. 180 // TODO(rossberg): Multiple outputs are currently typed as Internal. 181 CheckUpperIs(node, Type::Internal()); 182 break; 183 case IrOpcode::kEnd: 184 // End has no outputs. 185 CHECK(node->op()->ValueOutputCount() == 0); 186 CHECK(node->op()->EffectOutputCount() == 0); 187 CHECK(node->op()->ControlOutputCount() == 0); 188 // Type is empty. 189 CheckNotTyped(node); 190 break; 191 case IrOpcode::kDead: 192 // Dead is never connected to the graph. 193 UNREACHABLE(); 194 break; 195 case IrOpcode::kBranch: { 196 // Branch uses are IfTrue and IfFalse. 197 int count_true = 0, count_false = 0; 198 for (auto use : node->uses()) { 199 CHECK(use->opcode() == IrOpcode::kIfTrue || 200 use->opcode() == IrOpcode::kIfFalse); 201 if (use->opcode() == IrOpcode::kIfTrue) ++count_true; 202 if (use->opcode() == IrOpcode::kIfFalse) ++count_false; 203 } 204 CHECK_EQ(1, count_true); 205 CHECK_EQ(1, count_false); 206 // Type is empty. 207 CheckNotTyped(node); 208 break; 209 } 210 case IrOpcode::kIfTrue: 211 case IrOpcode::kIfFalse: 212 CHECK_EQ(IrOpcode::kBranch, 213 NodeProperties::GetControlInput(node, 0)->opcode()); 214 // Type is empty. 215 CheckNotTyped(node); 216 break; 217 case IrOpcode::kIfSuccess: { 218 // IfSuccess and IfException continuation only on throwing nodes. 219 Node* input = NodeProperties::GetControlInput(node, 0); 220 CHECK(!input->op()->HasProperty(Operator::kNoThrow)); 221 // Type is empty. 222 CheckNotTyped(node); 223 break; 224 } 225 case IrOpcode::kIfException: { 226 // IfSuccess and IfException continuation only on throwing nodes. 227 Node* input = NodeProperties::GetControlInput(node, 0); 228 CHECK(!input->op()->HasProperty(Operator::kNoThrow)); 229 // Type can be anything. 230 CheckUpperIs(node, Type::Any()); 231 break; 232 } 233 case IrOpcode::kSwitch: { 234 // Switch uses are Case and Default. 235 int count_case = 0, count_default = 0; 236 for (auto use : node->uses()) { 237 switch (use->opcode()) { 238 case IrOpcode::kIfValue: { 239 for (auto user : node->uses()) { 240 if (user != use && user->opcode() == IrOpcode::kIfValue) { 241 CHECK_NE(OpParameter<int32_t>(use->op()), 242 OpParameter<int32_t>(user->op())); 243 } 244 } 245 ++count_case; 246 break; 247 } 248 case IrOpcode::kIfDefault: { 249 ++count_default; 250 break; 251 } 252 default: { 253 V8_Fatal(__FILE__, __LINE__, "Switch #%d illegally used by #%d:%s", 254 node->id(), use->id(), use->op()->mnemonic()); 255 break; 256 } 257 } 258 } 259 CHECK_EQ(1, count_default); 260 CHECK_EQ(node->op()->ControlOutputCount(), count_case + count_default); 261 // Type is empty. 262 CheckNotTyped(node); 263 break; 264 } 265 case IrOpcode::kIfValue: 266 case IrOpcode::kIfDefault: 267 CHECK_EQ(IrOpcode::kSwitch, 268 NodeProperties::GetControlInput(node)->opcode()); 269 // Type is empty. 270 CheckNotTyped(node); 271 break; 272 case IrOpcode::kLoop: 273 case IrOpcode::kMerge: 274 CHECK_EQ(control_count, input_count); 275 // Type is empty. 276 CheckNotTyped(node); 277 break; 278 case IrOpcode::kDeoptimize: 279 case IrOpcode::kReturn: 280 case IrOpcode::kThrow: 281 // Deoptimize, Return and Throw uses are End. 282 for (auto use : node->uses()) { 283 CHECK_EQ(IrOpcode::kEnd, use->opcode()); 284 } 285 // Type is empty. 286 CheckNotTyped(node); 287 break; 288 case IrOpcode::kTerminate: 289 // Terminates take one loop and effect. 290 CHECK_EQ(1, control_count); 291 CHECK_EQ(1, effect_count); 292 CHECK_EQ(2, input_count); 293 CHECK_EQ(IrOpcode::kLoop, 294 NodeProperties::GetControlInput(node)->opcode()); 295 // Terminate uses are End. 296 for (auto use : node->uses()) { 297 CHECK_EQ(IrOpcode::kEnd, use->opcode()); 298 } 299 // Type is empty. 300 CheckNotTyped(node); 301 break; 302 case IrOpcode::kOsrNormalEntry: 303 case IrOpcode::kOsrLoopEntry: 304 // Osr entries take one control and effect. 305 CHECK_EQ(1, control_count); 306 CHECK_EQ(1, effect_count); 307 CHECK_EQ(2, input_count); 308 // Type is empty. 309 CheckNotTyped(node); 310 break; 311 312 // Common operators 313 // ---------------- 314 case IrOpcode::kParameter: { 315 // Parameters have the start node as inputs. 316 CHECK_EQ(1, input_count); 317 // Parameter has an input that produces enough values. 318 int const index = ParameterIndexOf(node->op()); 319 Node* const start = NodeProperties::GetValueInput(node, 0); 320 CHECK_EQ(IrOpcode::kStart, start->opcode()); 321 // Currently, parameter indices start at -1 instead of 0. 322 CHECK_LE(-1, index); 323 CHECK_LT(index + 1, start->op()->ValueOutputCount()); 324 // Type can be anything. 325 CheckUpperIs(node, Type::Any()); 326 break; 327 } 328 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant? 329 // Constants have no inputs. 330 CHECK_EQ(0, input_count); 331 // Type is a 32 bit integer, signed or unsigned. 332 CheckUpperIs(node, Type::Integral32()); 333 break; 334 case IrOpcode::kInt64Constant: 335 // Constants have no inputs. 336 CHECK_EQ(0, input_count); 337 // Type is internal. 338 // TODO(rossberg): Introduce proper Int64 type. 339 CheckUpperIs(node, Type::Internal()); 340 break; 341 case IrOpcode::kFloat32Constant: 342 case IrOpcode::kFloat64Constant: 343 case IrOpcode::kNumberConstant: 344 // Constants have no inputs. 345 CHECK_EQ(0, input_count); 346 // Type is a number. 347 CheckUpperIs(node, Type::Number()); 348 break; 349 case IrOpcode::kHeapConstant: 350 // Constants have no inputs. 351 CHECK_EQ(0, input_count); 352 // Type can be anything represented as a heap pointer. 353 CheckUpperIs(node, Type::TaggedPointer()); 354 break; 355 case IrOpcode::kExternalConstant: 356 // Constants have no inputs. 357 CHECK_EQ(0, input_count); 358 // Type is considered internal. 359 CheckUpperIs(node, Type::Internal()); 360 break; 361 case IrOpcode::kOsrValue: 362 // OSR values have a value and a control input. 363 CHECK_EQ(1, control_count); 364 CHECK_EQ(1, input_count); 365 // Type is merged from other values in the graph and could be any. 366 CheckUpperIs(node, Type::Any()); 367 break; 368 case IrOpcode::kProjection: { 369 // Projection has an input that produces enough values. 370 int index = static_cast<int>(ProjectionIndexOf(node->op())); 371 Node* input = NodeProperties::GetValueInput(node, 0); 372 CHECK_GT(input->op()->ValueOutputCount(), index); 373 // Type can be anything. 374 // TODO(rossberg): Introduce tuple types for this. 375 // TODO(titzer): Convince rossberg not to. 376 CheckUpperIs(node, Type::Any()); 377 break; 378 } 379 case IrOpcode::kSelect: { 380 CHECK_EQ(0, effect_count); 381 CHECK_EQ(0, control_count); 382 CHECK_EQ(3, value_count); 383 break; 384 } 385 case IrOpcode::kPhi: { 386 // Phi input count matches parent control node. 387 CHECK_EQ(0, effect_count); 388 CHECK_EQ(1, control_count); 389 Node* control = NodeProperties::GetControlInput(node, 0); 390 CHECK_EQ(value_count, control->op()->ControlInputCount()); 391 CHECK_EQ(input_count, 1 + value_count); 392 // Type must be subsumed by all input types. 393 // TODO(rossberg): for now at least, narrowing does not really hold. 394 /* 395 for (int i = 0; i < value_count; ++i) { 396 CHECK(type_of(ValueInput(node, i))->Is(type_of(node))); 397 } 398 */ 399 break; 400 } 401 case IrOpcode::kEffectPhi: { 402 // EffectPhi input count matches parent control node. 403 CHECK_EQ(0, value_count); 404 CHECK_EQ(1, control_count); 405 Node* control = NodeProperties::GetControlInput(node, 0); 406 CHECK_EQ(effect_count, control->op()->ControlInputCount()); 407 CHECK_EQ(input_count, 1 + effect_count); 408 break; 409 } 410 case IrOpcode::kEffectSet: { 411 CHECK_EQ(0, value_count); 412 CHECK_EQ(0, control_count); 413 CHECK_LT(1, effect_count); 414 break; 415 } 416 case IrOpcode::kGuard: 417 // TODO(bmeurer): what are the constraints on these? 418 break; 419 case IrOpcode::kBeginRegion: 420 // TODO(rossberg): what are the constraints on these? 421 break; 422 case IrOpcode::kFinishRegion: { 423 // TODO(rossberg): what are the constraints on these? 424 // Type must be subsumed by input type. 425 if (typing == TYPED) { 426 Node* val = NodeProperties::GetValueInput(node, 0); 427 CHECK(NodeProperties::GetType(val)->Is(NodeProperties::GetType(node))); 428 } 429 break; 430 } 431 case IrOpcode::kFrameState: 432 // TODO(jarin): what are the constraints on these? 433 CHECK_EQ(5, value_count); 434 CHECK_EQ(0, control_count); 435 CHECK_EQ(0, effect_count); 436 CHECK_EQ(6, input_count); 437 break; 438 case IrOpcode::kStateValues: 439 case IrOpcode::kObjectState: 440 case IrOpcode::kTypedStateValues: 441 // TODO(jarin): what are the constraints on these? 442 break; 443 case IrOpcode::kCall: 444 // TODO(rossberg): what are the constraints on these? 445 break; 446 case IrOpcode::kTailCall: 447 // TODO(bmeurer): what are the constraints on these? 448 break; 449 450 // JavaScript operators 451 // -------------------- 452 case IrOpcode::kJSEqual: 453 case IrOpcode::kJSNotEqual: 454 case IrOpcode::kJSStrictEqual: 455 case IrOpcode::kJSStrictNotEqual: 456 case IrOpcode::kJSLessThan: 457 case IrOpcode::kJSGreaterThan: 458 case IrOpcode::kJSLessThanOrEqual: 459 case IrOpcode::kJSGreaterThanOrEqual: 460 // Type is Boolean. 461 CheckUpperIs(node, Type::Boolean()); 462 break; 463 464 case IrOpcode::kJSBitwiseOr: 465 case IrOpcode::kJSBitwiseXor: 466 case IrOpcode::kJSBitwiseAnd: 467 case IrOpcode::kJSShiftLeft: 468 case IrOpcode::kJSShiftRight: 469 case IrOpcode::kJSShiftRightLogical: 470 // Type is 32 bit integral. 471 CheckUpperIs(node, Type::Integral32()); 472 break; 473 case IrOpcode::kJSAdd: 474 // Type is Number or String. 475 CheckUpperIs(node, Type::NumberOrString()); 476 break; 477 case IrOpcode::kJSSubtract: 478 case IrOpcode::kJSMultiply: 479 case IrOpcode::kJSDivide: 480 case IrOpcode::kJSModulus: 481 // Type is Number. 482 CheckUpperIs(node, Type::Number()); 483 break; 484 485 case IrOpcode::kJSToBoolean: 486 // Type is Boolean. 487 CheckUpperIs(node, Type::Boolean()); 488 break; 489 case IrOpcode::kJSToNumber: 490 // Type is Number. 491 CheckUpperIs(node, Type::Number()); 492 break; 493 case IrOpcode::kJSToString: 494 // Type is String. 495 CheckUpperIs(node, Type::String()); 496 break; 497 case IrOpcode::kJSToName: 498 // Type is Name. 499 CheckUpperIs(node, Type::Name()); 500 break; 501 case IrOpcode::kJSToObject: 502 // Type is Receiver. 503 CheckUpperIs(node, Type::Receiver()); 504 break; 505 506 case IrOpcode::kJSCreate: 507 // Type is Object. 508 CheckUpperIs(node, Type::Object()); 509 break; 510 case IrOpcode::kJSCreateArguments: 511 // Type is OtherObject. 512 CheckUpperIs(node, Type::OtherObject()); 513 break; 514 case IrOpcode::kJSCreateArray: 515 // Type is OtherObject. 516 CheckUpperIs(node, Type::OtherObject()); 517 break; 518 case IrOpcode::kJSCreateClosure: 519 // Type is Function. 520 CheckUpperIs(node, Type::Function()); 521 break; 522 case IrOpcode::kJSCreateIterResultObject: 523 // Type is OtherObject. 524 CheckUpperIs(node, Type::OtherObject()); 525 break; 526 case IrOpcode::kJSCreateLiteralArray: 527 case IrOpcode::kJSCreateLiteralObject: 528 case IrOpcode::kJSCreateLiteralRegExp: 529 // Type is OtherObject. 530 CheckUpperIs(node, Type::OtherObject()); 531 break; 532 case IrOpcode::kJSLoadProperty: 533 case IrOpcode::kJSLoadNamed: 534 case IrOpcode::kJSLoadGlobal: 535 // Type can be anything. 536 CheckUpperIs(node, Type::Any()); 537 break; 538 case IrOpcode::kJSStoreProperty: 539 case IrOpcode::kJSStoreNamed: 540 case IrOpcode::kJSStoreGlobal: 541 // Type is empty. 542 CheckNotTyped(node); 543 break; 544 case IrOpcode::kJSDeleteProperty: 545 case IrOpcode::kJSHasProperty: 546 case IrOpcode::kJSInstanceOf: 547 // Type is Boolean. 548 CheckUpperIs(node, Type::Boolean()); 549 break; 550 case IrOpcode::kJSTypeOf: 551 // Type is String. 552 CheckUpperIs(node, Type::String()); 553 break; 554 555 case IrOpcode::kJSLoadContext: 556 case IrOpcode::kJSLoadDynamic: 557 // Type can be anything. 558 CheckUpperIs(node, Type::Any()); 559 break; 560 case IrOpcode::kJSStoreContext: 561 // Type is empty. 562 CheckNotTyped(node); 563 break; 564 case IrOpcode::kJSCreateFunctionContext: 565 case IrOpcode::kJSCreateCatchContext: 566 case IrOpcode::kJSCreateWithContext: 567 case IrOpcode::kJSCreateBlockContext: 568 case IrOpcode::kJSCreateModuleContext: 569 case IrOpcode::kJSCreateScriptContext: { 570 // Type is Context, and operand is Internal. 571 Node* context = NodeProperties::GetContextInput(node); 572 // TODO(rossberg): This should really be Is(Internal), but the typer 573 // currently can't do backwards propagation. 574 CheckUpperMaybe(context, Type::Internal()); 575 if (typing == TYPED) CHECK(NodeProperties::GetType(node)->IsContext()); 576 break; 577 } 578 579 case IrOpcode::kJSCallConstruct: 580 case IrOpcode::kJSConvertReceiver: 581 // Type is Receiver. 582 CheckUpperIs(node, Type::Receiver()); 583 break; 584 case IrOpcode::kJSCallFunction: 585 case IrOpcode::kJSCallRuntime: 586 case IrOpcode::kJSYield: 587 // Type can be anything. 588 CheckUpperIs(node, Type::Any()); 589 break; 590 591 case IrOpcode::kJSForInPrepare: { 592 // TODO(bmeurer): What are the constraints on thse? 593 CheckUpperIs(node, Type::Any()); 594 break; 595 } 596 case IrOpcode::kJSForInDone: { 597 // TODO(bmeurer): OSR breaks this invariant, although the node is not user 598 // visible, so we know it is safe (fullcodegen has an unsigned smi there). 599 // CheckValueInputIs(node, 0, Type::UnsignedSmall()); 600 break; 601 } 602 case IrOpcode::kJSForInNext: { 603 CheckUpperIs(node, Type::Union(Type::Name(), Type::Undefined(), zone)); 604 break; 605 } 606 case IrOpcode::kJSForInStep: { 607 // TODO(bmeurer): OSR breaks this invariant, although the node is not user 608 // visible, so we know it is safe (fullcodegen has an unsigned smi there). 609 // CheckValueInputIs(node, 0, Type::UnsignedSmall()); 610 CheckUpperIs(node, Type::UnsignedSmall()); 611 break; 612 } 613 614 case IrOpcode::kJSLoadMessage: 615 case IrOpcode::kJSStoreMessage: 616 break; 617 618 case IrOpcode::kJSStackCheck: 619 // Type is empty. 620 CheckNotTyped(node); 621 break; 622 623 // Simplified operators 624 // ------------------------------- 625 case IrOpcode::kBooleanNot: 626 // Boolean -> Boolean 627 CheckValueInputIs(node, 0, Type::Boolean()); 628 CheckUpperIs(node, Type::Boolean()); 629 break; 630 case IrOpcode::kBooleanToNumber: 631 // Boolean -> Number 632 CheckValueInputIs(node, 0, Type::Boolean()); 633 CheckUpperIs(node, Type::Number()); 634 break; 635 case IrOpcode::kNumberEqual: 636 case IrOpcode::kNumberLessThan: 637 case IrOpcode::kNumberLessThanOrEqual: 638 // (Number, Number) -> Boolean 639 CheckValueInputIs(node, 0, Type::Number()); 640 CheckValueInputIs(node, 1, Type::Number()); 641 CheckUpperIs(node, Type::Boolean()); 642 break; 643 case IrOpcode::kNumberAdd: 644 case IrOpcode::kNumberSubtract: 645 case IrOpcode::kNumberMultiply: 646 case IrOpcode::kNumberDivide: 647 case IrOpcode::kNumberModulus: 648 // (Number, Number) -> Number 649 CheckValueInputIs(node, 0, Type::Number()); 650 CheckValueInputIs(node, 1, Type::Number()); 651 // TODO(rossberg): activate once we retype after opcode changes. 652 // CheckUpperIs(node, Type::Number()); 653 break; 654 case IrOpcode::kNumberBitwiseOr: 655 case IrOpcode::kNumberBitwiseXor: 656 case IrOpcode::kNumberBitwiseAnd: 657 // (Signed32, Signed32) -> Signed32 658 CheckValueInputIs(node, 0, Type::Signed32()); 659 CheckValueInputIs(node, 1, Type::Signed32()); 660 CheckUpperIs(node, Type::Signed32()); 661 break; 662 case IrOpcode::kNumberShiftLeft: 663 case IrOpcode::kNumberShiftRight: 664 // (Signed32, Unsigned32) -> Signed32 665 CheckValueInputIs(node, 0, Type::Signed32()); 666 CheckValueInputIs(node, 1, Type::Unsigned32()); 667 CheckUpperIs(node, Type::Signed32()); 668 break; 669 case IrOpcode::kNumberShiftRightLogical: 670 // (Unsigned32, Unsigned32) -> Unsigned32 671 CheckValueInputIs(node, 0, Type::Unsigned32()); 672 CheckValueInputIs(node, 1, Type::Unsigned32()); 673 CheckUpperIs(node, Type::Unsigned32()); 674 break; 675 case IrOpcode::kNumberToInt32: 676 // Number -> Signed32 677 CheckValueInputIs(node, 0, Type::Number()); 678 CheckUpperIs(node, Type::Signed32()); 679 break; 680 case IrOpcode::kNumberToUint32: 681 // Number -> Unsigned32 682 CheckValueInputIs(node, 0, Type::Number()); 683 CheckUpperIs(node, Type::Unsigned32()); 684 break; 685 case IrOpcode::kNumberIsHoleNaN: 686 // Number -> Boolean 687 CheckValueInputIs(node, 0, Type::Number()); 688 CheckUpperIs(node, Type::Boolean()); 689 break; 690 case IrOpcode::kPlainPrimitiveToNumber: 691 // PlainPrimitive -> Number 692 CheckValueInputIs(node, 0, Type::PlainPrimitive()); 693 CheckUpperIs(node, Type::Number()); 694 break; 695 case IrOpcode::kStringEqual: 696 case IrOpcode::kStringLessThan: 697 case IrOpcode::kStringLessThanOrEqual: 698 // (String, String) -> Boolean 699 CheckValueInputIs(node, 0, Type::String()); 700 CheckValueInputIs(node, 1, Type::String()); 701 CheckUpperIs(node, Type::Boolean()); 702 break; 703 case IrOpcode::kReferenceEqual: { 704 // (Unique, Any) -> Boolean and 705 // (Any, Unique) -> Boolean 706 CheckUpperIs(node, Type::Boolean()); 707 break; 708 } 709 case IrOpcode::kObjectIsNumber: 710 case IrOpcode::kObjectIsSmi: 711 CheckValueInputIs(node, 0, Type::Any()); 712 CheckUpperIs(node, Type::Boolean()); 713 break; 714 case IrOpcode::kAllocate: 715 CheckValueInputIs(node, 0, Type::PlainNumber()); 716 CheckUpperIs(node, Type::TaggedPointer()); 717 break; 718 719 case IrOpcode::kChangeTaggedToInt32: { 720 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32 721 // TODO(neis): Activate once ChangeRepresentation works in typer. 722 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged()); 723 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); 724 // CheckValueInputIs(node, 0, from)); 725 // CheckUpperIs(node, to)); 726 break; 727 } 728 case IrOpcode::kChangeTaggedToUint32: { 729 // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32 730 // TODO(neis): Activate once ChangeRepresentation works in typer. 731 // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged()); 732 // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32()); 733 // CheckValueInputIs(node, 0, from)); 734 // CheckUpperIs(node, to)); 735 break; 736 } 737 case IrOpcode::kChangeTaggedToFloat64: { 738 // Number /\ Tagged -> Number /\ UntaggedFloat64 739 // TODO(neis): Activate once ChangeRepresentation works in typer. 740 // Type* from = Type::Intersect(Type::Number(), Type::Tagged()); 741 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64()); 742 // CheckValueInputIs(node, 0, from)); 743 // CheckUpperIs(node, to)); 744 break; 745 } 746 case IrOpcode::kChangeInt32ToTagged: { 747 // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged 748 // TODO(neis): Activate once ChangeRepresentation works in typer. 749 // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); 750 // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged()); 751 // CheckValueInputIs(node, 0, from)); 752 // CheckUpperIs(node, to)); 753 break; 754 } 755 case IrOpcode::kChangeUint32ToTagged: { 756 // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged 757 // TODO(neis): Activate once ChangeRepresentation works in typer. 758 // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32()); 759 // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged()); 760 // CheckValueInputIs(node, 0, from)); 761 // CheckUpperIs(node, to)); 762 break; 763 } 764 case IrOpcode::kChangeFloat64ToTagged: { 765 // Number /\ UntaggedFloat64 -> Number /\ Tagged 766 // TODO(neis): Activate once ChangeRepresentation works in typer. 767 // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64()); 768 // Type* to = Type::Intersect(Type::Number(), Type::Tagged()); 769 // CheckValueInputIs(node, 0, from)); 770 // CheckUpperIs(node, to)); 771 break; 772 } 773 case IrOpcode::kChangeBoolToBit: { 774 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1 775 // TODO(neis): Activate once ChangeRepresentation works in typer. 776 // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); 777 // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); 778 // CheckValueInputIs(node, 0, from)); 779 // CheckUpperIs(node, to)); 780 break; 781 } 782 case IrOpcode::kChangeBitToBool: { 783 // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr 784 // TODO(neis): Activate once ChangeRepresentation works in typer. 785 // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); 786 // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); 787 // CheckValueInputIs(node, 0, from)); 788 // CheckUpperIs(node, to)); 789 break; 790 } 791 792 case IrOpcode::kLoadField: 793 // Object -> fieldtype 794 // TODO(rossberg): activate once machine ops are typed. 795 // CheckValueInputIs(node, 0, Type::Object()); 796 // CheckUpperIs(node, FieldAccessOf(node->op()).type)); 797 break; 798 case IrOpcode::kLoadBuffer: 799 break; 800 case IrOpcode::kLoadElement: 801 // Object -> elementtype 802 // TODO(rossberg): activate once machine ops are typed. 803 // CheckValueInputIs(node, 0, Type::Object()); 804 // CheckUpperIs(node, ElementAccessOf(node->op()).type)); 805 break; 806 case IrOpcode::kStoreField: 807 // (Object, fieldtype) -> _|_ 808 // TODO(rossberg): activate once machine ops are typed. 809 // CheckValueInputIs(node, 0, Type::Object()); 810 // CheckValueInputIs(node, 1, FieldAccessOf(node->op()).type)); 811 CheckNotTyped(node); 812 break; 813 case IrOpcode::kStoreBuffer: 814 break; 815 case IrOpcode::kStoreElement: 816 // (Object, elementtype) -> _|_ 817 // TODO(rossberg): activate once machine ops are typed. 818 // CheckValueInputIs(node, 0, Type::Object()); 819 // CheckValueInputIs(node, 1, ElementAccessOf(node->op()).type)); 820 CheckNotTyped(node); 821 break; 822 823 // Machine operators 824 // ----------------------- 825 case IrOpcode::kLoad: 826 case IrOpcode::kStore: 827 case IrOpcode::kWord32And: 828 case IrOpcode::kWord32Or: 829 case IrOpcode::kWord32Xor: 830 case IrOpcode::kWord32Shl: 831 case IrOpcode::kWord32Shr: 832 case IrOpcode::kWord32Sar: 833 case IrOpcode::kWord32Ror: 834 case IrOpcode::kWord32Equal: 835 case IrOpcode::kWord32Clz: 836 case IrOpcode::kWord32Ctz: 837 case IrOpcode::kWord32Popcnt: 838 case IrOpcode::kWord64And: 839 case IrOpcode::kWord64Or: 840 case IrOpcode::kWord64Xor: 841 case IrOpcode::kWord64Shl: 842 case IrOpcode::kWord64Shr: 843 case IrOpcode::kWord64Sar: 844 case IrOpcode::kWord64Ror: 845 case IrOpcode::kWord64Clz: 846 case IrOpcode::kWord64Popcnt: 847 case IrOpcode::kWord64Ctz: 848 case IrOpcode::kWord64Equal: 849 case IrOpcode::kInt32Add: 850 case IrOpcode::kInt32AddWithOverflow: 851 case IrOpcode::kInt32Sub: 852 case IrOpcode::kInt32SubWithOverflow: 853 case IrOpcode::kInt32Mul: 854 case IrOpcode::kInt32MulHigh: 855 case IrOpcode::kInt32Div: 856 case IrOpcode::kInt32Mod: 857 case IrOpcode::kInt32LessThan: 858 case IrOpcode::kInt32LessThanOrEqual: 859 case IrOpcode::kUint32Div: 860 case IrOpcode::kUint32Mod: 861 case IrOpcode::kUint32MulHigh: 862 case IrOpcode::kUint32LessThan: 863 case IrOpcode::kUint32LessThanOrEqual: 864 case IrOpcode::kInt64Add: 865 case IrOpcode::kInt64AddWithOverflow: 866 case IrOpcode::kInt64Sub: 867 case IrOpcode::kInt64SubWithOverflow: 868 case IrOpcode::kInt64Mul: 869 case IrOpcode::kInt64Div: 870 case IrOpcode::kInt64Mod: 871 case IrOpcode::kInt64LessThan: 872 case IrOpcode::kInt64LessThanOrEqual: 873 case IrOpcode::kUint64Div: 874 case IrOpcode::kUint64Mod: 875 case IrOpcode::kUint64LessThan: 876 case IrOpcode::kUint64LessThanOrEqual: 877 case IrOpcode::kFloat32Add: 878 case IrOpcode::kFloat32Sub: 879 case IrOpcode::kFloat32Mul: 880 case IrOpcode::kFloat32Div: 881 case IrOpcode::kFloat32Max: 882 case IrOpcode::kFloat32Min: 883 case IrOpcode::kFloat32Abs: 884 case IrOpcode::kFloat32Sqrt: 885 case IrOpcode::kFloat32Equal: 886 case IrOpcode::kFloat32LessThan: 887 case IrOpcode::kFloat32LessThanOrEqual: 888 case IrOpcode::kFloat64Add: 889 case IrOpcode::kFloat64Sub: 890 case IrOpcode::kFloat64Mul: 891 case IrOpcode::kFloat64Div: 892 case IrOpcode::kFloat64Mod: 893 case IrOpcode::kFloat64Max: 894 case IrOpcode::kFloat64Min: 895 case IrOpcode::kFloat64Abs: 896 case IrOpcode::kFloat64Sqrt: 897 case IrOpcode::kFloat32RoundDown: 898 case IrOpcode::kFloat64RoundDown: 899 case IrOpcode::kFloat32RoundUp: 900 case IrOpcode::kFloat64RoundUp: 901 case IrOpcode::kFloat32RoundTruncate: 902 case IrOpcode::kFloat64RoundTruncate: 903 case IrOpcode::kFloat64RoundTiesAway: 904 case IrOpcode::kFloat32RoundTiesEven: 905 case IrOpcode::kFloat64RoundTiesEven: 906 case IrOpcode::kFloat64Equal: 907 case IrOpcode::kFloat64LessThan: 908 case IrOpcode::kFloat64LessThanOrEqual: 909 case IrOpcode::kTruncateInt64ToInt32: 910 case IrOpcode::kRoundInt64ToFloat32: 911 case IrOpcode::kRoundInt64ToFloat64: 912 case IrOpcode::kRoundUint64ToFloat64: 913 case IrOpcode::kRoundUint64ToFloat32: 914 case IrOpcode::kTruncateFloat64ToFloat32: 915 case IrOpcode::kTruncateFloat64ToInt32: 916 case IrOpcode::kBitcastFloat32ToInt32: 917 case IrOpcode::kBitcastFloat64ToInt64: 918 case IrOpcode::kBitcastInt32ToFloat32: 919 case IrOpcode::kBitcastInt64ToFloat64: 920 case IrOpcode::kChangeInt32ToInt64: 921 case IrOpcode::kChangeUint32ToUint64: 922 case IrOpcode::kChangeInt32ToFloat64: 923 case IrOpcode::kChangeUint32ToFloat64: 924 case IrOpcode::kChangeFloat32ToFloat64: 925 case IrOpcode::kChangeFloat64ToInt32: 926 case IrOpcode::kChangeFloat64ToUint32: 927 case IrOpcode::kTryTruncateFloat32ToInt64: 928 case IrOpcode::kTryTruncateFloat64ToInt64: 929 case IrOpcode::kTryTruncateFloat32ToUint64: 930 case IrOpcode::kTryTruncateFloat64ToUint64: 931 case IrOpcode::kFloat64ExtractLowWord32: 932 case IrOpcode::kFloat64ExtractHighWord32: 933 case IrOpcode::kFloat64InsertLowWord32: 934 case IrOpcode::kFloat64InsertHighWord32: 935 case IrOpcode::kLoadStackPointer: 936 case IrOpcode::kLoadFramePointer: 937 case IrOpcode::kCheckedLoad: 938 case IrOpcode::kCheckedStore: 939 // TODO(rossberg): Check. 940 break; 941 } 942 } // NOLINT(readability/fn_size) 943 944 945 void Verifier::Run(Graph* graph, Typing typing) { 946 CHECK_NOT_NULL(graph->start()); 947 CHECK_NOT_NULL(graph->end()); 948 Zone zone; 949 Visitor visitor(&zone, typing); 950 AllNodes all(&zone, graph); 951 for (Node* node : all.live) visitor.Check(node); 952 953 // Check the uniqueness of projections. 954 for (Node* proj : all.live) { 955 if (proj->opcode() != IrOpcode::kProjection) continue; 956 Node* node = proj->InputAt(0); 957 for (Node* other : node->uses()) { 958 if (all.IsLive(other) && other != proj && 959 other->opcode() == IrOpcode::kProjection && 960 ProjectionIndexOf(other->op()) == ProjectionIndexOf(proj->op())) { 961 V8_Fatal(__FILE__, __LINE__, 962 "Node #%d:%s has duplicate projections #%d and #%d", 963 node->id(), node->op()->mnemonic(), proj->id(), other->id()); 964 } 965 } 966 } 967 } 968 969 970 // ----------------------------------------------------------------------------- 971 972 static bool HasDominatingDef(Schedule* schedule, Node* node, 973 BasicBlock* container, BasicBlock* use_block, 974 int use_pos) { 975 BasicBlock* block = use_block; 976 while (true) { 977 while (use_pos >= 0) { 978 if (block->NodeAt(use_pos) == node) return true; 979 use_pos--; 980 } 981 block = block->dominator(); 982 if (block == nullptr) break; 983 use_pos = static_cast<int>(block->NodeCount()) - 1; 984 if (node == block->control_input()) return true; 985 } 986 return false; 987 } 988 989 990 static bool Dominates(Schedule* schedule, Node* dominator, Node* dominatee) { 991 BasicBlock* dom = schedule->block(dominator); 992 BasicBlock* sub = schedule->block(dominatee); 993 while (sub != nullptr) { 994 if (sub == dom) { 995 return true; 996 } 997 sub = sub->dominator(); 998 } 999 return false; 1000 } 1001 1002 1003 static void CheckInputsDominate(Schedule* schedule, BasicBlock* block, 1004 Node* node, int use_pos) { 1005 for (int j = node->op()->ValueInputCount() - 1; j >= 0; j--) { 1006 BasicBlock* use_block = block; 1007 if (node->opcode() == IrOpcode::kPhi) { 1008 use_block = use_block->PredecessorAt(j); 1009 use_pos = static_cast<int>(use_block->NodeCount()) - 1; 1010 } 1011 Node* input = node->InputAt(j); 1012 if (!HasDominatingDef(schedule, node->InputAt(j), block, use_block, 1013 use_pos)) { 1014 V8_Fatal(__FILE__, __LINE__, 1015 "Node #%d:%s in B%d is not dominated by input@%d #%d:%s", 1016 node->id(), node->op()->mnemonic(), block->rpo_number(), j, 1017 input->id(), input->op()->mnemonic()); 1018 } 1019 } 1020 // Ensure that nodes are dominated by their control inputs; 1021 // kEnd is an exception, as unreachable blocks resulting from kMerge 1022 // are not in the RPO. 1023 if (node->op()->ControlInputCount() == 1 && 1024 node->opcode() != IrOpcode::kEnd) { 1025 Node* ctl = NodeProperties::GetControlInput(node); 1026 if (!Dominates(schedule, ctl, node)) { 1027 V8_Fatal(__FILE__, __LINE__, 1028 "Node #%d:%s in B%d is not dominated by control input #%d:%s", 1029 node->id(), node->op()->mnemonic(), block->rpo_number(), 1030 ctl->id(), ctl->op()->mnemonic()); 1031 } 1032 } 1033 } 1034 1035 1036 void ScheduleVerifier::Run(Schedule* schedule) { 1037 const size_t count = schedule->BasicBlockCount(); 1038 Zone tmp_zone; 1039 Zone* zone = &tmp_zone; 1040 BasicBlock* start = schedule->start(); 1041 BasicBlockVector* rpo_order = schedule->rpo_order(); 1042 1043 // Verify the RPO order contains only blocks from this schedule. 1044 CHECK_GE(count, rpo_order->size()); 1045 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end(); 1046 ++b) { 1047 CHECK_EQ((*b), schedule->GetBlockById((*b)->id())); 1048 // All predecessors and successors should be in rpo and in this schedule. 1049 for (BasicBlock const* predecessor : (*b)->predecessors()) { 1050 CHECK_GE(predecessor->rpo_number(), 0); 1051 CHECK_EQ(predecessor, schedule->GetBlockById(predecessor->id())); 1052 } 1053 for (BasicBlock const* successor : (*b)->successors()) { 1054 CHECK_GE(successor->rpo_number(), 0); 1055 CHECK_EQ(successor, schedule->GetBlockById(successor->id())); 1056 } 1057 } 1058 1059 // Verify RPO numbers of blocks. 1060 CHECK_EQ(start, rpo_order->at(0)); // Start should be first. 1061 for (size_t b = 0; b < rpo_order->size(); b++) { 1062 BasicBlock* block = rpo_order->at(b); 1063 CHECK_EQ(static_cast<int>(b), block->rpo_number()); 1064 BasicBlock* dom = block->dominator(); 1065 if (b == 0) { 1066 // All blocks except start should have a dominator. 1067 CHECK_NULL(dom); 1068 } else { 1069 // Check that the immediate dominator appears somewhere before the block. 1070 CHECK_NOT_NULL(dom); 1071 CHECK_LT(dom->rpo_number(), block->rpo_number()); 1072 } 1073 } 1074 1075 // Verify that all blocks reachable from start are in the RPO. 1076 BoolVector marked(static_cast<int>(count), false, zone); 1077 { 1078 ZoneQueue<BasicBlock*> queue(zone); 1079 queue.push(start); 1080 marked[start->id().ToSize()] = true; 1081 while (!queue.empty()) { 1082 BasicBlock* block = queue.front(); 1083 queue.pop(); 1084 for (size_t s = 0; s < block->SuccessorCount(); s++) { 1085 BasicBlock* succ = block->SuccessorAt(s); 1086 if (!marked[succ->id().ToSize()]) { 1087 marked[succ->id().ToSize()] = true; 1088 queue.push(succ); 1089 } 1090 } 1091 } 1092 } 1093 // Verify marked blocks are in the RPO. 1094 for (size_t i = 0; i < count; i++) { 1095 BasicBlock* block = schedule->GetBlockById(BasicBlock::Id::FromSize(i)); 1096 if (marked[i]) { 1097 CHECK_GE(block->rpo_number(), 0); 1098 CHECK_EQ(block, rpo_order->at(block->rpo_number())); 1099 } 1100 } 1101 // Verify RPO blocks are marked. 1102 for (size_t b = 0; b < rpo_order->size(); b++) { 1103 CHECK(marked[rpo_order->at(b)->id().ToSize()]); 1104 } 1105 1106 { 1107 // Verify the dominance relation. 1108 ZoneVector<BitVector*> dominators(zone); 1109 dominators.resize(count, nullptr); 1110 1111 // Compute a set of all the nodes that dominate a given node by using 1112 // a forward fixpoint. O(n^2). 1113 ZoneQueue<BasicBlock*> queue(zone); 1114 queue.push(start); 1115 dominators[start->id().ToSize()] = 1116 new (zone) BitVector(static_cast<int>(count), zone); 1117 while (!queue.empty()) { 1118 BasicBlock* block = queue.front(); 1119 queue.pop(); 1120 BitVector* block_doms = dominators[block->id().ToSize()]; 1121 BasicBlock* idom = block->dominator(); 1122 if (idom != nullptr && !block_doms->Contains(idom->id().ToInt())) { 1123 V8_Fatal(__FILE__, __LINE__, "Block B%d is not dominated by B%d", 1124 block->rpo_number(), idom->rpo_number()); 1125 } 1126 for (size_t s = 0; s < block->SuccessorCount(); s++) { 1127 BasicBlock* succ = block->SuccessorAt(s); 1128 BitVector* succ_doms = dominators[succ->id().ToSize()]; 1129 1130 if (succ_doms == nullptr) { 1131 // First time visiting the node. S.doms = B U B.doms 1132 succ_doms = new (zone) BitVector(static_cast<int>(count), zone); 1133 succ_doms->CopyFrom(*block_doms); 1134 succ_doms->Add(block->id().ToInt()); 1135 dominators[succ->id().ToSize()] = succ_doms; 1136 queue.push(succ); 1137 } else { 1138 // Nth time visiting the successor. S.doms = S.doms ^ (B U B.doms) 1139 bool had = succ_doms->Contains(block->id().ToInt()); 1140 if (had) succ_doms->Remove(block->id().ToInt()); 1141 if (succ_doms->IntersectIsChanged(*block_doms)) queue.push(succ); 1142 if (had) succ_doms->Add(block->id().ToInt()); 1143 } 1144 } 1145 } 1146 1147 // Verify the immediateness of dominators. 1148 for (BasicBlockVector::iterator b = rpo_order->begin(); 1149 b != rpo_order->end(); ++b) { 1150 BasicBlock* block = *b; 1151 BasicBlock* idom = block->dominator(); 1152 if (idom == nullptr) continue; 1153 BitVector* block_doms = dominators[block->id().ToSize()]; 1154 1155 for (BitVector::Iterator it(block_doms); !it.Done(); it.Advance()) { 1156 BasicBlock* dom = 1157 schedule->GetBlockById(BasicBlock::Id::FromInt(it.Current())); 1158 if (dom != idom && 1159 !dominators[idom->id().ToSize()]->Contains(dom->id().ToInt())) { 1160 V8_Fatal(__FILE__, __LINE__, 1161 "Block B%d is not immediately dominated by B%d", 1162 block->rpo_number(), idom->rpo_number()); 1163 } 1164 } 1165 } 1166 } 1167 1168 // Verify phis are placed in the block of their control input. 1169 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end(); 1170 ++b) { 1171 for (BasicBlock::const_iterator i = (*b)->begin(); i != (*b)->end(); ++i) { 1172 Node* phi = *i; 1173 if (phi->opcode() != IrOpcode::kPhi) continue; 1174 // TODO(titzer): Nasty special case. Phis from RawMachineAssembler 1175 // schedules don't have control inputs. 1176 if (phi->InputCount() > phi->op()->ValueInputCount()) { 1177 Node* control = NodeProperties::GetControlInput(phi); 1178 CHECK(control->opcode() == IrOpcode::kMerge || 1179 control->opcode() == IrOpcode::kLoop); 1180 CHECK_EQ((*b), schedule->block(control)); 1181 } 1182 } 1183 } 1184 1185 // Verify that all uses are dominated by their definitions. 1186 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end(); 1187 ++b) { 1188 BasicBlock* block = *b; 1189 1190 // Check inputs to control for this block. 1191 Node* control = block->control_input(); 1192 if (control != nullptr) { 1193 CHECK_EQ(block, schedule->block(control)); 1194 CheckInputsDominate(schedule, block, control, 1195 static_cast<int>(block->NodeCount()) - 1); 1196 } 1197 // Check inputs for all nodes in the block. 1198 for (size_t i = 0; i < block->NodeCount(); i++) { 1199 Node* node = block->NodeAt(i); 1200 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1); 1201 } 1202 } 1203 } 1204 1205 1206 #ifdef DEBUG 1207 1208 // static 1209 void Verifier::VerifyNode(Node* node) { 1210 CHECK_EQ(OperatorProperties::GetTotalInputCount(node->op()), 1211 node->InputCount()); 1212 // If this node has no effect or no control outputs, 1213 // we check that no its uses are effect or control inputs. 1214 bool check_no_control = node->op()->ControlOutputCount() == 0; 1215 bool check_no_effect = node->op()->EffectOutputCount() == 0; 1216 bool check_no_frame_state = node->opcode() != IrOpcode::kFrameState; 1217 if (check_no_effect || check_no_control) { 1218 for (Edge edge : node->use_edges()) { 1219 Node* const user = edge.from(); 1220 CHECK(!user->IsDead()); 1221 if (NodeProperties::IsControlEdge(edge)) { 1222 CHECK(!check_no_control); 1223 } else if (NodeProperties::IsEffectEdge(edge)) { 1224 CHECK(!check_no_effect); 1225 } else if (NodeProperties::IsFrameStateEdge(edge)) { 1226 CHECK(!check_no_frame_state); 1227 } 1228 } 1229 } 1230 // Frame state inputs should be frame states (or sentinels). 1231 for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(node->op()); 1232 i++) { 1233 Node* input = NodeProperties::GetFrameStateInput(node, i); 1234 CHECK(input->opcode() == IrOpcode::kFrameState || 1235 input->opcode() == IrOpcode::kStart || 1236 input->opcode() == IrOpcode::kDead); 1237 } 1238 // Effect inputs should be effect-producing nodes (or sentinels). 1239 for (int i = 0; i < node->op()->EffectInputCount(); i++) { 1240 Node* input = NodeProperties::GetEffectInput(node, i); 1241 CHECK(input->op()->EffectOutputCount() > 0 || 1242 input->opcode() == IrOpcode::kDead); 1243 } 1244 // Control inputs should be control-producing nodes (or sentinels). 1245 for (int i = 0; i < node->op()->ControlInputCount(); i++) { 1246 Node* input = NodeProperties::GetControlInput(node, i); 1247 CHECK(input->op()->ControlOutputCount() > 0 || 1248 input->opcode() == IrOpcode::kDead); 1249 } 1250 } 1251 1252 1253 void Verifier::VerifyEdgeInputReplacement(const Edge& edge, 1254 const Node* replacement) { 1255 // Check that the user does not misuse the replacement. 1256 DCHECK(!NodeProperties::IsControlEdge(edge) || 1257 replacement->op()->ControlOutputCount() > 0); 1258 DCHECK(!NodeProperties::IsEffectEdge(edge) || 1259 replacement->op()->EffectOutputCount() > 0); 1260 DCHECK(!NodeProperties::IsFrameStateEdge(edge) || 1261 replacement->opcode() == IrOpcode::kFrameState); 1262 } 1263 1264 #endif // DEBUG 1265 1266 } // namespace compiler 1267 } // namespace internal 1268 } // namespace v8 1269