| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/verifier.h" | 5 #include "src/compiler/verifier.h" |
| 6 | 6 |
| 7 #include <deque> | 7 #include <deque> |
| 8 #include <queue> | 8 #include <queue> |
| 9 | 9 |
| 10 #include "src/compiler/generic-algorithm.h" | 10 #include "src/compiler/generic-algorithm.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {} | 49 Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {} |
| 50 | 50 |
| 51 // Fulfills the PreNodeCallback interface. | 51 // Fulfills the PreNodeCallback interface. |
| 52 GenericGraphVisit::Control Pre(Node* node); | 52 GenericGraphVisit::Control Pre(Node* node); |
| 53 | 53 |
| 54 Zone* zone; | 54 Zone* zone; |
| 55 Typing typing; | 55 Typing typing; |
| 56 | 56 |
| 57 private: | 57 private: |
| 58 // TODO(rossberg): Get rid of these once we got rid of NodeProperties. | 58 // TODO(rossberg): Get rid of these once we got rid of NodeProperties. |
| 59 Bounds bounds(Node* node) { | 59 Bounds bounds(Node* node) { return NodeProperties::GetBounds(node); } |
| 60 return NodeProperties::GetBounds(node); | 60 Node* ValueInput(Node* node, int i = 0) { |
| 61 } | |
| 62 Node* Operand(Node* node, int i = 0) { | |
| 63 return NodeProperties::GetValueInput(node, i); | 61 return NodeProperties::GetValueInput(node, i); |
| 64 } | 62 } |
| 65 FieldAccess Field(Node* node) { | 63 FieldAccess Field(Node* node) { |
| 66 DCHECK(node->opcode() == IrOpcode::kLoadField || | 64 DCHECK(node->opcode() == IrOpcode::kLoadField || |
| 67 node->opcode() == IrOpcode::kStoreField); | 65 node->opcode() == IrOpcode::kStoreField); |
| 68 return OpParameter<FieldAccess>(node); | 66 return OpParameter<FieldAccess>(node); |
| 69 } | 67 } |
| 70 ElementAccess Element(Node* node) { | 68 ElementAccess Element(Node* node) { |
| 71 DCHECK(node->opcode() == IrOpcode::kLoadElement || | 69 DCHECK(node->opcode() == IrOpcode::kLoadElement || |
| 72 node->opcode() == IrOpcode::kStoreElement); | 70 node->opcode() == IrOpcode::kStoreElement); |
| 73 return OpParameter<ElementAccess>(node); | 71 return OpParameter<ElementAccess>(node); |
| 74 } | 72 } |
| 73 void CheckNotTyped(Node* node) { CHECK(!NodeProperties::IsTyped(node)); } |
| 74 void CheckUpperIs(Node* node, Type* type) { |
| 75 if (typing == TYPED) CHECK(bounds(node).upper->Is(type)); |
| 76 } |
| 77 void CheckUpperMaybe(Node* node, Type* type) { |
| 78 if (typing == TYPED) CHECK(bounds(node).upper->Maybe(type)); |
| 79 } |
| 80 void CheckValueInputIs(Node* node, int i, Type* type) { |
| 81 if (typing == TYPED) CHECK(bounds(ValueInput(node, i)).upper->Is(type)); |
| 82 } |
| 75 }; | 83 }; |
| 76 | 84 |
| 77 | 85 |
| 78 GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) { | 86 GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) { |
| 79 int value_count = OperatorProperties::GetValueInputCount(node->op()); | 87 int value_count = OperatorProperties::GetValueInputCount(node->op()); |
| 80 int context_count = OperatorProperties::GetContextInputCount(node->op()); | 88 int context_count = OperatorProperties::GetContextInputCount(node->op()); |
| 81 int frame_state_count = | 89 int frame_state_count = |
| 82 OperatorProperties::GetFrameStateInputCount(node->op()); | 90 OperatorProperties::GetFrameStateInputCount(node->op()); |
| 83 int effect_count = OperatorProperties::GetEffectInputCount(node->op()); | 91 int effect_count = OperatorProperties::GetEffectInputCount(node->op()); |
| 84 int control_count = OperatorProperties::GetControlInputCount(node->op()); | 92 int control_count = OperatorProperties::GetControlInputCount(node->op()); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 // Verify all successors are projections if multiple value outputs exist. | 142 // Verify all successors are projections if multiple value outputs exist. |
| 135 if (OperatorProperties::GetValueOutputCount(node->op()) > 1) { | 143 if (OperatorProperties::GetValueOutputCount(node->op()) > 1) { |
| 136 Node::Uses uses = node->uses(); | 144 Node::Uses uses = node->uses(); |
| 137 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) { | 145 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) { |
| 138 CHECK(!NodeProperties::IsValueEdge(it.edge()) || | 146 CHECK(!NodeProperties::IsValueEdge(it.edge()) || |
| 139 (*it)->opcode() == IrOpcode::kProjection || | 147 (*it)->opcode() == IrOpcode::kProjection || |
| 140 (*it)->opcode() == IrOpcode::kParameter); | 148 (*it)->opcode() == IrOpcode::kParameter); |
| 141 } | 149 } |
| 142 } | 150 } |
| 143 | 151 |
| 144 if (typing == TYPED) { | 152 switch (node->opcode()) { |
| 145 switch (node->opcode()) { | 153 case IrOpcode::kStart: |
| 146 // Control operators | 154 // Start has no inputs. |
| 147 // ----------------- | 155 CHECK_EQ(0, input_count); |
| 148 case IrOpcode::kStart: | 156 // Type is a tuple. |
| 149 // Start has no inputs. | 157 // TODO(rossberg): Multiple outputs are currently typed as Internal. |
| 150 CHECK_EQ(0, input_count); | 158 CheckUpperIs(node, Type::Internal()); |
| 151 // Type is a tuple. | 159 break; |
| 152 // TODO(rossberg): Multiple outputs are currently typed as Internal. | 160 case IrOpcode::kEnd: |
| 153 CHECK(bounds(node).upper->Is(Type::Internal())); | 161 // End has no outputs. |
| 154 break; | 162 CHECK(!OperatorProperties::HasValueOutput(node->op())); |
| 155 case IrOpcode::kEnd: | 163 CHECK(!OperatorProperties::HasEffectOutput(node->op())); |
| 156 // End has no outputs. | 164 CHECK(!OperatorProperties::HasControlOutput(node->op())); |
| 157 CHECK(!OperatorProperties::HasValueOutput(node->op())); | 165 // Type is empty. |
| 158 CHECK(!OperatorProperties::HasEffectOutput(node->op())); | 166 CheckNotTyped(node); |
| 159 CHECK(!OperatorProperties::HasControlOutput(node->op())); | 167 break; |
| 160 // Type is empty. | 168 case IrOpcode::kDead: |
| 161 CHECK(!NodeProperties::IsTyped(node)); | 169 // Dead is never connected to the graph. |
| 162 break; | 170 UNREACHABLE(); |
| 163 case IrOpcode::kDead: | 171 case IrOpcode::kBranch: { |
| 164 // Dead is never connected to the graph. | 172 // Branch uses are IfTrue and IfFalse. |
| 165 UNREACHABLE(); | 173 Node::Uses uses = node->uses(); |
| 166 case IrOpcode::kBranch: { | 174 int count_true = 0, count_false = 0; |
| 167 // Branch uses are IfTrue and IfFalse. | 175 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) { |
| 168 Node::Uses uses = node->uses(); | 176 CHECK((*it)->opcode() == IrOpcode::kIfTrue || |
| 169 int count_true = 0, count_false = 0; | 177 (*it)->opcode() == IrOpcode::kIfFalse); |
| 170 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) { | 178 if ((*it)->opcode() == IrOpcode::kIfTrue) ++count_true; |
| 171 CHECK((*it)->opcode() == IrOpcode::kIfTrue || | 179 if ((*it)->opcode() == IrOpcode::kIfFalse) ++count_false; |
| 172 (*it)->opcode() == IrOpcode::kIfFalse); | |
| 173 if ((*it)->opcode() == IrOpcode::kIfTrue) ++count_true; | |
| 174 if ((*it)->opcode() == IrOpcode::kIfFalse) ++count_false; | |
| 175 } | |
| 176 CHECK(count_true == 1 && count_false == 1); | |
| 177 // Type is empty. | |
| 178 CHECK(!NodeProperties::IsTyped(node)); | |
| 179 break; | |
| 180 } | 180 } |
| 181 case IrOpcode::kIfTrue: | 181 CHECK(count_true == 1 && count_false == 1); |
| 182 case IrOpcode::kIfFalse: | 182 // Type is empty. |
| 183 CHECK_EQ(IrOpcode::kBranch, | 183 CheckNotTyped(node); |
| 184 NodeProperties::GetControlInput(node, 0)->opcode()); | 184 break; |
| 185 // Type is empty. | 185 } |
| 186 CHECK(!NodeProperties::IsTyped(node)); | 186 case IrOpcode::kIfTrue: |
| 187 break; | 187 case IrOpcode::kIfFalse: |
| 188 case IrOpcode::kLoop: | 188 CHECK_EQ(IrOpcode::kBranch, |
| 189 case IrOpcode::kMerge: | 189 NodeProperties::GetControlInput(node, 0)->opcode()); |
| 190 // Type is empty. | 190 // Type is empty. |
| 191 CHECK(!NodeProperties::IsTyped(node)); | 191 CheckNotTyped(node); |
| 192 break; | 192 break; |
| 193 case IrOpcode::kReturn: | 193 case IrOpcode::kLoop: |
| 194 // TODO(rossberg): check successor is End | 194 case IrOpcode::kMerge: |
| 195 // Type is empty. | 195 CHECK_EQ(control_count, input_count); |
| 196 CHECK(!NodeProperties::IsTyped(node)); | 196 // Type is empty. |
| 197 break; | 197 CheckNotTyped(node); |
| 198 case IrOpcode::kThrow: | 198 break; |
| 199 // TODO(rossberg): what are the constraints on these? | 199 case IrOpcode::kReturn: |
| 200 // Type is empty. | 200 // TODO(rossberg): check successor is End |
| 201 CHECK(!NodeProperties::IsTyped(node)); | 201 // Type is empty. |
| 202 break; | 202 CheckNotTyped(node); |
| 203 | 203 break; |
| 204 // Common operators | 204 case IrOpcode::kThrow: |
| 205 // ---------------- | 205 // TODO(rossberg): what are the constraints on these? |
| 206 case IrOpcode::kParameter: { | 206 // Type is empty. |
| 207 // Parameters have the start node as inputs. | 207 CheckNotTyped(node); |
| 208 CHECK_EQ(1, input_count); | 208 break; |
| 209 CHECK_EQ(IrOpcode::kStart, | 209 |
| 210 NodeProperties::GetValueInput(node, 0)->opcode()); | 210 // Common operators |
| 211 // Parameter has an input that produces enough values. | 211 // ---------------- |
| 212 int index = OpParameter<int>(node); | 212 case IrOpcode::kParameter: { |
| 213 Node* input = NodeProperties::GetValueInput(node, 0); | 213 // Parameters have the start node as inputs. |
| 214 // Currently, parameter indices start at -1 instead of 0. | 214 CHECK_EQ(1, input_count); |
| 215 CHECK_GT( | 215 CHECK_EQ(IrOpcode::kStart, |
| 216 OperatorProperties::GetValueOutputCount(input->op()), index + 1); | 216 NodeProperties::GetValueInput(node, 0)->opcode()); |
| 217 // Type can be anything. | 217 // Parameter has an input that produces enough values. |
| 218 CHECK(bounds(node).upper->Is(Type::Any())); | 218 int index = OpParameter<int>(node); |
| 219 break; | 219 Node* input = NodeProperties::GetValueInput(node, 0); |
| 220 // Currently, parameter indices start at -1 instead of 0. |
| 221 CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index + 1); |
| 222 // Type can be anything. |
| 223 CheckUpperIs(node, Type::Any()); |
| 224 break; |
| 225 } |
| 226 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant? |
| 227 // Constants have no inputs. |
| 228 CHECK_EQ(0, input_count); |
| 229 // Type is a 32 bit integer, signed or unsigned. |
| 230 CheckUpperIs(node, Type::Integral32()); |
| 231 break; |
| 232 case IrOpcode::kInt64Constant: |
| 233 // Constants have no inputs. |
| 234 CHECK_EQ(0, input_count); |
| 235 // Type is internal. |
| 236 // TODO(rossberg): Introduce proper Int64 type. |
| 237 CheckUpperIs(node, Type::Internal()); |
| 238 break; |
| 239 case IrOpcode::kFloat32Constant: |
| 240 case IrOpcode::kFloat64Constant: |
| 241 case IrOpcode::kNumberConstant: |
| 242 // Constants have no inputs. |
| 243 CHECK_EQ(0, input_count); |
| 244 // Type is a number. |
| 245 CheckUpperIs(node, Type::Number()); |
| 246 break; |
| 247 case IrOpcode::kHeapConstant: |
| 248 // Constants have no inputs. |
| 249 CHECK_EQ(0, input_count); |
| 250 // Type can be anything represented as a heap pointer. |
| 251 CheckUpperIs(node, Type::TaggedPtr()); |
| 252 break; |
| 253 case IrOpcode::kExternalConstant: |
| 254 // Constants have no inputs. |
| 255 CHECK_EQ(0, input_count); |
| 256 // Type is considered internal. |
| 257 CheckUpperIs(node, Type::Internal()); |
| 258 break; |
| 259 case IrOpcode::kProjection: { |
| 260 // Projection has an input that produces enough values. |
| 261 int index = OpParameter<int>(node->op()); |
| 262 Node* input = NodeProperties::GetValueInput(node, 0); |
| 263 CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index); |
| 264 // Type can be anything. |
| 265 // TODO(rossberg): Introduce tuple types for this. |
| 266 // TODO(titzer): Convince rossberg not to. |
| 267 CheckUpperIs(node, Type::Any()); |
| 268 break; |
| 269 } |
| 270 case IrOpcode::kPhi: { |
| 271 // Phi input count matches parent control node. |
| 272 CHECK_EQ(0, effect_count); |
| 273 CHECK_EQ(1, control_count); |
| 274 Node* control = NodeProperties::GetControlInput(node, 0); |
| 275 CHECK_EQ(value_count, |
| 276 OperatorProperties::GetControlInputCount(control->op())); |
| 277 CHECK_EQ(input_count, 1 + value_count); |
| 278 // Type must be subsumed by all input types. |
| 279 // TODO(rossberg): for now at least, narrowing does not really hold. |
| 280 /* |
| 281 for (int i = 0; i < value_count; ++i) { |
| 282 // TODO(rossberg, jarin): Figure out what to do about lower bounds. |
| 283 // CHECK(bounds(node).lower->Is(bounds(ValueInput(node, i)).lower)); |
| 284 CHECK(bounds(ValueInput(node, i)).upper->Is(bounds(node).upper)); |
| 220 } | 285 } |
| 221 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant? | 286 */ |
| 222 // Constants have no inputs. | 287 break; |
| 223 CHECK_EQ(0, input_count); | 288 } |
| 224 // Type is a 32 bit integer, signed or unsigned. | 289 case IrOpcode::kEffectPhi: { |
| 225 CHECK(bounds(node).upper->Is(Type::Integral32())); | 290 // EffectPhi input count matches parent control node. |
| 226 break; | 291 CHECK_EQ(0, value_count); |
| 227 case IrOpcode::kInt64Constant: | 292 CHECK_EQ(1, control_count); |
| 228 // Constants have no inputs. | 293 Node* control = NodeProperties::GetControlInput(node, 0); |
| 229 CHECK_EQ(0, input_count); | 294 CHECK_EQ(effect_count, |
| 230 // Type is internal. | 295 OperatorProperties::GetControlInputCount(control->op())); |
| 231 // TODO(rossberg): Introduce proper Int64 type. | 296 CHECK_EQ(input_count, 1 + effect_count); |
| 232 CHECK(bounds(node).upper->Is(Type::Internal())); | 297 break; |
| 233 break; | 298 } |
| 234 case IrOpcode::kFloat32Constant: | 299 case IrOpcode::kValueEffect: |
| 235 case IrOpcode::kFloat64Constant: | 300 // TODO(rossberg): what are the constraints on these? |
| 236 case IrOpcode::kNumberConstant: | 301 break; |
| 237 // Constants have no inputs. | 302 case IrOpcode::kFinish: { |
| 238 CHECK_EQ(0, input_count); | 303 // TODO(rossberg): what are the constraints on these? |
| 239 // Type is a number. | 304 // Type must be subsumed by input type. |
| 240 CHECK(bounds(node).upper->Is(Type::Number())); | 305 if (typing == TYPED) { |
| 241 break; | 306 CHECK(bounds(ValueInput(node)).lower->Is(bounds(node).lower)); |
| 242 case IrOpcode::kHeapConstant: | 307 CHECK(bounds(ValueInput(node)).upper->Is(bounds(node).upper)); |
| 243 // Constants have no inputs. | |
| 244 CHECK_EQ(0, input_count); | |
| 245 // Type can be anything represented as a heap pointer. | |
| 246 CHECK(bounds(node).upper->Is(Type::TaggedPtr())); | |
| 247 break; | |
| 248 case IrOpcode::kExternalConstant: | |
| 249 // Constants have no inputs. | |
| 250 CHECK_EQ(0, input_count); | |
| 251 // Type is considered internal. | |
| 252 CHECK(bounds(node).upper->Is(Type::Internal())); | |
| 253 break; | |
| 254 case IrOpcode::kProjection: { | |
| 255 // Projection has an input that produces enough values. | |
| 256 int index = OpParameter<int>(node->op()); | |
| 257 Node* input = NodeProperties::GetValueInput(node, 0); | |
| 258 CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index); | |
| 259 // Type can be anything. | |
| 260 // TODO(rossberg): Introduce tuple types for this. | |
| 261 CHECK(bounds(node).upper->Is(Type::Any())); | |
| 262 break; | |
| 263 } | 308 } |
| 264 case IrOpcode::kPhi: { | 309 break; |
| 265 // Phi input count matches parent control node. | 310 } |
| 266 CHECK_EQ(1, control_count); | 311 case IrOpcode::kFrameState: |
| 267 Node* control = NodeProperties::GetControlInput(node, 0); | 312 // TODO(jarin): what are the constraints on these? |
| 268 CHECK_EQ(value_count, | 313 break; |
| 269 OperatorProperties::GetControlInputCount(control->op())); | 314 case IrOpcode::kStateValues: |
| 270 // Type must be subsumed by all input types. | 315 // TODO(jarin): what are the constraints on these? |
| 271 // TODO(rossberg): for now at least, narrowing does not really hold. | 316 break; |
| 272 /* | 317 case IrOpcode::kCall: |
| 273 for (int i = 0; i < value_count; ++i) { | 318 // TODO(rossberg): what are the constraints on these? |
| 274 // TODO(rossberg, jarin): Figure out what to do about lower bounds. | 319 break; |
| 275 // CHECK(bounds(node).lower->Is(bounds(Operand(node, i)).lower)); | 320 |
| 276 CHECK(bounds(Operand(node, i)).upper->Is(bounds(node).upper)); | 321 // JavaScript operators |
| 277 } | 322 // -------------------- |
| 278 */ | 323 case IrOpcode::kJSEqual: |
| 279 break; | 324 case IrOpcode::kJSNotEqual: |
| 325 case IrOpcode::kJSStrictEqual: |
| 326 case IrOpcode::kJSStrictNotEqual: |
| 327 case IrOpcode::kJSLessThan: |
| 328 case IrOpcode::kJSGreaterThan: |
| 329 case IrOpcode::kJSLessThanOrEqual: |
| 330 case IrOpcode::kJSGreaterThanOrEqual: |
| 331 case IrOpcode::kJSUnaryNot: |
| 332 // Type is Boolean. |
| 333 CheckUpperIs(node, Type::Boolean()); |
| 334 break; |
| 335 |
| 336 case IrOpcode::kJSBitwiseOr: |
| 337 case IrOpcode::kJSBitwiseXor: |
| 338 case IrOpcode::kJSBitwiseAnd: |
| 339 case IrOpcode::kJSShiftLeft: |
| 340 case IrOpcode::kJSShiftRight: |
| 341 case IrOpcode::kJSShiftRightLogical: |
| 342 // Type is 32 bit integral. |
| 343 CheckUpperIs(node, Type::Integral32()); |
| 344 break; |
| 345 case IrOpcode::kJSAdd: |
| 346 // Type is Number or String. |
| 347 CheckUpperIs(node, Type::NumberOrString()); |
| 348 break; |
| 349 case IrOpcode::kJSSubtract: |
| 350 case IrOpcode::kJSMultiply: |
| 351 case IrOpcode::kJSDivide: |
| 352 case IrOpcode::kJSModulus: |
| 353 // Type is Number. |
| 354 CheckUpperIs(node, Type::Number()); |
| 355 break; |
| 356 |
| 357 case IrOpcode::kJSToBoolean: |
| 358 // Type is Boolean. |
| 359 CheckUpperIs(node, Type::Boolean()); |
| 360 break; |
| 361 case IrOpcode::kJSToNumber: |
| 362 // Type is Number. |
| 363 CheckUpperIs(node, Type::Number()); |
| 364 break; |
| 365 case IrOpcode::kJSToString: |
| 366 // Type is String. |
| 367 CheckUpperIs(node, Type::String()); |
| 368 break; |
| 369 case IrOpcode::kJSToName: |
| 370 // Type is Name. |
| 371 CheckUpperIs(node, Type::Name()); |
| 372 break; |
| 373 case IrOpcode::kJSToObject: |
| 374 // Type is Receiver. |
| 375 CheckUpperIs(node, Type::Receiver()); |
| 376 break; |
| 377 |
| 378 case IrOpcode::kJSCreate: |
| 379 // Type is Object. |
| 380 CheckUpperIs(node, Type::Object()); |
| 381 break; |
| 382 case IrOpcode::kJSLoadProperty: |
| 383 case IrOpcode::kJSLoadNamed: |
| 384 // Type can be anything. |
| 385 CheckUpperIs(node, Type::Any()); |
| 386 break; |
| 387 case IrOpcode::kJSStoreProperty: |
| 388 case IrOpcode::kJSStoreNamed: |
| 389 // Type is empty. |
| 390 CheckNotTyped(node); |
| 391 break; |
| 392 case IrOpcode::kJSDeleteProperty: |
| 393 case IrOpcode::kJSHasProperty: |
| 394 case IrOpcode::kJSInstanceOf: |
| 395 // Type is Boolean. |
| 396 CheckUpperIs(node, Type::Boolean()); |
| 397 break; |
| 398 case IrOpcode::kJSTypeOf: |
| 399 // Type is String. |
| 400 CheckUpperIs(node, Type::String()); |
| 401 break; |
| 402 |
| 403 case IrOpcode::kJSLoadContext: |
| 404 // Type can be anything. |
| 405 CheckUpperIs(node, Type::Any()); |
| 406 break; |
| 407 case IrOpcode::kJSStoreContext: |
| 408 // Type is empty. |
| 409 CheckNotTyped(node); |
| 410 break; |
| 411 case IrOpcode::kJSCreateFunctionContext: |
| 412 case IrOpcode::kJSCreateCatchContext: |
| 413 case IrOpcode::kJSCreateWithContext: |
| 414 case IrOpcode::kJSCreateBlockContext: |
| 415 case IrOpcode::kJSCreateModuleContext: |
| 416 case IrOpcode::kJSCreateGlobalContext: { |
| 417 // Type is Context, and operand is Internal. |
| 418 Node* context = NodeProperties::GetContextInput(node); |
| 419 // TODO(rossberg): This should really be Is(Internal), but the typer |
| 420 // currently can't do backwards propagation. |
| 421 CheckUpperMaybe(context, Type::Internal()); |
| 422 if (typing == TYPED) CHECK(bounds(node).upper->IsContext()); |
| 423 break; |
| 424 } |
| 425 |
| 426 case IrOpcode::kJSCallConstruct: |
| 427 // Type is Receiver. |
| 428 CheckUpperIs(node, Type::Receiver()); |
| 429 break; |
| 430 case IrOpcode::kJSCallFunction: |
| 431 case IrOpcode::kJSCallRuntime: |
| 432 case IrOpcode::kJSYield: |
| 433 case IrOpcode::kJSDebugger: |
| 434 // Type can be anything. |
| 435 CheckUpperIs(node, Type::Any()); |
| 436 break; |
| 437 |
| 438 // Simplified operators |
| 439 // ------------------------------- |
| 440 case IrOpcode::kBooleanNot: |
| 441 // Boolean -> Boolean |
| 442 CheckValueInputIs(node, 0, Type::Boolean()); |
| 443 CheckUpperIs(node, Type::Boolean()); |
| 444 break; |
| 445 case IrOpcode::kBooleanToNumber: |
| 446 // Boolean -> Number |
| 447 CheckValueInputIs(node, 0, Type::Boolean()); |
| 448 CheckUpperIs(node, Type::Number()); |
| 449 break; |
| 450 case IrOpcode::kNumberEqual: |
| 451 case IrOpcode::kNumberLessThan: |
| 452 case IrOpcode::kNumberLessThanOrEqual: |
| 453 // (Number, Number) -> Boolean |
| 454 CheckValueInputIs(node, 0, Type::Number()); |
| 455 CheckValueInputIs(node, 1, Type::Number()); |
| 456 CheckUpperIs(node, Type::Boolean()); |
| 457 break; |
| 458 case IrOpcode::kNumberAdd: |
| 459 case IrOpcode::kNumberSubtract: |
| 460 case IrOpcode::kNumberMultiply: |
| 461 case IrOpcode::kNumberDivide: |
| 462 case IrOpcode::kNumberModulus: |
| 463 // (Number, Number) -> Number |
| 464 CheckValueInputIs(node, 0, Type::Number()); |
| 465 CheckValueInputIs(node, 1, Type::Number()); |
| 466 // TODO(rossberg): activate once we retype after opcode changes. |
| 467 // CheckUpperIs(node, Type::Number()); |
| 468 break; |
| 469 case IrOpcode::kNumberToInt32: |
| 470 // Number -> Signed32 |
| 471 CheckValueInputIs(node, 0, Type::Number()); |
| 472 CheckUpperIs(node, Type::Signed32()); |
| 473 break; |
| 474 case IrOpcode::kNumberToUint32: |
| 475 // Number -> Unsigned32 |
| 476 CheckValueInputIs(node, 0, Type::Number()); |
| 477 CheckUpperIs(node, Type::Unsigned32()); |
| 478 break; |
| 479 case IrOpcode::kStringEqual: |
| 480 case IrOpcode::kStringLessThan: |
| 481 case IrOpcode::kStringLessThanOrEqual: |
| 482 // (String, String) -> Boolean |
| 483 CheckValueInputIs(node, 0, Type::String()); |
| 484 CheckValueInputIs(node, 1, Type::String()); |
| 485 CheckUpperIs(node, Type::Boolean()); |
| 486 break; |
| 487 case IrOpcode::kStringAdd: |
| 488 // (String, String) -> String |
| 489 CheckValueInputIs(node, 0, Type::String()); |
| 490 CheckValueInputIs(node, 1, Type::String()); |
| 491 CheckUpperIs(node, Type::String()); |
| 492 break; |
| 493 case IrOpcode::kReferenceEqual: { |
| 494 // (Unique, Any) -> Boolean and |
| 495 // (Any, Unique) -> Boolean |
| 496 if (typing == TYPED) { |
| 497 CHECK(bounds(ValueInput(node, 0)).upper->Is(Type::Unique()) || |
| 498 bounds(ValueInput(node, 1)).upper->Is(Type::Unique())); |
| 280 } | 499 } |
| 281 case IrOpcode::kEffectPhi: { | 500 CheckUpperIs(node, Type::Boolean()); |
| 282 // EffectPhi input count matches parent control node. | 501 break; |
| 283 CHECK_EQ(1, control_count); | 502 } |
| 284 Node* control = NodeProperties::GetControlInput(node, 0); | 503 case IrOpcode::kObjectIsSmi: |
| 285 CHECK_EQ(effect_count, | 504 CheckValueInputIs(node, 0, Type::Any()); |
| 286 OperatorProperties::GetControlInputCount(control->op())); | 505 CheckUpperIs(node, Type::Boolean()); |
| 287 break; | 506 break; |
| 288 } | 507 case IrOpcode::kObjectIsNonNegativeSmi: |
| 289 case IrOpcode::kValueEffect: | 508 CheckValueInputIs(node, 0, Type::Any()); |
| 290 // TODO(rossberg): what are the constraints on these? | 509 CheckUpperIs(node, Type::Boolean()); |
| 291 break; | 510 break; |
| 292 case IrOpcode::kFinish: { | 511 |
| 293 // TODO(rossberg): what are the constraints on these? | 512 case IrOpcode::kChangeTaggedToInt32: { |
| 294 // Type must be subsumed by input type. | 513 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32 |
| 295 CHECK(bounds(Operand(node)).lower->Is(bounds(node).lower)); | 514 // TODO(neis): Activate once ChangeRepresentation works in typer. |
| 296 CHECK(bounds(Operand(node)).upper->Is(bounds(node).upper)); | 515 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged()); |
| 297 break; | 516 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); |
| 298 } | 517 // CheckValueInputIs(node, 0, from)); |
| 299 case IrOpcode::kFrameState: | 518 // CheckUpperIs(node, to)); |
| 300 // TODO(jarin): what are the constraints on these? | 519 break; |
| 301 break; | 520 } |
| 302 case IrOpcode::kStateValues: | 521 case IrOpcode::kChangeTaggedToUint32: { |
| 303 // TODO(jarin): what are the constraints on these? | 522 // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32 |
| 304 break; | 523 // TODO(neis): Activate once ChangeRepresentation works in typer. |
| 305 case IrOpcode::kCall: | 524 // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged()); |
| 306 // TODO(rossberg): what are the constraints on these? | 525 // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32()); |
| 307 break; | 526 // CheckValueInputIs(node, 0, from)); |
| 308 | 527 // CheckUpperIs(node, to)); |
| 309 // JavaScript operators | 528 break; |
| 310 // -------------------- | 529 } |
| 311 case IrOpcode::kJSEqual: | 530 case IrOpcode::kChangeTaggedToFloat64: { |
| 312 case IrOpcode::kJSNotEqual: | 531 // Number /\ Tagged -> Number /\ UntaggedFloat64 |
| 313 case IrOpcode::kJSStrictEqual: | 532 // TODO(neis): Activate once ChangeRepresentation works in typer. |
| 314 case IrOpcode::kJSStrictNotEqual: | 533 // Type* from = Type::Intersect(Type::Number(), Type::Tagged()); |
| 315 case IrOpcode::kJSLessThan: | 534 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64()); |
| 316 case IrOpcode::kJSGreaterThan: | 535 // CheckValueInputIs(node, 0, from)); |
| 317 case IrOpcode::kJSLessThanOrEqual: | 536 // CheckUpperIs(node, to)); |
| 318 case IrOpcode::kJSGreaterThanOrEqual: | 537 break; |
| 319 case IrOpcode::kJSUnaryNot: | 538 } |
| 320 // Type is Boolean. | 539 case IrOpcode::kChangeInt32ToTagged: { |
| 321 CHECK(bounds(node).upper->Is(Type::Boolean())); | 540 // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged |
| 322 break; | 541 // TODO(neis): Activate once ChangeRepresentation works in typer. |
| 323 | 542 // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); |
| 324 case IrOpcode::kJSBitwiseOr: | 543 // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged()); |
| 325 case IrOpcode::kJSBitwiseXor: | 544 // CheckValueInputIs(node, 0, from)); |
| 326 case IrOpcode::kJSBitwiseAnd: | 545 // CheckUpperIs(node, to)); |
| 327 case IrOpcode::kJSShiftLeft: | 546 break; |
| 328 case IrOpcode::kJSShiftRight: | 547 } |
| 329 case IrOpcode::kJSShiftRightLogical: | 548 case IrOpcode::kChangeUint32ToTagged: { |
| 330 // Type is 32 bit integral. | 549 // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged |
| 331 CHECK(bounds(node).upper->Is(Type::Integral32())); | 550 // TODO(neis): Activate once ChangeRepresentation works in typer. |
| 332 break; | 551 // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32()); |
| 333 case IrOpcode::kJSAdd: | 552 // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged()); |
| 334 // Type is Number or String. | 553 // CheckValueInputIs(node, 0, from)); |
| 335 CHECK(bounds(node).upper->Is(Type::NumberOrString())); | 554 // CheckUpperIs(node, to)); |
| 336 break; | 555 break; |
| 337 case IrOpcode::kJSSubtract: | 556 } |
| 338 case IrOpcode::kJSMultiply: | 557 case IrOpcode::kChangeFloat64ToTagged: { |
| 339 case IrOpcode::kJSDivide: | 558 // Number /\ UntaggedFloat64 -> Number /\ Tagged |
| 340 case IrOpcode::kJSModulus: | 559 // TODO(neis): Activate once ChangeRepresentation works in typer. |
| 341 // Type is Number. | 560 // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64()); |
| 342 CHECK(bounds(node).upper->Is(Type::Number())); | 561 // Type* to = Type::Intersect(Type::Number(), Type::Tagged()); |
| 343 break; | 562 // CheckValueInputIs(node, 0, from)); |
| 344 | 563 // CheckUpperIs(node, to)); |
| 345 case IrOpcode::kJSToBoolean: | 564 break; |
| 346 // Type is Boolean. | 565 } |
| 347 CHECK(bounds(node).upper->Is(Type::Boolean())); | 566 case IrOpcode::kChangeBoolToBit: { |
| 348 break; | 567 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1 |
| 349 case IrOpcode::kJSToNumber: | 568 // TODO(neis): Activate once ChangeRepresentation works in typer. |
| 350 // Type is Number. | 569 // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); |
| 351 CHECK(bounds(node).upper->Is(Type::Number())); | 570 // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); |
| 352 break; | 571 // CheckValueInputIs(node, 0, from)); |
| 353 case IrOpcode::kJSToString: | 572 // CheckUpperIs(node, to)); |
| 354 // Type is String. | 573 break; |
| 355 CHECK(bounds(node).upper->Is(Type::String())); | 574 } |
| 356 break; | 575 case IrOpcode::kChangeBitToBool: { |
| 357 case IrOpcode::kJSToName: | 576 // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr |
| 358 // Type is Name. | 577 // TODO(neis): Activate once ChangeRepresentation works in typer. |
| 359 CHECK(bounds(node).upper->Is(Type::Name())); | 578 // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); |
| 360 break; | 579 // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); |
| 361 case IrOpcode::kJSToObject: | 580 // CheckValueInputIs(node, 0, from)); |
| 362 // Type is Receiver. | 581 // CheckUpperIs(node, to)); |
| 363 CHECK(bounds(node).upper->Is(Type::Receiver())); | 582 break; |
| 364 break; | 583 } |
| 365 | 584 |
| 366 case IrOpcode::kJSCreate: | 585 case IrOpcode::kLoadField: |
| 367 // Type is Object. | 586 // Object -> fieldtype |
| 368 CHECK(bounds(node).upper->Is(Type::Object())); | 587 // TODO(rossberg): activate once machine ops are typed. |
| 369 break; | 588 // CheckValueInputIs(node, 0, Type::Object()); |
| 370 case IrOpcode::kJSLoadProperty: | 589 // CheckUpperIs(node, Field(node).type)); |
| 371 case IrOpcode::kJSLoadNamed: | 590 break; |
| 372 // Type can be anything. | 591 case IrOpcode::kLoadElement: |
| 373 CHECK(bounds(node).upper->Is(Type::Any())); | 592 // Object -> elementtype |
| 374 break; | 593 // TODO(rossberg): activate once machine ops are typed. |
| 375 case IrOpcode::kJSStoreProperty: | 594 // CheckValueInputIs(node, 0, Type::Object()); |
| 376 case IrOpcode::kJSStoreNamed: | 595 // CheckUpperIs(node, Element(node).type)); |
| 377 // Type is empty. | 596 break; |
| 378 CHECK(!NodeProperties::IsTyped(node)); | 597 case IrOpcode::kStoreField: |
| 379 break; | 598 // (Object, fieldtype) -> _|_ |
| 380 case IrOpcode::kJSDeleteProperty: | 599 // TODO(rossberg): activate once machine ops are typed. |
| 381 case IrOpcode::kJSHasProperty: | 600 // CheckValueInputIs(node, 0, Type::Object()); |
| 382 case IrOpcode::kJSInstanceOf: | 601 // CheckValueInputIs(node, 1, Field(node).type)); |
| 383 // Type is Boolean. | 602 CheckNotTyped(node); |
| 384 CHECK(bounds(node).upper->Is(Type::Boolean())); | 603 break; |
| 385 break; | 604 case IrOpcode::kStoreElement: |
| 386 case IrOpcode::kJSTypeOf: | 605 // (Object, elementtype) -> _|_ |
| 387 // Type is String. | 606 // TODO(rossberg): activate once machine ops are typed. |
| 388 CHECK(bounds(node).upper->Is(Type::String())); | 607 // CheckValueInputIs(node, 0, Type::Object()); |
| 389 break; | 608 // CheckValueInputIs(node, 1, Element(node).type)); |
| 390 | 609 CheckNotTyped(node); |
| 391 case IrOpcode::kJSLoadContext: | 610 break; |
| 392 // Type can be anything. | 611 |
| 393 CHECK(bounds(node).upper->Is(Type::Any())); | 612 // Machine operators |
| 394 break; | 613 // ----------------------- |
| 395 case IrOpcode::kJSStoreContext: | 614 case IrOpcode::kLoad: |
| 396 // Type is empty. | 615 case IrOpcode::kStore: |
| 397 CHECK(!NodeProperties::IsTyped(node)); | 616 case IrOpcode::kWord32And: |
| 398 break; | 617 case IrOpcode::kWord32Or: |
| 399 case IrOpcode::kJSCreateFunctionContext: | 618 case IrOpcode::kWord32Xor: |
| 400 case IrOpcode::kJSCreateCatchContext: | 619 case IrOpcode::kWord32Shl: |
| 401 case IrOpcode::kJSCreateWithContext: | 620 case IrOpcode::kWord32Shr: |
| 402 case IrOpcode::kJSCreateBlockContext: | 621 case IrOpcode::kWord32Sar: |
| 403 case IrOpcode::kJSCreateModuleContext: | 622 case IrOpcode::kWord32Ror: |
| 404 case IrOpcode::kJSCreateGlobalContext: { | 623 case IrOpcode::kWord32Equal: |
| 405 // Type is Context, and operand is Internal. | 624 case IrOpcode::kWord64And: |
| 406 Bounds outer = bounds(NodeProperties::GetContextInput(node)); | 625 case IrOpcode::kWord64Or: |
| 407 // TODO(rossberg): This should really be Is(Internal), but the typer | 626 case IrOpcode::kWord64Xor: |
| 408 // currently can't do backwards propagation. | 627 case IrOpcode::kWord64Shl: |
| 409 CHECK(outer.upper->Maybe(Type::Internal())); | 628 case IrOpcode::kWord64Shr: |
| 410 CHECK(bounds(node).upper->IsContext()); | 629 case IrOpcode::kWord64Sar: |
| 411 break; | 630 case IrOpcode::kWord64Ror: |
| 412 } | 631 case IrOpcode::kWord64Equal: |
| 413 | 632 case IrOpcode::kInt32Add: |
| 414 case IrOpcode::kJSCallConstruct: | 633 case IrOpcode::kInt32AddWithOverflow: |
| 415 // Type is Receiver. | 634 case IrOpcode::kInt32Sub: |
| 416 CHECK(bounds(node).upper->Is(Type::Receiver())); | 635 case IrOpcode::kInt32SubWithOverflow: |
| 417 break; | 636 case IrOpcode::kInt32Mul: |
| 418 case IrOpcode::kJSCallFunction: | 637 case IrOpcode::kInt32MulHigh: |
| 419 case IrOpcode::kJSCallRuntime: | 638 case IrOpcode::kInt32Div: |
| 420 case IrOpcode::kJSYield: | 639 case IrOpcode::kInt32Mod: |
| 421 case IrOpcode::kJSDebugger: | 640 case IrOpcode::kInt32LessThan: |
| 422 // Type can be anything. | 641 case IrOpcode::kInt32LessThanOrEqual: |
| 423 CHECK(bounds(node).upper->Is(Type::Any())); | 642 case IrOpcode::kUint32Div: |
| 424 break; | 643 case IrOpcode::kUint32Mod: |
| 425 | 644 case IrOpcode::kUint32LessThan: |
| 426 // Simplified operators | 645 case IrOpcode::kUint32LessThanOrEqual: |
| 427 // ------------------------------- | 646 case IrOpcode::kInt64Add: |
| 428 case IrOpcode::kBooleanNot: | 647 case IrOpcode::kInt64Sub: |
| 429 // Boolean -> Boolean | 648 case IrOpcode::kInt64Mul: |
| 430 CHECK(bounds(Operand(node)).upper->Is(Type::Boolean())); | 649 case IrOpcode::kInt64Div: |
| 431 CHECK(bounds(node).upper->Is(Type::Boolean())); | 650 case IrOpcode::kInt64Mod: |
| 432 break; | 651 case IrOpcode::kInt64LessThan: |
| 433 case IrOpcode::kBooleanToNumber: | 652 case IrOpcode::kInt64LessThanOrEqual: |
| 434 // Boolean -> Number | 653 case IrOpcode::kUint64Div: |
| 435 CHECK(bounds(Operand(node)).upper->Is(Type::Boolean())); | 654 case IrOpcode::kUint64Mod: |
| 436 CHECK(bounds(node).upper->Is(Type::Number())); | 655 case IrOpcode::kUint64LessThan: |
| 437 break; | 656 case IrOpcode::kFloat64Add: |
| 438 case IrOpcode::kNumberEqual: | 657 case IrOpcode::kFloat64Sub: |
| 439 case IrOpcode::kNumberLessThan: | 658 case IrOpcode::kFloat64Mul: |
| 440 case IrOpcode::kNumberLessThanOrEqual: | 659 case IrOpcode::kFloat64Div: |
| 441 // (Number, Number) -> Boolean | 660 case IrOpcode::kFloat64Mod: |
| 442 CHECK(bounds(Operand(node, 0)).upper->Is(Type::Number())); | 661 case IrOpcode::kFloat64Sqrt: |
| 443 CHECK(bounds(Operand(node, 1)).upper->Is(Type::Number())); | 662 case IrOpcode::kFloat64Equal: |
| 444 CHECK(bounds(node).upper->Is(Type::Boolean())); | 663 case IrOpcode::kFloat64LessThan: |
| 445 break; | 664 case IrOpcode::kFloat64LessThanOrEqual: |
| 446 case IrOpcode::kNumberAdd: | 665 case IrOpcode::kTruncateInt64ToInt32: |
| 447 case IrOpcode::kNumberSubtract: | 666 case IrOpcode::kTruncateFloat64ToFloat32: |
| 448 case IrOpcode::kNumberMultiply: | 667 case IrOpcode::kTruncateFloat64ToInt32: |
| 449 case IrOpcode::kNumberDivide: | 668 case IrOpcode::kChangeInt32ToInt64: |
| 450 case IrOpcode::kNumberModulus: | 669 case IrOpcode::kChangeUint32ToUint64: |
| 451 // (Number, Number) -> Number | 670 case IrOpcode::kChangeInt32ToFloat64: |
| 452 CHECK(bounds(Operand(node, 0)).upper->Is(Type::Number())); | 671 case IrOpcode::kChangeUint32ToFloat64: |
| 453 CHECK(bounds(Operand(node, 1)).upper->Is(Type::Number())); | 672 case IrOpcode::kChangeFloat32ToFloat64: |
| 454 // TODO(rossberg): activate once we retype after opcode changes. | 673 case IrOpcode::kChangeFloat64ToInt32: |
| 455 // CHECK(bounds(node).upper->Is(Type::Number())); | 674 case IrOpcode::kChangeFloat64ToUint32: |
| 456 break; | 675 case IrOpcode::kLoadStackPointer: |
| 457 case IrOpcode::kNumberToInt32: | 676 // TODO(rossberg): Check. |
| 458 // Number -> Signed32 | 677 break; |
| 459 CHECK(bounds(Operand(node)).upper->Is(Type::Number())); | |
| 460 CHECK(bounds(node).upper->Is(Type::Signed32())); | |
| 461 break; | |
| 462 case IrOpcode::kNumberToUint32: | |
| 463 // Number -> Unsigned32 | |
| 464 CHECK(bounds(Operand(node)).upper->Is(Type::Number())); | |
| 465 CHECK(bounds(node).upper->Is(Type::Unsigned32())); | |
| 466 break; | |
| 467 case IrOpcode::kStringEqual: | |
| 468 case IrOpcode::kStringLessThan: | |
| 469 case IrOpcode::kStringLessThanOrEqual: | |
| 470 // (String, String) -> Boolean | |
| 471 CHECK(bounds(Operand(node, 0)).upper->Is(Type::String())); | |
| 472 CHECK(bounds(Operand(node, 1)).upper->Is(Type::String())); | |
| 473 CHECK(bounds(node).upper->Is(Type::Boolean())); | |
| 474 break; | |
| 475 case IrOpcode::kStringAdd: | |
| 476 // (String, String) -> String | |
| 477 CHECK(bounds(Operand(node, 0)).upper->Is(Type::String())); | |
| 478 CHECK(bounds(Operand(node, 1)).upper->Is(Type::String())); | |
| 479 CHECK(bounds(node).upper->Is(Type::String())); | |
| 480 break; | |
| 481 case IrOpcode::kReferenceEqual: { | |
| 482 // (Unique, Any) -> Boolean and | |
| 483 // (Any, Unique) -> Boolean | |
| 484 CHECK(bounds(Operand(node, 0)).upper->Is(Type::Unique()) || | |
| 485 bounds(Operand(node, 1)).upper->Is(Type::Unique())); | |
| 486 CHECK(bounds(node).upper->Is(Type::Boolean())); | |
| 487 break; | |
| 488 } | |
| 489 case IrOpcode::kObjectIsSmi: | |
| 490 CHECK(bounds(Operand(node)).upper->Is(Type::Any())); | |
| 491 CHECK(bounds(node).upper->Is(Type::Boolean())); | |
| 492 break; | |
| 493 case IrOpcode::kObjectIsNonNegativeSmi: | |
| 494 CHECK(bounds(Operand(node)).upper->Is(Type::Any())); | |
| 495 CHECK(bounds(node).upper->Is(Type::Boolean())); | |
| 496 break; | |
| 497 | |
| 498 case IrOpcode::kChangeTaggedToInt32: { | |
| 499 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32 | |
| 500 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
| 501 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged()); | |
| 502 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); | |
| 503 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
| 504 // CHECK(bounds(node).upper->Is(to)); | |
| 505 break; | |
| 506 } | |
| 507 case IrOpcode::kChangeTaggedToUint32: { | |
| 508 // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32 | |
| 509 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
| 510 // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged()); | |
| 511 // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32()); | |
| 512 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
| 513 // CHECK(bounds(node).upper->Is(to)); | |
| 514 break; | |
| 515 } | |
| 516 case IrOpcode::kChangeTaggedToFloat64: { | |
| 517 // Number /\ Tagged -> Number /\ UntaggedFloat64 | |
| 518 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
| 519 // Type* from = Type::Intersect(Type::Number(), Type::Tagged()); | |
| 520 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64()); | |
| 521 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
| 522 // CHECK(bounds(node).upper->Is(to)); | |
| 523 break; | |
| 524 } | |
| 525 case IrOpcode::kChangeInt32ToTagged: { | |
| 526 // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged | |
| 527 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
| 528 // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); | |
| 529 // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged()); | |
| 530 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
| 531 // CHECK(bounds(node).upper->Is(to)); | |
| 532 break; | |
| 533 } | |
| 534 case IrOpcode::kChangeUint32ToTagged: { | |
| 535 // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged | |
| 536 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
| 537 // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32()); | |
| 538 // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged()); | |
| 539 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
| 540 // CHECK(bounds(node).upper->Is(to)); | |
| 541 break; | |
| 542 } | |
| 543 case IrOpcode::kChangeFloat64ToTagged: { | |
| 544 // Number /\ UntaggedFloat64 -> Number /\ Tagged | |
| 545 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
| 546 // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64()); | |
| 547 // Type* to = Type::Intersect(Type::Number(), Type::Tagged()); | |
| 548 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
| 549 // CHECK(bounds(node).upper->Is(to)); | |
| 550 break; | |
| 551 } | |
| 552 case IrOpcode::kChangeBoolToBit: { | |
| 553 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1 | |
| 554 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
| 555 // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); | |
| 556 // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); | |
| 557 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
| 558 // CHECK(bounds(node).upper->Is(to)); | |
| 559 break; | |
| 560 } | |
| 561 case IrOpcode::kChangeBitToBool: { | |
| 562 // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr | |
| 563 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
| 564 // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); | |
| 565 // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); | |
| 566 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
| 567 // CHECK(bounds(node).upper->Is(to)); | |
| 568 break; | |
| 569 } | |
| 570 | |
| 571 case IrOpcode::kLoadField: | |
| 572 // Object -> fieldtype | |
| 573 // TODO(rossberg): activate once machine ops are typed. | |
| 574 // CHECK(bounds(Operand(node)).upper->Is(Type::Object())); | |
| 575 // CHECK(bounds(node).upper->Is(Field(node).type)); | |
| 576 break; | |
| 577 case IrOpcode::kLoadElement: | |
| 578 // Object -> elementtype | |
| 579 // TODO(rossberg): activate once machine ops are typed. | |
| 580 // CHECK(bounds(Operand(node)).upper->Is(Type::Object())); | |
| 581 // CHECK(bounds(node).upper->Is(Element(node).type)); | |
| 582 break; | |
| 583 case IrOpcode::kStoreField: | |
| 584 // (Object, fieldtype) -> _|_ | |
| 585 // TODO(rossberg): activate once machine ops are typed. | |
| 586 // CHECK(bounds(Operand(node, 0)).upper->Is(Type::Object())); | |
| 587 // CHECK(bounds(Operand(node, 1)).upper->Is(Field(node).type)); | |
| 588 CHECK(!NodeProperties::IsTyped(node)); | |
| 589 break; | |
| 590 case IrOpcode::kStoreElement: | |
| 591 // (Object, elementtype) -> _|_ | |
| 592 // TODO(rossberg): activate once machine ops are typed. | |
| 593 // CHECK(bounds(Operand(node, 0)).upper->Is(Type::Object())); | |
| 594 // CHECK(bounds(Operand(node, 1)).upper->Is(Element(node).type)); | |
| 595 CHECK(!NodeProperties::IsTyped(node)); | |
| 596 break; | |
| 597 | |
| 598 // Machine operators | |
| 599 // ----------------------- | |
| 600 case IrOpcode::kLoad: | |
| 601 case IrOpcode::kStore: | |
| 602 case IrOpcode::kWord32And: | |
| 603 case IrOpcode::kWord32Or: | |
| 604 case IrOpcode::kWord32Xor: | |
| 605 case IrOpcode::kWord32Shl: | |
| 606 case IrOpcode::kWord32Shr: | |
| 607 case IrOpcode::kWord32Sar: | |
| 608 case IrOpcode::kWord32Ror: | |
| 609 case IrOpcode::kWord32Equal: | |
| 610 case IrOpcode::kWord64And: | |
| 611 case IrOpcode::kWord64Or: | |
| 612 case IrOpcode::kWord64Xor: | |
| 613 case IrOpcode::kWord64Shl: | |
| 614 case IrOpcode::kWord64Shr: | |
| 615 case IrOpcode::kWord64Sar: | |
| 616 case IrOpcode::kWord64Ror: | |
| 617 case IrOpcode::kWord64Equal: | |
| 618 case IrOpcode::kInt32Add: | |
| 619 case IrOpcode::kInt32AddWithOverflow: | |
| 620 case IrOpcode::kInt32Sub: | |
| 621 case IrOpcode::kInt32SubWithOverflow: | |
| 622 case IrOpcode::kInt32Mul: | |
| 623 case IrOpcode::kInt32MulHigh: | |
| 624 case IrOpcode::kInt32Div: | |
| 625 case IrOpcode::kInt32Mod: | |
| 626 case IrOpcode::kInt32LessThan: | |
| 627 case IrOpcode::kInt32LessThanOrEqual: | |
| 628 case IrOpcode::kUint32Div: | |
| 629 case IrOpcode::kUint32Mod: | |
| 630 case IrOpcode::kUint32LessThan: | |
| 631 case IrOpcode::kUint32LessThanOrEqual: | |
| 632 case IrOpcode::kInt64Add: | |
| 633 case IrOpcode::kInt64Sub: | |
| 634 case IrOpcode::kInt64Mul: | |
| 635 case IrOpcode::kInt64Div: | |
| 636 case IrOpcode::kInt64Mod: | |
| 637 case IrOpcode::kInt64LessThan: | |
| 638 case IrOpcode::kInt64LessThanOrEqual: | |
| 639 case IrOpcode::kUint64Div: | |
| 640 case IrOpcode::kUint64Mod: | |
| 641 case IrOpcode::kUint64LessThan: | |
| 642 case IrOpcode::kFloat64Add: | |
| 643 case IrOpcode::kFloat64Sub: | |
| 644 case IrOpcode::kFloat64Mul: | |
| 645 case IrOpcode::kFloat64Div: | |
| 646 case IrOpcode::kFloat64Mod: | |
| 647 case IrOpcode::kFloat64Sqrt: | |
| 648 case IrOpcode::kFloat64Equal: | |
| 649 case IrOpcode::kFloat64LessThan: | |
| 650 case IrOpcode::kFloat64LessThanOrEqual: | |
| 651 case IrOpcode::kTruncateInt64ToInt32: | |
| 652 case IrOpcode::kTruncateFloat64ToFloat32: | |
| 653 case IrOpcode::kTruncateFloat64ToInt32: | |
| 654 case IrOpcode::kChangeInt32ToInt64: | |
| 655 case IrOpcode::kChangeUint32ToUint64: | |
| 656 case IrOpcode::kChangeInt32ToFloat64: | |
| 657 case IrOpcode::kChangeUint32ToFloat64: | |
| 658 case IrOpcode::kChangeFloat32ToFloat64: | |
| 659 case IrOpcode::kChangeFloat64ToInt32: | |
| 660 case IrOpcode::kChangeFloat64ToUint32: | |
| 661 case IrOpcode::kLoadStackPointer: | |
| 662 // TODO(rossberg): Check. | |
| 663 break; | |
| 664 } | |
| 665 } | 678 } |
| 666 | 679 |
| 667 return GenericGraphVisit::CONTINUE; | 680 return GenericGraphVisit::CONTINUE; |
| 668 } | 681 } |
| 669 | 682 |
| 670 | 683 |
| 671 void Verifier::Run(Graph* graph, Typing typing) { | 684 void Verifier::Run(Graph* graph, Typing typing) { |
| 672 Visitor visitor(graph->zone(), typing); | 685 Visitor visitor(graph->zone(), typing); |
| 673 CHECK_NE(NULL, graph->start()); | 686 CHECK_NE(NULL, graph->start()); |
| 674 CHECK_NE(NULL, graph->end()); | 687 CHECK_NE(NULL, graph->end()); |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 // Check inputs for all nodes in the block. | 923 // Check inputs for all nodes in the block. |
| 911 for (size_t i = 0; i < block->NodeCount(); i++) { | 924 for (size_t i = 0; i < block->NodeCount(); i++) { |
| 912 Node* node = block->NodeAt(i); | 925 Node* node = block->NodeAt(i); |
| 913 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1); | 926 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1); |
| 914 } | 927 } |
| 915 } | 928 } |
| 916 } | 929 } |
| 917 } | 930 } |
| 918 } | 931 } |
| 919 } // namespace v8::internal::compiler | 932 } // namespace v8::internal::compiler |
| OLD | NEW |