Source/JavaScriptCore:
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGValidate.cpp
1 /*
2  * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGValidate.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "CodeBlockWithJITType.h"
32 #include "DFGClobberize.h"
33 #include "DFGClobbersExitState.h"
34 #include "DFGMayExit.h"
35 #include "JSCInlines.h"
36 #include <wtf/Assertions.h>
37 #include <wtf/BitVector.h>
38
39 namespace JSC { namespace DFG {
40
41 namespace {
42
43 class Validate {
44 public:
45     Validate(Graph& graph, GraphDumpMode graphDumpMode, CString graphDumpBeforePhase)
46         : m_graph(graph)
47         , m_graphDumpMode(graphDumpMode)
48         , m_graphDumpBeforePhase(graphDumpBeforePhase)
49     {
50     }
51     
52     #define VALIDATE(context, assertion) do { \
53         if (!(assertion)) { \
54             startCrashing(); \
55             dataLogF("\n\n\nAt "); \
56             reportValidationContext context; \
57             dataLogF(": validation failed: %s (%s:%d).\n", #assertion, __FILE__, __LINE__); \
58             dumpGraphIfAppropriate(); \
59             WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
60             CRASH(); \
61         } \
62     } while (0)
63     
64     #define V_EQUAL(context, left, right) do { \
65         if (left != right) { \
66             startCrashing(); \
67             dataLogF("\n\n\nAt "); \
68             reportValidationContext context; \
69             dataLogF(": validation failed: (%s = ", #left); \
70             dataLog(left); \
71             dataLogF(") == (%s = ", #right); \
72             dataLog(right); \
73             dataLogF(") (%s:%d).\n", __FILE__, __LINE__); \
74             dumpGraphIfAppropriate(); \
75             WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #left " == " #right); \
76             CRASH(); \
77         } \
78     } while (0)
79
80     #define notSet (static_cast<size_t>(-1))
81         
82     void validate()
83     {
84         // NB. This code is not written for performance, since it is not intended to run
85         // in release builds.
86
87         // Validate that all local variables at the head of the root block are dead.
88         BasicBlock* root = m_graph.block(0);
89         for (unsigned i = 0; i < root->variablesAtHead.numberOfLocals(); ++i)
90             V_EQUAL((virtualRegisterForLocal(i), root), static_cast<Node*>(0), root->variablesAtHead.local(i));
91         
92         // Validate ref counts and uses.
93         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
94             BasicBlock* block = m_graph.block(blockIndex);
95             if (!block)
96                 continue;
97             VALIDATE((block), block->isReachable);
98             for (size_t i = 0; i < block->numNodes(); ++i)
99                 m_myRefCounts.add(block->node(i), 0);
100         }
101         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
102             BasicBlock* block = m_graph.block(blockIndex);
103             if (!block)
104                 continue;
105             for (size_t i = 0; i < block->numNodes(); ++i) {
106                 Node* node = block->node(i);
107                 m_acceptableNodes.add(node);
108                 if (!node->shouldGenerate())
109                     continue;
110                 if (node->op() == Upsilon) {
111                     VALIDATE((node), m_graph.m_form == SSA);
112                     if (node->phi()->shouldGenerate())
113                         m_myRefCounts.find(node)->value++;
114                 }
115                 for (unsigned j = 0; j < m_graph.numChildren(node); ++j) {
116                     // Phi children in LoadStore form are invalid.
117                     if (m_graph.m_form == LoadStore && block->isPhiIndex(i))
118                         continue;
119                     
120                     Edge edge = m_graph.child(node, j);
121                     if (!edge)
122                         continue;
123                     
124                     m_myRefCounts.find(edge.node())->value++;
125
126                     validateEdgeWithDoubleResultIfNecessary(node, edge);
127                     VALIDATE((node, edge), edge->hasInt52Result() == (edge.useKind() == Int52RepUse));
128                     
129                     if (m_graph.m_form == SSA) {
130                         // In SSA, all edges must hasResult().
131                         VALIDATE((node, edge), edge->hasResult());
132                         continue;
133                     }
134                     
135                     // Unless I'm a Flush, Phantom, GetLocal, or Phi, my children should hasResult().
136                     switch (node->op()) {
137                     case Flush:
138                     case GetLocal:
139                         VALIDATE((node, edge), edge->hasVariableAccessData(m_graph));
140                         VALIDATE((node, edge), edge->variableAccessData() == node->variableAccessData());
141                         break;
142                     case PhantomLocal:
143                         VALIDATE((node, edge), edge->hasVariableAccessData(m_graph));
144                         VALIDATE((node, edge), edge->variableAccessData() == node->variableAccessData());
145                         VALIDATE((node, edge), edge->op() != SetLocal);
146                         break;
147                     case Phi:
148                         VALIDATE((node, edge), edge->hasVariableAccessData(m_graph));
149                         if (m_graph.m_unificationState == LocallyUnified)
150                             break;
151                         VALIDATE((node, edge), edge->variableAccessData() == node->variableAccessData());
152                         break;
153                     default:
154                         VALIDATE((node, edge), edge->hasResult());
155                         break;
156                     }
157                 }
158             }
159         }
160         
161         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
162             BasicBlock* block = m_graph.block(blockIndex);
163             if (!block)
164                 continue;
165             for (size_t i = 0; i < block->numNodes(); ++i) {
166                 Node* node = block->node(i);
167                 if (m_graph.m_refCountState == ExactRefCount)
168                     V_EQUAL((node), m_myRefCounts.get(node), node->adjustedRefCount());
169             }
170             
171             bool foundTerminal = false;
172             for (size_t i = 0 ; i < block->size(); ++i) {
173                 Node* node = block->at(i);
174                 if (node->isTerminal()) {
175                     foundTerminal = true;
176                     for (size_t j = i + 1; j < block->size(); ++j) {
177                         node = block->at(j);
178                         VALIDATE((node), node->op() == Phantom || node->op() == PhantomLocal || node->op() == Flush || node->op() == Check);
179                         m_graph.doToChildren(
180                             node,
181                             [&] (Edge edge) {
182                                 VALIDATE((node, edge), shouldNotHaveTypeCheck(edge.useKind()));
183                             });
184                     }
185                     break;
186                 }
187             }
188             VALIDATE((block), foundTerminal);
189             
190             for (size_t i = 0; i < block->size(); ++i) {
191                 Node* node = block->at(i);
192
193                 VALIDATE((node), node->origin.isSet());
194                 VALIDATE((node), node->origin.semantic.isSet() == node->origin.forExit.isSet());
195                 VALIDATE((node), !(!node->origin.forExit.isSet() && node->origin.exitOK));
196                 VALIDATE((node), !(mayExit(m_graph, node) == Exits && !node->origin.exitOK));
197
198                 if (i) {
199                     Node* previousNode = block->at(i - 1);
200                     VALIDATE(
201                         (node),
202                         !clobbersExitState(m_graph, previousNode)
203                         || !node->origin.exitOK
204                         || node->op() == ExitOK
205                         || node->origin.forExit != previousNode->origin.forExit);
206                     VALIDATE(
207                         (node),
208                         !(!previousNode->origin.exitOK && node->origin.exitOK)
209                         || node->op() == ExitOK
210                         || node->origin.forExit != previousNode->origin.forExit);
211                 }
212                 
213                 VALIDATE((node), !node->hasStructure() || !!node->structure());
214                 VALIDATE((node), !node->hasCellOperand() || node->cellOperand()->value().isCell());
215                 VALIDATE((node), !node->hasCellOperand() || !!node->cellOperand()->value());
216                 
217                 if (!(node->flags() & NodeHasVarArgs)) {
218                     if (!node->child2())
219                         VALIDATE((node), !node->child3());
220                     if (!node->child1())
221                         VALIDATE((node), !node->child2());
222                 }
223                  
224                 switch (node->op()) {
225                 case Identity:
226                     VALIDATE((node), canonicalResultRepresentation(node->result()) == canonicalResultRepresentation(node->child1()->result()));
227                     break;
228                 case SetLocal:
229                 case PutStack:
230                 case Upsilon:
231                     VALIDATE((node), !!node->child1());
232                     switch (node->child1().useKind()) {
233                     case UntypedUse:
234                     case CellUse:
235                     case KnownCellUse:
236                     case Int32Use:
237                     case KnownInt32Use:
238                     case Int52RepUse:
239                     case DoubleRepUse:
240                     case BooleanUse:
241                     case KnownBooleanUse:
242                         break;
243                     default:
244                         VALIDATE((node), !"Bad use kind");
245                         break;
246                     }
247                     break;
248                 case MakeRope:
249                 case ValueAdd:
250                 case ArithAdd:
251                 case ArithSub:
252                 case ArithMul:
253                 case ArithIMul:
254                 case ArithDiv:
255                 case ArithMod:
256                 case ArithMin:
257                 case ArithMax:
258                 case ArithPow:
259                 case CompareLess:
260                 case CompareLessEq:
261                 case CompareGreater:
262                 case CompareGreaterEq:
263                 case CompareEq:
264                 case CompareStrictEq:
265                 case StrCat:
266                     VALIDATE((node), !!node->child1());
267                     VALIDATE((node), !!node->child2());
268                     break;
269                 case CheckStructure:
270                 case StringFromCharCode:
271                     VALIDATE((node), !!node->child1());
272                     break;
273                 case PutStructure:
274                     VALIDATE((node), !node->transition()->previous->dfgShouldWatch());
275                     break;
276                 case MultiPutByOffset:
277                     for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
278                         const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
279                         if (variant.kind() != PutByIdVariant::Transition)
280                             continue;
281                         VALIDATE((node), !variant.oldStructureForTransition()->dfgShouldWatch());
282                     }
283                     break;
284                 case MaterializeNewObject:
285                     for (Structure* structure : node->structureSet()) {
286                         // This only supports structures that are JSFinalObject or JSArray.
287                         VALIDATE(
288                             (node),
289                             structure->classInfo() == JSFinalObject::info()
290                             || structure->classInfo() == JSArray::info());
291
292                         // We only support certain indexing shapes.
293                         VALIDATE((node), !hasAnyArrayStorage(structure->indexingType()));
294                     }
295                     break;
296                 case DoubleConstant:
297                 case Int52Constant:
298                     VALIDATE((node), node->isNumberConstant());
299                     break;
300                 default:
301                     break;
302                 }
303             }
304         }
305         
306         switch (m_graph.m_form) {
307         case LoadStore:
308         case ThreadedCPS:
309             validateCPS();
310             break;
311             
312         case SSA:
313             validateSSA();
314             break;
315         }
316
317         // Validate clobbered states.
318         struct DefLambdaAdaptor {
319             std::function<void(PureValue)> pureValue;
320             std::function<void(HeapLocation, LazyNode)> locationAndNode;
321
322             void operator()(PureValue value) const
323             {
324                 pureValue(value);
325             }
326
327             void operator()(HeapLocation location, LazyNode node) const
328             {
329                 locationAndNode(location, node);
330             }
331         };
332         for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
333             for (Node* node : *block) {
334                 clobberize(m_graph, node,
335                     [&] (AbstractHeap) { },
336                     [&] (AbstractHeap heap)
337                     {
338                         // CSE assumes that HEAP TOP is never written.
339                         // If this assumption is weakened, you need to update clobbering
340                         // in CSE accordingly.
341                         if (heap.kind() == Stack)
342                             VALIDATE((node), !heap.payload().isTop());
343                     },
344                     DefLambdaAdaptor {
345                         [&] (PureValue) { },
346                         [&] (HeapLocation location, LazyNode)
347                         {
348                             VALIDATE((node), location.heap().kind() != SideState);
349
350                             // More specific kinds should be used instead.
351                             VALIDATE((node), location.heap().kind() != World);
352                             VALIDATE((node), location.heap().kind() != Heap);
353                         }
354                 });
355             }
356         }
357     }
358     
359 private:
360     Graph& m_graph;
361     GraphDumpMode m_graphDumpMode;
362     CString m_graphDumpBeforePhase;
363     
364     HashMap<Node*, unsigned> m_myRefCounts;
365     HashSet<Node*> m_acceptableNodes;
366     
367     void validateCPS()
368     {
369         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
370             BasicBlock* block = m_graph.block(blockIndex);
371             if (!block)
372                 continue;
373             
374             HashSet<Node*> phisInThisBlock;
375             HashSet<Node*> nodesInThisBlock;
376             
377             for (size_t i = 0; i < block->numNodes(); ++i) {
378                 Node* node = block->node(i);
379                 nodesInThisBlock.add(node);
380                 if (block->isPhiIndex(i))
381                     phisInThisBlock.add(node);
382                 for (unsigned j = 0; j < m_graph.numChildren(node); ++j) {
383                     Edge edge = m_graph.child(node, j);
384                     if (!edge)
385                         continue;
386                     VALIDATE((node, edge), m_acceptableNodes.contains(edge.node()));
387                 }
388             }
389             
390             for (size_t i = 0; i < block->phis.size(); ++i) {
391                 Node* node = block->phis[i];
392                 ASSERT(phisInThisBlock.contains(node));
393                 VALIDATE((node), node->op() == Phi);
394                 VirtualRegister local = node->local();
395                 for (unsigned j = 0; j < m_graph.numChildren(node); ++j) {
396                     // Phi children in LoadStore form are invalid.
397                     if (m_graph.m_form == LoadStore && block->isPhiIndex(i))
398                         continue;
399                     
400                     Edge edge = m_graph.child(node, j);
401                     if (!edge)
402                         continue;
403                     
404                     VALIDATE(
405                         (node, edge),
406                         edge->op() == SetLocal
407                         || edge->op() == SetArgument
408                         || edge->op() == Flush
409                         || edge->op() == Phi);
410                     
411                     if (phisInThisBlock.contains(edge.node()))
412                         continue;
413                     
414                     if (nodesInThisBlock.contains(edge.node())) {
415                         VALIDATE(
416                             (node, edge),
417                             edge->op() == SetLocal
418                             || edge->op() == SetArgument
419                             || edge->op() == Flush);
420                         
421                         continue;
422                     }
423                     
424                     // There must exist a predecessor block that has this node index in
425                     // its tail variables.
426                     bool found = false;
427                     for (unsigned k = 0; k < block->predecessors.size(); ++k) {
428                         BasicBlock* prevBlock = block->predecessors[k];
429                         VALIDATE((block->predecessors[k]), prevBlock);
430                         Node* prevNode = prevBlock->variablesAtTail.operand(local);
431                         // If we have a Phi that is not referring to *this* block then all predecessors
432                         // must have that local available.
433                         VALIDATE((local, block, block->predecessors[k]), prevNode);
434                         switch (prevNode->op()) {
435                         case GetLocal:
436                         case Flush:
437                         case PhantomLocal:
438                             prevNode = prevNode->child1().node();
439                             break;
440                         default:
441                             break;
442                         }
443                         if (node->shouldGenerate()) {
444                             VALIDATE((local, block->predecessors[k], prevNode),
445                                      prevNode->shouldGenerate());
446                         }
447                         VALIDATE(
448                             (local, block->predecessors[k], prevNode),
449                             prevNode->op() == SetLocal
450                             || prevNode->op() == SetArgument
451                             || prevNode->op() == Phi);
452                         if (prevNode == edge.node()) {
453                             found = true;
454                             break;
455                         }
456                         // At this point it cannot refer into this block.
457                         VALIDATE((local, block->predecessors[k], prevNode), !prevBlock->isInBlock(edge.node()));
458                     }
459                     
460                     VALIDATE((node, edge), found);
461                 }
462             }
463             
464             Operands<size_t> getLocalPositions(
465                 block->variablesAtHead.numberOfArguments(),
466                 block->variablesAtHead.numberOfLocals());
467             Operands<size_t> setLocalPositions(
468                 block->variablesAtHead.numberOfArguments(),
469                 block->variablesAtHead.numberOfLocals());
470             
471             for (size_t i = 0; i < block->variablesAtHead.numberOfArguments(); ++i) {
472                 VALIDATE((virtualRegisterForArgument(i), block), !block->variablesAtHead.argument(i) || block->variablesAtHead.argument(i)->hasVariableAccessData(m_graph));
473                 if (m_graph.m_form == ThreadedCPS)
474                     VALIDATE((virtualRegisterForArgument(i), block), !block->variablesAtTail.argument(i) || block->variablesAtTail.argument(i)->hasVariableAccessData(m_graph));
475                 
476                 getLocalPositions.argument(i) = notSet;
477                 setLocalPositions.argument(i) = notSet;
478             }
479             for (size_t i = 0; i < block->variablesAtHead.numberOfLocals(); ++i) {
480                 VALIDATE((virtualRegisterForLocal(i), block), !block->variablesAtHead.local(i) || block->variablesAtHead.local(i)->hasVariableAccessData(m_graph));
481                 if (m_graph.m_form == ThreadedCPS)
482                     VALIDATE((virtualRegisterForLocal(i), block), !block->variablesAtTail.local(i) || block->variablesAtTail.local(i)->hasVariableAccessData(m_graph));
483
484                 getLocalPositions.local(i) = notSet;
485                 setLocalPositions.local(i) = notSet;
486             }
487             
488             for (size_t i = 0; i < block->size(); ++i) {
489                 Node* node = block->at(i);
490                 ASSERT(nodesInThisBlock.contains(node));
491                 VALIDATE((node), node->op() != Phi);
492                 VALIDATE((node), node->origin.forExit.isSet());
493                 for (unsigned j = 0; j < m_graph.numChildren(node); ++j) {
494                     Edge edge = m_graph.child(node, j);
495                     if (!edge)
496                         continue;
497                     VALIDATE((node, edge), nodesInThisBlock.contains(edge.node()));
498                     switch (node->op()) {
499                     case PhantomLocal:
500                     case GetLocal:
501                     case Flush:
502                         break;
503                     default:
504                         VALIDATE((node, edge), !phisInThisBlock.contains(edge.node()));
505                         break;
506                     }
507                 }
508                 
509                 switch (node->op()) {
510                 case Phi:
511                 case Upsilon:
512                 case CheckInBounds:
513                 case PhantomNewObject:
514                 case PhantomNewFunction:
515                 case PhantomNewGeneratorFunction:
516                 case PhantomCreateActivation:
517                 case GetMyArgumentByVal:
518                 case PutHint:
519                 case CheckStructureImmediate:
520                 case MaterializeCreateActivation:
521                 case PutStack:
522                 case KillStack:
523                 case GetStack:
524                     VALIDATE((node), !"unexpected node type in CPS");
525                     break;
526                 case MaterializeNewObject: {
527                     // CPS only allows array lengths to be constant. This constraint only exists
528                     // because we don't have DFG support for anything more and we don't need any
529                     // other kind of support for now.
530                     ObjectMaterializationData& data = node->objectMaterializationData();
531                     for (unsigned i = data.m_properties.size(); i--;) {
532                         PromotedLocationDescriptor descriptor = data.m_properties[i];
533                         Edge edge = m_graph.varArgChild(node, 1 + i);
534                         switch (descriptor.kind()) {
535                         case PublicLengthPLoc:
536                         case VectorLengthPLoc:
537                             VALIDATE((node, edge), edge->isInt32Constant());
538                             break;
539                         default:
540                             break;
541                         }
542                     }
543
544                     // CPS only allows one structure.
545                     VALIDATE((node), node->structureSet().size() == 1);
546
547                     // CPS disallows int32 and double arrays. Those require weird type checks and
548                     // conversions. They are not needed in the DFG right now. We should add support
549                     // for these if the DFG ever needs it.
550                     for (Structure* structure : node->structureSet()) {
551                         VALIDATE((node), !hasInt32(structure->indexingType()));
552                         VALIDATE((node), !hasDouble(structure->indexingType()));
553                     }
554                     break;
555                 }
556                 case Phantom:
557                     VALIDATE((node), m_graph.m_fixpointState != FixpointNotConverged);
558                     break;
559                 default:
560                     break;
561                 }
562                 
563                 if (!node->shouldGenerate())
564                     continue;
565                 switch (node->op()) {
566                 case GetLocal:
567                     // Ignore GetLocal's that we know to be dead, but that the graph
568                     // doesn't yet know to be dead.
569                     if (!m_myRefCounts.get(node))
570                         break;
571                     if (m_graph.m_form == ThreadedCPS) {
572                         VALIDATE((node, block), getLocalPositions.operand(node->local()) == notSet);
573                         VALIDATE((node, block), !!node->child1());
574                     }
575                     getLocalPositions.operand(node->local()) = i;
576                     break;
577                 case SetLocal:
578                     // Only record the first SetLocal. There may be multiple SetLocals
579                     // because of flushing.
580                     if (setLocalPositions.operand(node->local()) != notSet)
581                         break;
582                     setLocalPositions.operand(node->local()) = i;
583                     break;
584                 case SetArgument:
585                     // This acts like a reset. It's ok to have a second GetLocal for a local in the same
586                     // block if we had a SetArgument for that local.
587                     getLocalPositions.operand(node->local()) = notSet;
588                     setLocalPositions.operand(node->local()) = notSet;
589                     break;
590                 default:
591                     break;
592                 }
593             }
594             
595             if (m_graph.m_form == LoadStore)
596                 continue;
597             
598             for (size_t i = 0; i < block->variablesAtHead.numberOfArguments(); ++i) {
599                 checkOperand(
600                     block, getLocalPositions, setLocalPositions, virtualRegisterForArgument(i));
601             }
602             for (size_t i = 0; i < block->variablesAtHead.numberOfLocals(); ++i) {
603                 checkOperand(
604                     block, getLocalPositions, setLocalPositions, virtualRegisterForLocal(i));
605             }
606         }
607     }
608     
609     void validateSSA()
610     {
611         // FIXME: Add more things here.
612         // https://bugs.webkit.org/show_bug.cgi?id=123471
613         
614         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
615             BasicBlock* block = m_graph.block(blockIndex);
616             if (!block)
617                 continue;
618             
619             VALIDATE((block), block->phis.isEmpty());
620
621             bool didSeeExitOK = false;
622             
623             for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
624                 Node* node = block->at(nodeIndex);
625                 didSeeExitOK |= node->origin.exitOK;
626                 switch (node->op()) {
627                 case Phi:
628                     // Phi cannot exit, and it would be wrong to hoist anything to the Phi that could
629                     // exit.
630                     VALIDATE((node), !node->origin.exitOK);
631
632                     // It never makes sense to have exitOK anywhere in the block before a Phi. It's only
633                     // OK to exit after all Phis are done.
634                     VALIDATE((node), !didSeeExitOK);
635                     break;
636                     
637                 case GetLocal:
638                 case SetLocal:
639                 case GetLocalUnlinked:
640                 case SetArgument:
641                 case Phantom:
642                     VALIDATE((node), !"bad node type for SSA");
643                     break;
644
645                 default:
646                     // FIXME: Add more things here.
647                     // https://bugs.webkit.org/show_bug.cgi?id=123471
648                     break;
649                 }
650                 switch (node->op()) {
651                 case PhantomNewObject:
652                 case PhantomNewFunction:
653                 case PhantomNewGeneratorFunction:
654                 case PhantomCreateActivation:
655                 case PhantomDirectArguments:
656                 case PhantomClonedArguments:
657                 case MovHint:
658                 case Upsilon:
659                 case ForwardVarargs:
660                 case CallForwardVarargs:
661                 case TailCallForwardVarargs:
662                 case TailCallForwardVarargsInlinedCaller:
663                 case ConstructForwardVarargs:
664                 case GetMyArgumentByVal:
665                     break;
666
667                 case Check:
668                     // FIXME: This is probably not correct.
669                     break;
670
671                 case PutHint:
672                     VALIDATE((node), node->child1()->isPhantomAllocation());
673                     break;
674
675                 default:
676                     m_graph.doToChildren(
677                         node,
678                         [&] (const Edge& edge) {
679                             VALIDATE((node), !edge->isPhantomAllocation());
680                         });
681                     break;
682                 }
683             }
684         }
685     }
686
687     void validateEdgeWithDoubleResultIfNecessary(Node* node, Edge edge)
688     {
689         if (!edge->hasDoubleResult())
690             return;
691
692         if (m_graph.m_planStage < PlanStage::AfterFixup)
693             return;
694         
695         VALIDATE((node, edge), edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse || edge.useKind() == DoubleRepMachineIntUse);
696     }
697
698     void checkOperand(
699         BasicBlock* block, Operands<size_t>& getLocalPositions,
700         Operands<size_t>& setLocalPositions, VirtualRegister operand)
701     {
702         if (getLocalPositions.operand(operand) == notSet)
703             return;
704         if (setLocalPositions.operand(operand) == notSet)
705             return;
706         
707         VALIDATE(
708             (block->at(getLocalPositions.operand(operand)),
709              block->at(setLocalPositions.operand(operand)),
710              block),
711             getLocalPositions.operand(operand) < setLocalPositions.operand(operand));
712     }
713     
714     void reportValidationContext(Node* node)
715     {
716         dataLogF("@%u", node->index());
717     }
718     
719     void reportValidationContext(BasicBlock* block)
720     {
721         dataLog("Block ", *block);
722     }
723     
724     void reportValidationContext(Node* node, Edge edge)
725     {
726         dataLog(node, " -> ", edge);
727     }
728     
729     void reportValidationContext(VirtualRegister local, BasicBlock* block)
730     {
731         if (!block) {
732             dataLog(local, " in null Block ");
733             return;
734         }
735
736         dataLog(local, " in Block ", *block);
737     }
738     
739     void reportValidationContext(
740         VirtualRegister local, BasicBlock* sourceBlock, BasicBlock* destinationBlock)
741     {
742         dataLog(local, " in Block ", *sourceBlock, " -> ", *destinationBlock);
743     }
744     
745     void reportValidationContext(
746         VirtualRegister local, BasicBlock* sourceBlock, Node* prevNode)
747     {
748         dataLog(prevNode, " for ", local, " in Block ", *sourceBlock);
749     }
750     
751     void reportValidationContext(Node* node, BasicBlock* block)
752     {
753         dataLog(node, " in Block ", *block);
754     }
755     
756     void reportValidationContext(Node* node, Node* node2, BasicBlock* block)
757     {
758         dataLog(node, " and ", node2, " in Block ", *block);
759     }
760     
761     void reportValidationContext(
762         Node* node, BasicBlock* block, Node* expectedNode, Edge incomingEdge)
763     {
764         dataLog(node, " in Block ", *block, ", searching for ", expectedNode, " from ", incomingEdge);
765     }
766     
767     void dumpGraphIfAppropriate()
768     {
769         if (m_graphDumpMode == DontDumpGraph)
770             return;
771         dataLog("\n");
772         if (!m_graphDumpBeforePhase.isNull()) {
773             dataLog("Before phase:\n");
774             dataLog(m_graphDumpBeforePhase);
775         }
776         dataLog("At time of failure:\n");
777         m_graph.dump();
778     }
779 };
780
781 } // End anonymous namespace.
782
783 void validate(Graph& graph, GraphDumpMode graphDumpMode, CString graphDumpBeforePhase)
784 {
785     Validate validationObject(graph, graphDumpMode, graphDumpBeforePhase);
786     validationObject.validate();
787 }
788
789 } } // namespace JSC::DFG
790
791 #endif // ENABLE(DFG_JIT)
792