verifier.cc 37.4 KB
Newer Older
1 2 3 4 5 6
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/verifier.h"

7
#include <algorithm>
8 9
#include <deque>
#include <queue>
10 11
#include <sstream>
#include <string>
12

13
#include "src/bit-vector.h"
14
#include "src/compiler/all-nodes.h"
15
#include "src/compiler/common-operator.h"
16 17 18 19 20
#include "src/compiler/graph.h"
#include "src/compiler/node.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/opcodes.h"
#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 26 27 28 29 30 31

namespace v8 {
namespace internal {
namespace compiler {


static bool IsDefUseChainLinkPresent(Node* def, Node* use) {
32 33
  auto const uses = def->uses();
  return std::find(uses.begin(), uses.end(), use) != uses.end();
34 35 36 37
}


static bool IsUseDefChainLinkPresent(Node* def, Node* use) {
38 39
  auto const inputs = use->inputs();
  return std::find(inputs.begin(), inputs.end(), def) != inputs.end();
40 41 42
}


43
class Verifier::Visitor {
44
 public:
45
  Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {}
46

47
  void Check(Node* node);
48

49 50 51 52 53
  Zone* zone;
  Typing typing;

 private:
  // TODO(rossberg): Get rid of these once we got rid of NodeProperties.
54 55
  Bounds bounds(Node* node) { return NodeProperties::GetBounds(node); }
  Node* ValueInput(Node* node, int i = 0) {
56 57 58 59 60 61 62 63 64 65 66 67
    return NodeProperties::GetValueInput(node, i);
  }
  FieldAccess Field(Node* node) {
    DCHECK(node->opcode() == IrOpcode::kLoadField ||
           node->opcode() == IrOpcode::kStoreField);
    return OpParameter<FieldAccess>(node);
  }
  ElementAccess Element(Node* node) {
    DCHECK(node->opcode() == IrOpcode::kLoadElement ||
           node->opcode() == IrOpcode::kStoreElement);
    return OpParameter<ElementAccess>(node);
  }
68 69 70
  void CheckNotTyped(Node* node) {
    if (NodeProperties::IsTyped(node)) {
      std::ostringstream str;
71 72 73
      str << "TypeError: node #" << node->id() << ":" << *node->op()
          << " should never have a type";
      FATAL(str.str().c_str());
74 75 76 77 78
    }
  }
  void CheckUpperIs(Node* node, Type* type) {
    if (typing == TYPED && !bounds(node).upper->Is(type)) {
      std::ostringstream str;
79 80
      str << "TypeError: node #" << node->id() << ":" << *node->op()
          << " upper bound ";
81 82 83
      bounds(node).upper->PrintTo(str);
      str << " is not ";
      type->PrintTo(str);
84
      FATAL(str.str().c_str());
85 86 87 88 89
    }
  }
  void CheckUpperMaybe(Node* node, Type* type) {
    if (typing == TYPED && !bounds(node).upper->Maybe(type)) {
      std::ostringstream str;
90 91
      str << "TypeError: node #" << node->id() << ":" << *node->op()
          << " upper bound ";
92 93 94
      bounds(node).upper->PrintTo(str);
      str << " must intersect ";
      type->PrintTo(str);
95
      FATAL(str.str().c_str());
96 97 98 99 100 101
    }
  }
  void CheckValueInputIs(Node* node, int i, Type* type) {
    Node* input = ValueInput(node, i);
    if (typing == TYPED && !bounds(input).upper->Is(type)) {
      std::ostringstream str;
102 103 104
      str << "TypeError: node #" << node->id() << ":" << *node->op()
          << "(input @" << i << " = " << input->opcode() << ":"
          << input->op()->mnemonic() << ") upper bound ";
105 106 107
      bounds(input).upper->PrintTo(str);
      str << " is not ";
      type->PrintTo(str);
108
      FATAL(str.str().c_str());
109 110
    }
  }
111 112 113
};


114
void Verifier::Visitor::Check(Node* node) {
115
  int value_count = node->op()->ValueInputCount();
116
  int context_count = OperatorProperties::GetContextInputCount(node->op());
117 118
  int frame_state_count =
      OperatorProperties::GetFrameStateInputCount(node->op());
119 120
  int effect_count = node->op()->EffectInputCount();
  int control_count = node->op()->ControlInputCount();
121 122

  // Verify number of inputs matches up.
123 124
  int input_count = value_count + context_count + frame_state_count +
                    effect_count + control_count;
125 126
  CHECK_EQ(input_count, node->InputCount());

127
  // Verify that frame state has been inserted for the nodes that need it.
128 129
  for (int i = 0; i < frame_state_count; i++) {
    Node* frame_state = NodeProperties::GetFrameStateInput(node, i);
130 131 132 133
    CHECK(frame_state->opcode() == IrOpcode::kFrameState ||
          // kFrameState uses undefined as a sentinel.
          (node->opcode() == IrOpcode::kFrameState &&
           frame_state->opcode() == IrOpcode::kHeapConstant));
134 135 136 137
    CHECK(IsDefUseChainLinkPresent(frame_state, node));
    CHECK(IsUseDefChainLinkPresent(frame_state, node));
  }

138 139 140
  // Verify all value inputs actually produce a value.
  for (int i = 0; i < value_count; ++i) {
    Node* value = NodeProperties::GetValueInput(node, i);
141
    CHECK(value->op()->ValueOutputCount() > 0);
142 143 144 145 146 147 148
    CHECK(IsDefUseChainLinkPresent(value, node));
    CHECK(IsUseDefChainLinkPresent(value, node));
  }

  // Verify all context inputs are value nodes.
  for (int i = 0; i < context_count; ++i) {
    Node* context = NodeProperties::GetContextInput(node);
149
    CHECK(context->op()->ValueOutputCount() > 0);
150 151 152 153 154 155 156
    CHECK(IsDefUseChainLinkPresent(context, node));
    CHECK(IsUseDefChainLinkPresent(context, node));
  }

  // Verify all effect inputs actually have an effect.
  for (int i = 0; i < effect_count; ++i) {
    Node* effect = NodeProperties::GetEffectInput(node);
157
    CHECK(effect->op()->EffectOutputCount() > 0);
158 159 160 161 162 163 164
    CHECK(IsDefUseChainLinkPresent(effect, node));
    CHECK(IsUseDefChainLinkPresent(effect, node));
  }

  // Verify all control inputs are control nodes.
  for (int i = 0; i < control_count; ++i) {
    Node* control = NodeProperties::GetControlInput(node, i);
165
    CHECK(control->op()->ControlOutputCount() > 0);
166 167 168 169 170
    CHECK(IsDefUseChainLinkPresent(control, node));
    CHECK(IsUseDefChainLinkPresent(control, node));
  }

  // Verify all successors are projections if multiple value outputs exist.
171
  if (node->op()->ValueOutputCount() > 1) {
danno's avatar
danno committed
172 173 174 175 176
    for (Edge edge : node->use_edges()) {
      Node* use = edge.from();
      CHECK(!NodeProperties::IsValueEdge(edge) ||
            use->opcode() == IrOpcode::kProjection ||
            use->opcode() == IrOpcode::kParameter);
177 178 179
    }
  }

180
  switch (node->opcode()) {
181 182 183 184 185 186 187 188 189 190
    case IrOpcode::kAlways:
      // Always has no inputs.
      CHECK_EQ(0, input_count);
      // Always uses are Branch.
      for (auto use : node->uses()) {
        CHECK(use->opcode() == IrOpcode::kBranch);
      }
      // Type is boolean.
      CheckUpperIs(node, Type::Boolean());
      break;
191 192 193 194 195 196 197 198 199
    case IrOpcode::kStart:
      // Start has no inputs.
      CHECK_EQ(0, input_count);
      // Type is a tuple.
      // TODO(rossberg): Multiple outputs are currently typed as Internal.
      CheckUpperIs(node, Type::Internal());
      break;
    case IrOpcode::kEnd:
      // End has no outputs.
200 201 202
      CHECK(node->op()->ValueOutputCount() == 0);
      CHECK(node->op()->EffectOutputCount() == 0);
      CHECK(node->op()->ControlOutputCount() == 0);
203 204 205 206 207 208 209 210 211
      // Type is empty.
      CheckNotTyped(node);
      break;
    case IrOpcode::kDead:
      // Dead is never connected to the graph.
      UNREACHABLE();
    case IrOpcode::kBranch: {
      // Branch uses are IfTrue and IfFalse.
      int count_true = 0, count_false = 0;
212 213 214 215 216
      for (auto use : node->uses()) {
        CHECK(use->opcode() == IrOpcode::kIfTrue ||
              use->opcode() == IrOpcode::kIfFalse);
        if (use->opcode() == IrOpcode::kIfTrue) ++count_true;
        if (use->opcode() == IrOpcode::kIfFalse) ++count_false;
217
      }
218 219
      CHECK_EQ(1, count_true);
      CHECK_EQ(1, count_false);
220 221 222 223 224 225 226 227 228 229 230
      // Type is empty.
      CheckNotTyped(node);
      break;
    }
    case IrOpcode::kIfTrue:
    case IrOpcode::kIfFalse:
      CHECK_EQ(IrOpcode::kBranch,
               NodeProperties::GetControlInput(node, 0)->opcode());
      // Type is empty.
      CheckNotTyped(node);
      break;
231 232 233 234 235 236 237 238 239
    case IrOpcode::kIfSuccess:
    case IrOpcode::kIfException: {
      // IfSuccess and IfException continuation only on throwing nodes.
      Node* input = NodeProperties::GetControlInput(node, 0);
      CHECK(!input->op()->HasProperty(Operator::kNoThrow));
      // Type is empty.
      CheckNotTyped(node);
      break;
    }
240
    case IrOpcode::kSwitch: {
241 242
      // Switch uses are Case and Default.
      int count_case = 0, count_default = 0;
243
      for (auto use : node->uses()) {
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
        switch (use->opcode()) {
          case IrOpcode::kIfValue: {
            for (auto user : node->uses()) {
              if (user != use && user->opcode() == IrOpcode::kIfValue) {
                CHECK_NE(OpParameter<int32_t>(use->op()),
                         OpParameter<int32_t>(user->op()));
              }
            }
            ++count_case;
            break;
          }
          case IrOpcode::kIfDefault: {
            ++count_default;
            break;
          }
          default: {
            UNREACHABLE();
            break;
          }
        }
264
      }
265 266 267
      CHECK_LE(1, count_case);
      CHECK_EQ(1, count_default);
      CHECK_EQ(node->op()->ControlOutputCount(), count_case + count_default);
268 269 270 271
      // Type is empty.
      CheckNotTyped(node);
      break;
    }
272 273
    case IrOpcode::kIfValue:
    case IrOpcode::kIfDefault:
274 275 276 277 278
      CHECK_EQ(IrOpcode::kSwitch,
               NodeProperties::GetControlInput(node)->opcode());
      // Type is empty.
      CheckNotTyped(node);
      break;
279 280 281 282 283 284
    case IrOpcode::kLoop:
    case IrOpcode::kMerge:
      CHECK_EQ(control_count, input_count);
      // Type is empty.
      CheckNotTyped(node);
      break;
285 286 287 288
    case IrOpcode::kDeoptimize:
      // TODO(rossberg): check successor is End
      // Type is empty.
      CheckNotTyped(node);
289 290 291 292 293 294 295 296 297 298
    case IrOpcode::kReturn:
      // TODO(rossberg): check successor is End
      // Type is empty.
      CheckNotTyped(node);
      break;
    case IrOpcode::kThrow:
      // TODO(rossberg): what are the constraints on these?
      // Type is empty.
      CheckNotTyped(node);
      break;
299 300 301 302 303 304 305 306
    case IrOpcode::kOsrNormalEntry:
    case IrOpcode::kOsrLoopEntry:
      // Osr entries have
      CHECK_EQ(1, effect_count);
      CHECK_EQ(1, control_count);
      // Type is empty.
      CheckNotTyped(node);
      break;
307 308 309 310 311 312 313 314 315 316 317 318

    // Common operators
    // ----------------
    case IrOpcode::kParameter: {
      // Parameters have the start node as inputs.
      CHECK_EQ(1, input_count);
      CHECK_EQ(IrOpcode::kStart,
               NodeProperties::GetValueInput(node, 0)->opcode());
      // Parameter has an input that produces enough values.
      int index = OpParameter<int>(node);
      Node* input = NodeProperties::GetValueInput(node, 0);
      // Currently, parameter indices start at -1 instead of 0.
319
      CHECK_GT(input->op()->ValueOutputCount(), index + 1);
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
      // Type can be anything.
      CheckUpperIs(node, Type::Any());
      break;
    }
    case IrOpcode::kInt32Constant:  // TODO(rossberg): rename Word32Constant?
      // Constants have no inputs.
      CHECK_EQ(0, input_count);
      // Type is a 32 bit integer, signed or unsigned.
      CheckUpperIs(node, Type::Integral32());
      break;
    case IrOpcode::kInt64Constant:
      // Constants have no inputs.
      CHECK_EQ(0, input_count);
      // Type is internal.
      // TODO(rossberg): Introduce proper Int64 type.
      CheckUpperIs(node, Type::Internal());
      break;
    case IrOpcode::kFloat32Constant:
    case IrOpcode::kFloat64Constant:
    case IrOpcode::kNumberConstant:
      // Constants have no inputs.
      CHECK_EQ(0, input_count);
      // Type is a number.
      CheckUpperIs(node, Type::Number());
      break;
    case IrOpcode::kHeapConstant:
      // Constants have no inputs.
      CHECK_EQ(0, input_count);
      // Type can be anything represented as a heap pointer.
349
      CheckUpperIs(node, Type::TaggedPointer());
350 351 352 353 354 355 356
      break;
    case IrOpcode::kExternalConstant:
      // Constants have no inputs.
      CHECK_EQ(0, input_count);
      // Type is considered internal.
      CheckUpperIs(node, Type::Internal());
      break;
357 358 359 360 361 362 363
    case IrOpcode::kOsrValue:
      // OSR values have a value and a control input.
      CHECK_EQ(1, control_count);
      CHECK_EQ(1, input_count);
      // Type is merged from other values in the graph and could be any.
      CheckUpperIs(node, Type::Any());
      break;
364 365
    case IrOpcode::kProjection: {
      // Projection has an input that produces enough values.
366
      int index = static_cast<int>(ProjectionIndexOf(node->op()));
367
      Node* input = NodeProperties::GetValueInput(node, 0);
368
      CHECK_GT(input->op()->ValueOutputCount(), index);
369 370 371 372 373 374
      // Type can be anything.
      // TODO(rossberg): Introduce tuple types for this.
      // TODO(titzer): Convince rossberg not to.
      CheckUpperIs(node, Type::Any());
      break;
    }
375 376 377 378 379 380
    case IrOpcode::kSelect: {
      CHECK_EQ(0, effect_count);
      CHECK_EQ(0, control_count);
      CHECK_EQ(3, value_count);
      break;
    }
381 382 383 384 385
    case IrOpcode::kPhi: {
      // Phi input count matches parent control node.
      CHECK_EQ(0, effect_count);
      CHECK_EQ(1, control_count);
      Node* control = NodeProperties::GetControlInput(node, 0);
386
      CHECK_EQ(value_count, control->op()->ControlInputCount());
387 388 389 390 391 392 393 394
      CHECK_EQ(input_count, 1 + value_count);
      // Type must be subsumed by all input types.
      // TODO(rossberg): for now at least, narrowing does not really hold.
      /*
      for (int i = 0; i < value_count; ++i) {
        // TODO(rossberg, jarin): Figure out what to do about lower bounds.
        // CHECK(bounds(node).lower->Is(bounds(ValueInput(node, i)).lower));
        CHECK(bounds(ValueInput(node, i)).upper->Is(bounds(node).upper));
395
      }
396 397 398 399 400 401 402 403
      */
      break;
    }
    case IrOpcode::kEffectPhi: {
      // EffectPhi input count matches parent control node.
      CHECK_EQ(0, value_count);
      CHECK_EQ(1, control_count);
      Node* control = NodeProperties::GetControlInput(node, 0);
404
      CHECK_EQ(effect_count, control->op()->ControlInputCount());
405 406 407
      CHECK_EQ(input_count, 1 + effect_count);
      break;
    }
408 409 410 411 412 413
    case IrOpcode::kEffectSet: {
      CHECK_EQ(0, value_count);
      CHECK_EQ(0, control_count);
      CHECK_LT(1, effect_count);
      break;
    }
414 415 416 417 418 419 420 421 422
    case IrOpcode::kValueEffect:
      // TODO(rossberg): what are the constraints on these?
      break;
    case IrOpcode::kFinish: {
      // TODO(rossberg): what are the constraints on these?
      // Type must be subsumed by input type.
      if (typing == TYPED) {
        CHECK(bounds(ValueInput(node)).lower->Is(bounds(node).lower));
        CHECK(bounds(ValueInput(node)).upper->Is(bounds(node).upper));
423
      }
424 425 426 427 428 429
      break;
    }
    case IrOpcode::kFrameState:
      // TODO(jarin): what are the constraints on these?
      break;
    case IrOpcode::kStateValues:
430
    case IrOpcode::kTypedStateValues:
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
      // TODO(jarin): what are the constraints on these?
      break;
    case IrOpcode::kCall:
      // TODO(rossberg): what are the constraints on these?
      break;

    // JavaScript operators
    // --------------------
    case IrOpcode::kJSEqual:
    case IrOpcode::kJSNotEqual:
    case IrOpcode::kJSStrictEqual:
    case IrOpcode::kJSStrictNotEqual:
    case IrOpcode::kJSLessThan:
    case IrOpcode::kJSGreaterThan:
    case IrOpcode::kJSLessThanOrEqual:
    case IrOpcode::kJSGreaterThanOrEqual:
    case IrOpcode::kJSUnaryNot:
      // Type is Boolean.
      CheckUpperIs(node, Type::Boolean());
      break;

    case IrOpcode::kJSBitwiseOr:
    case IrOpcode::kJSBitwiseXor:
    case IrOpcode::kJSBitwiseAnd:
    case IrOpcode::kJSShiftLeft:
    case IrOpcode::kJSShiftRight:
    case IrOpcode::kJSShiftRightLogical:
      // Type is 32 bit integral.
      CheckUpperIs(node, Type::Integral32());
      break;
    case IrOpcode::kJSAdd:
      // Type is Number or String.
      CheckUpperIs(node, Type::NumberOrString());
      break;
    case IrOpcode::kJSSubtract:
    case IrOpcode::kJSMultiply:
    case IrOpcode::kJSDivide:
    case IrOpcode::kJSModulus:
      // Type is Number.
      CheckUpperIs(node, Type::Number());
      break;

    case IrOpcode::kJSToBoolean:
      // Type is Boolean.
      CheckUpperIs(node, Type::Boolean());
      break;
    case IrOpcode::kJSToNumber:
      // Type is Number.
      CheckUpperIs(node, Type::Number());
      break;
    case IrOpcode::kJSToString:
      // Type is String.
      CheckUpperIs(node, Type::String());
      break;
    case IrOpcode::kJSToName:
      // Type is Name.
      CheckUpperIs(node, Type::Name());
      break;
    case IrOpcode::kJSToObject:
      // Type is Receiver.
      CheckUpperIs(node, Type::Receiver());
      break;

    case IrOpcode::kJSCreate:
      // Type is Object.
      CheckUpperIs(node, Type::Object());
      break;
    case IrOpcode::kJSLoadProperty:
    case IrOpcode::kJSLoadNamed:
      // Type can be anything.
      CheckUpperIs(node, Type::Any());
      break;
    case IrOpcode::kJSStoreProperty:
    case IrOpcode::kJSStoreNamed:
      // Type is empty.
      CheckNotTyped(node);
      break;
    case IrOpcode::kJSDeleteProperty:
    case IrOpcode::kJSHasProperty:
    case IrOpcode::kJSInstanceOf:
      // Type is Boolean.
      CheckUpperIs(node, Type::Boolean());
      break;
    case IrOpcode::kJSTypeOf:
      // Type is String.
      CheckUpperIs(node, Type::String());
      break;

    case IrOpcode::kJSLoadContext:
      // Type can be anything.
      CheckUpperIs(node, Type::Any());
      break;
    case IrOpcode::kJSStoreContext:
      // Type is empty.
      CheckNotTyped(node);
      break;
    case IrOpcode::kJSCreateFunctionContext:
    case IrOpcode::kJSCreateCatchContext:
    case IrOpcode::kJSCreateWithContext:
    case IrOpcode::kJSCreateBlockContext:
    case IrOpcode::kJSCreateModuleContext:
532
    case IrOpcode::kJSCreateScriptContext: {
533 534 535 536 537 538 539 540
      // Type is Context, and operand is Internal.
      Node* context = NodeProperties::GetContextInput(node);
      // TODO(rossberg): This should really be Is(Internal), but the typer
      // currently can't do backwards propagation.
      CheckUpperMaybe(context, Type::Internal());
      if (typing == TYPED) CHECK(bounds(node).upper->IsContext());
      break;
    }
541

542 543 544 545 546 547 548 549 550 551 552
    case IrOpcode::kJSCallConstruct:
      // Type is Receiver.
      CheckUpperIs(node, Type::Receiver());
      break;
    case IrOpcode::kJSCallFunction:
    case IrOpcode::kJSCallRuntime:
    case IrOpcode::kJSYield:
      // Type can be anything.
      CheckUpperIs(node, Type::Any());
      break;

553 554 555 556 557
    case IrOpcode::kJSStackCheck:
      // Type is empty.
      CheckNotTyped(node);
      break;

558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
    // Simplified operators
    // -------------------------------
    case IrOpcode::kBooleanNot:
      // Boolean -> Boolean
      CheckValueInputIs(node, 0, Type::Boolean());
      CheckUpperIs(node, Type::Boolean());
      break;
    case IrOpcode::kBooleanToNumber:
      // Boolean -> Number
      CheckValueInputIs(node, 0, Type::Boolean());
      CheckUpperIs(node, Type::Number());
      break;
    case IrOpcode::kNumberEqual:
    case IrOpcode::kNumberLessThan:
    case IrOpcode::kNumberLessThanOrEqual:
      // (Number, Number) -> Boolean
      CheckValueInputIs(node, 0, Type::Number());
      CheckValueInputIs(node, 1, Type::Number());
      CheckUpperIs(node, Type::Boolean());
      break;
    case IrOpcode::kNumberAdd:
    case IrOpcode::kNumberSubtract:
    case IrOpcode::kNumberMultiply:
    case IrOpcode::kNumberDivide:
    case IrOpcode::kNumberModulus:
      // (Number, Number) -> Number
      CheckValueInputIs(node, 0, Type::Number());
      CheckValueInputIs(node, 1, Type::Number());
      // TODO(rossberg): activate once we retype after opcode changes.
      // CheckUpperIs(node, Type::Number());
      break;
    case IrOpcode::kNumberToInt32:
      // Number -> Signed32
      CheckValueInputIs(node, 0, Type::Number());
      CheckUpperIs(node, Type::Signed32());
      break;
    case IrOpcode::kNumberToUint32:
      // Number -> Unsigned32
      CheckValueInputIs(node, 0, Type::Number());
      CheckUpperIs(node, Type::Unsigned32());
      break;
599 600 601 602 603
    case IrOpcode::kPlainPrimitiveToNumber:
      // PlainPrimitive -> Number
      CheckValueInputIs(node, 0, Type::PlainPrimitive());
      CheckUpperIs(node, Type::Number());
      break;
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
    case IrOpcode::kStringEqual:
    case IrOpcode::kStringLessThan:
    case IrOpcode::kStringLessThanOrEqual:
      // (String, String) -> Boolean
      CheckValueInputIs(node, 0, Type::String());
      CheckValueInputIs(node, 1, Type::String());
      CheckUpperIs(node, Type::Boolean());
      break;
    case IrOpcode::kStringAdd:
      // (String, String) -> String
      CheckValueInputIs(node, 0, Type::String());
      CheckValueInputIs(node, 1, Type::String());
      CheckUpperIs(node, Type::String());
      break;
    case IrOpcode::kReferenceEqual: {
      // (Unique, Any) -> Boolean  and
      // (Any, Unique) -> Boolean
      if (typing == TYPED) {
        CHECK(bounds(ValueInput(node, 0)).upper->Is(Type::Unique()) ||
              bounds(ValueInput(node, 1)).upper->Is(Type::Unique()));
624
      }
625 626
      CheckUpperIs(node, Type::Boolean());
      break;
627
    }
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
    case IrOpcode::kObjectIsSmi:
      CheckValueInputIs(node, 0, Type::Any());
      CheckUpperIs(node, Type::Boolean());
      break;
    case IrOpcode::kObjectIsNonNegativeSmi:
      CheckValueInputIs(node, 0, Type::Any());
      CheckUpperIs(node, Type::Boolean());
      break;

    case IrOpcode::kChangeTaggedToInt32: {
      // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
      // TODO(neis): Activate once ChangeRepresentation works in typer.
      // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
      // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
      // CheckValueInputIs(node, 0, from));
      // CheckUpperIs(node, to));
      break;
    }
    case IrOpcode::kChangeTaggedToUint32: {
      // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32
      // TODO(neis): Activate once ChangeRepresentation works in typer.
      // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged());
      // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32());
      // CheckValueInputIs(node, 0, from));
      // CheckUpperIs(node, to));
      break;
    }
    case IrOpcode::kChangeTaggedToFloat64: {
      // Number /\ Tagged -> Number /\ UntaggedFloat64
      // TODO(neis): Activate once ChangeRepresentation works in typer.
      // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
      // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
      // CheckValueInputIs(node, 0, from));
      // CheckUpperIs(node, to));
      break;
    }
    case IrOpcode::kChangeInt32ToTagged: {
      // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged
      // TODO(neis): Activate once ChangeRepresentation works in typer.
      // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
      // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged());
      // CheckValueInputIs(node, 0, from));
      // CheckUpperIs(node, to));
      break;
    }
    case IrOpcode::kChangeUint32ToTagged: {
      // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged
      // TODO(neis): Activate once ChangeRepresentation works in typer.
      // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32());
      // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged());
      // CheckValueInputIs(node, 0, from));
      // CheckUpperIs(node, to));
      break;
    }
    case IrOpcode::kChangeFloat64ToTagged: {
      // Number /\ UntaggedFloat64 -> Number /\ Tagged
      // TODO(neis): Activate once ChangeRepresentation works in typer.
      // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64());
      // Type* to = Type::Intersect(Type::Number(), Type::Tagged());
      // CheckValueInputIs(node, 0, from));
      // CheckUpperIs(node, to));
      break;
    }
    case IrOpcode::kChangeBoolToBit: {
      // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
      // TODO(neis): Activate once ChangeRepresentation works in typer.
      // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
      // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
      // CheckValueInputIs(node, 0, from));
      // CheckUpperIs(node, to));
      break;
    }
700 701 702 703 704 705 706
    case IrOpcode::kChangeBitToBool: {
      // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
      // TODO(neis): Activate once ChangeRepresentation works in typer.
      // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
      // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
      // CheckValueInputIs(node, 0, from));
      // CheckUpperIs(node, to));
707 708 709 710 711 712 713 714 715
      break;
    }

    case IrOpcode::kLoadField:
      // Object -> fieldtype
      // TODO(rossberg): activate once machine ops are typed.
      // CheckValueInputIs(node, 0, Type::Object());
      // CheckUpperIs(node, Field(node).type));
      break;
716 717
    case IrOpcode::kLoadBuffer:
      break;
718 719 720 721 722 723 724 725 726 727 728 729 730
    case IrOpcode::kLoadElement:
      // Object -> elementtype
      // TODO(rossberg): activate once machine ops are typed.
      // CheckValueInputIs(node, 0, Type::Object());
      // CheckUpperIs(node, Element(node).type));
      break;
    case IrOpcode::kStoreField:
      // (Object, fieldtype) -> _|_
      // TODO(rossberg): activate once machine ops are typed.
      // CheckValueInputIs(node, 0, Type::Object());
      // CheckValueInputIs(node, 1, Field(node).type));
      CheckNotTyped(node);
      break;
731 732
    case IrOpcode::kStoreBuffer:
      break;
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
    case IrOpcode::kStoreElement:
      // (Object, elementtype) -> _|_
      // TODO(rossberg): activate once machine ops are typed.
      // CheckValueInputIs(node, 0, Type::Object());
      // CheckValueInputIs(node, 1, Element(node).type));
      CheckNotTyped(node);
      break;

    // Machine operators
    // -----------------------
    case IrOpcode::kLoad:
    case IrOpcode::kStore:
    case IrOpcode::kWord32And:
    case IrOpcode::kWord32Or:
    case IrOpcode::kWord32Xor:
    case IrOpcode::kWord32Shl:
    case IrOpcode::kWord32Shr:
    case IrOpcode::kWord32Sar:
    case IrOpcode::kWord32Ror:
    case IrOpcode::kWord32Equal:
753
    case IrOpcode::kWord32Clz:
754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
    case IrOpcode::kWord64And:
    case IrOpcode::kWord64Or:
    case IrOpcode::kWord64Xor:
    case IrOpcode::kWord64Shl:
    case IrOpcode::kWord64Shr:
    case IrOpcode::kWord64Sar:
    case IrOpcode::kWord64Ror:
    case IrOpcode::kWord64Equal:
    case IrOpcode::kInt32Add:
    case IrOpcode::kInt32AddWithOverflow:
    case IrOpcode::kInt32Sub:
    case IrOpcode::kInt32SubWithOverflow:
    case IrOpcode::kInt32Mul:
    case IrOpcode::kInt32MulHigh:
    case IrOpcode::kInt32Div:
    case IrOpcode::kInt32Mod:
    case IrOpcode::kInt32LessThan:
    case IrOpcode::kInt32LessThanOrEqual:
    case IrOpcode::kUint32Div:
    case IrOpcode::kUint32Mod:
774
    case IrOpcode::kUint32MulHigh:
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
    case IrOpcode::kUint32LessThan:
    case IrOpcode::kUint32LessThanOrEqual:
    case IrOpcode::kInt64Add:
    case IrOpcode::kInt64Sub:
    case IrOpcode::kInt64Mul:
    case IrOpcode::kInt64Div:
    case IrOpcode::kInt64Mod:
    case IrOpcode::kInt64LessThan:
    case IrOpcode::kInt64LessThanOrEqual:
    case IrOpcode::kUint64Div:
    case IrOpcode::kUint64Mod:
    case IrOpcode::kUint64LessThan:
    case IrOpcode::kFloat64Add:
    case IrOpcode::kFloat64Sub:
    case IrOpcode::kFloat64Mul:
    case IrOpcode::kFloat64Div:
    case IrOpcode::kFloat64Mod:
792 793
    case IrOpcode::kFloat64Max:
    case IrOpcode::kFloat64Min:
794
    case IrOpcode::kFloat64Sqrt:
795
    case IrOpcode::kFloat64RoundDown:
796 797
    case IrOpcode::kFloat64RoundTruncate:
    case IrOpcode::kFloat64RoundTiesAway:
798 799 800 801 802 803 804 805 806 807 808 809 810
    case IrOpcode::kFloat64Equal:
    case IrOpcode::kFloat64LessThan:
    case IrOpcode::kFloat64LessThanOrEqual:
    case IrOpcode::kTruncateInt64ToInt32:
    case IrOpcode::kTruncateFloat64ToFloat32:
    case IrOpcode::kTruncateFloat64ToInt32:
    case IrOpcode::kChangeInt32ToInt64:
    case IrOpcode::kChangeUint32ToUint64:
    case IrOpcode::kChangeInt32ToFloat64:
    case IrOpcode::kChangeUint32ToFloat64:
    case IrOpcode::kChangeFloat32ToFloat64:
    case IrOpcode::kChangeFloat64ToInt32:
    case IrOpcode::kChangeFloat64ToUint32:
811 812 813 814
    case IrOpcode::kFloat64ExtractLowWord32:
    case IrOpcode::kFloat64ExtractHighWord32:
    case IrOpcode::kFloat64InsertLowWord32:
    case IrOpcode::kFloat64InsertHighWord32:
815
    case IrOpcode::kLoadStackPointer:
816 817
    case IrOpcode::kCheckedLoad:
    case IrOpcode::kCheckedStore:
818 819
      // TODO(rossberg): Check.
      break;
820
  }
821
}  // NOLINT(readability/fn_size)
822 823


824
void Verifier::Run(Graph* graph, Typing typing) {
825 826
  CHECK_NOT_NULL(graph->start());
  CHECK_NOT_NULL(graph->end());
827 828
  Zone zone;
  Visitor visitor(&zone, typing);
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
  AllNodes all(&zone, graph);
  for (Node* node : all.live) visitor.Check(node);

  // Check the uniqueness of projections.
  for (Node* proj : all.live) {
    if (proj->opcode() != IrOpcode::kProjection) continue;
    Node* node = proj->InputAt(0);
    for (Node* other : node->uses()) {
      if (all.IsLive(other) && other != proj &&
          other->opcode() == IrOpcode::kProjection &&
          ProjectionIndexOf(other->op()) == ProjectionIndexOf(proj->op())) {
        V8_Fatal(__FILE__, __LINE__,
                 "Node #%d:%s has duplicate projections #%d and #%d",
                 node->id(), node->op()->mnemonic(), proj->id(), other->id());
      }
    }
  }
846
}
847 848


849 850
// -----------------------------------------------------------------------------

851 852 853 854 855 856
static bool HasDominatingDef(Schedule* schedule, Node* node,
                             BasicBlock* container, BasicBlock* use_block,
                             int use_pos) {
  BasicBlock* block = use_block;
  while (true) {
    while (use_pos >= 0) {
857
      if (block->NodeAt(use_pos) == node) return true;
858 859
      use_pos--;
    }
860
    block = block->dominator();
861
    if (block == NULL) break;
862 863
    use_pos = static_cast<int>(block->NodeCount()) - 1;
    if (node == block->control_input()) return true;
864 865 866 867 868
  }
  return false;
}


869 870 871 872 873 874 875 876 877 878 879 880 881
static bool Dominates(Schedule* schedule, Node* dominator, Node* dominatee) {
  BasicBlock* dom = schedule->block(dominator);
  BasicBlock* sub = schedule->block(dominatee);
  while (sub != NULL) {
    if (sub == dom) {
      return true;
    }
    sub = sub->dominator();
  }
  return false;
}


882 883
static void CheckInputsDominate(Schedule* schedule, BasicBlock* block,
                                Node* node, int use_pos) {
884
  for (int j = node->op()->ValueInputCount() - 1; j >= 0; j--) {
885 886 887
    BasicBlock* use_block = block;
    if (node->opcode() == IrOpcode::kPhi) {
      use_block = use_block->PredecessorAt(j);
888
      use_pos = static_cast<int>(use_block->NodeCount()) - 1;
889 890 891 892 893 894
    }
    Node* input = node->InputAt(j);
    if (!HasDominatingDef(schedule, node->InputAt(j), block, use_block,
                          use_pos)) {
      V8_Fatal(__FILE__, __LINE__,
               "Node #%d:%s in B%d is not dominated by input@%d #%d:%s",
895
               node->id(), node->op()->mnemonic(), block->rpo_number(), j,
896
               input->id(), input->op()->mnemonic());
897
    }
898 899 900 901
  }
  // Ensure that nodes are dominated by their control inputs;
  // kEnd is an exception, as unreachable blocks resulting from kMerge
  // are not in the RPO.
902
  if (node->op()->ControlInputCount() == 1 &&
903 904 905 906 907
      node->opcode() != IrOpcode::kEnd) {
    Node* ctl = NodeProperties::GetControlInput(node);
    if (!Dominates(schedule, ctl, node)) {
      V8_Fatal(__FILE__, __LINE__,
               "Node #%d:%s in B%d is not dominated by control input #%d:%s",
908 909
               node->id(), node->op()->mnemonic(), block->rpo_number(),
               ctl->id(), ctl->op()->mnemonic());
910
    }
911 912 913 914 915
  }
}


void ScheduleVerifier::Run(Schedule* schedule) {
916
  const size_t count = schedule->BasicBlockCount();
917
  Zone tmp_zone;
918 919 920 921 922
  Zone* zone = &tmp_zone;
  BasicBlock* start = schedule->start();
  BasicBlockVector* rpo_order = schedule->rpo_order();

  // Verify the RPO order contains only blocks from this schedule.
923
  CHECK_GE(count, rpo_order->size());
924 925 926
  for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
       ++b) {
    CHECK_EQ((*b), schedule->GetBlockById((*b)->id()));
927
    // All predecessors and successors should be in rpo and in this schedule.
928 929 930
    for (BasicBlock const* predecessor : (*b)->predecessors()) {
      CHECK_GE(predecessor->rpo_number(), 0);
      CHECK_EQ(predecessor, schedule->GetBlockById(predecessor->id()));
931
    }
932 933 934
    for (BasicBlock const* successor : (*b)->successors()) {
      CHECK_GE(successor->rpo_number(), 0);
      CHECK_EQ(successor, schedule->GetBlockById(successor->id()));
935
    }
936 937 938 939 940 941
  }

  // Verify RPO numbers of blocks.
  CHECK_EQ(start, rpo_order->at(0));  // Start should be first.
  for (size_t b = 0; b < rpo_order->size(); b++) {
    BasicBlock* block = rpo_order->at(b);
942 943
    CHECK_EQ(static_cast<int>(b), block->rpo_number());
    BasicBlock* dom = block->dominator();
944 945
    if (b == 0) {
      // All blocks except start should have a dominator.
946
      CHECK_NULL(dom);
947 948
    } else {
      // Check that the immediate dominator appears somewhere before the block.
949
      CHECK_NOT_NULL(dom);
950
      CHECK_LT(dom->rpo_number(), block->rpo_number());
951 952 953 954
    }
  }

  // Verify that all blocks reachable from start are in the RPO.
955
  BoolVector marked(static_cast<int>(count), false, zone);
956
  {
957
    ZoneQueue<BasicBlock*> queue(zone);
958
    queue.push(start);
959
    marked[start->id().ToSize()] = true;
960 961 962
    while (!queue.empty()) {
      BasicBlock* block = queue.front();
      queue.pop();
963
      for (size_t s = 0; s < block->SuccessorCount(); s++) {
964
        BasicBlock* succ = block->SuccessorAt(s);
965 966
        if (!marked[succ->id().ToSize()]) {
          marked[succ->id().ToSize()] = true;
967 968 969 970 971 972
          queue.push(succ);
        }
      }
    }
  }
  // Verify marked blocks are in the RPO.
973 974
  for (size_t i = 0; i < count; i++) {
    BasicBlock* block = schedule->GetBlockById(BasicBlock::Id::FromSize(i));
975
    if (marked[i]) {
976 977
      CHECK_GE(block->rpo_number(), 0);
      CHECK_EQ(block, rpo_order->at(block->rpo_number()));
978 979 980 981
    }
  }
  // Verify RPO blocks are marked.
  for (size_t b = 0; b < rpo_order->size(); b++) {
982
    CHECK(marked[rpo_order->at(b)->id().ToSize()]);
983 984 985 986
  }

  {
    // Verify the dominance relation.
987 988
    ZoneVector<BitVector*> dominators(zone);
    dominators.resize(count, NULL);
989 990 991

    // Compute a set of all the nodes that dominate a given node by using
    // a forward fixpoint. O(n^2).
992
    ZoneQueue<BasicBlock*> queue(zone);
993
    queue.push(start);
994 995
    dominators[start->id().ToSize()] =
        new (zone) BitVector(static_cast<int>(count), zone);
996 997 998
    while (!queue.empty()) {
      BasicBlock* block = queue.front();
      queue.pop();
999 1000 1001
      BitVector* block_doms = dominators[block->id().ToSize()];
      BasicBlock* idom = block->dominator();
      if (idom != NULL && !block_doms->Contains(idom->id().ToInt())) {
1002
        V8_Fatal(__FILE__, __LINE__, "Block B%d is not dominated by B%d",
1003
                 block->rpo_number(), idom->rpo_number());
1004
      }
1005
      for (size_t s = 0; s < block->SuccessorCount(); s++) {
1006
        BasicBlock* succ = block->SuccessorAt(s);
1007
        BitVector* succ_doms = dominators[succ->id().ToSize()];
1008 1009

        if (succ_doms == NULL) {
1010
          // First time visiting the node. S.doms = B U B.doms
1011
          succ_doms = new (zone) BitVector(static_cast<int>(count), zone);
1012
          succ_doms->CopyFrom(*block_doms);
1013 1014
          succ_doms->Add(block->id().ToInt());
          dominators[succ->id().ToSize()] = succ_doms;
1015 1016
          queue.push(succ);
        } else {
1017
          // Nth time visiting the successor. S.doms = S.doms ^ (B U B.doms)
1018 1019
          bool had = succ_doms->Contains(block->id().ToInt());
          if (had) succ_doms->Remove(block->id().ToInt());
1020
          if (succ_doms->IntersectIsChanged(*block_doms)) queue.push(succ);
1021
          if (had) succ_doms->Add(block->id().ToInt());
1022 1023 1024 1025 1026 1027 1028 1029
        }
      }
    }

    // Verify the immediateness of dominators.
    for (BasicBlockVector::iterator b = rpo_order->begin();
         b != rpo_order->end(); ++b) {
      BasicBlock* block = *b;
1030
      BasicBlock* idom = block->dominator();
1031
      if (idom == NULL) continue;
1032
      BitVector* block_doms = dominators[block->id().ToSize()];
1033 1034

      for (BitVector::Iterator it(block_doms); !it.Done(); it.Advance()) {
1035 1036 1037 1038
        BasicBlock* dom =
            schedule->GetBlockById(BasicBlock::Id::FromInt(it.Current()));
        if (dom != idom &&
            !dominators[idom->id().ToSize()]->Contains(dom->id().ToInt())) {
1039
          V8_Fatal(__FILE__, __LINE__,
1040
                   "Block B%d is not immediately dominated by B%d",
1041
                   block->rpo_number(), idom->rpo_number());
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
        }
      }
    }
  }

  // Verify phis are placed in the block of their control input.
  for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
       ++b) {
    for (BasicBlock::const_iterator i = (*b)->begin(); i != (*b)->end(); ++i) {
      Node* phi = *i;
      if (phi->opcode() != IrOpcode::kPhi) continue;
      // TODO(titzer): Nasty special case. Phis from RawMachineAssembler
      // schedules don't have control inputs.
1055
      if (phi->InputCount() > phi->op()->ValueInputCount()) {
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
        Node* control = NodeProperties::GetControlInput(phi);
        CHECK(control->opcode() == IrOpcode::kMerge ||
              control->opcode() == IrOpcode::kLoop);
        CHECK_EQ((*b), schedule->block(control));
      }
    }
  }

  // Verify that all uses are dominated by their definitions.
  for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
       ++b) {
    BasicBlock* block = *b;

    // Check inputs to control for this block.
1070
    Node* control = block->control_input();
1071 1072 1073
    if (control != NULL) {
      CHECK_EQ(block, schedule->block(control));
      CheckInputsDominate(schedule, block, control,
1074
                          static_cast<int>(block->NodeCount()) - 1);
1075 1076
    }
    // Check inputs for all nodes in the block.
1077 1078
    for (size_t i = 0; i < block->NodeCount(); i++) {
      Node* node = block->NodeAt(i);
1079 1080 1081 1082
      CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1);
    }
  }
}
1083 1084 1085
}
}
}  // namespace v8::internal::compiler