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

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

Issue 509343002: Better typing and type verification (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 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
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, bool is_typed)
49 : reached_from_start(NodeSet::key_compare(), 50 : zone(z),
50 NodeSet::allocator_type(zone)), 51 with_typing(is_typed),
52 reached_from_start(NodeSet::key_compare(),
53 NodeSet::allocator_type(z)),
51 reached_from_end(NodeSet::key_compare(), 54 reached_from_end(NodeSet::key_compare(),
52 NodeSet::allocator_type(zone)) {} 55 NodeSet::allocator_type(z)) {}
53 56
54 // Fulfills the PreNodeCallback interface. 57 // Fulfills the PreNodeCallback interface.
55 GenericGraphVisit::Control Pre(Node* node); 58 GenericGraphVisit::Control Pre(Node* node);
56 59
60 Zone* zone;
61 bool with_typing;
57 bool from_start; 62 bool from_start;
58 NodeSet reached_from_start; 63 NodeSet reached_from_start;
59 NodeSet reached_from_end; 64 NodeSet reached_from_end;
65
66 private:
67 // TODO(rossberg): Get rid of these once we got rid of NodeProperties.
68 Bounds bounds(Node* node) {
69 return NodeProperties::GetBounds(node);
70 }
71 Node* operand(Node* node, int i = 0) {
72 return NodeProperties::GetValueInput(node, i);
73 }
74 FieldAccess field(Node* node) {
75 DCHECK(node->opcode() == IrOpcode::kLoadField ||
76 node->opcode() == IrOpcode::kStoreField);
77 return static_cast<Operator1<FieldAccess>*>(node->op())->parameter();
78 }
79 ElementAccess element(Node* node) {
80 DCHECK(node->opcode() == IrOpcode::kLoadElement ||
81 node->opcode() == IrOpcode::kStoreElement);
82 return static_cast<Operator1<ElementAccess>*>(node->op())->parameter();
83 }
60 }; 84 };
61 85
62 86
63 GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) { 87 GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
64 int value_count = OperatorProperties::GetValueInputCount(node->op()); 88 int value_count = OperatorProperties::GetValueInputCount(node->op());
65 int context_count = OperatorProperties::GetContextInputCount(node->op()); 89 int context_count = OperatorProperties::GetContextInputCount(node->op());
66 int frame_state_count = 90 int frame_state_count =
67 OperatorProperties::GetFrameStateInputCount(node->op()); 91 OperatorProperties::GetFrameStateInputCount(node->op());
68 int effect_count = OperatorProperties::GetEffectInputCount(node->op()); 92 int effect_count = OperatorProperties::GetEffectInputCount(node->op());
69 int control_count = OperatorProperties::GetControlInputCount(node->op()); 93 int control_count = OperatorProperties::GetControlInputCount(node->op());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 // Verify all successors are projections if multiple value outputs exist. 132 // Verify all successors are projections if multiple value outputs exist.
109 if (OperatorProperties::GetValueOutputCount(node->op()) > 1) { 133 if (OperatorProperties::GetValueOutputCount(node->op()) > 1) {
110 Node::Uses uses = node->uses(); 134 Node::Uses uses = node->uses();
111 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) { 135 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
112 CHECK(!NodeProperties::IsValueEdge(it.edge()) || 136 CHECK(!NodeProperties::IsValueEdge(it.edge()) ||
113 (*it)->opcode() == IrOpcode::kProjection || 137 (*it)->opcode() == IrOpcode::kProjection ||
114 (*it)->opcode() == IrOpcode::kParameter); 138 (*it)->opcode() == IrOpcode::kParameter);
115 } 139 }
116 } 140 }
117 141
118 switch (node->opcode()) { 142 if (with_typing) {
119 case IrOpcode::kStart: 143 // Multiple value outputs are currently typed as Internal.
120 // Start has no inputs. 144 // TODO(rossberg): Introduce tuple types.
121 CHECK_EQ(0, input_count); 145 if (OperatorProperties::GetValueOutputCount(node->op()) > 1) {
122 break; 146 CHECK(bounds(node).upper->Is(Type::Internal()));
123 case IrOpcode::kEnd:
124 // End has no outputs.
125 CHECK(!OperatorProperties::HasValueOutput(node->op()));
126 CHECK(!OperatorProperties::HasEffectOutput(node->op()));
127 CHECK(!OperatorProperties::HasControlOutput(node->op()));
128 break;
129 case IrOpcode::kDead:
130 // Dead is never connected to the graph.
131 UNREACHABLE();
132 case IrOpcode::kBranch: {
133 // Branch uses are IfTrue and IfFalse.
134 Node::Uses uses = node->uses();
135 bool got_true = false, got_false = false;
136 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
137 CHECK(((*it)->opcode() == IrOpcode::kIfTrue && !got_true) ||
138 ((*it)->opcode() == IrOpcode::kIfFalse && !got_false));
139 if ((*it)->opcode() == IrOpcode::kIfTrue) got_true = true;
140 if ((*it)->opcode() == IrOpcode::kIfFalse) got_false = true;
141 }
142 // TODO(rossberg): Currently fails for various tests.
143 // CHECK(got_true && got_false);
144 break;
145 } 147 }
146 case IrOpcode::kIfTrue: 148
147 case IrOpcode::kIfFalse: 149 switch (node->opcode()) {
148 CHECK_EQ(IrOpcode::kBranch, 150 // Control operators
149 NodeProperties::GetControlInput(node, 0)->opcode()); 151 // -----------------
150 break; 152 case IrOpcode::kStart:
151 case IrOpcode::kLoop: 153 // Start has no inputs.
152 case IrOpcode::kMerge: 154 CHECK_EQ(0, input_count);
153 break; 155 // Type is Internal.
154 case IrOpcode::kReturn: 156 CHECK(bounds(node).upper->Is(Type::Internal()));
155 // TODO(rossberg): check successor is End 157 break;
156 break; 158 case IrOpcode::kEnd:
157 case IrOpcode::kThrow: 159 // End has no outputs.
158 // TODO(rossberg): what are the constraints on these? 160 CHECK(!OperatorProperties::HasValueOutput(node->op()));
159 break; 161 CHECK(!OperatorProperties::HasEffectOutput(node->op()));
160 case IrOpcode::kParameter: { 162 CHECK(!OperatorProperties::HasControlOutput(node->op()));
161 // Parameters have the start node as inputs. 163 break;
162 CHECK_EQ(1, input_count); 164 case IrOpcode::kDead:
163 CHECK_EQ(IrOpcode::kStart, 165 // Dead is never connected to the graph.
164 NodeProperties::GetValueInput(node, 0)->opcode()); 166 UNREACHABLE();
165 // Parameter has an input that produces enough values. 167 case IrOpcode::kBranch: {
166 int index = static_cast<Operator1<int>*>(node->op())->parameter(); 168 // Ignore dead branches, because they may violate well-formedness.
167 Node* input = NodeProperties::GetValueInput(node, 0); 169 // TODO(rossberg): Can we avoid this?
168 // Currently, parameter indices start at -1 instead of 0. 170 Node* parent = NodeProperties::GetControlInput(node, 0);
169 CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index + 1); 171 if (parent->opcode() == IrOpcode::kDead) break;
170 break; 172 // Branch uses are IfTrue and IfFalse.
173 Node::Uses uses = node->uses();
174 bool count_true = 0, count_false = 0;
175 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
176 CHECK((*it)->opcode() == IrOpcode::kIfTrue ||
177 (*it)->opcode() == IrOpcode::kIfFalse);
178 if ((*it)->opcode() == IrOpcode::kIfTrue) ++count_true;
179 if ((*it)->opcode() == IrOpcode::kIfFalse) ++count_false;
180 }
181 CHECK(count_true == 1 && count_false == 1);
182 break;
183 }
184 case IrOpcode::kIfTrue:
185 case IrOpcode::kIfFalse:
186 CHECK_EQ(IrOpcode::kBranch,
187 NodeProperties::GetControlInput(node, 0)->opcode());
188 break;
189 case IrOpcode::kLoop:
190 case IrOpcode::kMerge:
191 break;
192 case IrOpcode::kReturn:
193 // TODO(rossberg): check successor is End
194 break;
195 case IrOpcode::kThrow:
196 // TODO(rossberg): what are the constraints on these?
197 break;
198
199 // Common operators
200 // ----------------
201 case IrOpcode::kParameter: {
202 // Parameters have the start node as inputs.
203 CHECK_EQ(1, input_count);
204 CHECK_EQ(IrOpcode::kStart,
205 NodeProperties::GetValueInput(node, 0)->opcode());
206 // Parameter has an input that produces enough values.
207 int index = static_cast<Operator1<int>*>(node->op())->parameter();
208 Node* input = NodeProperties::GetValueInput(node, 0);
209 // Currently, parameter indices start at -1 instead of 0.
210 CHECK_GT(
211 OperatorProperties::GetValueOutputCount(input->op()), index + 1);
212 // Type can be anything.
213 CHECK(bounds(node).upper->Is(Type::Any()));
214 break;
215 }
216 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant?
217 // Constants have no inputs.
218 CHECK_EQ(0, input_count);
219 // Type is a 32 bit integer, signed or unsigned.
220 CHECK(bounds(node).upper->Is(Type::Integral32()));
221 break;
222 case IrOpcode::kInt64Constant: // Close enough...
223 case IrOpcode::kFloat64Constant:
224 case IrOpcode::kNumberConstant:
225 // Constants have no inputs.
226 CHECK_EQ(0, input_count);
227 // Type is a number.
228 CHECK(bounds(node).upper->Is(Type::Number()));
229 break;
230 case IrOpcode::kHeapConstant:
231 // Constants have no inputs.
232 CHECK_EQ(0, input_count);
233 // Type can be anything represented as a heap pointer.
234 CHECK(bounds(node).upper->Is(Type::TaggedPtr()));
235 break;
236 case IrOpcode::kExternalConstant:
237 // Constants have no inputs.
238 CHECK_EQ(0, input_count);
239 // Type is considered internal.
240 CHECK(bounds(node).upper->Is(Type::Internal()));
241 break;
242 case IrOpcode::kProjection: {
243 // Projection has an input that produces enough values.
244 int index = static_cast<Operator1<int>*>(node->op())->parameter();
245 Node* input = NodeProperties::GetValueInput(node, 0);
246 CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index);
247 // Type can be anything.
248 // TODO(rossberg): Introduce tuple types for this.
249 CHECK(bounds(node).upper->Is(Type::Any()));
250 break;
251 }
252 case IrOpcode::kPhi: {
253 // Phi input count matches parent control node.
254 CHECK_EQ(1, control_count);
255 Node* control = NodeProperties::GetControlInput(node, 0);
256 CHECK_EQ(value_count,
257 OperatorProperties::GetControlInputCount(control->op()));
258 // Type must be subsumed by all input types.
259 for (int i = 0; i < value_count; ++i) {
260 CHECK(bounds(node).lower->Is(bounds(operand(node, i)).lower));
261 CHECK(bounds(operand(node, i)).upper->Is(bounds(node).upper));
262 }
263 break;
264 }
265 case IrOpcode::kEffectPhi: {
266 // EffectPhi input count matches parent control node.
267 CHECK_EQ(1, control_count);
268 Node* control = NodeProperties::GetControlInput(node, 0);
269 CHECK_EQ(effect_count,
270 OperatorProperties::GetControlInputCount(control->op()));
271 break;
272 }
273 case IrOpcode::kControlEffect:
274 case IrOpcode::kValueEffect:
275 // TODO(rossberg): what are the constraints on these?
276 break;
277 case IrOpcode::kFinish: {
278 // TODO(rossberg): what are the constraints on these?
279 // Type must be subsumed by input type.
280 CHECK(bounds(operand(node)).lower->Is(bounds(node).lower));
281 CHECK(bounds(operand(node)).upper->Is(bounds(node).upper));
282 break;
283 }
284 case IrOpcode::kLazyDeoptimization:
285 // TODO(jarin): what are the constraints on these?
286 break;
287 case IrOpcode::kDeoptimize:
288 // TODO(jarin): what are the constraints on these?
289 break;
290 case IrOpcode::kFrameState:
291 // TODO(jarin): what are the constraints on these?
292 break;
293 case IrOpcode::kStateValues:
294 // TODO(jarin): what are the constraints on these?
295 break;
296 case IrOpcode::kCall:
297 // TODO(rossberg): what are the constraints on these?
298 break;
299 case IrOpcode::kContinuation:
300 // TODO(jarin): 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 case IrOpcode::kJSSubtract:
329 case IrOpcode::kJSMultiply:
330 case IrOpcode::kJSDivide:
331 case IrOpcode::kJSModulus:
332 // Type is Number.
333 CHECK(bounds(node).upper->Is(Type::Number()));
334 break;
335
336 case IrOpcode::kJSToBoolean:
337 // Type is Boolean.
338 CHECK(bounds(node).upper->Is(Type::Boolean()));
339 break;
340 case IrOpcode::kJSToNumber:
341 // Type is Number.
342 CHECK(bounds(node).upper->Is(Type::Number()));
343 break;
344 case IrOpcode::kJSToString:
345 // Type is String.
346 CHECK(bounds(node).upper->Is(Type::String()));
347 break;
348 case IrOpcode::kJSToName:
349 // Type is Name.
350 CHECK(bounds(node).upper->Is(Type::Name()));
351 break;
352 case IrOpcode::kJSToObject:
353 // Type is Receiver.
354 CHECK(bounds(node).upper->Is(Type::Receiver()));
355 break;
356
357 case IrOpcode::kJSCreate:
358 // Type is Object.
359 CHECK(bounds(node).upper->Is(Type::Object()));
360 break;
361 case IrOpcode::kJSLoadProperty:
362 case IrOpcode::kJSLoadNamed:
363 // Type can be anything.
364 CHECK(bounds(node).upper->Is(Type::Any()));
365 break;
366 case IrOpcode::kJSStoreProperty:
367 case IrOpcode::kJSStoreNamed:
368 // Type is empty.
369 CHECK(bounds(node).upper->Is(Type::None()));
370 break;
371 case IrOpcode::kJSDeleteProperty:
372 case IrOpcode::kJSHasProperty:
373 case IrOpcode::kJSInstanceOf:
374 // Type is Boolean.
375 CHECK(bounds(node).upper->Is(Type::Boolean()));
376 break;
377 case IrOpcode::kJSTypeOf:
378 // Type is String.
379 CHECK(bounds(node).upper->Is(Type::String()));
380 break;
381
382 case IrOpcode::kJSLoadContext:
383 // Type can be anything.
384 CHECK(bounds(node).upper->Is(Type::Any()));
385 break;
386 case IrOpcode::kJSStoreContext:
387 // Type is empty.
388 CHECK(bounds(node).upper->Is(Type::None()));
389 break;
390 case IrOpcode::kJSCreateFunctionContext:
391 case IrOpcode::kJSCreateCatchContext:
392 case IrOpcode::kJSCreateWithContext:
393 case IrOpcode::kJSCreateBlockContext:
394 case IrOpcode::kJSCreateModuleContext:
395 case IrOpcode::kJSCreateGlobalContext: {
396 // Type is Context, and operand is Internal.
397 Bounds outer = bounds(NodeProperties::GetContextInput(node));
398 // TODO(rossberg): This should really be Is(Internal), but the typer
399 // currently can't do backwards propagation.
400 CHECK(outer.upper->Maybe(Type::Internal()));
401 CHECK(bounds(node).upper->Is(Type::Context(outer.upper, zone)));
402 CHECK(bounds(node).lower->Is(Type::Context(outer.lower, zone)));
403 break;
404 }
405
406 case IrOpcode::kJSCallConstruct:
407 // Type is Receiver.
408 CHECK(bounds(node).upper->Is(Type::Receiver()));
409 break;
410 case IrOpcode::kJSCallFunction:
411 case IrOpcode::kJSCallRuntime:
412 case IrOpcode::kJSYield:
413 case IrOpcode::kJSDebugger:
414 // Type can be anything.
415 CHECK(bounds(node).upper->Is(Type::Any()));
416 break;
417
418 // Simplified operators
419 // -------------------------------
420 case IrOpcode::kBooleanNot:
421 // Boolean -> Boolean
422 CHECK(bounds(operand(node)).upper->Is(Type::Boolean()));
423 CHECK(bounds(node).upper->Is(Type::Boolean()));
424 break;
425 case IrOpcode::kNumberEqual:
426 case IrOpcode::kNumberLessThan:
427 case IrOpcode::kNumberLessThanOrEqual:
428 // (Number, Number) -> Boolean
429 CHECK(bounds(operand(node, 0)).upper->Is(Type::Number()));
430 CHECK(bounds(operand(node, 1)).upper->Is(Type::Number()));
431 CHECK(bounds(node).upper->Is(Type::Boolean()));
432 break;
433 case IrOpcode::kNumberAdd:
434 case IrOpcode::kNumberSubtract:
435 case IrOpcode::kNumberMultiply:
436 case IrOpcode::kNumberDivide:
437 case IrOpcode::kNumberModulus:
438 // (Number, Number) -> Number
439 CHECK(bounds(operand(node, 0)).upper->Is(Type::Number()));
440 CHECK(bounds(operand(node, 1)).upper->Is(Type::Number()));
441 CHECK(bounds(node).upper->Is(Type::Number()));
442 break;
443 case IrOpcode::kNumberToInt32:
444 // Number -> Signed32
445 CHECK(bounds(operand(node)).upper->Is(Type::Number()));
446 CHECK(bounds(node).upper->Is(Type::Signed32()));
447 break;
448 case IrOpcode::kNumberToUint32:
449 // Number -> Unsigned32
450 CHECK(bounds(operand(node)).upper->Is(Type::Number()));
451 CHECK(bounds(node).upper->Is(Type::Unsigned32()));
452 break;
453 case IrOpcode::kStringEqual:
454 case IrOpcode::kStringLessThan:
455 case IrOpcode::kStringLessThanOrEqual:
456 // (String, String) -> Boolean
457 CHECK(bounds(operand(node, 0)).upper->Is(Type::String()));
458 CHECK(bounds(operand(node, 1)).upper->Is(Type::String()));
459 CHECK(bounds(node).upper->Is(Type::Boolean()));
460 break;
461 case IrOpcode::kStringAdd:
462 // (String, String) -> String
463 CHECK(bounds(operand(node, 0)).upper->Is(Type::String()));
464 CHECK(bounds(operand(node, 1)).upper->Is(Type::String()));
465 CHECK(bounds(node).upper->Is(Type::String()));
466 break;
467 case IrOpcode::kReferenceEqual: {
468 // (Unique, Unique) -> Boolean
469 CHECK(bounds(operand(node, 0)).upper->Is(Type::Unique()));
470 CHECK(bounds(operand(node, 1)).upper->Is(Type::Unique()));
471 CHECK(bounds(node).upper->Is(Type::Boolean()));
472 break;
473 }
474
475 case IrOpcode::kChangeTaggedToInt32: {
476 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
477 Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
478 Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
479 CHECK(bounds(operand(node)).upper->Is(from));
480 CHECK(bounds(node).upper->Is(to));
481 break;
482 }
483 case IrOpcode::kChangeTaggedToUint32: {
484 // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32
485 Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged());
486 Type* to = Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32());
487 CHECK(bounds(operand(node)).upper->Is(from));
488 CHECK(bounds(node).upper->Is(to));
489 break;
490 }
491 case IrOpcode::kChangeTaggedToFloat64: {
492 // Number /\ Tagged -> Number /\ UntaggedFloat64
493 Type* from = Type::Intersect(Type::Number(), Type::Tagged());
494 Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
495 CHECK(bounds(operand(node)).upper->Is(from));
496 CHECK(bounds(node).upper->Is(to));
497 break;
498 }
499 case IrOpcode::kChangeInt32ToTagged: {
500 // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged
501 Type* from = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
502 Type* to = Type::Intersect(Type::Signed32(), Type::Tagged());
503 CHECK(bounds(operand(node)).upper->Is(from));
504 CHECK(bounds(node).upper->Is(to));
505 break;
506 }
507 case IrOpcode::kChangeUint32ToTagged: {
508 // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged
509 Type* from = Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32());
510 Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged());
511 CHECK(bounds(operand(node)).upper->Is(from));
512 CHECK(bounds(node).upper->Is(to));
513 break;
514 }
515 case IrOpcode::kChangeFloat64ToTagged: {
516 // Number /\ UntaggedFloat64 -> Number /\ Tagged
517 Type* from = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
518 Type* to = Type::Intersect(Type::Number(), Type::Tagged());
519 CHECK(bounds(operand(node)).upper->Is(from));
520 CHECK(bounds(node).upper->Is(to));
521 break;
522 }
523 case IrOpcode::kChangeBoolToBit: {
524 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
525 Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
526 Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
527 CHECK(bounds(operand(node)).upper->Is(from));
528 CHECK(bounds(node).upper->Is(to));
529 break;
530 }
531 case IrOpcode::kChangeBitToBool: {
532 // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
533 Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
534 Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
535 CHECK(bounds(operand(node)).upper->Is(from));
536 CHECK(bounds(node).upper->Is(to));
537 break;
538 }
539
540 case IrOpcode::kLoadField:
541 // Object -> fieldtype
542 CHECK(bounds(operand(node)).upper->Is(Type::Object()));
543 CHECK(bounds(node).upper->Is(field(node).type));
544 break;
545 case IrOpcode::kLoadElement:
546 // Object -> elementtype
547 CHECK(bounds(operand(node)).upper->Is(Type::Object()));
548 CHECK(bounds(node).upper->Is(element(node).type));
549 break;
550 case IrOpcode::kStoreField:
551 // (Object, fieldtype) -> _|_
552 CHECK(bounds(operand(node, 0)).upper->Is(Type::Object()));
553 CHECK(bounds(operand(node, 1)).upper->Is(field(node).type));
554 CHECK(bounds(node).upper->Is(Type::None()));
555 break;
556 case IrOpcode::kStoreElement:
557 // (Object, elementtype) -> _|_
558 CHECK(bounds(operand(node, 0)).upper->Is(Type::Object()));
559 CHECK(bounds(operand(node, 1)).upper->Is(element(node).type));
560 CHECK(bounds(node).upper->Is(Type::None()));
561 break;
562
563 // Machine operators
564 // -----------------------
565 case IrOpcode::kLoad:
566 case IrOpcode::kStore:
567 case IrOpcode::kWord32And:
568 case IrOpcode::kWord32Or:
569 case IrOpcode::kWord32Xor:
570 case IrOpcode::kWord32Shl:
571 case IrOpcode::kWord32Shr:
572 case IrOpcode::kWord32Sar:
573 case IrOpcode::kWord32Ror:
574 case IrOpcode::kWord32Equal:
575 case IrOpcode::kWord64And:
576 case IrOpcode::kWord64Or:
577 case IrOpcode::kWord64Xor:
578 case IrOpcode::kWord64Shl:
579 case IrOpcode::kWord64Shr:
580 case IrOpcode::kWord64Sar:
581 case IrOpcode::kWord64Ror:
582 case IrOpcode::kWord64Equal:
583 case IrOpcode::kInt32Add:
584 case IrOpcode::kInt32AddWithOverflow:
585 case IrOpcode::kInt32Sub:
586 case IrOpcode::kInt32SubWithOverflow:
587 case IrOpcode::kInt32Mul:
588 case IrOpcode::kInt32Div:
589 case IrOpcode::kInt32UDiv:
590 case IrOpcode::kInt32Mod:
591 case IrOpcode::kInt32UMod:
592 case IrOpcode::kInt32LessThan:
593 case IrOpcode::kInt32LessThanOrEqual:
594 case IrOpcode::kUint32LessThan:
595 case IrOpcode::kUint32LessThanOrEqual:
596 case IrOpcode::kInt64Add:
597 case IrOpcode::kInt64Sub:
598 case IrOpcode::kInt64Mul:
599 case IrOpcode::kInt64Div:
600 case IrOpcode::kInt64UDiv:
601 case IrOpcode::kInt64Mod:
602 case IrOpcode::kInt64UMod:
603 case IrOpcode::kInt64LessThan:
604 case IrOpcode::kInt64LessThanOrEqual:
605 case IrOpcode::kFloat64Add:
606 case IrOpcode::kFloat64Sub:
607 case IrOpcode::kFloat64Mul:
608 case IrOpcode::kFloat64Div:
609 case IrOpcode::kFloat64Mod:
610 case IrOpcode::kFloat64Equal:
611 case IrOpcode::kFloat64LessThan:
612 case IrOpcode::kFloat64LessThanOrEqual:
613 case IrOpcode::kTruncateInt64ToInt32:
614 case IrOpcode::kTruncateFloat64ToInt32:
615 case IrOpcode::kChangeInt32ToInt64:
616 case IrOpcode::kChangeUint32ToUint64:
617 case IrOpcode::kChangeInt32ToFloat64:
618 case IrOpcode::kChangeUint32ToFloat64:
619 case IrOpcode::kChangeFloat64ToInt32:
620 case IrOpcode::kChangeFloat64ToUint32:
621 // TODO(rossberg): Check.
622 break;
171 } 623 }
172 case IrOpcode::kInt32Constant:
173 case IrOpcode::kInt64Constant:
174 case IrOpcode::kFloat64Constant:
175 case IrOpcode::kExternalConstant:
176 case IrOpcode::kNumberConstant:
177 case IrOpcode::kHeapConstant:
178 // Constants have no inputs.
179 CHECK_EQ(0, input_count);
180 break;
181 case IrOpcode::kPhi: {
182 // Phi input count matches parent control node.
183 CHECK_EQ(1, control_count);
184 Node* control = NodeProperties::GetControlInput(node, 0);
185 CHECK_EQ(value_count,
186 OperatorProperties::GetControlInputCount(control->op()));
187 break;
188 }
189 case IrOpcode::kEffectPhi: {
190 // EffectPhi input count matches parent control node.
191 CHECK_EQ(1, control_count);
192 Node* control = NodeProperties::GetControlInput(node, 0);
193 CHECK_EQ(effect_count,
194 OperatorProperties::GetControlInputCount(control->op()));
195 break;
196 }
197 case IrOpcode::kLazyDeoptimization:
198 // TODO(jarin): what are the constraints on these?
199 break;
200 case IrOpcode::kDeoptimize:
201 // TODO(jarin): what are the constraints on these?
202 break;
203 case IrOpcode::kFrameState:
204 // TODO(jarin): what are the constraints on these?
205 break;
206 case IrOpcode::kCall:
207 // TODO(rossberg): what are the constraints on these?
208 break;
209 case IrOpcode::kContinuation:
210 // TODO(jarin): what are the constraints on these?
211 break;
212 case IrOpcode::kProjection: {
213 // Projection has an input that produces enough values.
214 int index = static_cast<Operator1<int>*>(node->op())->parameter();
215 Node* input = NodeProperties::GetValueInput(node, 0);
216 CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index);
217 break;
218 }
219 default:
220 // TODO(rossberg): Check other node kinds.
221 break;
222 } 624 }
223 625
224 if (from_start) { 626 if (from_start) {
225 reached_from_start.insert(node); 627 reached_from_start.insert(node);
226 } else { 628 } else {
227 reached_from_end.insert(node); 629 reached_from_end.insert(node);
228 } 630 }
229 631
230 return GenericGraphVisit::CONTINUE; 632 return GenericGraphVisit::CONTINUE;
231 } 633 }
232 634
233 635
234 void Verifier::Run(Graph* graph) { 636 void Verifier::Run(Graph* graph) {
235 Visitor visitor(graph->zone()); 637 Visitor visitor(graph->zone(), graph->is_typed());
236 638
237 CHECK_NE(NULL, graph->start()); 639 CHECK_NE(NULL, graph->start());
238 visitor.from_start = true; 640 visitor.from_start = true;
239 graph->VisitNodeUsesFromStart(&visitor); 641 graph->VisitNodeUsesFromStart(&visitor);
240 CHECK_NE(NULL, graph->end()); 642 CHECK_NE(NULL, graph->end());
241 visitor.from_start = false; 643 visitor.from_start = false;
242 graph->VisitNodeInputsFromEnd(&visitor); 644 graph->VisitNodeInputsFromEnd(&visitor);
243 645
244 // All control nodes reachable from end are reachable from start. 646 // All control nodes reachable from end are reachable from start.
245 for (NodeSet::iterator it = visitor.reached_from_end.begin(); 647 for (NodeSet::iterator it = visitor.reached_from_end.begin();
246 it != visitor.reached_from_end.end(); ++it) { 648 it != visitor.reached_from_end.end(); ++it) {
247 CHECK(!NodeProperties::IsControl(*it) || 649 CHECK(!NodeProperties::IsControl(*it) ||
248 visitor.reached_from_start.count(*it)); 650 visitor.reached_from_start.count(*it));
249 } 651 }
250 } 652 }
251 653
252 654
655 // -----------------------------------------------------------------------------
656
253 static bool HasDominatingDef(Schedule* schedule, Node* node, 657 static bool HasDominatingDef(Schedule* schedule, Node* node,
254 BasicBlock* container, BasicBlock* use_block, 658 BasicBlock* container, BasicBlock* use_block,
255 int use_pos) { 659 int use_pos) {
256 BasicBlock* block = use_block; 660 BasicBlock* block = use_block;
257 while (true) { 661 while (true) {
258 while (use_pos >= 0) { 662 while (use_pos >= 0) {
259 if (block->nodes_[use_pos] == node) return true; 663 if (block->nodes_[use_pos] == node) return true;
260 use_pos--; 664 use_pos--;
261 } 665 }
262 block = schedule->dominator(block); 666 block = schedule->dominator(block);
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 // Check inputs for all nodes in the block. 847 // Check inputs for all nodes in the block.
444 for (size_t i = 0; i < block->nodes_.size(); i++) { 848 for (size_t i = 0; i < block->nodes_.size(); i++) {
445 Node* node = block->nodes_[i]; 849 Node* node = block->nodes_[i];
446 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1); 850 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1);
447 } 851 }
448 } 852 }
449 } 853 }
450 } 854 }
451 } 855 }
452 } // namespace v8::internal::compiler 856 } // namespace v8::internal::compiler
OLDNEW
« src/compiler/opcodes.h ('K') | « src/compiler/typer.cc ('k') | src/types.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698