Cleanups to Verifier.

This CL broadens the checks done by the verifier in untyped mode and introduces some subroutines to shorten the code a bit.

Introduce routines CheckUpperIs() CheckUpperMaybe() and CheckValueInputIs() that are called unconditionally by the verifier. If the typing mode is untyped, then don't check anything.

Also added a couple checks for Merge and Loop nodes that catch bugs where the operator and the node disagree on input counts (a bug encountered today).

R=mstarzinger@chromium.org, rossberg@chromium.org
BUG=

Review URL: https://codereview.chromium.org/669073002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24809 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
titzer@chromium.org 2014-10-22 14:39:41 +00:00
parent db000e307a
commit f843327ea0

View File

@ -6,6 +6,8 @@
#include <deque> #include <deque>
#include <queue> #include <queue>
#include <sstream>
#include <string>
#include "src/compiler/generic-algorithm.h" #include "src/compiler/generic-algorithm.h"
#include "src/compiler/generic-node-inl.h" #include "src/compiler/generic-node-inl.h"
@ -20,6 +22,7 @@
#include "src/compiler/schedule.h" #include "src/compiler/schedule.h"
#include "src/compiler/simplified-operator.h" #include "src/compiler/simplified-operator.h"
#include "src/data-flow.h" #include "src/data-flow.h"
#include "src/ostreams.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -56,10 +59,8 @@ class Verifier::Visitor : public NullNodeVisitor {
private: private:
// TODO(rossberg): Get rid of these once we got rid of NodeProperties. // TODO(rossberg): Get rid of these once we got rid of NodeProperties.
Bounds bounds(Node* node) { Bounds bounds(Node* node) { return NodeProperties::GetBounds(node); }
return NodeProperties::GetBounds(node); Node* ValueInput(Node* node, int i = 0) {
}
Node* Operand(Node* node, int i = 0) {
return NodeProperties::GetValueInput(node, i); return NodeProperties::GetValueInput(node, i);
} }
FieldAccess Field(Node* node) { FieldAccess Field(Node* node) {
@ -72,6 +73,50 @@ class Verifier::Visitor : public NullNodeVisitor {
node->opcode() == IrOpcode::kStoreElement); node->opcode() == IrOpcode::kStoreElement);
return OpParameter<ElementAccess>(node); return OpParameter<ElementAccess>(node);
} }
void CheckNotTyped(Node* node) {
if (NodeProperties::IsTyped(node)) {
std::ostringstream str;
str << "TypeError: node #" << node->opcode() << ":"
<< node->op()->mnemonic() << " should never have a type";
V8_Fatal(__FILE__, __LINE__, str.str().c_str());
}
}
void CheckUpperIs(Node* node, Type* type) {
if (typing == TYPED && !bounds(node).upper->Is(type)) {
std::ostringstream str;
str << "TypeError: node #" << node->opcode() << ":"
<< node->op()->mnemonic() << " upper bound ";
bounds(node).upper->PrintTo(str);
str << " is not ";
type->PrintTo(str);
V8_Fatal(__FILE__, __LINE__, str.str().c_str());
}
}
void CheckUpperMaybe(Node* node, Type* type) {
if (typing == TYPED && !bounds(node).upper->Maybe(type)) {
std::ostringstream str;
str << "TypeError: node #" << node->opcode() << ":"
<< node->op()->mnemonic() << " upper bound ";
bounds(node).upper->PrintTo(str);
str << " must intersect ";
type->PrintTo(str);
V8_Fatal(__FILE__, __LINE__, str.str().c_str());
}
}
void CheckValueInputIs(Node* node, int i, Type* type) {
Node* input = ValueInput(node, i);
if (typing == TYPED && !bounds(input).upper->Is(type)) {
std::ostringstream str;
str << "TypeError: node #" << node->opcode() << ":"
<< node->op()->mnemonic() << "(input @" << i << " = "
<< input->opcode() << ":" << input->op()->mnemonic()
<< ") upper bound ";
bounds(input).upper->PrintTo(str);
str << " is not ";
type->PrintTo(str);
V8_Fatal(__FILE__, __LINE__, str.str().c_str());
}
}
}; };
@ -141,16 +186,13 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
} }
} }
if (typing == TYPED) {
switch (node->opcode()) { switch (node->opcode()) {
// Control operators
// -----------------
case IrOpcode::kStart: case IrOpcode::kStart:
// Start has no inputs. // Start has no inputs.
CHECK_EQ(0, input_count); CHECK_EQ(0, input_count);
// Type is a tuple. // Type is a tuple.
// TODO(rossberg): Multiple outputs are currently typed as Internal. // TODO(rossberg): Multiple outputs are currently typed as Internal.
CHECK(bounds(node).upper->Is(Type::Internal())); CheckUpperIs(node, Type::Internal());
break; break;
case IrOpcode::kEnd: case IrOpcode::kEnd:
// End has no outputs. // End has no outputs.
@ -158,7 +200,7 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
CHECK(!OperatorProperties::HasEffectOutput(node->op())); CHECK(!OperatorProperties::HasEffectOutput(node->op()));
CHECK(!OperatorProperties::HasControlOutput(node->op())); CHECK(!OperatorProperties::HasControlOutput(node->op()));
// Type is empty. // Type is empty.
CHECK(!NodeProperties::IsTyped(node)); CheckNotTyped(node);
break; break;
case IrOpcode::kDead: case IrOpcode::kDead:
// Dead is never connected to the graph. // Dead is never connected to the graph.
@ -175,7 +217,7 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
} }
CHECK(count_true == 1 && count_false == 1); CHECK(count_true == 1 && count_false == 1);
// Type is empty. // Type is empty.
CHECK(!NodeProperties::IsTyped(node)); CheckNotTyped(node);
break; break;
} }
case IrOpcode::kIfTrue: case IrOpcode::kIfTrue:
@ -183,22 +225,23 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
CHECK_EQ(IrOpcode::kBranch, CHECK_EQ(IrOpcode::kBranch,
NodeProperties::GetControlInput(node, 0)->opcode()); NodeProperties::GetControlInput(node, 0)->opcode());
// Type is empty. // Type is empty.
CHECK(!NodeProperties::IsTyped(node)); CheckNotTyped(node);
break; break;
case IrOpcode::kLoop: case IrOpcode::kLoop:
case IrOpcode::kMerge: case IrOpcode::kMerge:
CHECK_EQ(control_count, input_count);
// Type is empty. // Type is empty.
CHECK(!NodeProperties::IsTyped(node)); CheckNotTyped(node);
break; break;
case IrOpcode::kReturn: case IrOpcode::kReturn:
// TODO(rossberg): check successor is End // TODO(rossberg): check successor is End
// Type is empty. // Type is empty.
CHECK(!NodeProperties::IsTyped(node)); CheckNotTyped(node);
break; break;
case IrOpcode::kThrow: case IrOpcode::kThrow:
// TODO(rossberg): what are the constraints on these? // TODO(rossberg): what are the constraints on these?
// Type is empty. // Type is empty.
CHECK(!NodeProperties::IsTyped(node)); CheckNotTyped(node);
break; break;
// Common operators // Common operators
@ -212,24 +255,23 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
int index = OpParameter<int>(node); int index = OpParameter<int>(node);
Node* input = NodeProperties::GetValueInput(node, 0); Node* input = NodeProperties::GetValueInput(node, 0);
// Currently, parameter indices start at -1 instead of 0. // Currently, parameter indices start at -1 instead of 0.
CHECK_GT( CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index + 1);
OperatorProperties::GetValueOutputCount(input->op()), index + 1);
// Type can be anything. // Type can be anything.
CHECK(bounds(node).upper->Is(Type::Any())); CheckUpperIs(node, Type::Any());
break; break;
} }
case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant? case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant?
// Constants have no inputs. // Constants have no inputs.
CHECK_EQ(0, input_count); CHECK_EQ(0, input_count);
// Type is a 32 bit integer, signed or unsigned. // Type is a 32 bit integer, signed or unsigned.
CHECK(bounds(node).upper->Is(Type::Integral32())); CheckUpperIs(node, Type::Integral32());
break; break;
case IrOpcode::kInt64Constant: case IrOpcode::kInt64Constant:
// Constants have no inputs. // Constants have no inputs.
CHECK_EQ(0, input_count); CHECK_EQ(0, input_count);
// Type is internal. // Type is internal.
// TODO(rossberg): Introduce proper Int64 type. // TODO(rossberg): Introduce proper Int64 type.
CHECK(bounds(node).upper->Is(Type::Internal())); CheckUpperIs(node, Type::Internal());
break; break;
case IrOpcode::kFloat32Constant: case IrOpcode::kFloat32Constant:
case IrOpcode::kFloat64Constant: case IrOpcode::kFloat64Constant:
@ -237,19 +279,19 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// Constants have no inputs. // Constants have no inputs.
CHECK_EQ(0, input_count); CHECK_EQ(0, input_count);
// Type is a number. // Type is a number.
CHECK(bounds(node).upper->Is(Type::Number())); CheckUpperIs(node, Type::Number());
break; break;
case IrOpcode::kHeapConstant: case IrOpcode::kHeapConstant:
// Constants have no inputs. // Constants have no inputs.
CHECK_EQ(0, input_count); CHECK_EQ(0, input_count);
// Type can be anything represented as a heap pointer. // Type can be anything represented as a heap pointer.
CHECK(bounds(node).upper->Is(Type::TaggedPtr())); CheckUpperIs(node, Type::TaggedPtr());
break; break;
case IrOpcode::kExternalConstant: case IrOpcode::kExternalConstant:
// Constants have no inputs. // Constants have no inputs.
CHECK_EQ(0, input_count); CHECK_EQ(0, input_count);
// Type is considered internal. // Type is considered internal.
CHECK(bounds(node).upper->Is(Type::Internal())); CheckUpperIs(node, Type::Internal());
break; break;
case IrOpcode::kProjection: { case IrOpcode::kProjection: {
// Projection has an input that produces enough values. // Projection has an input that produces enough values.
@ -258,32 +300,37 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index); CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index);
// Type can be anything. // Type can be anything.
// TODO(rossberg): Introduce tuple types for this. // TODO(rossberg): Introduce tuple types for this.
CHECK(bounds(node).upper->Is(Type::Any())); // TODO(titzer): Convince rossberg not to.
CheckUpperIs(node, Type::Any());
break; break;
} }
case IrOpcode::kPhi: { case IrOpcode::kPhi: {
// Phi input count matches parent control node. // Phi input count matches parent control node.
CHECK_EQ(0, effect_count);
CHECK_EQ(1, control_count); CHECK_EQ(1, control_count);
Node* control = NodeProperties::GetControlInput(node, 0); Node* control = NodeProperties::GetControlInput(node, 0);
CHECK_EQ(value_count, CHECK_EQ(value_count,
OperatorProperties::GetControlInputCount(control->op())); OperatorProperties::GetControlInputCount(control->op()));
CHECK_EQ(input_count, 1 + value_count);
// Type must be subsumed by all input types. // Type must be subsumed by all input types.
// TODO(rossberg): for now at least, narrowing does not really hold. // TODO(rossberg): for now at least, narrowing does not really hold.
/* /*
for (int i = 0; i < value_count; ++i) { for (int i = 0; i < value_count; ++i) {
// TODO(rossberg, jarin): Figure out what to do about lower bounds. // TODO(rossberg, jarin): Figure out what to do about lower bounds.
// CHECK(bounds(node).lower->Is(bounds(Operand(node, i)).lower)); // CHECK(bounds(node).lower->Is(bounds(ValueInput(node, i)).lower));
CHECK(bounds(Operand(node, i)).upper->Is(bounds(node).upper)); CHECK(bounds(ValueInput(node, i)).upper->Is(bounds(node).upper));
} }
*/ */
break; break;
} }
case IrOpcode::kEffectPhi: { case IrOpcode::kEffectPhi: {
// EffectPhi input count matches parent control node. // EffectPhi input count matches parent control node.
CHECK_EQ(0, value_count);
CHECK_EQ(1, control_count); CHECK_EQ(1, control_count);
Node* control = NodeProperties::GetControlInput(node, 0); Node* control = NodeProperties::GetControlInput(node, 0);
CHECK_EQ(effect_count, CHECK_EQ(effect_count,
OperatorProperties::GetControlInputCount(control->op())); OperatorProperties::GetControlInputCount(control->op()));
CHECK_EQ(input_count, 1 + effect_count);
break; break;
} }
case IrOpcode::kValueEffect: case IrOpcode::kValueEffect:
@ -292,8 +339,10 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
case IrOpcode::kFinish: { case IrOpcode::kFinish: {
// TODO(rossberg): what are the constraints on these? // TODO(rossberg): what are the constraints on these?
// Type must be subsumed by input type. // Type must be subsumed by input type.
CHECK(bounds(Operand(node)).lower->Is(bounds(node).lower)); if (typing == TYPED) {
CHECK(bounds(Operand(node)).upper->Is(bounds(node).upper)); CHECK(bounds(ValueInput(node)).lower->Is(bounds(node).lower));
CHECK(bounds(ValueInput(node)).upper->Is(bounds(node).upper));
}
break; break;
} }
case IrOpcode::kFrameState: case IrOpcode::kFrameState:
@ -318,7 +367,7 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
case IrOpcode::kJSGreaterThanOrEqual: case IrOpcode::kJSGreaterThanOrEqual:
case IrOpcode::kJSUnaryNot: case IrOpcode::kJSUnaryNot:
// Type is Boolean. // Type is Boolean.
CHECK(bounds(node).upper->Is(Type::Boolean())); CheckUpperIs(node, Type::Boolean());
break; break;
case IrOpcode::kJSBitwiseOr: case IrOpcode::kJSBitwiseOr:
@ -328,73 +377,73 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
case IrOpcode::kJSShiftRight: case IrOpcode::kJSShiftRight:
case IrOpcode::kJSShiftRightLogical: case IrOpcode::kJSShiftRightLogical:
// Type is 32 bit integral. // Type is 32 bit integral.
CHECK(bounds(node).upper->Is(Type::Integral32())); CheckUpperIs(node, Type::Integral32());
break; break;
case IrOpcode::kJSAdd: case IrOpcode::kJSAdd:
// Type is Number or String. // Type is Number or String.
CHECK(bounds(node).upper->Is(Type::NumberOrString())); CheckUpperIs(node, Type::NumberOrString());
break; break;
case IrOpcode::kJSSubtract: case IrOpcode::kJSSubtract:
case IrOpcode::kJSMultiply: case IrOpcode::kJSMultiply:
case IrOpcode::kJSDivide: case IrOpcode::kJSDivide:
case IrOpcode::kJSModulus: case IrOpcode::kJSModulus:
// Type is Number. // Type is Number.
CHECK(bounds(node).upper->Is(Type::Number())); CheckUpperIs(node, Type::Number());
break; break;
case IrOpcode::kJSToBoolean: case IrOpcode::kJSToBoolean:
// Type is Boolean. // Type is Boolean.
CHECK(bounds(node).upper->Is(Type::Boolean())); CheckUpperIs(node, Type::Boolean());
break; break;
case IrOpcode::kJSToNumber: case IrOpcode::kJSToNumber:
// Type is Number. // Type is Number.
CHECK(bounds(node).upper->Is(Type::Number())); CheckUpperIs(node, Type::Number());
break; break;
case IrOpcode::kJSToString: case IrOpcode::kJSToString:
// Type is String. // Type is String.
CHECK(bounds(node).upper->Is(Type::String())); CheckUpperIs(node, Type::String());
break; break;
case IrOpcode::kJSToName: case IrOpcode::kJSToName:
// Type is Name. // Type is Name.
CHECK(bounds(node).upper->Is(Type::Name())); CheckUpperIs(node, Type::Name());
break; break;
case IrOpcode::kJSToObject: case IrOpcode::kJSToObject:
// Type is Receiver. // Type is Receiver.
CHECK(bounds(node).upper->Is(Type::Receiver())); CheckUpperIs(node, Type::Receiver());
break; break;
case IrOpcode::kJSCreate: case IrOpcode::kJSCreate:
// Type is Object. // Type is Object.
CHECK(bounds(node).upper->Is(Type::Object())); CheckUpperIs(node, Type::Object());
break; break;
case IrOpcode::kJSLoadProperty: case IrOpcode::kJSLoadProperty:
case IrOpcode::kJSLoadNamed: case IrOpcode::kJSLoadNamed:
// Type can be anything. // Type can be anything.
CHECK(bounds(node).upper->Is(Type::Any())); CheckUpperIs(node, Type::Any());
break; break;
case IrOpcode::kJSStoreProperty: case IrOpcode::kJSStoreProperty:
case IrOpcode::kJSStoreNamed: case IrOpcode::kJSStoreNamed:
// Type is empty. // Type is empty.
CHECK(!NodeProperties::IsTyped(node)); CheckNotTyped(node);
break; break;
case IrOpcode::kJSDeleteProperty: case IrOpcode::kJSDeleteProperty:
case IrOpcode::kJSHasProperty: case IrOpcode::kJSHasProperty:
case IrOpcode::kJSInstanceOf: case IrOpcode::kJSInstanceOf:
// Type is Boolean. // Type is Boolean.
CHECK(bounds(node).upper->Is(Type::Boolean())); CheckUpperIs(node, Type::Boolean());
break; break;
case IrOpcode::kJSTypeOf: case IrOpcode::kJSTypeOf:
// Type is String. // Type is String.
CHECK(bounds(node).upper->Is(Type::String())); CheckUpperIs(node, Type::String());
break; break;
case IrOpcode::kJSLoadContext: case IrOpcode::kJSLoadContext:
// Type can be anything. // Type can be anything.
CHECK(bounds(node).upper->Is(Type::Any())); CheckUpperIs(node, Type::Any());
break; break;
case IrOpcode::kJSStoreContext: case IrOpcode::kJSStoreContext:
// Type is empty. // Type is empty.
CHECK(!NodeProperties::IsTyped(node)); CheckNotTyped(node);
break; break;
case IrOpcode::kJSCreateFunctionContext: case IrOpcode::kJSCreateFunctionContext:
case IrOpcode::kJSCreateCatchContext: case IrOpcode::kJSCreateCatchContext:
@ -403,45 +452,45 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
case IrOpcode::kJSCreateModuleContext: case IrOpcode::kJSCreateModuleContext:
case IrOpcode::kJSCreateGlobalContext: { case IrOpcode::kJSCreateGlobalContext: {
// Type is Context, and operand is Internal. // Type is Context, and operand is Internal.
Bounds outer = bounds(NodeProperties::GetContextInput(node)); Node* context = NodeProperties::GetContextInput(node);
// TODO(rossberg): This should really be Is(Internal), but the typer // TODO(rossberg): This should really be Is(Internal), but the typer
// currently can't do backwards propagation. // currently can't do backwards propagation.
CHECK(outer.upper->Maybe(Type::Internal())); CheckUpperMaybe(context, Type::Internal());
CHECK(bounds(node).upper->IsContext()); if (typing == TYPED) CHECK(bounds(node).upper->IsContext());
break; break;
} }
case IrOpcode::kJSCallConstruct: case IrOpcode::kJSCallConstruct:
// Type is Receiver. // Type is Receiver.
CHECK(bounds(node).upper->Is(Type::Receiver())); CheckUpperIs(node, Type::Receiver());
break; break;
case IrOpcode::kJSCallFunction: case IrOpcode::kJSCallFunction:
case IrOpcode::kJSCallRuntime: case IrOpcode::kJSCallRuntime:
case IrOpcode::kJSYield: case IrOpcode::kJSYield:
case IrOpcode::kJSDebugger: case IrOpcode::kJSDebugger:
// Type can be anything. // Type can be anything.
CHECK(bounds(node).upper->Is(Type::Any())); CheckUpperIs(node, Type::Any());
break; break;
// Simplified operators // Simplified operators
// ------------------------------- // -------------------------------
case IrOpcode::kBooleanNot: case IrOpcode::kBooleanNot:
// Boolean -> Boolean // Boolean -> Boolean
CHECK(bounds(Operand(node)).upper->Is(Type::Boolean())); CheckValueInputIs(node, 0, Type::Boolean());
CHECK(bounds(node).upper->Is(Type::Boolean())); CheckUpperIs(node, Type::Boolean());
break; break;
case IrOpcode::kBooleanToNumber: case IrOpcode::kBooleanToNumber:
// Boolean -> Number // Boolean -> Number
CHECK(bounds(Operand(node)).upper->Is(Type::Boolean())); CheckValueInputIs(node, 0, Type::Boolean());
CHECK(bounds(node).upper->Is(Type::Number())); CheckUpperIs(node, Type::Number());
break; break;
case IrOpcode::kNumberEqual: case IrOpcode::kNumberEqual:
case IrOpcode::kNumberLessThan: case IrOpcode::kNumberLessThan:
case IrOpcode::kNumberLessThanOrEqual: case IrOpcode::kNumberLessThanOrEqual:
// (Number, Number) -> Boolean // (Number, Number) -> Boolean
CHECK(bounds(Operand(node, 0)).upper->Is(Type::Number())); CheckValueInputIs(node, 0, Type::Number());
CHECK(bounds(Operand(node, 1)).upper->Is(Type::Number())); CheckValueInputIs(node, 1, Type::Number());
CHECK(bounds(node).upper->Is(Type::Boolean())); CheckUpperIs(node, Type::Boolean());
break; break;
case IrOpcode::kNumberAdd: case IrOpcode::kNumberAdd:
case IrOpcode::kNumberSubtract: case IrOpcode::kNumberSubtract:
@ -449,50 +498,52 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
case IrOpcode::kNumberDivide: case IrOpcode::kNumberDivide:
case IrOpcode::kNumberModulus: case IrOpcode::kNumberModulus:
// (Number, Number) -> Number // (Number, Number) -> Number
CHECK(bounds(Operand(node, 0)).upper->Is(Type::Number())); CheckValueInputIs(node, 0, Type::Number());
CHECK(bounds(Operand(node, 1)).upper->Is(Type::Number())); CheckValueInputIs(node, 1, Type::Number());
// TODO(rossberg): activate once we retype after opcode changes. // TODO(rossberg): activate once we retype after opcode changes.
// CHECK(bounds(node).upper->Is(Type::Number())); // CheckUpperIs(node, Type::Number());
break; break;
case IrOpcode::kNumberToInt32: case IrOpcode::kNumberToInt32:
// Number -> Signed32 // Number -> Signed32
CHECK(bounds(Operand(node)).upper->Is(Type::Number())); CheckValueInputIs(node, 0, Type::Number());
CHECK(bounds(node).upper->Is(Type::Signed32())); CheckUpperIs(node, Type::Signed32());
break; break;
case IrOpcode::kNumberToUint32: case IrOpcode::kNumberToUint32:
// Number -> Unsigned32 // Number -> Unsigned32
CHECK(bounds(Operand(node)).upper->Is(Type::Number())); CheckValueInputIs(node, 0, Type::Number());
CHECK(bounds(node).upper->Is(Type::Unsigned32())); CheckUpperIs(node, Type::Unsigned32());
break; break;
case IrOpcode::kStringEqual: case IrOpcode::kStringEqual:
case IrOpcode::kStringLessThan: case IrOpcode::kStringLessThan:
case IrOpcode::kStringLessThanOrEqual: case IrOpcode::kStringLessThanOrEqual:
// (String, String) -> Boolean // (String, String) -> Boolean
CHECK(bounds(Operand(node, 0)).upper->Is(Type::String())); CheckValueInputIs(node, 0, Type::String());
CHECK(bounds(Operand(node, 1)).upper->Is(Type::String())); CheckValueInputIs(node, 1, Type::String());
CHECK(bounds(node).upper->Is(Type::Boolean())); CheckUpperIs(node, Type::Boolean());
break; break;
case IrOpcode::kStringAdd: case IrOpcode::kStringAdd:
// (String, String) -> String // (String, String) -> String
CHECK(bounds(Operand(node, 0)).upper->Is(Type::String())); CheckValueInputIs(node, 0, Type::String());
CHECK(bounds(Operand(node, 1)).upper->Is(Type::String())); CheckValueInputIs(node, 1, Type::String());
CHECK(bounds(node).upper->Is(Type::String())); CheckUpperIs(node, Type::String());
break; break;
case IrOpcode::kReferenceEqual: { case IrOpcode::kReferenceEqual: {
// (Unique, Any) -> Boolean and // (Unique, Any) -> Boolean and
// (Any, Unique) -> Boolean // (Any, Unique) -> Boolean
CHECK(bounds(Operand(node, 0)).upper->Is(Type::Unique()) || if (typing == TYPED) {
bounds(Operand(node, 1)).upper->Is(Type::Unique())); CHECK(bounds(ValueInput(node, 0)).upper->Is(Type::Unique()) ||
CHECK(bounds(node).upper->Is(Type::Boolean())); bounds(ValueInput(node, 1)).upper->Is(Type::Unique()));
}
CheckUpperIs(node, Type::Boolean());
break; break;
} }
case IrOpcode::kObjectIsSmi: case IrOpcode::kObjectIsSmi:
CHECK(bounds(Operand(node)).upper->Is(Type::Any())); CheckValueInputIs(node, 0, Type::Any());
CHECK(bounds(node).upper->Is(Type::Boolean())); CheckUpperIs(node, Type::Boolean());
break; break;
case IrOpcode::kObjectIsNonNegativeSmi: case IrOpcode::kObjectIsNonNegativeSmi:
CHECK(bounds(Operand(node)).upper->Is(Type::Any())); CheckValueInputIs(node, 0, Type::Any());
CHECK(bounds(node).upper->Is(Type::Boolean())); CheckUpperIs(node, Type::Boolean());
break; break;
case IrOpcode::kChangeTaggedToInt32: { case IrOpcode::kChangeTaggedToInt32: {
@ -500,8 +551,8 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// TODO(neis): Activate once ChangeRepresentation works in typer. // TODO(neis): Activate once ChangeRepresentation works in typer.
// Type* from = Type::Intersect(Type::Signed32(), Type::Tagged()); // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
// Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
// CHECK(bounds(Operand(node)).upper->Is(from)); // CheckValueInputIs(node, 0, from));
// CHECK(bounds(node).upper->Is(to)); // CheckUpperIs(node, to));
break; break;
} }
case IrOpcode::kChangeTaggedToUint32: { case IrOpcode::kChangeTaggedToUint32: {
@ -509,8 +560,8 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// TODO(neis): Activate once ChangeRepresentation works in typer. // TODO(neis): Activate once ChangeRepresentation works in typer.
// Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged()); // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged());
// Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32()); // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32());
// CHECK(bounds(Operand(node)).upper->Is(from)); // CheckValueInputIs(node, 0, from));
// CHECK(bounds(node).upper->Is(to)); // CheckUpperIs(node, to));
break; break;
} }
case IrOpcode::kChangeTaggedToFloat64: { case IrOpcode::kChangeTaggedToFloat64: {
@ -518,8 +569,8 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// TODO(neis): Activate once ChangeRepresentation works in typer. // TODO(neis): Activate once ChangeRepresentation works in typer.
// Type* from = Type::Intersect(Type::Number(), Type::Tagged()); // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
// Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64()); // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
// CHECK(bounds(Operand(node)).upper->Is(from)); // CheckValueInputIs(node, 0, from));
// CHECK(bounds(node).upper->Is(to)); // CheckUpperIs(node, to));
break; break;
} }
case IrOpcode::kChangeInt32ToTagged: { case IrOpcode::kChangeInt32ToTagged: {
@ -527,8 +578,8 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// TODO(neis): Activate once ChangeRepresentation works in typer. // TODO(neis): Activate once ChangeRepresentation works in typer.
// Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
// Type* to = Type::Intersect(Type::Signed32(), Type::Tagged()); // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged());
// CHECK(bounds(Operand(node)).upper->Is(from)); // CheckValueInputIs(node, 0, from));
// CHECK(bounds(node).upper->Is(to)); // CheckUpperIs(node, to));
break; break;
} }
case IrOpcode::kChangeUint32ToTagged: { case IrOpcode::kChangeUint32ToTagged: {
@ -536,8 +587,8 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// TODO(neis): Activate once ChangeRepresentation works in typer. // TODO(neis): Activate once ChangeRepresentation works in typer.
// Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32()); // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32());
// Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged()); // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged());
// CHECK(bounds(Operand(node)).upper->Is(from)); // CheckValueInputIs(node, 0, from));
// CHECK(bounds(node).upper->Is(to)); // CheckUpperIs(node, to));
break; break;
} }
case IrOpcode::kChangeFloat64ToTagged: { case IrOpcode::kChangeFloat64ToTagged: {
@ -545,8 +596,8 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// TODO(neis): Activate once ChangeRepresentation works in typer. // TODO(neis): Activate once ChangeRepresentation works in typer.
// Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64()); // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64());
// Type* to = Type::Intersect(Type::Number(), Type::Tagged()); // Type* to = Type::Intersect(Type::Number(), Type::Tagged());
// CHECK(bounds(Operand(node)).upper->Is(from)); // CheckValueInputIs(node, 0, from));
// CHECK(bounds(node).upper->Is(to)); // CheckUpperIs(node, to));
break; break;
} }
case IrOpcode::kChangeBoolToBit: { case IrOpcode::kChangeBoolToBit: {
@ -554,8 +605,8 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// TODO(neis): Activate once ChangeRepresentation works in typer. // TODO(neis): Activate once ChangeRepresentation works in typer.
// Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
// Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
// CHECK(bounds(Operand(node)).upper->Is(from)); // CheckValueInputIs(node, 0, from));
// CHECK(bounds(node).upper->Is(to)); // CheckUpperIs(node, to));
break; break;
} }
case IrOpcode::kChangeBitToBool: { case IrOpcode::kChangeBitToBool: {
@ -563,36 +614,36 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// TODO(neis): Activate once ChangeRepresentation works in typer. // TODO(neis): Activate once ChangeRepresentation works in typer.
// Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
// Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
// CHECK(bounds(Operand(node)).upper->Is(from)); // CheckValueInputIs(node, 0, from));
// CHECK(bounds(node).upper->Is(to)); // CheckUpperIs(node, to));
break; break;
} }
case IrOpcode::kLoadField: case IrOpcode::kLoadField:
// Object -> fieldtype // Object -> fieldtype
// TODO(rossberg): activate once machine ops are typed. // TODO(rossberg): activate once machine ops are typed.
// CHECK(bounds(Operand(node)).upper->Is(Type::Object())); // CheckValueInputIs(node, 0, Type::Object());
// CHECK(bounds(node).upper->Is(Field(node).type)); // CheckUpperIs(node, Field(node).type));
break; break;
case IrOpcode::kLoadElement: case IrOpcode::kLoadElement:
// Object -> elementtype // Object -> elementtype
// TODO(rossberg): activate once machine ops are typed. // TODO(rossberg): activate once machine ops are typed.
// CHECK(bounds(Operand(node)).upper->Is(Type::Object())); // CheckValueInputIs(node, 0, Type::Object());
// CHECK(bounds(node).upper->Is(Element(node).type)); // CheckUpperIs(node, Element(node).type));
break; break;
case IrOpcode::kStoreField: case IrOpcode::kStoreField:
// (Object, fieldtype) -> _|_ // (Object, fieldtype) -> _|_
// TODO(rossberg): activate once machine ops are typed. // TODO(rossberg): activate once machine ops are typed.
// CHECK(bounds(Operand(node, 0)).upper->Is(Type::Object())); // CheckValueInputIs(node, 0, Type::Object());
// CHECK(bounds(Operand(node, 1)).upper->Is(Field(node).type)); // CheckValueInputIs(node, 1, Field(node).type));
CHECK(!NodeProperties::IsTyped(node)); CheckNotTyped(node);
break; break;
case IrOpcode::kStoreElement: case IrOpcode::kStoreElement:
// (Object, elementtype) -> _|_ // (Object, elementtype) -> _|_
// TODO(rossberg): activate once machine ops are typed. // TODO(rossberg): activate once machine ops are typed.
// CHECK(bounds(Operand(node, 0)).upper->Is(Type::Object())); // CheckValueInputIs(node, 0, Type::Object());
// CHECK(bounds(Operand(node, 1)).upper->Is(Element(node).type)); // CheckValueInputIs(node, 1, Element(node).type));
CHECK(!NodeProperties::IsTyped(node)); CheckNotTyped(node);
break; break;
// Machine operators // Machine operators
@ -662,7 +713,6 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// TODO(rossberg): Check. // TODO(rossberg): Check.
break; break;
} }
}
return GenericGraphVisit::CONTINUE; return GenericGraphVisit::CONTINUE;
} }