Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/compiler/verifier.cc

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

Powered by Google App Engine
This is Rietveld 408576698